]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from CUPS 1.5svn-r9602.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Mon, 14 Mar 2011 18:45:10 +0000 (18:45 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Mon, 14 Mar 2011 18:45:10 +0000 (18:45 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@3046 a1ca3aef-8c08-0410-bb20-df032aa958be

49 files changed:
CHANGES-1.4.txt
CHANGES.txt
backend/backend-private.h
backend/ipp.c
backend/lpd.c
backend/network.c
backend/pseudo [new file with mode: 0644]
backend/runloop.c
backend/snmp-supplies.c
backend/socket.c
backend/usb-libusb.c
cgi-bin/admin.c
cups/Makefile
cups/auth.c
cups/cups-private.h
cups/dest.c
cups/file.c
cups/globals.c
cups/libcups2.def
cups/libcups_s.exp
cups/mark.c
cups/ppd-cache.c [new file with mode: 0644]
cups/ppd-private.h
cups/ppd.c
cups/ppd.h
cups/pwg-file.c [deleted file]
cups/pwg-media.c
cups/pwg-ppd.c [deleted file]
cups/request.c
cups/sidechannel.c
cups/sidechannel.h
cups/testppd.c
cups/testpwg.c
filter/commandtops.c
filter/raster.c
filter/testraster.c
notifier/dbus.c
ppdc/sample.drv
scheduler/auth.c
scheduler/conf.c
scheduler/conf.h
scheduler/cups-driverd.cxx
scheduler/dirsvc.c
scheduler/ipp.c
scheduler/job.c
scheduler/main.c
scheduler/printers.c
scheduler/printers.h
test/run-stp-tests.sh

index 3259a2970765b0781d36f0fded8fdc49bc19ca89..612a85a013b2954b52a678956f1334a4d8d1298b 100644 (file)
@@ -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)
index 662d77602651e92738a013c05d8c5fb1dcfcba1c..a5c3bdd4bc7688d8a8725f01e001bfaee8c95fe2 100644 (file)
@@ -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
index 47f9b32ce740c479c0618b4390b55d007de2a618..592b1e340a08ff9461c3ee48df194e1b0e8966a6 100644 (file)
@@ -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
index fb172cd2df745d20e063bda0ec8aa8193c1505a1..1f5bb8e18747cce5f5c1f6784518de715415b886 100644 (file)
@@ -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;
+  p     = 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");
       }
index 702c0fb9dfdbdc38f1fe42bd53602c2b32a8d3bc..af690adb0a4622ba97da3c7a0866601d8bd36ab1 100644 (file)
@@ -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);
 
  /*
index 0a4908a77e03da8ffac70d70b0d569627d8e221d..fb42f791f244fead9f5639191d9526b0a5da4424 100644 (file)
@@ -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 (file)
index 0000000..3a82a52
--- /dev/null
@@ -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$".
+#
index fbc5a467f57f88b161da2e235562eaf9829671d8..43b83999639d1760fdca3276ddaaa398f96661fe 100644 (file)
@@ -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;
     }
index 990e54982fe8d054edfbf7faaeb551ae3cc8af15..d6d8ae1b968e8771b30dc00e6c4fc4688cf3a596 100644 (file)
@@ -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;
index 7d9196b98466a5f5231dc8653c684528a91035a0..4149559489c3ef45922460ae8fdf40f326ddbdb4 100644 (file)
@@ -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);
 
index 2c2d73e56ccef8ceb431f9ff930c0fc9f5e0a9c6..08af5997a0694aa71dbd1a0fea598a231a3e8960 100644 (file)
@@ -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...
index c38352a6b4d599019750ff58c75225b02354e2e7..05fa23b38110c184446c9e3c11c0b42551e1e180 100644 (file)
@@ -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)
     {
index 5ce0009161156a5e887818a0fad5a381f9a6780f..adc5581fe131c52d17d1cf1480251325a327084f 100644 (file)
@@ -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 \
index 4d7facf4e1535e065dd9a275c9d1a3d36e10c6eb..f9054d222567701dbff0d2d896532da5dc5baa68 100644 (file)
@@ -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... */
   {
index d6a8bbba9dcf4ab357d52a443aa4a8fc6f3591e5..6e1677f8867a2bd7525784062aa5142e5940e5c0 100644 (file)
@@ -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 $".
  */
index 1406c3420b6671000268385ec7290e67f534512c..bd738bf00e6727e86b2b2b760869adf26d8516ed 100644 (file)
@@ -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.
  *
  *   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.
 
 #ifdef __APPLE__
 #  include <SystemConfiguration/SystemConfiguration.h>
-#  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 $".
  */
index b788b72393e7b32461b44d399f901ec10dd0cde5..21e6fabb8931834cfd9fdd18980d1984047f05ff 100644 (file)
@@ -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);
 }
