From 5a9febac19255ab8aea598449ea63bda730b2fe0 Mon Sep 17 00:00:00 2001 From: msweet Date: Mon, 1 Oct 2012 03:01:10 +0000 Subject: [PATCH] Merge changes from CUPS 1.7svn-r10629. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@3933 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES-1.6.txt | 21 +- CHANGES-IPPTOOL.txt | 3 +- CHANGES.txt | 4 +- backend/dnssd.c | 12 +- backend/ipp.c | 296 ++++++++++++++---- backend/lpd.c | 25 +- backend/snmp-supplies.c | 60 ++-- backend/socket.c | 20 +- backend/usb-darwin.c | 10 +- backend/usb-libusb.c | 26 +- berkeley/lpq.c | 2 +- cgi-bin/admin.c | 10 +- cgi-bin/classes.c | 2 +- cgi-bin/help-index.c | 4 +- cgi-bin/ipp-var.c | 9 +- cgi-bin/jobs.c | 2 +- cgi-bin/printers.c | 2 +- cgi-bin/search.c | 14 +- config-scripts/cups-common.m4 | 1 + config-scripts/cups-directories.m4 | 2 +- config.h.in | 7 + cups/Makefile | 4 +- cups/adminutil.c | 4 +- cups/adminutil.h | 13 +- cups/array-private.h | 9 +- cups/array.c | 35 ++- cups/auth.c | 9 +- cups/backend.c | 2 +- cups/conflicts.c | 2 +- cups/cups-private.h | 1 + cups/debug.c | 36 +-- cups/dest-options.c | 34 +-- cups/dest.c | 21 +- cups/encode.c | 22 +- cups/globals.c | 2 +- cups/http-support.c | 12 +- cups/http.c | 16 +- cups/ipp.c | 104 ++++++- cups/ipp.h | 10 +- cups/langprintf.c | 4 +- cups/language.c | 22 +- cups/ppd-cache.c | 296 ++++++++++-------- cups/ppd-private.h | 8 +- cups/ppd.c | 8 +- cups/pwg-media.c | 2 +- cups/request.c | 52 ++-- cups/snprintf.c | 36 ++- cups/string.c | 18 +- cups/testarray.c | 6 +- cups/testhttp.c | 4 +- cups/testi18n.c | 14 +- cups/testppd.c | 14 +- cups/usersys.c | 6 +- cups/util.c | 4 +- doc/help/api-cups.html | 475 +++++++++++++++++++++++++++-- doc/help/api-httpipp.html | 58 ++-- doc/help/network.html | 34 ++- doc/help/spec-ppd.html | 74 +++++ filter/interpret.c | 2 +- filter/raster.c | 3 + filter/spec-ppd.shtml | 70 +++++ locale/checkpo.c | 4 +- locale/po2strings.c | 8 +- notifier/dbus.c | 8 +- ppdc/ppdc-source.cxx | 6 +- ppdc/ppdc-string.cxx | 8 +- scheduler/auth.c | 6 +- scheduler/client.c | 16 +- scheduler/conf.c | 2 +- scheduler/cups-driverd.cxx | 18 +- scheduler/cups-lpd.c | 10 +- scheduler/cupsfilter.c | 2 +- scheduler/dirsvc.c | 27 +- scheduler/ipp.c | 164 +++++++++- scheduler/job.c | 47 ++- scheduler/log.c | 8 +- scheduler/mime.c | 10 +- scheduler/printers.c | 67 +++- scheduler/type.c | 6 +- scheduler/util.c | 4 +- systemv/cupstestppd.c | 18 +- systemv/lpstat.c | 4 +- test/ippserver.c | 39 ++- test/ipptool.c | 40 +++ test/run-stp-tests.sh | 5 + test/str-header.html | 10 +- 86 files changed, 2011 insertions(+), 604 deletions(-) diff --git a/CHANGES-1.6.txt b/CHANGES-1.6.txt index 582e6ee41..369d96694 100644 --- a/CHANGES-1.6.txt +++ b/CHANGES-1.6.txt @@ -3,13 +3,32 @@ CHANGES-1.6.txt CHANGES IN CUPS V1.6.2 + - Documentation fixes + - OpenBSD build fix (STR #4195, STR #4196) + - The scheduler could crash when using Avahi (STR #4183, STR #4192) + - The IPP backend could get stuck in an endless loop on certain network + errors (STR #4194) + - 32-bit builds failed on Debian (STR #4133) + - The scheduler no longer accepts or sends job description attributes. + - The IPP backend now works around some conformance issues for broken + printers (STR #4190) + - cupsBackendReport() now filters out all control characters from the + reported 1284 device IDs (STR #4124) + - The scheduler no longer allows job-name values that are not valid + network Unicode strings (STR #4072) + - The web interface did not preserve the order of classes, jobs, or + printers (STR #4170) + - The network backends now support disabling of SNMP supply level + queries via the "snmp" URI option (STR #4106) + - The IPP backend did not specify the compression used (STR #4181) + - ipptool did not support octetString values. - The scheduler did not recognize dnssd: or ipps: URIs as Bonjour shared queues (STR #4158) - Applications could not get the PPD file for statically-configured Bonjour-shared print queues (STR #4159) - The cupsd.conf file included obsolete browsing directives (STR #4157) - Fixed a USB backend compatibility issue on systems using libusb - (STR #4155) + (STR #4155, STR #4191) - Some Bonjour features were not available on systems with Avahi (STR #4156) - CUPS now includes the port number in the Host: header for HTTP diff --git a/CHANGES-IPPTOOL.txt b/CHANGES-IPPTOOL.txt index 861db490e..9c4a8038a 100644 --- a/CHANGES-IPPTOOL.txt +++ b/CHANGES-IPPTOOL.txt @@ -1,4 +1,4 @@ -CHANGES-IPPTOOL.txt - 2012-08-23 +CHANGES-IPPTOOL.txt - 2012-09-15 -------------------------------- This file provides a list of changes to the ipptool binary distribution posted @@ -7,6 +7,7 @@ on cups.org. 2012-MM-DD + - ipptool did not support octetString values. - Fixed REPEAT-MATCH for STATUS and EXPECT - was incorrectly erroring out. diff --git a/CHANGES.txt b/CHANGES.txt index 76e4c4c0a..c60449303 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,5 +1,7 @@ -CHANGES.txt - 1.7b1 - 2012-08-10 +CHANGES.txt - 1.7b1 - 2012-08-30 -------------------------------- CHANGES IN CUPS V1.7b1 + - CUPS now supports higher-level PIN printing, external accounting + systems, and "print here" printing environments (STR #4169) diff --git a/backend/dnssd.c b/backend/dnssd.c index 7cff1cb4f..46c0f1347 100644 --- a/backend/dnssd.c +++ b/backend/dnssd.c @@ -1080,7 +1080,7 @@ query_callback( device_id[0] = '\0'; make_and_model[0] = '\0'; - strcpy(model, "Unknown"); + strlcpy(model, "Unknown", sizeof(model)); for (data = rdata, dataend = data + rdlen; data < dataend; @@ -1134,9 +1134,9 @@ query_callback( if (!_cups_strcasecmp(key, "usb_MFG") || !_cups_strcasecmp(key, "usb_MANU") || !_cups_strcasecmp(key, "usb_MANUFACTURER")) - strcpy(make_and_model, value); + strlcpy(make_and_model, value, sizeof(make_and_model)); else if (!_cups_strcasecmp(key, "usb_MDL") || !_cups_strcasecmp(key, "usb_MODEL")) - strcpy(model, value); + strlcpy(model, value, sizeof(model)); else if (!_cups_strcasecmp(key, "product") && !strstr(value, "Ghostscript")) { if (value[0] == '(') @@ -1148,14 +1148,14 @@ query_callback( if ((ptr = value + strlen(value) - 1) > value && *ptr == ')') *ptr = '\0'; - strcpy(model, value + 1); + strlcpy(model, value + 1, sizeof(model)); } else - strcpy(model, value); + strlcpy(model, value, sizeof(model)); } else if (!_cups_strcasecmp(key, "ty")) { - strcpy(model, value); + strlcpy(model, value, sizeof(model)); if ((ptr = strchr(model, ',')) != NULL) *ptr = '\0'; diff --git a/backend/ipp.c b/backend/ipp.c index 348188bd7..8215b8ffd 100644 --- a/backend/ipp.c +++ b/backend/ipp.c @@ -16,19 +16,22 @@ * * Contents: * - * main() - Send a file to the printer or server. - * cancel_job() - Cancel a print job. + * main() - Send a file to the printer or server. + * cancel_job() - Cancel a print job. * check_printer_state() - Check the printer state. - * compress_files() - Compress print files. - * monitor_printer() - Monitor the printer state. - * new_request() - Create a new print creation or validation request. - * password_cb() - Disable the password prompt for - * cupsDoFileRequest(). - * report_attr() - Report an IPP attribute value. + * compress_files() - Compress print files. + * monitor_printer() - Monitor the printer state. + * new_request() - Create a new print creation or validation + * request. + * password_cb() - Disable the password prompt for + * cupsDoFileRequest(). + * quote_string() - Quote a string value. + * report_attr() - Report an IPP attribute value. * report_printer_state() - Report the printer state. - * run_as_user() - Run the IPP backend as the printing user. - * timeout_cb() - Handle HTTP timeouts. - * sigterm_handler() - Handle 'terminate' signals that stop the backend. + * run_as_user() - Run the IPP backend as the printing user. + * sigterm_handler() - Handle 'terminate' signals that stop the backend. + * timeout_cb() - Handle HTTP timeouts. + * update_reasons() - Update the printer-state-reasons values. */ /* @@ -165,7 +168,10 @@ static ipp_t *new_request(ipp_op_t op, int version, const char *uri, const char *format, _ppd_cache_t *pc, ipp_attribute_t *media_col_sup, ipp_attribute_t *doc_handling_sup); -static const char *password_cb(const char *); +static const char *password_cb(const char *prompt, http_t *http, + const char *method, const char *resource, + void *user_data); +static const char *quote_string(const char *s, char *q, size_t qsize); static void report_attr(ipp_attribute_t *attr); static void report_printer_state(ipp_t *ipp); #if defined(HAVE_GSSAPI) && defined(HAVE_XPC) @@ -203,6 +209,7 @@ main(int argc, /* I - Number of command-line args */ *value, /* Value of option */ sep; /* Separator character */ http_addrlist_t *addrlist; /* Address of printer */ + int snmp_enabled = 1; /* Is SNMP enabled? */ int snmp_fd, /* SNMP socket */ start_count, /* Page count via SNMP at start */ page_count, /* Page count via SNMP */ @@ -331,7 +338,7 @@ main(int argc, /* I - Number of command-line args */ if ((auth_info_required = getenv("AUTH_INFO_REQUIRED")) == NULL) auth_info_required = "none"; - state_reasons = _cupsArrayNewStrings(getenv("PRINTER_STATE_REASONS")); + state_reasons = _cupsArrayNewStrings(getenv("PRINTER_STATE_REASONS"), ','); #ifdef HAVE_GSSAPI /* @@ -508,6 +515,16 @@ main(int argc, /* I - Number of command-line args */ value); } } + else if (!_cups_strcasecmp(name, "snmp")) + { + /* + * Enable/disable SNMP stuff... + */ + + snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") || + _cups_strcasecmp(value, "yes") || + _cups_strcasecmp(value, "true"); + } else if (!_cups_strcasecmp(name, "version")) { if (!strcmp(value, "1.0")) @@ -595,12 +612,12 @@ main(int argc, /* I - Number of command-line args */ * Set the authentication info, if any... */ - cupsSetPasswordCB(password_cb); + cupsSetPasswordCB2(password_cb, NULL); if (username[0]) { /* - * Use authenticaion information in the device URI... + * Use authentication information in the device URI... */ if ((password = strchr(username, ':')) != NULL) @@ -659,11 +676,14 @@ main(int argc, /* I - Number of command-line args */ * See if the printer supports SNMP... */ - if ((snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family)) >= 0) - { + if (snmp_enabled) + snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family); + else + snmp_fd = -1; + + if (snmp_fd >= 0) have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), &start_count, NULL); - } else have_supplies = start_count = 0; @@ -932,6 +952,8 @@ main(int argc, /* I - Number of command-line args */ _cupsLangPrintFilter(stderr, "ERROR", _("Unable to get printer status.")); sleep(10); + + httpReconnect(http); } ippDelete(supported); @@ -1258,6 +1280,16 @@ main(int argc, /* I - Number of command-line args */ compatsize = fileinfo.st_size; } + /* + * If the printer only claims to support IPP/1.0, or if the user specifically + * included version=1.0 in the URI, then do not try to use Create-Job or + * Send-Document. This is another dreaded compatibility hack, but unfortunately + * there are enough broken printers out there that we need this for now... + */ + + if (version == 10) + create_job = send_document = 0; + /* * Start monitoring the printer in the background... */ @@ -1474,10 +1506,9 @@ main(int argc, /* I - Number of command-line args */ goto cleanup; } } - else if (ipp_status == IPP_ERROR_JOB_CANCELED) + else if (ipp_status == IPP_ERROR_JOB_CANCELED || + ipp_status == IPP_NOT_AUTHORIZED) goto cleanup; - else if (ipp_status == IPP_NOT_AUTHORIZED) - continue; else { /* @@ -1578,6 +1609,10 @@ main(int argc, /* I - Number of command-line args */ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE, "document-format", NULL, document_format); + if (compression) + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "compression", NULL, compression); + fprintf(stderr, "DEBUG: Sending file %d using chunking...\n", i + 1); http_status = cupsSendRequest(http, request, resource, 0); if (http_status == HTTP_CONTINUE && request->state == IPP_DATA) @@ -1654,12 +1689,34 @@ main(int argc, /* I - Number of command-line args */ ipp_status == IPP_NOT_POSSIBLE || ipp_status == IPP_PRINTER_BUSY) continue; - else if (ipp_status == IPP_REQUEST_VALUE) + else if (ipp_status == IPP_REQUEST_VALUE || + ipp_status == IPP_ERROR_JOB_CANCELED || + ipp_status == IPP_NOT_AUTHORIZED || + ipp_status == IPP_INTERNAL_ERROR) + { + /* + * Print file is too large, job was canceled, we need new + * authentication data, or we had some sort of error... + */ + + goto cleanup; + } + else if (ipp_status == IPP_NOT_FOUND) { /* - * Print file is too large, abort this job... + * Printer does not actually implement support for Create-Job/ + * Send-Document, so log the conformance issue and stop the printer. */ + fputs("DEBUG: This printer claims to support Create-Job and " + "Send-Document, but those operations failed.\n", stderr); + fputs("DEBUG: Add '?version=1.0' to the device URI to use legacy " + "compatibility mode.\n", stderr); + update_reasons(NULL, "+cups-ipp-conformance-failure-report," + "cups-ipp-missing-send-document"); + + ipp_status = IPP_INTERNAL_ERROR; /* Force queue to stop */ + goto cleanup; } else @@ -2107,7 +2164,7 @@ monitor_printer( httpSetTimeout(http, 30.0, timeout_cb, NULL); if (username[0]) cupsSetUser(username); - cupsSetPasswordCB(password_cb); + cupsSetPasswordCB2(password_cb, NULL); /* * Loop until the job is canceled, aborted, or completed. @@ -2297,7 +2354,8 @@ new_request( *media_size; /* media-size value */ const char *media_source, /* media-source value */ *media_type, /* media-type value */ - *collate_str; /* multiple-document-handling value */ + *collate_str, /* multiple-document-handling value */ + *mandatory; /* Mandatory attributes */ /* @@ -2366,6 +2424,85 @@ new_request( * Send standard IPP attributes... */ + if (pc->password && + (keyword = cupsGetOption("job-password", num_options, + options)) != NULL) + { + ippAddOctetString(request, IPP_TAG_OPERATION, "job-password", + keyword, strlen(keyword)); + ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, + "job-password-encryption", NULL, "none"); + } + + if (pc->account_id && + (keyword = cupsGetOption("job-account-id", num_options, + options)) != NULL) + ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, "job-account-id", + NULL, keyword); + + if (pc->account_id && + (keyword = cupsGetOption("job-accounting-user-id", num_options, + options)) != NULL) + ippAddString(request, IPP_TAG_JOB, IPP_TAG_NAME, + "job-accounting-user-id", NULL, keyword); + + for (mandatory = (char *)cupsArrayFirst(pc->mandatory); + mandatory; + mandatory = (char *)cupsArrayNext(pc->mandatory)) + { + if (strcmp(mandatory, "copies") && + strcmp(mandatory, "destination-uris") && + strcmp(mandatory, "finishings") && + strcmp(mandatory, "job-account-id") && + strcmp(mandatory, "job-accounting-user-id") && + strcmp(mandatory, "job-password") && + strcmp(mandatory, "media") && + strncmp(mandatory, "media-col", 9) && + strcmp(mandatory, "multiple-document-handling") && + strcmp(mandatory, "output-bin") && + strcmp(mandatory, "print-color-mode") && + strcmp(mandatory, "print-quality") && + strcmp(mandatory, "sides") && + (keyword = cupsGetOption(mandatory, num_options, options)) != NULL) + { + _ipp_option_t *opt = _ippFindOption(mandatory); + /* Option type */ + ipp_tag_t value_tag = opt ? opt->value_tag : IPP_TAG_NAME; + /* Value type */ + + switch (value_tag) + { + case IPP_TAG_INTEGER : + case IPP_TAG_ENUM : + ippAddInteger(request, IPP_TAG_JOB, value_tag, mandatory, + atoi(keyword)); + break; + case IPP_TAG_BOOLEAN : + ippAddBoolean(request, IPP_TAG_JOB, mandatory, + !_cups_strcasecmp(keyword, "true")); + break; + case IPP_TAG_RANGE : + { + int lower, upper; /* Range */ + + if (sscanf(keyword, "%d-%d", &lower, &upper) != 2) + lower = upper = atoi(keyword); + + ippAddRange(request, IPP_TAG_JOB, mandatory, lower, upper); + } + break; + case IPP_TAG_STRING : + ippAddOctetString(request, IPP_TAG_JOB, mandatory, keyword, + strlen(keyword)); + break; + default : + ippAddString(request, IPP_TAG_JOB, value_tag, mandatory, + NULL, keyword); + break; + } + } + } + if ((keyword = cupsGetOption("PageSize", num_options, options)) == NULL) keyword = cupsGetOption("media", num_options, options); @@ -2431,19 +2568,19 @@ new_request( ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-bin", NULL, keyword); - if ((keyword = cupsGetOption("output-mode", num_options, + if ((keyword = cupsGetOption("print-color-mode", num_options, options)) != NULL) - ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-mode", + ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "print-color-mode", NULL, keyword); else if ((keyword = cupsGetOption("ColorModel", num_options, options)) != NULL) { if (!_cups_strcasecmp(keyword, "Gray")) - ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-mode", - NULL, "monochrome"); + ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, + "print-color-mode", NULL, "monochrome"); else - ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-mode", - NULL, "color"); + ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, + "print-color-mode", NULL, "color"); } if ((keyword = cupsGetOption("print-quality", num_options, @@ -2599,12 +2736,22 @@ new_request( */ static const char * /* O - Password */ -password_cb(const char *prompt) /* I - Prompt (not used) */ +password_cb(const char *prompt, /* I - Prompt (not used) */ + http_t *http, /* I - Connection */ + const char *method, /* I - Request method (not used) */ + const char *resource, /* I - Resource path (not used) */ + void *user_data) /* I - User data (not used) */ { + char def_username[HTTP_MAX_VALUE]; /* Default username */ + + fprintf(stderr, "DEBUG: password_cb(prompt=\"%s\"), password=%p, " "password_tries=%d\n", prompt, password, password_tries); (void)prompt; + (void)method; + (void)resource; + (void)user_data; /* * Remember that we need to authenticate... @@ -2612,6 +2759,16 @@ password_cb(const char *prompt) /* I - Prompt (not used) */ auth_info_required = "username,password"; + if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username", + def_username)) + { + char quoted[HTTP_MAX_VALUE * 2 + 4]; + /* Quoted string */ + + fprintf(stderr, "ATTR: auth-info-default=%s,\n", + quote_string(def_username, quoted, sizeof(quoted))); + } + if (password && *password && password_tries < 3) { password_tries ++; @@ -2629,6 +2786,56 @@ password_cb(const char *prompt) /* I - Prompt (not used) */ } +/* + * 'quote_string()' - Quote a string value. + */ + +static const char * /* O - Quoted string */ +quote_string(const char *s, /* I - String */ + char *q, /* I - Quoted string buffer */ + size_t qsize) /* I - Size of quoted string buffer */ +{ + char *qptr, /* Pointer into string buffer */ + *qend; /* End of string buffer */ + + + qptr = q; + qend = q + qsize - 5; + + if (qend < q) + { + *q = '\0'; + return (q); + } + + *qptr++ = '\''; + *qptr++ = '\"'; + + while (*s && qptr < qend) + { + if (*s == '\\' || *s == '\"' || *s == '\'') + { + if (q < (qend - 3)) + { + *qptr++ = '\\'; + *qptr++ = '\\'; + *qptr++ = '\\'; + } + else + break; + } + + *qptr++ = *s++; + } + + *qptr++ = '\"'; + *qptr++ = '\''; + *qptr = '\0'; + + return (q); +} + + /* * 'report_attr()' - Report an IPP attribute value. */ @@ -2638,8 +2845,7 @@ report_attr(ipp_attribute_t *attr) /* I - Attribute */ { int i; /* Looping var */ char value[1024], /* Value string */ - *valptr, /* Pointer into value string */ - *attrptr; /* Pointer into attribute value */ + *valptr; /* Pointer into value string */ const char *cached; /* Cached attribute */ @@ -2666,23 +2872,9 @@ report_attr(ipp_attribute_t *attr) /* I - Attribute */ case IPP_TAG_TEXT : case IPP_TAG_NAME : case IPP_TAG_KEYWORD : - *valptr++ = '\''; - *valptr++ = '\"'; - for (attrptr = attr->values[i].string.text; - *attrptr && valptr < (value + sizeof(value) - 10); - attrptr ++) - { - if (*attrptr == '\\' || *attrptr == '\"' || *attrptr == '\'') - { - *valptr++ = '\\'; - *valptr++ = '\\'; - *valptr++ = '\\'; - } - - *valptr++ = *attrptr; - } - *valptr++ = '\"'; - *valptr++ = '\''; + quote_string(attr->values[i].string.text, valptr, + value + sizeof(value) - valptr); + valptr += strlen(valptr); break; default : @@ -3133,7 +3325,7 @@ update_reasons(ipp_attribute_t *attr, /* I - printer-state-reasons or NULL */ else op = '\0'; - new_reasons = _cupsArrayNewStrings(s); + new_reasons = _cupsArrayNewStrings(s, ','); } else return; diff --git a/backend/lpd.c b/backend/lpd.c index e33081ce9..9d9e01b2b 100644 --- a/backend/lpd.c +++ b/backend/lpd.c @@ -126,6 +126,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ int port; /* Port number */ char portname[256]; /* Port name (string) */ http_addrlist_t *addrlist; /* List of addresses for printer */ + int snmp_enabled = 1; /* Is SNMP enabled? */ int snmp_fd; /* SNMP socket */ int fd; /* Print file */ int status; /* Status of LPD job */ @@ -356,7 +357,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ */ if (!value[0] || !_cups_strcasecmp(value, "on") || - !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true") || + !_cups_strcasecmp(value, "yes") || + !_cups_strcasecmp(value, "true") || !_cups_strcasecmp(value, "rfc1179")) reserve = RESERVE_RFC1179; else if (!_cups_strcasecmp(value, "any")) @@ -371,7 +373,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ */ manual_copies = !value[0] || !_cups_strcasecmp(value, "on") || - !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); + !_cups_strcasecmp(value, "yes") || + !_cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "sanitize_title")) { @@ -380,7 +383,18 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ */ sanitize_title = !value[0] || !_cups_strcasecmp(value, "on") || - !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); + !_cups_strcasecmp(value, "yes") || + !_cups_strcasecmp(value, "true"); + } + else if (!_cups_strcasecmp(name, "snmp")) + { + /* + * Enable/disable SNMP stuff... + */ + + snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") || + _cups_strcasecmp(value, "yes") || + _cups_strcasecmp(value, "true"); } else if (!_cups_strcasecmp(name, "timeout")) { @@ -428,7 +442,10 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ } } - snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family); + if (snmp_enabled) + snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family); + else + snmp_fd = -1; /* * Wait for data from the filter... diff --git a/backend/snmp-supplies.c b/backend/snmp-supplies.c index 380dd793d..4c0258ddd 100644 --- a/backend/snmp-supplies.c +++ b/backend/snmp-supplies.c @@ -318,9 +318,9 @@ backendSNMPSupplies( if ((supplies[i].max_capacity > 0 || (quirks & CUPS_SNMP_CAPACITY)) && supplies[i].level >= 0) - sprintf(ptr, "%d", percent); + snprintf(ptr, sizeof(value) - (ptr - value), "%d", percent); else - strcpy(ptr, "-1"); + strlcpy(ptr, "-1", sizeof(value) - (ptr - value)); } fprintf(stderr, "ATTR: marker-levels=%s\n", value); @@ -458,34 +458,34 @@ backend_init_supplies( "other", "unknown", "toner", - "wasteToner", + "waste-toner", "ink", - "inkCartridge", - "inkRibbon", - "wasteInk", + "ink-cartridge", + "ink-ribbon", + "waste-ink", "opc", "developer", - "fuserOil", - "solidWax", - "ribbonWax", - "wasteWax", + "fuser-oil", + "solid-wax", + "ribbon-wax", + "waste-wax", "fuser", - "coronaWire", - "fuserOilWick", - "cleanerUnit", - "fuserCleaningPad", - "transferUnit", - "tonerCartridge", - "fuserOiler", + "corona-wire", + "fuser-oil-wick", + "cleaner-unit", + "fuser-cleaning-pad", + "transfer-unit", + "toner-cartridge", + "fuser-oiler", "water", - "wasteWater", - "glueWaterAdditive", - "wastePaper", - "bindingSupply", - "bandingSupply", - "stitchingWire", - "shrinkWrap", - "paperWrap", + "waste-water", + "glue-water-additive", + "waste-paper", + "binding-supply", + "banding-supply", + "stitching-wire", + "shrink-wrap", + "paper-wrap", "staples", "inserts", "covers" @@ -682,7 +682,7 @@ backend_init_supplies( */ for (i = 0; i < num_supplies; i ++) - strcpy(supplies[i].color, "none"); + strlcpy(supplies[i].color, "none", sizeof(supplies[i].color)); _cupsSNMPWalk(snmp_fd, ¤t_addr, CUPS_SNMP_VERSION_1, _cupsSNMPDefaultCommunity(), prtMarkerColorantValue, @@ -697,7 +697,7 @@ backend_init_supplies( if (i) *ptr++ = ','; - strcpy(ptr, supplies[i].color); + strlcpy(ptr, supplies[i].color, sizeof(value) - (ptr - value)); } fprintf(stderr, "ATTR: marker-colors=%s\n", value); @@ -745,9 +745,9 @@ backend_init_supplies( type = supplies[i].type; if (type < CUPS_TC_other || type > CUPS_TC_covers) - strcpy(ptr, "unknown"); + strlcpy(ptr, "unknown", sizeof(value) - (ptr - value)); else - strcpy(ptr, types[type - CUPS_TC_other]); + strlcpy(ptr, types[type - CUPS_TC_other], sizeof(value) - (ptr - value)); } fprintf(stderr, "ATTR: marker-types=%s\n", value); @@ -814,7 +814,7 @@ backend_walk_cb(cups_snmp_t *packet, /* I - SNMP packet */ if (!_cups_strcasecmp(colors[k][0], (char *)packet->object_value.string.bytes)) { - strcpy(supplies[j].color, colors[k][1]); + strlcpy(supplies[j].color, colors[k][1], sizeof(supplies[j].color)); break; } } diff --git a/backend/socket.c b/backend/socket.c index f40d837fb..77255a394 100644 --- a/backend/socket.c +++ b/backend/socket.c @@ -87,6 +87,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ http_addrlist_t *addrlist, /* Address list */ *addr; /* Connected address */ char addrname[256]; /* Address name */ + int snmp_enabled = 1; /* Is SNMP enabled? */ int snmp_fd, /* SNMP socket */ start_count, /* Page count via SNMP at start */ page_count, /* Page count via SNMP */ @@ -246,6 +247,16 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ waiteof = !value[0] || !_cups_strcasecmp(value, "on") || !_cups_strcasecmp(value, "yes") || !_cups_strcasecmp(value, "true"); } + else if (!_cups_strcasecmp(name, "snmp")) + { + /* + * Enable/disable SNMP stuff... + */ + + snmp_enabled = !value[0] || !_cups_strcasecmp(value, "on") || + _cups_strcasecmp(value, "yes") || + _cups_strcasecmp(value, "true"); + } else if (!_cups_strcasecmp(name, "contimeout")) { /* @@ -286,11 +297,14 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ * See if the printer supports SNMP... */ - if ((snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family)) >= 0) - { + if (snmp_enabled) + snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family); + else + snmp_fd = -1; + + if (snmp_fd >= 0) have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), &start_count, NULL); - } else have_supplies = start_count = 0; diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index 187bf3f54..5f303bec5 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -684,7 +684,7 @@ print_device(const char *uri, /* I - Device URI */ /* * Ignore timeout errors, but retain the number of bytes written to - * avoid sending duplicate data ()... + * avoid sending duplicate data... */ if (iostatus == kIOUSBTransactionTimeout) @@ -707,7 +707,7 @@ print_device(const char *uri, /* I - Device URI */ /* * Retry a write after an aborted write since we probably just got - * SIGTERM ()... + * SIGTERM... */ else if (iostatus == kIOReturnAborted) @@ -1180,12 +1180,12 @@ static Boolean list_device_cb(void *refcon, if (!make || !CFStringGetCString(make, makestr, sizeof(makestr), kCFStringEncodingUTF8)) - strcpy(makestr, "Unknown"); + strlcpy(makestr, "Unknown", sizeof(makestr)); if (!model || !CFStringGetCString(model, &modelstr[1], sizeof(modelstr)-1, kCFStringEncodingUTF8)) - strcpy(modelstr + 1, "Printer"); + strlcpy(modelstr + 1, "Printer", sizeof(modelstr) - 1); optionsstr[0] = '\0'; if (serial != NULL) @@ -2164,7 +2164,7 @@ static void parse_pserror(char *sockBuffer, } /* move everything over... */ - strcpy(gErrorBuffer, pLineEnd); + strlcpy(gErrorBuffer, pLineEnd, sizeof(gErrorBuffer)); gErrorBufferPtr = gErrorBuffer; pLineEnd = (char *)next_line((const char *)gErrorBuffer); } diff --git a/backend/usb-libusb.c b/backend/usb-libusb.c index 705dbcbad..da7e0cce9 100644 --- a/backend/usb-libusb.c +++ b/backend/usb-libusb.c @@ -147,17 +147,37 @@ static const struct quirk_printer_struct quirk_printers[] = { Printer, http://www.cups.org/str.php?L4155 */ { 0x04a9, 0x10b6, USBLP_QUIRK_BIDIR }, /* Canon, Inc. PIXMA iP4300 Printer, https://bugs.launchpad.net/bugs/1032385 */ + { 0x04a9, 0x170c, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP500 + Printer, https://bugs.launchpad.net/bugs/1032456 */ + { 0x04a9, 0x1717, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP510 + Printer, https://bugs.launchpad.net/bugs/1050009 */ + { 0x04a9, 0x173d, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP550 + Printer, http://www.cups.org/str.php?L4155 */ + { 0x04a9, 0x173e, USBLP_QUIRK_BIDIR }, /* Canon, Inc. MP560 + Printer, http://www.cups.org/str.php?L4155 */ + { 0x04f9, 0x001a, USBLP_QUIRK_NO_REATTACH }, /* Brother Industries, Ltd + HL-1430 Laser Printer, + https://bugs.launchpad.net/bugs/1038695 */ { 0x04f9, 0x000d, USBLP_QUIRK_BIDIR | USBLP_QUIRK_NO_REATTACH }, /* Brother Industries, Ltd - HL-1440 Laser Printer */ + HL-1440 Laser Printer, + https://bugs.launchpad.net/bugs/1000253 */ + { 0x06bc, 0x000b, USBLP_QUIRK_NO_REATTACH }, /* Oki Data Corp. + Okipage 14ex Printer, + https://bugs.launchpad.net/bugs/872483 */ + { 0x06bc, 0x01c7, USBLP_QUIRK_NO_REATTACH }, /* Oki Data Corp. B410d, + https://bugs.launchpad.net/bugs/872483 */ { 0x04b8, 0x0202, USBLP_QUIRK_BAD_CLASS }, /* Seiko Epson Receipt Printer M129C */ { 0x067b, 0x2305, USBLP_QUIRK_BIDIR | USBLP_QUIRK_NO_REATTACH | USBLP_QUIRK_RESET }, /* Prolific Technology, Inc. PL2305 Parallel Port - (USB -> Parallel adapter) */ - { 0x04e8, 0x0000, USBLP_QUIRK_RESET }, /* All Samsung devices */ + (USB -> Parallel adapter), https://bugs.launchpad.net/bugs/987485 */ + { 0x04e8, 0x0000, USBLP_QUIRK_RESET }, /* All Samsung devices, + https://bugs.launchpad.net/bugs/1032456 */ + { 0x0a5f, 0x0000, USBLP_QUIRK_BIDIR }, /* All Zebra devices, + https://bugs.launchpad.net/bugs/1001028 */ { 0, 0 } }; diff --git a/berkeley/lpq.c b/berkeley/lpq.c index 2dfc3bfbf..9356fc1f3 100644 --- a/berkeley/lpq.c +++ b/berkeley/lpq.c @@ -527,7 +527,7 @@ show_jobs(const char *command, /* I - Command name */ */ if (jobstate == IPP_JOB_PROCESSING) - strcpy(rankstr, "active"); + strlcpy(rankstr, "active", sizeof(rankstr)); else { /* diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c index d0f488e5a..84c9d9c90 100644 --- a/cgi-bin/admin.c +++ b/cgi-bin/admin.c @@ -962,13 +962,13 @@ do_am_printer(http_t *http, /* I - HTTP connection */ else if (!_cups_strncasecmp(make, "laserjet", 8) || !_cups_strncasecmp(make, "deskjet", 7) || !_cups_strncasecmp(make, "designjet", 9)) - strcpy(make, "HP"); + strlcpy(make, "HP", sizeof(make)); else if (!_cups_strncasecmp(make, "phaser", 6)) - strcpy(make, "Xerox"); + strlcpy(make, "Xerox", sizeof(make)); else if (!_cups_strncasecmp(make, "stylus", 6)) - strcpy(make, "Epson"); + strlcpy(make, "Epson", sizeof(make)); else - strcpy(make, "Generic"); + strlcpy(make, "Generic", sizeof(make)); if (!cgiGetVariable("CURRENT_MAKE")) cgiSetVariable("CURRENT_MAKE", make); @@ -4187,7 +4187,7 @@ get_option_value( if (bufptr == buffer || (bufend - bufptr) < 2) return (NULL); - strcpy(bufptr, "}"); + memcpy(bufptr, "}", 2); } return (buffer); diff --git a/cgi-bin/classes.c b/cgi-bin/classes.c index 1be7664ca..8d42e5cda 100644 --- a/cgi-bin/classes.c +++ b/cgi-bin/classes.c @@ -380,7 +380,7 @@ show_all_classes(http_t *http, /* I - Connection to server */ sprintf(val, "%d", count); cgiSetVariable("TOTAL", val); - if ((var = cgiGetVariable("ORDER")) != NULL) + if ((var = cgiGetVariable("ORDER")) != NULL && *var) ascending = !_cups_strcasecmp(var, "asc"); else ascending = 1; diff --git a/cgi-bin/help-index.c b/cgi-bin/help-index.c index c48ffeb4d..08586a0b1 100644 --- a/cgi-bin/help-index.c +++ b/cgi-bin/help-index.c @@ -3,7 +3,7 @@ * * Online help index routines for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -910,7 +910,7 @@ help_load_file( node = NULL; offset = 0; - strcpy(section, "Other"); + strlcpy(section, "Other", sizeof(section)); while (cupsFileGets(fp, line, sizeof(line))) { diff --git a/cgi-bin/ipp-var.c b/cgi-bin/ipp-var.c index 1251e89a6..75fb84452 100644 --- a/cgi-bin/ipp-var.c +++ b/cgi-bin/ipp-var.c @@ -129,7 +129,7 @@ cgiGetAttributes(ipp_t *request, /* I - IPP request */ *nameptr = '\0'; if (!strncmp(name, "printer_state_history", 21)) - strcpy(name, "printer_state_history"); + strlcpy(name, "printer_state_history", sizeof(name)); /* * Possibly add it to the list of attributes... @@ -1432,7 +1432,7 @@ cgiShowJobs(http_t *http, /* I - Connection to server */ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/"); - if ((which_jobs = cgiGetVariable("which_jobs")) != NULL) + if ((which_jobs = cgiGetVariable("which_jobs")) != NULL && *which_jobs) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "which-jobs", NULL, which_jobs); @@ -1480,10 +1480,11 @@ cgiShowJobs(http_t *http, /* I - Connection to server */ if (first < 0) first = 0; - if ((var = cgiGetVariable("ORDER")) != NULL) + if ((var = cgiGetVariable("ORDER")) != NULL && *var) ascending = !_cups_strcasecmp(var, "asc"); else - ascending = !which_jobs || !_cups_strcasecmp(which_jobs, "not-completed"); + ascending = !which_jobs || !*which_jobs || + !_cups_strcasecmp(which_jobs, "not-completed"); section = cgiGetVariable("SECTION"); diff --git a/cgi-bin/jobs.c b/cgi-bin/jobs.c index 30aefa667..bfb354885 100644 --- a/cgi-bin/jobs.c +++ b/cgi-bin/jobs.c @@ -182,7 +182,7 @@ do_job_op(http_t *http, /* I - HTTP connection */ char url[1024]; /* Encoded URL */ - strcpy(url, "5;URL="); + strlcpy(url, "5;URL=", sizeof(url)); cgiFormEncode(url + 6, getenv("HTTP_REFERER"), sizeof(url) - 6); cgiSetVariable("refresh_page", url); } diff --git a/cgi-bin/printers.c b/cgi-bin/printers.c index 4230eec19..36e992025 100644 --- a/cgi-bin/printers.c +++ b/cgi-bin/printers.c @@ -397,7 +397,7 @@ show_all_printers(http_t *http, /* I - Connection to server */ sprintf(val, "%d", count); cgiSetVariable("TOTAL", val); - if ((var = cgiGetVariable("ORDER")) != NULL) + if ((var = cgiGetVariable("ORDER")) != NULL && *var) ascending = !_cups_strcasecmp(var, "asc"); else ascending = 1; diff --git a/cgi-bin/search.c b/cgi-bin/search.c index f8d6c797f..94150de58 100644 --- a/cgi-bin/search.c +++ b/cgi-bin/search.c @@ -3,7 +3,7 @@ * * Search routines for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -208,7 +208,7 @@ cgiCompileSearch(const char *query) /* I - Query string */ * Add the prefix string... */ - strcpy(sptr, prefix); + memcpy(sptr, prefix, strlen(prefix) + 1); sptr += strlen(sptr); /* @@ -249,16 +249,16 @@ cgiCompileSearch(const char *query) /* I - Query string */ return (NULL); } - strcpy(sptr, ".*|.*"); + memcpy(sptr, ".*|.*", 6); sptr += 5; - strcpy(sptr, lword2); + memcpy(sptr, lword2, strlen(lword2) + 1); sptr += strlen(sptr); - strcpy(sptr, ".*"); + memcpy(sptr, ".*", 3); sptr += 2; - strcpy(sptr, lword); + memcpy(sptr, lword, strlen(lword) + 1); sptr += strlen(sptr); free(lword); @@ -287,7 +287,7 @@ cgiCompileSearch(const char *query) /* I - Query string */ free(lword); if (sptr > s) - strcpy(sptr, ".*"); + memcpy(sptr, ".*", 3); else { /* diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 index 1c21309e7..d5a22ce67 100644 --- a/config-scripts/cups-common.m4 +++ b/config-scripts/cups-common.m4 @@ -130,6 +130,7 @@ AC_CHECK_HEADER(crypt.h,AC_DEFINE(HAVE_CRYPT_H)) AC_CHECK_HEADER(langinfo.h,AC_DEFINE(HAVE_LANGINFO_H)) AC_CHECK_HEADER(malloc.h,AC_DEFINE(HAVE_MALLOC_H)) AC_CHECK_HEADER(shadow.h,AC_DEFINE(HAVE_SHADOW_H)) +AC_CHECK_HEADER(stdint.h,AC_DEFINE(HAVE_STDINT_H)) AC_CHECK_HEADER(string.h,AC_DEFINE(HAVE_STRING_H)) AC_CHECK_HEADER(strings.h,AC_DEFINE(HAVE_STRINGS_H)) AC_CHECK_HEADER(bstring.h,AC_DEFINE(HAVE_BSTRING_H)) diff --git a/config-scripts/cups-directories.m4 b/config-scripts/cups-directories.m4 index 010e5f5d7..fe6e01e19 100644 --- a/config-scripts/cups-directories.m4 +++ b/config-scripts/cups-directories.m4 @@ -106,7 +106,7 @@ if test "$libdir" = "\${exec_prefix}/lib"; then libdir="$exec_prefix/lib32" ;; Linux*) - if test -d /usr/lib64; then + if test -d /usr/lib64 -a ! -d /usr/lib64/fakeroot; then libdir="$exec_prefix/lib64" fi ;; diff --git a/config.h.in b/config.h.in index 60fa36cb1..34af9141c 100644 --- a/config.h.in +++ b/config.h.in @@ -174,6 +174,13 @@ #undef HAVE_SCSI_SG_H +/* + * Use ? + */ + +#undef HAVE_STDINT_H + + /* * Use , , and/or ? */ diff --git a/cups/Makefile b/cups/Makefile index 0b6765794..8d5cefd8b 100644 --- a/cups/Makefile +++ b/cups/Makefile @@ -518,7 +518,7 @@ apihelp: --css ../doc/cups-printable.css \ --header api-cups.header --intro api-cups.shtml \ api-cups.xml \ - cups.h adminutil.c dest.c language.c notify.c \ + cups.h adminutil.c dest*.c language.c notify.c \ options.c tempfile.c usersys.c \ util.c >../doc/help/api-cups.html mxmldoc --tokens help/api-cups.html api-cups.xml >../doc/help/api-cups.tokens @@ -573,7 +573,7 @@ framedhelp: --section "Programming" --title "CUPS API" \ --css ../doc/cups-printable.css \ --header api-cups.header --intro api-cups.shtml \ - cups.h adminutil.c dest.c language.c notify.c \ + cups.h adminutil.c dest*.c language.c notify.c \ options.c tempfile.c usersys.c \ util.c mxmldoc --framed api-filedir \ diff --git a/cups/adminutil.c b/cups/adminutil.c index 803d2203c..440e443b5 100644 --- a/cups/adminutil.c +++ b/cups/adminutil.c @@ -65,7 +65,7 @@ static void write_option(cups_file_t *dstfp, int order, /* * 'cupsAdminCreateWindowsPPD()' - Create the Windows PPD file for a printer. * - * @since CUPS 1.2/OS X 10.5@ + * @deprecated@ */ char * /* O - PPD file or NULL */ @@ -393,7 +393,7 @@ cupsAdminCreateWindowsPPD( /* * 'cupsAdminExportSamba()' - Export a printer to Samba. * - * @since CUPS 1.2/OS X 10.5@ + * @deprecated@ */ int /* O - 1 on success, 0 on failure */ diff --git a/cups/adminutil.h b/cups/adminutil.h index 14c681b16..826061570 100644 --- a/cups/adminutil.h +++ b/cups/adminutil.h @@ -3,7 +3,7 @@ * * Administration utility API definitions for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 2001-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -55,16 +55,19 @@ extern int cupsAdminExportSamba(const char *dest, const char *ppd, const char *samba_server, const char *samba_user, const char *samba_password, - FILE *logfile) _CUPS_API_1_2; + FILE *logfile) _CUPS_DEPRECATED; extern char *cupsAdminCreateWindowsPPD(http_t *http, const char *dest, - char *buffer, int bufsize) _CUPS_API_1_2; + char *buffer, int bufsize) + _CUPS_DEPRECATED; extern int cupsAdminGetServerSettings(http_t *http, int *num_settings, - cups_option_t **settings) _CUPS_API_1_3; + cups_option_t **settings) + _CUPS_API_1_3; extern int cupsAdminSetServerSettings(http_t *http, int num_settings, - cups_option_t *settings) _CUPS_API_1_3; + cups_option_t *settings) + _CUPS_API_1_3; # ifdef __cplusplus diff --git a/cups/array-private.h b/cups/array-private.h index c0d9a92e8..4d3c29734 100644 --- a/cups/array-private.h +++ b/cups/array-private.h @@ -3,7 +3,7 @@ * * Private array definitions for CUPS. * - * Copyright 2011 by Apple Inc. + * Copyright 2011-2012 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -37,9 +37,10 @@ extern "C" { * Functions... */ -extern int _cupsArrayAddStrings(cups_array_t *a, const char *s) - _CUPS_API_1_5; -extern cups_array_t *_cupsArrayNewStrings(const char *s) _CUPS_API_1_5; +extern int _cupsArrayAddStrings(cups_array_t *a, const char *s, + char delim) _CUPS_API_1_5; +extern cups_array_t *_cupsArrayNewStrings(const char *s, char delim) + _CUPS_API_1_5; # ifdef __cplusplus } diff --git a/cups/array.c b/cups/array.c index 2fb7701c0..a84f3e2a2 100644 --- a/cups/array.c +++ b/cups/array.c @@ -138,8 +138,7 @@ cupsArrayAdd(cups_array_t *a, /* I - Array */ /* - * '_cupsArrayAddStrings()' - Add zero or more comma-delimited strings to an - * array. + * '_cupsArrayAddStrings()' - Add zero or more delimited strings to an array. * * Note: The array MUST be created using the @link _cupsArrayNewStrings@ * function. Duplicate strings are NOT added. If the string pointer "s" is NULL @@ -148,7 +147,8 @@ cupsArrayAdd(cups_array_t *a, /* I - Array */ int /* O - 1 on success, 0 on failure */ _cupsArrayAddStrings(cups_array_t *a, /* I - Array */ - const char *s) /* I - Comma-delimited strings or NULL */ + const char *s, /* I - Delimited strings or NULL */ + char delim)/* I - Delimiter character */ { char *buffer, /* Copy of string */ *start, /* Start of string */ @@ -159,10 +159,21 @@ _cupsArrayAddStrings(cups_array_t *a, /* I - Array */ if (!a || !s || !*s) return (0); - if (!strchr(s, ',')) + if (delim == ' ') { /* - * String doesn't contain a comma, so add it as a single value... + * Skip leading whitespace... + */ + + while (*s && isspace(*s & 255)) + s ++; + } + + if (!strchr(s, delim) || + (delim == ' ' && !strchr(s, '\t') && !strchr(s, '\n'))) + { + /* + * String doesn't contain a delimiter, so add it as a single value... */ if (!cupsArrayFind(a, (void *)s)) @@ -179,7 +190,14 @@ _cupsArrayAddStrings(cups_array_t *a, /* I - Array */ * it... */ - if ((end = strchr(start, ',')) != NULL) + if (delim == ' ') + { + while (*end && !isspace(*end & 255)) + end ++; + while (*end && isspace(*end & 255)) + *end++ = '\0'; + } + else if ((end = strchr(start, delim)) != NULL) *end++ = '\0'; else end = start + strlen(start); @@ -782,7 +800,8 @@ cupsArrayNew3(cups_array_func_t f, /* I - Comparison function or @code NULL@ fo */ cups_array_t * /* O - Array */ -_cupsArrayNewStrings(const char *s) /* I - Comma-delimited strings or NULL */ +_cupsArrayNewStrings(const char *s, /* I - Delimited strings or NULL */ + char delim) /* I - Delimiter character */ { cups_array_t *a; /* Array */ @@ -790,7 +809,7 @@ _cupsArrayNewStrings(const char *s) /* I - Comma-delimited strings or NULL */ if ((a = cupsArrayNew3((cups_array_func_t)strcmp, NULL, NULL, 0, (cups_acopy_func_t)_cupsStrAlloc, (cups_afree_func_t)_cupsStrFree)) != NULL) - _cupsArrayAddStrings(a, s); + _cupsArrayAddStrings(a, s, delim); return (a); } diff --git a/cups/auth.c b/cups/auth.c index 4b0856ade..fab0db347 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -190,11 +190,18 @@ cupsDoAuthentication( * Nope - get a new password from the user... */ + char default_username[HTTP_MAX_VALUE]; + /* Default username */ + cg = _cupsGlobals(); if (!cg->lang_default) cg->lang_default = cupsLangDefault(); + if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username", + default_username)) + cupsSetUser(default_username); + snprintf(prompt, sizeof(prompt), _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), cupsUser(), @@ -458,7 +465,7 @@ _cupsSetNegotiateAuthString( authsize = sizeof(http->_authstring); } - strcpy(http->authstring, "Negotiate "); + strlcpy(http->authstring, "Negotiate ", authsize); httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value, output_token.length); diff --git a/cups/backend.c b/cups/backend.c index bed23f464..6f8a6b2e8 100644 --- a/cups/backend.c +++ b/cups/backend.c @@ -136,7 +136,7 @@ quote_string(const char *s) /* I - String to write */ if (*s == '\\' || *s == '\"') putchar('\\'); - if (*s == '\n') + if (((*s & 255) < ' ' && *s != '\t') || *s == 0x7f) putchar(' '); else putchar(*s); diff --git a/cups/conflicts.c b/cups/conflicts.c index 456f69053..ae048d135 100644 --- a/cups/conflicts.c +++ b/cups/conflicts.c @@ -930,7 +930,7 @@ ppd_load_constraints(ppd_file_t *ppd) /* I - PPD file */ if (!_cups_strncasecmp(option, "Custom", 6) && !_cups_strcasecmp(choice, "True")) { _cups_strcpy(option, option + 6); - strcpy(choice, "Custom"); + strlcpy(choice, "Custom", sizeof(choice)); } constptr->option = ppdFindOption(ppd, option); diff --git a/cups/cups-private.h b/cups/cups-private.h index 816e72552..4918755bf 100644 --- a/cups/cups-private.h +++ b/cups/cups-private.h @@ -24,6 +24,7 @@ # include "string-private.h" # include "debug-private.h" +# include "array-private.h" # include "ipp-private.h" # include "http-private.h" # include "language-private.h" diff --git a/cups/debug.c b/cups/debug.c index e8298ad06..71b693c70 100644 --- a/cups/debug.c +++ b/cups/debug.c @@ -229,16 +229,8 @@ debug_vsnprintf(char *buffer, /* O - Output buffer */ if (bufptr) { - if ((bufptr + strlen(temp)) > bufend) - { - strncpy(bufptr, temp, (size_t)(bufend - bufptr)); - bufptr = bufend; - } - else - { - strcpy(bufptr, temp); - bufptr += strlen(temp); - } + strlcpy(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr += strlen(bufptr); } break; @@ -267,16 +259,8 @@ debug_vsnprintf(char *buffer, /* O - Output buffer */ if (bufptr) { - if ((bufptr + strlen(temp)) > bufend) - { - strncpy(bufptr, temp, (size_t)(bufend - bufptr)); - bufptr = bufend; - } - else - { - strcpy(bufptr, temp); - bufptr += strlen(temp); - } + strlcpy(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr += strlen(bufptr); } break; @@ -290,16 +274,8 @@ debug_vsnprintf(char *buffer, /* O - Output buffer */ if (bufptr) { - if ((bufptr + strlen(temp)) > bufend) - { - strncpy(bufptr, temp, (size_t)(bufend - bufptr)); - bufptr = bufend; - } - else - { - strcpy(bufptr, temp); - bufptr += strlen(temp); - } + strlcpy(bufptr, temp, (size_t)(bufend - bufptr)); + bufptr += strlen(bufptr); } break; diff --git a/cups/dest-options.c b/cups/dest-options.c index 32616a683..d8eff72e5 100644 --- a/cups/dest-options.c +++ b/cups/dest-options.c @@ -269,13 +269,13 @@ cupsCheckDestSupported( * Returns 1 if there is a conflict, 0 if there are no conflicts, and -1 if * there was an unrecoverable error such as a resolver loop. * - * If "num_conflicts" and "conflicts" are not NULL, they are set to contain the - * list of conflicting option/value pairs. Similarly, if "num_resolved" and - * "resolved" are not NULL they will be set to the list of changes needed to - * resolve the conflict. + * If "num_conflicts" and "conflicts" are not @code NULL@, they are set to + * contain the list of conflicting option/value pairs. Similarly, if + * "num_resolved" and "resolved" are not @code NULL@ they will be set to the + * list of changes needed to resolve the conflict. * * If cupsCopyDestConflicts returns 1 but "num_resolved" and "resolved" are set - * to 0 and NULL, respectively, then the conflict cannot be resolved. + * to 0 and @code NULL@, respectively, then the conflict cannot be resolved. * * @since CUPS 1.6/OS X 10.8@ */ @@ -716,14 +716,13 @@ cupsFreeDestInfo(cups_dinfo_t *dinfo) /* I - Destination information */ /* * 'cupsGetDestMediaByName()' - Get media names, dimensions, and margins. * - * The "media" string is a PWG media name, while "width" and "length" are the - * dimensions in hundredths of millimeters. "flags" provides some matching + * The "media" string is a PWG media name. "Flags" provides some matching * guidance (multiple flags can be combined): * - * CUPS_MEDIA_FLAGS_DEFAULT = find the closest size supported by the printer - * CUPS_MEDIA_FLAGS_BORDERLESS = find a borderless size - * CUPS_MEDIA_FLAGS_DUPLEX = find a size compatible with 2-sided printing - * CUPS_MEDIA_FLAGS_EXACT = find an exact match for the size + * CUPS_MEDIA_FLAGS_DEFAULT = find the closest size supported by the printer, + * CUPS_MEDIA_FLAGS_BORDERLESS = find a borderless size, + * CUPS_MEDIA_FLAGS_DUPLEX = find a size compatible with 2-sided printing, + * CUPS_MEDIA_FLAGS_EXACT = find an exact match for the size, and * CUPS_MEDIA_FLAGS_READY = if the printer supports media sensing, find the * size amongst the "ready" media. * @@ -782,14 +781,13 @@ cupsGetDestMediaByName( /* * 'cupsGetDestMediaBySize()' - Get media names, dimensions, and margins. * - * The "media" string is a PWG media name, while "width" and "length" are the - * dimensions in hundredths of millimeters. "flags" provides some matching - * guidance (multiple flags can be combined): + * "Width" and "length" are the dimensions in hundredths of millimeters. + * "Flags" provides some matching guidance (multiple flags can be combined): * - * CUPS_MEDIA_FLAGS_DEFAULT = find the closest size supported by the printer - * CUPS_MEDIA_FLAGS_BORDERLESS = find a borderless size - * CUPS_MEDIA_FLAGS_DUPLEX = find a size compatible with 2-sided printing - * CUPS_MEDIA_FLAGS_EXACT = find an exact match for the size + * CUPS_MEDIA_FLAGS_DEFAULT = find the closest size supported by the printer, + * CUPS_MEDIA_FLAGS_BORDERLESS = find a borderless size, + * CUPS_MEDIA_FLAGS_DUPLEX = find a size compatible with 2-sided printing, + * CUPS_MEDIA_FLAGS_EXACT = find an exact match for the size, and * CUPS_MEDIA_FLAGS_READY = if the printer supports media sensing, find the * size amongst the "ready" media. * diff --git a/cups/dest.c b/cups/dest.c index 0714f6670..46bc3adb1 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -319,7 +319,8 @@ cupsAddDest(const char *name, /* I - Destination name */ if (instance && !cupsGetDest(name, NULL, num_dests, *dests)) return (num_dests); - dest = cups_add_dest(name, instance, &num_dests, dests); + if ((dest = cups_add_dest(name, instance, &num_dests, dests)) == NULL) + return (num_dests); /* * Find the base dest again now the array has been realloc'd. @@ -1409,6 +1410,7 @@ _cupsGetDests(http_t *http, /* I - Connection to server or "printer-is-shared", "printer-location", "printer-make-and-model", + "printer-mandatory-job-attributes", "printer-name", "printer-state", "printer-state-change-time", @@ -1514,6 +1516,7 @@ _cupsGetDests(http_t *http, /* I - Connection to server or !strcmp(attr->name, "printer-info") || !strcmp(attr->name, "printer-is-shared") || !strcmp(attr->name, "printer-make-and-model") || + !strcmp(attr->name, "printer-mandatory-job-attributes") || !strcmp(attr->name, "printer-state") || !strcmp(attr->name, "printer-state-change-time") || !strcmp(attr->name, "printer-type") || @@ -1788,7 +1791,7 @@ cupsGetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ * need to set a default if one exists... */ - if (dest == NULL && defprinter != NULL) + if (!dest && *dests && defprinter) { for (i = 0; i < num_dests; i ++) (*dests)[i].is_default = 0; @@ -2449,7 +2452,7 @@ appleCopyNetwork(void) * 'appleGetPaperSize()' - Get the default paper size. */ -char * /* O - Default paper size */ +static char * /* O - Default paper size */ appleGetPaperSize(char *name, /* I - Paper size name buffer */ int namesize) /* I - Size of buffer */ { @@ -3150,7 +3153,7 @@ cups_dnssd_query_cb( device->state = _CUPS_DNSSD_PENDING; make_and_model[0] = '\0'; - strcpy(model, "Unknown"); + strlcpy(model, "Unknown", sizeof(model)); for (txt = rdata, txtend = txt + rdlen; txt < txtend; @@ -3192,10 +3195,10 @@ cups_dnssd_query_cb( if (!_cups_strcasecmp(key, "usb_MFG") || !_cups_strcasecmp(key, "usb_MANU") || !_cups_strcasecmp(key, "usb_MANUFACTURER")) - strcpy(make_and_model, value); + strlcpy(make_and_model, value, sizeof(make_and_model)); else if (!_cups_strcasecmp(key, "usb_MDL") || !_cups_strcasecmp(key, "usb_MODEL")) - strcpy(model, value); + strlcpy(model, value, sizeof(model)); else if (!_cups_strcasecmp(key, "product") && !strstr(value, "Ghostscript")) { if (value[0] == '(') @@ -3207,14 +3210,14 @@ cups_dnssd_query_cb( if ((ptr = value + strlen(value) - 1) > value && *ptr == ')') *ptr = '\0'; - strcpy(model, value + 1); + strlcpy(model, value + 1, sizeof(model)); } else - strcpy(model, value); + strlcpy(model, value, sizeof(model)); } else if (!_cups_strcasecmp(key, "ty")) { - strcpy(model, value); + strlcpy(model, value, sizeof(model)); if ((ptr = strchr(model, ',')) != NULL) *ptr = '\0'; diff --git a/cups/encode.c b/cups/encode.c index b417fe164..565a43705 100644 --- a/cups/encode.c +++ b/cups/encode.c @@ -39,6 +39,7 @@ static const _ipp_option_t ipp_options[] = { { 1, "auth-info", IPP_TAG_TEXT, IPP_TAG_JOB }, + { 1, "auth-info-default", IPP_TAG_TEXT, IPP_TAG_PRINTER }, { 1, "auth-info-required", IPP_TAG_KEYWORD, IPP_TAG_PRINTER }, { 0, "blackplot", IPP_TAG_BOOLEAN, IPP_TAG_JOB }, { 0, "blackplot-default", IPP_TAG_BOOLEAN, IPP_TAG_PRINTER }, @@ -71,13 +72,29 @@ static const _ipp_option_t ipp_options[] = { 0, "hue", IPP_TAG_INTEGER, IPP_TAG_JOB }, { 0, "hue-default", IPP_TAG_INTEGER, IPP_TAG_PRINTER }, { 1, "include-schemes", IPP_TAG_NAME, IPP_TAG_OPERATION }, - { 0, "job-impressions", IPP_TAG_INTEGER, IPP_TAG_JOB }, + { 0, "job-account-id", IPP_TAG_NAME, IPP_TAG_JOB }, + { 0, "job-account-id-default",IPP_TAG_NAME, IPP_TAG_PRINTER }, + { 0, "job-accounting-user-id", IPP_TAG_NAME, IPP_TAG_JOB }, + { 0, "job-accounting-user-id-default", IPP_TAG_NAME, IPP_TAG_PRINTER }, + { 0, "job-hold-until", IPP_TAG_KEYWORD, IPP_TAG_JOB }, + { 0, "job-id", IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ + { 0, "job-impressions", IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ + { 0, "job-impressions-completed", IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ { 0, "job-k-limit", IPP_TAG_INTEGER, IPP_TAG_PRINTER }, + { 0, "job-k-octets", IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ + { 0, "job-k-octets-completed",IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ + { 0, "job-media-sheets", IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ + { 0, "job-media-sheets-completed", IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ { 0, "job-page-limit", IPP_TAG_INTEGER, IPP_TAG_PRINTER }, + { 0, "job-password", IPP_TAG_STRING, IPP_TAG_OPERATION }, + { 0, "job-password-encryption", IPP_TAG_KEYWORD, IPP_TAG_OPERATION }, { 0, "job-priority", IPP_TAG_INTEGER, IPP_TAG_JOB }, { 0, "job-quota-period", IPP_TAG_INTEGER, IPP_TAG_PRINTER }, { 1, "job-sheets", IPP_TAG_NAME, IPP_TAG_JOB }, { 1, "job-sheets-default", IPP_TAG_NAME, IPP_TAG_PRINTER }, + { 0, "job-state", IPP_TAG_ENUM, IPP_TAG_ZERO }, /* never send as option */ + { 0, "job-state-message", IPP_TAG_TEXT, IPP_TAG_ZERO }, /* never send as option */ + { 0, "job-state-reasons", IPP_TAG_KEYWORD, IPP_TAG_ZERO }, /* never send as option */ { 0, "job-uuid", IPP_TAG_URI, IPP_TAG_JOB }, { 0, "landscape", IPP_TAG_BOOLEAN, IPP_TAG_JOB }, { 1, "marker-change-time", IPP_TAG_INTEGER, IPP_TAG_PRINTER }, @@ -179,6 +196,9 @@ static const _ipp_option_t ipp_options[] = { 0, "sides", IPP_TAG_KEYWORD, IPP_TAG_JOB, IPP_TAG_DOCUMENT }, { 0, "sides-default", IPP_TAG_KEYWORD, IPP_TAG_PRINTER }, + { 0, "time-at-completed", IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ + { 0, "time-at-creation", IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ + { 0, "time-at-processing", IPP_TAG_INTEGER, IPP_TAG_ZERO }, /* never send as option */ { 0, "wrap", IPP_TAG_BOOLEAN, IPP_TAG_JOB }, { 0, "wrap-default", IPP_TAG_BOOLEAN, IPP_TAG_PRINTER }, { 0, "x-dimension", IPP_TAG_INTEGER, IPP_TAG_JOB, diff --git a/cups/globals.c b/cups/globals.c index bc4191c1d..d7bd5ac50 100644 --- a/cups/globals.c +++ b/cups/globals.c @@ -227,7 +227,7 @@ cups_globals_alloc(void) * Open the registry... */ - strcpy(installdir, "C:/Program Files/cups.org"); + strlcpy(installdir, "C:/Program Files/cups.org", sizeof(installdir)); if (!RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\cups.org", 0, KEY_READ, &key)) diff --git a/cups/http-support.c b/cups/http-support.c index 19538941d..e69b44d05 100644 --- a/cups/http-support.c +++ b/cups/http-support.c @@ -82,6 +82,7 @@ typedef struct _http_uribuf_s /* URI buffer */ char *buffer; /* Pointer to buffer */ size_t bufsize; /* Size of buffer */ int options; /* Options passed to _httpResolveURI */ + const char *resource; /* Resource from URI */ } _http_uribuf_t; @@ -1523,6 +1524,7 @@ _httpResolveURI( uribuf.buffer = resolved_uri; uribuf.bufsize = resolved_size; uribuf.options = options; + uribuf.resource = resource; resolved_uri[0] = '\0'; @@ -2064,8 +2066,14 @@ http_resolve_cb( * Assemble the final device URI... */ - httpAssembleURI(HTTP_URI_CODING_ALL, uribuf->buffer, uribuf->bufsize, scheme, - NULL, hostTarget, ntohs(port), resource); + if ((!strcmp(scheme, "ipp") || !strcmp(scheme, "ipps")) && + !strcmp(uribuf->resource, "/cups")) + httpAssembleURIf(HTTP_URI_CODING_ALL, uribuf->buffer, uribuf->bufsize, + scheme, NULL, hostTarget, ntohs(port), "%s?snmp=false", + resource); + else + httpAssembleURI(HTTP_URI_CODING_ALL, uribuf->buffer, uribuf->bufsize, + scheme, NULL, hostTarget, ntohs(port), resource); DEBUG_printf(("8http_resolve_cb: Resolved URI is \"%s\"...", uribuf->buffer)); } diff --git a/cups/http.c b/cups/http.c index a88a08187..c53465b2f 100644 --- a/cups/http.c +++ b/cups/http.c @@ -2646,7 +2646,8 @@ httpSetLength(http_t *http, /* I - Connection to server */ if (!length) { - strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"); + strlcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked", + HTTP_MAX_VALUE); http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0'; } else @@ -2991,8 +2992,11 @@ _httpWait(http_t *http, /* I - Connection to server */ pfd.fd = http->fd; pfd.events = POLLIN; - while ((nfds = poll(&pfd, 1, msec)) < 0 && - (errno == EINTR || errno == EAGAIN)); + do + { + nfds = poll(&pfd, 1, msec); + } + while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); #else do @@ -3469,12 +3473,12 @@ http_debug_hex(const char *prefix, /* I - Prefix for line */ while (j < 16) { - strcpy(ptr, " "); + memcpy(ptr, " ", 3); ptr += 2; j ++; } - strcpy(ptr, " "); + memcpy(ptr, " ", 3); ptr += 2; for (j = 0; j < 16 && (i + j) < bytes; j ++) @@ -4231,6 +4235,8 @@ http_setup_ssl(http_t *http) /* I - Connection to server */ credential->datalen); cupsArrayAdd(names, credential); } + else + free(credential); } } } diff --git a/cups/ipp.c b/cups/ipp.c index 0a1e31c56..9290edbbc 100644 --- a/cups/ipp.c +++ b/cups/ipp.c @@ -623,7 +623,8 @@ ippAddOctetString(ipp_t *ipp, /* I - IPP message */ if (!ipp || !name || group < IPP_TAG_ZERO || - group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE) + group == IPP_TAG_END || group >= IPP_TAG_UNSUPPORTED_VALUE || + datalen < 0 || datalen > IPP_MAX_OCTETSTRING) return (NULL); if ((attr = ipp_add_attr(ipp, name, group, IPP_TAG_STRING, 1)) == NULL) @@ -999,7 +1000,8 @@ ippAddString(ipp_t *ipp, /* I - IPP message */ { ipp_tag_t temp_tag; /* Temporary value tag (masked) */ ipp_attribute_t *attr; /* New attribute */ - char code[32]; /* Charset/language code buffer */ + char code[IPP_MAX_LANGUAGE]; + /* Charset/language code buffer */ DEBUG_printf(("ippAddString(ipp=%p, group=%02x(%s), value_tag=%02x(%s), " @@ -2466,13 +2468,25 @@ ippReadIO(void *src, /* I - Data source */ { int n; /* Length of data */ unsigned char *buffer, /* Data buffer */ - string[IPP_MAX_NAME], + string[IPP_MAX_TEXT], /* Small string buffer */ *bufptr; /* Pointer into buffer */ ipp_attribute_t *attr; /* Current attribute */ ipp_tag_t tag; /* Current tag */ ipp_tag_t value_tag; /* Current value tag */ _ipp_value_t *value; /* Current value */ + static const int maxlen[] = /* Maximum length of strings */ + { + IPP_MAX_TEXT - 1, + IPP_MAX_NAME - 1, + 0, + IPP_MAX_KEYWORD - 1, + IPP_MAX_URI - 1, + IPP_MAX_URISCHEME - 1, + IPP_MAX_CHARSET - 1, + IPP_MAX_LANGUAGE - 1, + IPP_MAX_MIMETYPE - 1 + }; DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)", @@ -2913,6 +2927,16 @@ ippReadIO(void *src, /* I - Data source */ case IPP_TAG_CHARSET : case IPP_TAG_LANGUAGE : case IPP_TAG_MIMETYPE : + if (n > maxlen[tag - IPP_TAG_TEXT]) + { + _cupsSetError(IPP_INTERNAL_ERROR, + _("IPP string value too large."), 1); + DEBUG_printf(("1ippReadIO: bad %s value length %d.", + ippTagString(tag), n)); + _cupsBufferRelease((char *)buffer); + return (IPP_ERROR); + } + if (n > 0) { if ((*cb)(src, buffer, n) < n) @@ -3015,6 +3039,21 @@ ippReadIO(void *src, /* I - Data source */ _cupsBufferRelease((char *)buffer); return (IPP_ERROR); } + else if (n > (2 + IPP_MAX_LANGUAGE + IPP_MAX_TEXT)) + { + if (tag == IPP_TAG_TEXTLANG) + _cupsSetError(IPP_INTERNAL_ERROR, + _("IPP textWithLanguage value more than " + "maximum 1090 bytes."), 1); + else + _cupsSetError(IPP_INTERNAL_ERROR, + _("IPP nameWithLanguage value more than " + "maximum 1090 bytes."), 1); + DEBUG_printf(("1ippReadIO: bad stringWithLanguage value " + "length %d.", n)); + _cupsBufferRelease((char *)buffer); + return (IPP_ERROR); + } if ((*cb)(src, buffer, n) < n) { @@ -3048,6 +3087,15 @@ ippReadIO(void *src, /* I - Data source */ _cupsBufferRelease((char *)buffer); return (IPP_ERROR); } + else if (n >= IPP_MAX_LANGUAGE) + { + _cupsSetError(IPP_INTERNAL_ERROR, + _("IPP language length too large."), 1); + DEBUG_printf(("1ippReadIO: bad language value length %d.", + n)); + _cupsBufferRelease((char *)buffer); + return (IPP_ERROR); + } memcpy(string, bufptr + 2, n); string[n] = '\0'; @@ -3065,6 +3113,15 @@ ippReadIO(void *src, /* I - Data source */ _cupsBufferRelease((char *)buffer); return (IPP_ERROR); } + else if (n >= IPP_MAX_TEXT) + { + _cupsSetError(IPP_INTERNAL_ERROR, + _("IPP text length too large."), 1); + DEBUG_printf(("1ippReadIO: bad text value length %d.", + n)); + _cupsBufferRelease((char *)buffer); + return (IPP_ERROR); + } bufptr[2 + n] = '\0'; value->string.text = _cupsStrAlloc((char *)bufptr + 2); @@ -3116,7 +3173,15 @@ ippReadIO(void *src, /* I - Data source */ * we need to carry over... */ - if (n == 0) + if (!attr) + { + _cupsSetError(IPP_INTERNAL_ERROR, + _("IPP memberName with no attribute."), 1); + DEBUG_puts("1ippReadIO: Member name without attribute."); + _cupsBufferRelease((char *)buffer); + return (IPP_ERROR); + } + else if (n == 0) { _cupsSetError(IPP_INTERNAL_ERROR, _("IPP memberName value is empty."), 1); @@ -3146,7 +3211,18 @@ ippReadIO(void *src, /* I - Data source */ break; default : /* Other unsupported values */ + if (tag == IPP_TAG_STRING && n > IPP_MAX_OCTETSTRING) + { + _cupsSetError(IPP_INTERNAL_ERROR, + _("IPP octetString length too large."), 1); + DEBUG_printf(("1ippReadIO: bad octetString value length %d.", + n)); + _cupsBufferRelease((char *)buffer); + return (IPP_ERROR); + } + value->unknown.length = n; + if (n > 0) { if ((value->unknown.data = malloc(n)) == NULL) @@ -4996,7 +5072,8 @@ ipp_free_values(ipp_attribute_t *attr, /* I - Attribute to free values from */ _ipp_value_t *value; /* Current value */ - DEBUG_printf(("4ipp_free_values(attr=%p, element=%d, count=%d)", attr, element, count)); + DEBUG_printf(("4ipp_free_values(attr=%p, element=%d, count=%d)", attr, + element, count)); if (!(attr->value_tag & IPP_TAG_COPY)) { @@ -5008,8 +5085,12 @@ ipp_free_values(ipp_attribute_t *attr, /* I - Attribute to free values from */ { case IPP_TAG_TEXTLANG : case IPP_TAG_NAMELANG : - if (element == 0 && count == attr->num_values && attr->values[0].string.language) + if (element == 0 && count == attr->num_values && + attr->values[0].string.language) + { _cupsStrFree(attr->values[0].string.language); + attr->values[0].string.language = NULL; + } case IPP_TAG_TEXT : case IPP_TAG_NAME : @@ -5023,7 +5104,10 @@ ipp_free_values(ipp_attribute_t *attr, /* I - Attribute to free values from */ for (i = count, value = attr->values + element; i > 0; i --, value ++) + { _cupsStrFree(value->string.text); + value->string.text = NULL; + } break; case IPP_TAG_DEFAULT : @@ -5044,7 +5128,10 @@ ipp_free_values(ipp_attribute_t *attr, /* I - Attribute to free values from */ for (i = count, value = attr->values + element; i > 0; i --, value ++) + { ippDelete(value->collection); + value->collection = NULL; + } break; case IPP_TAG_STRING : @@ -5052,8 +5139,13 @@ ipp_free_values(ipp_attribute_t *attr, /* I - Attribute to free values from */ for (i = count, value = attr->values + element; i > 0; i --, value ++) + { if (value->unknown.data) + { free(value->unknown.data); + value->unknown.data = NULL; + } + } break; } } diff --git a/cups/ipp.h b/cups/ipp.h index 2fb1995e3..2118dd353 100644 --- a/cups/ipp.h +++ b/cups/ipp.h @@ -54,8 +54,16 @@ extern "C" { * Common limits... */ +# define IPP_MAX_CHARSET 64 /* Maximum length of charset values w/nul */ +# define IPP_MAX_KEYWORD 256 /* Maximum length of keyword values w/nul */ +# define IPP_MAX_LANGUAGE 64 /* Maximum length of naturalLanguage values w/nul */ # define IPP_MAX_LENGTH 32767 /* Maximum size of any single value */ -# define IPP_MAX_NAME 256 /* Maximum length of common name values */ +# define IPP_MAX_MIMETYPE 256 /* Maximum length of mimeMediaType values w/nul */ +# define IPP_MAX_NAME 256 /* Maximum length of common name values w/nul */ +# define IPP_MAX_OCTETSTRING 1023 /* Maximum length of octetString values w/o nul */ +# define IPP_MAX_TEXT 1024 /* Maximum length of text values w/nul */ +# define IPP_MAX_URI 1024 /* Maximum length of uri values w/nul */ +# define IPP_MAX_URISCHEME 64 /* Maximum length of uriScheme values w/nul */ # define IPP_MAX_VALUES 8 /* Power-of-2 allocation increment */ diff --git a/cups/langprintf.c b/cups/langprintf.c index 1a9f8b789..f85507547 100644 --- a/cups/langprintf.c +++ b/cups/langprintf.c @@ -3,7 +3,7 @@ * * Localized printf/puts functions for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 2002-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -304,7 +304,7 @@ _cupsSetLocale(char *argv[]) /* IO - Command-line arguments */ strlcpy(charset, ".UTF-8", sizeof(new_lc_time) - (charset - new_lc_time)); } else - strcpy(new_lc_time, "C"); + strlcpy(new_lc_time, "C", sizeof(new_lc_time)); setlocale(LC_TIME, new_lc_time); #endif /* LC_TIME */ diff --git a/cups/language.c b/cups/language.c index 49f038238..aee4dee3b 100644 --- a/cups/language.c +++ b/cups/language.c @@ -446,7 +446,7 @@ cupsLangGet(const char *language) /* I - Language or locale */ * Set the character set to UTF-8... */ - strcpy(charset, "UTF8"); + strlcpy(charset, "UTF8", sizeof(charset)); /* * Apple's setlocale doesn't give us the user's localization @@ -582,7 +582,7 @@ cupsLangGet(const char *language) /* I - Language or locale */ */ if (!charset[0]) - strcpy(charset, "UTF8"); + strlcpy(charset, "UTF8", sizeof(charset)); /* * Parse the language string passed in to a locale string. "C" is the @@ -597,7 +597,7 @@ cupsLangGet(const char *language) /* I - Language or locale */ if (language == NULL || !language[0] || !strcmp(language, "POSIX")) - strcpy(langname, "C"); + strlcpy(langname, "C", sizeof(langname)); else { /* @@ -646,7 +646,7 @@ cupsLangGet(const char *language) /* I - Language or locale */ if (strlen(langname) != 2) { - strcpy(langname, "C"); + strlcpy(langname, "C", sizeof(langname)); country[0] = '\0'; charset[0] = '\0'; } @@ -701,7 +701,7 @@ cupsLangGet(const char *language) /* I - Language or locale */ if (country[0]) snprintf(real, sizeof(real), "%s_%s", langname, country); else - strcpy(real, langname); + strlcpy(real, langname, sizeof(real)); _cupsMutexLock(&lang_mutex); @@ -847,6 +847,7 @@ _cupsMessageLoad(const char *filename, /* I - Message catalog to load */ *ptr, /* Pointer into buffer */ *temp; /* New string */ int length; /* Length of combined strings */ + size_t ptrlen; /* Length of string */ DEBUG_printf(("4_cupsMessageLoad(filename=\"%s\")", filename)); @@ -978,9 +979,10 @@ _cupsMessageLoad(const char *filename, /* I - Message catalog to load */ */ length = (int)strlen(m->str ? m->str : m->id); + ptrlen = strlen(ptr); if ((temp = realloc(m->str ? m->str : m->id, - length + strlen(ptr) + 1)) == NULL) + length + ptrlen + 1)) == NULL) { if (m->str) free(m->str); @@ -995,25 +997,25 @@ _cupsMessageLoad(const char *filename, /* I - Message catalog to load */ { /* * Copy the new portion to the end of the msgstr string - safe - * to use strcpy because the buffer is allocated to the correct + * to use memcpy because the buffer is allocated to the correct * size... */ m->str = temp; - strcpy(m->str + length, ptr); + memcpy(m->str + length, ptr, ptrlen + 1); } else { /* * Copy the new portion to the end of the msgid string - safe - * to use strcpy because the buffer is allocated to the correct + * to use memcpy because the buffer is allocated to the correct * size... */ m->id = temp; - strcpy(m->id + length, ptr); + memcpy(m->id + length, ptr, ptrlen + 1); } } else if (!strncmp(s, "msgstr", 6) && m) diff --git a/cups/ppd-cache.c b/cups/ppd-cache.c index d39bf14e5..2e7a5d626 100644 --- a/cups/ppd-cache.c +++ b/cups/ppd-cache.c @@ -329,7 +329,7 @@ _ppdCacheCreateWithFile( goto create_error; } - if ((num_sizes = atoi(value)) <= 0 || num_sizes > 65536) + if ((num_sizes = atoi(value)) < 0 || num_sizes > 65536) { DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumSizes value %d on line " "%d.", num_sizes, linenum)); @@ -337,12 +337,15 @@ _ppdCacheCreateWithFile( goto create_error; } - if ((pc->sizes = calloc(num_sizes, sizeof(_pwg_size_t))) == NULL) + if (num_sizes > 0) { - DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d sizes.", - num_sizes)); - _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); - goto create_error; + if ((pc->sizes = calloc(num_sizes, sizeof(_pwg_size_t))) == NULL) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d sizes.", + num_sizes)); + _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); + goto create_error; + } } } else if (!_cups_strcasecmp(line, "Size")) @@ -557,6 +560,19 @@ _ppdCacheCreateWithFile( } else if (!_cups_strcasecmp(line, "MaxCopies")) pc->max_copies = atoi(value); + else if (!_cups_strcasecmp(line, "JobAccountId")) + pc->account_id = !_cups_strcasecmp(value, "true"); + else if (!_cups_strcasecmp(line, "JobAccountingUserId")) + pc->accounting_user_id = !_cups_strcasecmp(value, "true"); + else if (!_cups_strcasecmp(line, "JobPassword")) + pc->password = _cupsStrAlloc(value); + else if (!_cups_strcasecmp(line, "Mandatory")) + { + if (pc->mandatory) + _cupsArrayAddStrings(pc->mandatory, value, ' '); + else + pc->mandatory = _cupsArrayNewStrings(value, ' '); + } else { DEBUG_printf(("_ppdCacheCreateWithFile: Unknown %s on line %d.", line, @@ -684,148 +700,145 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ * Copy and convert size data... */ - if (ppd->num_sizes == 0) - { - DEBUG_puts("_ppdCacheCreateWithPPD: No page sizes in PPD."); - goto create_error; - } - - if ((pc->sizes = calloc(ppd->num_sizes, sizeof(_pwg_size_t))) == NULL) - { - DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d " - "_pwg_size_t's.", ppd->num_sizes)); - goto create_error; - } - - for (i = ppd->num_sizes, pwg_size = pc->sizes, ppd_size = ppd->sizes; - i > 0; - i --, ppd_size ++) + if (ppd->num_sizes > 0) { - /* - * Don't copy over custom size... - */ - - if (!_cups_strcasecmp(ppd_size->name, "Custom")) - continue; - - /* - * Convert the PPD size name to the corresponding PWG keyword name. - */ - - if ((pwg_media = _pwgMediaForPPD(ppd_size->name)) != NULL) + if ((pc->sizes = calloc(ppd->num_sizes, sizeof(_pwg_size_t))) == NULL) { - /* - * Standard name, do we have conflicts? - */ - - for (j = 0; j < pc->num_sizes; j ++) - if (!strcmp(pc->sizes[j].map.pwg, pwg_media->pwg)) - { - pwg_media = NULL; - break; - } + DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d " + "_pwg_size_t's.", ppd->num_sizes)); + goto create_error; } - if (pwg_media) + for (i = ppd->num_sizes, pwg_size = pc->sizes, ppd_size = ppd->sizes; + i > 0; + i --, ppd_size ++) { /* - * Standard name and no conflicts, use it! + * Don't copy over custom size... */ - pwg_name = pwg_media->pwg; - new_known_pwg = 1; - } - else - { + if (!_cups_strcasecmp(ppd_size->name, "Custom")) + continue; + /* - * Not a standard name; convert it to a PWG vendor name of the form: - * - * pp_lowerppd_WIDTHxHEIGHTuu + * Convert the PPD size name to the corresponding PWG keyword name. */ - pwg_name = pwg_keyword; - new_known_pwg = 0; + if ((pwg_media = _pwgMediaForPPD(ppd_size->name)) != NULL) + { + /* + * Standard name, do we have conflicts? + */ - pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name)); - _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), NULL, ppd_name, - _PWG_FROMPTS(ppd_size->width), - _PWG_FROMPTS(ppd_size->length)); - } + for (j = 0; j < pc->num_sizes; j ++) + if (!strcmp(pc->sizes[j].map.pwg, pwg_media->pwg)) + { + pwg_media = NULL; + break; + } + } - /* - * If we have a similar paper with non-zero margins then we only want to - * keep it if it has a larger imageable area length. The NULL check is for - * dimensions that are <= 0... - */ + if (pwg_media) + { + /* + * Standard name and no conflicts, use it! + */ - if ((pwg_media = _pwgMediaForSize(_PWG_FROMPTS(ppd_size->width), - _PWG_FROMPTS(ppd_size->length))) == NULL) - continue; - - new_width = pwg_media->width; - new_length = pwg_media->length; - new_left = _PWG_FROMPTS(ppd_size->left); - new_bottom = _PWG_FROMPTS(ppd_size->bottom); - new_right = _PWG_FROMPTS(ppd_size->width - ppd_size->right); - new_top = _PWG_FROMPTS(ppd_size->length - ppd_size->top); - new_imageable = new_length - new_top - new_bottom; - new_borderless = new_bottom == 0 && new_top == 0 && - new_left == 0 && new_right == 0; - - for (k = pc->num_sizes, similar = 0, old_size = pc->sizes, new_size = NULL; - k > 0 && !similar; - k --, old_size ++) - { - old_imageable = old_size->length - old_size->top - old_size->bottom; - old_borderless = old_size->left == 0 && old_size->bottom == 0 && - old_size->right == 0 && old_size->top == 0; - old_known_pwg = strncmp(old_size->map.pwg, "oe_", 3) && - strncmp(old_size->map.pwg, "om_", 3); - - similar = old_borderless == new_borderless && - _PWG_EQUIVALENT(old_size->width, new_width) && - _PWG_EQUIVALENT(old_size->length, new_length); - - if (similar && - (new_known_pwg || (!old_known_pwg && new_imageable > old_imageable))) + pwg_name = pwg_media->pwg; + new_known_pwg = 1; + } + else { /* - * The new paper has a larger imageable area so it could replace - * the older paper. Regardless of the imageable area, we always - * prefer the size with a well-known PWG name. + * Not a standard name; convert it to a PWG vendor name of the form: + * + * pp_lowerppd_WIDTHxHEIGHTuu */ - new_size = old_size; - _cupsStrFree(old_size->map.ppd); - _cupsStrFree(old_size->map.pwg); + pwg_name = pwg_keyword; + new_known_pwg = 0; + + pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name)); + _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), NULL, ppd_name, + _PWG_FROMPTS(ppd_size->width), + _PWG_FROMPTS(ppd_size->length)); } - } - if (!similar) - { /* - * The paper was unique enough to deserve its own entry so add it to the - * end. + * If we have a similar paper with non-zero margins then we only want to + * keep it if it has a larger imageable area length. The NULL check is for + * dimensions that are <= 0... */ - new_size = pwg_size ++; - pc->num_sizes ++; - } + if ((pwg_media = _pwgMediaForSize(_PWG_FROMPTS(ppd_size->width), + _PWG_FROMPTS(ppd_size->length))) == NULL) + continue; - if (new_size) - { - /* - * Save this size... - */ + new_width = pwg_media->width; + new_length = pwg_media->length; + new_left = _PWG_FROMPTS(ppd_size->left); + new_bottom = _PWG_FROMPTS(ppd_size->bottom); + new_right = _PWG_FROMPTS(ppd_size->width - ppd_size->right); + new_top = _PWG_FROMPTS(ppd_size->length - ppd_size->top); + new_imageable = new_length - new_top - new_bottom; + new_borderless = new_bottom == 0 && new_top == 0 && + new_left == 0 && new_right == 0; + + for (k = pc->num_sizes, similar = 0, old_size = pc->sizes, new_size = NULL; + k > 0 && !similar; + k --, old_size ++) + { + old_imageable = old_size->length - old_size->top - old_size->bottom; + old_borderless = old_size->left == 0 && old_size->bottom == 0 && + old_size->right == 0 && old_size->top == 0; + old_known_pwg = strncmp(old_size->map.pwg, "oe_", 3) && + strncmp(old_size->map.pwg, "om_", 3); + + similar = old_borderless == new_borderless && + _PWG_EQUIVALENT(old_size->width, new_width) && + _PWG_EQUIVALENT(old_size->length, new_length); + + if (similar && + (new_known_pwg || (!old_known_pwg && new_imageable > old_imageable))) + { + /* + * The new paper has a larger imageable area so it could replace + * the older paper. Regardless of the imageable area, we always + * prefer the size with a well-known PWG name. + */ + + new_size = old_size; + _cupsStrFree(old_size->map.ppd); + _cupsStrFree(old_size->map.pwg); + } + } + + if (!similar) + { + /* + * The paper was unique enough to deserve its own entry so add it to the + * end. + */ + + new_size = pwg_size ++; + pc->num_sizes ++; + } + + if (new_size) + { + /* + * Save this size... + */ - new_size->map.ppd = _cupsStrAlloc(ppd_size->name); - new_size->map.pwg = _cupsStrAlloc(pwg_name); - new_size->width = new_width; - new_size->length = new_length; - new_size->left = new_left; - new_size->bottom = new_bottom; - new_size->right = new_right; - new_size->top = new_top; + new_size->map.ppd = _cupsStrAlloc(ppd_size->name); + new_size->map.pwg = _cupsStrAlloc(pwg_name); + new_size->width = new_width; + new_size->length = new_length; + new_size->left = new_left; + new_size->bottom = new_bottom; + new_size->right = new_right; + new_size->top = new_top; + } } } @@ -1366,6 +1379,23 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ else pc->max_copies = 9999; + /* + * cupsJobAccountId, cupsJobAccountingUserId, cupsJobPassword, and + * cupsMandatory. + */ + + if ((ppd_attr = ppdFindAttr(ppd, "cupsJobAccountId", NULL)) != NULL) + pc->account_id = !_cups_strcasecmp(ppd_attr->value, "true"); + + if ((ppd_attr = ppdFindAttr(ppd, "cupsJobAccountingUserId", NULL)) != NULL) + pc->accounting_user_id = !_cups_strcasecmp(ppd_attr->value, "true"); + + if ((ppd_attr = ppdFindAttr(ppd, "cupsJobPassword", NULL)) != NULL) + pc->password = _cupsStrAlloc(ppd_attr->value); + + if ((ppd_attr = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL) + pc->mandatory = _cupsArrayNewStrings(ppd_attr->value, ' '); + /* * Return the cache data... */ @@ -1466,6 +1496,10 @@ _ppdCacheDestroy(_ppd_cache_t *pc) /* I - PPD cache and mapping data */ cupsArrayDelete(pc->prefilters); cupsArrayDelete(pc->finishings); + _cupsStrFree(pc->password); + + cupsArrayDelete(pc->mandatory); + free(pc); } @@ -2357,6 +2391,22 @@ _ppdCacheWriteFile( cupsFilePrintf(fp, "MaxCopies %d\n", pc->max_copies); + /* + * Accounting/quota/PIN/managed printing values... + */ + + cupsFilePrintf(fp, "AccountId %s\n", pc->account_id ? "true" : "false"); + cupsFilePrintf(fp, "AccountingUserId %s\n", + pc->accounting_user_id ? "true" : "false"); + + if (pc->password) + cupsFilePutConf(fp, "Password", pc->password); + + for (value = (char *)cupsArrayFirst(pc->mandatory); + value; + value = (char *)cupsArrayNext(pc->mandatory)) + cupsFilePutConf(fp, "Mandatory", value); + /* * IPP attributes, if any... */ diff --git a/cups/ppd-private.h b/cups/ppd-private.h index 426c74ff8..1eaa2c816 100644 --- a/cups/ppd-private.h +++ b/cups/ppd-private.h @@ -49,7 +49,7 @@ extern "C" { * Constants... */ -# define _PPD_CACHE_VERSION 3 /* Version number in cache file */ +# define _PPD_CACHE_VERSION 4 /* Version number in cache file */ /* @@ -141,7 +141,11 @@ struct _ppd_cache_s /**** PPD cache and PWG conversion data ****/ *prefilters; /* cupsPreFilter values */ int single_file; /* cupsSingleFile value */ cups_array_t *finishings; /* cupsIPPFinishings values */ - int max_copies; /* cupsMaxCopies value */ + int max_copies, /* cupsMaxCopies value */ + account_id, /* cupsJobAccountId value */ + accounting_user_id; /* cupsJobAccountingUserId value */ + char *password; /* cupsJobPassword value */ + cups_array_t *mandatory; /* cupsMandatory value */ }; diff --git a/cups/ppd.c b/cups/ppd.c index 1ff51b244..fe58fcfe0 100644 --- a/cups/ppd.c +++ b/cups/ppd.c @@ -1264,7 +1264,7 @@ _ppdOpen( ppd->patches = temp; - strcpy(ppd->patches + strlen(ppd->patches), string); + memcpy(ppd->patches + strlen(ppd->patches), string, strlen(string) + 1); } } else if (!strcmp(keyword, "OpenUI")) @@ -1378,7 +1378,7 @@ _ppdOpen( */ if (!_cups_strcasecmp(name, "PageRegion")) - strcpy(custom_name, "CustomPageSize"); + strlcpy(custom_name, "CustomPageSize", sizeof(custom_name)); else snprintf(custom_name, sizeof(custom_name), "Custom%s", name); @@ -1944,9 +1944,9 @@ _ppdOpen( cupsCharsetToUTF8((cups_utf8_t *)choice->text, text, sizeof(choice->text), encoding); else if (!strcmp(name, "True")) - strcpy(choice->text, _("Yes")); + strlcpy(choice->text, _("Yes"), sizeof(choice->text)); else if (!strcmp(name, "False")) - strcpy(choice->text, _("No")); + strlcpy(choice->text, _("No"), sizeof(choice->text)); else strlcpy(choice->text, name, sizeof(choice->text)); diff --git a/cups/pwg-media.c b/cups/pwg-media.c index f4850dcf6..222b6ef7c 100644 --- a/cups/pwg-media.c +++ b/cups/pwg-media.c @@ -486,7 +486,7 @@ _pwgInitSize(_pwg_size_t *size, /* I - Size to initialize */ if ((media = ippFindAttribute(job, "PageSize", IPP_TAG_NAME)) == NULL) media = ippFindAttribute(job, "PageRegion", IPP_TAG_NAME); - if (media) + if (media && media->values[0].string.text) { const char *name = media->values[0].string.text; /* Name string */ diff --git a/cups/request.c b/cups/request.c index a10852fa8..51457df84 100644 --- a/cups/request.c +++ b/cups/request.c @@ -51,9 +51,9 @@ /* * 'cupsDoFileRequest()' - Do an IPP request with a file. * - * This function sends the IPP request to the specified server, retrying - * and authenticating as necessary. The request is freed with @link ippDelete@ - * after receiving a valid IPP response. + * This function sends the IPP request and attached file to the specified + * server, retrying and authenticating as necessary. The request is freed with + * @link ippDelete@. */ ipp_t * /* O - Response data */ @@ -102,14 +102,14 @@ cupsDoFileRequest(http_t *http, /* I - Connection to server or @code CUPS_HT /* * 'cupsDoIORequest()' - Do an IPP request with file descriptors. * - * This function sends the IPP request to the specified server, retrying - * and authenticating as necessary. The request is freed with ippDelete() - * after receiving a valid IPP response. + * This function sends the IPP request with the optional input file "infile" to + * the specified server, retrying and authenticating as necessary. The request + * is freed with @link ippDelete@. * - * If "infile" is a valid file descriptor, cupsDoIORequest() copies + * If "infile" is a valid file descriptor, @code cupsDoIORequest@ copies * all of the data from the file after the IPP request message. * - * If "outfile" is a valid file descriptor, cupsDoIORequest() copies + * If "outfile" is a valid file descriptor, @code cupsDoIORequest@ copies * all of the data after the IPP response message to the file. * * @since CUPS 1.3/OS X 10.5@ @@ -309,8 +309,7 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP * 'cupsDoRequest()' - Do an IPP request. * * This function sends the IPP request to the specified server, retrying - * and authenticating as necessary. The request is freed with ippDelete() - * after receiving a valid IPP response. + * and authenticating as necessary. The request is freed with @link ippDelete@. */ ipp_t * /* O - Response data */ @@ -331,9 +330,9 @@ cupsDoRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ * 'cupsGetResponse()' - Get a response to an IPP request. * * Use this function to get the response for an IPP request sent using - * cupsSendDocument() or cupsSendRequest(). For requests that return - * additional data, use httpRead() after getting a successful response, - * otherwise call httpFlush() to complete the response processing. + * @link cupsSendRequest@. For requests that return additional data, use + * @link cupsReadResponseData@ after getting a successful response, + * otherwise call @link httpFlush@ to complete the response processing. * * @since CUPS 1.4/OS X 10.6@ */ @@ -481,7 +480,8 @@ cupsGetResponse(http_t *http, /* I - Connection to server or @code CUPS_HTTP /* - * 'cupsLastError()' - Return the last IPP status code. + * 'cupsLastError()' - Return the last IPP status code received on the current + * thread. */ ipp_status_t /* O - IPP status code from last request */ @@ -492,7 +492,8 @@ cupsLastError(void) /* - * 'cupsLastErrorString()' - Return the last IPP status-message. + * 'cupsLastErrorString()' - Return the last IPP status-message received on the + * current thread. * * @since CUPS 1.2/OS X 10.5@ */ @@ -537,8 +538,9 @@ _cupsNextDelay(int current, /* I - Current delay value or 0 */ /* * 'cupsReadResponseData()' - Read additional data after the IPP response. * - * This function is used after cupsGetResponse() to read the PPD or document - * files for CUPS_GET_PPD and CUPS_GET_DOCUMENT requests, respectively. + * This function is used after @link cupsGetResponse@ to read the PPD or document + * files from @code CUPS_GET_PPD@ and @code CUPS_GET_DOCUMENT@ requests, + * respectively. * * @since CUPS 1.4/OS X 10.6@ */ @@ -579,13 +581,17 @@ cupsReadResponseData( /* * 'cupsSendRequest()' - Send an IPP request. * - * Use httpWrite() to write any additional data (document, PPD file, etc.) - * for the request, cupsGetResponse() to get the IPP response, and httpRead() - * to read any additional data following the response. Only one request can be - * sent/queued at a time. + * Use @link cupsWriteRequestData@ to write any additional data (document, PPD + * file, etc.) for the request, @link cupsGetResponse@ to get the IPP response, + * and @link cupsReadResponseData@ to read any additional data following the + * response. Only one request can be sent/queued at a time per @code http_t@ + * connection. + * + * Returns the initial HTTP status code, which will be @code HTTP_CONTINUE@ + * on a successful send of the request. * - * Unlike cupsDoFileRequest(), cupsDoIORequest(), and cupsDoRequest(), the - * request is not freed. + * Note: Unlike @link cupsDoFileRequest@, @link cupsDoIORequest@, and + * @link cupsDoRequest@, the request is NOT freed with @link ippDelete@. * * @since CUPS 1.4/OS X 10.6@ */ diff --git a/cups/snprintf.c b/cups/snprintf.c index fcebf895e..9271052d5 100644 --- a/cups/snprintf.c +++ b/cups/snprintf.c @@ -3,7 +3,7 @@ * * snprintf functions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -48,6 +48,7 @@ _cups_vsnprintf(char *buffer, /* O - Output buffer */ char tformat[100], /* Temporary format string for sprintf() */ *tptr, /* Pointer into temporary format */ temp[1024]; /* Buffer for formatted numbers */ + size_t templen; /* Length of "temp" */ char *s; /* Pointer to string */ int slen; /* Length of string */ int bytes; /* Total number of bytes needed */ @@ -183,20 +184,21 @@ _cups_vsnprintf(char *buffer, /* O - Output buffer */ break; sprintf(temp, tformat, va_arg(ap, double)); + templen = strlen(temp): - bytes += (int)strlen(temp); + bytes += (int)templen; if (bufptr) { - if ((bufptr + strlen(temp)) > bufend) + if ((bufptr + templen) > bufend) { - strncpy(bufptr, temp, (size_t)(bufend - bufptr)); + strlcpy(bufptr, temp, (size_t)(bufend - bufptr)); bufptr = bufend; } else { - strcpy(bufptr, temp); - bufptr += strlen(temp); + memcpy(bufptr, temp, templen + 1); + bufptr += templen; } } break; @@ -213,20 +215,21 @@ _cups_vsnprintf(char *buffer, /* O - Output buffer */ break; sprintf(temp, tformat, va_arg(ap, int)); + templen = strlen(temp): - bytes += (int)strlen(temp); + bytes += (int)templen; if (bufptr) { - if ((bufptr + strlen(temp)) > bufend) + if ((bufptr + templen) > bufend) { - strncpy(bufptr, temp, (size_t)(bufend - bufptr)); + strlcpy(bufptr, temp, (size_t)(bufend - bufptr)); bufptr = bufend; } else { - strcpy(bufptr, temp); - bufptr += strlen(temp); + memcpy(bufptr, temp, templen + 1); + bufptr += templen; } } break; @@ -236,20 +239,21 @@ _cups_vsnprintf(char *buffer, /* O - Output buffer */ break; sprintf(temp, tformat, va_arg(ap, void *)); + templen = strlen(temp): - bytes += (int)strlen(temp); + bytes += (int)templen; if (bufptr) { - if ((bufptr + strlen(temp)) > bufend) + if ((bufptr + templen) > bufend) { - strncpy(bufptr, temp, (size_t)(bufend - bufptr)); + strlcpy(bufptr, temp, (size_t)(bufend - bufptr)); bufptr = bufend; } else { - strcpy(bufptr, temp); - bufptr += strlen(temp); + memcpy(bufptr, temp, templen + 1); + bufptr += templen; } } break; diff --git a/cups/string.c b/cups/string.c index 538a26386..ad5b5bc61 100644 --- a/cups/string.c +++ b/cups/string.c @@ -3,7 +3,7 @@ * * String functions for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -69,6 +69,7 @@ static int compare_sp_items(_cups_sp_item_t *a, _cups_sp_item_t *b); char * /* O - String pointer */ _cupsStrAlloc(const char *s) /* I - String */ { + size_t slen; /* Length of string */ _cups_sp_item_t *item, /* String pool item */ *key; /* Search key */ @@ -128,7 +129,8 @@ _cupsStrAlloc(const char *s) /* I - String */ * Not found, so allocate a new one... */ - item = (_cups_sp_item_t *)calloc(1, sizeof(_cups_sp_item_t) + strlen(s)); + slen = strlen(s); + item = (_cups_sp_item_t *)calloc(1, sizeof(_cups_sp_item_t) + slen); if (!item) { _cupsMutexUnlock(&sp_mutex); @@ -137,7 +139,7 @@ _cupsStrAlloc(const char *s) /* I - String */ } item->ref_count = 1; - strcpy(item->str, s); + memcpy(item->str, s, slen + 1); #ifdef DEBUG_GUARDS item->guard = _CUPS_STR_GUARD; @@ -588,16 +590,18 @@ _cups_strcpy(char *dst, /* I - Destination string */ char * /* O - New string pointer */ _cups_strdup(const char *s) /* I - String to duplicate */ { - char *t; /* New string pointer */ + char *t; /* New string pointer */ + size_t slen; /* Length of string */ - if (s == NULL) + if (!s) return (NULL); - if ((t = malloc(strlen(s) + 1)) == NULL) + slen = strlen(s); + if ((t = malloc(slen + 1)) == NULL) return (NULL); - return (strcpy(t, s)); + return (memcpy(t, s, slen + 1)); } #endif /* !HAVE_STRDUP */ diff --git a/cups/testarray.c b/cups/testarray.c index 2e254c24e..9f7eb2a71 100644 --- a/cups/testarray.c +++ b/cups/testarray.c @@ -3,7 +3,7 @@ * * Array test program for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -139,7 +139,7 @@ main(int argc, /* I - Number of command-line arguments */ /* * cupsArrayCount() */ - + fputs("cupsArrayCount: ", stdout); if (cupsArrayCount(array) == 4) puts("PASS"); @@ -319,7 +319,7 @@ main(int argc, /* I - Number of command-line arguments */ * the same buffer in the first place... :) */ - strcpy(word, text); + strlcpy(word, text, sizeof(word)); /* * Grab the next word and compare... diff --git a/cups/testhttp.c b/cups/testhttp.c index a133f8233..089e4d28c 100644 --- a/cups/testhttp.c +++ b/cups/testhttp.c @@ -3,7 +3,7 @@ * * HTTP test program for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -218,7 +218,7 @@ main(int argc, /* I - Number of command-line arguments */ fputs("httpGetDateString()/httpGetDateTime(): ", stdout); start = time(NULL); - strcpy(buffer, httpGetDateString(start)); + strlcpy(buffer, httpGetDateString(start), sizeof(buffer)); current = httpGetDateTime(buffer); i = (int)(current - start); diff --git a/cups/testi18n.c b/cups/testi18n.c index 725c01b2b..d8eb4ba0f 100644 --- a/cups/testi18n.c +++ b/cups/testi18n.c @@ -3,7 +3,7 @@ * * Internationalization test for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -282,7 +282,7 @@ main(int argc, /* I - Argument Count */ fputs("cupsCharsetToUTF8(CUPS_ISO8859_1): ", stdout); - strcpy(legsrc, legdest); + strlcpy(legsrc, legdest, sizeof(legsrc)); len = cupsCharsetToUTF8(utf8dest, legsrc, 1024, CUPS_ISO8859_1); if (len != strlen((char *)utf8latin)) @@ -333,7 +333,7 @@ main(int argc, /* I - Argument Count */ fputs("cupsCharsetToUTF8(CUPS_ISO8859_7): ", stdout); - strcpy(legsrc, legdest); + strlcpy(legsrc, legdest, sizeof(legsrc)); len = cupsCharsetToUTF8(utf8dest, legsrc, 1024, CUPS_ISO8859_7); if (len != strlen((char *)utf8greek)) @@ -379,7 +379,7 @@ main(int argc, /* I - Argument Count */ fputs("cupsCharsetToUTF8(CUPS_WINDOWS_932): ", stdout); - strcpy(legsrc, legdest); + strlcpy(legsrc, legdest, sizeof(legsrc)); len = cupsCharsetToUTF8(utf8dest, legsrc, 1024, CUPS_WINDOWS_932); if (len != strlen((char *)utf8japan)) @@ -426,7 +426,7 @@ main(int argc, /* I - Argument Count */ #ifndef __linux fputs("cupsCharsetToUTF8(CUPS_EUC_JP): ", stdout); - strcpy(legsrc, legdest); + strlcpy(legsrc, legdest, sizeof(legsrc)); len = cupsCharsetToUTF8(utf8dest, legsrc, 1024, CUPS_EUC_JP); if (len != strlen((char *)utf8japan)) @@ -473,7 +473,7 @@ main(int argc, /* I - Argument Count */ fputs("cupsCharsetToUTF8(CUPS_WINDOWS_950): ", stdout); - strcpy(legsrc, legdest); + strlcpy(legsrc, legdest, sizeof(legsrc)); len = cupsCharsetToUTF8(utf8dest, legsrc, 1024, CUPS_WINDOWS_950); if (len != strlen((char *)utf8taiwan)) @@ -519,7 +519,7 @@ main(int argc, /* I - Argument Count */ fputs("cupsCharsetToUTF8(CUPS_EUC_TW): ", stdout); - strcpy(legsrc, legdest); + strlcpy(legsrc, legdest, sizeof(legsrc)); len = cupsCharsetToUTF8(utf8dest, legsrc, 1024, CUPS_EUC_TW); if (len != strlen((char *)utf8taiwan)) diff --git a/cups/testppd.c b/cups/testppd.c index 5e291ce83..ef88425dc 100644 --- a/cups/testppd.c +++ b/cups/testppd.c @@ -3,7 +3,7 @@ * * PPD test program for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -150,6 +150,7 @@ main(int argc, /* I - Number of command-line arguments */ maxsize, /* Maximum size */ *size; /* Current size */ ppd_attr_t *attr; /* Current attribute */ + _ppd_cache_t *pc; /* PPD cache */ status = 0; @@ -897,7 +898,7 @@ main(int argc, /* I - Number of command-line arguments */ if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0) - strcpy(realfile, "Unknown"); + strlcpy(realfile, "Unknown", sizeof(realfile)); else realfile[realsize] = '\0'; @@ -1073,6 +1074,15 @@ main(int argc, /* I - Number of command-line arguments */ attr = (ppd_attr_t *)cupsArrayNext(ppd->sorted_attrs)) printf(" *%s %s/%s: \"%s\"\n", attr->name, attr->spec, attr->text, attr->value ? attr->value : ""); + + puts("\nPPD Cache:"); + if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL) + printf(" Unable to create: %s\n", cupsLastErrorString()); + else + { + _ppdCacheWriteFile(pc, "t.cache", NULL); + puts(" Wrote t.cache."); + } } if (!strncmp(argv[1], "-d", 2)) diff --git a/cups/usersys.c b/cups/usersys.c index 7aee0007f..989700726 100644 --- a/cups/usersys.c +++ b/cups/usersys.c @@ -358,7 +358,7 @@ cupsSetServer(const char *server) /* I - Server name */ } if (cg->server[0] == '/') - strcpy(cg->servername, "localhost"); + strlcpy(cg->servername, "localhost", sizeof(cg->servername)); else strlcpy(cg->servername, cg->server, sizeof(cg->servername)); } @@ -949,7 +949,7 @@ cups_read_client_conf( value = NULL; if (cg->server[0] == '/') - strcpy(cg->servername, "localhost"); + strlcpy(cg->servername, "localhost", sizeof(cg->servername)); else strlcpy(cg->servername, cg->server, sizeof(cg->servername)); } @@ -1035,7 +1035,7 @@ cups_read_client_conf( * Use the default "unknown" user name... */ - strcpy(cg->user, "unknown"); + strlcpy(cg->user, "unknown", sizeof(cg->user)); } } } diff --git a/cups/util.c b/cups/util.c index a73130763..c9826549c 100644 --- a/cups/util.c +++ b/cups/util.c @@ -605,7 +605,7 @@ cupsGetJobs2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_D } } else - strcpy(uri, "ipp://localhost/"); + strlcpy(uri, "ipp://localhost/", sizeof(uri)); if (!http) if ((http = _cupsConnect()) == NULL) @@ -1059,7 +1059,7 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL DEBUG_printf(("2cupsGetPPD3: Local hostname=\"%s\"", localhost)); if (!_cups_strcasecmp(localhost, hostname)) - strcpy(hostname, "localhost"); + strlcpy(hostname, "localhost", sizeof(hostname)); /* * Get the hostname and port number we are connected to... diff --git a/doc/help/api-cups.html b/doc/help/api-cups.html index 1cd0e5036..0f960dfe2 100644 --- a/doc/help/api-cups.html +++ b/doc/help/api-cups.html @@ -391,23 +391,34 @@ div.contents ul.subcontents li {
  • Passwords and Authentication
  • Functions
      -
    • appleGetPaperSize
    • cupsAddDest
    • cupsAddOption
    • cupsAdminCreateWindowsPPD
    • cupsAdminExportSamba
    • cupsAdminGetServerSettings
    • cupsAdminSetServerSettings
    • +
    • cupsCancelDestJob
    • cupsCancelJob
    • cupsCancelJob2
    • +
    • cupsCheckDestSupported
    • +
    • cupsCloseDestJob
    • cupsConnectDest
    • cupsConnectDestBlock
    • cupsCopyDest
    • +
    • cupsCopyDestConflicts
    • +
    • cupsCopyDestInfo
    • +
    • cupsCreateDestJob
    • cupsCreateJob
    • cupsEncryption
    • cupsEnumDests
    • cupsEnumDestsBlock
    • +
    • cupsFinishDestDocument
    • cupsFinishDocument
    • +
    • cupsFreeDestInfo
    • cupsFreeDests
    • cupsFreeJobs
    • cupsFreeOptions
    • @@ -415,6 +426,8 @@ div.contents ul.subcontents li {
    • cupsGetDefault
    • cupsGetDefault2
    • cupsGetDest
    • +
    • cupsGetDestMediaByName
    • +
    • cupsGetDestMediaBySize
    • cupsGetDests
    • cupsGetDests2
    • cupsGetJobs
    • @@ -436,6 +449,10 @@ for the given language.">cupsLangEncoding
    • cupsLangFlush
    • cupsLangFree
    • cupsLangGet
    • +
    • cupsLocalizeDestOption
    • +
    • cupsLocalizeDestValue
    • cupsNotifySubject
    • cupsNotifyText
    • cupsParseOptions
    • @@ -461,6 +478,7 @@ connections.">cupsSetCredentials
    • cupsSetServer
    • cupsSetServerCertCB
    • cupsSetUser
    • +
    • cupsStartDestDocument
    • cupsStartDocument
    • cupsTempFd
    • cupsTempFile
    • @@ -949,22 +967,6 @@ fields for the username and password. The username should default to the string returned by the cupsUser function.

      Functions

      -

      appleGetPaperSize

      -

      Get the default paper size.

      -

      -char *appleGetPaperSize (
      -    char *name,
      -    int namesize
      -);

      -

      Parameters

      -
      -
      name
      -
      Paper size name buffer
      -
      namesize
      -
      Size of buffer
      -
      -

      Return Value

      -

      Default paper size

      cupsAddDest

      Add a destination to the list of destinations.

      @@ -1023,7 +1025,7 @@ int cupsAddOption (

      Discussion

      New option arrays can be initialized simply by passing 0 for the "num_options" parameter.

      -

       CUPS 1.2/OS X 10.5 cupsAdminCreateWindowsPPD

      +

       DEPRECATED cupsAdminCreateWindowsPPD

      Create the Windows PPD file for a printer.

      char *cupsAdminCreateWindowsPPD (
      @@ -1045,7 +1047,7 @@ char *cupsAdminCreateWindowsPPD (

      Return Value

      PPD file or NULL

      -

       CUPS 1.2/OS X 10.5 cupsAdminExportSamba

      +

       DEPRECATED cupsAdminExportSamba

      Export a printer to Samba.

      int cupsAdminExportSamba (
      @@ -1116,6 +1118,31 @@ int cupsAdminSetServerSettings (

      Return Value

      1 on success, 0 on failure

      +

      cupsCancelDestJob

      +

      Include necessary headers...

      +

      +ipp_status_t cupsCancelDestJob (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    int job_id
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      job_id
      +
      Job ID
      +
      +

      Return Value

      +

      Cancel a job on a destination.

      +

      The "job_id" is the number returned by cupsCreateDestJob.
      +
      +Returns IPP_OK on success and IPP_NOT_AUTHORIZED or IPP_FORBIDDEN on +failure. + +

      cupsCancelJob

      Cancel a print job on the default server.

      @@ -1170,6 +1197,64 @@ to cancel the current job on the named destination.
      Use the cupsLastError and cupsLastErrorString functions to get the cause of any failure. +

      +

       CUPS 1.6/OS X 10.8 cupsCheckDestSupported

      +

      Check that the option and value are supported +by the destination.

      +

      +int cupsCheckDestSupported (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *dinfo,
      +    const char *option,
      +    const char *value
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      dinfo
      +
      Destination information
      +
      option
      +
      Option
      +
      value
      +
      Value
      +
      +

      Return Value

      +

      1 if supported, 0 otherwise

      +

      Discussion

      +

      Returns 1 if supported, 0 otherwise. + +

      +

       CUPS 1.6/OS X 10.8 cupsCloseDestJob

      +

      Close a job and start printing.

      +

      +ipp_status_t cupsCloseDestJob (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *info,
      +    int job_id
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      info
      +
      Destination information
      +
      job_id
      +
      Job ID
      +
      +

      Return Value

      +

      IPP status code

      +

      Discussion

      +

      Use when the last call to cupsStartDocument passed 0 for "last_document". +"job_id" is the job ID returned by cupsCreateDestJob. Returns IPP_OK +on success. +

       CUPS 1.6/OS X 10.8 cupsConnectDest

      Connect to the server for a destination.

      @@ -1272,6 +1357,125 @@ int cupsCopyDest (
      copy) - for use with the cupsEnumDests* functions. The caller is responsible for calling cupsFreeDests() on the returned object(s). +

      +

       CUPS 1.6/OS X 10.8 cupsCopyDestConflicts

      +

      Get conflicts and resolutions for a new +option/value pair.

      +

      +int cupsCopyDestConflicts (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *dinfo,
      +    int num_options,
      +    cups_option_t *options,
      +    const char *new_option,
      +    const char *new_value,
      +    int *num_conflicts,
      +    cups_option_t **conflicts,
      +    int *num_resolved,
      +    cups_option_t **resolved
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      dinfo
      +
      Destination information
      +
      num_options
      +
      Number of current options
      +
      options
      +
      Current options
      +
      new_option
      +
      New option
      +
      new_value
      +
      New value
      +
      num_conflicts
      +
      Number of conflicting options
      +
      conflicts
      +
      Conflicting options
      +
      num_resolved
      +
      Number of options to resolve
      +
      resolved
      +
      Resolved options
      +
      +

      Return Value

      +

      1 if there is a conflict, 0 if none, -1 on error

      +

      Discussion

      +

      "num_options" and "options" represent the currently selected options by the +user. "new_option" and "new_value" are the setting the user has just +changed.
      +
      +Returns 1 if there is a conflict, 0 if there are no conflicts, and -1 if +there was an unrecoverable error such as a resolver loop.
      +
      +If "num_conflicts" and "conflicts" are not NULL, they are set to +contain the list of conflicting option/value pairs. Similarly, if +"num_resolved" and "resolved" are not NULL they will be set to the +list of changes needed to resolve the conflict.
      +
      +If cupsCopyDestConflicts returns 1 but "num_resolved" and "resolved" are set +to 0 and NULL, respectively, then the conflict cannot be resolved. + +

      +

       CUPS 1.6/OS X 10.8 cupsCopyDestInfo

      +

      Get the supported values/capabilities for the +destination.

      +

      +cups_dinfo_t *cupsCopyDestInfo (
      +    http_t *http,
      +    cups_dest_t *dest
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      +

      Return Value

      +

      Destination information

      +

      Discussion

      +

      The caller is responsible for calling cupsFreeDestInfo on the return +value. NULL is returned on error. + +

      +

       CUPS 1.6/OS X 10.8 cupsCreateDestJob

      +

      Create a job on a destination.

      +

      +ipp_status_t cupsCreateDestJob (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *info,
      +    int *job_id,
      +    const char *title,
      +    int num_options,
      +    cups_option_t *options
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      info
      +
      Destination information
      +
      job_id
      +
      Job ID or 0 on error
      +
      title
      +
      Job name
      +
      num_options
      +
      Number of job options
      +
      options
      +
      Job options
      +
      +

      Return Value

      +

      IPP status code

      +

      Discussion

      +

      Returns IPP_OK or IPP_OK_SUBST on success, saving the job ID +in the variable pointed to by "job_id". +

       CUPS 1.4/OS X 10.6 cupsCreateJob

      Create an empty job for streaming.

      @@ -1401,6 +1605,29 @@ continue enumeration or 0 to stop.
      Enumeration happens on the current thread and does not return until all destinations have been enumerated or the block returns 0. +

      +

       CUPS 1.6/OS X 10.8 cupsFinishDestDocument

      +

      Finish the current document.

      +

      +ipp_status_t cupsFinishDestDocument (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *info
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      info
      +
      Destination information
      +
      +

      Return Value

      +

      Status of document submission

      +

      Discussion

      +

      Returns IPP_OK or IPP_OK_SUBST on success. +

       CUPS 1.4/OS X 10.6 cupsFinishDocument

      Finish sending a document.

      @@ -1422,6 +1649,18 @@ ipp_status_t cupsFinishDocument (

      The document must have been started using cupsStartDocument.

      +

      cupsFreeDestInfo

      +

      Free destination information obtained using +cupsCopyDestInfo.

      +

      +void cupsFreeDestInfo (
      +    cups_dinfo_t *dinfo
      +);

      +

      Parameters

      +
      +
      dinfo
      +
      Destination information
      +

      cupsFreeDests

      Free the memory used by the list of destinations.

      @@ -1541,6 +1780,99 @@ not support the lpoptions-defined default printer.

      Discussion

      Use the cupsGetDests or cupsGetDests2 functions to get a list of supported destinations for the current user.

      +

       CUPS 1.6/OS X 10.8 cupsGetDestMediaByName

      +

      Get media names, dimensions, and margins.

      +

      +int cupsGetDestMediaByName (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *dinfo,
      +    const char *media,
      +    unsigned flags,
      +    cups_size_t *size
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      dinfo
      +
      Destination information
      +
      media
      +
      Media name
      +
      flags
      +
      Media matching flags
      +
      size
      +
      Media size information
      +
      +

      Return Value

      +

      1 on match, 0 on failure

      +

      Discussion

      +

      The "media" string is a PWG media name. "Flags" provides some matching +guidance (multiple flags can be combined):
      +
      +CUPS_MEDIA_FLAGS_DEFAULT = find the closest size supported by the printer, +CUPS_MEDIA_FLAGS_BORDERLESS = find a borderless size, +CUPS_MEDIA_FLAGS_DUPLEX = find a size compatible with 2-sided printing, +CUPS_MEDIA_FLAGS_EXACT = find an exact match for the size, and +CUPS_MEDIA_FLAGS_READY = if the printer supports media sensing, find the +size amongst the "ready" media.
      +
      +The matching result (if any) is returned in the "cups_size_t" structure.
      +
      +Returns 1 when there is a match and 0 if there is not a match. + +

      +

       CUPS 1.6/OS X 10.8 cupsGetDestMediaBySize

      +

      Get media names, dimensions, and margins.

      +

      +int cupsGetDestMediaBySize (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *dinfo,
      +    int width,
      +    int length,
      +    unsigned flags,
      +    cups_size_t *size
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      dinfo
      +
      Destination information
      +
      width
      +
      Media width in hundredths of +of millimeters
      +
      length
      +
      Media length in hundredths of +of millimeters
      +
      flags
      +
      Media matching flags
      +
      size
      +
      Media size information
      +
      +

      Return Value

      +

      1 on match, 0 on failure

      +

      Discussion

      +

      "Width" and "length" are the dimensions in hundredths of millimeters. +"Flags" provides some matching guidance (multiple flags can be combined):
      +
      +CUPS_MEDIA_FLAGS_DEFAULT = find the closest size supported by the printer, +CUPS_MEDIA_FLAGS_BORDERLESS = find a borderless size, +CUPS_MEDIA_FLAGS_DUPLEX = find a size compatible with 2-sided printing, +CUPS_MEDIA_FLAGS_EXACT = find an exact match for the size, and +CUPS_MEDIA_FLAGS_READY = if the printer supports media sensing, find the +size amongst the "ready" media.
      +
      +The matching result (if any) is returned in the "cups_size_t" structure.
      +
      +Returns 1 when there is a match and 0 if there is not a match. + +

      cupsGetDests

      Get the list of destinations from the default server.

      @@ -1945,6 +2277,65 @@ cups_lang_t *cupsLangGet (

      Return Value

      Language data

      +

       CUPS 1.6/OS X 10.8 cupsLocalizeDestOption

      +

      Get the localized string for a destination +option.

      +

      +const char *cupsLocalizeDestOption (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *dinfo,
      +    const char *option
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      dinfo
      +
      Destination information
      +
      option
      +
      Option to localize
      +
      +

      Return Value

      +

      Localized string

      +

      Discussion

      +

      The returned string is stored in the destination information and will become +invalid if the destination information is deleted. + +

      +

       CUPS 1.6/OS X 10.8 cupsLocalizeDestValue

      +

      Get the localized string for a destination +option+value pair.

      +

      +const char *cupsLocalizeDestValue (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *dinfo,
      +    const char *option,
      +    const char *value
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      dinfo
      +
      Destination information
      +
      option
      +
      Option to localize
      +
      value
      +
      Value to localize
      +
      +

      Return Value

      +

      Localized string

      +

      Discussion

      +

      The returned string is stored in the destination information and will become +invalid if the destination information is deleted. + +

       CUPS 1.2/OS X 10.5 cupsNotifySubject

      Return the subject for the given notification message.

      @@ -2420,6 +2811,52 @@ void cupsSetUser (
      Note: The current user name is tracked separately for each thread in a program. Multi-threaded programs that override the user name need to do so in each thread for the same user name to be used.

      +

       CUPS 1.6/OS X 10.8 cupsStartDestDocument

      +

      Start a new document.

      +

      +http_status_t cupsStartDestDocument (
      +    http_t *http,
      +    cups_dest_t *dest,
      +    cups_dinfo_t *info,
      +    int job_id,
      +    const char *docname,
      +    const char *format,
      +    int num_options,
      +    cups_option_t *options,
      +    int last_document
      +);

      +

      Parameters

      +
      +
      http
      +
      Connection to destination
      +
      dest
      +
      Destination
      +
      info
      +
      Destination information
      +
      job_id
      +
      Job ID
      +
      docname
      +
      Document name
      +
      format
      +
      Document format
      +
      num_options
      +
      Number of document options
      +
      options
      +
      Document options
      +
      last_document
      +
      1 if this is the last document
      +
      +

      Return Value

      +

      Status of document creation

      +

      Discussion

      +

      "job_id" is the job ID returned by cupsCreateDestJob. "docname" is the name +of the document/file being printed, "format" is the MIME media type for the +document (see CUPS_FORMAT_xxx constants), and "num_options" and "options" +are the options do be applied to the document. "last_document" should be 1 +if this is the last document to be submitted in the job. Returns +HTTP_CONTINUE on success. + +

       CUPS 1.4/OS X 10.6 cupsStartDocument

      Add a document to a job created with cupsCreateJob().

      diff --git a/doc/help/api-httpipp.html b/doc/help/api-httpipp.html index 33e1672af..b30af9eb8 100644 --- a/doc/help/api-httpipp.html +++ b/doc/help/api-httpipp.html @@ -395,8 +395,10 @@ div.contents ul.subcontents li {

    • cupsGetFd
    • cupsGetFile
    • cupsGetResponse
    • -
    • cupsLastError
    • -
    • cupsLastErrorString
    • +
    • cupsLastError
    • +
    • cupsLastErrorString
    • cupsPutFd
    • cupsPutFile
    • cupsReadResponseData
    • @@ -1010,9 +1012,9 @@ status, prior to resubmitting your request.

      Return Value

      Response data

      Discussion

      -

      This function sends the IPP request to the specified server, retrying -and authenticating as necessary. The request is freed with ippDelete -after receiving a valid IPP response.

      +

      This function sends the IPP request and attached file to the specified +server, retrying and authenticating as necessary. The request is freed with +ippDelete.

       CUPS 1.3/OS X 10.5 cupsDoIORequest

      Do an IPP request with file descriptors.

      @@ -1039,14 +1041,14 @@ after receiving a valid IPP response.

      Return Value

      Response data

      Discussion

      -

      This function sends the IPP request to the specified server, retrying -and authenticating as necessary. The request is freed with ippDelete() -after receiving a valid IPP response.
      +

      This function sends the IPP request with the optional input file "infile" to +the specified server, retrying and authenticating as necessary. The request +is freed with ippDelete.

      -If "infile" is a valid file descriptor, cupsDoIORequest() copies +If "infile" is a valid file descriptor, cupsDoIORequest copies all of the data from the file after the IPP request message.

      -If "outfile" is a valid file descriptor, cupsDoIORequest() copies +If "outfile" is a valid file descriptor, cupsDoIORequest copies all of the data after the IPP response message to the file.

      @@ -1071,8 +1073,7 @@ all of the data after the IPP response message to the file.

      Response data

      Discussion

      This function sends the IPP request to the specified server, retrying -and authenticating as necessary. The request is freed with ippDelete() -after receiving a valid IPP response.

      +and authenticating as necessary. The request is freed with ippDelete.

      cupsEncodeOptions

      Encode printer options into IPP attributes.

      @@ -1220,19 +1221,21 @@ the request respectively.

      Response or NULL on HTTP error

      Discussion

      Use this function to get the response for an IPP request sent using -cupsSendDocument() or cupsSendRequest(). For requests that return -additional data, use httpRead() after getting a successful response, -otherwise call httpFlush() to complete the response processing. +cupsSendRequest. For requests that return additional data, use +cupsReadResponseData after getting a successful response, +otherwise call httpFlush to complete the response processing.

      cupsLastError

      -

      Return the last IPP status code.

      +

      Return the last IPP status code received on the current +thread.

      ipp_status_t cupsLastError (void);

      Return Value

      IPP status code from last request

       CUPS 1.2/OS X 10.5 cupsLastErrorString

      -

      Return the last IPP status-message.

      +

      Return the last IPP status-message received on the +current thread.

      const char *cupsLastErrorString (void);

      Return Value

      @@ -1305,8 +1308,9 @@ ssize_t cupsReadResponseData (

      Return Value

      Bytes read, 0 on EOF, -1 on error

      Discussion

      -

      This function is used after cupsGetResponse() to read the PPD or document -files for CUPS_GET_PPD and CUPS_GET_DOCUMENT requests, respectively. +

      This function is used after cupsGetResponse to read the PPD or document +files from CUPS_GET_PPD and CUPS_GET_DOCUMENT requests, +respectively.

       CUPS 1.4/OS X 10.6 cupsSendRequest

      @@ -1332,13 +1336,17 @@ files for CUPS_GET_PPD and CUPS_GET_DOCUMENT requests, respectively.

      Return Value

      Initial HTTP status

      Discussion

      -

      Use httpWrite() to write any additional data (document, PPD file, etc.) -for the request, cupsGetResponse() to get the IPP response, and httpRead() -to read any additional data following the response. Only one request can be -sent/queued at a time.
      +

      Use cupsWriteRequestData to write any additional data (document, PPD +file, etc.) for the request, cupsGetResponse to get the IPP response, +and cupsReadResponseData to read any additional data following the +response. Only one request can be sent/queued at a time per http_t +connection.
      +
      +Returns the initial HTTP status code, which will be HTTP_CONTINUE +on a successful send of the request.

      -Unlike cupsDoFileRequest(), cupsDoIORequest(), and cupsDoRequest(), the -request is not freed. +Note: Unlike cupsDoFileRequest, cupsDoIORequest, and +cupsDoRequest, the request is NOT freed with ippDelete.

       CUPS 1.4/OS X 10.6 cupsWriteRequestData

      diff --git a/doc/help/network.html b/doc/help/network.html index 6743651f7..ebe1b5f94 100644 --- a/doc/help/network.html +++ b/doc/help/network.html @@ -93,16 +93,22 @@ page on the device.

       socket://ip-address-or-hostname
      -socket://ip-address-or-hostname/?waiteof=false
      +socket://ip-address-or-hostname/?option=value
      +socket://ip-address-or-hostname/?option=value&option=value
       socket://ip-address-or-hostname:port-number
      -socket://ip-address-or-hostname:port-number/?waiteof=false
      +socket://ip-address-or-hostname:port-number/?option=value
      +socket://ip-address-or-hostname:port-number/?option=value&option=value
       
      +

      The "contimeout" option controls the number of seconds that the backend will wait to obtain a connection to the printer. The default is 1 week.

      + +

      The "snmp" option controls whether the socket backend queries for supply and page count information via SNMP.

      +

      The "waiteof" option controls whether the socket backend waits for the printer to complete the printing of the job. The default is to wait.

      Internet Printing Protocol (IPP)

      -

      IPP is the only protocol that CUPS supports natively and is supported by some network printers and print servers. However, since many printers do not implement IPP properly, only use IPP when the vendor actually documents official support for it. IPP printing normally happens over port 631 and uses the http and ipp URI schemes:

      +

      IPP is the only protocol that CUPS supports natively and is supported by some network printers and print servers. However, since many printers do not implement IPP properly, only use IPP when the vendor actually documents official support for it. IPP printing normally happens over port 631 and uses the http, ipp, and ipps URI schemes:

       http://ip-address-or-hostname:port-number/resource
      @@ -114,6 +120,12 @@ ipp://ip-address-or-hostname/resource?option=value&option=value
       ipp://ip-address-or-hostname:port-number/resource
       ipp://ip-address-or-hostname:port-number/resource?option=value
       ipp://ip-address-or-hostname:port-number/resource?option=value&option=value
      +ipps://ip-address-or-hostname/resource
      +ipps://ip-address-or-hostname/resource?option=value
      +ipps://ip-address-or-hostname/resource?option=value&option=value
      +ipps://ip-address-or-hostname:port-number/resource
      +ipps://ip-address-or-hostname:port-number/resource?option=value
      +ipps://ip-address-or-hostname:port-number/resource?option=value&option=value
       

      The ipp backend supports many options, which are summarized in Table 2.

      @@ -147,17 +159,21 @@ ipp://ip-address-or-hostname:port-number/resource?option encryption=required Specifies that the connection to the IPP server should be encrypted using TLS. + + snmp=false + Specifies that SNMP supply and page count queries should not be performed. + version=1.0 - Specifies that version 1.0 of the IPP protocol should be used instead of the default version 1.1. + Specifies that version 1.0 of the IPP protocol should be used instead of the default version 2.0. - version=2.0 - Specifies that version 2.0 of the IPP protocol should be used instead of the default version 1.1. + version=1.1 + Specifies that version 1.1 of the IPP protocol should be used instead of the default version 2.0. version=2.1 - Specifies that version 2.1 of the IPP protocol should be used instead of the default version 1.1. + Specifies that version 2.1 of the IPP protocol should be used instead of the default version 2.0. waitjob=false @@ -266,6 +282,10 @@ lpd://username@ip-address-or-hostname/queue?option=value&option sanitize_title=yes Specifies that the job title string should be restricted to ASCII characters. + + snmp=false + Specifies that SNMP supply and page count queries should not be performed. + timeout=seconds Specifies the number of seconds to wait for LPD commands to complete. diff --git a/doc/help/spec-ppd.html b/doc/help/spec-ppd.html index ec0a03091..8fd539a1b 100644 --- a/doc/help/spec-ppd.html +++ b/doc/help/spec-ppd.html @@ -410,7 +410,11 @@ div.contents ul.subcontents li {
    • cupsIPPFinishings
    • cupsIPPReason
    • cupsIPPSupplies
    • +
    • cupsJobAccountId
    • +
    • cupsJobAccountingUserId
    • +
    • cupsJobPassword
    • cupsLanguages
    • +
    • cupsMandatory
    • cupsManualCopies
    • cupsMarkerName
    • cupsMarkerNotice
    • @@ -1706,6 +1710,49 @@ http://www.vendor.com/help" *cupsIPPSupplies: False + +

      CUPS 1.7cupsJobAccountId

      + +

      *cupsJobAccountId: boolean

      + +

      This keyword defines whether the printer accepts the job-account-id IPP attribute.

      + +

      Example:

      + +
      +*% Specify the printer accepts the job-account-id IPP attribute.
      +*cupsJobAccountId: True
      +
      + + +

      CUPS 1.7cupsJobAccountingUserId

      + +

      *cupsJobAccountingUserId: boolean

      + +

      This keyword defines whether the printer accepts the job-accounting-user-id IPP attribute.

      + +

      Example:

      + +
      +*% Specify the printer accepts the job-accounting-user-id IPP attribute.
      +*cupsJobAccountingUserId: True
      +
      + + +

      CUPS 1.7cupsJobPassword

      + +

      *cupsJobPassword: "format"

      + +

      This keyword defines the format of the job-password IPP attribute, if supported by the printer. Currently the only supported format is "1111" indicating a 4-digit PIN code.

      + +

      Example:

      + +
      +*% Specify the printer supports 4-digit PIN codes.
      +*cupsJobPassword: "1111"
      +
      + +

      CUPS 1.2/OS X 10.5cupsLanguages

      *cupsLanguages: "locale list"

      @@ -1721,6 +1768,21 @@ list of locale names ("en", "en_US", "fr_CA", etc.)

      *cupsLanguages: "en_CA en_UK en_US fr_CA fr_FR" + +

      CUPS 1.7cupsMandatory

      + +

      *cupsMandatory: "attribute1 attribute2 ... attributeN"

      + +

      This keyword defines a list of IPP attributes that must be provided when submitting a print job creation request.

      + +

      Example:

      + +
      +*% Specify that the user must supply a job-password
      +*cupsMandatory: "job-password job-password-encryption"
      +
      + +

      cupsManualCopies

      *cupsManualCopies: boolean

      @@ -2249,6 +2311,18 @@ the device.

      Change History

      +

      Changes in CUPS 1.7

      + + + +

      Changes in CUPS 1.6

        diff --git a/filter/interpret.c b/filter/interpret.c index 7723f6569..70d083c63 100644 --- a/filter/interpret.c +++ b/filter/interpret.c @@ -200,7 +200,7 @@ cupsRasterInterpretPPD( h->cupsImagingBBox[2] = 612.0f; h->cupsImagingBBox[3] = 792.0f; - strcpy(h->cupsPageSizeName, "Letter"); + strlcpy(h->cupsPageSizeName, "Letter", sizeof(h->cupsPageSizeName)); #ifdef __APPLE__ /* diff --git a/filter/raster.c b/filter/raster.c index 14980f4a8..1ecd90dea 100644 --- a/filter/raster.c +++ b/filter/raster.c @@ -46,6 +46,9 @@ */ #include +#ifdef HAVE_STDINT_H +# include +#endif /* HAVE_STDINT_H */ /* diff --git a/filter/spec-ppd.shtml b/filter/spec-ppd.shtml index 0f54d3785..38a246288 100644 --- a/filter/spec-ppd.shtml +++ b/filter/spec-ppd.shtml @@ -1264,6 +1264,49 @@ http://www.vendor.com/help" *cupsIPPSupplies: False + +

        CUPS 1.7cupsJobAccountId

        + +

        *cupsJobAccountId: boolean

        + +

        This keyword defines whether the printer accepts the job-account-id IPP attribute.

        + +

        Example:

        + +
        +*% Specify the printer accepts the job-account-id IPP attribute.
        +*cupsJobAccountId: True
        +
        + + +

        CUPS 1.7cupsJobAccountingUserId

        + +

        *cupsJobAccountingUserId: boolean

        + +

        This keyword defines whether the printer accepts the job-accounting-user-id IPP attribute.

        + +

        Example:

        + +
        +*% Specify the printer accepts the job-accounting-user-id IPP attribute.
        +*cupsJobAccountingUserId: True
        +
        + + +

        CUPS 1.7cupsJobPassword

        + +

        *cupsJobPassword: "format"

        + +

        This keyword defines the format of the job-password IPP attribute, if supported by the printer. Currently the only supported format is "1111" indicating a 4-digit PIN code.

        + +

        Example:

        + +
        +*% Specify the printer supports 4-digit PIN codes.
        +*cupsJobPassword: "1111"
        +
        + +

        CUPS 1.2/OS X 10.5cupsLanguages

        *cupsLanguages: "locale list"

        @@ -1279,6 +1322,21 @@ list of locale names ("en", "en_US", "fr_CA", etc.)

        *cupsLanguages: "en_CA en_UK en_US fr_CA fr_FR" + +

        CUPS 1.7cupsMandatory

        + +

        *cupsMandatory: "attribute1 attribute2 ... attributeN"

        + +

        This keyword defines a list of IPP attributes that must be provided when submitting a print job creation request.

        + +

        Example:

        + +
        +*% Specify that the user must supply a job-password
        +*cupsMandatory: "job-password job-password-encryption"
        +
        + +

        cupsManualCopies

        *cupsManualCopies: boolean

        @@ -1807,6 +1865,18 @@ the device.

        Change History

        +

        Changes in CUPS 1.7

        + + + +

        Changes in CUPS 1.6

          diff --git a/locale/checkpo.c b/locale/checkpo.c index 73cad3ca5..eec10c4eb 100644 --- a/locale/checkpo.c +++ b/locale/checkpo.c @@ -4,7 +4,7 @@ * Verify that translations in the .po file have the same number and type of * printf-style format strings. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -338,7 +338,7 @@ abbreviate(const char *s, /* I - String to abbreviate */ } if (*s) - strcpy(bufptr, "..."); + memcpy(bufptr, "...", 4); else *bufptr = '\0'; diff --git a/locale/po2strings.c b/locale/po2strings.c index 0b7d1f32f..75335bab0 100644 --- a/locale/po2strings.c +++ b/locale/po2strings.c @@ -213,10 +213,12 @@ main(int argc, /* I - Number of command-line args */ * Append to current string... */ + size_t ptrlen = strlen(ptr); /* Length of string */ + length = (int)strlen(msgstr ? msgstr : msgid); if ((temp = realloc(msgstr ? msgstr : msgid, - length + strlen(ptr) + 1)) == NULL) + length + ptrlen + 1)) == NULL) { free(msgid); if (msgstr) @@ -235,7 +237,7 @@ main(int argc, /* I - Number of command-line args */ msgstr = temp; - strcpy(msgstr + length, ptr); + memcpy(msgstr + length, ptr, ptrlen + 1); } else { @@ -247,7 +249,7 @@ main(int argc, /* I - Number of command-line args */ msgid = temp; - strcpy(msgid + length, ptr); + memcpy(msgid + length, ptr, ptrlen + 1); } } else if (!strncmp(s, "msgstr", 6) && msgid) diff --git a/notifier/dbus.c b/notifier/dbus.c index 890b2ae09..1629c4e7f 100644 --- a/notifier/dbus.c +++ b/notifier/dbus.c @@ -3,7 +3,7 @@ * * D-Bus notifier for CUPS. * - * Copyright 2008-2011 by Apple Inc. + * Copyright 2008-2012 by Apple Inc. * Copyright (C) 2011 Red Hat, Inc. * Copyright (C) 2007 Tim Waugh * Copyright 1997-2005 by Easy Software Products. @@ -445,7 +445,8 @@ main(int argc, /* I - Number of command-line args */ if (i) *p++ = ','; - strcpy(p, ippGetString(attr, i, NULL)); + strlcpy(p, ippGetString(attr, i, NULL), + reasons_length - (p - printer_reasons)); p += strlen(p); } if (!dbus_message_iter_append_string(&iter, &printer_reasons)) @@ -517,7 +518,8 @@ main(int argc, /* I - Number of command-line args */ if (i) *p++ = ','; - strcpy(p, ippGetString(attr, i, NULL)); + strlcpy(p, ippGetString(attr, i, NULL), + reasons_length - (p - job_reasons)); p += strlen(p); } if (!dbus_message_iter_append_string(&iter, &job_reasons)) diff --git a/ppdc/ppdc-source.cxx b/ppdc/ppdc-source.cxx index 78e97adc8..9560daa49 100644 --- a/ppdc/ppdc-source.cxx +++ b/ppdc/ppdc-source.cxx @@ -943,7 +943,7 @@ ppdcSource::get_filter(ppdcFile *fp) // I - File to read while (isspace(*ptr)) ptr ++; - strcpy(program, ptr); + strlcpy(program, ptr, sizeof(program)); } else { @@ -1706,7 +1706,7 @@ ppdcSource::get_po(ppdcFile *fp) // I - File to read if ((baseptr = strrchr(basedir, '/')) != NULL) *baseptr = '\0'; else - strcpy(basedir, "."); + strlcpy(basedir, ".", sizeof(basedir)); // Find the po file... pofilename[0] = '\0'; @@ -2630,7 +2630,7 @@ ppdcSource::scan_file(ppdcFile *fp, // I - File to read if ((baseptr = strrchr(basedir, '/')) != NULL) *baseptr = '\0'; else - strcpy(basedir, "."); + strlcpy(basedir, ".", sizeof(basedir)); // Find the include file... if (find_include(inctemp, basedir, incname, sizeof(incname))) diff --git a/ppdc/ppdc-string.cxx b/ppdc/ppdc-string.cxx index caf8f8015..706bd138c 100644 --- a/ppdc/ppdc-string.cxx +++ b/ppdc/ppdc-string.cxx @@ -3,7 +3,7 @@ // // Shared string class for the CUPS PPD Compiler. // -// Copyright 2007-2009 by Apple Inc. +// Copyright 2007-2012 by Apple Inc. // Copyright 2002-2005 by Easy Software Products. // // These coded instructions, statements, and computer programs are the @@ -36,8 +36,10 @@ ppdcString::ppdcString(const char *v) // I - String if (v) { - value = new char[strlen(v) + 1]; - strcpy(value, v); + size_t vlen = strlen(v); + + value = new char[vlen + 1]; + memcpy(value, v, vlen + 1); } else value = 0; diff --git a/scheduler/auth.c b/scheduler/auth.c index 00b5960f8..8aff4f21e 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -89,7 +89,11 @@ extern const char *cssmErrorString(int error); typedef struct xucred cupsd_ucred_t; # define CUPSD_UCRED_UID(c) (c).cr_uid #else +# ifndef __OpenBSD__ typedef struct ucred cupsd_ucred_t; +# else +typedef struct sockpeercred cupsd_ucred_t; +# endif # define CUPSD_UCRED_UID(c) (c).uid #endif /* HAVE_SYS_UCRED_H */ #ifdef HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID @@ -1173,7 +1177,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (sscanf(authorization, "%255s", scheme) != 1) - strcpy(scheme, "UNKNOWN"); + strlcpy(scheme, "UNKNOWN", sizeof(scheme)); cupsdLogMessage(CUPSD_LOG_ERROR, "[Client %d] Bad authentication data \"%s ...\"", diff --git a/scheduler/client.c b/scheduler/client.c index 18d45ade9..d4d6ac8b4 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -392,13 +392,13 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */ cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get local address - %s", strerror(errno)); - strcpy(con->servername, "localhost"); + strlcpy(con->servername, "localhost", sizeof(con->servername)); con->serverport = LocalPort; } #ifdef AF_LOCAL else if (_httpAddrFamily(&temp) == AF_LOCAL) { - strcpy(con->servername, "localhost"); + strlcpy(con->servername, "localhost", sizeof(con->servername)); con->serverport = LocalPort; } #endif /* AF_LOCAL */ @@ -912,7 +912,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ * con->uri are HTTP_MAX_URI bytes in size... */ - strcpy(con->uri, resource); + strlcpy(con->uri, resource, sizeof(con->uri)); } /* @@ -1489,7 +1489,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ else { if (type == NULL) - strcpy(line, "text/plain"); + strlcpy(line, "text/plain", sizeof(line)); else snprintf(line, sizeof(line), "%s/%s", type->super, type->type); @@ -1914,7 +1914,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ type = mimeFileType(MimeDatabase, filename, NULL, NULL); if (type == NULL) - strcpy(line, "text/plain"); + strlcpy(line, "text/plain", sizeof(line)); else snprintf(line, sizeof(line), "%s/%s", type->super, type->type); @@ -3776,7 +3776,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ * the POSIX locale... */ - strcpy(lang, "LANG=C"); + strlcpy(lang, "LANG=C", sizeof(lang)); break; case 2 : @@ -3804,9 +3804,9 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ else if (con->language) snprintf(lang, sizeof(lang), "LANG=%s.UTF8", con->language->language); else - strcpy(lang, "LANG=C"); + strlcpy(lang, "LANG=C", sizeof(lang)); - strcpy(remote_addr, "REMOTE_ADDR="); + strlcpy(remote_addr, "REMOTE_ADDR=", sizeof(remote_addr)); httpAddrString(con->http.hostaddr, remote_addr + 12, sizeof(remote_addr) - 12); diff --git a/scheduler/conf.c b/scheduler/conf.c index 0dad19a5e..b750db389 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -227,7 +227,7 @@ cupsdAddAlias(cups_array_t *aliases, /* I - Array of aliases */ return; a->namelen = namelen; - strcpy(a->name, name); /* OK since a->name is allocated */ + memcpy(a->name, name, namelen + 1); /* OK since a->name is allocated */ cupsArrayAdd(aliases, a); } diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx index 1a270b372..31a8a25a0 100644 --- a/scheduler/cups-driverd.cxx +++ b/scheduler/cups-driverd.cxx @@ -1877,7 +1877,7 @@ load_drivers(cups_array_t *include, /* I - Drivers to include */ device_id[0] = '\0'; product[0] = '\0'; psversion[0] = '\0'; - strcpy(type_str, "postscript"); + strlcpy(type_str, "postscript", sizeof(type_str)); if (sscanf(line, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\"" "%*[ \t]\"%127[^\"]\"%*[ \t]\"%255[^\"]\"" @@ -2043,7 +2043,7 @@ load_ppd(const char *filename, /* I - Real filename */ manufacturer[0] = '\0'; device_id[0] = '\0'; lang_encoding[0] = '\0'; - strcpy(lang_version, "en"); + strlcpy(lang_version, "en", sizeof(lang_version)); model_number = 0; install_group = 0; type = PPD_TYPE_POSTSCRIPT; @@ -2166,7 +2166,7 @@ load_ppd(const char *filename, /* I - Real filename */ cupsCharsetToUTF8((cups_utf8_t *)make_model, nick_name, sizeof(make_model), _ppdGetEncoding(lang_encoding)); else - strcpy(make_model, model_name); + strlcpy(make_model, model_name, sizeof(make_model)); while (isspace(make_model[0] & 255)) _cups_strcpy(make_model, make_model + 1); @@ -2236,13 +2236,13 @@ load_ppd(const char *filename, /* I - Real filename */ if (*ptr && ptr > manufacturer) *ptr = '\0'; else - strcpy(manufacturer, "Other"); + strlcpy(manufacturer, "Other", sizeof(manufacturer)); } else if (!_cups_strncasecmp(manufacturer, "LHAG", 4) || !_cups_strncasecmp(manufacturer, "linotype", 8)) - strcpy(manufacturer, "LHAG"); + strlcpy(manufacturer, "LHAG", sizeof(manufacturer)); else if (!_cups_strncasecmp(manufacturer, "Hewlett", 7)) - strcpy(manufacturer, "HP"); + strlcpy(manufacturer, "HP", sizeof(manufacturer)); /* * Fix the lang_version as needed... @@ -2290,7 +2290,7 @@ load_ppd(const char *filename, /* I - Real filename */ * Unknown language; use "xx"... */ - strcpy(lang_version, "xx"); + strlcpy(lang_version, "xx", sizeof(lang_version)); } /* @@ -2519,8 +2519,8 @@ load_ppds(const char *d, /* I - Actual directory */ * See if this file has been scanned before... */ - strcpy(key.record.filename, name); - strcpy(key.record.name, name); + strlcpy(key.record.filename, name, sizeof(key.record.filename)); + strlcpy(key.record.name, name, sizeof(key.record.name)); ppd = (ppd_info_t *)cupsArrayFind(PPDsByName, &key); diff --git a/scheduler/cups-lpd.c b/scheduler/cups-lpd.c index 11bcd4df4..15b855072 100644 --- a/scheduler/cups-lpd.c +++ b/scheduler/cups-lpd.c @@ -184,7 +184,7 @@ main(int argc, /* I - Number of command-line arguments */ if (getpeername(0, (struct sockaddr *)&hostaddr, &hostlen)) { syslog(LOG_WARNING, "Unable to get client address - %s", strerror(errno)); - strcpy(hostname, "unknown"); + strlcpy(hostname, "unknown", sizeof(hostname)); } else { @@ -914,7 +914,7 @@ recv_print_job( break; } - strcpy(filename, control); + strlcpy(filename, control, sizeof(filename)); } break; @@ -950,7 +950,7 @@ recv_print_job( break; } - strcpy(filename, temp[num_data]); + strlcpy(filename, temp[num_data], sizeof(filename)); num_data ++; break; @@ -1116,7 +1116,7 @@ recv_print_job( { syslog(LOG_WARNING, "No username specified by client! " "Using \"anonymous\"..."); - strcpy(user, "anonymous"); + strlcpy(user, "anonymous", sizeof(user)); } /* @@ -1528,7 +1528,7 @@ send_state(const char *queue, /* I - Destination */ */ if (jobstate == IPP_JOB_PROCESSING) - strcpy(rankstr, "active"); + strlcpy(rankstr, "active", sizeof(rankstr)); else { snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]); diff --git a/scheduler/cupsfilter.c b/scheduler/cupsfilter.c index 11997e0a2..60f522c28 100644 --- a/scheduler/cupsfilter.c +++ b/scheduler/cupsfilter.c @@ -771,7 +771,7 @@ escape_options( if (sptr > s) *sptr++ = ' '; - strcpy(sptr, option->name); + strlcpy(sptr, option->name, bytes - (sptr - s)); sptr += strlen(sptr); *sptr++ = '='; diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index af9099809..0e5e3e695 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -234,9 +234,12 @@ cupsdStartBrowsing(void) if (FatalErrors & CUPSD_FATAL_BROWSE) cupsdEndProcess(getpid(), 0); - } - avahi_threaded_poll_start(DNSSDMaster); + avahi_threaded_poll_free(DNSSDMaster); + DNSSDMaster = NULL; + } + else + avahi_threaded_poll_start(DNSSDMaster); } # endif /* HAVE_DNSSD */ @@ -457,14 +460,26 @@ cupsdUpdateDNSSDName(void) # endif /* __APPLE__ */ # ifdef HAVE_AVAHI { - cupsdSetString(&DNSSDComputerName, avahi_client_get_host_name(DNSSDClient)); - cupsdSetString(&DNSSDHostName, - avahi_client_get_host_name_fqdn(DNSSDClient)); + const char *host_name = avahi_client_get_host_name(DNSSDClient); + const char *host_fqdn = avahi_client_get_host_name_fqdn(DNSSDClient); + + cupsdSetString(&DNSSDComputerName, host_name ? host_name : ServerName); + + if (host_fqdn) + cupsdSetString(&DNSSDHostName, host_fqdn); + else if (strchr(ServerName, '.')) + cupsdSetString(&DNSSDHostName, ServerName); + else + cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); } # else /* HAVE_DNSSD */ { cupsdSetString(&DNSSDComputerName, ServerName); - cupsdSetString(&DNSSDHostName, ServerName); + + if (strchr(ServerName, '.')) + cupsdSetString(&DNSSDHostName, ServerName); + else + cupsdSetStringf(&DNSSDHostName, "%s.local", ServerName); } # endif /* HAVE_AVAHI */ diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 4da385b41..e52c28462 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -1274,6 +1274,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ http_status_t status; /* Policy status */ ipp_attribute_t *attr, /* Current attribute */ *auth_info; /* auth-info attribute */ + const char *mandatory; /* Current mandatory job attribute */ const char *val; /* Default option value */ int priority; /* Job priority */ cupsd_job_t *job; /* Current job */ @@ -1285,6 +1286,21 @@ add_job(cupsd_client_t *con, /* I - Client connection */ ipp_attribute_t *media_col, /* media-col attribute */ *media_margin; /* media-*-margin attribute */ ipp_t *unsup_col; /* media-col in unsupported response */ + static const char * const readonly[] =/* List of read-only attributes */ + { + "job-id", + "job-k-octets", + /*"job-impressions",*/ /* For now we allow this since cupsd can't count */ + "job-impressions-completed", + "job-media-sheets", + "job-media-sheets-completed", + "job-state", + "job-state-message", + "job-state-reasons", + "time-at-completed", + "time-at-creation", + "time-at-processing" + }; cupsdLogMessage(CUPSD_LOG_DEBUG2, "add_job(%p[%d], %p(%s), %p(%s/%s))", @@ -1350,9 +1366,51 @@ add_job(cupsd_client_t *con, /* I - Client connection */ /* * Validate job template attributes; for now just document-format, - * copies, number-up, and page-ranges... + * copies, job-sheets, number-up, page-ranges, mandatory attributes, and + * media... */ + for (i = 0; i < (int)(sizeof(readonly) / sizeof(readonly[0])); i ++) + { + if ((attr = ippFindAttribute(con->request, readonly[i], + IPP_TAG_ZERO)) != NULL) + { + ippDeleteAttribute(con->request, attr); + + if (StrictConformance) + { + send_ipp_status(con, IPP_BAD_REQUEST, + _("The '%s' Job Description attribute cannot be " + "supplied in a job creation request."), readonly[i]); + return (NULL); + } + + cupsdLogMessage(CUPSD_LOG_WARN, + "Unexpected '%s' Job Description attribute in a job " + "creation request.", readonly[i]); + } + } + + if (printer->pc) + { + for (mandatory = (char *)cupsArrayFirst(printer->pc->mandatory); + mandatory; + mandatory = (char *)cupsArrayNext(printer->pc->mandatory)) + { + if (!ippFindAttribute(con->request, mandatory, IPP_TAG_ZERO)) + { + /* + * Missing a required attribute... + */ + + send_ipp_status(con, IPP_CONFLICT, + _("The \"%s\" attribute is required for print jobs."), + mandatory); + return (NULL); + } + } + } + if (filetype && printer->filetypes && !cupsArrayFind(printer->filetypes, filetype)) { @@ -8248,8 +8306,8 @@ print_job(cupsd_client_t *con, /* I - Client connection */ * Auto-type it! */ - strcpy(super, "application"); - strcpy(type, "octet-stream"); + strlcpy(super, "application", sizeof(super)); + strlcpy(type, "octet-stream", sizeof(type)); } if (!strcmp(super, "application") && !strcmp(type, "octet-stream")) @@ -8617,7 +8675,8 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */ if ((attr = ippFindAttribute(con->request, "printer-state-message", IPP_TAG_TEXT)) == NULL) - strcpy(printer->state_message, "Rejecting Jobs"); + strlcpy(printer->state_message, "Rejecting Jobs", + sizeof(printer->state_message)); else strlcpy(printer->state_message, attr->values[0].string.text, sizeof(printer->state_message)); @@ -9477,8 +9536,8 @@ send_document(cupsd_client_t *con, /* I - Client connection */ * No document format attribute? Auto-type it! */ - strcpy(super, "application"); - strcpy(type, "octet-stream"); + strlcpy(super, "application", sizeof(super)); + strlcpy(type, "octet-stream", sizeof(type)); } if (!strcmp(super, "application") && !strcmp(type, "octet-stream")) @@ -10531,6 +10590,7 @@ set_printer_defaults( break; case IPP_TAG_NAME : + case IPP_TAG_TEXT : case IPP_TAG_KEYWORD : case IPP_TAG_URI : printer->num_options = cupsAddOption(name, @@ -10723,7 +10783,7 @@ stop_printer(cupsd_client_t *con, /* I - Client connection */ if ((attr = ippFindAttribute(con->request, "printer-state-message", IPP_TAG_TEXT)) == NULL) - strcpy(printer->state_message, "Paused"); + strlcpy(printer->state_message, "Paused", sizeof(printer->state_message)); else { strlcpy(printer->state_message, attr->values[0].string.text, @@ -10920,7 +10980,8 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ http_status_t status; /* Policy status */ ipp_attribute_t *attr, /* Current attribute */ *auth_info; /* auth-info attribute */ - ipp_attribute_t *format; /* Document-format attribute */ + ipp_attribute_t *format, /* Document-format attribute */ + *name; /* Job-name attribute */ cups_ptype_t dtype; /* Destination type (printer/class) */ char super[MIME_MAX_SUPER], /* Supertype of file */ @@ -10947,7 +11008,7 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ ) { send_ipp_status(con, IPP_ATTRIBUTES, - _("Unsupported compression \"%s\"."), + _("Unsupported 'compression' value \"%s\"."), attr->values[0].string.text); ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD, "compression", NULL, attr->values[0].string.text); @@ -10965,7 +11026,8 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ if (sscanf(format->values[0].string.text, "%15[^/]/%31[^;]", super, type) != 2) { - send_ipp_status(con, IPP_BAD_REQUEST, _("Bad document-format \"%s\"."), + send_ipp_status(con, IPP_BAD_REQUEST, + _("Bad 'document-format' value \"%s\"."), format->values[0].string.text); return; } @@ -10976,7 +11038,7 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_INFO, "Hint: Do you have the raw file printing rules enabled?"); send_ipp_status(con, IPP_DOCUMENT_FORMAT, - _("Unsupported document-format \"%s\"."), + _("Unsupported 'document-format' value \"%s\"."), format->values[0].string.text); ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE, "document-format", NULL, format->values[0].string.text); @@ -10984,6 +11046,86 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ } } + /* + * Is the job-name valid? + */ + + if ((name = ippFindAttribute(con->request, "job-name", IPP_TAG_ZERO)) != NULL) + { + int bad_name = 0; /* Is the job-name value bad? */ + + if ((name->value_tag != IPP_TAG_NAME && name->value_tag != IPP_TAG_NAMELANG) || + name->num_values != 1) + { + bad_name = 1; + } + else + { + /* + * Validate that job-name conforms to RFC 5198 (Network Unicode) and + * IPP Everywhere requirements for "name" values... + */ + + const unsigned char *nameptr; /* Pointer into "job-name" attribute */ + + for (nameptr = (unsigned char *)name->values[0].string.text; + *nameptr; + nameptr ++) + { + if (*nameptr < ' ' && *nameptr != '\t') + break; + else if (*nameptr == 0x7f) + break; + else if ((*nameptr & 0xe0) == 0xc0) + { + if ((nameptr[1] & 0xc0) != 0x80) + break; + + nameptr ++; + } + else if ((*nameptr & 0xf0) == 0xe0) + { + if ((nameptr[1] & 0xc0) != 0x80 || + (nameptr[2] & 0xc0) != 0x80) + break; + + nameptr += 2; + } + else if ((*nameptr & 0xf8) == 0xf0) + { + if ((nameptr[1] & 0xc0) != 0x80 || + (nameptr[2] & 0xc0) != 0x80 || + (nameptr[3] & 0xc0) != 0x80) + break; + + nameptr += 3; + } + else if (*nameptr & 0x80) + break; + } + + if (*nameptr) + bad_name = 1; + } + + if (bad_name) + { + if (StrictConformance) + { + send_ipp_status(con, IPP_ATTRIBUTES, + _("Unsupported 'job-name' value.")); + ippCopyAttribute(con->response, name, 0); + return; + } + else + { + cupsdLogMessage(CUPSD_LOG_WARN, + "Unsupported 'job-name' value, deleting from request."); + ippDeleteAttribute(con->request, name); + } + } + } + /* * Is the destination valid? */ diff --git a/scheduler/job.c b/scheduler/job.c index 9390e472e..2f5002fb7 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -903,7 +903,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ IPP_TAG_LANGUAGE); #ifdef __APPLE__ - strcpy(apple_language, "APPLE_LANGUAGE="); + strlcpy(apple_language, "APPLE_LANGUAGE=", sizeof(apple_language)); _cupsAppleLanguage(attr->values[0].string.text, apple_language + 15, sizeof(apple_language) - 15); #endif /* __APPLE__ */ @@ -916,7 +916,7 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ * the POSIX locale... */ - strcpy(lang, "LANG=C"); + strlcpy(lang, "LANG=C", sizeof(lang)); break; case 2 : @@ -974,14 +974,15 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ * All of these strcpy's are safe because we allocated the psr string... */ - strcpy(printer_state_reasons, "PRINTER_STATE_REASONS="); + strlcpy(printer_state_reasons, "PRINTER_STATE_REASONS=", psrlen); for (psrptr = printer_state_reasons + 22, i = 0; i < job->printer->num_reasons; i ++) { if (i) *psrptr++ = ','; - strcpy(psrptr, job->printer->reasons[i]); + strlcpy(psrptr, job->printer->reasons[i], + psrlen - (psrptr - printer_state_reasons)); psrptr += strlen(psrptr); } } @@ -3441,19 +3442,16 @@ get_options(cupsd_job_t *job, /* I - Job */ "com.apple.print.DocumentTicket.PMSpoolFormat", IPP_TAG_ZERO) && !ippFindAttribute(job->attrs, "APPrinterPreset", IPP_TAG_ZERO) && - (ippFindAttribute(job->attrs, "output-mode", IPP_TAG_ZERO) || - ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_ZERO) || + (ippFindAttribute(job->attrs, "print-color-mode", IPP_TAG_ZERO) || ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ZERO))) { /* - * Map output-mode and print-quality to a preset... + * Map print-color-mode and print-quality to a preset... */ if ((attr = ippFindAttribute(job->attrs, "print-color-mode", - IPP_TAG_KEYWORD)) == NULL) - attr = ippFindAttribute(job->attrs, "output-mode", IPP_TAG_KEYWORD); - - if (attr && !strcmp(attr->values[0].string.text, "monochrome")) + IPP_TAG_KEYWORD)) != NULL && + !strcmp(attr->values[0].string.text, "monochrome")) print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME; else print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR; @@ -3645,13 +3643,22 @@ get_options(cupsd_job_t *job, /* I - Job */ attr->value_tag == IPP_TAG_BEGIN_COLLECTION) /* Not yet supported */ continue; - if (!strcmp(attr->name, "job-hold-until")) + if (!strcmp(attr->name, "job-hold-until") || + !strcmp(attr->name, "job-id") || + !strcmp(attr->name, "job-k-octets") || + !strcmp(attr->name, "job-media-sheets") || + !strcmp(attr->name, "job-media-sheets-completed") || + !strcmp(attr->name, "job-state") || + !strcmp(attr->name, "job-state-reasons")) continue; if (!strncmp(attr->name, "job-", 4) && + strcmp(attr->name, "job-account-id") && + strcmp(attr->name, "job-accounting-user-id") && strcmp(attr->name, "job-billing") && strcmp(attr->name, "job-impressions") && strcmp(attr->name, "job-originating-host-name") && + strcmp(attr->name, "job-password") && strcmp(attr->name, "job-uuid") && !(job->printer->type & CUPS_PRINTER_REMOTE)) continue; @@ -3758,10 +3765,10 @@ get_options(cupsd_job_t *job, /* I - Job */ for (i = num_pwgppds, pwgppd = pwgppds; i > 0; i --, pwgppd ++) { *optptr++ = ' '; - strcpy(optptr, pwgppd->name); + strlcpy(optptr, pwgppd->name, optlength - (optptr - options)); optptr += strlen(optptr); *optptr++ = '='; - strcpy(optptr, pwgppd->value); + strlcpy(optptr, pwgppd->value, optlength - (optptr - options)); optptr += strlen(optptr); } @@ -4734,11 +4741,21 @@ update_job(cupsd_job_t *job) /* I - Job to check */ cups_option_t *attrs; /* Attributes */ const char *attr; /* Attribute */ - cupsdLogJob(job, CUPSD_LOG_DEBUG, "ATTR: %s", message); num_attrs = cupsParseOptions(message, 0, &attrs); + if ((attr = cupsGetOption("auth-info-default", num_attrs, + attrs)) != NULL) + { + job->printer->num_options = cupsAddOption("auth-info", attr, + job->printer->num_options, + &(job->printer->options)); + cupsdSetPrinterAttrs(job->printer); + + cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); + } + if ((attr = cupsGetOption("auth-info-required", num_attrs, attrs)) != NULL) { diff --git a/scheduler/log.c b/scheduler/log.c index 21603c883..a476d2a03 100644 --- a/scheduler/log.c +++ b/scheduler/log.c @@ -3,7 +3,7 @@ * * Log file routines for the CUPS scheduler. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -198,7 +198,7 @@ cupsdCheckLogFile(cups_file_t **lf, /* IO - Log file */ cupsFileClose(*lf); - strcpy(backname, filename); + strlcpy(backname, filename, sizeof(backname)); strlcat(backname, ".O", sizeof(backname)); unlink(backname); @@ -485,7 +485,7 @@ cupsdLogJob(cupsd_job_t *job, /* I - Job */ if ((temp = malloc(sizeof(cupsd_joblog_t) + strlen(log_line))) != NULL) { temp->time = time(NULL); - strcpy(temp->message, log_line); + strlcpy(temp->message, log_line, sizeof(temp->message)); } if (!job->history) @@ -603,7 +603,7 @@ cupsdLogPage(cupsd_job_t *job, /* I - Job being printed */ if (!PageLogFormat) return (1); - strcpy(number, "1"); + strlcpy(number, "1", sizeof(number)); copies = 1; sscanf(page, "%255s%d", number, &copies); diff --git a/scheduler/mime.c b/scheduler/mime.c index fd7c12a49..15684cd0e 100644 --- a/scheduler/mime.c +++ b/scheduler/mime.c @@ -3,7 +3,7 @@ * * MIME database file routines for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -134,7 +134,7 @@ mimeDeleteFilter(mime_t *mime, /* I - MIME database */ filter ? filter->dst->super : "???", filter ? filter->cost : -1, filter ? CUPS_LLCAST filter->maxsize : CUPS_LLCAST -1)); - + if (!mime || !filter) return; @@ -798,7 +798,7 @@ mime_load_convs( if (!mime_add_fcache(filtercache, filter, filterpath)) { DEBUG_printf(("mime_load_convs: Filter %s not found in %s.", filter, - filterpath)); + filterpath)); _mimeError(mime, "Filter \"%s\" not found.", filter); continue; } @@ -836,8 +836,8 @@ mime_load_convs( * Force * / * to be "application/octet-stream"... */ - strcpy(super, "application"); - strcpy(type, "octet-stream"); + strlcpy(super, "application", sizeof(super)); + strlcpy(type, "octet-stream", sizeof(type)); } /* diff --git a/scheduler/printers.c b/scheduler/printers.c index 1883c203a..b5de7ccd8 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -348,9 +348,9 @@ cupsdCreateCommonData(void) "multiple-document-handling", "number-up", "output-bin", - "output-mode", "orientation-requested", "page-ranges", + "print-color-mode", "print-quality", "printer-resolution", "sides" @@ -367,9 +367,9 @@ cupsdCreateCommonData(void) "multiple-document-handling", "number-up", "output-bin", - "output-mode", "orientation-requested", "page-ranges", + "print-color-mode", "print-quality", "printer-resolution", "sides" @@ -3248,6 +3248,9 @@ add_printer_defaults(cupsd_printer_t *p)/* I - Printer */ cupsArrayAdd(CommonDefaults, _cupsStrAlloc("copies-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("document-format-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("finishings-default")); + cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-account-id-default")); + cupsArrayAdd(CommonDefaults, + _cupsStrAlloc("job-accounting-user-id-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-hold-until-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-priority-default")); cupsArrayAdd(CommonDefaults, _cupsStrAlloc("job-sheets-default")); @@ -3753,7 +3756,8 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ qualities[3]; /* print-quality values */ int num_margins, /* Number of media-*-margin-supported values */ margins[16]; /* media-*-margin-supported values */ - const char *filter; /* Current filter */ + const char *filter, /* Current filter */ + *mandatory; /* Current mandatory attribute */ static const char * const sides[3] = /* sides-supported values */ { "one-sided", @@ -3825,6 +3829,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ p->pc = _ppdCacheCreateWithPPD(ppd); + if (!p->pc) + cupsdLogMessage(CUPSD_LOG_WARN, "Unable to create cache of \"%s\": %s", + ppd_name, cupsLastErrorString()); + ppdMarkDefaults(ppd); if (ppd->color_device) @@ -3839,6 +3847,23 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "color-supported", ppd->color_device); + + if (p->pc && p->pc->account_id) + ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, "job-account-id-supported", + 1); + + if (p->pc && p->pc->accounting_user_id) + ippAddBoolean(p->ppd_attrs, IPP_TAG_PRINTER, + "job-accounting-user-id-supported", 1); + + if (p->pc && p->pc->password) + { + ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "job-password-encryption-supported", NULL, "none"); + ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, + "job-password-supported", strlen(p->pc->password)); + } + if (ppd->throughput) { ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, @@ -4314,40 +4339,50 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } /* - * output-mode and print-color-mode... + * print-color-mode... */ if (ppd->color_device) { - static const char * const output_modes[] = + static const char * const color_modes[] = { "monochrome", "color" }; ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-supported", 2, NULL, output_modes); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-default", NULL, "color"); - - ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "print-color-mode-supported", 2, NULL, output_modes); + "print-color-mode-supported", 2, NULL, color_modes); ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "print-color-mode-default", NULL, "color"); } else { - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-supported", NULL, "monochrome"); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-mode-default", NULL, "monochrome"); - ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "print-color-mode-supported", NULL, "monochrome"); ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, "print-color-mode-default", NULL, "monochrome"); } + /* + * Mandatory job attributes, if any... + */ + + if (p->pc && cupsArrayCount(p->pc->mandatory) > 0) + { + int count = cupsArrayCount(p->pc->mandatory); + /* Number of mandatory attributes */ + + attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "printer-mandatory-job-attributes", count, NULL, + NULL); + + for (val = attr->values, + mandatory = (char *)cupsArrayFirst(p->pc->mandatory); + mandatory; + val ++, mandatory = (char *)cupsArrayNext(p->pc->mandatory)) + val->string.text = _cupsStrRetain(mandatory); + } + /* * Printer resolutions... */ diff --git a/scheduler/type.c b/scheduler/type.c index 60c858a96..1a59eaf16 100644 --- a/scheduler/type.c +++ b/scheduler/type.c @@ -3,7 +3,7 @@ * * MIME typing routines for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -515,7 +515,7 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ case MIME_MAGIC_MATCH : if (length[0] > (sizeof(temp->value.matchv) - 1)) return (-1); - strcpy(temp->value.matchv, value[0]); + strlcpy(temp->value.matchv, value[0], sizeof(temp->value.matchv)); break; case MIME_MAGIC_ASCII : case MIME_MAGIC_PRINTABLE : @@ -554,7 +554,7 @@ mimeAddTypeRule(mime_type_t *mt, /* I - Type to add to */ if (length[0] > (sizeof(temp->value.localev) - 1)) return (-1); - strcpy(temp->value.localev, value[0]); + strlcpy(temp->value.localev, value[0], sizeof(temp->value.localev)); break; case MIME_MAGIC_CONTAINS : temp->offset = strtol(value[0], NULL, 0); diff --git a/scheduler/util.c b/scheduler/util.c index fc55d5799..8611869be 100644 --- a/scheduler/util.c +++ b/scheduler/util.c @@ -3,7 +3,7 @@ * * Mini-daemon utility functions for CUPS. * - * Copyright 2007-2011 by Apple Inc. + * Copyright 2007-2012 by Apple Inc. * Copyright 1997-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -163,7 +163,7 @@ cupsdCreateStringsArray(const char *s) /* I - Comma-delimited strings */ if (!s || !*s) return (NULL); else - return (_cupsArrayNewStrings(s)); + return (_cupsArrayNewStrings(s, ',')); } diff --git a/systemv/cupstestppd.c b/systemv/cupstestppd.c index 6e5c50de9..491b14640 100644 --- a/systemv/cupstestppd.c +++ b/systemv/cupstestppd.c @@ -1880,7 +1880,7 @@ check_constraints(ppd_file_t *ppd, /* I - PPD file */ if (!_cups_strncasecmp(option, "Custom", 6) && !_cups_strcasecmp(choice, "True")) { _cups_strcpy(option, option + 6); - strcpy(choice, "Custom"); + strlcpy(choice, "Custom", sizeof(choice)); } if ((o = ppdFindOption(ppd, option)) == NULL) @@ -1981,13 +1981,13 @@ check_constraints(ppd_file_t *ppd, /* I - PPD file */ if (!_cups_strncasecmp(c->option1, "Custom", 6) && !_cups_strcasecmp(c->choice1, "True")) { - strcpy(option, c->option1 + 6); - strcpy(choice, "Custom"); + strlcpy(option, c->option1 + 6, sizeof(option)); + strlcpy(choice, "Custom", sizeof(choice)); } else { - strcpy(option, c->option1); - strcpy(choice, c->choice1); + strlcpy(option, c->option1, sizeof(option)); + strlcpy(choice, c->choice1, sizeof(choice)); } if ((o = ppdFindOption(ppd, option)) == NULL) @@ -2022,13 +2022,13 @@ check_constraints(ppd_file_t *ppd, /* I - PPD file */ if (!_cups_strncasecmp(c->option2, "Custom", 6) && !_cups_strcasecmp(c->choice2, "True")) { - strcpy(option, c->option2 + 6); - strcpy(choice, "Custom"); + strlcpy(option, c->option2 + 6, sizeof(option)); + strlcpy(choice, "Custom", sizeof(choice)); } else { - strcpy(option, c->option2); - strcpy(choice, c->choice2); + strlcpy(option, c->option2, sizeof(option)); + strlcpy(choice, c->choice2, sizeof(choice)); } if ((o = ppdFindOption(ppd, option)) == NULL) diff --git a/systemv/lpstat.c b/systemv/lpstat.c index 20ef8bf00..fd36fe898 100644 --- a/systemv/lpstat.c +++ b/systemv/lpstat.c @@ -1437,7 +1437,7 @@ show_jobs(const char *dests, /* I - Destinations */ */ if (!strftime(date, sizeof(date), "%b %d %H:%M", jobdate)) - strcpy(date, "Unknown"); + strlcpy(date, "Unknown", sizeof(date)); _cupsLangPrintf(stdout, "%s;%s;%d;%s;%s", temp, username ? username : "unknown", @@ -1446,7 +1446,7 @@ show_jobs(const char *dests, /* I - Destinations */ else { if (!strftime(date, sizeof(date), "%c", jobdate)) - strcpy(date, "Unknown"); + strlcpy(date, "Unknown", sizeof(date)); if (ranking) _cupsLangPrintf(stdout, "%3d %-21s %-13s %8.0f %s", diff --git a/test/ippserver.c b/test/ippserver.c index 80db180b2..a6b53cbcf 100644 --- a/test/ippserver.c +++ b/test/ippserver.c @@ -269,6 +269,7 @@ static _ipp_printer_t *create_printer(const char *servername, const char *icon, const char *docformats, int ppm, int ppm_color, int duplex, int port, + int pin, #ifdef HAVE_DNSSD const char *regtype, #endif /* HAVE_DNSSD */ @@ -360,7 +361,8 @@ main(int argc, /* I - Number of command-line args */ int port = 8631, /* Port number (0 = auto) TODO: FIX */ duplex = 0, /* Duplex mode */ ppm = 10, /* Pages per minute for mono */ - ppm_color = 0; /* Pages per minute for color */ + ppm_color = 0, /* Pages per minute for color */ + pin = 0; /* PIN printing mode? */ char directory[1024] = ""; /* Spool directory */ _ipp_printer_t *printer; /* Printer object */ @@ -386,6 +388,10 @@ main(int argc, /* I - Number of command-line args */ make = argv[i]; break; + case 'P' : /* -P (PIN printing mode) */ + pin = 1; + break; + case 'd' : /* -d spool-directory */ i ++; if (i >= argc) @@ -507,7 +513,7 @@ main(int argc, /* I - Number of command-line args */ */ if ((printer = create_printer(servername, name, location, make, model, icon, - formats, ppm, ppm_color, duplex, port, + formats, ppm, ppm_color, duplex, port, pin, #ifdef HAVE_DNSSD regtype, #endif /* HAVE_DNSSD */ @@ -1002,6 +1008,7 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) int ppm_color, /* I - Pages per minute in color (0 for gray) */ int duplex, /* I - 1 = duplex, 0 = simplex */ int port, /* I - Port for listeners or 0 for auto */ + int pin, /* I - Require PIN printing */ #ifdef HAVE_DNSSD const char *regtype, /* I - Bonjour service type */ #endif /* HAVE_DNSSD */ @@ -1072,7 +1079,10 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) { /* job-creation-attributes-supported values */ "copies", "ipp-attribute-fidelity", + "job-account-id", + "job-accounting-user-id", "job-name", + "job-password", "job-priority", "media", "media-col", @@ -1322,6 +1332,13 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) "ipp-versions-supported", sizeof(versions) / sizeof(versions[0]), NULL, versions); + /* job-account-id-supported */ + ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, "job-account-id-supported", 1); + + /* job-accounting-user-id-supported */ + ippAddBoolean(printer->attrs, IPP_TAG_PRINTER, + "job-accounting-user-id-supported", 1); + /* job-creation-attributes-supported */ ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD | IPP_TAG_COPY, "job-creation-attributes-supported", @@ -1332,6 +1349,10 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) ippAddRange(printer->attrs, IPP_TAG_PRINTER, "job-k-octets-supported", 0, k_supported); + /* job-password-supported */ + ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, + "job-password-supported", 4); + /* job-priority-default */ ippAddInteger(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "job-priority-default", 50); @@ -1573,6 +1594,20 @@ create_printer(const char *servername, /* I - Server hostname (NULL for default) ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-make-and-model", NULL, make_model); + /* printer-mandatory-job-attributes */ + if (pin) + { + static const char * const names[] = + { + "job-accounting-user-id", + "job-password" + }; + + ippAddStrings(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "printer-mandatory-job-attributes", + (int)(sizeof(names) / sizeof(names[0])), NULL, names); + } + /* printer-more-info */ ippAddString(printer->attrs, IPP_TAG_PRINTER, IPP_TAG_URI, "printer-more-info", NULL, adminurl); diff --git a/test/ipptool.c b/test/ipptool.c index 537c299b2..a364a93f7 100644 --- a/test/ipptool.c +++ b/test/ipptool.c @@ -1702,6 +1702,11 @@ do_tests(_cups_vars_t *vars, /* I - Variables */ } break; + case IPP_TAG_STRING : + attrptr = ippAddOctetString(request, group, attr, token, + strlen(token)); + break; + default : print_fatal_error("Unsupported ATTR value tag %s on line %d.", ippTagString(value), linenum); @@ -3790,6 +3795,41 @@ print_attr(ipp_attribute_t *attr, /* I - Attribute to print */ break; case IPP_TAG_STRING : + for (i = 0; i < attr->num_values; i ++) + { + if (Output == _CUPS_OUTPUT_PLIST) + { + char buffer[IPP_MAX_LENGTH * 5 / 4 + 1]; + /* Output buffer */ + + printf("%s\n", + httpEncode64_2(buffer, sizeof(buffer), + attr->values[i].unknown.data, + attr->values[i].unknown.length)); + } + else + { + char *ptr, /* Pointer into data */ + *end; /* End of data */ + + putchar('\"'); + for (ptr = attr->values[i].unknown.data, + end = ptr + attr->values[i].unknown.length; + ptr < end; + ptr ++) + { + if (*ptr == '\\' || *ptr == '\"') + printf("\\%c", *ptr); + else if (!isprint(*ptr & 255)) + printf("\\%03o", *ptr & 255); + else + putchar(*ptr); + } + putchar('\"'); + } + } + break; + case IPP_TAG_TEXT : case IPP_TAG_NAME : case IPP_TAG_KEYWORD : diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh index ff589e9e0..7ab618f04 100755 --- a/test/run-stp-tests.sh +++ b/test/run-stp-tests.sh @@ -368,6 +368,11 @@ else ln -s /usr/lib/cups/filter/texttops /tmp/cups-$user/bin/filter ln -s /usr/share/cups/mime/legacy.convs /tmp/cups-$user/share/mime + ln -s /usr/share/cups/charsets /tmp/cups-$user/share + if test -f $root/data/psglyphs; then + ln -s /usr/share/cups/data/psglyphs $root/data + fi + ln -s /usr/share/cups/fonts /tmp/cups-$user/share fi # diff --git a/test/str-header.html b/test/str-header.html index f9204bbe9..7d97e91bf 100644 --- a/test/str-header.html +++ b/test/str-header.html @@ -1,10 +1,10 @@ - - + + - CUPS 1.5 Software Test Report + CUPS 1.7 Software Test Report