From: msweet Date: Mon, 14 Mar 2011 18:45:10 +0000 (+0000) Subject: Merge changes from CUPS 1.5svn-r9602. X-Git-Tag: release-1.6.3~53 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;ds=sidebyside;h=f14324a7920bee90b63469ce754e8040933f38e1;p=thirdparty%2Fcups.git Merge changes from CUPS 1.5svn-r9602. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@3046 a1ca3aef-8c08-0410-bb20-df032aa958be --- diff --git a/CHANGES-1.4.txt b/CHANGES-1.4.txt index 3259a2970..612a85a01 100644 --- a/CHANGES-1.4.txt +++ b/CHANGES-1.4.txt @@ -9,6 +9,15 @@ CHANGES IN CUPS V1.4.7 STR #3755, STR #3769, STR #3783) - Configure script fixes (STR #3659, STR #3691) - Compilation fixes (STR #3718, STR #3771, STR #3774) + - Fixed an issue when reading compressed CUPS raster streams (STR #3812) + - Fixed an issue with PostScript printer auto-configuration (STR #3443) + - Fixed some compatibility issues with the libusb-based USB backend + (STR #3799) + - The network backends no longer try to collect SNMP supply and status + information for raw queues (STR #3809) + - The DBUS notifier did not report job state changes (STR #3805) + - The scheduler did not always report that the "normal" print-quality + value was supported (STR #3803) - The gziptoany filter did not report the correct error if it was unable to write the uncompressed document to the next filter or backend in the chain (STR #3797) diff --git a/CHANGES.txt b/CHANGES.txt index 662d77602..a5c3bdd4b 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,9 @@ -CHANGES.txt - 2011-02-21 +CHANGES.txt - 2011-03-07 ------------------------ CHANGES IN CUPS V1.5b1 + - Dropped support for the printer-state-history attribute (STR #3654) - Added support for a new cupsIPPSupplies keyword in PPD files to allow drivers to disable IPP supply level reporting. - Added support for a new cupsFilter2 keyword in PPD files to allow for diff --git a/backend/backend-private.h b/backend/backend-private.h index 47f9b32ce..592b1e340 100644 --- a/backend/backend-private.h +++ b/backend/backend-private.h @@ -3,7 +3,7 @@ * * Backend support definitions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -309,7 +309,7 @@ extern int backendSNMPSupplies(int snmp_fd, http_addr_t *addr, int *page_count, int *printer_state); extern int backendWaitLoop(int snmp_fd, http_addr_t *addr, - _cups_sccb_t side_cb); + int use_bc, _cups_sccb_t side_cb); # ifdef __cplusplus diff --git a/backend/ipp.c b/backend/ipp.c index fb172cd2d..1f5bb8e18 100644 --- a/backend/ipp.c +++ b/backend/ipp.c @@ -115,7 +115,7 @@ static ipp_t *new_request(ipp_op_t op, int version, const char *uri, const char *user, const char *title, int num_options, cups_option_t *options, const char *compression, int copies, - const char *format, _pwg_t *pwg, + const char *format, _ppd_cache_t *pc, ipp_attribute_t *media_col_sup); static const char *password_cb(const char *); static void report_attr(ipp_attribute_t *attr); @@ -167,7 +167,8 @@ main(int argc, /* I - Number of command-line args */ *supported; /* get-printer-attributes response */ time_t start_time; /* Time of first connect */ int contimeout; /* Connection timeout */ - int delay; /* Delay for retries... */ + int delay, /* Delay for retries */ + prev_delay; /* Previous delay */ const char *compression; /* Compression mode */ int waitjob, /* Wait for job complete? */ waitprinter; /* Wait for printer ready? */ @@ -197,7 +198,7 @@ main(int argc, /* I - Number of command-line args */ #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ int version; /* IPP version */ ppd_file_t *ppd; /* PPD file */ - _pwg_t *pwg; /* PWG<->PPD mapping data */ + _ppd_cache_t *pc; /* PPD cache and mapping data */ /* @@ -548,14 +549,14 @@ main(int argc, /* I - Number of command-line args */ */ if (num_files == 0) - if (!backendWaitLoop(snmp_fd, &(addrlist->addr), backendNetworkSideCB)) + if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB)) return (CUPS_BACKEND_OK); /* * Try connecting to the remote server... */ - delay = 5; + delay = _cupsNextDelay(0, &prev_delay); do { @@ -634,8 +635,7 @@ main(int argc, /* I - Number of command-line args */ sleep(delay); - if (delay < 30) - delay += 5; + delay = _cupsNextDelay(delay, &prev_delay); } else { @@ -759,8 +759,7 @@ main(int argc, /* I - Number of command-line args */ sleep(delay); - if (delay < 30) - delay += 5; + delay = _cupsNextDelay(delay, &prev_delay); } else if ((ipp_status == IPP_BAD_REQUEST || ipp_status == IPP_VERSION_NOT_SUPPORTED) && version > 10) @@ -946,7 +945,7 @@ main(int argc, /* I - Number of command-line args */ { copies_remaining = 1; - if (argc < 7) + if (argc < 7 && !send_options) copies = 1; } else @@ -957,7 +956,7 @@ main(int argc, /* I - Number of command-line args */ */ options = NULL; - pwg = NULL; + pc = NULL; if (send_options) { @@ -970,7 +969,7 @@ main(int argc, /* I - Number of command-line args */ */ ppd = ppdOpenFile(getenv("PPD")); - pwg = _pwgCreateWithPPD(ppd); + pc = _ppdCacheCreateWithPPD(ppd); ppdClose(ppd); } @@ -1026,7 +1025,7 @@ main(int argc, /* I - Number of command-line args */ { request = new_request(IPP_VALIDATE_JOB, version, uri, argv[2], argv[3], num_options, options, compression, - copies_sup ? copies : 1, document_format, pwg, + copies_sup ? copies : 1, document_format, pc, media_col_sup); ippDelete(cupsDoRequest(http, request, resource)); @@ -1102,7 +1101,7 @@ main(int argc, /* I - Number of command-line args */ request = new_request(num_files > 1 ? IPP_CREATE_JOB : IPP_PRINT_JOB, version, uri, argv[2], argv[3], num_options, options, compression, copies_sup ? copies : 1, document_format, - pwg, media_col_sup); + pc, media_col_sup); /* * Do the request... @@ -1299,7 +1298,7 @@ main(int argc, /* I - Number of command-line args */ _cupsLangPrintFilter(stderr, "INFO", _("Waiting for job to complete.")); - for (delay = 1; !job_canceled;) + for (delay = _cupsNextDelay(0, &prev_delay); !job_canceled;) { /* * Check for side-channel requests... @@ -1333,6 +1332,7 @@ main(int argc, /* I - Number of command-line args */ * Do the request... */ + httpReconnect(http); response = cupsDoRequest(http, request, resource); ipp_status = cupsLastError(); @@ -1400,23 +1400,13 @@ main(int argc, /* I - Number of command-line args */ ippDelete(response); -#if 0 /* - * Check the printer state and report it if necessary... - */ - - check_printer_state(http, uri, resource, argv[2], version, job_id); -#endif /* 0 */ - - /* - * Wait 1-10 seconds before polling again... + * Wait before polling again... */ sleep(delay); - delay ++; - if (delay > 10) - delay = 1; + delay = _cupsNextDelay(delay, &prev_delay); } } @@ -1458,7 +1448,7 @@ main(int argc, /* I - Number of command-line args */ cleanup: cupsFreeOptions(num_options, options); - _pwgDestroy(pwg); + _ppdCacheDestroy(pc); httpClose(http); @@ -1480,7 +1470,9 @@ main(int argc, /* I - Number of command-line args */ * Return the queue status... */ - fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required); + if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN || + ipp_status <= IPP_OK_CONFLICT) + fprintf(stderr, "ATTR: auth-info-required=%s\n", auth_info_required); if (ipp_status == IPP_NOT_AUTHORIZED || ipp_status == IPP_FORBIDDEN) return (CUPS_BACKEND_AUTH_REQUIRED); @@ -1679,8 +1671,7 @@ monitor_printer( *response; /* IPP response */ ipp_attribute_t *attr; /* Attribute in response */ int delay, /* Current delay */ - prev_delay, /* Previous delay */ - temp_delay; /* Temporary delay value */ + prev_delay; /* Previous delay */ /* @@ -1695,8 +1686,7 @@ monitor_printer( * Loop until the job is canceled, aborted, or completed. */ - delay = 1; - prev_delay = 0; + delay = _cupsNextDelay(0, &prev_delay); while (monitor->job_state < IPP_JOB_CANCELED && !job_canceled) { @@ -1762,15 +1752,12 @@ monitor_printer( } /* - * Sleep for N seconds, and then update the next sleep time using a - * Fibonacci series (1 1 2 3 5 8)... + * Sleep for N seconds... */ sleep(delay); - temp_delay = delay; - delay = (delay + prev_delay) % 12; - prev_delay = delay < temp_delay ? 0 : temp_delay; + delay = _cupsNextDelay(delay, &prev_delay); } /* @@ -1799,7 +1786,7 @@ new_request( const char *compression, /* I - compression value or NULL */ int copies, /* I - copies value or 0 */ const char *format, /* I - documet-format value or NULL */ - _pwg_t *pwg, /* I - PWG<->PPD mapping data */ + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ ipp_attribute_t *media_col_sup) /* I - media-col-supported values */ { int i; /* Looping var */ @@ -1869,7 +1856,7 @@ new_request( if (num_options > 0) { - if (pwg) + if (pc) { /* * Send standard IPP attributes... @@ -1878,7 +1865,7 @@ new_request( if ((keyword = cupsGetOption("PageSize", num_options, options)) == NULL) keyword = cupsGetOption("media", num_options, options); - if ((size = _pwgGetSize(pwg, keyword)) != NULL) + if ((size = _ppdCacheGetSize(pc, keyword)) != NULL) { /* * Add a media-col value... @@ -1893,11 +1880,12 @@ new_request( media_col = ippNew(); ippAddCollection(media_col, IPP_TAG_ZERO, "media-size", media_size); - media_source = _pwgGetSource(pwg, cupsGetOption("InputSlot", - num_options, - options)); - media_type = _pwgGetType(pwg, cupsGetOption("MediaType", - num_options, options)); + media_source = _ppdCacheGetSource(pc, cupsGetOption("InputSlot", + num_options, + options)); + media_type = _ppdCacheGetType(pc, cupsGetOption("MediaType", + num_options, + options)); for (i = 0; i < media_col_sup->num_values; i ++) { @@ -1932,8 +1920,8 @@ new_request( if ((keyword = cupsGetOption("output-bin", num_options, options)) == NULL) - keyword = _pwgGetBin(pwg, cupsGetOption("OutputBin", num_options, - options)); + keyword = _ppdCacheGetBin(pc, cupsGetOption("OutputBin", num_options, + options)); if (keyword) ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "output-bin", @@ -1975,17 +1963,17 @@ new_request( if ((keyword = cupsGetOption("sides", num_options, options)) != NULL) ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, keyword); - else if (pwg->sides_option && - (keyword = cupsGetOption(pwg->sides_option, num_options, + else if (pc->sides_option && + (keyword = cupsGetOption(pc->sides_option, num_options, options)) != NULL) { - if (!strcasecmp(keyword, pwg->sides_1sided)) + if (!strcasecmp(keyword, pc->sides_1sided)) ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, "one-sided"); - else if (!strcasecmp(keyword, pwg->sides_2sided_long)) + else if (!strcasecmp(keyword, pc->sides_2sided_long)) ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, "two-sided-long-edge"); - if (!strcasecmp(keyword, pwg->sides_2sided_short)) + if (!strcasecmp(keyword, pc->sides_2sided_short)) ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "sides", NULL, "two-sided-short-edge"); } diff --git a/backend/lpd.c b/backend/lpd.c index 702c0fb9d..af690adb0 100644 --- a/backend/lpd.c +++ b/backend/lpd.c @@ -431,7 +431,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ */ if (argc == 6) - if (!backendWaitLoop(snmp_fd, &(addrlist->addr), backendNetworkSideCB)) + if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 0, backendNetworkSideCB)) return (CUPS_BACKEND_OK); /* diff --git a/backend/network.c b/backend/network.c index 0a4908a77..fb42f791f 100644 --- a/backend/network.c +++ b/backend/network.c @@ -1,9 +1,9 @@ /* * "$Id$" * - * Common network APIs for the Common UNIX Printing System (CUPS). + * Common backend network APIs for CUPS. * - * Copyright 2007-2009 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 2006-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -279,6 +279,12 @@ backendNetworkSideCB( break; } + case CUPS_SC_CMD_GET_CONNECTED : + status = CUPS_SC_STATUS_OK; + data[0] = device_fd != -1; + datalen = 1; + break; + default : status = CUPS_SC_STATUS_NOT_IMPLEMENTED; datalen = 0; diff --git a/backend/pseudo b/backend/pseudo new file mode 100644 index 000000000..3a82a522a --- /dev/null +++ b/backend/pseudo @@ -0,0 +1,30 @@ +#!/bin/sh +# +# "$Id$" +# +# Psuedo-backend for CUPS testing purposes. +# +# Copyright 2011 by Apple Inc. +# +# These coded instructions, statements, and computer programs are the +# property of Apple Inc. and are protected by Federal copyright +# law. Distribution and use rights are outlined in the file "LICENSE.txt" +# which should have been included with this file. If this file is +# file is missing or damaged, see the license at "http://www.cups.org/". +# +# This file is subject to the Apple OS-Developed Software exception. +# + +if test $# = 0; then + echo 'direct pseudo:///deskjet "HP DeskJet" "HP DeskJet (pseudo)" "MFG:HP;MDL:DeskJet;CMD:PCL;" "Nowhere"' + echo 'direct pseudo:///laserjet "HP LaserJet" "HP LaserJet (pseudo)" "MFG:HP;MDL:LaserJet;CMD:PCL;" "Nowhere"' + exit 0 +fi + +cat $6 >/dev/null +sleep 5 +exit 0 + +# +# End of "$Id$". +# diff --git a/backend/runloop.c b/backend/runloop.c index fbc5a467f..43b839996 100644 --- a/backend/runloop.c +++ b/backend/runloop.c @@ -431,6 +431,7 @@ int /* O - 1 if data is ready, 0 if not */ backendWaitLoop( int snmp_fd, /* I - SNMP socket or -1 if none */ http_addr_t *addr, /* I - Address of device */ + int use_bc, /* I - Use back-channel? */ _cups_sccb_t side_cb) /* I - Side-channel callback */ { fd_set input; /* Input set for reading */ @@ -494,7 +495,7 @@ backendWaitLoop( * loop since it may have read from print_fd... */ - if ((*side_cb)(0, -1, snmp_fd, addr, 0)) + if ((*side_cb)(0, -1, snmp_fd, addr, use_bc)) side_cb = NULL; continue; } diff --git a/backend/snmp-supplies.c b/backend/snmp-supplies.c index 990e54982..d6d8ae1b9 100644 --- a/backend/snmp-supplies.c +++ b/backend/snmp-supplies.c @@ -474,9 +474,9 @@ backend_init_supplies( * See if we should be getting supply levels via SNMP... */ - if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL && - (ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL && - ppdattr->value && strcasecmp(ppdattr->value, "true")) + if ((ppd = ppdOpenFile(getenv("PPD"))) == NULL || + ((ppdattr = ppdFindAttr(ppd, "cupsSNMPSupplies", NULL)) != NULL && + ppdattr->value && strcasecmp(ppdattr->value, "true"))) { ppdClose(ppd); return; diff --git a/backend/socket.c b/backend/socket.c index 7d9196b98..414955948 100644 --- a/backend/socket.c +++ b/backend/socket.c @@ -286,8 +286,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ if ((snmp_fd = _cupsSNMPOpen(addrlist->addr.addr.sa_family)) >= 0) { - have_supplies = !backendSNMPSupplies(snmp_fd, &(addr->addr), &start_count, - NULL); + have_supplies = !backendSNMPSupplies(snmp_fd, &(addrlist->addr), + &start_count, NULL); } else have_supplies = start_count = 0; @@ -297,7 +297,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ */ if (print_fd == 0) - if (!backendWaitLoop(snmp_fd, &(addrlist->addr), backendNetworkSideCB)) + if (!backendWaitLoop(snmp_fd, &(addrlist->addr), 1, backendNetworkSideCB)) return (CUPS_BACKEND_OK); /* @@ -393,7 +393,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ #ifdef AF_INET6 if (addr->addr.addr.sa_family == AF_INET6) - fprintf(stderr, "DEBUG: Connected to [%s]:%d (IPv6)...\n", + fprintf(stderr, "DEBUG: Connected to [%s]:%d (IPv6)...\n", httpAddrString(&addr->addr, addrname, sizeof(addrname)), ntohs(addr->addr.ipv6.sin6_port)); else @@ -419,8 +419,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ lseek(print_fd, 0, SEEK_SET); } - tbytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addr->addr), 1, 0, - backendNetworkSideCB); + tbytes = backendRunLoop(print_fd, device_fd, snmp_fd, &(addrlist->addr), 1, + 0, backendNetworkSideCB); if (print_fd != 0 && tbytes >= 0) _cupsLangPrintFilter(stderr, "INFO", _("Print file sent.")); @@ -454,8 +454,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ * Collect the final page count as needed... */ - if (have_supplies && - !backendSNMPSupplies(snmp_fd, &(addr->addr), &page_count, NULL) && + if (have_supplies && + !backendSNMPSupplies(snmp_fd, &(addrlist->addr), &page_count, NULL) && page_count > start_count) fprintf(stderr, "PAGE: total %d\n", page_count - start_count); diff --git a/backend/usb-libusb.c b/backend/usb-libusb.c index 2c2d73e56..08af5997a 100644 --- a/backend/usb-libusb.c +++ b/backend/usb-libusb.c @@ -411,7 +411,7 @@ get_device_id(usb_printer_t *printer, /* I - Printer */ if (usb_control_msg(printer->handle, USB_TYPE_CLASS | USB_ENDPOINT_IN | USB_RECIP_INTERFACE, - 0, printer->conf, printer->iface, + 0, printer->conf, (printer->iface << 8) | printer->altset, buffer, bufsize, 5000) < 0) { *buffer = '\0'; @@ -675,6 +675,7 @@ open_device(usb_printer_t *printer, /* I - Printer */ goto error; } +#if 0 /* STR #3801: Claiming interface 0 causes problems with some printers */ if (number != 0) while (usb_claim_interface(printer->handle, 0) < 0) { @@ -685,6 +686,7 @@ open_device(usb_printer_t *printer, /* I - Printer */ goto error; } +#endif /* 0 */ /* * Set alternate setting... diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c index c38352a6b..05fa23b38 100644 --- a/cgi-bin/admin.c +++ b/cgi-bin/admin.c @@ -1026,7 +1026,7 @@ do_am_printer(http_t *http, /* I - HTTP connection */ fputs("DEBUG: Getting list of devices...\n", stderr); current_device = 0; - if (cupsGetDevices(http, 30, CUPS_INCLUDE_ALL, CUPS_EXCLUDE_NONE, + if (cupsGetDevices(http, 5, CUPS_INCLUDE_ALL, CUPS_EXCLUDE_NONE, (cups_device_cb_t)choose_device_cb, (void *)title) == IPP_OK) { diff --git a/cups/Makefile b/cups/Makefile index 5ce000916..adc5581fe 100644 --- a/cups/Makefile +++ b/cups/Makefile @@ -56,9 +56,8 @@ LIBOBJS = \ options.o \ page.o \ ppd.o \ - pwg-file.o \ + ppd-cache.o \ pwg-media.o \ - pwg-ppd.o \ request.o \ sidechannel.o \ snmp.o \ diff --git a/cups/auth.c b/cups/auth.c index 4d7facf4e..f9054d222 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -3,7 +3,7 @@ * * Authentication functions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * This file contains Kerberos support code, copyright 2006 by @@ -122,10 +122,10 @@ cupsDoAuthentication( { DEBUG_printf(("2cupsDoAuthentication: authstring=\"%s\"", http->authstring)); - + if (http->status == HTTP_UNAUTHORIZED) http->digest_tries ++; - + return (0); } else if (localauth == -1) @@ -140,7 +140,8 @@ cupsDoAuthentication( */ if ((http->digest_tries > 1 || !http->userpass[0]) && - strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9)) + (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5) || + !strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Digest", 6))) { /* * Nope - get a new password from the user... @@ -185,171 +186,22 @@ cupsDoAuthentication( * Got a password; encode it for the server... */ +#ifdef HAVE_GSSAPI if (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9)) { -#ifdef HAVE_GSSAPI /* * Kerberos authentication... */ - OM_uint32 minor_status, /* Minor status code */ - major_status; /* Major status code */ - gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER, - /* Output token */ - input_token = GSS_C_EMPTY_BUFFER; - /* Input token */ - char *gss_service_name; - /* GSS service name */ -# ifdef USE_SPNEGO - const char *authorization; - /* Pointer into Authorization string */ -# endif /* USE_SPNEGO */ - - -# ifdef __APPLE__ - /* - * If the weak-linked GSSAPI/Kerberos library is not present, don't try - * to use it... - */ - - if (gss_init_sec_context == NULL) - { - DEBUG_puts("1cupsDoAuthentication: Weak-linked GSSAPI/Kerberos framework " - "is not present"); - http->status = HTTP_AUTHORIZATION_CANCELED; - - return (-1); - } -# endif /* __APPLE__ */ - - if (http->gssname == GSS_C_NO_NAME) - { - if ((gss_service_name = getenv("CUPS_GSSSERVICENAME")) == NULL) - gss_service_name = CUPS_DEFAULT_GSSSERVICENAME; - else - DEBUG_puts("2cupsDoAuthentication: GSS service name set via " - "environment variable"); - - http->gssname = cups_get_gssname(http, gss_service_name); - } - -# ifdef USE_SPNEGO /* We don't implement SPNEGO just yet... */ - /* - * Find the start of the Kerberos input token... - */ - - authorization = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE); - - authorization += 9; - while (*authorization && _cups_isspace(*authorization)) - authorization ++; - - if (*authorization) - { - /* - * Decode the authorization string to get the input token... - */ - - int len = strlen(authorization); - - input_token.value = malloc(len); - input_token.value = httpDecode64_2(input_token.value, &len, - authorization); - input_token.length = len; - -# ifdef DEBUG - { - char *ptr = (char *)input_token.value; - int left = len; - - fputs("input_token=", stdout); - while (left > 0) - { - if (*ptr < ' ') - printf("\\%03o", *ptr & 255); - else - putchar(*ptr); - ptr ++; - left --; - } - putchar('\n'); - } -# endif /* DEBUG */ - } -# endif /* USE_SPNEGO */ - - if (http->gssctx != GSS_C_NO_CONTEXT) - { - gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER); - http->gssctx = GSS_C_NO_CONTEXT; - } - - major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, - &http->gssctx, - http->gssname, http->gssmech, -#ifdef GSS_C_DELEG_POLICY_FLAG - GSS_C_DELEG_POLICY_FLAG | -#endif /* GSS_C_DELEG_POLICY_FLAG */ - GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, - GSS_C_INDEFINITE, - GSS_C_NO_CHANNEL_BINDINGS, - &input_token, &http->gssmech, - &output_token, NULL, NULL); - - if (input_token.value) - free(input_token.value); - - if (GSS_ERROR(major_status)) + if (_cupsSetNegotiateAuthString(http)) { - cups_gss_printf(major_status, minor_status, - "cupsDoAuthentication: Unable to initialize security " - "context"); http->status = HTTP_AUTHORIZATION_CANCELED; - return (-1); } - - if (major_status == GSS_S_CONTINUE_NEEDED) - cups_gss_printf(major_status, minor_status, - "cupsDoAuthentication: Continuation needed!"); - - if (output_token.length > 0 && output_token.length <= 65536) - { - /* - * Allocate the authorization string since Windows KDCs can have - * arbitrarily large credentials... - */ - - int authsize = 10 + /* "Negotiate " */ - output_token.length * 4 / 3 + 1 + /* Base64 */ - 1; /* nul */ - - httpSetAuthString(http, NULL, NULL); - - if ((http->authstring = malloc(authsize)) == NULL) - { - http->authstring = http->_authstring; - authsize = sizeof(http->_authstring); - } - - strcpy(http->authstring, "Negotiate "); - httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value, - output_token.length); - - gss_release_buffer(&minor_status, &output_token); - } - else - { - DEBUG_printf(("1cupsDoAuthentication: Kerberos credentials too large - " - "%d bytes!", (int)output_token.length)); - http->status = HTTP_AUTHORIZATION_CANCELED; - gss_release_buffer(&minor_status, &output_token); - - return (-1); - } -#endif /* HAVE_GSSAPI */ } - else if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Digest", 6)) + else +#endif /* HAVE_GSSAPI */ + if (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Basic", 5)) { /* * Basic authentication... @@ -362,7 +214,7 @@ cupsDoAuthentication( (int)strlen(http->userpass)); httpSetAuthString(http, "Basic", encode); } - else + else if (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Digest", 6)) { /* * Digest authentication... @@ -382,6 +234,13 @@ cupsDoAuthentication( "response=\"%s\"", cupsUser(), realm, nonce, resource, encode); httpSetAuthString(http, "Digest", digest); } + else + { + DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"", + http->fields[HTTP_FIELD_WWW_AUTHENTICATE])); + http->status = HTTP_AUTHORIZATION_CANCELED; + return (-1); + } DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring)); @@ -390,6 +249,114 @@ cupsDoAuthentication( #ifdef HAVE_GSSAPI +/* + * '_cupsSetNegotiateAuthString()' - Set the Kerberos authentication string. + */ + +int /* O - 0 on success, -1 on error */ +_cupsSetNegotiateAuthString( + http_t *http) /* I - Connection to server */ +{ + OM_uint32 minor_status, /* Minor status code */ + major_status; /* Major status code */ + gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; + /* Output token */ + char *gss_service_name; /* GSS service name */ + + +# ifdef __APPLE__ + /* + * If the weak-linked GSSAPI/Kerberos library is not present, don't try + * to use it... + */ + + if (gss_init_sec_context == NULL) + { + DEBUG_puts("1_cupsSetNegotiateAuthString: Weak-linked GSSAPI/Kerberos " + "framework is not present"); + return (-1); + } +# endif /* __APPLE__ */ + + if (http->gssname == GSS_C_NO_NAME) + { + if ((gss_service_name = getenv("CUPS_GSSSERVICENAME")) == NULL) + gss_service_name = CUPS_DEFAULT_GSSSERVICENAME; + else + DEBUG_puts("2_cupsSetNegotiateAuthString: GSS service name set via " + "environment variable"); + + http->gssname = cups_get_gssname(http, gss_service_name); + } + + if (http->gssctx != GSS_C_NO_CONTEXT) + { + gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER); + http->gssctx = GSS_C_NO_CONTEXT; + } + + major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, + &http->gssctx, + http->gssname, http->gssmech, +#ifdef GSS_C_DELEG_POLICY_FLAG + GSS_C_DELEG_POLICY_FLAG | +#endif /* GSS_C_DELEG_POLICY_FLAG */ + GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, + GSS_C_INDEFINITE, + GSS_C_NO_CHANNEL_BINDINGS, + GSS_C_NO_BUFFER, &http->gssmech, + &output_token, NULL, NULL); + + if (GSS_ERROR(major_status)) + { + cups_gss_printf(major_status, minor_status, + "_cupsSetNegotiateAuthString: Unable to initialize " + "security context"); + return (-1); + } + + if (major_status == GSS_S_CONTINUE_NEEDED) + cups_gss_printf(major_status, minor_status, + "_cupsSetNegotiateAuthString: Continuation needed!"); + + if (output_token.length > 0 && output_token.length <= 65536) + { + /* + * Allocate the authorization string since Windows KDCs can have + * arbitrarily large credentials... + */ + + int authsize = 10 + /* "Negotiate " */ + output_token.length * 4 / 3 + 1 + /* Base64 */ + 1; /* nul */ + + httpSetAuthString(http, NULL, NULL); + + if ((http->authstring = malloc(authsize)) == NULL) + { + http->authstring = http->_authstring; + authsize = sizeof(http->_authstring); + } + + strcpy(http->authstring, "Negotiate "); + httpEncode64_2(http->authstring + 10, authsize - 10, output_token.value, + output_token.length); + + gss_release_buffer(&minor_status, &output_token); + } + else + { + DEBUG_printf(("1_cupsSetNegotiateAuthString: Kerberos credentials too " + "large - %d bytes!", (int)output_token.length)); + gss_release_buffer(&minor_status, &output_token); + + return (-1); + } + + return (0); +} + + /* * 'cups_get_gssname()' - Get CUPS service credentials for authentication. */ @@ -540,7 +507,7 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ /* * Delete any previous authorization reference... */ - + if (http->auth_ref) { AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults); @@ -548,10 +515,10 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ } if (!getenv("GATEWAY_INTERFACE") && - httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", + httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", auth_key, sizeof(auth_key))) { - status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, + status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &http->auth_ref); if (status != errAuthorizationSuccess) { @@ -568,13 +535,13 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ auth_rights.count = 1; auth_rights.items = &auth_right; - auth_flags = kAuthorizationFlagDefaults | + auth_flags = kAuthorizationFlagDefaults | kAuthorizationFlagPreAuthorize | - kAuthorizationFlagInteractionAllowed | + kAuthorizationFlagInteractionAllowed | kAuthorizationFlagExtendRights; - status = AuthorizationCopyRights(http->auth_ref, &auth_rights, - kAuthorizationEmptyEnvironment, + status = AuthorizationCopyRights(http->auth_ref, &auth_rights, + kAuthorizationEmptyEnvironment, auth_flags, NULL); if (status == errAuthorizationSuccess) status = AuthorizationMakeExternalForm(http->auth_ref, &auth_extrn); @@ -585,7 +552,7 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ * Set the authorization string and return... */ - httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn, + httpEncode64_2(buffer, sizeof(buffer), (void *)&auth_extrn, sizeof(auth_extrn)); httpSetAuthString(http, "AuthRef", buffer); @@ -613,11 +580,14 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ * information... */ -# ifdef HAVE_GSSAPI - if (strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) && -# else if ( +# ifdef HAVE_GSSAPI + strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) && # endif /* HAVE_GSSAPI */ +# ifdef HAVE_AUTHORIZATION_H + !httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", + auth_key, sizeof(auth_key)) && +# endif /* HAVE_AUTHORIZATION_H */ http->hostaddr->addr.sa_family == AF_LOCAL && !getenv("GATEWAY_INTERFACE")) /* Not via CGI programs... */ { diff --git a/cups/cups-private.h b/cups/cups-private.h index d6a8bbba9..6e1677f88 100644 --- a/cups/cups-private.h +++ b/cups/cups-private.h @@ -1,5 +1,5 @@ /* - * "$Id$" + * "$Id: cups-private.h 9596 2011-03-11 18:26:36Z mike $" * * Private definitions for CUPS. * @@ -161,8 +161,10 @@ typedef struct _cups_globals_s /**** CUPS global state data ****/ # ifdef __APPLE__ extern CFStringRef _cupsAppleCopyDefaultPaperID(void); +extern CFStringRef _cupsAppleCopyDefaultPrinter(void); extern int _cupsAppleGetUseLastPrinter(void); extern void _cupsAppleSetDefaultPaperID(CFStringRef name); +extern void _cupsAppleSetDefaultPrinter(CFStringRef name); extern void _cupsAppleSetUseLastPrinter(int uselast); # endif /* __APPLE__ */ @@ -175,10 +177,14 @@ extern const char *_cupsGetPassword(const char *prompt); extern void _cupsGlobalLock(void); extern _cups_globals_t *_cupsGlobals(void); extern void _cupsGlobalUnlock(void); +extern int _cupsNextDelay(int current, int *previous); extern void _cupsSetDefaults(void); extern void _cupsSetError(ipp_status_t status, const char *message, int localize); extern void _cupsSetHTTPError(http_status_t status); +# ifdef HAVE_GSSAPI +extern int _cupsSetNegotiateAuthString(http_t *http); +# endif /* HAVE_GSSAPI */ extern char *_cupsUserDefault(char *name, size_t namesize); @@ -192,5 +198,5 @@ extern char *_cupsUserDefault(char *name, size_t namesize); #endif /* !_CUPS_CUPS_PRIVATE_H_ */ /* - * End of "$Id$". + * End of "$Id: cups-private.h 9596 2011-03-11 18:26:36Z mike $". */ diff --git a/cups/dest.c b/cups/dest.c index 1406c3420..bd738bf00 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -1,5 +1,5 @@ /* - * "$Id: dest.c 7946 2008-09-16 23:27:54Z mike $" + * "$Id: dest.c 9568 2011-02-25 06:13:56Z mike $" * * User-defined destination (and option) support for CUPS. * @@ -19,8 +19,10 @@ * cupsAddDest() - Add a destination to the list of * destinations. * _cupsAppleCopyDefaultPaperID() - Get the default paper ID. + * _cupsAppleCopyDefaultPrinter() - Get the default printer at this location. * _cupsAppleGetUseLastPrinter() - Get whether to use the last used printer. * _cupsAppleSetDefaultPaperID() - Set the default paper id. + * _cupsAppleSetDefaultPrinter() - Set the default printer for this location. * _cupsAppleSetUseLastPrinter() - Set whether to use the last used printer. * cupsFreeDests() - Free the memory used by the list of * destinations. @@ -46,7 +48,6 @@ * location. * appleGetPaperSize() - Get the default paper size. * appleGetPrinter() - Get a printer from the history array. - * appleSetDefault() - Set the default printer for this location. * cups_add_dest() - Add a destination to the array. * cups_compare_dests() - Compare two destinations. * cups_find_dest() - Find a destination using a binary search. @@ -70,13 +71,12 @@ #ifdef __APPLE__ # include -# define kDefaultPaperIDKey CFSTR("DefaultPaperID") -# define kLocationHistoryArrayKey CFSTR("kLocationHistoryArrayKeyTMP") -# define kLocationNetworkKey CFSTR("kLocationNetworkKey") -# define kLocationPrinterIDKey CFSTR("kLocationPrinterIDKey") -# define kPMPrintingPreferences CFSTR("com.apple.print.PrintingPrefs") -# define kCUPSPrintingPreferences CFSTR("org.cups.PrintingPrefs") -# define kUseLastPrinterAsCurrentPrinterKey CFSTR("UseLastPrinterAsCurrentPrinter") +# define kCUPSPrintingPrefs CFSTR("org.cups.PrintingPrefs") +# define kDefaultPaperIDKey CFSTR("DefaultPaperID") +# define kLastUsedPrintersKey CFSTR("LastUsedPrinters") +# define kLocationNetworkKey CFSTR("Network") +# define kLocationPrinterIDKey CFSTR("PrinterID") +# define kUseLastPrinter CFSTR("UseLastPrinter") #endif /* __APPLE__ */ @@ -90,7 +90,6 @@ static CFStringRef appleCopyNetwork(void); static char *appleGetPaperSize(char *name, int namesize); static CFStringRef appleGetPrinter(CFArrayRef locations, CFStringRef network, CFIndex *locindex); -static void appleSetDefault(const char *name); #endif /* __APPLE__ */ static cups_dest_t *cups_add_dest(const char *name, const char *instance, int *num_dests, cups_dest_t **dests); @@ -187,17 +186,79 @@ cupsAddDest(const char *name, /* I - Destination name */ CFStringRef /* O - Default paper ID */ _cupsAppleCopyDefaultPaperID(void) { - CFStringRef paper; /* Default paper ID */ + return (CFPreferencesCopyAppValue(kDefaultPaperIDKey, + kCUPSPrintingPrefs)); +} + + +/* + * '_cupsAppleCopyDefaultPrinter()' - Get the default printer at this location. + */ + +CFStringRef /* O - Default printer name */ +_cupsAppleCopyDefaultPrinter(void) +{ + CFStringRef network; /* Network location */ + CFArrayRef locations; /* Location array */ + CFStringRef locprinter; /* Current printer */ - paper = CFPreferencesCopyAppValue(kDefaultPaperIDKey, - kCUPSPrintingPreferences); + /* + * Use location-based defaults only if "use last printer" is selected in the + * system preferences... + */ - if (!paper) - paper = CFPreferencesCopyAppValue(kDefaultPaperIDKey, - kPMPrintingPreferences); + if (!_cupsAppleGetUseLastPrinter()) + { + DEBUG_puts("1_cupsAppleCopyDefaultPrinter: Not using last printer as " + "default."); + return (NULL); + } - return (paper); + /* + * Get the current location... + */ + + if ((network = appleCopyNetwork()) == NULL) + { + DEBUG_puts("1_cupsAppleCopyDefaultPrinter: Unable to get current " + "network."); + return (NULL); + } + +//# ifdef DEBUG +// CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8); +// DEBUG_printf(("2_cupsUserDefault: network=\"%s\"", name)); +//# endif /* DEBUG */ + + /* + * Lookup the network in the preferences... + */ + + if ((locations = appleCopyLocations()) == NULL) + { + /* + * Missing or bad location array, so no location-based default... + */ + + DEBUG_puts("1_cupsAppleCopyDefaultPrinter: Missing or bad last used " + "printer array."); + + CFRelease(network); + + return (NULL); + } + + DEBUG_printf(("1_cupsAppleCopyDefaultPrinter: Got locations, %d entries.", + (int)CFArrayGetCount(locations))); + + if ((locprinter = appleGetPrinter(locations, network, NULL)) != NULL) + CFRetain(locprinter); + + CFRelease(network); + CFRelease(locations); + + return (locprinter); } @@ -215,13 +276,9 @@ _cupsAppleGetUseLastPrinter(void) if (getenv("CUPS_DISABLE_APPLE_DEFAULT")) return (0); - uselast = CFPreferencesGetAppBooleanValue(kUseLastPrinterAsCurrentPrinterKey, - kCUPSPrintingPreferences, + uselast = CFPreferencesGetAppBooleanValue(kUseLastPrinter, + kCUPSPrintingPrefs, &uselast_set); - if (!uselast_set) - uselast = CFPreferencesGetAppBooleanValue(kUseLastPrinterAsCurrentPrinterKey, - kPMPrintingPreferences, - &uselast_set); if (!uselast_set) return (1); else @@ -237,7 +294,110 @@ void _cupsAppleSetDefaultPaperID( CFStringRef name) /* I - New paper ID */ { - CFPreferencesSetAppValue(kDefaultPaperIDKey, name, kCUPSPrintingPreferences); + CFPreferencesSetAppValue(kDefaultPaperIDKey, name, kCUPSPrintingPrefs); + CFPreferencesAppSynchronize(kCUPSPrintingPrefs); + notify_post("com.apple.printerPrefsChange"); +} + + +/* + * '_cupsAppleSetDefaultPrinter()' - Set the default printer for this location. + */ + +void +_cupsAppleSetDefaultPrinter( + CFStringRef name) /* I - Default printer/class name */ +{ + CFStringRef network; /* Current network */ + CFArrayRef locations; /* Old locations array */ + CFIndex locindex; /* Index in locations array */ + CFStringRef locprinter; /* Current printer */ + CFMutableArrayRef newlocations; /* New locations array */ + CFMutableDictionaryRef newlocation; /* New location */ + + + /* + * Get the current location... + */ + + if ((network = appleCopyNetwork()) == NULL) + { + DEBUG_puts("1_cupsAppleSetDefaultPrinter: Unable to get current network..."); + return; + } + + /* + * Lookup the network in the preferences... + */ + + if ((locations = appleCopyLocations()) != NULL) + locprinter = appleGetPrinter(locations, network, &locindex); + else + { + locprinter = NULL; + locindex = -1; + } + + if (!locprinter || CFStringCompare(locprinter, name, 0) != kCFCompareEqualTo) + { + /* + * Need to change the locations array... + */ + + if (locations) + { + newlocations = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, + locations); + + if (locprinter) + CFArrayRemoveValueAtIndex(newlocations, locindex); + } + else + newlocations = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); + + newlocation = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks); + + if (newlocation && newlocations) + { + /* + * Put the new location at the front of the array... + */ + + CFDictionaryAddValue(newlocation, kLocationNetworkKey, network); + CFDictionaryAddValue(newlocation, kLocationPrinterIDKey, name); + CFArrayInsertValueAtIndex(newlocations, 0, newlocation); + + /* + * Limit the number of locations to 10... + */ + + while (CFArrayGetCount(newlocations) > 10) + CFArrayRemoveValueAtIndex(newlocations, 10); + + /* + * Push the changes out... + */ + + CFPreferencesSetAppValue(kLastUsedPrintersKey, newlocations, + kCUPSPrintingPrefs); + CFPreferencesAppSynchronize(kCUPSPrintingPrefs); + notify_post("com.apple.printerPrefsChange"); + } + + if (newlocations) + CFRelease(newlocations); + + if (newlocation) + CFRelease(newlocation); + } + + if (locations) + CFRelease(locations); + + CFRelease(network); } @@ -249,9 +409,11 @@ void _cupsAppleSetUseLastPrinter( int uselast) /* O - 1 to use last printer, 0 otherwise */ { - CFPreferencesSetAppValue(kUseLastPrinterAsCurrentPrinterKey, + CFPreferencesSetAppValue(kUseLastPrinter, uselast ? kCFBooleanTrue : kCFBooleanFalse, - kCUPSPrintingPreferences); + kCUPSPrintingPrefs); + CFPreferencesAppSynchronize(kCUPSPrintingPrefs); + notify_post("com.apple.printerPrefsChange"); } #endif /* __APPLE__ */ @@ -1254,7 +1416,18 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ */ if ((dest = cupsGetDest(NULL, NULL, num_dests, dests)) != NULL) - appleSetDefault(dest->name); + { + CFStringRef name = CFStringCreateWithCString(kCFAllocatorDefault, + dest->name, + kCFStringEncodingUTF8); + /* Default printer name */ + + if (name) + { + _cupsAppleSetDefaultPrinter(name); + CFRelease(name); + } + } #endif /* __APPLE__ */ #ifdef HAVE_NOTIFY_POST @@ -1281,9 +1454,7 @@ _cupsUserDefault(char *name, /* I - Name buffer */ { const char *env; /* LPDEST or PRINTER env variable */ #ifdef __APPLE__ - CFStringRef network; /* Network location */ - CFArrayRef locations; /* Location array */ - CFStringRef locprinter; /* Current printer */ + CFStringRef locprinter; /* Last printer as this location */ #endif /* __APPLE__ */ @@ -1303,59 +1474,15 @@ _cupsUserDefault(char *name, /* I - Name buffer */ * system preferences... */ - if (!_cupsAppleGetUseLastPrinter()) + if ((locprinter = _cupsAppleCopyDefaultPrinter()) != NULL) { - DEBUG_puts("1_cupsUserDefault: Not using last printer as default..."); - name[0] = '\0'; - return (NULL); - } - - /* - * Get the current location... - */ - - if ((network = appleCopyNetwork()) == NULL) - { - DEBUG_puts("1_cupsUserDefault: Unable to get current network..."); - name[0] = '\0'; - return (NULL); - } - -# ifdef DEBUG - CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8); - DEBUG_printf(("2_cupsUserDefault: network=\"%s\"", name)); -# endif /* DEBUG */ - - /* - * Lookup the network in the preferences... - */ - - if ((locations = appleCopyLocations()) == NULL) - { - /* - * Missing or bad location array, so no location-based default... - */ - - DEBUG_puts("1_cupsUserDefault: Missing or bad location history array..."); - - CFRelease(network); - - name[0] = '\0'; - return (NULL); - } - - DEBUG_printf(("2_cupsUserDefault: Got location, %d entries...", - (int)CFArrayGetCount(locations))); - - if ((locprinter = appleGetPrinter(locations, network, NULL)) != NULL) CFStringGetCString(locprinter, name, namesize, kCFStringEncodingUTF8); + CFRelease(locprinter); + } else name[0] = '\0'; - CFRelease(network); - CFRelease(locations); - - DEBUG_printf(("1_cupsUserDefault: Returning \"%s\"...", name)); + DEBUG_printf(("1_cupsUserDefault: Returning \"%s\".", name)); return (*name ? name : NULL); @@ -1385,8 +1512,8 @@ appleCopyLocations(void) * Look up the location array in the preferences... */ - if ((locations = CFPreferencesCopyAppValue(kLocationHistoryArrayKey, - kPMPrintingPreferences)) == NULL) + if ((locations = CFPreferencesCopyAppValue(kLastUsedPrintersKey, + kCUPSPrintingPrefs)) == NULL) return (NULL); if (CFGetTypeID(locations) != CFArrayGetTypeID()) @@ -1412,16 +1539,21 @@ appleCopyNetwork(void) CFStringRef network = NULL; /* Current network ID */ - if ((dynamicStore = SCDynamicStoreCreate(NULL, CFSTR("Printing"), NULL, + if ((dynamicStore = SCDynamicStoreCreate(NULL, CFSTR("libcups"), NULL, NULL)) != NULL) { + /* + * First use the IPv6 router address, if available, since that will generally + * be a globally-unique link-local address. + */ + if ((key = SCDynamicStoreKeyCreateNetworkGlobalEntity( - NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4)) != NULL) + NULL, kSCDynamicStoreDomainState, kSCEntNetIPv6)) != NULL) { if ((ip_dict = SCDynamicStoreCopyValue(dynamicStore, key)) != NULL) { if ((network = CFDictionaryGetValue(ip_dict, - kSCPropNetIPv4Router)) != NULL) + kSCPropNetIPv6Router)) != NULL) CFRetain(network); CFRelease(ip_dict); @@ -1430,6 +1562,29 @@ appleCopyNetwork(void) CFRelease(key); } + /* + * If that doesn't work, try the IPv4 router address. This isn't as unique + * and will likely be a 10.x.y.z or 192.168.y.z address... + */ + + if (!network) + { + if ((key = SCDynamicStoreKeyCreateNetworkGlobalEntity( + NULL, kSCDynamicStoreDomainState, kSCEntNetIPv4)) != NULL) + { + if ((ip_dict = SCDynamicStoreCopyValue(dynamicStore, key)) != NULL) + { + if ((network = CFDictionaryGetValue(ip_dict, + kSCPropNetIPv4Router)) != NULL) + CFRetain(network); + + CFRelease(ip_dict); + } + + CFRelease(key); + } + } + CFRelease(dynamicStore); } @@ -1502,118 +1657,6 @@ appleGetPrinter(CFArrayRef locations, /* I - Location array */ return (NULL); } - - -/* - * 'appleSetDefault()' - Set the default printer for this location. - */ - -static void -appleSetDefault(const char *name) /* I - Default printer/class name */ -{ - CFStringRef network; /* Current network */ - CFArrayRef locations; /* Old locations array */ - CFIndex locindex; /* Index in locations array */ - CFStringRef locprinter; /* Current printer */ - CFMutableArrayRef newlocations; /* New locations array */ - CFMutableDictionaryRef newlocation; /* New location */ - CFStringRef newprinter; /* New printer */ - - - /* - * Get the current location... - */ - - if ((network = appleCopyNetwork()) == NULL) - { - DEBUG_puts("1appleSetDefault: Unable to get current network..."); - return; - } - - if ((newprinter = CFStringCreateWithCString(kCFAllocatorDefault, name, - kCFStringEncodingUTF8)) == NULL) - { - CFRelease(network); - return; - } - - /* - * Lookup the network in the preferences... - */ - - if ((locations = appleCopyLocations()) != NULL) - locprinter = appleGetPrinter(locations, network, &locindex); - else - { - locprinter = NULL; - locindex = -1; - } - - if (!locprinter || - CFStringCompare(locprinter, newprinter, 0) != kCFCompareEqualTo) - { - /* - * Need to change the locations array... - */ - - if (locations) - { - newlocations = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, - locations); - - if (locprinter) - CFArrayRemoveValueAtIndex(newlocations, locindex); - } - else - newlocations = CFArrayCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeArrayCallBacks); - - newlocation = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, - &kCFTypeDictionaryKeyCallBacks, - &kCFTypeDictionaryValueCallBacks); - - if (newlocation && newlocations) - { - /* - * Put the new location at the front of the array... - */ - - CFDictionaryAddValue(newlocation, kLocationNetworkKey, network); - CFDictionaryAddValue(newlocation, kLocationPrinterIDKey, newprinter); - CFArrayInsertValueAtIndex(newlocations, 0, newlocation); - - /* - * Limit the number of locations to 10... - */ - - while (CFArrayGetCount(newlocations) > 10) - CFArrayRemoveValueAtIndex(newlocations, 10); - - /* - * Push the changes out... - */ - - CFPreferencesSetAppValue(kLocationHistoryArrayKey, newlocations, - kPMPrintingPreferences); - CFPreferencesAppSynchronize(kPMPrintingPreferences); - notify_post("com.apple.printerPrefsChange"); - } - - if (newlocations) - CFRelease(newlocations); - - if (newlocation) - CFRelease(newlocation); - } - - if (locations) - CFRelease(locations); - - CFRelease(network); - CFRelease(newprinter); -} - - #endif /* __APPLE__ */ @@ -2122,5 +2165,5 @@ cups_make_string( /* - * End of "$Id: dest.c 7946 2008-09-16 23:27:54Z mike $". + * End of "$Id: dest.c 9568 2011-02-25 06:13:56Z mike $". */ diff --git a/cups/file.c b/cups/file.c index b788b7239..21e6fabb8 100644 --- a/cups/file.c +++ b/cups/file.c @@ -386,7 +386,7 @@ cupsFileFlush(cups_file_t *fp) /* I - CUPS file */ fp->ptr = fp->buf; } - + return (0); } @@ -406,7 +406,7 @@ cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */ if (!fp || (fp->mode != 'r' && fp->mode != 's')) { - DEBUG_puts("3cupsFileGetChar: Bad arguments!"); + DEBUG_puts("5cupsFileGetChar: Bad arguments!"); return (-1); } @@ -417,7 +417,7 @@ cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */ if (fp->ptr >= fp->end) if (cups_fill(fp) < 0) { - DEBUG_puts("3cupsFileGetChar: Unable to fill buffer!"); + DEBUG_puts("5cupsFileGetChar: Unable to fill buffer!"); return (-1); } @@ -425,11 +425,11 @@ cupsFileGetChar(cups_file_t *fp) /* I - CUPS file */ * Return the next character in the buffer... */ - DEBUG_printf(("3cupsFileGetChar: Returning %d...", *(fp->ptr) & 255)); + DEBUG_printf(("5cupsFileGetChar: Returning %d...", *(fp->ptr) & 255)); fp->pos ++; - DEBUG_printf(("4cupsFileGetChar: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); + DEBUG_printf(("6cupsFileGetChar: pos=" CUPS_LLFMT, CUPS_LLCAST fp->pos)); return (*(fp->ptr)++ & 255); } diff --git a/cups/globals.c b/cups/globals.c index 00f74c316..93985e0e9 100644 --- a/cups/globals.c +++ b/cups/globals.c @@ -314,8 +314,9 @@ cups_globals_free(_cups_globals_t *cg) /* I - Pointer to global data */ free(buffer); } - cupsArrayDelete(cg->pwg_size_lut); cupsArrayDelete(cg->leg_size_lut); + cupsArrayDelete(cg->ppd_size_lut); + cupsArrayDelete(cg->pwg_size_lut); httpClose(cg->http); diff --git a/cups/libcups2.def b/cups/libcups2.def index 35c382576..6e9581823 100644 --- a/cups/libcups2.def +++ b/cups/libcups2.def @@ -15,6 +15,7 @@ _cupsMD5Init _cupsMessageFree _cupsMessageLoad _cupsMessageLookup +_cupsNextDelay _cupsSetError _cupsSetLocale _cupsStrAlloc diff --git a/cups/libcups_s.exp b/cups/libcups_s.exp index b86fbe759..80b347a75 100644 --- a/cups/libcups_s.exp +++ b/cups/libcups_s.exp @@ -13,6 +13,7 @@ _cupsMD5Init _cupsMessageFree _cupsMessageLoad _cupsMessageLookup +_cupsNextDelay _cupsSetError _cupsSetLocale _cupsSNMPClose diff --git a/cups/mark.c b/cups/mark.c index 4dbd7555c..763b5310d 100644 --- a/cups/mark.c +++ b/cups/mark.c @@ -3,7 +3,7 @@ * * Option marking routines for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -62,8 +62,9 @@ static void ppd_mark_option(ppd_file_t *ppd, const char *option, * 'cupsMarkOptions()' - Mark command-line options in a PPD file. * * This function maps the IPP "finishings", "media", "mirror", - * "multiple-document-handling", "output-bin", "printer-resolution", and - * "sides" attributes to their corresponding PPD options and choices. + * "multiple-document-handling", "output-bin", "print-color-mode", + * "print-quality", "printer-resolution", and "sides" attributes to their + * corresponding PPD options and choices. */ int /* O - 1 if conflicts exist, 0 otherwise */ @@ -78,14 +79,14 @@ cupsMarkOptions( const char *val, /* Pointer into value */ *media, /* media option */ *output_bin, /* output-bin option */ - *output_mode, /* output-mode option */ *page_size, /* PageSize option */ *ppd_keyword, /* PPD keyword */ + *print_color_mode, /* print-color-mode option */ *print_quality, /* print-quality option */ *sides; /* sides option */ cups_option_t *optptr; /* Current option */ ppd_attr_t *attr; /* PPD attribute */ - _pwg_t *pwg; /* PWG mapping data */ + _ppd_cache_t *cache; /* PPD cache and mapping data */ /* @@ -104,22 +105,25 @@ cupsMarkOptions( media = cupsGetOption("media", num_options, options); output_bin = cupsGetOption("output-bin", num_options, options); - output_mode = cupsGetOption("output-mode", num_options, options); page_size = cupsGetOption("PageSize", num_options, options); print_quality = cupsGetOption("print-quality", num_options, options); sides = cupsGetOption("sides", num_options, options); - if ((media || output_bin || output_mode || print_quality || sides) && - !ppd->pwg) + if ((print_color_mode = cupsGetOption("print-color-mode", num_options, + options)) == NULL) + print_color_mode = cupsGetOption("output-mode", num_options, options); + + if ((media || output_bin || print_color_mode || print_quality || sides) && + !ppd->cache) { /* - * Load PWG mapping data as needed... + * Load PPD cache and mapping data as needed... */ - ppd->pwg = _pwgCreateWithPPD(ppd); + ppd->cache = _ppdCacheCreateWithPPD(ppd); } - pwg = (_pwg_t *)ppd->pwg; + cache = ppd->cache; if (media) { @@ -154,40 +158,40 @@ cupsMarkOptions( { if (!strncasecmp(s, "Custom.", 7) || ppdPageSize(ppd, s)) ppd_mark_option(ppd, "PageSize", s); - else if ((ppd_keyword = _pwgGetPageSize(pwg, NULL, s, NULL)) != NULL) + else if ((ppd_keyword = _ppdCacheGetPageSize(cache, NULL, s, NULL)) != NULL) ppd_mark_option(ppd, "PageSize", ppd_keyword); } - if (pwg && pwg->source_option && - !cupsGetOption(pwg->source_option, num_options, options) && - (ppd_keyword = _pwgGetInputSlot(pwg, NULL, s)) != NULL) - ppd_mark_option(ppd, pwg->source_option, ppd_keyword); + if (cache && cache->source_option && + !cupsGetOption(cache->source_option, num_options, options) && + (ppd_keyword = _ppdCacheGetInputSlot(cache, NULL, s)) != NULL) + ppd_mark_option(ppd, cache->source_option, ppd_keyword); if (!cupsGetOption("MediaType", num_options, options) && - (ppd_keyword = _pwgGetMediaType(pwg, NULL, s)) != NULL) + (ppd_keyword = _ppdCacheGetMediaType(cache, NULL, s)) != NULL) ppd_mark_option(ppd, "MediaType", ppd_keyword); } } - if (pwg) + if (cache) { if (!cupsGetOption("com.apple.print.DocumentTicket.PMSpoolFormat", num_options, options) && !cupsGetOption("APPrinterPreset", num_options, options) && - (output_mode || print_quality)) + (print_color_mode || print_quality)) { /* * Map output-mode and print-quality to a preset... */ - _pwg_output_mode_t pwg_om; /* output-mode index */ + _pwg_print_color_mode_t pwg_pcm;/* print-color-mode index */ _pwg_print_quality_t pwg_pq; /* print-quality index */ cups_option_t *preset;/* Current preset option */ - if (output_mode && !strcmp(output_mode, "monochrome")) - pwg_om = _PWG_OUTPUT_MODE_MONOCHROME; + if (print_color_mode && !strcmp(print_color_mode, "monochrome")) + pwg_pcm = _PWG_PRINT_COLOR_MODE_MONOCHROME; else - pwg_om = _PWG_OUTPUT_MODE_COLOR; + pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR; if (print_quality) { @@ -200,33 +204,33 @@ cupsMarkOptions( else pwg_pq = _PWG_PRINT_QUALITY_NORMAL; - if (pwg->num_presets[pwg_om][pwg_pq] == 0) + if (cache->num_presets[pwg_pcm][pwg_pq] == 0) { /* * Try to find a preset that works so that we maximize the chances of us * getting a good print using IPP attributes. */ - if (pwg->num_presets[pwg_om][_PWG_PRINT_QUALITY_NORMAL] > 0) + if (cache->num_presets[pwg_pcm][_PWG_PRINT_QUALITY_NORMAL] > 0) pwg_pq = _PWG_PRINT_QUALITY_NORMAL; - else if (pwg->num_presets[_PWG_OUTPUT_MODE_COLOR][pwg_pq] > 0) - pwg_om = _PWG_OUTPUT_MODE_COLOR; + else if (cache->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_pq] > 0) + pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR; else { - pwg_pq = _PWG_PRINT_QUALITY_NORMAL; - pwg_om = _PWG_OUTPUT_MODE_COLOR; + pwg_pq = _PWG_PRINT_QUALITY_NORMAL; + pwg_pcm = _PWG_PRINT_COLOR_MODE_COLOR; } } - if (pwg->num_presets[pwg_om][pwg_pq] > 0) + if (cache->num_presets[pwg_pcm][pwg_pq] > 0) { /* * Copy the preset options as long as the corresponding names are not * already defined in the IPP request... */ - for (i = pwg->num_presets[pwg_om][pwg_pq], - preset = pwg->presets[pwg_om][pwg_pq]; + for (i = cache->num_presets[pwg_pcm][pwg_pq], + preset = cache->presets[pwg_pcm][pwg_pq]; i > 0; i --, preset ++) { @@ -237,7 +241,7 @@ cupsMarkOptions( } if (output_bin && !cupsGetOption("OutputBin", num_options, options) && - (ppd_keyword = _pwgGetOutputBin(pwg, output_bin)) != NULL) + (ppd_keyword = _ppdCacheGetOutputBin(cache, output_bin)) != NULL) { /* * Map output-bin to OutputBin... @@ -246,19 +250,19 @@ cupsMarkOptions( ppd_mark_option(ppd, "OutputBin", ppd_keyword); } - if (sides && pwg->sides_option && - !cupsGetOption(pwg->sides_option, num_options, options)) + if (sides && cache->sides_option && + !cupsGetOption(cache->sides_option, num_options, options)) { /* * Map sides to duplex option... */ if (!strcmp(sides, "one-sided")) - ppd_mark_option(ppd, pwg->sides_option, pwg->sides_1sided); + ppd_mark_option(ppd, cache->sides_option, cache->sides_1sided); else if (!strcmp(sides, "two-sided-long-edge")) - ppd_mark_option(ppd, pwg->sides_option, pwg->sides_2sided_long); + ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_long); else if (!strcmp(sides, "two-sided-short-edge")) - ppd_mark_option(ppd, pwg->sides_option, pwg->sides_2sided_short); + ppd_mark_option(ppd, cache->sides_option, cache->sides_2sided_short); } } diff --git a/cups/ppd-cache.c b/cups/ppd-cache.c new file mode 100644 index 000000000..e0b5d65bc --- /dev/null +++ b/cups/ppd-cache.c @@ -0,0 +1,2348 @@ +/* + * "$Id$" + * + * PPD cache implementation for CUPS. + * + * Copyright 2010-2011 by Apple Inc. + * + * These coded instructions, statements, and computer programs are the + * property of Apple Inc. and are protected by Federal copyright + * law. Distribution and use rights are outlined in the file "LICENSE.txt" + * which should have been included with this file. If this file is + * file is missing or damaged, see the license at "http://www.cups.org/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * _ppdCacheCreateWithFile() - Create PPD cache and mapping data from a + * written file. + * _ppdCacheCreateWithPPD() - Create PWG mapping data from a PPD file. + * _ppdCacheDestroy() - Free all memory used for PWG mapping data. + * _ppdCacheGetBin() - Get the PWG output-bin keyword associated with + * a PPD OutputBin. + * _ppdCacheGetInputSlot() - Get the PPD InputSlot associated with the job + * attributes or a keyword string. + * _ppdCacheGetMediaType() - Get the PPD MediaType associated with the job + * attributes or a keyword string. + * _ppdCacheGetOutputBin() - Get the PPD OutputBin associated with the + * keyword string. + * _ppdCacheGetPageSize() - Get the PPD PageSize associated with the job + * attributes or a keyword string. + * _ppdCacheGetSize() - Get the PWG size associated with a PPD + * PageSize. + * _ppdCacheGetSource() - Get the PWG media-source associated with a PPD + * InputSlot. + * _ppdCacheGetType() - Get the PWG media-type associated with a PPD + * MediaType. + * _ppdCacheWriteFile() - Write PWG mapping data to a file. + * _pwgInputSlotForSource() - Get the InputSlot name for the given PWG + * media-source. + * _pwgMediaTypeForType() - Get the MediaType name for the given PWG + * media-type. + * _pwgPageSizeForMedia() - Get the PageSize name for the given media. + * pwg_ppdize_name() - Convert an IPP keyword to a PPD keyword. + * pwg_unppdize_name() - Convert a PPD keyword to a lowercase IPP + * keyword. + */ + +/* + * Include necessary headers... + */ + +#include "cups-private.h" +#include + + +/* + * Macro to test for two almost-equal PWG measurements. + */ + +#define _PWG_EQUIVALENT(x, y) (abs((x)-(y)) < 2) + + +/* + * Local functions... + */ + +static void pwg_ppdize_name(const char *ipp, char *name, size_t namesize); +static void pwg_unppdize_name(const char *ppd, char *name, size_t namesize); + + +/* + * '_ppdCacheCreateWithFile()' - Create PPD cache and mapping data from a + * written file. + * + * Use the @link _ppdCacheWriteFile@ function to write PWG mapping data to a + * file. + */ + +_ppd_cache_t * /* O - PPD cache and mapping data */ +_ppdCacheCreateWithFile( + const char *filename, /* I - File to read */ + ipp_t **attrs) /* IO - IPP attributes, if any */ +{ + cups_file_t *fp; /* File */ + _ppd_cache_t *pc; /* PWG mapping data */ + _pwg_size_t *size; /* Current size */ + _pwg_map_t *map; /* Current map */ + int linenum, /* Current line number */ + num_bins, /* Number of bins in file */ + num_sizes, /* Number of sizes in file */ + num_sources, /* Number of sources in file */ + num_types; /* Number of types in file */ + char line[2048], /* Current line */ + *value, /* Pointer to value in line */ + *valueptr, /* Pointer into value */ + pwg_keyword[128], /* PWG keyword */ + ppd_keyword[PPD_MAX_NAME]; + /* PPD keyword */ + _pwg_print_color_mode_t print_color_mode; + /* Print color mode for preset */ + _pwg_print_quality_t print_quality; /* Print quality for preset */ + + + DEBUG_printf(("_ppdCacheCreateWithFile(filename=\"%s\")", filename)); + + /* + * Range check input... + */ + + if (attrs) + *attrs = NULL; + + if (!filename) + { + _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0); + return (NULL); + } + + /* + * Open the file... + */ + + if ((fp = cupsFileOpen(filename, "r")) == NULL) + { + _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); + return (NULL); + } + + /* + * Read the first line and make sure it has "#CUPS-PPD-CACHE-version" in it... + */ + + if (!cupsFileGets(fp, line, sizeof(line))) + { + _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); + DEBUG_puts("_ppdCacheCreateWithFile: Unable to read first line."); + cupsFileClose(fp); + return (NULL); + } + + if (strncmp(line, "#CUPS-PPD-CACHE-", 16) || + atoi(line + 16) != _PPD_CACHE_VERSION) + { + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + DEBUG_printf(("_ppdCacheCreateWithFile: Wrong first line \"%s\".", line)); + cupsFileClose(fp); + return (NULL); + } + + /* + * Allocate the mapping data structure... + */ + + if ((pc = calloc(1, sizeof(_ppd_cache_t))) == NULL) + { + _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); + DEBUG_puts("_ppdCacheCreateWithFile: Unable to allocate _ppd_cache_t."); + goto create_error; + } + + /* + * Read the file... + */ + + linenum = 0; + num_bins = 0; + num_sizes = 0; + num_sources = 0; + num_types = 0; + + while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) + { + DEBUG_printf(("_ppdCacheCreateWithFile: line=\"%s\", value=\"%s\", " + "linenum=%d", line, value, linenum)); + + if (!value) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Missing value on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + else if (!strcasecmp(line, "Filter")) + { + if (!pc->filters) + pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, + (cups_acopy_func_t)_cupsStrAlloc, + (cups_afree_func_t)_cupsStrFree); + + cupsArrayAdd(pc->filters, value); + } + else if (!strcasecmp(line, "PreFilter")) + { + if (!pc->prefilters) + pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, + (cups_acopy_func_t)_cupsStrAlloc, + (cups_afree_func_t)_cupsStrFree); + + cupsArrayAdd(pc->prefilters, value); + } + else if (!strcasecmp(line, "Product")) + { + pc->product = _cupsStrAlloc(value); + } + else if (!strcasecmp(line, "IPP")) + { + off_t pos = cupsFileTell(fp), /* Position in file */ + length = strtol(value, NULL, 10); + /* Length of IPP attributes */ + + if (attrs && *attrs) + { + DEBUG_puts("_ppdCacheCreateWithFile: IPP listed multiple times."); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + else if (length <= 0) + { + DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP length."); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if (attrs) + { + /* + * Read IPP attributes into the provided variable... + */ + + *attrs = ippNew(); + + if (ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL, + *attrs) != IPP_DATA) + { + DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP data."); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + } + else + { + /* + * Skip the IPP data entirely... + */ + + cupsFileSeek(fp, pos + length); + } + + if (cupsFileTell(fp) != (pos + length)) + { + DEBUG_puts("_ppdCacheCreateWithFile: Bad IPP data."); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + } + else if (!strcasecmp(line, "NumBins")) + { + if (num_bins > 0) + { + DEBUG_puts("_ppdCacheCreateWithFile: NumBins listed multiple times."); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if ((num_bins = atoi(value)) <= 0 || num_bins > 65536) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumBins value %d on line " + "%d.", num_sizes, linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if ((pc->bins = calloc(num_bins, sizeof(_pwg_map_t))) == NULL) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d bins.", + num_sizes)); + _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); + goto create_error; + } + } + else if (!strcasecmp(line, "Bin")) + { + if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad Bin on line %d.", linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if (pc->num_bins >= num_bins) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Too many Bin's on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + map = pc->bins + pc->num_bins; + map->pwg = _cupsStrAlloc(pwg_keyword); + map->ppd = _cupsStrAlloc(ppd_keyword); + + pc->num_bins ++; + } + else if (!strcasecmp(line, "NumSizes")) + { + if (num_sizes > 0) + { + DEBUG_puts("_ppdCacheCreateWithFile: NumSizes listed multiple times."); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if ((num_sizes = atoi(value)) <= 0 || num_sizes > 65536) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumSizes value %d on line " + "%d.", num_sizes, linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + 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 (!strcasecmp(line, "Size")) + { + if (pc->num_sizes >= num_sizes) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Too many Size's on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + size = pc->sizes + pc->num_sizes; + + if (sscanf(value, "%127s%40s%d%d%d%d%d%d", pwg_keyword, ppd_keyword, + &(size->width), &(size->length), &(size->left), + &(size->bottom), &(size->right), &(size->top)) != 8) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad Size on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + size->map.pwg = _cupsStrAlloc(pwg_keyword); + size->map.ppd = _cupsStrAlloc(ppd_keyword); + + pc->num_sizes ++; + } + else if (!strcasecmp(line, "CustomSize")) + { + if (pc->custom_max_width > 0) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Too many CustomSize's on line " + "%d.", linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if (sscanf(value, "%d%d%d%d%d%d%d%d", &(pc->custom_max_width), + &(pc->custom_max_length), &(pc->custom_min_width), + &(pc->custom_min_length), &(pc->custom_size.left), + &(pc->custom_size.bottom), &(pc->custom_size.right), + &(pc->custom_size.top)) != 8) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad CustomSize on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max", + pc->custom_max_width, pc->custom_max_length); + pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword); + + _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min", + pc->custom_min_width, pc->custom_min_length); + pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword); + } + else if (!strcasecmp(line, "SourceOption")) + { + pc->source_option = _cupsStrAlloc(value); + } + else if (!strcasecmp(line, "NumSources")) + { + if (num_sources > 0) + { + DEBUG_puts("_ppdCacheCreateWithFile: NumSources listed multiple " + "times."); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if ((num_sources = atoi(value)) <= 0 || num_sources > 65536) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumSources value %d on " + "line %d.", num_sources, linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if ((pc->sources = calloc(num_sources, sizeof(_pwg_map_t))) == NULL) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d sources.", + num_sources)); + _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); + goto create_error; + } + } + else if (!strcasecmp(line, "Source")) + { + if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad Source on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if (pc->num_sources >= num_sources) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Too many Source's on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + map = pc->sources + pc->num_sources; + map->pwg = _cupsStrAlloc(pwg_keyword); + map->ppd = _cupsStrAlloc(ppd_keyword); + + pc->num_sources ++; + } + else if (!strcasecmp(line, "NumTypes")) + { + if (num_types > 0) + { + DEBUG_puts("_ppdCacheCreateWithFile: NumTypes listed multiple times."); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if ((num_types = atoi(value)) <= 0 || num_types > 65536) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad NumTypes value %d on " + "line %d.", num_types, linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if ((pc->types = calloc(num_types, sizeof(_pwg_map_t))) == NULL) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Unable to allocate %d types.", + num_types)); + _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); + goto create_error; + } + } + else if (!strcasecmp(line, "Type")) + { + if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad Type on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if (pc->num_types >= num_types) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Too many Type's on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + map = pc->types + pc->num_types; + map->pwg = _cupsStrAlloc(pwg_keyword); + map->ppd = _cupsStrAlloc(ppd_keyword); + + pc->num_types ++; + } + else if (!strcasecmp(line, "Preset")) + { + /* + * Preset output-mode print-quality name=value ... + */ + + print_color_mode = (_pwg_print_color_mode_t)strtol(value, &valueptr, 10); + print_quality = (_pwg_print_quality_t)strtol(valueptr, &valueptr, 10); + + if (print_color_mode < _PWG_PRINT_COLOR_MODE_MONOCHROME || + print_color_mode >= _PWG_PRINT_COLOR_MODE_MAX || + print_quality < _PWG_PRINT_QUALITY_DRAFT || + print_quality >= _PWG_PRINT_QUALITY_MAX || + valueptr == value || !*valueptr) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Bad Preset on line %d.", + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + pc->num_presets[print_color_mode][print_quality] = + cupsParseOptions(valueptr, 0, + pc->presets[print_color_mode] + print_quality); + } + else if (!strcasecmp(line, "SidesOption")) + pc->sides_option = _cupsStrAlloc(value); + else if (!strcasecmp(line, "Sides1Sided")) + pc->sides_1sided = _cupsStrAlloc(value); + else if (!strcasecmp(line, "Sides2SidedLong")) + pc->sides_2sided_long = _cupsStrAlloc(value); + else if (!strcasecmp(line, "Sides2SidedShort")) + pc->sides_2sided_short = _cupsStrAlloc(value); + else + { + DEBUG_printf(("_ppdCacheCreateWithFile: Unknown %s on line %d.", line, + linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + } + + if (pc->num_sizes < num_sizes) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Not enough sizes (%d < %d).", + pc->num_sizes, num_sizes)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if (pc->num_sources < num_sources) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Not enough sources (%d < %d).", + pc->num_sources, num_sources)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + if (pc->num_types < num_types) + { + DEBUG_printf(("_ppdCacheCreateWithFile: Not enough types (%d < %d).", + pc->num_types, num_types)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PPD cache file."), 1); + goto create_error; + } + + cupsFileClose(fp); + + return (pc); + + /* + * If we get here the file was bad - free any data and return... + */ + + create_error: + + cupsFileClose(fp); + _ppdCacheDestroy(pc); + + if (attrs) + ippDelete(*attrs); + + return (NULL); +} + + +/* + * '_ppdCacheCreateWithPPD()' - Create PWG mapping data from a PPD file. + */ + +_ppd_cache_t * /* O - PPD cache and mapping data */ +_ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ +{ + int i, j, k; /* Looping vars */ + _ppd_cache_t *pc; /* PWG mapping data */ + ppd_option_t *input_slot, /* InputSlot option */ + *media_type, /* MediaType option */ + *output_bin, /* OutputBin option */ + *color_model, /* ColorModel option */ + *duplex; /* Duplex option */ + ppd_choice_t *choice; /* Current InputSlot/MediaType */ + _pwg_map_t *map; /* Current source/type map */ + ppd_attr_t *ppd_attr; /* Current PPD preset attribute */ + int num_options; /* Number of preset options and props */ + cups_option_t *options; /* Preset options and properties */ + ppd_size_t *ppd_size; /* Current PPD size */ + _pwg_size_t *pwg_size; /* Current PWG size */ + char pwg_keyword[3 + PPD_MAX_NAME + 1 + 12 + 1 + 12 + 3], + /* PWG keyword string */ + ppd_name[PPD_MAX_NAME]; + /* Normalized PPD name */ + const char *pwg_name; /* Standard PWG media name */ + _pwg_media_t *pwg_media; /* PWG media data */ + _pwg_print_color_mode_t pwg_print_color_mode; + /* print-color-mode index */ + _pwg_print_quality_t pwg_print_quality; + /* print-quality index */ + int similar; /* Are the old and new size similar? */ + _pwg_size_t *old_size; /* Current old size */ + int old_imageable, /* Old imageable length in 2540ths */ + old_borderless, /* Old borderless state */ + old_known_pwg; /* Old PWG name is well-known */ + int new_width, /* New width in 2540ths */ + new_length, /* New length in 2540ths */ + new_left, /* New left margin in 2540ths */ + new_bottom, /* New bottom margin in 2540ths */ + new_right, /* New right margin in 2540ths */ + new_top, /* New top margin in 2540ths */ + new_imageable, /* New imageable length in 2540ths */ + new_borderless, /* New borderless state */ + new_known_pwg; /* New PWG name is well-known */ + _pwg_size_t *new_size; /* New size to add, if any */ + const char *filter; /* Current filter */ + + + DEBUG_printf(("_ppdCacheCreateWithPPD(ppd=%p)", ppd)); + + /* + * Range check input... + */ + + if (!ppd) + return (NULL); + + /* + * Allocate memory... + */ + + if ((pc = calloc(1, sizeof(_ppd_cache_t))) == NULL) + { + DEBUG_puts("_ppdCacheCreateWithPPD: Unable to allocate _ppd_cache_t."); + goto create_error; + } + + /* + * 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 ++) + { + /* + * Don't copy over custom size... + */ + + if (!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) + { + /* + * 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; + } + } + + if (pwg_media) + { + /* + * Standard name and no conflicts, use it! + */ + + pwg_name = pwg_media->pwg; + new_known_pwg = 1; + } + else + { + /* + * Not a standard name; convert it to a PWG vendor name of the form: + * + * pp_lowerppd_WIDTHxHEIGHTuu + */ + + 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 we have a similar paper with non-zero margins then we only + * want to keep it if it has a larger imageable area length. + */ + + new_width = _PWG_FROMPTS(ppd_size->width); + new_length = _PWG_FROMPTS(ppd_size->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; + } + } + + if (ppd->variable_sizes) + { + /* + * Generate custom size data... + */ + + _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max", + _PWG_FROMPTS(ppd->custom_max[0]), + _PWG_FROMPTS(ppd->custom_max[1])); + pc->custom_max_keyword = _cupsStrAlloc(pwg_keyword); + pc->custom_max_width = _PWG_FROMPTS(ppd->custom_max[0]); + pc->custom_max_length = _PWG_FROMPTS(ppd->custom_max[1]); + + _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min", + _PWG_FROMPTS(ppd->custom_min[0]), + _PWG_FROMPTS(ppd->custom_min[1])); + pc->custom_min_keyword = _cupsStrAlloc(pwg_keyword); + pc->custom_min_width = _PWG_FROMPTS(ppd->custom_min[0]); + pc->custom_min_length = _PWG_FROMPTS(ppd->custom_min[1]); + + pc->custom_size.left = _PWG_FROMPTS(ppd->custom_margins[0]); + pc->custom_size.bottom = _PWG_FROMPTS(ppd->custom_margins[1]); + pc->custom_size.right = _PWG_FROMPTS(ppd->custom_margins[2]); + pc->custom_size.top = _PWG_FROMPTS(ppd->custom_margins[3]); + } + + /* + * Copy and convert InputSlot data... + */ + + if ((input_slot = ppdFindOption(ppd, "InputSlot")) == NULL) + input_slot = ppdFindOption(ppd, "HPPaperSource"); + + if (input_slot) + { + pc->source_option = _cupsStrAlloc(input_slot->keyword); + + if ((pc->sources = calloc(input_slot->num_choices, + sizeof(_pwg_map_t))) == NULL) + { + DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d " + "_pwg_map_t's for InputSlot.", input_slot->num_choices)); + goto create_error; + } + + pc->num_sources = input_slot->num_choices; + + for (i = input_slot->num_choices, choice = input_slot->choices, + map = pc->sources; + i > 0; + i --, choice ++, map ++) + { + if (!strncasecmp(choice->choice, "Auto", 4) || + !strcasecmp(choice->choice, "Default")) + pwg_name = "auto"; + else if (!strcasecmp(choice->choice, "Cassette")) + pwg_name = "main"; + else if (!strcasecmp(choice->choice, "PhotoTray")) + pwg_name = "photo"; + else if (!strcasecmp(choice->choice, "CDTray")) + pwg_name = "disc"; + else if (!strncasecmp(choice->choice, "Multipurpose", 12) || + !strcasecmp(choice->choice, "MP") || + !strcasecmp(choice->choice, "MPTray")) + pwg_name = "alternate"; + else if (!strcasecmp(choice->choice, "LargeCapacity")) + pwg_name = "large-capacity"; + else if (!strncasecmp(choice->choice, "Lower", 5)) + pwg_name = "bottom"; + else if (!strncasecmp(choice->choice, "Middle", 6)) + pwg_name = "middle"; + else if (!strncasecmp(choice->choice, "Upper", 5)) + pwg_name = "top"; + else if (!strncasecmp(choice->choice, "Side", 4)) + pwg_name = "side"; + else if (!strcasecmp(choice->choice, "Roll") || + !strcasecmp(choice->choice, "Roll1")) + pwg_name = "main-roll"; + else if (!strcasecmp(choice->choice, "Roll2")) + pwg_name = "alternate-roll"; + else + { + /* + * Convert PPD name to lowercase... + */ + + pwg_name = pwg_keyword; + pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword)); + } + + map->pwg = _cupsStrAlloc(pwg_name); + map->ppd = _cupsStrAlloc(choice->choice); + } + } + + /* + * Copy and convert MediaType data... + */ + + if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL) + { + if ((pc->types = calloc(media_type->num_choices, + sizeof(_pwg_map_t))) == NULL) + { + DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d " + "_pwg_map_t's for MediaType.", media_type->num_choices)); + goto create_error; + } + + pc->num_types = media_type->num_choices; + + for (i = media_type->num_choices, choice = media_type->choices, + map = pc->types; + i > 0; + i --, choice ++, map ++) + { + if (!strncasecmp(choice->choice, "Auto", 4) || + !strcasecmp(choice->choice, "Any") || + !strcasecmp(choice->choice, "Default")) + pwg_name = "auto"; + else if (!strncasecmp(choice->choice, "Card", 4)) + pwg_name = "cardstock"; + else if (!strncasecmp(choice->choice, "Env", 3)) + pwg_name = "envelope"; + else if (!strncasecmp(choice->choice, "Gloss", 5)) + pwg_name = "photographic-glossy"; + else if (!strcasecmp(choice->choice, "HighGloss")) + pwg_name = "photographic-high-gloss"; + else if (!strcasecmp(choice->choice, "Matte")) + pwg_name = "photographic-matte"; + else if (!strncasecmp(choice->choice, "Plain", 5)) + pwg_name = "stationery"; + else if (!strncasecmp(choice->choice, "Coated", 6)) + pwg_name = "stationery-coated"; + else if (!strcasecmp(choice->choice, "Inkjet")) + pwg_name = "stationery-inkjet"; + else if (!strcasecmp(choice->choice, "Letterhead")) + pwg_name = "stationery-letterhead"; + else if (!strncasecmp(choice->choice, "Preprint", 8)) + pwg_name = "stationery-preprinted"; + else if (!strncasecmp(choice->choice, "Transparen", 10)) + pwg_name = "transparency"; + else + { + /* + * Convert PPD name to lowercase... + */ + + pwg_name = pwg_keyword; + pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword)); + } + + map->pwg = _cupsStrAlloc(pwg_name); + map->ppd = _cupsStrAlloc(choice->choice); + } + } + + + /* + * Copy and convert OutputBin data... + */ + + if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL) + { + if ((pc->bins = calloc(output_bin->num_choices, + sizeof(_pwg_map_t))) == NULL) + { + DEBUG_printf(("_ppdCacheCreateWithPPD: Unable to allocate %d " + "_pwg_map_t's for OutputBin.", output_bin->num_choices)); + goto create_error; + } + + pc->num_bins = output_bin->num_choices; + + for (i = output_bin->num_choices, choice = output_bin->choices, + map = pc->bins; + i > 0; + i --, choice ++, map ++) + { + pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword)); + + map->pwg = _cupsStrAlloc(pwg_keyword); + map->ppd = _cupsStrAlloc(choice->choice); + } + } + + if ((ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL)) != NULL) + { + /* + * Copy and convert APPrinterPreset (output-mode + print-quality) data... + */ + + const char *quality, /* com.apple.print.preset.quality value */ + *output_mode, /* com.apple.print.preset.output-mode value */ + *color_model_val, /* ColorModel choice */ + *graphicsType, /* com.apple.print.preset.graphicsType value */ + *media_front_coating; /* com.apple.print.preset.media-front-coating value */ + + do + { + num_options = _ppdParseOptions(ppd_attr->value, 0, &options, + _PPD_PARSE_ALL); + + if ((quality = cupsGetOption("com.apple.print.preset.quality", + num_options, options)) != NULL) + { + /* + * Get the print-quality for this preset... + */ + + if (!strcmp(quality, "low")) + pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT; + else if (!strcmp(quality, "high")) + pwg_print_quality = _PWG_PRINT_QUALITY_HIGH; + else + pwg_print_quality = _PWG_PRINT_QUALITY_NORMAL; + + /* + * Ignore graphicsType "Photo" presets that are not high quality. + */ + + graphicsType = cupsGetOption("com.apple.print.preset.graphicsType", + num_options, options); + + if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH && graphicsType && + !strcmp(graphicsType, "Photo")) + continue; + + /* + * Ignore presets for normal and draft quality where the coating + * isn't "none" or "autodetect". + */ + + media_front_coating = cupsGetOption( + "com.apple.print.preset.media-front-coating", + num_options, options); + + if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH && + media_front_coating && + strcmp(media_front_coating, "none") && + strcmp(media_front_coating, "autodetect")) + continue; + + /* + * Get the output mode for this preset... + */ + + output_mode = cupsGetOption("com.apple.print.preset.output-mode", + num_options, options); + color_model_val = cupsGetOption("ColorModel", num_options, options); + + if (output_mode) + { + if (!strcmp(output_mode, "monochrome")) + pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME; + else + pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR; + } + else if (color_model_val) + { + if (!strcasecmp(color_model_val, "Gray")) + pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME; + else + pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR; + } + else + pwg_print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR; + + /* + * Save the options for this combination as needed... + */ + + if (!pc->num_presets[pwg_print_color_mode][pwg_print_quality]) + pc->num_presets[pwg_print_color_mode][pwg_print_quality] = + _ppdParseOptions(ppd_attr->value, 0, + pc->presets[pwg_print_color_mode] + + pwg_print_quality, _PPD_PARSE_OPTIONS); + } + + cupsFreeOptions(num_options, options); + } + while ((ppd_attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL)) != NULL); + } + + if (!pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_DRAFT] && + !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_NORMAL] && + !pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][_PWG_PRINT_QUALITY_HIGH]) + { + /* + * Try adding some common color options to create grayscale presets. These + * are listed in order of popularity... + */ + + const char *color_option = NULL, /* Color control option */ + *gray_choice = NULL; /* Choice to select grayscale */ + + if ((color_model = ppdFindOption(ppd, "ColorModel")) != NULL && + ppdFindChoice(color_model, "Gray")) + { + color_option = "ColorModel"; + gray_choice = "Gray"; + } + else if ((color_model = ppdFindOption(ppd, "HPColorMode")) != NULL && + ppdFindChoice(color_model, "grayscale")) + { + color_option = "HPColorMode"; + gray_choice = "grayscale"; + } + else if ((color_model = ppdFindOption(ppd, "BRMonoColor")) != NULL && + ppdFindChoice(color_model, "Mono")) + { + color_option = "BRMonoColor"; + gray_choice = "Mono"; + } + else if ((color_model = ppdFindOption(ppd, "CNIJSGrayScale")) != NULL && + ppdFindChoice(color_model, "1")) + { + color_option = "CNIJSGrayScale"; + gray_choice = "1"; + } + else if ((color_model = ppdFindOption(ppd, "HPColorAsGray")) != NULL && + ppdFindChoice(color_model, "True")) + { + color_option = "HPColorAsGray"; + gray_choice = "True"; + } + + if (color_option && gray_choice) + { + /* + * Copy and convert ColorModel (output-mode) data... + */ + + cups_option_t *coption, /* Color option */ + *moption; /* Monochrome option */ + + for (pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT; + pwg_print_quality < _PWG_PRINT_QUALITY_MAX; + pwg_print_quality ++) + { + if (pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][pwg_print_quality]) + { + /* + * Copy the color options... + */ + + num_options = pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR] + [pwg_print_quality]; + options = calloc(sizeof(cups_option_t), num_options); + + if (options) + { + for (i = num_options, moption = options, + coption = pc->presets[_PWG_PRINT_COLOR_MODE_COLOR] + [pwg_print_quality]; + i > 0; + i --, moption ++, coption ++) + { + moption->name = _cupsStrRetain(coption->name); + moption->value = _cupsStrRetain(coption->value); + } + + pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] = + num_options; + pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] = + options; + } + } + else if (pwg_print_quality != _PWG_PRINT_QUALITY_NORMAL) + continue; + + /* + * Add the grayscale option to the preset... + */ + + pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME][pwg_print_quality] = + cupsAddOption(color_option, gray_choice, + pc->num_presets[_PWG_PRINT_COLOR_MODE_MONOCHROME] + [pwg_print_quality], + pc->presets[_PWG_PRINT_COLOR_MODE_MONOCHROME] + + pwg_print_quality); + } + } + } + + /* + * Copy and convert Duplex (sides) data... + */ + + if ((duplex = ppdFindOption(ppd, "Duplex")) == NULL) + if ((duplex = ppdFindOption(ppd, "JCLDuplex")) == NULL) + if ((duplex = ppdFindOption(ppd, "EFDuplex")) == NULL) + if ((duplex = ppdFindOption(ppd, "EFDuplexing")) == NULL) + duplex = ppdFindOption(ppd, "KD03Duplex"); + + if (duplex) + { + pc->sides_option = _cupsStrAlloc(duplex->keyword); + + for (i = duplex->num_choices, choice = duplex->choices; + i > 0; + i --, choice ++) + { + if ((!strcasecmp(choice->choice, "None") || + !strcasecmp(choice->choice, "False")) && !pc->sides_1sided) + pc->sides_1sided = _cupsStrAlloc(choice->choice); + else if ((!strcasecmp(choice->choice, "DuplexNoTumble") || + !strcasecmp(choice->choice, "LongEdge") || + !strcasecmp(choice->choice, "Top")) && !pc->sides_2sided_long) + pc->sides_2sided_long = _cupsStrAlloc(choice->choice); + else if ((!strcasecmp(choice->choice, "DuplexTumble") || + !strcasecmp(choice->choice, "ShortEdge") || + !strcasecmp(choice->choice, "Bottom")) && + !pc->sides_2sided_short) + pc->sides_2sided_short = _cupsStrAlloc(choice->choice); + } + } + + /* + * Copy filters and pre-filters... + */ + + pc->filters = cupsArrayNew3(NULL, NULL, NULL, 0, + (cups_acopy_func_t)_cupsStrAlloc, + (cups_afree_func_t)_cupsStrFree); + + cupsArrayAdd(pc->filters, + "application/vnd.cups-raw application/octet-stream 0 -"); + + if ((ppd_attr = ppdFindAttr(ppd, "cupsFilter2", NULL)) != NULL) + { + do + { + cupsArrayAdd(pc->filters, ppd_attr->value); + } + while ((ppd_attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) != NULL); + } + else if (ppd->num_filters > 0) + { + for (i = 0; i < ppd->num_filters; i ++) + cupsArrayAdd(pc->filters, ppd->filters[i]); + } + else + cupsArrayAdd(pc->filters, "application/vnd.cups-postscript 0 -"); + + /* + * See if we have a command filter... + */ + + for (filter = (const char *)cupsArrayFirst(pc->filters); + filter; + filter = (const char *)cupsArrayNext(pc->filters)) + if (!strncasecmp(filter, "application/vnd.cups-command", 28) && + _cups_isspace(filter[28])) + break; + + if (!filter && + ((ppd_attr = ppdFindAttr(ppd, "cupsCommands", NULL)) == NULL || + strcasecmp(ppd_attr->value, "none"))) + { + /* + * No command filter and no cupsCommands keyword telling us not to use one. + * See if this is a PostScript printer, and if so add a PostScript command + * filter... + */ + + for (filter = (const char *)cupsArrayFirst(pc->filters); + filter; + filter = (const char *)cupsArrayNext(pc->filters)) + if (!strncasecmp(filter, "application/vnd.cups-postscript", 31) && + _cups_isspace(filter[31])) + break; + + if (filter) + cupsArrayAdd(pc->filters, + "application/vnd.cups-command application/postscript 0 -"); + } + + if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL) + { + pc->prefilters = cupsArrayNew3(NULL, NULL, NULL, 0, + (cups_acopy_func_t)_cupsStrAlloc, + (cups_afree_func_t)_cupsStrFree); + + do + { + cupsArrayAdd(pc->prefilters, ppd_attr->value); + } + while ((ppd_attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL)) != NULL); + } + + /* + * Copy the product string, if any... + */ + + if (ppd->product) + pc->product = _cupsStrAlloc(ppd->product); + + /* + * Return the cache data... + */ + + return (pc); + + /* + * If we get here we need to destroy the PWG mapping data and return NULL... + */ + + create_error: + + _cupsSetError(IPP_INTERNAL_ERROR, _("Out of memory."), 1); + _ppdCacheDestroy(pc); + + return (NULL); +} + + +/* + * '_ppdCacheDestroy()' - Free all memory used for PWG mapping data. + */ + +void +_ppdCacheDestroy(_ppd_cache_t *pc) /* I - PPD cache and mapping data */ +{ + int i; /* Looping var */ + _pwg_map_t *map; /* Current map */ + _pwg_size_t *size; /* Current size */ + + + /* + * Range check input... + */ + + if (!pc) + return; + + /* + * Free memory as needed... + */ + + if (pc->bins) + { + for (i = pc->num_bins, map = pc->bins; i > 0; i --, map ++) + { + _cupsStrFree(map->pwg); + _cupsStrFree(map->ppd); + } + + free(pc->bins); + } + + if (pc->sizes) + { + for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++) + { + _cupsStrFree(size->map.pwg); + _cupsStrFree(size->map.ppd); + } + + free(pc->sizes); + } + + if (pc->source_option) + _cupsStrFree(pc->source_option); + + if (pc->sources) + { + for (i = pc->num_sources, map = pc->sources; i > 0; i --, map ++) + { + _cupsStrFree(map->pwg); + _cupsStrFree(map->ppd); + } + + free(pc->sources); + } + + if (pc->types) + { + for (i = pc->num_types, map = pc->types; i > 0; i --, map ++) + { + _cupsStrFree(map->pwg); + _cupsStrFree(map->ppd); + } + + free(pc->types); + } + + if (pc->custom_max_keyword) + _cupsStrFree(pc->custom_max_keyword); + + if (pc->custom_min_keyword) + _cupsStrFree(pc->custom_min_keyword); + + _cupsStrFree(pc->product); + cupsArrayDelete(pc->filters); + cupsArrayDelete(pc->prefilters); + + free(pc); +} + + +/* + * '_ppdCacheGetBin()' - Get the PWG output-bin keyword associated with a PPD + * OutputBin. + */ + +const char * /* O - output-bin or NULL */ +_ppdCacheGetBin( + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ + const char *output_bin) /* I - PPD OutputBin string */ +{ + int i; /* Looping var */ + + + /* + * Range check input... + */ + + if (!pc || !output_bin) + return (NULL); + + /* + * Look up the OutputBin string... + */ + + + for (i = 0; i < pc->num_bins; i ++) + if (!strcasecmp(output_bin, pc->bins[i].ppd)) + return (pc->bins[i].pwg); + + return (NULL); +} + + +/* + * '_ppdCacheGetInputSlot()' - Get the PPD InputSlot associated with the job + * attributes or a keyword string. + */ + +const char * /* O - PPD InputSlot or NULL */ +_ppdCacheGetInputSlot( + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ + ipp_t *job, /* I - Job attributes or NULL */ + const char *keyword) /* I - Keyword string or NULL */ +{ + /* + * Range check input... + */ + + if (!pc || pc->num_sources == 0 || (!job && !keyword)) + return (NULL); + + if (job && !keyword) + { + /* + * Lookup the media-col attribute and any media-source found there... + */ + + ipp_attribute_t *media_col, /* media-col attribute */ + *media_source; /* media-source attribute */ + _pwg_size_t size; /* Dimensional size */ + int margins_set; /* Were the margins set? */ + + media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION); + if (media_col && + (media_source = ippFindAttribute(media_col->values[0].collection, + "media-source", + IPP_TAG_KEYWORD)) != NULL) + { + /* + * Use the media-source value from media-col... + */ + + keyword = media_source->values[0].string.text; + } + else if (_pwgInitSize(&size, job, &margins_set)) + { + /* + * For media <= 5x7, look for a photo tray... + */ + + if (size.width <= (5 * 2540) && size.length <= (7 * 2540)) + keyword = "photo"; + } + } + + if (keyword) + { + int i; /* Looping var */ + + for (i = 0; i < pc->num_sources; i ++) + if (!strcasecmp(keyword, pc->sources[i].pwg)) + return (pc->sources[i].ppd); + } + + return (NULL); +} + + +/* + * '_ppdCacheGetMediaType()' - Get the PPD MediaType associated with the job + * attributes or a keyword string. + */ + +const char * /* O - PPD MediaType or NULL */ +_ppdCacheGetMediaType( + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ + ipp_t *job, /* I - Job attributes or NULL */ + const char *keyword) /* I - Keyword string or NULL */ +{ + /* + * Range check input... + */ + + if (!pc || pc->num_types == 0 || (!job && !keyword)) + return (NULL); + + if (job && !keyword) + { + /* + * Lookup the media-col attribute and any media-source found there... + */ + + ipp_attribute_t *media_col, /* media-col attribute */ + *media_type; /* media-type attribute */ + + media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION); + if (media_col) + { + if ((media_type = ippFindAttribute(media_col->values[0].collection, + "media-type", + IPP_TAG_KEYWORD)) == NULL) + media_type = ippFindAttribute(media_col->values[0].collection, + "media-type", IPP_TAG_NAME); + + if (media_type) + keyword = media_type->values[0].string.text; + } + } + + if (keyword) + { + int i; /* Looping var */ + + for (i = 0; i < pc->num_types; i ++) + if (!strcasecmp(keyword, pc->types[i].pwg)) + return (pc->types[i].ppd); + } + + return (NULL); +} + + +/* + * '_ppdCacheGetOutputBin()' - Get the PPD OutputBin associated with the keyword + * string. + */ + +const char * /* O - PPD OutputBin or NULL */ +_ppdCacheGetOutputBin( + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ + const char *output_bin) /* I - Keyword string */ +{ + int i; /* Looping var */ + + + /* + * Range check input... + */ + + if (!pc || !output_bin) + return (NULL); + + /* + * Look up the OutputBin string... + */ + + + for (i = 0; i < pc->num_bins; i ++) + if (!strcasecmp(output_bin, pc->bins[i].pwg)) + return (pc->bins[i].ppd); + + return (NULL); +} + + +/* + * '_ppdCacheGetPageSize()' - Get the PPD PageSize associated with the job + * attributes or a keyword string. + */ + +const char * /* O - PPD PageSize or NULL */ +_ppdCacheGetPageSize( + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ + ipp_t *job, /* I - Job attributes or NULL */ + const char *keyword, /* I - Keyword string or NULL */ + int *exact) /* O - 1 if exact match, 0 otherwise */ +{ + int i; /* Looping var */ + _pwg_size_t *size, /* Current size */ + *closest, /* Closest size */ + jobsize; /* Size data from job */ + int margins_set, /* Were the margins set? */ + dwidth, /* Difference in width */ + dlength, /* Difference in length */ + dleft, /* Difference in left margins */ + dright, /* Difference in right margins */ + dbottom, /* Difference in bottom margins */ + dtop, /* Difference in top margins */ + dmin, /* Minimum difference */ + dclosest; /* Closest difference */ + const char *ppd_name; /* PPD media name */ + + + DEBUG_printf(("_ppdCacheGetPageSize(pc=%p, job=%p, keyword=\"%s\", exact=%p)", + pc, job, keyword, exact)); + + /* + * Range check input... + */ + + if (!pc || (!job && !keyword)) + return (NULL); + + if (exact) + *exact = 0; + + ppd_name = keyword; + + if (job) + { + /* + * Try getting the PPD media name from the job attributes... + */ + + ipp_attribute_t *attr; /* Job attribute */ + + if ((attr = ippFindAttribute(job, "PageSize", IPP_TAG_ZERO)) == NULL) + if ((attr = ippFindAttribute(job, "PageRegion", IPP_TAG_ZERO)) == NULL) + attr = ippFindAttribute(job, "media", IPP_TAG_ZERO); + +#ifdef DEBUG + if (attr) + DEBUG_printf(("1_ppdCacheGetPageSize: Found attribute %s (%s)", + attr->name, ippTagString(attr->value_tag))); + else + DEBUG_puts("1_ppdCacheGetPageSize: Did not find media attribute."); +#endif /* DEBUG */ + + if (attr && (attr->value_tag == IPP_TAG_NAME || + attr->value_tag == IPP_TAG_KEYWORD)) + ppd_name = attr->values[0].string.text; + } + + DEBUG_printf(("1_ppdCacheGetPageSize: ppd_name=\"%s\"", ppd_name)); + + if (ppd_name) + { + /* + * Try looking up the named PPD size first... + */ + + for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++) + { + DEBUG_printf(("2_ppdCacheGetPageSize: size[%d]=[\"%s\" \"%s\"]", + (int)(size - pc->sizes), size->map.pwg, size->map.ppd)); + + if (!strcasecmp(ppd_name, size->map.ppd) || + !strcasecmp(ppd_name, size->map.pwg)) + { + if (exact) + *exact = 1; + + DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\"", ppd_name)); + + return (size->map.ppd); + } + } + } + + if (job && !keyword) + { + /* + * Get the size using media-col or media, with the preference being + * media-col. + */ + + if (!_pwgInitSize(&jobsize, job, &margins_set)) + return (NULL); + } + else + { + /* + * Get the size using a media keyword... + */ + + _pwg_media_t *media; /* Media definition */ + + + if ((media = _pwgMediaForPWG(keyword)) == NULL) + if ((media = _pwgMediaForLegacy(keyword)) == NULL) + if ((media = _pwgMediaForPPD(keyword)) == NULL) + return (NULL); + + jobsize.width = media->width; + jobsize.length = media->length; + margins_set = 0; + } + + /* + * Now that we have the dimensions and possibly the margins, look at the + * available sizes and find the match... + */ + + closest = NULL; + dclosest = 999999999; + + if (!ppd_name || strncasecmp(ppd_name, "Custom.", 7) || + strncasecmp(ppd_name, "custom_", 7)) + { + for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++) + { + /* + * Adobe uses a size matching algorithm with an epsilon of 5 points, which + * is just about 176/2540ths... + */ + + dwidth = size->width - jobsize.width; + dlength = size->length - jobsize.length; + + if (dwidth <= -176 || dwidth >= 176 || dlength <= -176 || dlength >= 176) + continue; + + if (margins_set) + { + /* + * Use a tighter epsilon of 1 point (35/2540ths) for margins... + */ + + dleft = size->left - jobsize.left; + dright = size->right - jobsize.right; + dtop = size->top - jobsize.top; + dbottom = size->bottom - jobsize.bottom; + + if (dleft <= -35 || dleft >= 35 || dright <= -35 || dright >= 35 || + dtop <= -35 || dtop >= 35 || dbottom <= -35 || dbottom >= 35) + { + dleft = dleft < 0 ? -dleft : dleft; + dright = dright < 0 ? -dright : dright; + dbottom = dbottom < 0 ? -dbottom : dbottom; + dtop = dtop < 0 ? -dtop : dtop; + dmin = dleft + dright + dbottom + dtop; + + if (dmin < dclosest) + { + dclosest = dmin; + closest = size; + } + + continue; + } + } + + if (exact) + *exact = 1; + + DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\"", size->map.ppd)); + + return (size->map.ppd); + } + } + + if (closest) + { + DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\" (closest)", + closest->map.ppd)); + + return (closest->map.ppd); + } + + /* + * If we get here we need to check for custom page size support... + */ + + if (jobsize.width >= pc->custom_min_width && + jobsize.width <= pc->custom_max_width && + jobsize.length >= pc->custom_min_length && + jobsize.length <= pc->custom_max_length) + { + /* + * In range, format as Custom.WWWWxLLLL (points). + */ + + snprintf(pc->custom_ppd_size, sizeof(pc->custom_ppd_size), "Custom.%dx%d", + (int)_PWG_TOPTS(jobsize.width), (int)_PWG_TOPTS(jobsize.length)); + + if (margins_set && exact) + { + dleft = pc->custom_size.left - jobsize.left; + dright = pc->custom_size.right - jobsize.right; + dtop = pc->custom_size.top - jobsize.top; + dbottom = pc->custom_size.bottom - jobsize.bottom; + + if (dleft > -35 && dleft < 35 && dright > -35 && dright < 35 && + dtop > -35 && dtop < 35 && dbottom > -35 && dbottom < 35) + *exact = 1; + } + else if (exact) + *exact = 1; + + DEBUG_printf(("1_ppdCacheGetPageSize: Returning \"%s\" (custom)", + pc->custom_ppd_size)); + + return (pc->custom_ppd_size); + } + + /* + * No custom page size support or the size is out of range - return NULL. + */ + + DEBUG_puts("1_ppdCacheGetPageSize: Returning NULL"); + + return (NULL); +} + + +/* + * '_ppdCacheGetSize()' - Get the PWG size associated with a PPD PageSize. + */ + +_pwg_size_t * /* O - PWG size or NULL */ +_ppdCacheGetSize( + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ + const char *page_size) /* I - PPD PageSize */ +{ + int i; + _pwg_size_t *size; /* Current size */ + + + /* + * Range check input... + */ + + if (!pc || !page_size) + return (NULL); + + if (!strncasecmp(page_size, "Custom.", 7)) + { + /* + * Custom size; size name can be one of the following: + * + * Custom.WIDTHxLENGTHin - Size in inches + * Custom.WIDTHxLENGTHft - Size in feet + * Custom.WIDTHxLENGTHcm - Size in centimeters + * Custom.WIDTHxLENGTHmm - Size in millimeters + * Custom.WIDTHxLENGTHm - Size in meters + * Custom.WIDTHxLENGTH[pt] - Size in points + */ + + double w, l; /* Width and length of page */ + char *ptr; /* Pointer into PageSize */ + struct lconv *loc; /* Locale data */ + + loc = localeconv(); + w = (float)_cupsStrScand(page_size + 7, &ptr, loc); + if (!ptr || *ptr != 'x') + return (NULL); + + l = (float)_cupsStrScand(ptr + 1, &ptr, loc); + if (!ptr) + return (NULL); + + if (!strcasecmp(ptr, "in")) + { + w *= 2540.0; + l *= 2540.0; + } + else if (!strcasecmp(ptr, "ft")) + { + w *= 12.0 * 2540.0; + l *= 12.0 * 2540.0; + } + else if (!strcasecmp(ptr, "mm")) + { + w *= 100.0; + l *= 100.0; + } + else if (!strcasecmp(ptr, "cm")) + { + w *= 1000.0; + l *= 1000.0; + } + else if (!strcasecmp(ptr, "m")) + { + w *= 100000.0; + l *= 100000.0; + } + else + { + w *= 2540.0 / 72.0; + l *= 2540.0 / 72.0; + } + + pc->custom_size.width = (int)w; + pc->custom_size.length = (int)l; + + return (&(pc->custom_size)); + } + + /* + * Not a custom size - look it up... + */ + + for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++) + if (!strcasecmp(page_size, size->map.ppd)) + return (size); + + return (NULL); +} + + +/* + * '_ppdCacheGetSource()' - Get the PWG media-source associated with a PPD + * InputSlot. + */ + +const char * /* O - PWG media-source keyword */ +_ppdCacheGetSource( + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ + const char *input_slot) /* I - PPD InputSlot */ +{ + int i; /* Looping var */ + _pwg_map_t *source; /* Current source */ + + + /* + * Range check input... + */ + + if (!pc || !input_slot) + return (NULL); + + for (i = pc->num_sources, source = pc->sources; i > 0; i --, source ++) + if (!strcasecmp(input_slot, source->ppd)) + return (source->pwg); + + return (NULL); +} + + +/* + * '_ppdCacheGetType()' - Get the PWG media-type associated with a PPD + * MediaType. + */ + +const char * /* O - PWG media-type keyword */ +_ppdCacheGetType( + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ + const char *media_type) /* I - PPD MediaType */ +{ + int i; /* Looping var */ + _pwg_map_t *type; /* Current type */ + + + /* + * Range check input... + */ + + if (!pc || !media_type) + return (NULL); + + for (i = pc->num_types, type = pc->types; i > 0; i --, type ++) + if (!strcasecmp(media_type, type->ppd)) + return (type->pwg); + + return (NULL); +} + + +/* + * '_ppdCacheWriteFile()' - Write PWG mapping data to a file. + */ + +int /* O - 1 on success, 0 on failure */ +_ppdCacheWriteFile( + _ppd_cache_t *pc, /* I - PPD cache and mapping data */ + const char *filename, /* I - File to write */ + ipp_t *attrs) /* I - Attributes to write, if any */ +{ + int i, j, k; /* Looping vars */ + cups_file_t *fp; /* Output file */ + _pwg_size_t *size; /* Current size */ + _pwg_map_t *map; /* Current map */ + cups_option_t *option; /* Current option */ + const char *value; /* Filter/pre-filter value */ + + + /* + * Range check input... + */ + + if (!pc || !filename) + { + _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0); + return (0); + } + + /* + * Open the file and write with compression... + */ + + if ((fp = cupsFileOpen(filename, "w9")) == NULL) + { + _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); + return (0); + } + + /* + * Standard header... + */ + + cupsFilePrintf(fp, "#CUPS-PPD-CACHE-%d\n", _PPD_CACHE_VERSION); + + /* + * Output bins... + */ + + if (pc->num_bins > 0) + { + cupsFilePrintf(fp, "NumBins %d\n", pc->num_bins); + for (i = pc->num_bins, map = pc->bins; i > 0; i --, map ++) + cupsFilePrintf(fp, "Bin %s %s\n", map->pwg, map->ppd); + } + + /* + * Media sizes... + */ + + cupsFilePrintf(fp, "NumSizes %d\n", pc->num_sizes); + for (i = pc->num_sizes, size = pc->sizes; i > 0; i --, size ++) + cupsFilePrintf(fp, "Size %s %s %d %d %d %d %d %d\n", size->map.pwg, + size->map.ppd, size->width, size->length, size->left, + size->bottom, size->right, size->top); + if (pc->custom_max_width > 0) + cupsFilePrintf(fp, "CustomSize %d %d %d %d %d %d %d %d\n", + pc->custom_max_width, pc->custom_max_length, + pc->custom_min_width, pc->custom_min_length, + pc->custom_size.left, pc->custom_size.bottom, + pc->custom_size.right, pc->custom_size.top); + + /* + * Media sources... + */ + + if (pc->source_option) + cupsFilePrintf(fp, "SourceOption %s\n", pc->source_option); + + if (pc->num_sources > 0) + { + cupsFilePrintf(fp, "NumSources %d\n", pc->num_sources); + for (i = pc->num_sources, map = pc->sources; i > 0; i --, map ++) + cupsFilePrintf(fp, "Source %s %s\n", map->pwg, map->ppd); + } + + /* + * Media types... + */ + + if (pc->num_types > 0) + { + cupsFilePrintf(fp, "NumTypes %d\n", pc->num_types); + for (i = pc->num_types, map = pc->types; i > 0; i --, map ++) + cupsFilePrintf(fp, "Type %s %s\n", map->pwg, map->ppd); + } + + /* + * Presets... + */ + + for (i = _PWG_PRINT_COLOR_MODE_MONOCHROME; i < _PWG_PRINT_COLOR_MODE_MAX; i ++) + for (j = _PWG_PRINT_QUALITY_DRAFT; j < _PWG_PRINT_QUALITY_MAX; j ++) + if (pc->num_presets[i][j]) + { + cupsFilePrintf(fp, "Preset %d %d", i, j); + for (k = pc->num_presets[i][j], option = pc->presets[i][j]; + k > 0; + k --, option ++) + cupsFilePrintf(fp, " %s=%s", option->name, option->value); + cupsFilePutChar(fp, '\n'); + } + + /* + * Duplex/sides... + */ + + if (pc->sides_option) + cupsFilePrintf(fp, "SidesOption %s\n", pc->sides_option); + + if (pc->sides_1sided) + cupsFilePrintf(fp, "Sides1Sided %s\n", pc->sides_1sided); + + if (pc->sides_2sided_long) + cupsFilePrintf(fp, "Sides2SidedLong %s\n", pc->sides_2sided_long); + + if (pc->sides_2sided_short) + cupsFilePrintf(fp, "Sides2SidedShort %s\n", pc->sides_2sided_short); + + /* + * Product, cupsFilter, cupsFilter2, and cupsPreFilter... + */ + + if (pc->product) + cupsFilePutConf(fp, "Product", pc->product); + + for (value = (const char *)cupsArrayFirst(pc->filters); + value; + value = (const char *)cupsArrayNext(pc->filters)) + cupsFilePutConf(fp, "Filter", value); + + for (value = (const char *)cupsArrayFirst(pc->prefilters); + value; + value = (const char *)cupsArrayNext(pc->prefilters)) + cupsFilePutConf(fp, "PreFilter", value); + + /* + * IPP attributes, if any... + */ + + if (attrs) + { + cupsFilePrintf(fp, "IPP " CUPS_LLFMT "\n", CUPS_LLCAST ippLength(attrs)); + + attrs->state = IPP_IDLE; + ippWriteIO(fp, (ipp_iocb_t)cupsFileWrite, 1, NULL, attrs); + } + + /* + * Close and return... + */ + + return (!cupsFileClose(fp)); +} + + +/* + * '_pwgInputSlotForSource()' - Get the InputSlot name for the given PWG + * media-source. + */ + +const char * /* O - InputSlot name */ +_pwgInputSlotForSource( + const char *media_source, /* I - PWG media-source */ + char *name, /* I - Name buffer */ + size_t namesize) /* I - Size of name buffer */ +{ + /* + * Range check input... + */ + + if (!media_source || !name || namesize < PPD_MAX_NAME) + return (NULL); + + if (strcasecmp(media_source, "main")) + strlcpy(name, "Cassette", namesize); + else if (strcasecmp(media_source, "alternate")) + strlcpy(name, "Multipurpose", namesize); + else if (strcasecmp(media_source, "large-capacity")) + strlcpy(name, "LargeCapacity", namesize); + else if (strcasecmp(media_source, "bottom")) + strlcpy(name, "Lower", namesize); + else if (strcasecmp(media_source, "middle")) + strlcpy(name, "Middle", namesize); + else if (strcasecmp(media_source, "top")) + strlcpy(name, "Upper", namesize); + else if (strcasecmp(media_source, "rear")) + strlcpy(name, "Rear", namesize); + else if (strcasecmp(media_source, "side")) + strlcpy(name, "Side", namesize); + else if (strcasecmp(media_source, "envelope")) + strlcpy(name, "Envelope", namesize); + else if (strcasecmp(media_source, "main-roll")) + strlcpy(name, "Roll", namesize); + else if (strcasecmp(media_source, "alternate-roll")) + strlcpy(name, "Roll2", namesize); + else + pwg_ppdize_name(media_source, name, namesize); + + return (name); +} + + +/* + * '_pwgMediaTypeForType()' - Get the MediaType name for the given PWG + * media-type. + */ + +const char * /* O - MediaType name */ +_pwgMediaTypeForType( + const char *media_type, /* I - PWG media-type */ + char *name, /* I - Name buffer */ + size_t namesize) /* I - Size of name buffer */ +{ + /* + * Range check input... + */ + + if (!media_type || !name || namesize < PPD_MAX_NAME) + return (NULL); + + if (strcasecmp(media_type, "auto")) + strlcpy(name, "Auto", namesize); + else if (strcasecmp(media_type, "cardstock")) + strlcpy(name, "Cardstock", namesize); + else if (strcasecmp(media_type, "envelope")) + strlcpy(name, "Envelope", namesize); + else if (strcasecmp(media_type, "photographic-glossy")) + strlcpy(name, "Glossy", namesize); + else if (strcasecmp(media_type, "photographic-high-gloss")) + strlcpy(name, "HighGloss", namesize); + else if (strcasecmp(media_type, "photographic-matte")) + strlcpy(name, "Matte", namesize); + else if (strcasecmp(media_type, "stationery")) + strlcpy(name, "Plain", namesize); + else if (strcasecmp(media_type, "stationery-coated")) + strlcpy(name, "Coated", namesize); + else if (strcasecmp(media_type, "stationery-inkjet")) + strlcpy(name, "Inkjet", namesize); + else if (strcasecmp(media_type, "stationery-letterhead")) + strlcpy(name, "Letterhead", namesize); + else if (strcasecmp(media_type, "stationery-preprinted")) + strlcpy(name, "Preprinted", namesize); + else if (strcasecmp(media_type, "transparency")) + strlcpy(name, "Transparency", namesize); + else + pwg_ppdize_name(media_type, name, namesize); + + return (name); +} + + +/* + * '_pwgPageSizeForMedia()' - Get the PageSize name for the given media. + */ + +const char * /* O - PageSize name */ +_pwgPageSizeForMedia( + _pwg_media_t *media, /* I - Media */ + char *name, /* I - PageSize name buffer */ + size_t namesize) /* I - Size of name buffer */ +{ + const char *sizeptr, /* Pointer to size in PWG name */ + *dimptr; /* Pointer to dimensions in PWG name */ + + + /* + * Range check input... + */ + + if (!media || !name || namesize < PPD_MAX_NAME) + return (NULL); + + /* + * Copy or generate a PageSize name... + */ + + if (media->ppd) + { + /* + * Use a standard Adobe name... + */ + + strlcpy(name, media->ppd, namesize); + } + else if (!media->pwg || !strncmp(media->pwg, "custom_", 7) || + (sizeptr = strchr(media->pwg, '_')) == NULL || + (dimptr = strchr(sizeptr + 1, '_')) == NULL || + (size_t)(dimptr - sizeptr) > namesize) + { + /* + * Use a name of the form "wNNNhNNN"... + */ + + snprintf(name, namesize, "w%dh%d", (int)_PWG_TOPTS(media->width), + (int)_PWG_TOPTS(media->length)); + } + else + { + /* + * Copy the size name from class_sizename_dimensions... + */ + + memcpy(name, sizeptr + 1, dimptr - sizeptr - 1); + name[dimptr - sizeptr - 1] = '\0'; + } + + return (name); +} + + +/* + * 'pwg_ppdize_name()' - Convert an IPP keyword to a PPD keyword. + */ + +static void +pwg_ppdize_name(const char *ipp, /* I - IPP keyword */ + char *name, /* I - Name buffer */ + size_t namesize) /* I - Size of name buffer */ +{ + char *ptr, /* Pointer into name buffer */ + *end; /* End of name buffer */ + + + *name = toupper(*ipp++); + + for (ptr = name + 1, end = name + namesize - 1; *ipp && ptr < end;) + { + if (*ipp == '-' && _cups_isalpha(ipp[1])) + { + ipp ++; + *ptr++ = toupper(*ipp++ & 255); + } + else + *ptr++ = *ipp++; + } + + *ptr = '\0'; +} + + +/* + * 'pwg_unppdize_name()' - Convert a PPD keyword to a lowercase IPP keyword. + */ + +static void +pwg_unppdize_name(const char *ppd, /* I - PPD keyword */ + char *name, /* I - Name buffer */ + size_t namesize) /* I - Size of name buffer */ +{ + char *ptr, /* Pointer into name buffer */ + *end; /* End of name buffer */ + + + for (ptr = name, end = name + namesize - 1; *ppd && ptr < end; ppd ++) + { + if (_cups_isalnum(*ppd) || *ppd == '-') + *ptr++ = tolower(*ppd & 255); + else if (*ppd == '_' || *ppd == '.') + *ptr++ = '-'; + + if (!_cups_isupper(*ppd) && _cups_isalnum(*ppd) && + _cups_isupper(ppd[1]) && ptr < end) + *ptr++ = '-'; + } + + *ptr = '\0'; +} + + +/* + * End of "$Id$". + */ diff --git a/cups/ppd-private.h b/cups/ppd-private.h index d44c1ca04..e907c46d7 100644 --- a/cups/ppd-private.h +++ b/cups/ppd-private.h @@ -3,7 +3,7 @@ * * Private PPD definitions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -45,6 +45,13 @@ extern "C" { # endif /* __cplusplus */ +/* + * Constants... + */ + +# define _PPD_CACHE_VERSION 1 /* Version number in cache file */ + + /* * Types and structures... */ @@ -71,12 +78,13 @@ typedef struct _ppd_cups_uiconsts_s /**** cupsUIConstraints ****/ _ppd_cups_uiconst_t *constraints; /* Constraints */ } _ppd_cups_uiconsts_t; -typedef enum _pwg_output_mode_e /**** PWG output-mode indices ****/ +typedef enum _pwg_print_color_mode_e /**** PWG print-color-mode indices ****/ { - _PWG_OUTPUT_MODE_MONOCHROME = 0, /* output-mode=monochrome */ - _PWG_OUTPUT_MODE_COLOR, /* output-mode=color */ - _PWG_OUTPUT_MODE_MAX -} _pwg_output_mode_t; + _PWG_PRINT_COLOR_MODE_MONOCHROME = 0, /* print-color-mode=monochrome */ + _PWG_PRINT_COLOR_MODE_COLOR, /* print-color-mode=color */ + /* Other proposed values are not supported by CUPS yet. */ + _PWG_PRINT_COLOR_MODE_MAX +} _pwg_print_color_mode_t; typedef enum _pwg_print_quality_e /**** PWG print-quality indices ****/ { @@ -86,7 +94,7 @@ typedef enum _pwg_print_quality_e /**** PWG print-quality indices ****/ _PWG_PRINT_QUALITY_MAX } _pwg_print_quality_t; -typedef struct _pwg_s /**** PWG-PPD conversion data ****/ +struct _ppd_cache_s /**** PPD cache and PWG conversion data ****/ { int num_bins; /* Number of output bins */ _pwg_map_t *bins; /* Output bins */ @@ -105,21 +113,46 @@ typedef struct _pwg_s /**** PWG-PPD conversion data ****/ _pwg_map_t *sources; /* Media sources */ int num_types; /* Number of media types */ _pwg_map_t *types; /* Media types */ - int num_presets[_PWG_OUTPUT_MODE_MAX][_PWG_PRINT_QUALITY_MAX]; - /* Number of output-mode/print-quality options */ - cups_option_t *presets[_PWG_OUTPUT_MODE_MAX][_PWG_PRINT_QUALITY_MAX]; - /* output-mode/print-quality options */ + int num_presets[_PWG_PRINT_COLOR_MODE_MAX][_PWG_PRINT_QUALITY_MAX]; + /* Number of print-color-mode/print-quality options */ + cups_option_t *presets[_PWG_PRINT_COLOR_MODE_MAX][_PWG_PRINT_QUALITY_MAX]; + /* print-color-mode/print-quality options */ char *sides_option, /* PPD option for sides */ *sides_1sided, /* Choice for one-sided */ *sides_2sided_long, /* Choice for two-sided-long-edge */ *sides_2sided_short; /* Choice for two-sided-short-edge */ -} _pwg_t; + char *product; /* Product value */ + cups_array_t *filters, /* cupsFilter/cupsFilter2 values */ + *prefilters; /* cupsPreFilter values */ +}; /* * Prototypes... */ +extern _ppd_cache_t *_ppdCacheCreateWithFile(const char *filename, + ipp_t **attrs); +extern _ppd_cache_t *_ppdCacheCreateWithPPD(ppd_file_t *ppd); +extern void _ppdCacheDestroy(_ppd_cache_t *pc); +extern const char *_ppdCacheGetBin(_ppd_cache_t *pc, + const char *output_bin); +extern const char *_ppdCacheGetInputSlot(_ppd_cache_t *pc, ipp_t *job, + const char *keyword); +extern const char *_ppdCacheGetMediaType(_ppd_cache_t *pc, ipp_t *job, + const char *keyword); +extern const char *_ppdCacheGetOutputBin(_ppd_cache_t *pc, + const char *keyword); +extern const char *_ppdCacheGetPageSize(_ppd_cache_t *pc, ipp_t *job, + const char *keyword, int *exact); +extern _pwg_size_t *_ppdCacheGetSize(_ppd_cache_t *pc, + const char *page_size); +extern const char *_ppdCacheGetSource(_ppd_cache_t *pc, + const char *input_slot); +extern const char *_ppdCacheGetType(_ppd_cache_t *pc, + const char *media_type); +extern int _ppdCacheWriteFile(_ppd_cache_t *pc, + const char *filename, ipp_t *attrs); extern void _ppdFreeLanguages(cups_array_t *languages); extern cups_encoding_t _ppdGetEncoding(const char *name); extern cups_array_t *_ppdGetLanguages(ppd_file_t *ppd); @@ -132,27 +165,12 @@ extern char *_ppdNormalizeMakeAndModel(const char *make_and_model, extern int _ppdParseOptions(const char *s, int num_options, cups_option_t **options, _ppd_parse_t which); -extern _pwg_t *_pwgCreateWithFile(const char *filename); -extern _pwg_t *_pwgCreateWithPPD(ppd_file_t *ppd); -extern void _pwgDestroy(_pwg_t *pwg); -extern const char *_pwgGetBin(_pwg_t *pwg, const char *output_bin); -extern const char *_pwgGetInputSlot(_pwg_t *pwg, ipp_t *job, - const char *keyword); -extern const char *_pwgGetMediaType(_pwg_t *pwg, ipp_t *job, - const char *keyword); -extern const char *_pwgGetOutputBin(_pwg_t *pwg, const char *keyword); -extern const char *_pwgGetPageSize(_pwg_t *pwg, ipp_t *job, - const char *keyword, int *exact); -extern _pwg_size_t *_pwgGetSize(_pwg_t *pwg, const char *page_size); -extern const char *_pwgGetSource(_pwg_t *pwg, const char *input_slot); -extern const char *_pwgGetType(_pwg_t *pwg, const char *media_type); extern const char *_pwgInputSlotForSource(const char *media_source, char *name, size_t namesize); extern const char *_pwgMediaTypeForType(const char *media_type, - char *name, size_t namesize); + char *name, size_t namesize); extern const char *_pwgPageSizeForMedia(_pwg_media_t *media, char *name, size_t namesize); -extern int _pwgWriteFile(_pwg_t *pwg, const char *filename); /* diff --git a/cups/ppd.c b/cups/ppd.c index f1d236251..89ad18b6b 100644 --- a/cups/ppd.c +++ b/cups/ppd.c @@ -310,11 +310,11 @@ ppdClose(ppd_file_t *ppd) /* I - PPD file record */ } /* - * Free any PWG mapping data... + * Free any PPD cache/mapping data... */ - if (ppd->pwg) - _pwgDestroy((_pwg_t *)ppd->pwg); + if (ppd->cache) + _ppdCacheDestroy(ppd->cache); /* * Free the whole record... diff --git a/cups/ppd.h b/cups/ppd.h index 1b00ae455..7d12fade2 100644 --- a/cups/ppd.h +++ b/cups/ppd.h @@ -273,6 +273,9 @@ typedef struct ppd_coption_s /**** Custom Option @since CUPS 1.2/Mac OS X 10.5@ cups_array_t *params; /* Parameters */ } ppd_coption_t; +typedef struct _ppd_cache_s _ppd_cache_t; + /**** PPD cache and mapping data @since CUPS 1.5@ @private@ ****/ + typedef struct ppd_file_s /**** PPD File ****/ { int language_level; /* Language level of device */ @@ -337,7 +340,7 @@ typedef struct ppd_file_s /**** PPD File ****/ cups_array_t *cups_uiconstraints; /* cupsUIConstraints @since CUPS 1.4/Mac OS X 10.6@ @private@ */ /**** New in CUPS 1.5 ****/ - void *pwg; /* PWG to/from PPD mappings @since CUPS 1.5@ @private@ */ + _ppd_cache_t *cache; /* PPD cache and mapping data @since CUPS 1.5@ @private@ */ } ppd_file_t; diff --git a/cups/pwg-file.c b/cups/pwg-file.c deleted file mode 100644 index 52bac4d3e..000000000 --- a/cups/pwg-file.c +++ /dev/null @@ -1,638 +0,0 @@ -/* - * "$Id$" - * - * PWG load/save API implementation for CUPS. - * - * Copyright 2010 by Apple Inc. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * This file is subject to the Apple OS-Developed Software exception. - * - * Contents: - * - * _pwgCreateWithFile() - Create PWG mapping data from a written file. - * _pwgDestroy() - Free all memory used for PWG mapping data. - * _pwgWriteFile() - Write PWG mapping data to a file. - */ - -/* - * Include necessary headers... - */ - -#include "cups-private.h" -#include - - -/* - * '_pwgCreateWithFile()' - Create PWG mapping data from a written file. - * - * Use the @link _pwgWriteFile@ function to write PWG mapping data to a file. - */ - -_pwg_t * /* O - PWG mapping data */ -_pwgCreateWithFile(const char *filename)/* I - File to read */ -{ - cups_file_t *fp; /* File */ - _pwg_t *pwg; /* PWG mapping data */ - _pwg_size_t *size; /* Current size */ - _pwg_map_t *map; /* Current map */ - int linenum, /* Current line number */ - num_bins, /* Number of bins in file */ - num_sizes, /* Number of sizes in file */ - num_sources, /* Number of sources in file */ - num_types; /* Number of types in file */ - char line[2048], /* Current line */ - *value, /* Pointer to value in line */ - *valueptr, /* Pointer into value */ - pwg_keyword[128], /* PWG keyword */ - ppd_keyword[PPD_MAX_NAME]; - /* PPD keyword */ - _pwg_output_mode_t output_mode; /* Output mode for preset */ - _pwg_print_quality_t print_quality; /* Print quality for preset */ - - - DEBUG_printf(("_pwgCreateWithFile(filename=\"%s\")", filename)); - - /* - * Range check input... - */ - - if (!filename) - { - _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0); - return (NULL); - } - - /* - * Open the file... - */ - - if ((fp = cupsFileOpen(filename, "r")) == NULL) - { - _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); - return (NULL); - } - - /* - * Allocate the mapping data structure... - */ - - if ((pwg = calloc(1, sizeof(_pwg_t))) == NULL) - { - DEBUG_puts("_pwgCreateWithFile: Unable to allocate pwg_t."); - _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); - goto create_error; - } - - /* - * Read the file... - */ - - linenum = 0; - num_bins = 0; - num_sizes = 0; - num_sources = 0; - num_types = 0; - - while (cupsFileGetConf(fp, line, sizeof(line), &value, &linenum)) - { - DEBUG_printf(("_pwgCreateWithFile: line=\"%s\", value=\"%s\", linenum=%d", - line, value, linenum)); - - if (!value) - { - DEBUG_printf(("_pwgCreateWithFile: Missing value on line %d.", linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - else if (!strcasecmp(line, "NumBins")) - { - if (num_bins > 0) - { - DEBUG_puts("_pwgCreateWithFile: NumBins listed multiple times."); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if ((num_bins = atoi(value)) <= 0 || num_bins > 65536) - { - DEBUG_printf(("_pwgCreateWithFile: Bad NumBins value %d on line %d.", - num_sizes, linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if ((pwg->bins = calloc(num_bins, sizeof(_pwg_map_t))) == NULL) - { - DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d bins.", - num_sizes)); - _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); - goto create_error; - } - } - else if (!strcasecmp(line, "Bin")) - { - if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2) - { - DEBUG_printf(("_pwgCreateWithFile: Bad Bin on line %d.", linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if (pwg->num_bins >= num_bins) - { - DEBUG_printf(("_pwgCreateWithFile: Too many Bin's on line %d.", - linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - map = pwg->bins + pwg->num_bins; - map->pwg = _cupsStrAlloc(pwg_keyword); - map->ppd = _cupsStrAlloc(ppd_keyword); - - pwg->num_bins ++; - } - else if (!strcasecmp(line, "NumSizes")) - { - if (num_sizes > 0) - { - DEBUG_puts("_pwgCreateWithFile: NumSizes listed multiple times."); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if ((num_sizes = atoi(value)) <= 0 || num_sizes > 65536) - { - DEBUG_printf(("_pwgCreateWithFile: Bad NumSizes value %d on line %d.", - num_sizes, linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if ((pwg->sizes = calloc(num_sizes, sizeof(_pwg_size_t))) == NULL) - { - DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d sizes.", - num_sizes)); - _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); - goto create_error; - } - } - else if (!strcasecmp(line, "Size")) - { - if (pwg->num_sizes >= num_sizes) - { - DEBUG_printf(("_pwgCreateWithFile: Too many Size's on line %d.", - linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - size = pwg->sizes + pwg->num_sizes; - - if (sscanf(value, "%127s%40s%d%d%d%d%d%d", pwg_keyword, ppd_keyword, - &(size->width), &(size->length), &(size->left), - &(size->bottom), &(size->right), &(size->top)) != 8) - { - DEBUG_printf(("_pwgCreateWithFile: Bad Size on line %d.", linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - size->map.pwg = _cupsStrAlloc(pwg_keyword); - size->map.ppd = _cupsStrAlloc(ppd_keyword); - - pwg->num_sizes ++; - } - else if (!strcasecmp(line, "CustomSize")) - { - if (pwg->custom_max_width > 0) - { - DEBUG_printf(("_pwgCreateWithFile: Too many CustomSize's on line %d.", - linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if (sscanf(value, "%d%d%d%d%d%d%d%d", &(pwg->custom_max_width), - &(pwg->custom_max_length), &(pwg->custom_min_width), - &(pwg->custom_min_length), &(pwg->custom_size.left), - &(pwg->custom_size.bottom), &(pwg->custom_size.right), - &(pwg->custom_size.top)) != 8) - { - DEBUG_printf(("_pwgCreateWithFile: Bad CustomSize on line %d.", linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max", - pwg->custom_max_width, pwg->custom_max_length); - pwg->custom_max_keyword = _cupsStrAlloc(pwg_keyword); - - _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min", - pwg->custom_min_width, pwg->custom_min_length); - pwg->custom_min_keyword = _cupsStrAlloc(pwg_keyword); - } - else if (!strcasecmp(line, "SourceOption")) - { - pwg->source_option = _cupsStrAlloc(value); - } - else if (!strcasecmp(line, "NumSources")) - { - if (num_sources > 0) - { - DEBUG_puts("_pwgCreateWithFile: NumSources listed multiple times."); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if ((num_sources = atoi(value)) <= 0 || num_sources > 65536) - { - DEBUG_printf(("_pwgCreateWithFile: Bad NumSources value %d on line %d.", - num_sources, linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if ((pwg->sources = calloc(num_sources, sizeof(_pwg_map_t))) == NULL) - { - DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d sources.", - num_sources)); - _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); - goto create_error; - } - } - else if (!strcasecmp(line, "Source")) - { - if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2) - { - DEBUG_printf(("_pwgCreateWithFile: Bad Source on line %d.", linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if (pwg->num_sources >= num_sources) - { - DEBUG_printf(("_pwgCreateWithFile: Too many Source's on line %d.", - linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - map = pwg->sources + pwg->num_sources; - map->pwg = _cupsStrAlloc(pwg_keyword); - map->ppd = _cupsStrAlloc(ppd_keyword); - - pwg->num_sources ++; - } - else if (!strcasecmp(line, "NumTypes")) - { - if (num_types > 0) - { - DEBUG_puts("_pwgCreateWithFile: NumTypes listed multiple times."); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if ((num_types = atoi(value)) <= 0 || num_types > 65536) - { - DEBUG_printf(("_pwgCreateWithFile: Bad NumTypes value %d on line %d.", - num_types, linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if ((pwg->types = calloc(num_types, sizeof(_pwg_map_t))) == NULL) - { - DEBUG_printf(("_pwgCreateWithFile: Unable to allocate %d types.", - num_types)); - _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); - goto create_error; - } - } - else if (!strcasecmp(line, "Type")) - { - if (sscanf(value, "%127s%40s", pwg_keyword, ppd_keyword) != 2) - { - DEBUG_printf(("_pwgCreateWithFile: Bad Type on line %d.", linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if (pwg->num_types >= num_types) - { - DEBUG_printf(("_pwgCreateWithFile: Too many Type's on line %d.", - linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - map = pwg->types + pwg->num_types; - map->pwg = _cupsStrAlloc(pwg_keyword); - map->ppd = _cupsStrAlloc(ppd_keyword); - - pwg->num_types ++; - } - else if (!strcasecmp(line, "Preset")) - { - /* - * Preset output-mode print-quality name=value ... - */ - - output_mode = (_pwg_output_mode_t)strtol(value, &valueptr, 10); - print_quality = (_pwg_print_quality_t)strtol(valueptr, &valueptr, 10); - - if (output_mode < _PWG_OUTPUT_MODE_MONOCHROME || - output_mode >= _PWG_OUTPUT_MODE_MAX || - print_quality < _PWG_PRINT_QUALITY_DRAFT || - print_quality >= _PWG_PRINT_QUALITY_MAX || - valueptr == value || !*valueptr) - { - DEBUG_printf(("_pwgCreateWithFile: Bad Preset on line %d.", linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - pwg->num_presets[output_mode][print_quality] = - cupsParseOptions(valueptr, 0, - pwg->presets[output_mode] + print_quality); - } - else if (!strcasecmp(line, "SidesOption")) - pwg->sides_option = _cupsStrAlloc(value); - else if (!strcasecmp(line, "Sides1Sided")) - pwg->sides_1sided = _cupsStrAlloc(value); - else if (!strcasecmp(line, "Sides2SidedLong")) - pwg->sides_2sided_long = _cupsStrAlloc(value); - else if (!strcasecmp(line, "Sides2SidedShort")) - pwg->sides_2sided_short = _cupsStrAlloc(value); - else - { - DEBUG_printf(("_pwgCreateWithFile: Unknown %s on line %d.", line, - linenum)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - } - - if (pwg->num_sizes < num_sizes) - { - DEBUG_printf(("_pwgCreateWithFile: Not enough sizes (%d < %d).", - pwg->num_sizes, num_sizes)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if (pwg->num_sources < num_sources) - { - DEBUG_printf(("_pwgCreateWithFile: Not enough sources (%d < %d).", - pwg->num_sources, num_sources)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - if (pwg->num_types < num_types) - { - DEBUG_printf(("_pwgCreateWithFile: Not enough types (%d < %d).", - pwg->num_types, num_types)); - _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); - goto create_error; - } - - cupsFileClose(fp); - - return (pwg); - - /* - * If we get here the file was bad - free any data and return... - */ - - create_error: - - cupsFileClose(fp); - _pwgDestroy(pwg); - - return (NULL); -} - - -/* - * '_pwgDestroy()' - Free all memory used for PWG mapping data. - */ - -void -_pwgDestroy(_pwg_t *pwg) /* I - PWG mapping data */ -{ - int i; /* Looping var */ - _pwg_map_t *map; /* Current map */ - _pwg_size_t *size; /* Current size */ - - - /* - * Range check input... - */ - - if (!pwg) - return; - - /* - * Free memory as needed... - */ - - if (pwg->bins) - { - for (i = pwg->num_bins, map = pwg->bins; i > 0; i --, map ++) - { - _cupsStrFree(map->pwg); - _cupsStrFree(map->ppd); - } - - free(pwg->bins); - } - - if (pwg->sizes) - { - for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++) - { - _cupsStrFree(size->map.pwg); - _cupsStrFree(size->map.ppd); - } - - free(pwg->sizes); - } - - if (pwg->source_option) - _cupsStrFree(pwg->source_option); - - if (pwg->sources) - { - for (i = pwg->num_sources, map = pwg->sources; i > 0; i --, map ++) - { - _cupsStrFree(map->pwg); - _cupsStrFree(map->ppd); - } - - free(pwg->sources); - } - - if (pwg->types) - { - for (i = pwg->num_types, map = pwg->types; i > 0; i --, map ++) - { - _cupsStrFree(map->pwg); - _cupsStrFree(map->ppd); - } - - free(pwg->types); - } - - if (pwg->custom_max_keyword) - _cupsStrFree(pwg->custom_max_keyword); - - if (pwg->custom_min_keyword) - _cupsStrFree(pwg->custom_min_keyword); - - free(pwg); -} - - -/* - * '_pwgWriteFile()' - Write PWG mapping data to a file. - */ - -int /* O - 1 on success, 0 on failure */ -_pwgWriteFile(_pwg_t *pwg, /* I - PWG mapping data */ - const char *filename) /* I - File to write */ -{ - int i, j, k; /* Looping vars */ - cups_file_t *fp; /* Output file */ - _pwg_size_t *size; /* Current size */ - _pwg_map_t *map; /* Current map */ - cups_option_t *option; /* Current option */ - - - /* - * Range check input... - */ - - if (!pwg || !filename) - { - _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0); - return (0); - } - - /* - * Open the file and write with compression... - */ - - if ((fp = cupsFileOpen(filename, "w9")) == NULL) - { - _cupsSetError(IPP_INTERNAL_ERROR, strerror(errno), 0); - return (0); - } - - /* - * Standard header... - */ - - cupsFilePuts(fp, "#CUPS-PWGPPD\n"); - - /* - * Output bins... - */ - - if (pwg->num_bins > 0) - { - cupsFilePrintf(fp, "NumBins %d\n", pwg->num_bins); - for (i = pwg->num_bins, map = pwg->bins; i > 0; i --, map ++) - cupsFilePrintf(fp, "Bin %s %s\n", map->pwg, map->ppd); - } - - /* - * Media sizes... - */ - - cupsFilePrintf(fp, "NumSizes %d\n", pwg->num_sizes); - for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++) - cupsFilePrintf(fp, "Size %s %s %d %d %d %d %d %d\n", size->map.pwg, - size->map.ppd, size->width, size->length, size->left, - size->bottom, size->right, size->top); - if (pwg->custom_max_width > 0) - cupsFilePrintf(fp, "CustomSize %d %d %d %d %d %d %d %d\n", - pwg->custom_max_width, pwg->custom_max_length, - pwg->custom_min_width, pwg->custom_min_length, - pwg->custom_size.left, pwg->custom_size.bottom, - pwg->custom_size.right, pwg->custom_size.top); - - /* - * Media sources... - */ - - if (pwg->source_option) - cupsFilePrintf(fp, "SourceOption %s\n", pwg->source_option); - - if (pwg->num_sources > 0) - { - cupsFilePrintf(fp, "NumSources %d\n", pwg->num_sources); - for (i = pwg->num_sources, map = pwg->sources; i > 0; i --, map ++) - cupsFilePrintf(fp, "Source %s %s\n", map->pwg, map->ppd); - } - - /* - * Media types... - */ - - if (pwg->num_types > 0) - { - cupsFilePrintf(fp, "NumTypes %d\n", pwg->num_types); - for (i = pwg->num_types, map = pwg->types; i > 0; i --, map ++) - cupsFilePrintf(fp, "Type %s %s\n", map->pwg, map->ppd); - } - - /* - * Presets... - */ - - for (i = _PWG_OUTPUT_MODE_MONOCHROME; i < _PWG_OUTPUT_MODE_MAX; i ++) - for (j = _PWG_PRINT_QUALITY_DRAFT; j < _PWG_PRINT_QUALITY_MAX; j ++) - if (pwg->num_presets[i][j]) - { - cupsFilePrintf(fp, "Preset %d %d", i, j); - for (k = pwg->num_presets[i][j], option = pwg->presets[i][j]; - k > 0; - k --, option ++) - cupsFilePrintf(fp, " %s=%s", option->name, option->value); - cupsFilePutChar(fp, '\n'); - } - - /* - * Duplex/sides... - */ - - if (pwg->sides_option) - cupsFilePrintf(fp, "SidesOption %s\n", pwg->sides_option); - - if (pwg->sides_1sided) - cupsFilePrintf(fp, "Sides1Sided %s\n", pwg->sides_1sided); - - if (pwg->sides_2sided_long) - cupsFilePrintf(fp, "Sides2SidedLong %s\n", pwg->sides_2sided_long); - - if (pwg->sides_2sided_short) - cupsFilePrintf(fp, "Sides2SidedShort %s\n", pwg->sides_2sided_short); - - /* - * Close and return... - */ - - return (!cupsFileClose(fp)); -} - - -/* - * End of "$Id$". - */ diff --git a/cups/pwg-media.c b/cups/pwg-media.c index 8e00ca031..306bf6d85 100644 --- a/cups/pwg-media.c +++ b/cups/pwg-media.c @@ -3,7 +3,7 @@ * * PWG media name API implementation for CUPS. * - * Copyright 2009-2010 by Apple Inc. + * Copyright 2009-2011 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -116,7 +116,7 @@ static _pwg_media_t const cups_pwg_media[] = _PWG_MEDIA_IN("na_f_44x68in", NULL, "AnsiF", 44, 68), /* Chinese Standard Sheet Media Inch Sizes */ - _PWG_MEDIA_IN("roc_16k_7.75x10.75in", NULL, NULL, 7.75, 10.75), + _PWG_MEDIA_IN("roc_16k_7.75x10.75in", NULL, "roc16k", 7.75, 10.75), _PWG_MEDIA_IN("roc_8k_10.75x15.5in", NULL, NULL, 10.75, 15.5), /* ISO Standard Sheet Media Sizes */ diff --git a/cups/pwg-ppd.c b/cups/pwg-ppd.c deleted file mode 100644 index 777ee07db..000000000 --- a/cups/pwg-ppd.c +++ /dev/null @@ -1,1489 +0,0 @@ -/* - * "$Id$" - * - * PWG PPD mapping API implementation for CUPS. - * - * Copyright 2010 by Apple Inc. - * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * which should have been included with this file. If this file is - * file is missing or damaged, see the license at "http://www.cups.org/". - * - * This file is subject to the Apple OS-Developed Software exception. - * - * Contents: - * - * _pwgCreateWithPPD() - Create PWG mapping data from a PPD file. - * _pwgGetBin() - Get the PWG output-bin keyword associated with a - * PPD OutputBin. - * _pwgGetInputSlot() - Get the PPD InputSlot associated with the job - * attributes or a keyword string. - * _pwgGetMediaType() - Get the PPD MediaType associated with the job - * attributes or a keyword string. - * _pwgGetOutputBin() - Get the PPD OutputBin associated with the - * keyword string. - * _pwgGetPageSize() - Get the PPD PageSize associated with the job - * attributes or a keyword string. - * _pwgGetSize() - Get the PWG size associated with a PPD PageSize. - * _pwgGetSource() - Get the PWG media-source associated with a PPD - * InputSlot. - * _pwgGetType() - Get the PWG media-type associated with a PPD - * MediaType. - * _pwgInputSlotForSource() - Get the InputSlot name for the given PWG source. - * _pwgMediaTypeForType() - Get the MediaType name for the given PWG type. - * _pwgPageSizeForMedia() - Get the PageSize name for the given media. - * pwg_ppdize_name() - Convert an IPP keyword to a PPD keyword. - * pwg_unppdize_name() - Convert a PPD keyword to a lowercase IPP - * keyword. - */ - -/* - * Include necessary headers... - */ - -#include "cups-private.h" -#include - - -/* - * Macro to test for two almost-equal PWG measurements. - */ - -#define _PWG_EQUIVALENT(x, y) (abs((x)-(y)) < 2) - - -/* - * Local functions... - */ - -static void pwg_ppdize_name(const char *ipp, char *name, size_t namesize); -static void pwg_unppdize_name(const char *ppd, char *name, size_t namesize); - - -/* - * '_pwgCreateWithPPD()' - Create PWG mapping data from a PPD file. - */ - -_pwg_t * /* O - PWG mapping data */ -_pwgCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ -{ - int i, j, k; /* Looping vars */ - _pwg_t *pwg; /* PWG mapping data */ - ppd_option_t *input_slot, /* InputSlot option */ - *media_type, /* MediaType option */ - *output_bin, /* OutputBin option */ - *color_model, /* ColorModel option */ - *duplex; /* Duplex option */ - ppd_choice_t *choice; /* Current InputSlot/MediaType */ - _pwg_map_t *map; /* Current source/type map */ - ppd_attr_t *ppd_attr; /* Current PPD preset attribute */ - int num_options; /* Number of preset options and props */ - cups_option_t *options; /* Preset options and properties */ - ppd_size_t *ppd_size; /* Current PPD size */ - _pwg_size_t *pwg_size; /* Current PWG size */ - char pwg_keyword[3 + PPD_MAX_NAME + 1 + 12 + 1 + 12 + 3], - /* PWG keyword string */ - ppd_name[PPD_MAX_NAME]; - /* Normalized PPD name */ - const char *pwg_name; /* Standard PWG media name */ - _pwg_media_t *pwg_media; /* PWG media data */ - _pwg_output_mode_t pwg_output_mode;/* output-mode index */ - _pwg_print_quality_t pwg_print_quality; - /* print-quality index */ - int similar; /* Are the old and new size similar? */ - _pwg_size_t *old_size; /* Current old size */ - int old_imageable, /* Old imageable length in 2540ths */ - old_borderless, /* Old borderless state */ - old_known_pwg; /* Old PWG name is well-known */ - int new_width, /* New width in 2540ths */ - new_length, /* New length in 2540ths */ - new_left, /* New left margin in 2540ths */ - new_bottom, /* New bottom margin in 2540ths */ - new_right, /* New right margin in 2540ths */ - new_top, /* New top margin in 2540ths */ - new_imageable, /* New imageable length in 2540ths */ - new_borderless, /* New borderless state */ - new_known_pwg; /* New PWG name is well-known */ - _pwg_size_t *new_size; /* New size to add, if any */ - - - DEBUG_printf(("_pwgCreateWithPPD(ppd=%p)", ppd)); - - /* - * Range check input... - */ - - if (!ppd) - return (NULL); - - /* - * Allocate memory... - */ - - if ((pwg = calloc(1, sizeof(_pwg_t))) == NULL) - { - DEBUG_puts("_pwgCreateWithPPD: Unable to allocate _pwg_t."); - goto create_error; - } - - /* - * Copy and convert size data... - */ - - if (ppd->num_sizes == 0) - { - DEBUG_puts("_pwgCreateWithPPD: No page sizes in PPD."); - goto create_error; - } - - if ((pwg->sizes = calloc(ppd->num_sizes, sizeof(_pwg_size_t))) == NULL) - { - DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_size_t's.", - ppd->num_sizes)); - goto create_error; - } - - for (i = ppd->num_sizes, pwg_size = pwg->sizes, ppd_size = ppd->sizes; - i > 0; - i --, ppd_size ++) - { - /* - * Don't copy over custom size... - */ - - if (!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) - { - /* - * Standard name, do we have conflicts? - */ - - for (j = 0; j < pwg->num_sizes; j ++) - if (!strcmp(pwg->sizes[j].map.pwg, pwg_media->pwg)) - { - pwg_media = NULL; - break; - } - } - - if (pwg_media) - { - /* - * Standard name and no conflicts, use it! - */ - - pwg_name = pwg_media->pwg; - new_known_pwg = 1; - } - else - { - /* - * Not a standard name; convert it to a PWG vendor name of the form: - * - * pp_lowerppd_WIDTHxHEIGHTuu - */ - - 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 we have a similar paper with non-zero margins then we only - * want to keep it if it has a larger imageable area length. - */ - - new_width = _PWG_FROMPTS(ppd_size->width); - new_length = _PWG_FROMPTS(ppd_size->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 = pwg->num_sizes, similar = 0, old_size = pwg->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 ++; - pwg->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; - } - } - - if (ppd->variable_sizes) - { - /* - * Generate custom size data... - */ - - _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "max", - _PWG_FROMPTS(ppd->custom_max[0]), - _PWG_FROMPTS(ppd->custom_max[1])); - pwg->custom_max_keyword = _cupsStrAlloc(pwg_keyword); - pwg->custom_max_width = _PWG_FROMPTS(ppd->custom_max[0]); - pwg->custom_max_length = _PWG_FROMPTS(ppd->custom_max[1]); - - _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), "custom", "min", - _PWG_FROMPTS(ppd->custom_min[0]), - _PWG_FROMPTS(ppd->custom_min[1])); - pwg->custom_min_keyword = _cupsStrAlloc(pwg_keyword); - pwg->custom_min_width = _PWG_FROMPTS(ppd->custom_min[0]); - pwg->custom_min_length = _PWG_FROMPTS(ppd->custom_min[1]); - - pwg->custom_size.left = _PWG_FROMPTS(ppd->custom_margins[0]); - pwg->custom_size.bottom = _PWG_FROMPTS(ppd->custom_margins[1]); - pwg->custom_size.right = _PWG_FROMPTS(ppd->custom_margins[2]); - pwg->custom_size.top = _PWG_FROMPTS(ppd->custom_margins[3]); - } - - /* - * Copy and convert InputSlot data... - */ - - if ((input_slot = ppdFindOption(ppd, "InputSlot")) == NULL) - input_slot = ppdFindOption(ppd, "HPPaperSource"); - - if (input_slot) - { - pwg->source_option = _cupsStrAlloc(input_slot->keyword); - - if ((pwg->sources = calloc(input_slot->num_choices, - sizeof(_pwg_map_t))) == NULL) - { - DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_map_t's " - "for InputSlot.", input_slot->num_choices)); - goto create_error; - } - - pwg->num_sources = input_slot->num_choices; - - for (i = input_slot->num_choices, choice = input_slot->choices, - map = pwg->sources; - i > 0; - i --, choice ++, map ++) - { - if (!strncasecmp(choice->choice, "Auto", 4) || - !strcasecmp(choice->choice, "Default")) - pwg_name = "auto"; - else if (!strcasecmp(choice->choice, "Cassette")) - pwg_name = "main"; - else if (!strcasecmp(choice->choice, "PhotoTray")) - pwg_name = "photo"; - else if (!strcasecmp(choice->choice, "CDTray")) - pwg_name = "disc"; - else if (!strncasecmp(choice->choice, "Multipurpose", 12) || - !strcasecmp(choice->choice, "MP") || - !strcasecmp(choice->choice, "MPTray")) - pwg_name = "alternate"; - else if (!strcasecmp(choice->choice, "LargeCapacity")) - pwg_name = "large-capacity"; - else if (!strncasecmp(choice->choice, "Lower", 5)) - pwg_name = "bottom"; - else if (!strncasecmp(choice->choice, "Middle", 6)) - pwg_name = "middle"; - else if (!strncasecmp(choice->choice, "Upper", 5)) - pwg_name = "top"; - else if (!strncasecmp(choice->choice, "Side", 4)) - pwg_name = "side"; - else if (!strcasecmp(choice->choice, "Roll") || - !strcasecmp(choice->choice, "Roll1")) - pwg_name = "main-roll"; - else if (!strcasecmp(choice->choice, "Roll2")) - pwg_name = "alternate-roll"; - else - { - /* - * Convert PPD name to lowercase... - */ - - pwg_name = pwg_keyword; - pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword)); - } - - map->pwg = _cupsStrAlloc(pwg_name); - map->ppd = _cupsStrAlloc(choice->choice); - } - } - - /* - * Copy and convert MediaType data... - */ - - if ((media_type = ppdFindOption(ppd, "MediaType")) != NULL) - { - if ((pwg->types = calloc(media_type->num_choices, - sizeof(_pwg_map_t))) == NULL) - { - DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_map_t's " - "for MediaType.", media_type->num_choices)); - goto create_error; - } - - pwg->num_types = media_type->num_choices; - - for (i = media_type->num_choices, choice = media_type->choices, - map = pwg->types; - i > 0; - i --, choice ++, map ++) - { - if (!strncasecmp(choice->choice, "Auto", 4) || - !strcasecmp(choice->choice, "Any") || - !strcasecmp(choice->choice, "Default")) - pwg_name = "auto"; - else if (!strncasecmp(choice->choice, "Card", 4)) - pwg_name = "cardstock"; - else if (!strncasecmp(choice->choice, "Env", 3)) - pwg_name = "envelope"; - else if (!strncasecmp(choice->choice, "Gloss", 5)) - pwg_name = "photographic-glossy"; - else if (!strcasecmp(choice->choice, "HighGloss")) - pwg_name = "photographic-high-gloss"; - else if (!strcasecmp(choice->choice, "Matte")) - pwg_name = "photographic-matte"; - else if (!strncasecmp(choice->choice, "Plain", 5)) - pwg_name = "stationery"; - else if (!strncasecmp(choice->choice, "Coated", 6)) - pwg_name = "stationery-coated"; - else if (!strcasecmp(choice->choice, "Inkjet")) - pwg_name = "stationery-inkjet"; - else if (!strcasecmp(choice->choice, "Letterhead")) - pwg_name = "stationery-letterhead"; - else if (!strncasecmp(choice->choice, "Preprint", 8)) - pwg_name = "stationery-preprinted"; - else if (!strncasecmp(choice->choice, "Transparen", 10)) - pwg_name = "transparency"; - else - { - /* - * Convert PPD name to lowercase... - */ - - pwg_name = pwg_keyword; - pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword)); - } - - map->pwg = _cupsStrAlloc(pwg_name); - map->ppd = _cupsStrAlloc(choice->choice); - } - } - - - /* - * Copy and convert OutputBin data... - */ - - if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL) - { - if ((pwg->bins = calloc(output_bin->num_choices, - sizeof(_pwg_map_t))) == NULL) - { - DEBUG_printf(("_pwgCreateWithPPD: Unable to allocate %d _pwg_map_t's " - "for OutputBin.", output_bin->num_choices)); - goto create_error; - } - - pwg->num_bins = output_bin->num_choices; - - for (i = output_bin->num_choices, choice = output_bin->choices, - map = pwg->bins; - i > 0; - i --, choice ++, map ++) - { - pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword)); - - map->pwg = _cupsStrAlloc(pwg_keyword); - map->ppd = _cupsStrAlloc(choice->choice); - } - } - - if ((ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL)) != NULL) - { - /* - * Copy and convert APPrinterPreset (output-mode + print-quality) data... - */ - - const char *quality, /* com.apple.print.preset.quality value */ - *output_mode, /* com.apple.print.preset.output-mode value */ - *color_model_val, /* ColorModel choice */ - *graphics_type, /* com.apple.print.preset.graphicsType value */ - *paper_coating; /* com.apple.print.preset.media-front-coating value */ - - - do - { - num_options = _ppdParseOptions(ppd_attr->value, 0, &options, - _PPD_PARSE_ALL); - - if ((quality = cupsGetOption("com.apple.print.preset.quality", - num_options, options)) != NULL) - { - /* - * Get the print-quality for this preset... - */ - - if (!strcmp(quality, "low")) - pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT; - else if (!strcmp(quality, "high")) - pwg_print_quality = _PWG_PRINT_QUALITY_HIGH; - else - pwg_print_quality = _PWG_PRINT_QUALITY_NORMAL; - - /* - * Ignore graphicsType "Photo" presets that are not high quality. - */ - - graphics_type = cupsGetOption("com.apple.print.preset.graphicsType", - num_options, options); - - if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH && graphics_type && - !strcmp(graphics_type, "Photo")) - continue; - - /* - * Ignore presets for normal and draft quality where the coating - * isn't "none" or "autodetect". - */ - - paper_coating = cupsGetOption( - "com.apple.print.preset.media-front-coating", - num_options, options); - - if (pwg_print_quality != _PWG_PRINT_QUALITY_HIGH && paper_coating && - strcmp(paper_coating, "none") && - strcmp(paper_coating, "autodetect")) - continue; - - /* - * Get the output mode for this preset... - */ - - output_mode = cupsGetOption("com.apple.print.preset.output-mode", - num_options, options); - color_model_val = cupsGetOption("ColorModel", num_options, options); - - if (output_mode) - { - if (!strcmp(output_mode, "monochrome")) - pwg_output_mode = _PWG_OUTPUT_MODE_MONOCHROME; - else - pwg_output_mode = _PWG_OUTPUT_MODE_COLOR; - } - else if (color_model_val) - { - if (!strcasecmp(color_model_val, "Gray")) - pwg_output_mode = _PWG_OUTPUT_MODE_MONOCHROME; - else - pwg_output_mode = _PWG_OUTPUT_MODE_COLOR; - } - else - pwg_output_mode = _PWG_OUTPUT_MODE_COLOR; - - /* - * Save the options for this combination as needed... - */ - - if (!pwg->num_presets[pwg_output_mode][pwg_print_quality]) - pwg->num_presets[pwg_output_mode][pwg_print_quality] = - _ppdParseOptions(ppd_attr->value, 0, - pwg->presets[pwg_output_mode] + - pwg_print_quality, _PPD_PARSE_OPTIONS); - } - - cupsFreeOptions(num_options, options); - } - while ((ppd_attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL)) != NULL); - } - - if (!pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][_PWG_PRINT_QUALITY_DRAFT] && - !pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][_PWG_PRINT_QUALITY_NORMAL] && - !pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][_PWG_PRINT_QUALITY_HIGH]) - { - /* - * Try adding some common color options to create grayscale presets. These - * are listed in order of popularity... - */ - - const char *color_option = NULL, /* Color control option */ - *gray_choice = NULL; /* Choice to select grayscale */ - - if ((color_model = ppdFindOption(ppd, "ColorModel")) != NULL && - ppdFindChoice(color_model, "Gray")) - { - color_option = "ColorModel"; - gray_choice = "Gray"; - } - else if ((color_model = ppdFindOption(ppd, "HPColorMode")) != NULL && - ppdFindChoice(color_model, "grayscale")) - { - color_option = "HPColorMode"; - gray_choice = "grayscale"; - } - else if ((color_model = ppdFindOption(ppd, "BRMonoColor")) != NULL && - ppdFindChoice(color_model, "Mono")) - { - color_option = "BRMonoColor"; - gray_choice = "Mono"; - } - else if ((color_model = ppdFindOption(ppd, "CNIJSGrayScale")) != NULL && - ppdFindChoice(color_model, "1")) - { - color_option = "CNIJSGrayScale"; - gray_choice = "1"; - } - else if ((color_model = ppdFindOption(ppd, "HPColorAsGray")) != NULL && - ppdFindChoice(color_model, "True")) - { - color_option = "HPColorAsGray"; - gray_choice = "True"; - } - - if (color_option && gray_choice) - { - /* - * Copy and convert ColorModel (output-mode) data... - */ - - cups_option_t *coption, /* Color option */ - *moption; /* Monochrome option */ - - for (pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT; - pwg_print_quality < _PWG_PRINT_QUALITY_MAX; - pwg_print_quality ++) - { - if (pwg->num_presets[_PWG_OUTPUT_MODE_COLOR][pwg_print_quality]) - { - /* - * Copy the color options... - */ - - num_options = pwg->num_presets[_PWG_OUTPUT_MODE_COLOR] - [pwg_print_quality]; - options = calloc(sizeof(cups_option_t), num_options); - - if (options) - { - for (i = num_options, moption = options, - coption = pwg->presets[_PWG_OUTPUT_MODE_COLOR] - [pwg_print_quality]; - i > 0; - i --, moption ++, coption ++) - { - moption->name = _cupsStrRetain(coption->name); - moption->value = _cupsStrRetain(coption->value); - } - - pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][pwg_print_quality] = - num_options; - pwg->presets[_PWG_OUTPUT_MODE_MONOCHROME][pwg_print_quality] = - options; - } - } - else if (pwg_print_quality != _PWG_PRINT_QUALITY_NORMAL) - continue; - - /* - * Add the grayscale option to the preset... - */ - - pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][pwg_print_quality] = - cupsAddOption(color_option, gray_choice, - pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME] - [pwg_print_quality], - pwg->presets[_PWG_OUTPUT_MODE_MONOCHROME] + - pwg_print_quality); - } - } - } - - /* - * Copy and convert Duplex (sides) data... - */ - - if ((duplex = ppdFindOption(ppd, "Duplex")) == NULL) - if ((duplex = ppdFindOption(ppd, "JCLDuplex")) == NULL) - if ((duplex = ppdFindOption(ppd, "EFDuplex")) == NULL) - if ((duplex = ppdFindOption(ppd, "EFDuplexing")) == NULL) - duplex = ppdFindOption(ppd, "KD03Duplex"); - - if (duplex) - { - pwg->sides_option = _cupsStrAlloc(duplex->keyword); - - for (i = duplex->num_choices, choice = duplex->choices; - i > 0; - i --, choice ++) - { - if ((!strcasecmp(choice->choice, "None") || - !strcasecmp(choice->choice, "False")) && !pwg->sides_1sided) - pwg->sides_1sided = _cupsStrAlloc(choice->choice); - else if ((!strcasecmp(choice->choice, "DuplexNoTumble") || - !strcasecmp(choice->choice, "LongEdge") || - !strcasecmp(choice->choice, "Top")) && !pwg->sides_2sided_long) - pwg->sides_2sided_long = _cupsStrAlloc(choice->choice); - else if ((!strcasecmp(choice->choice, "DuplexTumble") || - !strcasecmp(choice->choice, "ShortEdge") || - !strcasecmp(choice->choice, "Bottom")) && - !pwg->sides_2sided_short) - pwg->sides_2sided_short = _cupsStrAlloc(choice->choice); - } - } - - return (pwg); - - /* - * If we get here we need to destroy the PWG mapping data and return NULL... - */ - - create_error: - - _cupsSetError(IPP_INTERNAL_ERROR, _("Out of memory."), 1); - _pwgDestroy(pwg); - - return (NULL); -} - - -/* - * '_pwgGetBin()' - Get the PWG output-bin keyword associated with a PPD - * OutputBin. - */ - -const char * /* O - output-bin or NULL */ -_pwgGetBin(_pwg_t *pwg, /* I - PWG mapping data */ - const char *output_bin) /* I - PPD OutputBin string */ -{ - int i; /* Looping var */ - - - /* - * Range check input... - */ - - if (!pwg || !output_bin) - return (NULL); - - /* - * Look up the OutputBin string... - */ - - - for (i = 0; i < pwg->num_bins; i ++) - if (!strcasecmp(output_bin, pwg->bins[i].ppd)) - return (pwg->bins[i].pwg); - - return (NULL); -} - - -/* - * '_pwgGetInputSlot()' - Get the PPD InputSlot associated with the job - * attributes or a keyword string. - */ - -const char * /* O - PPD InputSlot or NULL */ -_pwgGetInputSlot(_pwg_t *pwg, /* I - PWG mapping data */ - ipp_t *job, /* I - Job attributes or NULL */ - const char *keyword) /* I - Keyword string or NULL */ -{ - /* - * Range check input... - */ - - if (!pwg || pwg->num_sources == 0 || (!job && !keyword)) - return (NULL); - - if (job && !keyword) - { - /* - * Lookup the media-col attribute and any media-source found there... - */ - - ipp_attribute_t *media_col, /* media-col attribute */ - *media_source; /* media-source attribute */ - _pwg_size_t size; /* Dimensional size */ - int margins_set; /* Were the margins set? */ - - media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION); - if (media_col && - (media_source = ippFindAttribute(media_col->values[0].collection, - "media-source", - IPP_TAG_KEYWORD)) != NULL) - { - /* - * Use the media-source value from media-col... - */ - - keyword = media_source->values[0].string.text; - } - else if (_pwgInitSize(&size, job, &margins_set)) - { - /* - * For media <= 5x7, look for a photo tray... - */ - - if (size.width <= (5 * 2540) && size.length <= (7 * 2540)) - keyword = "photo"; - } - } - - if (keyword) - { - int i; /* Looping var */ - - for (i = 0; i < pwg->num_sources; i ++) - if (!strcasecmp(keyword, pwg->sources[i].pwg)) - return (pwg->sources[i].ppd); - } - - return (NULL); -} - - -/* - * '_pwgGetMediaType()' - Get the PPD MediaType associated with the job - * attributes or a keyword string. - */ - -const char * /* O - PPD MediaType or NULL */ -_pwgGetMediaType(_pwg_t *pwg, /* I - PWG mapping data */ - ipp_t *job, /* I - Job attributes or NULL */ - const char *keyword) /* I - Keyword string or NULL */ -{ - /* - * Range check input... - */ - - if (!pwg || pwg->num_types == 0 || (!job && !keyword)) - return (NULL); - - if (job && !keyword) - { - /* - * Lookup the media-col attribute and any media-source found there... - */ - - ipp_attribute_t *media_col, /* media-col attribute */ - *media_type; /* media-type attribute */ - - media_col = ippFindAttribute(job, "media-col", IPP_TAG_BEGIN_COLLECTION); - if (media_col) - { - if ((media_type = ippFindAttribute(media_col->values[0].collection, - "media-type", - IPP_TAG_KEYWORD)) == NULL) - media_type = ippFindAttribute(media_col->values[0].collection, - "media-type", IPP_TAG_NAME); - - if (media_type) - keyword = media_type->values[0].string.text; - } - } - - if (keyword) - { - int i; /* Looping var */ - - for (i = 0; i < pwg->num_types; i ++) - if (!strcasecmp(keyword, pwg->types[i].pwg)) - return (pwg->types[i].ppd); - } - - return (NULL); -} - - -/* - * '_pwgGetOutputBin()' - Get the PPD OutputBin associated with the keyword - * string. - */ - -const char * /* O - PPD OutputBin or NULL */ -_pwgGetOutputBin(_pwg_t *pwg, /* I - PWG mapping data */ - const char *output_bin)/* I - Keyword string */ -{ - int i; /* Looping var */ - - - /* - * Range check input... - */ - - if (!pwg || !output_bin) - return (NULL); - - /* - * Look up the OutputBin string... - */ - - - for (i = 0; i < pwg->num_bins; i ++) - if (!strcasecmp(output_bin, pwg->bins[i].pwg)) - return (pwg->bins[i].ppd); - - return (NULL); -} - - -/* - * '_pwgGetPageSize()' - Get the PPD PageSize associated with the job - * attributes or a keyword string. - */ - -const char * /* O - PPD PageSize or NULL */ -_pwgGetPageSize(_pwg_t *pwg, /* I - PWG mapping data */ - ipp_t *job, /* I - Job attributes or NULL */ - const char *keyword, /* I - Keyword string or NULL */ - int *exact) /* I - 1 if exact match, 0 otherwise */ -{ - int i; /* Looping var */ - _pwg_size_t *size, /* Current size */ - *closest, /* Closest size */ - jobsize; /* Size data from job */ - int margins_set, /* Were the margins set? */ - dwidth, /* Difference in width */ - dlength, /* Difference in length */ - dleft, /* Difference in left margins */ - dright, /* Difference in right margins */ - dbottom, /* Difference in bottom margins */ - dtop, /* Difference in top margins */ - dmin, /* Minimum difference */ - dclosest; /* Closest difference */ - const char *ppd_name; /* PPD media name */ - - - DEBUG_printf(("_pwgGetPageSize(pwg=%p, job=%p, keyword=\"%s\", exact=%p)", - pwg, job, keyword, exact)); - - /* - * Range check input... - */ - - if (!pwg || (!job && !keyword)) - return (NULL); - - if (exact) - *exact = 0; - - ppd_name = keyword; - - if (job) - { - /* - * Try getting the PPD media name from the job attributes... - */ - - ipp_attribute_t *attr; /* Job attribute */ - - if ((attr = ippFindAttribute(job, "PageSize", IPP_TAG_ZERO)) == NULL) - if ((attr = ippFindAttribute(job, "PageRegion", IPP_TAG_ZERO)) == NULL) - attr = ippFindAttribute(job, "media", IPP_TAG_ZERO); - -#ifdef DEBUG - if (attr) - DEBUG_printf(("1_pwgGetPageSize: Found attribute %s (%s)", attr->name, - ippTagString(attr->value_tag))); - else - DEBUG_puts("1_pwgGetPageSize: Did not find media attribute."); -#endif /* DEBUG */ - - if (attr && (attr->value_tag == IPP_TAG_NAME || - attr->value_tag == IPP_TAG_KEYWORD)) - ppd_name = attr->values[0].string.text; - } - - DEBUG_printf(("1_pwgGetPageSize: ppd_name=\"%s\"", ppd_name)); - - if (ppd_name) - { - /* - * Try looking up the named PPD size first... - */ - - for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++) - { - DEBUG_printf(("2_pwgGetPageSize: size[%d]=[\"%s\" \"%s\"]", - (int)(size - pwg->sizes), size->map.pwg, size->map.ppd)); - - if (!strcasecmp(ppd_name, size->map.ppd)) - { - if (exact) - *exact = 1; - - DEBUG_printf(("1_pwgGetPageSize: Returning \"%s\"", ppd_name)); - - return (ppd_name); - } - } - } - - if (job && !keyword) - { - /* - * Get the size using media-col or media, with the preference being - * media-col. - */ - - if (!_pwgInitSize(&jobsize, job, &margins_set)) - return (NULL); - } - else - { - /* - * Get the size using a media keyword... - */ - - _pwg_media_t *media; /* Media definition */ - - - if ((media = _pwgMediaForPWG(keyword)) == NULL) - if ((media = _pwgMediaForLegacy(keyword)) == NULL) - if ((media = _pwgMediaForPPD(keyword)) == NULL) - return (NULL); - - jobsize.width = media->width; - jobsize.length = media->length; - margins_set = 0; - } - - /* - * Now that we have the dimensions and possibly the margins, look at the - * available sizes and find the match... - */ - - closest = NULL; - dclosest = 999999999; - - if (!ppd_name || strncasecmp(ppd_name, "Custom.", 7) || - strncasecmp(ppd_name, "custom_", 7)) - { - for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++) - { - /* - * Adobe uses a size matching algorithm with an epsilon of 5 points, which - * is just about 176/2540ths... - */ - - dwidth = size->width - jobsize.width; - dlength = size->length - jobsize.length; - - if (dwidth <= -176 || dwidth >= 176 || dlength <= -176 || dlength >= 176) - continue; - - if (margins_set) - { - /* - * Use a tighter epsilon of 1 point (35/2540ths) for margins... - */ - - dleft = size->left - jobsize.left; - dright = size->right - jobsize.right; - dtop = size->top - jobsize.top; - dbottom = size->bottom - jobsize.bottom; - - if (dleft <= -35 || dleft >= 35 || dright <= -35 || dright >= 35 || - dtop <= -35 || dtop >= 35 || dbottom <= -35 || dbottom >= 35) - { - dleft = dleft < 0 ? -dleft : dleft; - dright = dright < 0 ? -dright : dright; - dbottom = dbottom < 0 ? -dbottom : dbottom; - dtop = dtop < 0 ? -dtop : dtop; - dmin = dleft + dright + dbottom + dtop; - - if (dmin < dclosest) - { - dclosest = dmin; - closest = size; - } - - continue; - } - } - - if (exact) - *exact = 1; - - DEBUG_printf(("1_pwgGetPageSize: Returning \"%s\"", size->map.ppd)); - - return (size->map.ppd); - } - } - - if (closest) - { - DEBUG_printf(("1_pwgGetPageSize: Returning \"%s\" (closest)", - closest->map.ppd)); - - return (closest->map.ppd); - } - - /* - * If we get here we need to check for custom page size support... - */ - - if (jobsize.width >= pwg->custom_min_width && - jobsize.width <= pwg->custom_max_width && - jobsize.length >= pwg->custom_min_length && - jobsize.length <= pwg->custom_max_length) - { - /* - * In range, format as Custom.WWWWxLLLL (points). - */ - - snprintf(pwg->custom_ppd_size, sizeof(pwg->custom_ppd_size), "Custom.%dx%d", - (int)_PWG_TOPTS(jobsize.width), (int)_PWG_TOPTS(jobsize.length)); - - if (margins_set && exact) - { - dleft = pwg->custom_size.left - jobsize.left; - dright = pwg->custom_size.right - jobsize.right; - dtop = pwg->custom_size.top - jobsize.top; - dbottom = pwg->custom_size.bottom - jobsize.bottom; - - if (dleft > -35 && dleft < 35 && dright > -35 && dright < 35 && - dtop > -35 && dtop < 35 && dbottom > -35 && dbottom < 35) - *exact = 1; - } - else if (exact) - *exact = 1; - - DEBUG_printf(("1_pwgGetPageSize: Returning \"%s\" (custom)", - pwg->custom_ppd_size)); - - return (pwg->custom_ppd_size); - } - - /* - * No custom page size support or the size is out of range - return NULL. - */ - - DEBUG_puts("1_pwgGetPageSize: Returning NULL"); - - return (NULL); -} - - -/* - * '_pwgGetSize()' - Get the PWG size associated with a PPD PageSize. - */ - -_pwg_size_t * /* O - PWG size or NULL */ -_pwgGetSize(_pwg_t *pwg, /* I - PWG mapping data */ - const char *page_size) /* I - PPD PageSize */ -{ - int i; - _pwg_size_t *size; /* Current size */ - - - /* - * Range check input... - */ - - if (!pwg || !page_size) - return (NULL); - - if (!strncasecmp(page_size, "Custom.", 7)) - { - /* - * Custom size; size name can be one of the following: - * - * Custom.WIDTHxLENGTHin - Size in inches - * Custom.WIDTHxLENGTHft - Size in feet - * Custom.WIDTHxLENGTHcm - Size in centimeters - * Custom.WIDTHxLENGTHmm - Size in millimeters - * Custom.WIDTHxLENGTHm - Size in meters - * Custom.WIDTHxLENGTH[pt] - Size in points - */ - - double w, l; /* Width and length of page */ - char *ptr; /* Pointer into PageSize */ - struct lconv *loc; /* Locale data */ - - loc = localeconv(); - w = (float)_cupsStrScand(page_size + 7, &ptr, loc); - if (!ptr || *ptr != 'x') - return (NULL); - - l = (float)_cupsStrScand(ptr + 1, &ptr, loc); - if (!ptr) - return (NULL); - - if (!strcasecmp(ptr, "in")) - { - w *= 2540.0; - l *= 2540.0; - } - else if (!strcasecmp(ptr, "ft")) - { - w *= 12.0 * 2540.0; - l *= 12.0 * 2540.0; - } - else if (!strcasecmp(ptr, "mm")) - { - w *= 100.0; - l *= 100.0; - } - else if (!strcasecmp(ptr, "cm")) - { - w *= 1000.0; - l *= 1000.0; - } - else if (!strcasecmp(ptr, "m")) - { - w *= 100000.0; - l *= 100000.0; - } - else - { - w *= 2540.0 / 72.0; - l *= 2540.0 / 72.0; - } - - pwg->custom_size.width = (int)w; - pwg->custom_size.length = (int)l; - - return (&(pwg->custom_size)); - } - - /* - * Not a custom size - look it up... - */ - - for (i = pwg->num_sizes, size = pwg->sizes; i > 0; i --, size ++) - if (!strcasecmp(page_size, size->map.ppd)) - return (size); - - return (NULL); -} - - -/* - * '_pwgGetSource()' - Get the PWG media-source associated with a PPD InputSlot. - */ - -const char * /* O - PWG media-source keyword */ -_pwgGetSource(_pwg_t *pwg, /* I - PWG mapping data */ - const char *input_slot) /* I - PPD InputSlot */ -{ - int i; /* Looping var */ - _pwg_map_t *source; /* Current source */ - - - /* - * Range check input... - */ - - if (!pwg || !input_slot) - return (NULL); - - for (i = pwg->num_sources, source = pwg->sources; i > 0; i --, source ++) - if (!strcasecmp(input_slot, source->ppd)) - return (source->pwg); - - return (NULL); -} - - -/* - * '_pwgGetType()' - Get the PWG media-type associated with a PPD MediaType. - */ - -const char * /* O - PWG media-type keyword */ -_pwgGetType(_pwg_t *pwg, /* I - PWG mapping data */ - const char *media_type) /* I - PPD MediaType */ -{ - int i; /* Looping var */ - _pwg_map_t *type; /* Current type */ - - - /* - * Range check input... - */ - - if (!pwg || !media_type) - return (NULL); - - for (i = pwg->num_types, type = pwg->types; i > 0; i --, type ++) - if (!strcasecmp(media_type, type->ppd)) - return (type->pwg); - - return (NULL); -} - - -/* - * '_pwgInputSlotForSource()' - Get the InputSlot name for the given PWG source. - */ - -const char * /* O - InputSlot name */ -_pwgInputSlotForSource( - const char *media_source, /* I - PWG media-source */ - char *name, /* I - Name buffer */ - size_t namesize) /* I - Size of name buffer */ -{ - /* - * Range check input... - */ - - if (!media_source || !name || namesize < PPD_MAX_NAME) - return (NULL); - - if (strcasecmp(media_source, "main")) - strlcpy(name, "Cassette", namesize); - else if (strcasecmp(media_source, "alternate")) - strlcpy(name, "Multipurpose", namesize); - else if (strcasecmp(media_source, "large-capacity")) - strlcpy(name, "LargeCapacity", namesize); - else if (strcasecmp(media_source, "bottom")) - strlcpy(name, "Lower", namesize); - else if (strcasecmp(media_source, "middle")) - strlcpy(name, "Middle", namesize); - else if (strcasecmp(media_source, "top")) - strlcpy(name, "Upper", namesize); - else if (strcasecmp(media_source, "rear")) - strlcpy(name, "Rear", namesize); - else if (strcasecmp(media_source, "side")) - strlcpy(name, "Side", namesize); - else if (strcasecmp(media_source, "envelope")) - strlcpy(name, "Envelope", namesize); - else if (strcasecmp(media_source, "main-roll")) - strlcpy(name, "Roll", namesize); - else if (strcasecmp(media_source, "alternate-roll")) - strlcpy(name, "Roll2", namesize); - else - pwg_ppdize_name(media_source, name, namesize); - - return (name); -} - - -/* - * '_pwgMediaTypeForType()' - Get the MediaType name for the given PWG type. - */ - -const char * /* O - MediaType name */ -_pwgMediaTypeForType( - const char *media_type, /* I - PWG media-source */ - char *name, /* I - Name buffer */ - size_t namesize) /* I - Size of name buffer */ -{ - /* - * Range check input... - */ - - if (!media_type || !name || namesize < PPD_MAX_NAME) - return (NULL); - - if (strcasecmp(media_type, "auto")) - strlcpy(name, "Auto", namesize); - else if (strcasecmp(media_type, "cardstock")) - strlcpy(name, "Cardstock", namesize); - else if (strcasecmp(media_type, "envelope")) - strlcpy(name, "Envelope", namesize); - else if (strcasecmp(media_type, "photographic-glossy")) - strlcpy(name, "Glossy", namesize); - else if (strcasecmp(media_type, "photographic-high-gloss")) - strlcpy(name, "HighGloss", namesize); - else if (strcasecmp(media_type, "photographic-matte")) - strlcpy(name, "Matte", namesize); - else if (strcasecmp(media_type, "stationery")) - strlcpy(name, "Plain", namesize); - else if (strcasecmp(media_type, "stationery-coated")) - strlcpy(name, "Coated", namesize); - else if (strcasecmp(media_type, "stationery-inkjet")) - strlcpy(name, "Inkjet", namesize); - else if (strcasecmp(media_type, "stationery-letterhead")) - strlcpy(name, "Letterhead", namesize); - else if (strcasecmp(media_type, "stationery-preprinted")) - strlcpy(name, "Preprinted", namesize); - else if (strcasecmp(media_type, "transparency")) - strlcpy(name, "Transparency", namesize); - else - pwg_ppdize_name(media_type, name, namesize); - - return (name); -} - - -/* - * '_pwgPageSizeForMedia()' - Get the PageSize name for the given media. - */ - -const char * /* O - PageSize name */ -_pwgPageSizeForMedia( - _pwg_media_t *media, /* I - Media */ - char *name, /* I - PageSize name buffer */ - size_t namesize) /* I - Size of name buffer */ -{ - const char *sizeptr, /* Pointer to size in PWG name */ - *dimptr; /* Pointer to dimensions in PWG name */ - - - /* - * Range check input... - */ - - if (!media || !name || namesize < PPD_MAX_NAME) - return (NULL); - - /* - * Copy or generate a PageSize name... - */ - - if (media->ppd) - { - /* - * Use a standard Adobe name... - */ - - strlcpy(name, media->ppd, namesize); - } - else if (!media->pwg || !strncmp(media->pwg, "custom_", 7) || - (sizeptr = strchr(media->pwg, '_')) == NULL || - (dimptr = strchr(sizeptr + 1, '_')) == NULL || - (size_t)(dimptr - sizeptr) > namesize) - { - /* - * Use a name of the form "wNNNhNNN"... - */ - - snprintf(name, namesize, "w%dh%d", (int)_PWG_TOPTS(media->width), - (int)_PWG_TOPTS(media->length)); - } - else - { - /* - * Copy the size name from class_sizename_dimensions... - */ - - memcpy(name, sizeptr + 1, dimptr - sizeptr - 1); - name[dimptr - sizeptr - 1] = '\0'; - } - - return (name); -} - - -/* - * 'pwg_ppdize_name()' - Convert an IPP keyword to a PPD keyword. - */ - -static void -pwg_ppdize_name(const char *ipp, /* I - IPP keyword */ - char *name, /* I - Name buffer */ - size_t namesize) /* I - Size of name buffer */ -{ - char *ptr, /* Pointer into name buffer */ - *end; /* End of name buffer */ - - - *name = toupper(*ipp++); - - for (ptr = name + 1, end = name + namesize - 1; *ipp && ptr < end;) - { - if (*ipp == '-' && _cups_isalpha(ipp[1])) - { - ipp ++; - *ptr++ = toupper(*ipp++ & 255); - } - else - *ptr++ = *ipp++; - } - - *ptr = '\0'; -} - - -/* - * 'pwg_unppdize_name()' - Convert a PPD keyword to a lowercase IPP keyword. - */ - -static void -pwg_unppdize_name(const char *ppd, /* I - PPD keyword */ - char *name, /* I - Name buffer */ - size_t namesize) /* I - Size of name buffer */ -{ - char *ptr, /* Pointer into name buffer */ - *end; /* End of name buffer */ - - - for (ptr = name, end = name + namesize - 1; *ppd && ptr < end; ppd ++) - { - if (_cups_isalnum(*ppd) || *ppd == '-') - *ptr++ = tolower(*ppd & 255); - else if (*ppd == '_' || *ppd == '.') - *ptr++ = '-'; - - if (!_cups_isupper(*ppd) && _cups_isalnum(*ppd) && - _cups_isupper(ppd[1]) && ptr < end) - *ptr++ = '-'; - } - - *ptr = '\0'; -} - - -/* - * End of "$Id$". - */ diff --git a/cups/request.c b/cups/request.c index cf8426fb6..641a51ce0 100644 --- a/cups/request.c +++ b/cups/request.c @@ -22,6 +22,7 @@ * cupsGetResponse() - Get a response to an IPP request. * cupsLastError() - Return the last IPP status code. * cupsLastErrorString() - Return the last IPP status-message. + * _cupsNextDelay() - Return the next retry delay value. * cupsReadResponseData() - Read additional data after the IPP response. * cupsSendRequest() - Send an IPP request. * cupsWriteRequestData() - Write additional data after an IPP request. @@ -414,11 +415,13 @@ cupsGetResponse(http_t *http, /* I - Connection to server or @code CUPS_HTTP if (state == IPP_ERROR) { /* - * Delete the response... + * Flush remaining data and delete the response... */ DEBUG_puts("1cupsGetResponse: IPP read error!"); + httpFlush(http); + ippDelete(response); response = NULL; @@ -512,6 +515,36 @@ cupsLastErrorString(void) } +/* + * '_cupsNextDelay()' - Return the next retry delay value. + * + * This function currently returns the Fibonacci sequence 1 1 2 3 5 8. + * + * Pass 0 for the current delay value to initialize the sequence. + */ + +int /* O - Next delay value */ +_cupsNextDelay(int current, /* I - Current delay value or 0 */ + int *previous) /* IO - Previous delay value */ +{ + int next; /* Next delay value */ + + + if (current > 0) + { + next = (current + *previous) % 12; + *previous = next < current ? 0 : current; + } + else + { + next = 1; + *previous = 0; + } + + return (next); +} + + /* * 'cupsReadResponseData()' - Read additional data after the IPP response. * @@ -658,10 +691,10 @@ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP * "replay" attack... */ - cupsDoAuthentication(http, "POST", resource); + _cupsSetNegotiateAuthString(http); } - else #endif /* HAVE_GSSAPI */ + httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); DEBUG_printf(("2cupsSendRequest: authstring=\"%s\"", http->authstring)); diff --git a/cups/sidechannel.c b/cups/sidechannel.c index 17abb2b3f..460eae351 100644 --- a/cups/sidechannel.c +++ b/cups/sidechannel.c @@ -3,7 +3,7 @@ * * Side-channel API code for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -205,7 +205,7 @@ cupsSideChannelRead( */ if (buffer[0] < CUPS_SC_CMD_SOFT_RESET || - buffer[0] > CUPS_SC_CMD_SNMP_GET_NEXT) + buffer[0] >= CUPS_SC_CMD_MAX) { DEBUG_printf(("1cupsSideChannelRead: Bad command %d!", buffer[0])); *command = CUPS_SC_CMD_NONE; @@ -499,7 +499,7 @@ cupsSideChannelWrite( * Range check input... */ - if (command < CUPS_SC_CMD_SOFT_RESET || command > CUPS_SC_CMD_SNMP_GET_NEXT || + if (command < CUPS_SC_CMD_SOFT_RESET || command >= CUPS_SC_CMD_MAX || datalen < 0 || datalen > 16384 || (datalen > 0 && !data)) return (-1); diff --git a/cups/sidechannel.h b/cups/sidechannel.h index c52cd51cb..29cc01a76 100644 --- a/cups/sidechannel.h +++ b/cups/sidechannel.h @@ -1,9 +1,9 @@ /* * "$Id: sidechannel.h 7616 2008-05-28 00:34:13Z mike $" * - * Side-channel API definitions for the Common UNIX Printing System (CUPS). + * Side-channel API definitions for CUPS. * - * Copyright 2007-2008 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -62,11 +62,22 @@ enum cups_sc_command_e /**** Request command codes ****/ CUPS_SC_CMD_GET_DEVICE_ID = 4, /* Return the IEEE-1284 device ID */ CUPS_SC_CMD_GET_STATE = 5, /* Return the device state */ CUPS_SC_CMD_SNMP_GET = 6, /* Query an SNMP OID @since CUPS 1.4/Mac OS X 10.6@ */ - CUPS_SC_CMD_SNMP_GET_NEXT = 7 /* Query the next SNMP OID @since CUPS 1.4/Mac OS X 10.6@ */ + CUPS_SC_CMD_SNMP_GET_NEXT = 7, /* Query the next SNMP OID @since CUPS 1.4/Mac OS X 10.6@ */ + CUPS_SC_CMD_GET_CONNECTED = 8, /* Return whether the backend is "connected" to the printer @since CUPS 1.5@ */ + CUPS_SC_CMD_MAX /* End of valid values @private@ */ }; typedef enum cups_sc_command_e cups_sc_command_t; /**** Request command codes ****/ +enum cups_sc_connected_e /**** Connectivity values ****/ +{ + CUPS_SC_NOT_CONNECTED = 0, /* Backend is not "connected" to printer */ + CUPS_SC_CONNECTED = 1 /* Backend is "connected" to printer */ +}; +typedef enum cups_sc_connected_e cups_sc_connected_t; + /**** Connectivity values ****/ + + enum cups_sc_state_e /**** Printer state bits ****/ { CUPS_SC_STATE_OFFLINE = 0, /* Device is offline */ diff --git a/cups/testppd.c b/cups/testppd.c index 47cfa01e9..d788f9ace 100644 --- a/cups/testppd.c +++ b/cups/testppd.c @@ -3,7 +3,7 @@ * * PPD test program for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -441,6 +441,21 @@ main(int argc, /* I - Number of command-line arguments */ else puts("PASS"); + fputs("cupsMarkOptions(media=oe_letter-fullbleed_8.5x11in): ", stdout); + num_options = cupsAddOption("media", "oe_letter-fullbleed_8.5x11in", 0, + &options); + cupsMarkOptions(ppd, num_options, options); + cupsFreeOptions(num_options, options); + + size = ppdPageSize(ppd, NULL); + if (!size || strcmp(size->name, "Letter.Fullbleed")) + { + printf("FAIL (%s)\n", size ? size->name : "unknown"); + status ++; + } + else + puts("PASS"); + fputs("cupsMarkOptions(media=A4): ", stdout); num_options = cupsAddOption("media", "A4", 0, &options); cupsMarkOptions(ppd, num_options, options); diff --git a/cups/testpwg.c b/cups/testpwg.c index f15e11e4c..9cf2faadc 100644 --- a/cups/testpwg.c +++ b/cups/testpwg.c @@ -3,7 +3,7 @@ * * PWG test program for CUPS. * - * Copyright 2009-2010 by Apple Inc. + * Copyright 2009-2011 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -15,9 +15,9 @@ * * Contents: * - * main() - Main entry. - * test_pagesize() - Test the PWG mapping functions. - * test_pwg() - Test the PWG mapping functions. + * main() - Main entry. + * test_pagesize() - Test the PWG mapping functions. + * test_ppd_cache() - Test the PPD cache functions. */ /* @@ -32,9 +32,9 @@ * Local functions... */ -static int test_pwg(_pwg_t *pwg, ppd_file_t *ppd); -static int test_pagesize(_pwg_t *pwg, ppd_file_t *ppd, +static int test_pagesize(_ppd_cache_t *pc, ppd_file_t *ppd, const char *ppdsize); +static int test_ppd_cache(_ppd_cache_t *pc, ppd_file_t *ppd); /* @@ -48,7 +48,7 @@ main(int argc, /* I - Number of command-line args */ int status; /* Status of tests (0 = success, 1 = fail) */ const char *ppdfile; /* PPD filename */ ppd_file_t *ppd; /* PPD file */ - _pwg_t *pwg; /* PWG mapping data */ + _ppd_cache_t *pc; /* PPD cache and PWG mapping data */ _pwg_media_t *pwgmedia; /* PWG media size */ @@ -78,8 +78,8 @@ main(int argc, /* I - Number of command-line args */ else puts("PASS"); - fputs("_pwgCreateWithPPD(ppd): ", stdout); - if ((pwg = _pwgCreateWithPPD(ppd)) == NULL) + fputs("_ppdCacheCreateWithPPD(ppd): ", stdout); + if ((pc = _ppdCacheCreateWithPPD(ppd)) == NULL) { puts("FAIL"); status ++; @@ -87,7 +87,7 @@ main(int argc, /* I - Number of command-line args */ else { puts("PASS"); - status += test_pwg(pwg, ppd); + status += test_ppd_cache(pc, ppd); if (argc == 3) { @@ -112,13 +112,14 @@ main(int argc, /* I - Number of command-line args */ media = NULL; if (media) - printf("_pwgGetPageSize(media=%s): ", media->values[0].string.text); + printf("_ppdCacheGetPageSize(media=%s): ", + media->values[0].string.text); else - fputs("_pwgGetPageSize(media-col): ", stdout); + fputs("_ppdCacheGetPageSize(media-col): ", stdout); fflush(stdout); - if ((pagesize = _pwgGetPageSize(pwg, job, NULL, NULL)) == NULL) + if ((pagesize = _ppdCacheGetPageSize(pc, job, NULL, NULL)) == NULL) { puts("FAIL (Not Found)"); status = 1; @@ -142,11 +143,11 @@ main(int argc, /* I - Number of command-line args */ } /* - * _pwgDestroy should never fail... + * _ppdCacheDestroy should never fail... */ - fputs("_pwgDestroy(pwg): ", stdout); - _pwgDestroy(pwg); + fputs("_ppdCacheDestroy(pc): ", stdout); + _ppdCacheDestroy(pc); puts("PASS"); } @@ -268,9 +269,9 @@ main(int argc, /* I - Number of command-line args */ */ static int /* O - 1 on failure, 0 on success */ -test_pagesize(_pwg_t *pwg, /* I - PWG mapping data */ - ppd_file_t *ppd, /* I - PPD file */ - const char *ppdsize) /* I - PPD page size */ +test_pagesize(_ppd_cache_t *pc, /* I - PWG mapping data */ + ppd_file_t *ppd, /* I - PPD file */ + const char *ppdsize) /* I - PPD page size */ { int status = 0; /* Return status */ ipp_t *job; /* Job attributes */ @@ -279,10 +280,10 @@ test_pagesize(_pwg_t *pwg, /* I - PWG mapping data */ if (ppdPageSize(ppd, ppdsize)) { - printf("_pwgGetPageSize(keyword=%s): ", ppdsize); + printf("_ppdCacheGetPageSize(keyword=%s): ", ppdsize); fflush(stdout); - if ((pagesize = _pwgGetPageSize(pwg, NULL, ppdsize, NULL)) == NULL) + if ((pagesize = _ppdCacheGetPageSize(pc, NULL, ppdsize, NULL)) == NULL) { puts("FAIL (Not Found)"); status = 1; @@ -298,10 +299,10 @@ test_pagesize(_pwg_t *pwg, /* I - PWG mapping data */ job = ippNew(); ippAddString(job, IPP_TAG_JOB, IPP_TAG_KEYWORD, "media", NULL, ppdsize); - printf("_pwgGetPageSize(media=%s): ", ppdsize); + printf("_ppdCacheGetPageSize(media=%s): ", ppdsize); fflush(stdout); - if ((pagesize = _pwgGetPageSize(pwg, job, NULL, NULL)) == NULL) + if ((pagesize = _ppdCacheGetPageSize(pc, job, NULL, NULL)) == NULL) { puts("FAIL (Not Found)"); status = 1; @@ -322,16 +323,16 @@ test_pagesize(_pwg_t *pwg, /* I - PWG mapping data */ /* - * 'test_pwg()' - Test the PWG mapping functions. + * 'test_ppd_cache()' - Test the PPD cache functions. */ static int /* O - 1 on failure, 0 on success */ -test_pwg(_pwg_t *pwg, /* I - PWG mapping data */ - ppd_file_t *ppd) /* I - PPD file */ +test_ppd_cache(_ppd_cache_t *pc, /* I - PWG mapping data */ + ppd_file_t *ppd) /* I - PPD file */ { int i, /* Looping var */ status = 0; /* Return status */ - _pwg_t *pwg2; /* Loaded data */ + _ppd_cache_t *pc2; /* Loaded data */ _pwg_size_t *size, /* Size from original */ *size2; /* Size from saved */ _pwg_map_t *map, /* Map from original */ @@ -342,8 +343,8 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */ * Verify that we can write and read back the same data... */ - fputs("_pwgWriteFile(test.pwg): ", stdout); - if (!_pwgWriteFile(pwg, "test.pwg")) + fputs("_ppdCacheWriteFile(test.pwg): ", stdout); + if (!_ppdCacheWriteFile(pc, "test.pwg", NULL)) { puts("FAIL"); status ++; @@ -351,27 +352,28 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */ else puts("PASS"); - fputs("_pwgCreateWithFile(test.pwg): ", stdout); - if ((pwg2 = _pwgCreateWithFile("test.pwg")) == NULL) + fputs("_ppdCacheCreateWithFile(test.pwg): ", stdout); + if ((pc2 = _ppdCacheCreateWithFile("test.pwg", NULL)) == NULL) { puts("FAIL"); status ++; } else { - if (pwg2->num_sizes != pwg->num_sizes) + // TODO: FINISH ADDING ALL VALUES IN STRUCTURE + if (pc2->num_sizes != pc->num_sizes) { if (!status) puts("FAIL"); - printf(" SAVED num_sizes=%d, ORIG num_sizes=%d\n", pwg2->num_sizes, - pwg->num_sizes); + printf(" SAVED num_sizes=%d, ORIG num_sizes=%d\n", pc2->num_sizes, + pc->num_sizes); status ++; } else { - for (i = pwg->num_sizes, size = pwg->sizes, size2 = pwg2->sizes; + for (i = pc->num_sizes, size = pc->sizes, size2 = pc2->sizes; i > 0; i --, size ++, size2 ++) { @@ -424,7 +426,7 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */ } } - for (i = pwg->num_sources, map = pwg->sources, map2 = pwg2->sources; + for (i = pc->num_sources, map = pc->sources, map2 = pc2->sources; i > 0; i --, map ++, map2 ++) { @@ -447,7 +449,7 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */ } } - for (i = pwg->num_types, map = pwg->types, map2 = pwg2->types; + for (i = pc->num_types, map = pc->types, map2 = pc2->types; i > 0; i --, map ++, map2 ++) { @@ -474,17 +476,17 @@ test_pwg(_pwg_t *pwg, /* I - PWG mapping data */ if (!status) puts("PASS"); - _pwgDestroy(pwg2); + _ppdCacheDestroy(pc2); } /* * Test PageSize mapping code... */ - status += test_pagesize(pwg, ppd, "Letter"); - status += test_pagesize(pwg, ppd, "na-letter"); - status += test_pagesize(pwg, ppd, "A4"); - status += test_pagesize(pwg, ppd, "iso-a4"); + status += test_pagesize(pc, ppd, "Letter"); + status += test_pagesize(pc, ppd, "na-letter"); + status += test_pagesize(pc, ppd, "A4"); + status += test_pagesize(pc, ppd, "iso-a4"); return (status); } diff --git a/filter/commandtops.c b/filter/commandtops.c index 47a49072b..f858610a3 100644 --- a/filter/commandtops.c +++ b/filter/commandtops.c @@ -3,7 +3,7 @@ * * PostScript command filter for CUPS. * - * Copyright 2008-2010 by Apple Inc. + * Copyright 2008-2011 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -162,6 +162,19 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */ */ begin_ps(ppd, user); + fflush(stdout); + + /* + * Wait for the printer to become connected... + */ + + do + { + sleep(1); + datalen = 1; + } + while (cupsSideChannelDoRequest(CUPS_SC_CMD_GET_CONNECTED, buffer, &datalen, + 5.0) == CUPS_SC_STATUS_OK && !buffer[0]); /* * Then loop through every option in the PPD file and ask for the current @@ -199,7 +212,7 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */ * Read the response data... */ - while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer) - 1, 5.0)) > 0) + while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer) - 1, 90.0)) > 0) { /* * Trim whitespace from both ends... @@ -215,6 +228,8 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */ for (bufptr = buffer; isspace(*bufptr & 255); bufptr ++); + fprintf(stderr, "DEBUG: Got \"%s\" (%d bytes)\n", bufptr, (int)bytes); + /* * Skip blank lines... */ @@ -222,6 +237,13 @@ auto_configure(ppd_file_t *ppd, /* I - PPD file */ if (!*bufptr) continue; + /* + * Verify the result is a valid option choice... + */ + + if (!ppdFindChoice(option, bufptr)) + continue; + /* * Write out the result and move on to the next option... */ diff --git a/filter/raster.c b/filter/raster.c index d864634a9..a57dd1874 100644 --- a/filter/raster.c +++ b/filter/raster.c @@ -84,6 +84,7 @@ struct _cups_raster_s /**** Raster stream data ****/ * Local functions... */ +static int cups_raster_io(cups_raster_t *r, unsigned char *buf, int bytes); static unsigned cups_raster_read_header(cups_raster_t *r); static int cups_raster_read(cups_raster_t *r, unsigned char *buf, int bytes); @@ -189,7 +190,7 @@ cupsRasterOpenIO( * Open for read - get sync word... */ - if ((*r->iocb)(r->ctx, (unsigned char *)&(r->sync), sizeof(r->sync)) != + if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) != sizeof(r->sync)) { _cupsRasterAddError("Unable to read header from raster stream: %s\n", @@ -246,7 +247,7 @@ cupsRasterOpenIO( break; } - if ((*r->iocb)(r->ctx, (unsigned char *)&(r->sync), sizeof(r->sync)) + if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) < sizeof(r->sync)) { _cupsRasterAddError("Unable to write raster stream header: %s\n", @@ -284,7 +285,7 @@ cupsRasterReadHeader( if (!cups_raster_read_header(r)) return (0); - + /* * Copy the header to the user-supplied buffer... */ @@ -313,7 +314,7 @@ cupsRasterReadHeader2( if (!cups_raster_read_header(r)) return (0); - + /* * Copy the header to the user-supplied buffer... */ @@ -357,7 +358,7 @@ cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */ r->remaining -= len / r->header.cupsBytesPerLine; - if ((*r->iocb)(r->ctx, p, len) < (ssize_t)len) + if (cups_raster_io(r, p, len) < (ssize_t)len) return (0); /* @@ -538,7 +539,7 @@ cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */ * * @deprecated@ */ - + unsigned /* O - 1 on success, 0 on failure */ cupsRasterWriteHeader( cups_raster_t *r, /* I - Raster stream */ @@ -581,10 +582,10 @@ cupsRasterWriteHeader( fh.cupsColorOrder = htonl(r->header.cupsColorOrder); fh.cupsColorSpace = htonl(r->header.cupsColorSpace); - return ((*r->iocb)(r->ctx, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh)); + return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh)); } else - return ((*r->iocb)(r->ctx, (unsigned char *)&(r->header), sizeof(r->header)) + return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header)) == sizeof(r->header)); } @@ -597,7 +598,7 @@ cupsRasterWriteHeader( * * @since CUPS 1.2/Mac OS X 10.5@ */ - + unsigned /* O - 1 on success, 0 on failure */ cupsRasterWriteHeader2( cups_raster_t *r, /* I - Raster stream */ @@ -639,10 +640,10 @@ cupsRasterWriteHeader2( fh.cupsColorOrder = htonl(r->header.cupsColorOrder); fh.cupsColorSpace = htonl(r->header.cupsColorSpace); - return ((*r->iocb)(r->ctx, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh)); + return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh)); } else - return ((*r->iocb)(r->ctx, (unsigned char *)&(r->header), sizeof(r->header)) + return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header)) == sizeof(r->header)); } @@ -722,10 +723,10 @@ cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */ * Write the byte-swapped buffer... */ - return ((*r->iocb)(r->ctx, r->buffer, len)); + return (cups_raster_io(r, r->buffer, len)); } else - return ((*r->iocb)(r->ctx, p, len)); + return (cups_raster_io(r, p, len)); } /* @@ -897,6 +898,37 @@ cups_raster_read_header( } +/* + * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions. + */ + +static int /* O - Bytes read or -1 */ +cups_raster_io(cups_raster_t *r, /* I - Raster stream */ + unsigned char *buf, /* I - Buffer for read/write */ + int bytes) /* I - Number of bytes to read/write */ +{ + ssize_t count; /* Number of bytes read/written */ + size_t total; /* Total bytes read/written */ + + + DEBUG_printf(("4cups_raster_io(r=%p, buf=%p, bytes=%d)", r, buf, bytes)); + + for (total = 0; total < bytes; total += count, buf += count) + { + count = (*r->iocb)(r->ctx, buf, bytes - total); + + DEBUG_printf(("5cups_raster_io: count=%d, total=%d", (int)count, + (int)total)); + if (count == 0) + return (0); + else if (count < 0) + return (-1); + } + + return ((int)total); +} + + /* * 'cups_raster_read()' - Read through the raster buffer. */ @@ -914,7 +946,7 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */ DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=%d)\n", r, buf, bytes)); if (!r->compressed) - return ((*r->iocb)(r->ctx, buf, bytes)); + return (cups_raster_io(r, buf, bytes)); /* * Allocate a read buffer as needed... @@ -1256,7 +1288,7 @@ cups_raster_write( count ++; ptr += bpp; } - + *wptr++ = 257 - count; count *= bpp; @@ -1265,7 +1297,7 @@ cups_raster_write( } } - return ((*r->iocb)(r->ctx, r->buffer, wptr - r->buffer)); + return (cups_raster_io(r, r->buffer, wptr - r->buffer)); } @@ -1276,30 +1308,18 @@ cups_raster_write( static ssize_t /* O - Bytes read or -1 */ cups_read_fd(void *ctx, /* I - File descriptor as pointer */ unsigned char *buf, /* I - Buffer for read */ - size_t bytes) /* I - Number of bytes to read */ + size_t bytes) /* I - Maximum number of bytes to read */ { int fd = (int)((intptr_t)ctx); /* File descriptor */ ssize_t count; /* Number of bytes read */ - size_t total; /* Total bytes read */ - - for (total = 0; total < bytes; total += count, buf += count) - { - count = read(fd, buf, bytes - total); - if (count == 0) - return (0); - else if (count < 0) - { - if (errno == EINTR) - count = 0; - else - return (-1); - } - } + while ((count = read(fd, buf, bytes)) < 0) + if (errno != EINTR && errno != EAGAIN) + return (-1); - return ((ssize_t)total); + return (count); } @@ -1341,23 +1361,13 @@ cups_write_fd(void *ctx, /* I - File descriptor pointer */ int fd = (int)((intptr_t)ctx); /* File descriptor */ ssize_t count; /* Number of bytes written */ - size_t total; /* Total bytes written */ - - for (total = 0; total < bytes; total += count, buf += count) - { - count = write(fd, buf, bytes - total); - if (count < 0) - { - if (errno == EINTR) - count = 0; - else - return (-1); - } - } + while ((count = write(fd, buf, bytes)) < 0) + if (errno != EINTR && errno != EAGAIN) + return (-1); - return ((ssize_t)total); + return (count); } diff --git a/filter/testraster.c b/filter/testraster.c index 48085c4fb..a8188d11f 100644 --- a/filter/testraster.c +++ b/filter/testraster.c @@ -19,6 +19,7 @@ * main() - Test the raster functions. * do_ppd_tests() - Test the default option commands in a PPD file. * do_ps_tests() - Test standard PostScript commands. + * do_ras_file() - Test reading of a raster file. * do_raster_tests() - Test reading and writing of raster data. * print_changes() - Print differences in the page header. */ @@ -28,6 +29,12 @@ */ #include "image-private.h" +#ifdef WIN32 +# include +#else +# include +# include +#endif /* WIN32 */ /* @@ -193,6 +200,7 @@ static cups_page_header2_t setpagedevice_header = static int do_ppd_tests(const char *filename, int num_options, cups_option_t *options); static int do_ps_tests(void); +static int do_ras_file(const char *filename); static int do_raster_tests(cups_mode_t mode); static void print_changes(cups_page_header2_t *header, cups_page_header2_t *expected); @@ -207,6 +215,7 @@ main(int argc, /* I - Number of command-line args */ char *argv[]) /* I - Command-line arguments */ { int errors; /* Number of errors */ + const char *ext; /* Filename extension */ if (argc == 1) @@ -239,6 +248,7 @@ main(int argc, /* I - Number of command-line args */ else { puts("Usage: testraster [-o name=value ...] [filename.ppd ...]"); + puts(" testraster [filename.ras ...]"); return (1); } } @@ -246,11 +256,23 @@ main(int argc, /* I - Number of command-line args */ else { puts("Usage: testraster [-o name=value ...] [filename.ppd ...]"); + puts(" testraster [filename.ras ...]"); return (1); } } + else if ((ext = strrchr(argv[i], '.')) != NULL) + { + if (!strcmp(ext, ".ppd")) + errors += do_ppd_tests(argv[i], num_options, options); + else + errors += do_ras_file(argv[i]); + } else - errors += do_ppd_tests(argv[i], num_options, options); + { + puts("Usage: testraster [-o name=value ...] [filename.ppd ...]"); + puts(" testraster [filename.ras ...]"); + return (1); + } } cupsFreeOptions(num_options, options); @@ -352,7 +374,7 @@ do_ps_tests(void) } else puts("PASS"); - + fputs("_cupsRasterExecPS(\"roll\"): ", stdout); fflush(stdout); @@ -431,92 +453,66 @@ do_ps_tests(void) else puts("PASS"); -#if 0 - fputs("_cupsRasterExecPS(\"\"): ", stdout); - fflush(stdout); + return (errors); +} - if (_cupsRasterExecPS(&header, &preferred_bits, - "")) - { - puts("FAIL (error from function)"); - errors ++; - } - else if (header.) - { - printf("FAIL ()\n"); - errors ++; - } - else - puts("PASS"); - fputs("_cupsRasterExecPS(\"\"): ", stdout); - fflush(stdout); +/* + * 'do_ras_file()' - Test reading of a raster file. + */ - if (_cupsRasterExecPS(&header, &preferred_bits, - "")) - { - puts("FAIL (error from function)"); - errors ++; - } - else if (header.) - { - printf("FAIL ()\n"); - errors ++; - } - else - puts("PASS"); +static int /* O - Number of errors */ +do_ras_file(const char *filename) /* I - Filename */ +{ + unsigned y; /* Looping vars */ + int fd; /* File descriptor */ + cups_raster_t *ras; /* Raster stream */ + cups_page_header2_t header; /* Page header */ + unsigned char *data; /* Raster data */ + int errors = 0; /* Number of errors */ + unsigned pages = 0; /* Number of pages */ - fputs("_cupsRasterExecPS(\"\"): ", stdout); - fflush(stdout); - if (_cupsRasterExecPS(&header, &preferred_bits, - "")) + if ((fd = open(filename, O_RDONLY)) < 0) { - puts("FAIL (error from function)"); - errors ++; + printf("%s: %s\n", filename, strerror(errno)); + return (1); } - else if (header.) + + if ((ras = cupsRasterOpen(fd, CUPS_RASTER_READ)) == NULL) { - printf("FAIL ()\n"); - errors ++; + printf("%s: cupsRasterOpen failed.\n", filename); + close(fd); + return (1); } - else - puts("PASS"); - fputs("_cupsRasterExecPS(\"\"): ", stdout); - fflush(stdout); + printf("%s:\n", filename); - if (_cupsRasterExecPS(&header, &preferred_bits, - "")) + while (cupsRasterReadHeader2(ras, &header)) { - puts("FAIL (error from function)"); - errors ++; - } - else if (header.) - { - printf("FAIL ()\n"); - errors ++; - } - else - puts("PASS"); + pages ++; + data = malloc(header.cupsBytesPerLine); - fputs("_cupsRasterExecPS(\"\"): ", stdout); - fflush(stdout); + printf(" Page %u: %ux%ux%u@%ux%udpi", pages, + header.cupsWidth, header.cupsHeight, header.cupsBitsPerPixel, + header.HWResolution[0], header.HWResolution[1]); + fflush(stdout); - if (_cupsRasterExecPS(&header, &preferred_bits, - "")) - { - puts("FAIL (error from function)"); - errors ++; - } - else if (header.) - { - printf("FAIL ()\n"); - errors ++; + for (y = 0; y < header.cupsHeight; y ++) + if (cupsRasterReadPixels(ras, data, header.cupsBytesPerLine) < + header.cupsBytesPerLine) + break; + + if (y < header.cupsHeight) + printf(" ERROR AT LINE %d\n", y); + else + putchar('\n'); + + free(data); } - else - puts("PASS"); -#endif /* 0 */ + + cupsRasterClose(ras); + close(fd); return (errors); } diff --git a/notifier/dbus.c b/notifier/dbus.c index 62a6aaffc..542a929da 100644 --- a/notifier/dbus.c +++ b/notifier/dbus.c @@ -332,7 +332,7 @@ main(int argc, /* I - Number of command-line args */ const char *word2 = event + 4; /* Second word */ params = PARAMS_JOB; - if (!strcmp(word2, "state")) + if (!strcmp(word2, "state-changed")) signame = "JobState"; else if (!strcmp(word2, "created")) signame = "JobCreated"; diff --git a/ppdc/sample.drv b/ppdc/sample.drv index 7a4426b75..9410cd787 100644 --- a/ppdc/sample.drv +++ b/ppdc/sample.drv @@ -315,6 +315,7 @@ Version "1.5" Throughput 8 ModelNumber $HP_LASERJET ColorDevice No + Attribute 1284DeviceID "" "CMD:PCL;" UIConstraints "*Duplex *Option1 False" UIConstraints "*PageSize A3 *InputSlot Envelope" @@ -367,6 +368,7 @@ Version "1.5" ColorDevice Yes Attribute PSVersion "" "(2016.0) 0" Attribute LanguageLevel "" 2 + Attribute 1284DeviceID "" "CMD:PS;" UIConstraints "*Duplex *Option1 False" @@ -392,6 +394,7 @@ Version "1.5" Duplex Yes Installable "Option1/Duplexer" + Attribute "?Option1" "" "save currentpagedevice/Duplex known{(True)}{(False)}ifelse = flush restore" } } @@ -409,6 +412,7 @@ Version "1.5" ManualCopies Yes ColorDevice Yes Throughput 1 + Attribute 1284DeviceID "" "MFG:HP;MDL:HP DeskJet;CMD:PCL;" UIConstraints "*PageSize A3 *InputSlot Envelope" UIConstraints "*PageSize A4 *InputSlot Envelope" @@ -461,6 +465,7 @@ Version "1.5" Throughput 8 ModelNumber $HP_LASERJET ColorDevice No + Attribute 1284DeviceID "" "MFG:HP;MDL:HP LaserJet;CMD:PCL;" UIConstraints "*Duplex *Option1 False" UIConstraints "*PageSize A3 *InputSlot Envelope" diff --git a/scheduler/auth.c b/scheduler/auth.c index 191e17fc2..16c83b8cd 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -501,11 +501,23 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ struct passwd *pwd; /* Password entry for this user */ cupsd_ucred_t peercred; /* Peer credentials */ socklen_t peersize; /* Size of peer credentials */ +#ifdef HAVE_AUTHORIZATION_H + const char *name; /* Authorizing name */ + for (name = (char *)cupsArrayFirst(con->best->names); + name; + name = (char *)cupsArrayNext(con->best->names)) + if (!strncasecmp(name, "@AUTHKEY(", 9) || !strcasecmp(name, "@SYSTEM")) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "PeerCred authentication not allowed for resource."); + return; + } +#endif /* HAVE_AUTHORIZATION_H */ if ((pwd = getpwnam(authorization + 9)) == NULL) { - cupsdLogMessage(CUPSD_LOG_ERROR, "User \"%s\" does not exist!", + cupsdLogMessage(CUPSD_LOG_ERROR, "User \"%s\" does not exist.", authorization + 9); return; } diff --git a/scheduler/conf.c b/scheduler/conf.c index 26b80870c..193c03f8f 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -145,7 +145,6 @@ static const cupsd_var_t variables[] = { "MaxJobsPerUser", &MaxJobsPerUser, CUPSD_VARTYPE_INTEGER }, { "MaxLeaseDuration", &MaxLeaseDuration, CUPSD_VARTYPE_INTEGER }, { "MaxLogSize", &MaxLogSize, CUPSD_VARTYPE_INTEGER }, - { "MaxPrinterHistory", &MaxPrinterHistory, CUPSD_VARTYPE_INTEGER }, { "MaxRequestSize", &MaxRequestSize, CUPSD_VARTYPE_INTEGER }, { "MaxSubscriptions", &MaxSubscriptions, CUPSD_VARTYPE_INTEGER }, { "MaxSubscriptionsPerJob", &MaxSubscriptionsPerJob, CUPSD_VARTYPE_INTEGER }, @@ -626,7 +625,6 @@ cupsdReadConfiguration(void) MaxClients = 100; MaxClientsPerHost = 0; MaxLogSize = 1024 * 1024; - MaxPrinterHistory = 0; MaxRequestSize = 0; MultipleOperationTimeout = DEFAULT_TIMEOUT; ReloadTimeout = DEFAULT_KEEPALIVE; diff --git a/scheduler/conf.h b/scheduler/conf.h index 86a3e5a07..052725cce 100644 --- a/scheduler/conf.h +++ b/scheduler/conf.h @@ -183,8 +183,6 @@ VAR int MaxClients VALUE(100), /* Maximum number of copies per job */ MaxLogSize VALUE(1024 * 1024), /* Maximum size of log files */ - MaxPrinterHistory VALUE(10), - /* Maximum printer state history */ MaxRequestSize VALUE(0), /* Maximum size of IPP requests */ HostNameLookups VALUE(FALSE), diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx index 4b9d87855..5ddf5b3cf 100644 --- a/scheduler/cups-driverd.cxx +++ b/scheduler/cups-driverd.cxx @@ -1,13 +1,13 @@ /* * "$Id$" * - * PPD/driver support for the Common UNIX Printing System (CUPS). + * PPD/driver support for CUPS. * * This program handles listing and installing static PPD files, PPD files * created from driver information files, and dynamically generated PPD files * using driver helper programs. * - * Copyright 2007-2009 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -2391,15 +2391,34 @@ regex_device_id(const char *device_id) /* I - IEEE-1284 device ID */ *ptr++ = '('; - while (*device_id && *device_id != ';' && ptr < (res + sizeof(res) - 4)) + while (*device_id && *device_id != ';' && ptr < (res + sizeof(res) - 8)) { if (strchr("[]{}().*\\|", *device_id)) *ptr++ = '\\'; - *ptr++ = *device_id++; + if (*device_id == ':') + { + /* + * KEY:.*value + */ + + *ptr++ = *device_id++; + *ptr++ = '.'; + *ptr++ = '*'; + } + else + *ptr++ = *device_id++; } if (*device_id == ';' || !*device_id) + { + /* + * KEY:.*value.*; + */ + + *ptr++ = '.'; + *ptr++ = '*'; *ptr++ = ';'; + } *ptr++ = ')'; if (cmd) *ptr++ = '?'; diff --git a/scheduler/dirsvc.c b/scheduler/dirsvc.c index bf1041287..99182c674 100644 --- a/scheduler/dirsvc.c +++ b/scheduler/dirsvc.c @@ -2396,7 +2396,7 @@ dnssdBuildTxtRecord( keyvalue[i++][1] = for_lpd ? "100" : "0"; keyvalue[i ][0] = "product"; - keyvalue[i++][1] = p->product ? p->product : "Unknown"; + keyvalue[i++][1] = p->pc && p->pc->product ? p->pc->product : "Unknown"; snprintf(type_str, sizeof(type_str), "0x%X", p->type | CUPS_PRINTER_REMOTE); snprintf(state_str, sizeof(state_str), "%d", p->state); diff --git a/scheduler/ipp.c b/scheduler/ipp.c index fd1c6b6b5..9e3c80bc7 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -926,8 +926,6 @@ accept_jobs(cupsd_client_t *con, /* I - Client connection */ printer->accepting = 1; printer->state_message[0] = '\0'; - cupsdAddPrinterHistory(printer); - cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL, "Now accepting jobs."); @@ -1137,7 +1135,6 @@ add_class(cupsd_client_t *con, /* I - Client connection */ pclass->name, attr->values[0].boolean, pclass->accepting); pclass->accepting = attr->values[0].boolean; - cupsdAddPrinterHistory(pclass); cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, pclass, NULL, "%s accepting jobs.", pclass->accepting ? "Now" : "No longer"); @@ -1184,7 +1181,6 @@ add_class(cupsd_client_t *con, /* I - Client connection */ { strlcpy(pclass->state_message, attr->values[0].string.text, sizeof(pclass->state_message)); - cupsdAddPrinterHistory(pclass); cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, pclass, NULL, "%s", pclass->state_message); @@ -1275,8 +1271,6 @@ add_class(cupsd_client_t *con, /* I - Client connection */ } else { - cupsdAddPrinterHistory(pclass); - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, pclass, NULL, "New class \"%s\" added by \"%s\".", pclass->name, get_username(con)); @@ -1546,7 +1540,7 @@ add_job(cupsd_client_t *con, /* I - Client connection */ if (!ippFindAttribute(con->request, "PageRegion", IPP_TAG_ZERO) && !ippFindAttribute(con->request, "PageSize", IPP_TAG_ZERO) && - _pwgGetPageSize(printer->pwg, con->request, NULL, &exact)) + _ppdCacheGetPageSize(printer->pc, con->request, NULL, &exact)) { if (!exact && (media_col = ippFindAttribute(con->request, "media-col", @@ -2697,7 +2691,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ printer->name, attr->values[0].boolean, printer->accepting); printer->accepting = attr->values[0].boolean; - cupsdAddPrinterHistory(printer); cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL, "%s accepting jobs.", @@ -2745,7 +2738,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ { strlcpy(printer->state_message, attr->values[0].string.text, sizeof(printer->state_message)); - cupsdAddPrinterHistory(printer); cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL, "%s", printer->state_message); @@ -2952,11 +2944,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ char cache_name[1024]; /* Cache filename for printer attrs */ - snprintf(cache_name, sizeof(cache_name), "%s/%s.ipp4", CacheDir, - printer->name); - unlink(cache_name); - - snprintf(cache_name, sizeof(cache_name), "%s/%s.pwg3", CacheDir, + snprintf(cache_name, sizeof(cache_name), "%s/%s.data", CacheDir, printer->name); unlink(cache_name); @@ -3047,8 +3035,6 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ } else { - cupsdAddPrinterHistory(printer); - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, printer, NULL, "New printer \"%s\" added by \"%s\".", printer->name, get_username(con)); @@ -6025,7 +6011,6 @@ copy_printer_attrs( /* Printer icons */ time_t curtime; /* Current time */ int i; /* Looping var */ - ipp_attribute_t *history; /* History collection */ /* @@ -6163,23 +6148,6 @@ copy_printer_attrs( ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "printer-state-change-time", printer->state_time); - if (MaxPrinterHistory > 0 && printer->num_history > 0 && - cupsArrayFind(ra, "printer-state-history")) - { - /* - * Printer history is only sent if specifically requested, so that - * older CUPS/IPP clients won't barf on the collection attributes. - */ - - history = ippAddCollections(con->response, IPP_TAG_PRINTER, - "printer-state-history", - printer->num_history, NULL); - - for (i = 0; i < printer->num_history; i ++) - copy_attrs(history->values[i].collection = ippNew(), printer->history[i], - NULL, IPP_TAG_ZERO, 0, NULL); - } - if (!ra || cupsArrayFind(ra, "printer-state-message")) ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message", NULL, printer->state_message); @@ -6191,7 +6159,6 @@ copy_printer_attrs( { int type; /* printer-type value */ - /* * Add the CUPS-specific printer-type attribute... */ @@ -7043,13 +7010,10 @@ delete_printer(cupsd_client_t *con, /* I - Client connection */ printer->name); unlink(filename); - snprintf(filename, sizeof(filename), "%s/%s.ipp4", CacheDir, printer->name); - unlink(filename); - snprintf(filename, sizeof(filename), "%s/%s.png", CacheDir, printer->name); unlink(filename); - snprintf(filename, sizeof(filename), "%s/%s.pwg3", CacheDir, printer->name); + snprintf(filename, sizeof(filename), "%s/%s.data", CacheDir, printer->name); unlink(filename); #ifdef __APPLE__ @@ -8980,7 +8944,6 @@ hold_new_jobs(cupsd_client_t *con, /* I - Connection */ printer->holding_new_jobs = 1; cupsdSetPrinterReasons(printer, "+hold-new-jobs"); - cupsdAddPrinterHistory(printer); if (dtype & CUPS_PRINTER_CLASS) cupsdLogMessage(CUPSD_LOG_INFO, @@ -9827,8 +9790,6 @@ reject_jobs(cupsd_client_t *con, /* I - Client connection */ strlcpy(printer->state_message, attr->values[0].string.text, sizeof(printer->state_message)); - cupsdAddPrinterHistory(printer); - cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL, "No longer accepting jobs."); @@ -9904,7 +9865,6 @@ release_held_new_jobs( printer->holding_new_jobs = 0; cupsdSetPrinterReasons(printer, "-hold-new-jobs"); - cupsdAddPrinterHistory(printer); if (dtype & CUPS_PRINTER_CLASS) cupsdLogMessage(CUPSD_LOG_INFO, diff --git a/scheduler/job.c b/scheduler/job.c index efacdd318..d511e80f4 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -291,7 +291,7 @@ cupsdCheckJobs(void) if (job->kill_time && job->kill_time <= curtime) { - cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Stopping unresponsive job!", + cupsdLogMessage(CUPSD_LOG_ERROR, "[Job %d] Stopping unresponsive job!", job->id); stop_job(job, CUPSD_JOB_FORCE); @@ -904,9 +904,9 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ if (filter && filter->dst) { - if (strchr(filter->dst->type, '/')) + if ((ptr = strchr(filter->dst->type, '/')) != NULL) snprintf(final_content_type, sizeof(final_content_type), - "FINAL_CONTENT_TYPE=%s", filter->dst->type); + "FINAL_CONTENT_TYPE=%s", ptr + 1); else snprintf(final_content_type, sizeof(final_content_type), "FINAL_CONTENT_TYPE=%s/%s", filter->dst->super, @@ -3034,12 +3034,13 @@ get_options(cupsd_job_t *job, /* I - Job */ char *optptr, /* Pointer to options */ *valptr; /* Pointer in value string */ ipp_attribute_t *attr; /* Current attribute */ - _pwg_t *pwg; /* PWG->PPD mapping data */ + _ppd_cache_t *pc; /* PPD cache and mapping data */ int num_pwgppds; /* Number of PWG->PPD options */ cups_option_t *pwgppds, /* PWG->PPD options */ *pwgppd, /* Current PWG->PPD option */ *preset; /* Current preset option */ - int output_mode, /* Output mode (if any) */ + int print_color_mode, + /* Output mode (if any) */ print_quality; /* Print quality (if any) */ const char *ppd; /* PPD option choice */ int exact; /* Did we get an exact match? */ @@ -3055,28 +3056,31 @@ get_options(cupsd_job_t *job, /* I - Job */ * First build an options array for any PWG->PPD mapped option/choice pairs. */ - pwg = job->printer->pwg; + pc = job->printer->pc; num_pwgppds = 0; pwgppds = NULL; - if (pwg && + if (pc && !ippFindAttribute(job->attrs, "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-quality", IPP_TAG_ZERO))) { /* * Map output-mode and print-quality to a preset... */ - if ((attr = ippFindAttribute(job->attrs, "output-mode", - IPP_TAG_KEYWORD)) != NULL && - !strcmp(attr->values[0].string.text, "monochrome")) - output_mode = _PWG_OUTPUT_MODE_MONOCHROME; + 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")) + print_color_mode = _PWG_PRINT_COLOR_MODE_MONOCHROME; else - output_mode = _PWG_OUTPUT_MODE_COLOR; + print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR; if ((attr = ippFindAttribute(job->attrs, "print-quality", IPP_TAG_ENUM)) != NULL && @@ -3086,33 +3090,33 @@ get_options(cupsd_job_t *job, /* I - Job */ else print_quality = _PWG_PRINT_QUALITY_NORMAL; - if (pwg->num_presets[output_mode][print_quality] == 0) + if (pc->num_presets[print_color_mode][print_quality] == 0) { /* * Try to find a preset that works so that we maximize the chances of us * getting a good print using IPP attributes. */ - if (pwg->num_presets[output_mode][_PWG_PRINT_QUALITY_NORMAL] > 0) + if (pc->num_presets[print_color_mode][_PWG_PRINT_QUALITY_NORMAL] > 0) print_quality = _PWG_PRINT_QUALITY_NORMAL; - else if (pwg->num_presets[_PWG_OUTPUT_MODE_COLOR][print_quality] > 0) - output_mode = _PWG_OUTPUT_MODE_COLOR; + else if (pc->num_presets[_PWG_PRINT_COLOR_MODE_COLOR][print_quality] > 0) + print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR; else { - print_quality = _PWG_PRINT_QUALITY_NORMAL; - output_mode = _PWG_OUTPUT_MODE_COLOR; + print_quality = _PWG_PRINT_QUALITY_NORMAL; + print_color_mode = _PWG_PRINT_COLOR_MODE_COLOR; } } - if (pwg->num_presets[output_mode][print_quality] > 0) + if (pc->num_presets[print_color_mode][print_quality] > 0) { /* * Copy the preset options as long as the corresponding names are not * already defined in the IPP request... */ - for (i = pwg->num_presets[output_mode][print_quality], - preset = pwg->presets[output_mode][print_quality]; + for (i = pc->num_presets[print_color_mode][print_quality], + preset = pc->presets[print_color_mode][print_quality]; i > 0; i --, preset ++) { @@ -3123,13 +3127,13 @@ get_options(cupsd_job_t *job, /* I - Job */ } } - if (pwg) + if (pc) { if (!ippFindAttribute(job->attrs, "InputSlot", IPP_TAG_ZERO) && !ippFindAttribute(job->attrs, "HPPaperSource", IPP_TAG_ZERO)) { - if ((ppd = _pwgGetInputSlot(pwg, job->attrs, NULL)) != NULL) - num_pwgppds = cupsAddOption(pwg->source_option, ppd, num_pwgppds, + if ((ppd = _ppdCacheGetInputSlot(pc, job->attrs, NULL)) != NULL) + num_pwgppds = cupsAddOption(pc->source_option, ppd, num_pwgppds, &pwgppds); else if (!ippFindAttribute(job->attrs, "AP_D_InputSlot", IPP_TAG_ZERO)) num_pwgppds = cupsAddOption("AP_D_InputSlot", "", num_pwgppds, @@ -3137,12 +3141,12 @@ get_options(cupsd_job_t *job, /* I - Job */ } if (!ippFindAttribute(job->attrs, "MediaType", IPP_TAG_ZERO) && - (ppd = _pwgGetMediaType(pwg, job->attrs, NULL)) != NULL) + (ppd = _ppdCacheGetMediaType(pc, job->attrs, NULL)) != NULL) num_pwgppds = cupsAddOption("MediaType", ppd, num_pwgppds, &pwgppds); if (!ippFindAttribute(job->attrs, "PageRegion", IPP_TAG_ZERO) && !ippFindAttribute(job->attrs, "PageSize", IPP_TAG_ZERO) && - (ppd = _pwgGetPageSize(pwg, job->attrs, NULL, &exact)) != NULL) + (ppd = _ppdCacheGetPageSize(pc, job->attrs, NULL, &exact)) != NULL) { num_pwgppds = cupsAddOption("PageSize", ppd, num_pwgppds, &pwgppds); @@ -3155,7 +3159,7 @@ get_options(cupsd_job_t *job, /* I - Job */ IPP_TAG_ZERO)) != NULL && (attr->value_tag == IPP_TAG_KEYWORD || attr->value_tag == IPP_TAG_NAME) && - (ppd = _pwgGetOutputBin(pwg, attr->values[0].string.text)) != NULL) + (ppd = _ppdCacheGetOutputBin(pc, attr->values[0].string.text)) != NULL) { /* * Map output-bin to OutputBin option... @@ -3164,8 +3168,8 @@ get_options(cupsd_job_t *job, /* I - Job */ num_pwgppds = cupsAddOption("OutputBin", ppd, num_pwgppds, &pwgppds); } - if (pwg->sides_option && - !ippFindAttribute(job->attrs, pwg->sides_option, IPP_TAG_ZERO) && + if (pc->sides_option && + !ippFindAttribute(job->attrs, pc->sides_option, IPP_TAG_ZERO) && (attr = ippFindAttribute(job->attrs, "sides", IPP_TAG_KEYWORD)) != NULL) { /* @@ -3173,13 +3177,13 @@ get_options(cupsd_job_t *job, /* I - Job */ */ if (!strcmp(attr->values[0].string.text, "one-sided")) - num_pwgppds = cupsAddOption(pwg->sides_option, pwg->sides_1sided, + num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_1sided, num_pwgppds, &pwgppds); else if (!strcmp(attr->values[0].string.text, "two-sided-long-edge")) - num_pwgppds = cupsAddOption(pwg->sides_option, pwg->sides_2sided_long, + num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_2sided_long, num_pwgppds, &pwgppds); else if (!strcmp(attr->values[0].string.text, "two-sided-short-edge")) - num_pwgppds = cupsAddOption(pwg->sides_option, pwg->sides_2sided_short, + num_pwgppds = cupsAddOption(pc->sides_option, pc->sides_2sided_short, num_pwgppds, &pwgppds); } } @@ -4210,10 +4214,7 @@ update_job(cupsd_job_t *job) /* I - Job to check */ return; } else if (cupsdSetPrinterReasons(job->printer, message)) - { - cupsdAddPrinterHistory(job->printer); event |= CUPSD_EVENT_PRINTER_STATE; - } update_job_attrs(job, 0); } @@ -4379,7 +4380,6 @@ update_job(cupsd_job_t *job) /* I - Job to check */ { strlcpy(job->printer->state_message, ptr, sizeof(job->printer->state_message)); - cupsdAddPrinterHistory(job->printer); event |= CUPSD_EVENT_PRINTER_STATE | CUPSD_EVENT_JOB_PROGRESS; diff --git a/scheduler/main.c b/scheduler/main.c index 9d99264f5..2bed2e834 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -1800,7 +1800,6 @@ process_children(void) { strlcpy(job->printer->state_message, message, sizeof(job->printer->state_message)); - cupsdAddPrinterHistory(job->printer); } if (!job->attrs) diff --git a/scheduler/printers.c b/scheduler/printers.c index b04b75646..044902e2a 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -15,7 +15,6 @@ * Contents: * * cupsdAddPrinter() - Add a printer to the system. - * cupsdAddPrinterHistory() - Add the current printer state to the history. * cupsdCreateCommonData() - Create the common printer data. * cupsdDeleteAllPrinters() - Delete all printers from the system. * cupsdDeletePrinter() - Delete a printer from the system. @@ -43,10 +42,8 @@ * add_printer_filter() - Add a MIME filter for a printer. * add_printer_formats() - Add document-format-supported values for a * printer. - * add_string_array() - Add a string to an array of CUPS strings. * compare_printers() - Compare two printers. * delete_printer_filters() - Delete all MIME filters for a printer. - * delete_string_array() - Delete an array of CUPS strings. * dirty_printer() - Mark config and state files dirty for the * specified printer. * load_ppd() - Load a cached PPD file, updating the cache as @@ -89,10 +86,8 @@ static void add_printer_defaults(cupsd_printer_t *p); static void add_printer_filter(cupsd_printer_t *p, mime_type_t *type, const char *filter); static void add_printer_formats(cupsd_printer_t *p); -static void add_string_array(cups_array_t **a, const char *s); static int compare_printers(void *first, void *second, void *data); static void delete_printer_filters(cupsd_printer_t *p); -static void delete_string_array(cups_array_t **a); static void dirty_printer(cupsd_printer_t *p); static void load_ppd(cupsd_printer_t *p); static ipp_t *new_media_col(_pwg_size_t *size, const char *source, @@ -155,9 +150,6 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */ p->op_policy_ptr = DefaultPolicyPtr; - if (MaxPrinterHistory) - p->history = calloc(MaxPrinterHistory, sizeof(ipp_t *)); - /* * Insert the printer in the printer list alphabetically... */ @@ -180,67 +172,6 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */ } -/* - * 'cupsdAddPrinterHistory()' - Add the current printer state to the history. - */ - -void -cupsdAddPrinterHistory( - cupsd_printer_t *p) /* I - Printer */ -{ - ipp_t *history; /* History collection */ - - - /* - * Stop early if we aren't keeping history data... - */ - - if (MaxPrinterHistory <= 0) - return; - - /* - * Retire old history data as needed... - */ - - p->sequence_number ++; - - if (p->num_history >= MaxPrinterHistory) - { - p->num_history --; - ippDelete(p->history[0]); - memmove(p->history, p->history + 1, p->num_history * sizeof(ipp_t *)); - } - - /* - * Create a collection containing the current printer-state, printer-up-time, - * printer-state-message, and printer-state-reasons attributes. - */ - - history = ippNew(); - ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state", - p->state); - ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-accepting-jobs", - p->accepting); - ippAddBoolean(history, IPP_TAG_PRINTER, "printer-is-shared", p->shared); - ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-state-message", - NULL, p->state_message); - if (p->num_reasons == 0) - ippAddString(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "printer-state-reasons", NULL, "none"); - else - ippAddStrings(history, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "printer-state-reasons", p->num_reasons, NULL, - (const char * const *)p->reasons); - ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "printer-state-change-time", p->state_time); - ippAddInteger(history, IPP_TAG_PRINTER, IPP_TAG_INTEGER, - "printer-state-sequence-number", p->sequence_number); - - p->history[p->num_history] = history; - p->num_history ++; -} - - /* * 'cupsdCreateCommonData()' - Create the common printer data. */ @@ -880,14 +811,6 @@ cupsdDeletePrinter( if (p->printers != NULL) free(p->printers); - if (MaxPrinterHistory) - { - for (i = 0; i < p->num_history; i ++) - ippDelete(p->history[i]); - - free(p->history); - } - delete_printer_filters(p); for (i = 0; i < p->num_reasons; i ++) @@ -899,9 +822,6 @@ cupsdDeletePrinter( mimeDeleteType(MimeDatabase, p->filetype); mimeDeleteType(MimeDatabase, p->prefiltertype); - delete_string_array(&(p->filters)); - delete_string_array(&(p->pre_filters)); - cupsdFreeStrings(&(p->users)); cupsdFreeQuotas(p); @@ -923,7 +843,6 @@ cupsdDeletePrinter( cupsdClearString(&p->alert_description); #ifdef HAVE_DNSSD - cupsdClearString(&p->product); cupsdClearString(&p->pdl); #endif /* HAVE_DNSSD */ @@ -1059,7 +978,6 @@ cupsdLoadAllPrinters(void) */ cupsdSetPrinterAttrs(p); - cupsdAddPrinterHistory(p); if (strncmp(p->device_uri, "file:", 5) && p->state != IPP_PRINTER_STOPPED) @@ -1251,44 +1169,6 @@ cupsdLoadAllPrinters(void) cupsdLogMessage(CUPSD_LOG_ERROR, "Syntax error on line %d of printers.conf.", linenum); } - else if (!strcasecmp(line, "Product")) - { - if (value) - { -#ifdef HAVE_DNSSD - p->product = _cupsStrAlloc(value); -#endif /* HAVE_DNSSD */ - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "Filter")) - { - if (value) - { - if (!p->filters) - p->filters = cupsArrayNew(NULL, NULL); - - cupsArrayAdd(p->filters, _cupsStrAlloc(value)); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } - else if (!strcasecmp(line, "PreFilter")) - { - if (value) - { - if (!p->pre_filters) - p->pre_filters = cupsArrayNew(NULL, NULL); - - cupsArrayAdd(p->pre_filters, _cupsStrAlloc(value)); - } - else - cupsdLogMessage(CUPSD_LOG_ERROR, - "Syntax error on line %d of printers.conf.", linenum); - } else if (!strcasecmp(line, "Shared")) { /* @@ -1671,21 +1551,6 @@ cupsdSaveAllPrinters(void) cupsFilePrintf(fp, "Type %d\n", printer->type); -#ifdef HAVE_DNSSD - if (printer->product) - cupsFilePutConf(fp, "Product", printer->product); -#endif /* HAVE_DNSSD */ - - for (ptr = (char *)cupsArrayFirst(printer->filters); - ptr; - ptr = (char *)cupsArrayNext(printer->filters)) - cupsFilePutConf(fp, "Filter", ptr); - - for (ptr = (char *)cupsArrayFirst(printer->pre_filters); - ptr; - ptr = (char *)cupsArrayNext(printer->pre_filters)) - cupsFilePutConf(fp, "PreFilter", ptr); - if (printer->accepting) cupsFilePuts(fp, "Accepting Yes\n"); else @@ -2469,18 +2334,55 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ cupsdSetPrinterReasons(p, "-cups-missing-filter-warning," "cups-insecure-filter-warning"); - for (filter = (char *)cupsArrayFirst(p->filters); - filter; - filter = (char *)cupsArrayNext(p->filters)) - add_printer_filter(p, p->filetype, filter); + if (p->pc && p->pc->filters) + { + for (filter = (char *)cupsArrayFirst(p->pc->filters); + filter; + filter = (char *)cupsArrayNext(p->pc->filters)) + add_printer_filter(p, p->filetype, filter); + } + else if (!(p->type & CUPS_PRINTER_REMOTE)) + { + char interface[1024]; /* Interface script */ + + + snprintf(interface, sizeof(interface), "%s/interfaces/%s", ServerRoot, + p->name); + if (!access(interface, X_OK)) + { + /* + * Yes, we have a System V style interface script; use it! + */ + + snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s", + ServerRoot, p->name); + add_printer_filter(p, p->filetype, interface); + } + else + { + /* + * Add a filter from application/vnd.cups-raw to printer/name to + * handle "raw" printing by users. + */ + + add_printer_filter(p, p->filetype, "application/vnd.cups-raw 0 -"); - if (p->pre_filters) + /* + * Add a PostScript filter, since this is still possibly PS printer. + */ + + add_printer_filter(p, p->filetype, + "application/vnd.cups-postscript 0 -"); + } + } + + if (p->pc && p->pc->prefilters) { p->prefiltertype = mimeAddType(MimeDatabase, "prefilter", p->name); - for (filter = (char *)cupsArrayFirst(p->pre_filters); + for (filter = (char *)cupsArrayFirst(p->pc->prefilters); filter; - filter = (char *)cupsArrayNext(p->pre_filters)) + filter = (char *)cupsArrayNext(p->pc->prefilters)) add_printer_filter(p, p->prefiltertype, filter); } } @@ -2912,12 +2814,6 @@ cupsdSetPrinterState( if (s == IPP_PRINTER_PROCESSING) p->state_message[0] = '\0'; - /* - * Update the printer history... - */ - - cupsdAddPrinterHistory(p); - /* * Let the browse protocols reflect the change... */ @@ -3602,6 +3498,11 @@ add_printer_filter( struct stat fileinfo; /* File information */ + cupsdLogMessage(CUPSD_LOG_DEBUG2, + "add_printer_filter(p=%p(%s), filtertype=%p(%s/%s), " + "filter=\"%s\")", p, p->name, filtertype, filtertype->super, + filtertype->type, filter); + /* * Parse the filter string; it should be in one of the following formats: * @@ -3612,14 +3513,24 @@ add_printer_filter( if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, dsuper, dtype, &cost, program) == 6) { - snprintf(dest, sizeof(dest), "%s/%s", dsuper, dtype); + snprintf(dest, sizeof(dest), "%s/%s/%s", p->name, dsuper, dtype); + + if ((desttype = mimeType(MimeDatabase, "printer", dest)) == NULL) + { + desttype = mimeAddType(MimeDatabase, "printer", dest); + if (!p->dest_types) + p->dest_types = cupsArrayNew(NULL, NULL); + + cupsArrayAdd(p->dest_types, desttype); + } + } else { if (sscanf(filter, "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type, &cost, program) == 4) { - strlcpy(dest, p->name, sizeof(dest)); + desttype = filtertype; } else { @@ -3706,15 +3617,6 @@ add_printer_filter( * Add the filter to the MIME database, supporting wildcards as needed... */ - if ((desttype = mimeType(MimeDatabase, "printer", dest)) == NULL) - { - desttype = mimeAddType(MimeDatabase, "printer", dest); - if (!p->dest_types) - p->dest_types = cupsArrayNew(NULL, NULL); - - cupsArrayAdd(p->dest_types, desttype); - } - for (temptype = mimeFirstType(MimeDatabase); temptype; temptype = mimeNextType(MimeDatabase)) @@ -3908,21 +3810,6 @@ add_printer_formats(cupsd_printer_t *p) /* I - Printer */ } -/* - * 'add_string_array()' - Add a string to an array of CUPS strings. - */ - -static void -add_string_array(cups_array_t **a, /* I - Array */ - const char *s) /* I - String */ -{ - if (!*a) - *a = cupsArrayNew(NULL, NULL); - - cupsArrayAdd(*a, _cupsStrAlloc(s)); -} - - /* * 'compare_printers()' - Compare two printers. */ @@ -3987,26 +3874,6 @@ delete_printer_filters( } -/* - * 'delete_string_array()' - Delete an array of CUPS strings. - */ - -static void -delete_string_array(cups_array_t **a) /* I - Array */ -{ - char *ptr; /* Current string */ - - - for (ptr = (char *)cupsArrayFirst(*a); - ptr; - ptr = (char *)cupsArrayNext(*a)) - _cupsStrFree(ptr); - - cupsArrayDelete(*a); - *a = NULL; -} - - /* * 'dirty_printer()' - Mark config and state files dirty for the specified * printer. @@ -4035,11 +3902,8 @@ static void load_ppd(cupsd_printer_t *p) /* I - Printer */ { int i, j, k; /* Looping vars */ - cups_file_t *cache; /* IPP cache file */ - char cache_name[1024]; /* IPP cache filename */ - struct stat cache_info; /* IPP cache file info */ - char pwg_name[1024]; /* PWG cache filename */ - struct stat pwg_info; /* PWG cache file info */ + char cache_name[1024]; /* Cache filename */ + struct stat cache_info; /* Cache file info */ ppd_file_t *ppd; /* PPD file */ char ppd_name[1024]; /* PPD filename */ struct stat ppd_info; /* PPD file info */ @@ -4067,6 +3931,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ qualities[3]; /* print-quality values */ int num_margins, /* Number of media-*-margin-supported values */ margins[16]; /* media-*-margin-supported values */ + const char *filter; /* Current filter */ static const char * const sides[3] = /* sides-supported values */ { "one-sided", @@ -4085,14 +3950,10 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * Check to see if the cache is up-to-date... */ - snprintf(cache_name, sizeof(cache_name), "%s/%s.ipp4", CacheDir, p->name); + snprintf(cache_name, sizeof(cache_name), "%s/%s.data", CacheDir, p->name); if (stat(cache_name, &cache_info)) cache_info.st_mtime = 0; - snprintf(pwg_name, sizeof(pwg_name), "%s/%s.pwg3", CacheDir, p->name); - if (stat(pwg_name, &pwg_info)) - pwg_info.st_mtime = 0; - snprintf(ppd_name, sizeof(ppd_name), "%s/ppd/%s.ppd", ServerRoot, p->name); if (stat(ppd_name, &ppd_info)) ppd_info.st_mtime = 1; @@ -4100,29 +3961,22 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippDelete(p->ppd_attrs); p->ppd_attrs = ippNew(); - _pwgDestroy(p->pwg); - p->pwg = NULL; - - if (pwg_info.st_mtime >= ppd_info.st_mtime) - p->pwg = _pwgCreateWithFile(pwg_name); + _ppdCacheDestroy(p->pc); + p->pc = NULL; - if (cache_info.st_mtime >= ppd_info.st_mtime && p->pwg && - (cache = cupsFileOpen(cache_name, "r")) != NULL) + if (cache_info.st_mtime >= ppd_info.st_mtime) { - /* - * Load cached information and return... - */ - cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Loading %s...", cache_name); - if (ippReadIO(cache, (ipp_iocb_t)cupsFileRead, 1, NULL, - p->ppd_attrs) == IPP_DATA) + if ((p->pc = _ppdCacheCreateWithFile(cache_name, &p->ppd_attrs)) != NULL && + p->ppd_attrs) { - cupsFileClose(cache); + /* + * Loaded successfully! + */ + return; } - - cupsFileClose(cache); } /* @@ -4131,14 +3985,8 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ cupsdMarkDirty(CUPSD_DIRTY_PRINTERS); - _pwgDestroy(p->pwg); - p->pwg = NULL; - cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Loading %s...", ppd_name); - delete_string_array(&(p->filters)); - delete_string_array(&(p->pre_filters)); - p->type &= ~CUPS_PRINTER_OPTIONS; p->type |= CUPS_PRINTER_BW; @@ -4151,7 +3999,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * Add make/model and other various attributes... */ - p->pwg = _pwgCreateWithPPD(ppd); + p->pc = _ppdCacheCreateWithPPD(ppd); ppdMarkDefaults(ppd); @@ -4195,9 +4043,9 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ if (ppdFindChoice(output_mode, "draft") || ppdFindChoice(output_mode, "fast")) qualities[num_qualities ++] = IPP_QUALITY_DRAFT; - if (ppdFindChoice(output_mode, "normal") || - ppdFindChoice(output_mode, "good")) - qualities[num_qualities ++] = IPP_QUALITY_NORMAL; + + qualities[num_qualities ++] = IPP_QUALITY_NORMAL; + if (ppdFindChoice(output_mode, "best") || ppdFindChoice(output_mode, "high")) qualities[num_qualities ++] = IPP_QUALITY_HIGH; @@ -4219,8 +4067,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ qualities[num_qualities ++] = IPP_QUALITY_NORMAL; qualities[num_qualities ++] = IPP_QUALITY_HIGH; } - - if (num_qualities == 0) + else qualities[num_qualities ++] = IPP_QUALITY_NORMAL; ippAddIntegers(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, @@ -4255,7 +4102,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * Add media options from the PPD file... */ - if (ppd->num_sizes == 0 || !p->pwg) + if (ppd->num_sizes == 0 || !p->pc) { if (!ppdFindAttr(ppd, "APScannerOnly", NULL)) cupsdLogMessage(CUPSD_LOG_CRIT, @@ -4274,7 +4121,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ */ if ((size = ppdPageSize(ppd, NULL)) != NULL) - pwgsize = _pwgGetSize(p->pwg, size->name); + pwgsize = _ppdCacheGetSize(p->pc, size->name); else pwgsize = NULL; @@ -4294,12 +4141,12 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ media_type = ppdFindMarkedChoice(ppd, "MediaType"); col = new_media_col(pwgsize, input_slot ? - _pwgGetSource(p->pwg, - input_slot->choice) : + _ppdCacheGetSource(p->pc, + input_slot->choice) : NULL, media_type ? - _pwgGetType(p->pwg, - media_type->choice) : + _ppdCacheGetType(p->pc, + media_type->choice) : NULL); ippAddCollection(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-default", @@ -4311,8 +4158,8 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * media-supported */ - num_media = p->pwg->num_sizes; - if (p->pwg->custom_min_keyword) + num_media = p->pc->num_sizes; + if (p->pc->custom_min_keyword) num_media += 2; if ((attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, @@ -4321,16 +4168,16 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ { val = attr->values; - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes; + for (i = p->pc->num_sizes, pwgsize = p->pc->sizes; i > 0; i --, pwgsize ++, val ++) val->string.text = _cupsStrRetain(pwgsize->map.pwg); - if (p->pwg->custom_min_keyword) + if (p->pc->custom_min_keyword) { - val->string.text = _cupsStrRetain(p->pwg->custom_min_keyword); + val->string.text = _cupsStrRetain(p->pc->custom_min_keyword); val ++; - val->string.text = _cupsStrRetain(p->pwg->custom_max_keyword); + val->string.text = _cupsStrRetain(p->pc->custom_max_keyword); } } @@ -4338,12 +4185,12 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * media-source-supported */ - if (p->pwg->num_sources > 0 && + if (p->pc->num_sources > 0 && (attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "media-source-supported", p->pwg->num_sources, + "media-source-supported", p->pc->num_sources, NULL, NULL)) != NULL) { - for (i = p->pwg->num_sources, pwgsource = p->pwg->sources, + for (i = p->pc->num_sources, pwgsource = p->pc->sources, val = attr->values; i > 0; i --, pwgsource ++, val ++) @@ -4354,12 +4201,12 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * media-type-supported */ - if (p->pwg->num_types > 0 && + if (p->pc->num_types > 0 && (attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "media-type-supported", p->pwg->num_types, + "media-type-supported", p->pc->num_types, NULL, NULL)) != NULL) { - for (i = p->pwg->num_types, pwgtype = p->pwg->types, + for (i = p->pc->num_types, pwgtype = p->pc->types, val = attr->values; i > 0; i --, pwgtype ++, val ++) @@ -4370,7 +4217,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * media-*-margin-supported */ - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0; + for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, num_margins = 0; i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); i --, pwgsize ++) { @@ -4392,7 +4239,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-bottom-margin-supported", 0); - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0; + for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, num_margins = 0; i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); i --, pwgsize ++) { @@ -4414,7 +4261,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-left-margin-supported", 0); - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0; + for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, num_margins = 0; i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); i --, pwgsize ++) { @@ -4436,7 +4283,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_INTEGER, "media-right-margin-supported", 0); - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, num_margins = 0; + for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, num_margins = 0; i > 0 && num_margins < (int)(sizeof(margins) / sizeof(margins[0])); i --, pwgsize ++) { @@ -4462,23 +4309,23 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * media-col-database */ - num_media = p->pwg->num_sizes; - if (p->pwg->num_sources) + num_media = p->pc->num_sizes; + if (p->pc->num_sources) { - if (p->pwg->num_types > 0) - num_media += p->pwg->num_sizes * p->pwg->num_sources * - p->pwg->num_types; + if (p->pc->num_types > 0) + num_media += p->pc->num_sizes * p->pc->num_sources * + p->pc->num_types; else - num_media += p->pwg->num_sizes * p->pwg->num_sources; + num_media += p->pc->num_sizes * p->pc->num_sources; } - else if (p->pwg->num_types) - num_media += p->pwg->num_sizes * p->pwg->num_types; + else if (p->pc->num_types) + num_media += p->pc->num_sizes * p->pc->num_types; if ((attr = ippAddCollections(p->ppd_attrs, IPP_TAG_PRINTER, "media-col-database", num_media, NULL)) != NULL) { - for (i = p->pwg->num_sizes, pwgsize = p->pwg->sizes, val = attr->values; + for (i = p->pc->num_sizes, pwgsize = p->pc->sizes, val = attr->values; i > 0; i --, pwgsize ++) { @@ -4496,17 +4343,17 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * type... */ - if (p->pwg->num_sources > 0) + if (p->pc->num_sources > 0) { - for (j = p->pwg->num_sources, pwgsource = p->pwg->sources; + for (j = p->pc->num_sources, pwgsource = p->pc->sources; j > 0; j --, pwgsource ++) { ppdMarkOption(ppd, "InputSlot", pwgsource->ppd); - if (p->pwg->num_types > 0) + if (p->pc->num_types > 0) { - for (k = p->pwg->num_types, pwgtype = p->pwg->types; + for (k = p->pc->num_types, pwgtype = p->pc->types; k > 0; k --, pwgtype ++) { @@ -4525,9 +4372,9 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } } } - else if (p->pwg->num_types > 0) + else if (p->pc->num_types > 0) { - for (j = p->pwg->num_types, pwgtype = p->pwg->types; + for (j = p->pc->num_types, pwgtype = p->pc->types; j > 0; j --, pwgtype ++) { @@ -4552,35 +4399,35 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ * Output bin... */ - if (p->pwg && p->pwg->num_bins > 0) + if (p->pc && p->pc->num_bins > 0) { attr = ippAddStrings(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-supported", p->pwg->num_bins, + "output-bin-supported", p->pc->num_bins, NULL, NULL); if (attr != NULL) { for (i = 0, val = attr->values; - i < p->pwg->num_bins; + i < p->pc->num_bins; i ++, val ++) - val->string.text = _cupsStrAlloc(p->pwg->bins[i].pwg); + val->string.text = _cupsStrAlloc(p->pc->bins[i].pwg); } if ((output_bin = ppdFindOption(ppd, "OutputBin")) != NULL) { - for (i = 0; i < p->pwg->num_bins; i ++) - if (!strcmp(p->pwg->bins[i].ppd, output_bin->defchoice)) + for (i = 0; i < p->pc->num_bins; i ++) + if (!strcmp(p->pc->bins[i].ppd, output_bin->defchoice)) break; - if (i >= p->pwg->num_bins) + if (i >= p->pc->num_bins) i = 0; ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-default", NULL, p->pwg->bins[i].pwg); + "output-bin-default", NULL, p->pc->bins[i].pwg); } else ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, - "output-bin-default", NULL, p->pwg->bins[0].pwg); + "output-bin-default", NULL, p->pc->bins[0].pwg); } else if (((ppd_attr = ppdFindAttr(ppd, "DefaultOutputOrder", NULL)) != NULL && @@ -4608,7 +4455,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } /* - * output-mode... + * output-mode and print-color-mode... */ if (ppd->color_device) @@ -4623,6 +4470,11 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ "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); + ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_KEYWORD, + "print-color-mode-default", NULL, "color"); } else { @@ -4630,6 +4482,11 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ "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"); } /* @@ -4795,106 +4652,21 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ } /* - * Add a filter from application/vnd.cups-raw to printer/name to - * handle "raw" printing by users. + * Scan the filters in the PPD file... */ - add_string_array(&(p->filters), "application/vnd.cups-raw 0 -"); - - /* - * Add any pre-filters in the PPD file... - */ - - if ((ppd_attr = ppdFindAttr(ppd, "cupsPreFilter", NULL)) != NULL) - { - for (; ppd_attr; ppd_attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL)) - if (ppd_attr->value) - add_string_array(&(p->pre_filters), ppd_attr->value); - } - - /* - * Add any filters in the PPD file... - */ - - if ((ppd_attr = ppdFindAttr(ppd, "cupsFilter2", NULL)) != NULL) - { - /* - * Use new cupsFilter2 filter syntax... - */ - - for (; ppd_attr; ppd_attr = ppdFindNextAttr(ppd, "cupsFilter2", NULL)) - { - add_string_array(&(p->filters), ppd_attr->value); - - if (!strncasecmp(ppd_attr->value, "application/vnd.cups-command", 28) && - isspace(ppd_attr->value[28] & 255)) - p->type |= CUPS_PRINTER_COMMANDS; - } - } - else + if (p->pc) { - /* - * Use old cupsFilter syntax... - */ - - DEBUG_printf(("ppd->num_filters = %d\n", ppd->num_filters)); - for (i = 0; i < ppd->num_filters; i ++) + for (filter = (const char *)cupsArrayFirst(p->pc->filters); + filter; + filter = (const char *)cupsArrayNext(p->pc->filters)) { - DEBUG_printf(("ppd->filters[%d] = \"%s\"\n", i, ppd->filters[i])); - add_string_array(&(p->filters), ppd->filters[i]); - - if (!strncasecmp(ppd->filters[i], "application/vnd.cups-command", 28) && - isspace(ppd->filters[i][28] & 255)) - p->type |= CUPS_PRINTER_COMMANDS; - } - } - - if ((ppd_attr = ppdFindAttr(ppd, "cupsCommands", NULL)) != NULL && - ppd_attr->value && - (!ppd_attr->value[0] || !strcasecmp(ppd_attr->value, "none"))) - { - /* - * Printer does not support CUPS command files (or any commands as far as - * CUPS is concerned... - */ - - p->type &= ~CUPS_PRINTER_COMMANDS; - } - else if (ppd->num_filters == 0) - { - /* - * If there are no filters, add PostScript printing filters. - */ - - add_string_array(&(p->filters), - "application/vnd.cups-command 0 commandtops"); - add_string_array(&(p->filters), - "application/vnd.cups-postscript 0 -"); - - p->type |= CUPS_PRINTER_COMMANDS; - } - else if (!(p->type & CUPS_PRINTER_COMMANDS)) - { - /* - * See if this is a PostScript device without a command filter... - */ - - for (i = 0; i < ppd->num_filters; i ++) - if (!strncasecmp(ppd->filters[i], - "application/vnd.cups-postscript", 31) && - isspace(ppd->filters[i][31] & 255)) + if (!strncasecmp(filter, "application/vnd.cups-command", 28) && + _cups_isspace(filter[28])) + { + p->type |= CUPS_PRINTER_COMMANDS; break; - - if (i < ppd->num_filters) - { - /* - * Add the generic PostScript command filter... - */ - - add_string_array(&(p->filters), - "application/vnd.cups-command application/postscript " - "0 commandtops"); - p->type |= CUPS_PRINTER_COMMANDS; + } } } @@ -4905,12 +4677,11 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ *end; /* End of name */ int count; /* Number of commands */ - - if (ppd_attr && ppd_attr->value && ppd_attr->value[0]) + if ((ppd_attr = ppdFindAttr(ppd, "cupsCommands", NULL)) != NULL) { for (count = 0, start = ppd_attr->value; *start; count ++) { - while (isspace(*start & 255)) + while (_cups_isspace(*start)) start ++; if (!*start) @@ -5017,10 +4788,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ attr->values[i].string.text = _cupsStrAlloc("bcp"); } -#ifdef HAVE_DNSSD - cupsdSetString(&p->product, ppd->product); -#endif /* HAVE_DNSSD */ - if (ppdFindAttr(ppd, "APRemoteQueueID", NULL)) p->type |= CUPS_PRINTER_REMOTE; @@ -5179,19 +4946,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ cupsdLogMessage(CUPSD_LOG_INFO, "Hint: Run \"cupstestppd %s\" and fix any errors.", ppd_name); - - /* - * Add a filter from application/vnd.cups-raw to printer/name to - * handle "raw" printing by users. - */ - - add_string_array(&(p->filters), "application/vnd.cups-raw 0 -"); - - /* - * Add a PostScript filter, since this is still possibly PS printer. - */ - - add_string_array(&(p->filters), "application/vnd.cups-postscript 0 -"); } else { @@ -5213,10 +4967,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddString(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-make-and-model", NULL, "Local System V Printer"); - - snprintf(interface, sizeof(interface), "*/* 0 %s/interfaces/%s", - ServerRoot, p->name); - add_string_array(&(p->filters), interface); } else if (!strncmp(p->device_uri, "ipp://", 6) && (strstr(p->device_uri, "/printers/") != NULL || @@ -5289,7 +5039,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ ippAddInteger(p->ppd_attrs, IPP_TAG_PRINTER, IPP_TAG_ENUM, "finishings-default", IPP_FINISHINGS_NONE); - if (ppd && (cache = cupsFileOpen(cache_name, "w9")) != NULL) + if (ppd && p->pc) { /* * Save cached PPD attributes to disk... @@ -5297,20 +5047,7 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ cupsdLogMessage(CUPSD_LOG_DEBUG, "load_ppd: Saving %s...", cache_name); - p->ppd_attrs->state = IPP_IDLE; - - if (ippWriteIO(cache, (ipp_iocb_t)cupsFileWrite, 1, NULL, - p->ppd_attrs) != IPP_DATA) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to save PPD cache file \"%s\" - %s", cache_name, - strerror(errno)); - unlink(cache_name); - } - - cupsFileClose(cache); - - _pwgWriteFile(p->pwg, pwg_name); + _ppdCacheWriteFile(p->pc, cache_name, p->ppd_attrs); } else { @@ -5320,9 +5057,6 @@ load_ppd(cupsd_printer_t *p) /* I - Printer */ if (cache_info.st_mtime) unlink(cache_name); - - if (pwg_info.st_mtime) - unlink(pwg_name); } } diff --git a/scheduler/printers.h b/scheduler/printers.h index dcbf302f4..9dd9ded68 100644 --- a/scheduler/printers.h +++ b/scheduler/printers.h @@ -70,7 +70,8 @@ struct cupsd_printer_s int remote; /* Remote queue? */ mime_type_t *filetype, /* Pseudo-filetype for printer */ *prefiltertype; /* Pseudo-filetype for pre-filters */ - cups_array_t *filetypes; /* Supported file types */ + cups_array_t *filetypes, /* Supported file types */ + *dest_types; /* Destination types for queue */ cupsd_job_t *job; /* Current job in queue */ ipp_t *attrs, /* Attributes supported by this printer */ *ppd_attrs; /* Attributes based on the PPD */ @@ -83,8 +84,6 @@ struct cupsd_printer_s cups_array_t *quotas; /* Quota records */ int deny_users; /* 1 = deny, 0 = allow */ cups_array_t *users; /* Allowed/denied users */ - int num_history; /* Number of history collections */ - ipp_t **history; /* History data */ int sequence_number; /* Increasing sequence number */ int num_options; /* Number of default options */ cups_option_t *options; /* Default options */ @@ -93,14 +92,10 @@ struct cupsd_printer_s char *alert, /* PSX printer-alert value */ *alert_description; /* PSX printer-alert-description value */ time_t marker_time; /* Last time marker attributes were updated */ - cups_array_t *filters, /* Filters for queue */ - *pre_filters, /* Pre-filters for queue */ - *dest_types; /* Destination types for queue */ - _pwg_t *pwg; /* PWG<->PPD mapping data */ + _ppd_cache_t *pc; /* PPD cache and mapping data */ #ifdef HAVE_DNSSD char *reg_name, /* Name used for service registration */ - *product, /* PPD Product string */ *pdl, /* pdl value for TXT record */ *ipp_txt, /* IPP TXT record contents */ *printer_txt; /* LPD TXT record contents */ @@ -138,7 +133,6 @@ VAR cupsd_policy_t *DefaultPolicyPtr */ extern cupsd_printer_t *cupsdAddPrinter(const char *name); -extern void cupsdAddPrinterHistory(cupsd_printer_t *p); extern void cupsdCreateCommonData(void); extern void cupsdDeleteAllPrinters(void); extern int cupsdDeletePrinter(cupsd_printer_t *p, int update); diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh index 7179209a4..084d39544 100755 --- a/test/run-stp-tests.sh +++ b/test/run-stp-tests.sh @@ -251,6 +251,7 @@ ln -s $root/backend/ipp /tmp/cups-$user/bin/backend ln -s $root/backend/lpd /tmp/cups-$user/bin/backend ln -s $root/backend/mdns /tmp/cups-$user/bin/backend ln -s $root/backend/parallel /tmp/cups-$user/bin/backend +ln -s $root/backend/pseudo /tmp/cups-$user/bin/backend ln -s $root/backend/serial /tmp/cups-$user/bin/backend ln -s $root/backend/snmp /tmp/cups-$user/bin/backend ln -s $root/backend/socket /tmp/cups-$user/bin/backend @@ -810,20 +811,6 @@ else echo "

PASS: $count debug2 messages.

" >>$strfile fi -# Page log file... -if test `uname` = Darwin; then - # Currently just test for Mac OS X since others do not have UI to - # select a user-wide default media size... - if $GREP -iq 'testfile.pdf na_letter_8.5x11in' /tmp/cups-$user/log/page_log; then - echo "PASS: page_log formatted correctly." - echo "

PASS: page_log formatted correctly.

" >>$strfile - else - echo "FAIL: page_log formatted incorrectly." - echo "

FAIL: page_log formatted incorrectly - no page size information.

" >>$strfile - fail=`expr $fail + 1` - fi -fi - # Log files... echo "

access_log

" >>$strfile echo "
" >>$strfile