index 00f74c316c07f0d2ca8692de3335bfbd40d87a1c..93985e0e9462ac62260bd73a0be165b643173b0e 100644 (file)
@@ -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);
 
index 35c382576298ad2376a28952de96b02af4b98094..6e9581823fc2483626e7df2940acde3fdb4c8013 100644 (file)
@@ -15,6 +15,7 @@ _cupsMD5Init
 _cupsMessageFree\r
 _cupsMessageLoad\r
 _cupsMessageLookup\r
+_cupsNextDelay\r
 _cupsSetError\r
 _cupsSetLocale\r
 _cupsStrAlloc\r
index b86fbe759b20eae8337d524e538b63f72db978dd..80b347a75e0e71a5ae08d7bc154ff72c6d47d198 100644 (file)
@@ -13,6 +13,7 @@ _cupsMD5Init
 _cupsMessageFree
 _cupsMessageLoad
 _cupsMessageLookup
+_cupsNextDelay
 _cupsSetError
 _cupsSetLocale
 _cupsSNMPClose
index 4dbd7555c8438bf71f45e962ce51fa9bb55cf08d..763b5310d25d07c070fb998a89f79e67912dffb8 100644 (file)
@@ -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 (file)
index 0000000..e0b5d65
--- /dev/null
@@ -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 <math.h>
+
+
+/*
+ * 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$".
+ */
index d44c1ca0403b10f2821eb9b71ae60ede3b693d4d..e907c46d7248d6ea4875e15cad80a971cedcf2af 100644 (file)
@@ -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);
 
 
 /*
index f1d2362515d993302af2c34df2725cf00b88a08d..89ad18b6b16f8b8dc3ddb42398e6f92da12d802e 100644 (file)
@@ -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...
index 1b00ae4552459db3ccccecf4ae88a3d96c81bd1c..7d12fade239a51a06e6061628502ca3a65be0b42 100644 (file)
@@ -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 (file)
index 52bac4d..0000000
+++ /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 <math.h>
-
-
-/*
- * '_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$".
- */
index 8e00ca0317ee8e1cbf5d1320d9078046239cd338..306bf6d85065801bee4d1035b6dfddba6d649897 100644 (file)
@@ -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 (file)
index 777ee07..0000000
+++ /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 <math.h>
-
-
-/*
- * 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$".
- */
index cf8426fb6e8b57184369abe3072e7132766177dc..641a51ce09f9a1101d06cf9d4e838ebaf8d141d9 100644 (file)
@@ -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));
index 17abb2b3f4704f64925b073a42a526a5f1feb737..460eae3519322fbb4974ba56ac792827b74ff706 100644 (file)
@@ -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);
 
index c52cd51cb65c93747f5401d9d562753e560ce1b0..29cc01a7611e03667d66578cca0d429dab7bd158 100644 (file)
@@ -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 */
index 47cfa01e926fef21a1cc508adafed5346bd46868..d788f9acef95a90332c305cac6a1dc6002607eeb 100644 (file)
@@ -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);
index f15e11e4c2da9b159f871d1fa5d04b231abac4fa..9cf2faadc278c2a08f9e14523f6fe780720296b7 100644 (file)
@@ -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);
 }
