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
-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
2012-MM-DD
+ - ipptool did not support octetString values.
- Fixed REPEAT-MATCH for STATUS and EXPECT - was incorrectly erroring
out.
-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)
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;
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] == '(')
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';
*
* 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.
*/
/*
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)
*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 */
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
/*
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"))
* 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)
* 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;
_cupsLangPrintFilter(stderr, "ERROR",
_("Unable to get printer status."));
sleep(10);
+
+ httpReconnect(http);
}
ippDelete(supported);
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...
*/
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
{
/*
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)
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
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.
*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 */
/*
* 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);
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,
*/
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...
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 ++;
}
+/*
+ * '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.
*/
{
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 */
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 :
else
op = '\0';
- new_reasons = _cupsArrayNewStrings(s);
+ new_reasons = _cupsArrayNewStrings(s, ',');
}
else
return;
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 */
*/
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"))
*/
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"))
{
*/
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"))
{
}
}
- 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...
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);
"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"
*/
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,
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);
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);
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;
}
}
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 */
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"))
{
/*
* 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;
/*
* Ignore timeout errors, but retain the number of bytes written to
- * avoid sending duplicate data (<rdar://problem/6254911>)...
+ * avoid sending duplicate data...
*/
if (iostatus == kIOUSBTransactionTimeout)
/*
* Retry a write after an aborted write since we probably just got
- * SIGTERM (<rdar://problem/6860126>)...
+ * SIGTERM...
*/
else if (iostatus == kIOReturnAborted)
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)
}
/* move everything over... */
- strcpy(gErrorBuffer, pLineEnd);
+ strlcpy(gErrorBuffer, pLineEnd, sizeof(gErrorBuffer));
gErrorBufferPtr = gErrorBuffer;
pLineEnd = (char *)next_line((const char *)gErrorBuffer);
}
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 }
};
*/
if (jobstate == IPP_JOB_PROCESSING)
- strcpy(rankstr, "active");
+ strlcpy(rankstr, "active", sizeof(rankstr));
else
{
/*
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);
if (bufptr == buffer || (bufend - bufptr) < 2)
return (NULL);
- strcpy(bufptr, "}");
+ memcpy(bufptr, "}", 2);
}
return (buffer);
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;
*
* 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
node = NULL;
offset = 0;
- strcpy(section, "Other");
+ strlcpy(section, "Other", sizeof(section));
while (cupsFileGets(fp, line, sizeof(line)))
{
*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...
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);
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");
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);
}
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;
*
* 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
* Add the prefix string...
*/
- strcpy(sptr, prefix);
+ memcpy(sptr, prefix, strlen(prefix) + 1);
sptr += strlen(sptr);
/*
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);
free(lword);
if (sptr > s)
- strcpy(sptr, ".*");
+ memcpy(sptr, ".*", 3);
else
{
/*
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))
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
;;
#undef HAVE_SCSI_SG_H
+/*
+ * Use <stdint.h>?
+ */
+
+#undef HAVE_STDINT_H
+
+
/*
* Use <string.h>, <strings.h>, and/or <bstring.h>?
*/
--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
--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 \
/*
* 'cupsAdminCreateWindowsPPD()' - Create the Windows PPD file for a printer.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @deprecated@
*/
char * /* O - PPD file or NULL */
/*
* 'cupsAdminExportSamba()' - Export a printer to Samba.
*
- * @since CUPS 1.2/OS X 10.5@
+ * @deprecated@
*/
int /* O - 1 on success, 0 on failure */
*
* 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
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
*
* 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
* 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
}
/*
- * '_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
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 */
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))
* 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);
*/
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 */
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);
}
* 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(),
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);
if (*s == '\\' || *s == '\"')
putchar('\\');
- if (*s == '\n')
+ if (((*s & 255) < ' ' && *s != '\t') || *s == 0x7f)
putchar(' ');
else
putchar(*s);
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);
# include "string-private.h"
# include "debug-private.h"
+# include "array-private.h"
# include "ipp-private.h"
# include "http-private.h"
# include "language-private.h"
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;
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;
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;
* 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@
*/
/*
* '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.
*
/*
* '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.
*
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.
"printer-is-shared",
"printer-location",
"printer-make-and-model",
+ "printer-mandatory-job-attributes",
"printer-name",
"printer-state",
"printer-state-change-time",
!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") ||
* 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;
* '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 */
{
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;
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] == '(')
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';
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 },
{ 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 },
{ 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,
* 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))
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;
uribuf.buffer = resolved_uri;
uribuf.bufsize = resolved_size;
uribuf.options = options;
+ uribuf.resource = resource;
resolved_uri[0] = '\0';
* 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));
}
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
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
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 ++)
credential->datalen);
cupsArrayAdd(names, credential);
}
+ else
+ free(credential);
}
}
}
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)
{
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), "
{
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)",
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)
_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)
{
_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';
_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);
* 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);
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)
_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))
{
{
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 :
for (i = count, value = attr->values + element;
i > 0;
i --, value ++)
+ {
_cupsStrFree(value->string.text);
+ value->string.text = NULL;
+ }
break;
case IPP_TAG_DEFAULT :
for (i = count, value = attr->values + element;
i > 0;
i --, value ++)
+ {
ippDelete(value->collection);
+ value->collection = NULL;
+ }
break;
case IPP_TAG_STRING :
for (i = count, value = attr->values + element;
i > 0;
i --, value ++)
+ {
if (value->unknown.data)
+ {
free(value->unknown.data);
+ value->unknown.data = NULL;
+ }
+ }
break;
}
}
* 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 */
*
* 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
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 */
* 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
*/
if (!charset[0])
- strcpy(charset, "UTF8");
+ strlcpy(charset, "UTF8", sizeof(charset));
/*
* Parse the language string passed in to a locale string. "C" is the
if (language == NULL || !language[0] ||
!strcmp(language, "POSIX"))
- strcpy(langname, "C");
+ strlcpy(langname, "C", sizeof(langname));
else
{
/*
if (strlen(langname) != 2)
{
- strcpy(langname, "C");
+ strlcpy(langname, "C", sizeof(langname));
country[0] = '\0';
charset[0] = '\0';
}
if (country[0])
snprintf(real, sizeof(real), "%s_%s", langname, country);
else
- strcpy(real, langname);
+ strlcpy(real, langname, sizeof(real));
_cupsMutexLock(&lang_mutex);
*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));
*/
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);
{
/*
* 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)
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));
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"))
}
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,
* 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;
+ }
}
}
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...
*/
cupsArrayDelete(pc->prefilters);
cupsArrayDelete(pc->finishings);
+ _cupsStrFree(pc->password);
+
+ cupsArrayDelete(pc->mandatory);
+
free(pc);
}
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...
*/
* Constants...
*/
-# define _PPD_CACHE_VERSION 3 /* Version number in cache file */
+# define _PPD_CACHE_VERSION 4 /* Version number in cache file */
/*
*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 */
};
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"))
*/
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);
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));
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 */
/*
* '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 */
/*
* '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@
* '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 */
* '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@
*/
/*
- * '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 */
/*
- * '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@
*/
/*
* '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@
*/
/*
* '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@
*/
*
* 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
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 */
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;
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;
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;
*
* 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
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 */
* 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);
}
item->ref_count = 1;
- strcpy(item->str, s);
+ memcpy(item->str, s, slen + 1);
#ifdef DEBUG_GUARDS
item->guard = _CUPS_STR_GUARD;
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 */
*
* 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
/*
* cupsArrayCount()
*/
-
+
fputs("cupsArrayCount: ", stdout);
if (cupsArrayCount(array) == 4)
puts("PASS");
* the same buffer in the first place... :)
*/
- strcpy(word, text);
+ strlcpy(word, text, sizeof(word));
/*
* Grab the next word and compare...
*
* 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
fputs("httpGetDateString()/httpGetDateTime(): ", stdout);
start = time(NULL);
- strcpy(buffer, httpGetDateString(start));
+ strlcpy(buffer, httpGetDateString(start), sizeof(buffer));
current = httpGetDateTime(buffer);
i = (int)(current - start);
*
* 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
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))
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))
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))
#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))
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))
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))
*
* 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
maxsize, /* Maximum size */
*size; /* Current size */
ppd_attr_t *attr; /* Current attribute */
+ _ppd_cache_t *pc; /* PPD cache */
status = 0;
if ((realsize = readlink(filename, realfile, sizeof(realfile) - 1)) < 0)
- strcpy(realfile, "Unknown");
+ strlcpy(realfile, "Unknown", sizeof(realfile));
else
realfile[realsize] = '\0';
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))
}
if (cg->server[0] == '/')
- strcpy(cg->servername, "localhost");
+ strlcpy(cg->servername, "localhost", sizeof(cg->servername));
else
strlcpy(cg->servername, cg->server, sizeof(cg->servername));
}
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));
}
* Use the default "unknown" user name...
*/
- strcpy(cg->user, "unknown");
+ strlcpy(cg->user, "unknown", sizeof(cg->user));
}
}
}
}
}
else
- strcpy(uri, "ipp://localhost/");
+ strlcpy(uri, "ipp://localhost/", sizeof(uri));
if (!http)
if ((http = _cupsConnect()) == NULL)
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...
<li><a href="#PASSWORDS_AND_AUTHENTICATION">Passwords and Authentication</a></li>
</ul></li>
<li><a href="#FUNCTIONS">Functions</a><ul class="code">
- <li><a href="#appleGetPaperSize" title="Get the default paper size.">appleGetPaperSize</a></li>
<li><a href="#cupsAddDest" title="Add a destination to the list of destinations.">cupsAddDest</a></li>
<li><a href="#cupsAddOption" title="Add an option to an option array.">cupsAddOption</a></li>
<li><a href="#cupsAdminCreateWindowsPPD" title="Create the Windows PPD file for a printer.">cupsAdminCreateWindowsPPD</a></li>
<li><a href="#cupsAdminExportSamba" title="Export a printer to Samba.">cupsAdminExportSamba</a></li>
<li><a href="#cupsAdminGetServerSettings" title="Get settings from the server.">cupsAdminGetServerSettings</a></li>
<li><a href="#cupsAdminSetServerSettings" title="Set settings on the server.">cupsAdminSetServerSettings</a></li>
+ <li><a href="#cupsCancelDestJob" title="Include necessary headers...">cupsCancelDestJob</a></li>
<li><a href="#cupsCancelJob" title="Cancel a print job on the default server.">cupsCancelJob</a></li>
<li><a href="#cupsCancelJob2" title="Cancel or purge a print job.">cupsCancelJob2</a></li>
+ <li><a href="#cupsCheckDestSupported" title="Check that the option and value are supported
+by the destination.">cupsCheckDestSupported</a></li>
+ <li><a href="#cupsCloseDestJob" title="Close a job and start printing.">cupsCloseDestJob</a></li>
<li><a href="#cupsConnectDest" title="Connect to the server for a destination.">cupsConnectDest</a></li>
<li><a href="#cupsConnectDestBlock" title="Connect to the server for a destination.">cupsConnectDestBlock</a></li>
<li><a href="#cupsCopyDest" title="Callback block">cupsCopyDest</a></li>
+ <li><a href="#cupsCopyDestConflicts" title="Get conflicts and resolutions for a new
+option/value pair.">cupsCopyDestConflicts</a></li>
+ <li><a href="#cupsCopyDestInfo" title="Get the supported values/capabilities for the
+destination.">cupsCopyDestInfo</a></li>
+ <li><a href="#cupsCreateDestJob" title="Create a job on a destination.">cupsCreateDestJob</a></li>
<li><a href="#cupsCreateJob" title="Create an empty job for streaming.">cupsCreateJob</a></li>
<li><a href="#cupsEncryption" title="Get the current encryption settings.">cupsEncryption</a></li>
<li><a href="#cupsEnumDests" title="Enumerate available destinations with a callback function.">cupsEnumDests</a></li>
<li><a href="#cupsEnumDestsBlock" title="Enumerate available destinations with a block.">cupsEnumDestsBlock</a></li>
+ <li><a href="#cupsFinishDestDocument" title="Finish the current document.">cupsFinishDestDocument</a></li>
<li><a href="#cupsFinishDocument" title="Finish sending a document.">cupsFinishDocument</a></li>
+ <li><a href="#cupsFreeDestInfo" title="Free destination information obtained using
+cupsCopyDestInfo.">cupsFreeDestInfo</a></li>
<li><a href="#cupsFreeDests" title="Free the memory used by the list of destinations.">cupsFreeDests</a></li>
<li><a href="#cupsFreeJobs" title="Free memory used by job data.">cupsFreeJobs</a></li>
<li><a href="#cupsFreeOptions" title="Free all memory used by options.">cupsFreeOptions</a></li>
<li><a href="#cupsGetDefault" title="Get the default printer or class for the default server.">cupsGetDefault</a></li>
<li><a href="#cupsGetDefault2" title="Get the default printer or class for the specified server.">cupsGetDefault2</a></li>
<li><a href="#cupsGetDest" title="Get the named destination from the list.">cupsGetDest</a></li>
+ <li><a href="#cupsGetDestMediaByName" title="Get media names, dimensions, and margins.">cupsGetDestMediaByName</a></li>
+ <li><a href="#cupsGetDestMediaBySize" title="Get media names, dimensions, and margins.">cupsGetDestMediaBySize</a></li>
<li><a href="#cupsGetDests" title="Get the list of destinations from the default server.">cupsGetDests</a></li>
<li><a href="#cupsGetDests2" title="Get the list of destinations from the specified server.">cupsGetDests2</a></li>
<li><a href="#cupsGetJobs" title="Get the jobs from the default server.">cupsGetJobs</a></li>
<li><a href="#cupsLangFlush" title="Flush all language data out of the cache.">cupsLangFlush</a></li>
<li><a href="#cupsLangFree" title="Free language data.">cupsLangFree</a></li>
<li><a href="#cupsLangGet" title="Get a language.">cupsLangGet</a></li>
+ <li><a href="#cupsLocalizeDestOption" title="Get the localized string for a destination
+option.">cupsLocalizeDestOption</a></li>
+ <li><a href="#cupsLocalizeDestValue" title="Get the localized string for a destination
+option+value pair.">cupsLocalizeDestValue</a></li>
<li><a href="#cupsNotifySubject" title="Return the subject for the given notification message.">cupsNotifySubject</a></li>
<li><a href="#cupsNotifyText" title="Return the text for the given notification message.">cupsNotifyText</a></li>
<li><a href="#cupsParseOptions" title="Parse options from a command-line argument.">cupsParseOptions</a></li>
<li><a href="#cupsSetServer" title="Set the default server name and port.">cupsSetServer</a></li>
<li><a href="#cupsSetServerCertCB" title="Set the server certificate callback.">cupsSetServerCertCB</a></li>
<li><a href="#cupsSetUser" title="Set the default user name.">cupsSetUser</a></li>
+ <li><a href="#cupsStartDestDocument" title="Start a new document.">cupsStartDestDocument</a></li>
<li><a href="#cupsStartDocument" title="Add a document to a job created with cupsCreateJob().">cupsStartDocument</a></li>
<li><a href="#cupsTempFd" title="Creates a temporary file.">cupsTempFd</a></li>
<li><a href="#cupsTempFile" title="Generates a temporary filename.">cupsTempFile</a></li>
string returned by the <a href="#cupsUser"><code>cupsUser</code></a>
function.</p>
<h2 class="title"><a name="FUNCTIONS">Functions</a></h2>
-<h3 class="function"><a name="appleGetPaperSize">appleGetPaperSize</a></h3>
-<p class="description">Get the default paper size.</p>
-<p class="code">
-char *appleGetPaperSize (<br>
- char *name,<br>
- int namesize<br>
-);</p>
-<h4 class="parameters">Parameters</h4>
-<dl>
-<dt>name</dt>
-<dd class="description">Paper size name buffer</dd>
-<dt>namesize</dt>
-<dd class="description">Size of buffer</dd>
-</dl>
-<h4 class="returnvalue">Return Value</h4>
-<p class="description">Default paper size</p>
<h3 class="function"><a name="cupsAddDest">cupsAddDest</a></h3>
<p class="description">Add a destination to the list of destinations.</p>
<p class="code">
<h4 class="discussion">Discussion</h4>
<p class="discussion">New option arrays can be initialized simply by passing 0 for the
"num_options" parameter.</p>
-<h3 class="function"><span class="info"> CUPS 1.2/OS X 10.5 </span><a name="cupsAdminCreateWindowsPPD">cupsAdminCreateWindowsPPD</a></h3>
+<h3 class="function"><span class="info"> DEPRECATED </span><a name="cupsAdminCreateWindowsPPD">cupsAdminCreateWindowsPPD</a></h3>
<p class="description">Create the Windows PPD file for a printer.</p>
<p class="code">
char *cupsAdminCreateWindowsPPD (<br>
</dl>
<h4 class="returnvalue">Return Value</h4>
<p class="description">PPD file or NULL</p>
-<h3 class="function"><span class="info"> CUPS 1.2/OS X 10.5 </span><a name="cupsAdminExportSamba">cupsAdminExportSamba</a></h3>
+<h3 class="function"><span class="info"> DEPRECATED </span><a name="cupsAdminExportSamba">cupsAdminExportSamba</a></h3>
<p class="description">Export a printer to Samba.</p>
<p class="code">
int cupsAdminExportSamba (<br>
</dl>
<h4 class="returnvalue">Return Value</h4>
<p class="description">1 on success, 0 on failure</p>
+<h3 class="function"><a name="cupsCancelDestJob">cupsCancelDestJob</a></h3>
+<p class="description">Include necessary headers...</p>
+<p class="code">
+ipp_status_t cupsCancelDestJob (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ int job_id<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>job_id</dt>
+<dd class="description">Job ID</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Cancel a job on a destination.</p>
+<p class="discussion">The "job_id" is the number returned by cupsCreateDestJob.<br>
+<br>
+Returns IPP_OK on success and IPP_NOT_AUTHORIZED or IPP_FORBIDDEN on
+failure.
+
+</p>
<h3 class="function"><a name="cupsCancelJob">cupsCancelJob</a></h3>
<p class="description">Cancel a print job on the default server.</p>
<p class="code">
Use the <a href="#cupsLastError"><code>cupsLastError</code></a> and <a href="#cupsLastErrorString"><code>cupsLastErrorString</code></a> functions to get
the cause of any failure.
+</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsCheckDestSupported">cupsCheckDestSupported</a></h3>
+<p class="description">Check that the option and value are supported
+by the destination.</p>
+<p class="code">
+int cupsCheckDestSupported (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *dinfo,<br>
+ const char *option,<br>
+ const char *value<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>dinfo</dt>
+<dd class="description">Destination information</dd>
+<dt>option</dt>
+<dd class="description">Option</dd>
+<dt>value</dt>
+<dd class="description">Value</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 if supported, 0 otherwise</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">Returns 1 if supported, 0 otherwise.
+
+</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsCloseDestJob">cupsCloseDestJob</a></h3>
+<p class="description">Close a job and start printing.</p>
+<p class="code">
+ipp_status_t cupsCloseDestJob (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *info,<br>
+ int job_id<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>info</dt>
+<dd class="description">Destination information</dd>
+<dt>job_id</dt>
+<dd class="description">Job ID</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">IPP status code</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">Use when the last call to cupsStartDocument passed 0 for "last_document".
+"job_id" is the job ID returned by cupsCreateDestJob. Returns <code>IPP_OK</code>
+on success.
+
</p>
<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsConnectDest">cupsConnectDest</a></h3>
<p class="description">Connect to the server for a destination.</p>
copy) - for use with the cupsEnumDests* functions. The caller is responsible
for calling cupsFreeDests() on the returned object(s).
+</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsCopyDestConflicts">cupsCopyDestConflicts</a></h3>
+<p class="description">Get conflicts and resolutions for a new
+option/value pair.</p>
+<p class="code">
+int cupsCopyDestConflicts (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *dinfo,<br>
+ int num_options,<br>
+ <a href="#cups_option_t">cups_option_t</a> *options,<br>
+ const char *new_option,<br>
+ const char *new_value,<br>
+ int *num_conflicts,<br>
+ <a href="#cups_option_t">cups_option_t</a> **conflicts,<br>
+ int *num_resolved,<br>
+ <a href="#cups_option_t">cups_option_t</a> **resolved<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>dinfo</dt>
+<dd class="description">Destination information</dd>
+<dt>num_options</dt>
+<dd class="description">Number of current options</dd>
+<dt>options</dt>
+<dd class="description">Current options</dd>
+<dt>new_option</dt>
+<dd class="description">New option</dd>
+<dt>new_value</dt>
+<dd class="description">New value</dd>
+<dt>num_conflicts</dt>
+<dd class="description">Number of conflicting options</dd>
+<dt>conflicts</dt>
+<dd class="description">Conflicting options</dd>
+<dt>num_resolved</dt>
+<dd class="description">Number of options to resolve</dd>
+<dt>resolved</dt>
+<dd class="description">Resolved options</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 if there is a conflict, 0 if none, -1 on error</p>
+<h4 class="discussion">Discussion</h4>
+<p class="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.<br>
+<br>
+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.<br>
+<br>
+If "num_conflicts" and "conflicts" are not <code>NULL</code>, they are set to
+contain the list of conflicting option/value pairs. Similarly, if
+"num_resolved" and "resolved" are not <code>NULL</code> they will be set to the
+list of changes needed to resolve the conflict.<br>
+<br>
+If cupsCopyDestConflicts returns 1 but "num_resolved" and "resolved" are set
+to 0 and <code>NULL</code>, respectively, then the conflict cannot be resolved.
+
+</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsCopyDestInfo">cupsCopyDestInfo</a></h3>
+<p class="description">Get the supported values/capabilities for the
+destination.</p>
+<p class="code">
+<a href="#cups_dinfo_t">cups_dinfo_t</a> *cupsCopyDestInfo (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Destination information</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The caller is responsible for calling <a href="#cupsFreeDestInfo"><code>cupsFreeDestInfo</code></a> on the return
+value. <code>NULL</code> is returned on error.
+
+</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsCreateDestJob">cupsCreateDestJob</a></h3>
+<p class="description">Create a job on a destination.</p>
+<p class="code">
+ipp_status_t cupsCreateDestJob (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *info,<br>
+ int *job_id,<br>
+ const char *title,<br>
+ int num_options,<br>
+ <a href="#cups_option_t">cups_option_t</a> *options<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>info</dt>
+<dd class="description">Destination information</dd>
+<dt>job_id</dt>
+<dd class="description">Job ID or 0 on error</dd>
+<dt>title</dt>
+<dd class="description">Job name</dd>
+<dt>num_options</dt>
+<dd class="description">Number of job options</dd>
+<dt>options</dt>
+<dd class="description">Job options</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">IPP status code</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">Returns <code>IPP_OK</code> or <code>IPP_OK_SUBST</code> on success, saving the job ID
+in the variable pointed to by "job_id".
+
</p>
<h3 class="function"><span class="info"> CUPS 1.4/OS X 10.6 </span><a name="cupsCreateJob">cupsCreateJob</a></h3>
<p class="description">Create an empty job for streaming.</p>
Enumeration happens on the current thread and does not return until all
destinations have been enumerated or the block returns 0.
+</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsFinishDestDocument">cupsFinishDestDocument</a></h3>
+<p class="description">Finish the current document.</p>
+<p class="code">
+ipp_status_t cupsFinishDestDocument (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *info<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>info</dt>
+<dd class="description">Destination information</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Status of document submission</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">Returns <code>IPP_OK</code> or <code>IPP_OK_SUBST</code> on success.
+
</p>
<h3 class="function"><span class="info"> CUPS 1.4/OS X 10.6 </span><a name="cupsFinishDocument">cupsFinishDocument</a></h3>
<p class="description">Finish sending a document.</p>
<p class="discussion">The document must have been started using <a href="#cupsStartDocument"><code>cupsStartDocument</code></a>.
</p>
+<h3 class="function"><a name="cupsFreeDestInfo">cupsFreeDestInfo</a></h3>
+<p class="description">Free destination information obtained using
+<a href="#cupsCopyDestInfo"><code>cupsCopyDestInfo</code></a>.</p>
+<p class="code">
+void cupsFreeDestInfo (<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *dinfo<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>dinfo</dt>
+<dd class="description">Destination information</dd>
+</dl>
<h3 class="function"><a name="cupsFreeDests">cupsFreeDests</a></h3>
<p class="description">Free the memory used by the list of destinations.</p>
<p class="code">
<h4 class="discussion">Discussion</h4>
<p class="discussion">Use the <a href="#cupsGetDests"><code>cupsGetDests</code></a> or <a href="#cupsGetDests2"><code>cupsGetDests2</code></a> functions to get a
list of supported destinations for the current user.</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsGetDestMediaByName">cupsGetDestMediaByName</a></h3>
+<p class="description">Get media names, dimensions, and margins.</p>
+<p class="code">
+int cupsGetDestMediaByName (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *dinfo,<br>
+ const char *media,<br>
+ unsigned flags,<br>
+ <a href="#cups_size_t">cups_size_t</a> *size<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>dinfo</dt>
+<dd class="description">Destination information</dd>
+<dt>media</dt>
+<dd class="description">Media name</dd>
+<dt>flags</dt>
+<dd class="description">Media matching flags</dd>
+<dt>size</dt>
+<dd class="description">Media size information</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on match, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The "media" string is a PWG media name. "Flags" provides some matching
+guidance (multiple flags can be combined):<br>
+<br>
+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.<br>
+<br>
+The matching result (if any) is returned in the "cups_size_t" structure.<br>
+<br>
+Returns 1 when there is a match and 0 if there is not a match.
+
+</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsGetDestMediaBySize">cupsGetDestMediaBySize</a></h3>
+<p class="description">Get media names, dimensions, and margins.</p>
+<p class="code">
+int cupsGetDestMediaBySize (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *dinfo,<br>
+ int width,<br>
+ int length,<br>
+ unsigned flags,<br>
+ <a href="#cups_size_t">cups_size_t</a> *size<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>dinfo</dt>
+<dd class="description">Destination information</dd>
+<dt>width</dt>
+<dd class="description">Media width in hundredths of
+of millimeters</dd>
+<dt>length</dt>
+<dd class="description">Media length in hundredths of
+of millimeters</dd>
+<dt>flags</dt>
+<dd class="description">Media matching flags</dd>
+<dt>size</dt>
+<dd class="description">Media size information</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">1 on match, 0 on failure</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">"Width" and "length" are the dimensions in hundredths of millimeters.
+"Flags" provides some matching guidance (multiple flags can be combined):<br>
+<br>
+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.<br>
+<br>
+The matching result (if any) is returned in the "cups_size_t" structure.<br>
+<br>
+Returns 1 when there is a match and 0 if there is not a match.
+
+</p>
<h3 class="function"><a name="cupsGetDests">cupsGetDests</a></h3>
<p class="description">Get the list of destinations from the default server.</p>
<p class="code">
</dl>
<h4 class="returnvalue">Return Value</h4>
<p class="description">Language data</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsLocalizeDestOption">cupsLocalizeDestOption</a></h3>
+<p class="description">Get the localized string for a destination
+option.</p>
+<p class="code">
+const char *cupsLocalizeDestOption (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *dinfo,<br>
+ const char *option<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>dinfo</dt>
+<dd class="description">Destination information</dd>
+<dt>option</dt>
+<dd class="description">Option to localize</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Localized string</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The returned string is stored in the destination information and will become
+invalid if the destination information is deleted.
+
+</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsLocalizeDestValue">cupsLocalizeDestValue</a></h3>
+<p class="description">Get the localized string for a destination
+option+value pair.</p>
+<p class="code">
+const char *cupsLocalizeDestValue (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *dinfo,<br>
+ const char *option,<br>
+ const char *value<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>dinfo</dt>
+<dd class="description">Destination information</dd>
+<dt>option</dt>
+<dd class="description">Option to localize</dd>
+<dt>value</dt>
+<dd class="description">Value to localize</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Localized string</p>
+<h4 class="discussion">Discussion</h4>
+<p class="discussion">The returned string is stored in the destination information and will become
+invalid if the destination information is deleted.
+
+</p>
<h3 class="function"><span class="info"> CUPS 1.2/OS X 10.5 </span><a name="cupsNotifySubject">cupsNotifySubject</a></h3>
<p class="description">Return the subject for the given notification message.</p>
<p class="code">
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.</p>
+<h3 class="function"><span class="info"> CUPS 1.6/OS X 10.8 </span><a name="cupsStartDestDocument">cupsStartDestDocument</a></h3>
+<p class="description">Start a new document.</p>
+<p class="code">
+http_status_t cupsStartDestDocument (<br>
+ http_t *http,<br>
+ <a href="#cups_dest_t">cups_dest_t</a> *dest,<br>
+ <a href="#cups_dinfo_t">cups_dinfo_t</a> *info,<br>
+ int job_id,<br>
+ const char *docname,<br>
+ const char *format,<br>
+ int num_options,<br>
+ <a href="#cups_option_t">cups_option_t</a> *options,<br>
+ int last_document<br>
+);</p>
+<h4 class="parameters">Parameters</h4>
+<dl>
+<dt>http</dt>
+<dd class="description">Connection to destination</dd>
+<dt>dest</dt>
+<dd class="description">Destination</dd>
+<dt>info</dt>
+<dd class="description">Destination information</dd>
+<dt>job_id</dt>
+<dd class="description">Job ID</dd>
+<dt>docname</dt>
+<dd class="description">Document name</dd>
+<dt>format</dt>
+<dd class="description">Document format</dd>
+<dt>num_options</dt>
+<dd class="description">Number of document options</dd>
+<dt>options</dt>
+<dd class="description">Document options</dd>
+<dt>last_document</dt>
+<dd class="description">1 if this is the last document</dd>
+</dl>
+<h4 class="returnvalue">Return Value</h4>
+<p class="description">Status of document creation</p>
+<h4 class="discussion">Discussion</h4>
+<p class="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
+<code>HTTP_CONTINUE</code> on success.
+
+</p>
<h3 class="function"><span class="info"> CUPS 1.4/OS X 10.6 </span><a name="cupsStartDocument">cupsStartDocument</a></h3>
<p class="description">Add a document to a job created with cupsCreateJob().</p>
<p class="code">
<li><a href="#cupsGetFd" title="Get a file from the server.">cupsGetFd</a></li>
<li><a href="#cupsGetFile" title="Get a file from the server.">cupsGetFile</a></li>
<li><a href="#cupsGetResponse" title="Get a response to an IPP request.">cupsGetResponse</a></li>
- <li><a href="#cupsLastError" title="Return the last IPP status code.">cupsLastError</a></li>
- <li><a href="#cupsLastErrorString" title="Return the last IPP status-message.">cupsLastErrorString</a></li>
+ <li><a href="#cupsLastError" title="Return the last IPP status code received on the current
+thread.">cupsLastError</a></li>
+ <li><a href="#cupsLastErrorString" title="Return the last IPP status-message received on the
+current thread.">cupsLastErrorString</a></li>
<li><a href="#cupsPutFd" title="Put a file on the server.">cupsPutFd</a></li>
<li><a href="#cupsPutFile" title="Put a file on the server.">cupsPutFile</a></li>
<li><a href="#cupsReadResponseData" title="Read additional data after the IPP response.">cupsReadResponseData</a></li>
<h4 class="returnvalue">Return Value</h4>
<p class="description">Response data</p>
<h4 class="discussion">Discussion</h4>
-<p class="discussion">This function sends the IPP request to the specified server, retrying
-and authenticating as necessary. The request is freed with <a href="#ippDelete"><code>ippDelete</code></a>
-after receiving a valid IPP response.</p>
+<p class="discussion">This function sends the IPP request and attached file to the specified
+server, retrying and authenticating as necessary. The request is freed with
+<a href="#ippDelete"><code>ippDelete</code></a>.</p>
<h3 class="function"><span class="info"> CUPS 1.3/OS X 10.5 </span><a name="cupsDoIORequest">cupsDoIORequest</a></h3>
<p class="description">Do an IPP request with file descriptors.</p>
<p class="code">
<h4 class="returnvalue">Return Value</h4>
<p class="description">Response data</p>
<h4 class="discussion">Discussion</h4>
-<p class="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.<br>
+<p class="discussion">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 <a href="#ippDelete"><code>ippDelete</code></a>.<br>
<br>
-If "infile" is a valid file descriptor, cupsDoIORequest() copies
+If "infile" is a valid file descriptor, <code>cupsDoIORequest</code> copies
all of the data from the file after the IPP request message.<br>
<br>
-If "outfile" is a valid file descriptor, cupsDoIORequest() copies
+If "outfile" is a valid file descriptor, <code>cupsDoIORequest</code> copies
all of the data after the IPP response message to the file.
</p>
<p class="description">Response data</p>
<h4 class="discussion">Discussion</h4>
<p class="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.</p>
+and authenticating as necessary. The request is freed with <a href="#ippDelete"><code>ippDelete</code></a>.</p>
<h3 class="function"><a name="cupsEncodeOptions">cupsEncodeOptions</a></h3>
<p class="description">Encode printer options into IPP attributes.</p>
<p class="code">
<p class="description">Response or <code>NULL</code> on HTTP error</p>
<h4 class="discussion">Discussion</h4>
<p class="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.
+<a href="#cupsSendRequest"><code>cupsSendRequest</code></a>. For requests that return additional data, use
+<a href="#cupsReadResponseData"><code>cupsReadResponseData</code></a> after getting a successful response,
+otherwise call <a href="#httpFlush"><code>httpFlush</code></a> to complete the response processing.
</p>
<h3 class="function"><a name="cupsLastError">cupsLastError</a></h3>
-<p class="description">Return the last IPP status code.</p>
+<p class="description">Return the last IPP status code received on the current
+thread.</p>
<p class="code">
ipp_status_t cupsLastError (void);</p>
<h4 class="returnvalue">Return Value</h4>
<p class="description">IPP status code from last request</p>
<h3 class="function"><span class="info"> CUPS 1.2/OS X 10.5 </span><a name="cupsLastErrorString">cupsLastErrorString</a></h3>
-<p class="description">Return the last IPP status-message.</p>
+<p class="description">Return the last IPP status-message received on the
+current thread.</p>
<p class="code">
const char *cupsLastErrorString (void);</p>
<h4 class="returnvalue">Return Value</h4>
<h4 class="returnvalue">Return Value</h4>
<p class="description">Bytes read, 0 on EOF, -1 on error</p>
<h4 class="discussion">Discussion</h4>
-<p class="discussion">This function is used after cupsGetResponse() to read the PPD or document
-files for CUPS_GET_PPD and CUPS_GET_DOCUMENT requests, respectively.
+<p class="discussion">This function is used after <a href="#cupsGetResponse"><code>cupsGetResponse</code></a> to read the PPD or document
+files from <code>CUPS_GET_PPD</code> and <code>CUPS_GET_DOCUMENT</code> requests,
+respectively.
</p>
<h3 class="function"><span class="info"> CUPS 1.4/OS X 10.6 </span><a name="cupsSendRequest">cupsSendRequest</a></h3>
<h4 class="returnvalue">Return Value</h4>
<p class="description">Initial HTTP status</p>
<h4 class="discussion">Discussion</h4>
-<p class="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.<br>
+<p class="discussion">Use <a href="#cupsWriteRequestData"><code>cupsWriteRequestData</code></a> to write any additional data (document, PPD
+file, etc.) for the request, <a href="#cupsGetResponse"><code>cupsGetResponse</code></a> to get the IPP response,
+and <a href="#cupsReadResponseData"><code>cupsReadResponseData</code></a> to read any additional data following the
+response. Only one request can be sent/queued at a time per <code>http_t</code>
+connection.<br>
+<br>
+Returns the initial HTTP status code, which will be <code>HTTP_CONTINUE</code>
+on a successful send of the request.<br>
<br>
-Unlike cupsDoFileRequest(), cupsDoIORequest(), and cupsDoRequest(), the
-request is not freed.
+Note: Unlike <a href="#cupsDoFileRequest"><code>cupsDoFileRequest</code></a>, <a href="#cupsDoIORequest"><code>cupsDoIORequest</code></a>, and
+<a href="#cupsDoRequest"><code>cupsDoRequest</code></a>, the request is NOT freed with <a href="#ippDelete"><code>ippDelete</code></a>.
</p>
<h3 class="function"><span class="info"> CUPS 1.4/OS X 10.6 </span><a name="cupsWriteRequestData">cupsWriteRequestData</a></h3>
<PRE>
socket://<i>ip-address-or-hostname</i>
-socket://<i>ip-address-or-hostname</i>/?waiteof=false
+socket://<i>ip-address-or-hostname</i>/?option=value
+socket://<i>ip-address-or-hostname</i>/?option=value&option=value
socket://<i>ip-address-or-hostname</i>:<i>port-number</i>
-socket://<i>ip-address-or-hostname</i>:<i>port-number</i>/?waiteof=false
+socket://<i>ip-address-or-hostname</i>:<i>port-number</i>/?option=value
+socket://<i>ip-address-or-hostname</i>:<i>port-number</i>/?option=value&option=value
</PRE>
+<P>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.</P>
+
+<P>The "snmp" option controls whether the <tt>socket</tt> backend queries for supply and page count information via SNMP.</P>
+
<P>The "waiteof" option controls whether the <tt>socket</tt> backend waits for the printer to complete the printing of the job. The default is to wait.</P>
<H3><A NAME="IPP">Internet Printing Protocol (IPP)</A></H3>
-<P>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 <tt>http</tt> and <tt>ipp</tt> URI schemes:</P>
+<P>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 <tt>http</tt>, <tt>ipp</tt>, and <tt>ipps</tt> URI schemes:</P>
<PRE>
http://<i>ip-address-or-hostname</i>:<i>port-number</i>/<i>resource</i>
ipp://<i>ip-address-or-hostname</i>:<i>port-number</i>/<i>resource</i>
ipp://<i>ip-address-or-hostname</i>:<i>port-number</i>/<i>resource</i>?<i>option=value</i>
ipp://<i>ip-address-or-hostname</i>:<i>port-number</i>/<i>resource</i>?<i>option=value&option=value</i>
+ipps://<i>ip-address-or-hostname</i>/<i>resource</i>
+ipps://<i>ip-address-or-hostname</i>/<i>resource</i>?<i>option=value</i>
+ipps://<i>ip-address-or-hostname</i>/<i>resource</i>?<i>option=value&option=value</i>
+ipps://<i>ip-address-or-hostname</i>:<i>port-number</i>/<i>resource</i>
+ipps://<i>ip-address-or-hostname</i>:<i>port-number</i>/<i>resource</i>?<i>option=value</i>
+ipps://<i>ip-address-or-hostname</i>:<i>port-number</i>/<i>resource</i>?<i>option=value&option=value</i>
</PRE>
<P>The <tt>ipp</tt> backend supports many options, which are summarized in <A HREF="#TABLE2">Table 2</A>.</P>
<TD><TT>encryption=required</TT></TD>
<TD>Specifies that the connection to the IPP server should be encrypted using TLS.</TD>
</TR>
+<TR>
+ <TD><TT>snmp=false</TT></TD>
+ <TD>Specifies that SNMP supply and page count queries should not be performed.</TD>
+</TR>
<TR>
<TD><TT>version=1.0</TT></TD>
- <TD>Specifies that version 1.0 of the IPP protocol should be used instead of the default version 1.1.</TD>
+ <TD>Specifies that version 1.0 of the IPP protocol should be used instead of the default version 2.0.</TD>
</TR>
<TR>
- <TD><TT>version=2.0</TT></TD>
- <TD>Specifies that version 2.0 of the IPP protocol should be used instead of the default version 1.1.</TD>
+ <TD><TT>version=1.1</TT></TD>
+ <TD>Specifies that version 1.1 of the IPP protocol should be used instead of the default version 2.0.</TD>
</TR>
<TR>
<TD><TT>version=2.1</TT></TD>
- <TD>Specifies that version 2.1 of the IPP protocol should be used instead of the default version 1.1.</TD>
+ <TD>Specifies that version 2.1 of the IPP protocol should be used instead of the default version 2.0.</TD>
</TR>
<TR>
<TD><TT>waitjob=false</TT></TD>
<TD><TT>sanitize_title=yes</TT></TD>
<TD>Specifies that the job title string should be restricted to ASCII characters.</TD>
</TR>
+<TR>
+ <TD><TT>snmp=false</TT></TD>
+ <TD>Specifies that SNMP supply and page count queries should not be performed.</TD>
+</TR>
<TR>
<TD><TT>timeout=<I>seconds</I></TT></TD>
<TD>Specifies the number of seconds to wait for LPD commands to complete.</TD>
<li><a href="#cupsIPPFinishings">cupsIPPFinishings</a></li>
<li><a href="#cupsIPPReason">cupsIPPReason</a></li>
<li><a href="#cupsIPPSupplies">cupsIPPSupplies</a></li>
+ <li><a href="#cupsJobAccountId">cupsJobAccountId</a></li>
+ <li><a href="#cupsJobAccountingUserId">cupsJobAccountingUserId</a></li>
+ <li><a href="#cupsJobPassword">cupsJobPassword</a></li>
<li><a href="#cupsLanguages">cupsLanguages</a></li>
+ <li><a href="#cupsMandatory">cupsMandatory</a></li>
<li><a href="#cupsManualCopies">cupsManualCopies</a></li>
<li><a href="#cupsMarkerName">cupsMarkerName</a></li>
<li><a href="#cupsMarkerNotice">cupsMarkerNotice</a></li>
*cupsIPPSupplies: False
</pre>
+
+<h3><span class='info'>CUPS 1.7</span><a name='cupsJobAccountId'>cupsJobAccountId</a></h3>
+
+<p class='summary'>*cupsJobAccountId: boolean</p>
+
+<p>This keyword defines whether the printer accepts the job-account-id IPP attribute.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify the printer accepts the job-account-id IPP attribute.</em>
+*cupsJobAccountId: True
+</pre>
+
+
+<h3><span class='info'>CUPS 1.7</span><a name='cupsJobAccountingUserId'>cupsJobAccountingUserId</a></h3>
+
+<p class='summary'>*cupsJobAccountingUserId: boolean</p>
+
+<p>This keyword defines whether the printer accepts the job-accounting-user-id IPP attribute.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify the printer accepts the job-accounting-user-id IPP attribute.</em>
+*cupsJobAccountingUserId: True
+</pre>
+
+
+<h3><span class='info'>CUPS 1.7</span><a name='cupsJobPassword'>cupsJobPassword</a></h3>
+
+<p class='summary'>*cupsJobPassword: "format"</p>
+
+<p>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.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify the printer supports 4-digit PIN codes.</em>
+*cupsJobPassword: "1111"
+</pre>
+
+
<h3><span class='info'>CUPS 1.2/OS X 10.5</span><a name='cupsLanguages'>cupsLanguages</a></h3>
<p class='summary'>*cupsLanguages: "locale list"</p>
*cupsLanguages: "en_CA en_UK en_US fr_CA fr_FR"
</pre>
+
+<h3><span class='info'>CUPS 1.7</span><a name='cupsMandatory'>cupsMandatory</a></h3>
+
+<p class='summary'>*cupsMandatory: "attribute1 attribute2 ... attributeN"</p>
+
+<p>This keyword defines a list of IPP attributes that must be provided when submitting a print job creation request.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify that the user must supply a job-password</em>
+*cupsMandatory: "job-password job-password-encryption"
+</pre>
+
+
<h3><a name='cupsManualCopies'>cupsManualCopies</a></h3>
<p class='summary'>*cupsManualCopies: boolean</p>
<h2 class='title'><a name='HISTORY'>Change History</a></h2>
+<h3>Changes in CUPS 1.7</h3>
+
+<ul>
+
+ <li>Added <a href="#cupsJobAccountId"><tt>cupsJobAccountId</tt></a>,
+ <a href="#cupsJobAccountingUserId"><tt>cupsJobAccountingUserId</tt></a>,
+ <a href="#cupsJobPassword"><tt>cupsJobPassword</tt></a>,
+ <a href="#cupsMandatory"><tt>cupsMandatory</tt></a> keywords.</li>
+
+</ul>
+
+
<h3>Changes in CUPS 1.6</h3>
<ul>
h->cupsImagingBBox[2] = 612.0f;
h->cupsImagingBBox[3] = 792.0f;
- strcpy(h->cupsPageSizeName, "Letter");
+ strlcpy(h->cupsPageSizeName, "Letter", sizeof(h->cupsPageSizeName));
#ifdef __APPLE__
/*
*/
#include <cups/raster-private.h>
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif /* HAVE_STDINT_H */
/*
*cupsIPPSupplies: False
</pre>
+
+<h3><span class='info'>CUPS 1.7</span><a name='cupsJobAccountId'>cupsJobAccountId</a></h3>
+
+<p class='summary'>*cupsJobAccountId: boolean</p>
+
+<p>This keyword defines whether the printer accepts the job-account-id IPP attribute.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify the printer accepts the job-account-id IPP attribute.</em>
+*cupsJobAccountId: True
+</pre>
+
+
+<h3><span class='info'>CUPS 1.7</span><a name='cupsJobAccountingUserId'>cupsJobAccountingUserId</a></h3>
+
+<p class='summary'>*cupsJobAccountingUserId: boolean</p>
+
+<p>This keyword defines whether the printer accepts the job-accounting-user-id IPP attribute.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify the printer accepts the job-accounting-user-id IPP attribute.</em>
+*cupsJobAccountingUserId: True
+</pre>
+
+
+<h3><span class='info'>CUPS 1.7</span><a name='cupsJobPassword'>cupsJobPassword</a></h3>
+
+<p class='summary'>*cupsJobPassword: "format"</p>
+
+<p>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.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify the printer supports 4-digit PIN codes.</em>
+*cupsJobPassword: "1111"
+</pre>
+
+
<h3><span class='info'>CUPS 1.2/OS X 10.5</span><a name='cupsLanguages'>cupsLanguages</a></h3>
<p class='summary'>*cupsLanguages: "locale list"</p>
*cupsLanguages: "en_CA en_UK en_US fr_CA fr_FR"
</pre>
+
+<h3><span class='info'>CUPS 1.7</span><a name='cupsMandatory'>cupsMandatory</a></h3>
+
+<p class='summary'>*cupsMandatory: "attribute1 attribute2 ... attributeN"</p>
+
+<p>This keyword defines a list of IPP attributes that must be provided when submitting a print job creation request.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% Specify that the user must supply a job-password</em>
+*cupsMandatory: "job-password job-password-encryption"
+</pre>
+
+
<h3><a name='cupsManualCopies'>cupsManualCopies</a></h3>
<p class='summary'>*cupsManualCopies: boolean</p>
<h2 class='title'><a name='HISTORY'>Change History</a></h2>
+<h3>Changes in CUPS 1.7</h3>
+
+<ul>
+
+ <li>Added <a href="#cupsJobAccountId"><tt>cupsJobAccountId</tt></a>,
+ <a href="#cupsJobAccountingUserId"><tt>cupsJobAccountingUserId</tt></a>,
+ <a href="#cupsJobPassword"><tt>cupsJobPassword</tt></a>,
+ <a href="#cupsMandatory"><tt>cupsMandatory</tt></a> keywords.</li>
+
+</ul>
+
+
<h3>Changes in CUPS 1.6</h3>
<ul>
* 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
}
if (*s)
- strcpy(bufptr, "...");
+ memcpy(bufptr, "...", 4);
else
*bufptr = '\0';
* 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)
msgstr = temp;
- strcpy(msgstr + length, ptr);
+ memcpy(msgstr + length, ptr, ptrlen + 1);
}
else
{
msgid = temp;
- strcpy(msgid + length, ptr);
+ memcpy(msgid + length, ptr, ptrlen + 1);
}
}
else if (!strncmp(s, "msgstr", 6) && msgid)
*
* 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 <twaugh@redhat.com>
* Copyright 1997-2005 by Easy Software Products.
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))
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))
while (isspace(*ptr))
ptr ++;
- strcpy(program, ptr);
+ strlcpy(program, ptr, sizeof(program));
}
else
{
if ((baseptr = strrchr(basedir, '/')) != NULL)
*baseptr = '\0';
else
- strcpy(basedir, ".");
+ strlcpy(basedir, ".", sizeof(basedir));
// Find the po file...
pofilename[0] = '\0';
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)))
//
// 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
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;
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
if (sscanf(authorization, "%255s", scheme) != 1)
- strcpy(scheme, "UNKNOWN");
+ strlcpy(scheme, "UNKNOWN", sizeof(scheme));
cupsdLogMessage(CUPSD_LOG_ERROR,
"[Client %d] Bad authentication data \"%s ...\"",
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 */
* con->uri are HTTP_MAX_URI bytes in size...
*/
- strcpy(con->uri, resource);
+ strlcpy(con->uri, resource, sizeof(con->uri));
}
/*
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);
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);
* the POSIX locale...
*/
- strcpy(lang, "LANG=C");
+ strlcpy(lang, "LANG=C", sizeof(lang));
break;
case 2 :
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);
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);
}
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[^\"]\""
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;
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);
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...
* Unknown language; use "xx"...
*/
- strcpy(lang_version, "xx");
+ strlcpy(lang_version, "xx", sizeof(lang_version));
}
/*
* 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);
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
{
break;
}
- strcpy(filename, control);
+ strlcpy(filename, control, sizeof(filename));
}
break;
break;
}
- strcpy(filename, temp[num_data]);
+ strlcpy(filename, temp[num_data], sizeof(filename));
num_data ++;
break;
{
syslog(LOG_WARNING, "No username specified by client! "
"Using \"anonymous\"...");
- strcpy(user, "anonymous");
+ strlcpy(user, "anonymous", sizeof(user));
}
/*
*/
if (jobstate == IPP_JOB_PROCESSING)
- strcpy(rankstr, "active");
+ strlcpy(rankstr, "active", sizeof(rankstr));
else
{
snprintf(rankstr, sizeof(rankstr), "%d%s", rank, ranks[rank % 10]);
if (sptr > s)
*sptr++ = ' ';
- strcpy(sptr, option->name);
+ strlcpy(sptr, option->name, bytes - (sptr - s));
sptr += strlen(sptr);
*sptr++ = '=';
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 */
# 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 */
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 */
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))",
/*
* 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))
{
* 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"))
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));
* 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"))
break;
case IPP_TAG_NAME :
+ case IPP_TAG_TEXT :
case IPP_TAG_KEYWORD :
case IPP_TAG_URI :
printer->num_options = cupsAddOption(name,
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,
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 */
)
{
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);
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;
}
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);
}
}
+ /*
+ * 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?
*/
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__ */
* the POSIX locale...
*/
- strcpy(lang, "LANG=C");
+ strlcpy(lang, "LANG=C", sizeof(lang));
break;
case 2 :
* 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);
}
}
"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;
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;
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);
}
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)
{
*
* 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
cupsFileClose(*lf);
- strcpy(backname, filename);
+ strlcpy(backname, filename, sizeof(backname));
strlcat(backname, ".O", sizeof(backname));
unlink(backname);
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)
if (!PageLogFormat)
return (1);
- strcpy(number, "1");
+ strlcpy(number, "1", sizeof(number));
copies = 1;
sscanf(page, "%255s%d", number, &copies);
*
* 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
filter ? filter->dst->super : "???",
filter ? filter->cost : -1,
filter ? CUPS_LLCAST filter->maxsize : CUPS_LLCAST -1));
-
+
if (!mime || !filter)
return;
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;
}
* Force * / * to be "application/octet-stream"...
*/
- strcpy(super, "application");
- strcpy(type, "octet-stream");
+ strlcpy(super, "application", sizeof(super));
+ strlcpy(type, "octet-stream", sizeof(type));
}
/*
"multiple-document-handling",
"number-up",
"output-bin",
- "output-mode",
"orientation-requested",
"page-ranges",
+ "print-color-mode",
"print-quality",
"printer-resolution",
"sides"
"multiple-document-handling",
"number-up",
"output-bin",
- "output-mode",
"orientation-requested",
"page-ranges",
+ "print-color-mode",
"print-quality",
"printer-resolution",
"sides"
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"));
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",
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)
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,
}
/*
- * 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...
*/
*
* 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
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 :
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);
*
* 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
if (!s || !*s)
return (NULL);
else
- return (_cupsArrayNewStrings(s));
+ return (_cupsArrayNewStrings(s, ','));
}
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)
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)
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)
*/
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",
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",
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 */
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 */
make = argv[i];
break;
+ case 'P' : /* -P (PIN printing mode) */
+ pin = 1;
+ break;
+
case 'd' : /* -d spool-directory */
i ++;
if (i >= argc)
*/
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 */
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 */
{ /* 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",
"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",
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);
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);
}
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);
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("<data>%s</data>\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 :
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
#
<HTML>
<HEAD>
<META NAME="Description" CONTENT="CUPS Test Report">
- <META NAME="COPYRIGHT" CONTENT="Copyright 2007-2011, All Rights Reserved">
- <META NAME="DOCNUMBER" CONTENT="CUPS-STR-1.6">
+ <META NAME="COPYRIGHT" CONTENT="Copyright 2007-2012, All Rights Reserved">
+ <META NAME="DOCNUMBER" CONTENT="CUPS-STR-1.7">
<META NAME="Author" CONTENT="Apple Inc.">
- <TITLE>CUPS 1.5 Software Test Report</TITLE>
+ <TITLE>CUPS 1.7 Software Test Report</TITLE>
<STYLE TYPE="text/css"><!--
PRE {
font-size: 80%;
</HEAD>
<BODY>
-<H1>CUPS 1.6 Software Test Report</H1>
+<H1>CUPS 1.7 Software Test Report</H1>
<P>This software test report provides detailed test results that
-are used to evaluate the stability and compliance of CUPS Version 1.6.
+are used to evaluate the stability and compliance of CUPS Version 1.7.
<H2>Document Overview</H2>