index 47a49072b12d2be58f7ac810c58f963e30b341e4..f858610a3b690f1fe5dba97f0bff6311241e9bd3 100644 (file)
@@ -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...
       */
index d864634a9c3c1c05a8940b2b65bf6667272ce619..a57dd1874ee42e234b40187691d0b6cca699ccac 100644 (file)
@@ -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);
 }
 
 
index 48085c4fbca6e701331ad6c02ae5927ccc4e5a2b..a8188d11f26e2c5096b2c4ae2aa2184eee84a7a6 100644 (file)
@@ -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.
  */
  */
 
 #include "image-private.h"
+#ifdef WIN32
+#  include <io.h>
+#else
+#  include <unistd.h>
+#  include <fcntl.h>
+#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);
 }
index 62a6aaffc5538d380473d3f369e0aeae5c7cabdb..542a929da6eb9fdc022ca248033a9e35073f544d 100644 (file)
@@ -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";
index 7a4426b750a6992d41f86efe77f5271d2f1495ba..9410cd7876a9013537b26b7e4fd88c8aa745fc8d 100644 (file)
@@ -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"
index 191e17fc253a9c065f3f52aa924297a7dd237a76..16c83b8cdf54a76cc5a18cbdfd65aa7fc0b19e4f 100644 (file)
@@ -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;
     }
index 26b80870c04832c15d60745685c330ae630460f7..193c03f8f53c281b616f8b24fd87d19eddd7c652 100644 (file)
@@ -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;
index 86a3e5a074ae3ac75528629048004037ce275099..052725cce11b2b03361c42a64bf7a1d610b08e6d 100644 (file)
@@ -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),
index 4b9d87855e5037208bf030023a933e3f09aeac76..5ddf5b3cf13ebf23d14dfc86e270d30fbfa6c1fd 100644 (file)
@@ -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++ = '?';
index bf1041287f09253c685100e10d209aa8e8b9c8f1..99182c6748f1339cd8d60d476b97137f26dbe882 100644 (file)
@@ -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);
index fd1c6b6b55c1fdf3a6ff14fb1f8cbff468a82108..9e3c80bc7080e726d78e366a68076469616ae799 100644 (file)
@@ -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,
index efacdd318b2c9231f289f9bca8636228ac3ecc65..d511e80f47f9913471b349e3c1dc5f5c931ee649 100644 (file)
@@ -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;
 
index 9d99264f5fd05fc05d1e560d6fc5b2de38573652..2bed2e834ecf4676a7ba7a9d45ae5e3af29fff5c 100644 (file)
@@ -1800,7 +1800,6 @@ process_children(void)
            {
              strlcpy(job->printer->state_message, message,
                       sizeof(job->printer->state_message));
-             cupsdAddPrinterHistory(job->printer);
            }
 
            if (!job->attrs)
index b04b75646ab055ce9f6a00e3d99d16c9d5d9f225..044902e2a6193097edc680af174565b46f66a013 100644 (file)
@@ -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.
  *   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);
   }
 }
 
index dcbf302f4606d3924feab30467a95610d3c304f6..9dd9ded680cdb14da6dca8d31ed8d0f856017b21 100644 (file)
@@ -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);
index 7179209a4e03c86b94461e70dfadaf1e62f46d65..084d3954430b36d435a9350a8ef8b97697c67c1b 100755 (executable)
@@ -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 "<P>PASS: $count debug2 messages.</P>" >>$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 "<P>PASS: page_log formatted correctly.</P>" >>$strfile
-       else
-               echo "FAIL: page_log formatted incorrectly."
-               echo "<P>FAIL: page_log formatted incorrectly - no page size information.</P>" >>$strfile
-               fail=`expr $fail + 1`
-       fi
-fi
-
 # Log files...
 echo "<H2>access_log</H2>" >>$strfile
 echo "<PRE>" >>$strfile