]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from CUPS 1.6svn-r10390.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Fri, 30 Mar 2012 05:59:14 +0000 (05:59 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Fri, 30 Mar 2012 05:59:14 +0000 (05:59 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@3755 a1ca3aef-8c08-0410-bb20-df032aa958be

91 files changed:
CHANGES-1.5.txt
CHANGES-IPPTOOL.txt
CHANGES.txt
Makedefs.in
backend/backend-private.h
backend/dnssd.c
backend/ipp.c
backend/network.c
backend/runloop.c
backend/snmp-supplies.c
backend/testbackend.c
berkeley/lpc.c
cgi-bin/admin.c
cgi-bin/help.c
cgi-bin/var.c
config-scripts/cups-common.m4
config-scripts/cups-defaults.m4
config-scripts/cups-ssl.m4
config-scripts/cups-ssl.m4.orig [new file with mode: 0644]
config.h.in
cups/api-httpipp.shtml
cups/cups-private.h
cups/cups.h
cups/dest-job.c
cups/dest-options.c
cups/dest.c
cups/http-addrlist.c
cups/http-support.c
cups/http.c
cups/ipp-private.h
cups/ipp-support.c
cups/ipp.c
cups/ipp.h
cups/language.c
cups/ppd-cache.c
cups/ppd.c
cups/ppd.h
cups/pwg-media.c
cups/request.c
cups/sidechannel.c
cups/snmp-private.h
cups/testconflicts.c
cups/util.c
doc/help/api-httpipp.html
doc/help/api-ppdc.html
doc/help/man-ipptoolfile.html
doc/help/ref-cupsd-conf.html.in
doc/help/spec-ppd.html
doc/index.html.in
filter/commandtops.c
filter/spec-ppd.shtml
install-sh
locale/cups.pot
locale/cups.strings
locale/po2strings.c
man/ipptoolfile.man
notifier/rss.c
ppdc/ppdc-file.cxx
ppdc/ppdc-source.cxx
ppdc/ppdc.h
scheduler/Makefile
scheduler/auth.c
scheduler/client.c
scheduler/client.h
scheduler/client.h.orig [new file with mode: 0644]
scheduler/conf.c
scheduler/cups-driverd.cxx
scheduler/cups-lpd.c
scheduler/cupsd.h
scheduler/job.c
scheduler/job.h
scheduler/main.c
scheduler/network.c
scheduler/printers.c
scheduler/tls-darwin.c [new file with mode: 0644]
scheduler/tls-gnutls.c [new file with mode: 0644]
scheduler/tls-openssl.c [new file with mode: 0644]
scheduler/tls.c [new file with mode: 0644]
systemv/cupstestppd.c
templates/admin.tmpl
templates/help-header.tmpl
templates/jobs.tmpl
templates/trailer.tmpl
test/Makefile
test/ipp-1.1.test
test/ipp-2.0.test
test/ipptool.c
test/run-stp-tests.sh
vcnet/config.h
vcnet/cups.sln
vcnet/libcups2-installer.vdproj [new file with mode: 0644]

index 3250d60aaa91a31a7da2888ee28ad6d2aa3bb8df..344c5eda2b0f38cd3dc3dd89b087ec7d351fa8e2 100644 (file)
@@ -3,6 +3,18 @@ CHANGES-1.5.txt
 
 CHANGES IN CUPS V1.5.3
 
+       - Fixed compile problem with old versions of OpenSSL (STR #4036)
+       - The network backends did not check SNMP supply levels regularly
+         (STR #4040)
+       - The online help always included the "help on help" text (STR #4042)
+       - Fixed a SSL handshake issue on OS X (STR #4045)
+       - The scheduler could crash if a PPD file contained an invalid paper
+         size (STR #4049)
+       - The CUPS polling daemon did not reinitialize its connection to the
+         remote server on errors in all cases (STR #4031)
+       - PostScript auto-configuration was slow and unreliable with some
+         printers (STR #4028)
+       - Missing localizations caused empty output (STR #4033)
        - The cups-driverd program could temporarily "forget" a PPD file if it
          was updated in place.
        - The dnssd backend now prefers IPPS over IPP.
index 8d44270e98c6eca5e96db2b10175efa289ac1bd8..d16bbd5dde6a27a541728186fa11a3cbd0355429 100644 (file)
@@ -1,10 +1,21 @@
-CHANGES-IPPTOOL.txt - 2012-02-06
+CHANGES-IPPTOOL.txt - 2012-02-28
 --------------------------------
 
 This file provides a list of changes to the ipptool binary distribution posted
 on cups.org.
 
 
+2012-02-28
+
+       - Changed behavior of WITH-VALUES "/regex/" to not require all values to
+         match.
+       - Added WITH-ALL-VALUES directive for EXPECT predicates that require all
+         values to match.
+       - Updated test files to use WITH-ALL-VALUES where necessary.
+       - Updated test files to use new ABNF for media names from PWG Media
+         Names 2.0.
+
+
 2012-02-06
 
        - Fixed the packaging of ipptool on Windows (removed unnecessary DLLs)
index 0528f3c3d755c47c38c95abf5ecf12dd88533519..658c462ffb2e60a39c190ccf156cd6ec36073dc6 100644 (file)
@@ -1,9 +1,21 @@
-CHANGES.txt - 1.6b1 - 2012-02-15
+CHANGES.txt - 1.6b1 - 2012-03-16
 --------------------------------
 
 CHANGES IN CUPS V1.6b1
 
        - Documentation updates (STR #3927, STR #3980, STR #4010)
+       - The PreserveJobFiles and PreserveJobHistory directives now support
+         specification of a time interval (STR #3143)
+       - PPD files can now be archived in (gzip'd) tar files to further reduce
+         the disk space used by PPD files (STR #3772)
+       - The network backends now deal with printers that report their levels
+         in percent but do not specify a maximum capacity of 100 (STR #3551)
+       - The network backends now report full/almost-full waste bins in
+         printers along with end-of-life for cleaning pads (STR #4017)
+       - Added a configure option to set the permissions of the installed
+         cupsd (STR #3459)
+       - Added a new WITH-ALL-VALUES directive to ipptool EXPECT predicates
+         (STR #3949)
        - CUPS now supports a User directive in client.conf and the CUPS_USER
          environment variable for overriding the default username (STR #3114)
        - Now set the PJL USERNAME variable as needed (STR #3100)
index 5db6b0ab72e6c685a767bde768ab5d7f49fd1bab..9bf7afa85d4f838896c8d7d198a4cd69dfaba521 100644 (file)
@@ -42,6 +42,7 @@ SHELL         =       /bin/sh
 
 INSTALL_BIN    =       $(LIBTOOL) $(INSTALL) -c -m 555 @INSTALL_STRIP@
 INSTALL_CONFIG =       $(INSTALL) -c -m @CUPS_CONFIG_FILE_PERM@
+INSTALL_COMPDATA =     $(INSTALL) -c -m 444 @INSTALL_GZIP@
 INSTALL_DATA   =       $(INSTALL) -c -m 444
 INSTALL_DIR    =       $(INSTALL) -d
 INSTALL_LIB    =       $(LIBTOOL) $(INSTALL) -c -m 555 @INSTALL_STRIP@
@@ -62,6 +63,7 @@ CUPS_PRIMARY_SYSTEM_GROUP =   @CUPS_PRIMARY_SYSTEM_GROUP@
 #
 
 CUPS_CONFIG_FILE_PERM = @CUPS_CONFIG_FILE_PERM@
+CUPS_CUPSD_FILE_PERM = @CUPS_CUPSD_FILE_PERM@
 CUPS_LOG_FILE_PERM = @CUPS_LOG_FILE_PERM@
 
 #
index e46973ad090a2b6be7ef3fe0e8921c2cd08d15e1..980b3e518345a3ccb4695b34b9a872e47f6bd5a4 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Backend support definitions for CUPS.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -259,6 +259,20 @@ extern "C" {
 #define CUPS_TC_inserts                                33
 #define CUPS_TC_covers                         34
 
+#define CUPS_TC_tenThousandthsOfInches         3
+#define CUPS_TC_micrometers                    4
+#define CUPS_TC_impressions                    7
+#define CUPS_TC_sheets                         8
+#define CUPS_TC_hours                          11
+#define CUPS_TC_thousandthsOfOunces            12
+#define CUPS_TC_tenthsOfGrams                  13
+#define CUPS_TC_hundrethsOfFluidOunces         14
+#define CUPS_TC_tenthsOfMilliliters            15
+#define CUPS_TC_feet                           16
+#define CUPS_TC_meters                         17
+#define CUPS_TC_items                          18
+#define CUPS_TC_percent                                19
+
 /* These come from RFC 3808 to define character sets we support */
 /* Also see http://www.iana.org/assignments/character-sets */
 #define CUPS_TC_csASCII                                3
index 12571b15c4d1205ea413c1e11ddfd725fa422351..35c44e30df7e9bae8257f515db7f37e5b17b1f2d 100644 (file)
@@ -84,7 +84,8 @@ static void           browse_callback(DNSServiceRef sdRef,
                                        DNSServiceErrorType errorCode,
                                        const char *serviceName,
                                        const char *regtype,
-                                       const char *replyDomain, void *context);
+                                       const char *replyDomain, void *context)
+                                       __attribute__((nonnull(1,5,6,7,8)));
 static void            browse_local_callback(DNSServiceRef sdRef,
                                              DNSServiceFlags flags,
                                              uint32_t interfaceIndex,
@@ -92,13 +93,15 @@ static void         browse_local_callback(DNSServiceRef sdRef,
                                              const char *serviceName,
                                              const char *regtype,
                                              const char *replyDomain,
-                                             void *context);
+                                             void *context)
+                                             __attribute__((nonnull(1,5,6,7,8)));
 static int             compare_devices(cups_device_t *a, cups_device_t *b);
 static void            exec_backend(char **argv);
 static cups_device_t   *get_device(cups_array_t *devices,
                                    const char *serviceName,
                                    const char *regtype,
-                                   const char *replyDomain);
+                                   const char *replyDomain)
+                                   __attribute__((nonnull(1,2,3,4)));
 static void            query_callback(DNSServiceRef sdRef,
                                       DNSServiceFlags flags,
                                       uint32_t interfaceIndex,
@@ -106,9 +109,11 @@ static void                query_callback(DNSServiceRef sdRef,
                                       const char *fullName, uint16_t rrtype,
                                       uint16_t rrclass, uint16_t rdlen,
                                       const void *rdata, uint32_t ttl,
-                                      void *context);
+                                      void *context)
+                                      __attribute__((nonnull(1,5,9,11)));
 static void            sigterm_handler(int sig);
-static void            unquote(char *dst, const char *src, size_t dstsize);
+static void            unquote(char *dst, const char *src, size_t dstsize)
+                           __attribute__((nonnull(1,2)));
 
 
 /*
index 20391f8a2bd9327734dfa45d0a928ef13c415ef3..826d5b8a84b976b034a7cf8e3f52f5d31f3c85e5 100644 (file)
 #  define kPMPrintUIToolAgent  "com.apple.printuitool.agent"
 #  define kPMStartJob          100
 #  define kPMWaitForJob                101
+#  ifdef HAVE_XPC_PRIVATE_H
+#    include <xpc/private.h>
+#  else
 extern void    xpc_connection_set_target_uid(xpc_connection_t connection,
                                              uid_t uid);
+#  endif /* HAVE_XPC_PRIVATE_H */
 #endif /* HAVE_GSSAPI && HAVE_XPC */
 
 
@@ -1139,12 +1143,7 @@ main(int  argc,                          /* I - Number of command-line args */
   copies = atoi(argv[4]);
 
   if (copies_sup || argc < 7)
-  {
     copies_remaining = 1;
-
-    if (argc < 7 && !_cups_strncasecmp(final_content_type, "image/", 6))
-      copies = 1;
-  }
   else
     copies_remaining = copies;
 
@@ -1179,7 +1178,8 @@ main(int  argc,                           /* I - Number of command-line args */
   if (format_sup != NULL)
   {
     for (i = 0; i < format_sup->num_values; i ++)
-      if (!_cups_strcasecmp(final_content_type, format_sup->values[i].string.text))
+      if (!_cups_strcasecmp(final_content_type,
+                            format_sup->values[i].string.text))
       {
         document_format = final_content_type;
        break;
@@ -1189,7 +1189,7 @@ main(int  argc,                           /* I - Number of command-line args */
     {
       for (i = 0; i < format_sup->num_values; i ++)
        if (!_cups_strcasecmp("application/octet-stream",
-                       format_sup->values[i].string.text))
+                             format_sup->values[i].string.text))
        {
          document_format = "application/octet-stream";
          break;
@@ -1197,6 +1197,9 @@ main(int  argc,                           /* I - Number of command-line args */
     }
   }
 
+  fprintf(stderr, "DEBUG: final_content_type=\"%s\", document_format=\"%s\"\n",
+          final_content_type, document_format ? document_format : "(null)");
+
  /*
   * If the printer does not support HTTP/1.1 (which IPP requires), copy stdin
   * to a temporary file so that we can do a HTTP/1.0 submission...
@@ -1552,8 +1555,9 @@ main(int  argc,                           /* I - Number of command-line args */
         if ((i + 1) >= num_files)
          ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
 
-        ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
-                    "document-format", NULL, document_format);
+       if (document_format)
+         ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+                      "document-format", NULL, document_format);
 
        fprintf(stderr, "DEBUG: Sending file %d using chunking...\n", i + 1);
        http_status = cupsSendRequest(http, request, resource, 0);
@@ -1578,10 +1582,11 @@ main(int  argc,                         /* I - Number of command-line args */
 
        if (fd >= 0)
        {
-         while (!job_canceled &&
+         while (!job_canceled && http_status == HTTP_CONTINUE &&
                 (bytes = read(fd, buffer, sizeof(buffer))) > 0)
          {
-           if (cupsWriteRequestData(http, buffer, bytes) != HTTP_CONTINUE)
+           if ((http_status = cupsWriteRequestData(http, buffer, bytes))
+                   != HTTP_CONTINUE)
              break;
            else
            {
@@ -2446,9 +2451,46 @@ new_request(
                       NULL, "two-sided-short-edge");
       }
 
-      if (doc_handling_sup &&
-          (!format || _cups_strncasecmp(format, "image/", 6)) &&
-         (keyword = cupsGetOption("collate", num_options, options)) != NULL)
+      if ((keyword = cupsGetOption("multiple-document-handling",
+                                  num_options, options)) != NULL)
+      {
+        if (strstr(keyword, "uncollated"))
+          keyword = "false";
+        else
+          keyword = "true";
+      }
+      else if ((keyword = cupsGetOption("collate", num_options,
+                                        options)) == NULL)
+        keyword = "true";
+
+      if (format)
+      {
+        if (!_cups_strcasecmp(format, "image/gif") ||
+           !_cups_strcasecmp(format, "image/jp2") ||
+           !_cups_strcasecmp(format, "image/jpeg") ||
+           !_cups_strcasecmp(format, "image/png") ||
+           !_cups_strcasecmp(format, "image/tiff") ||
+           !_cups_strncasecmp(format, "image/x-", 8))
+       {
+        /*
+         * Collation makes no sense for single page image formats...
+         */
+
+         keyword = "false";
+       }
+       else if (!_cups_strncasecmp(format, "image/", 6) ||
+                !_cups_strcasecmp(format, "application/vnd.cups-raster"))
+       {
+        /*
+         * Multi-page image formats will have copies applied by the upstream
+         * filters...
+         */
+
+         copies = 1;
+       }
+      }
+
+      if (doc_handling_sup)
       {
         if (!_cups_strcasecmp(keyword, "true"))
          collate_str = "separate-documents-collated-copies";
@@ -2513,7 +2555,7 @@ new_request(
       cupsEncodeOptions(request, num_options, options);
     }
 
-    if (copies > 1 && copies <= pc->max_copies)
+    if (copies > 1 && (!pc || copies <= pc->max_copies))
       ippAddInteger(request, IPP_TAG_JOB, IPP_TAG_INTEGER, "copies", copies);
   }
 
index 6dbdca03bd832cb6a292473f52cb06f9e8f61850..f011f2cf2afb47ebc3c3c1b99b9a8d744e6c15b8 100644 (file)
@@ -92,7 +92,7 @@ backendNetworkSideCB(
          status = CUPS_SC_STATUS_NOT_IMPLEMENTED;
        else if (backendDrainOutput(print_fd, device_fd))
          status = CUPS_SC_STATUS_IO_ERROR;
-       else 
+       else
           status = CUPS_SC_STATUS_OK;
 
        datalen = 0;
@@ -119,8 +119,35 @@ backendNetworkSideCB(
 
         if (snmp_fd >= 0)
        {
+         char          *dataptr;       /* Pointer into data */
          cups_snmp_t   packet;         /* Packet from printer */
+          const char   *snmp_value;    /* CUPS_SNMP_VALUE env var */
 
+          if ((snmp_value = getenv("CUPS_SNMP_VALUE")) != NULL)
+          {
+            const char *snmp_count;    /* CUPS_SNMP_COUNT env var */
+            int                count;          /* Repetition count */
+
+            if ((snmp_count = getenv("CUPS_SNMP_COUNT")) != NULL)
+            {
+              if ((count = atoi(snmp_count)) <= 0)
+                count = 1;
+            }
+            else
+              count = 1;
+
+           for (dataptr = data + strlen(data) + 1;
+                count > 0 && dataptr < (data + sizeof(data) - 1);
+                count --, dataptr += strlen(dataptr))
+             strlcpy(dataptr, snmp_value, sizeof(data) - (dataptr - data));
+
+           fprintf(stderr, "DEBUG: Returning %s %s\n", data,
+                   data + strlen(data) + 1);
+
+           status  = CUPS_SC_STATUS_OK;
+           datalen = dataptr - data;
+           break;
+          }
 
           if (!_cupsSNMPStringToOID(data, packet.object_name, CUPS_SNMP_MAX_OID))
          {
@@ -141,7 +168,6 @@ backendNetworkSideCB(
           {
            if (_cupsSNMPRead(snmp_fd, &packet, 1.0))
            {
-             char      *dataptr;       /* Pointer into data */
              int       i;              /* Looping var */
 
 
@@ -172,7 +198,7 @@ backendNetworkSideCB(
                case CUPS_ASN1_OCTET_STRING :
                    if (packet.object_value.string.num_bytes < 0)
                      i = 0;
-                   else if (packet.object_value.string.num_bytes < 
+                   else if (packet.object_value.string.num_bytes <
                             (sizeof(data) - (dataptr - data)))
                      i = packet.object_value.string.num_bytes;
                    else
index 227883bfa27969ceeadc2afa8a6b2e185ee21466..777b0480199e486e3afd76f656cfc4f15fd95993 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Common run loop APIs for CUPS backends.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 2006-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -434,9 +434,11 @@ backendWaitLoop(
     int          use_bc,               /* I - Use back-channel? */
     _cups_sccb_t side_cb)              /* I - Side-channel callback */
 {
-  fd_set       input;                  /* Input set for reading */
-  time_t       curtime,                /* Current time */
-               snmp_update = 0;        /* Last SNMP status update */
+  int                  nfds;           /* Number of file descriptors */
+  fd_set               input;          /* Input set for reading */
+  time_t               curtime = 0,    /* Current time */
+                       snmp_update = 0;/* Last SNMP status update */
+  struct timeval       timeout;        /* Timeout for select() */
 
 
   fprintf(stderr, "DEBUG: backendWaitLoop(snmp_fd=%d, addr=%p, side_cb=%p)\n",
@@ -446,6 +448,9 @@ backendWaitLoop(
   * Now loop until we receive data from stdin...
   */
 
+  if (snmp_fd >= 0)
+    snmp_update = time(NULL) + 5;
+
   for (;;)
   {
    /*
@@ -457,7 +462,18 @@ backendWaitLoop(
     if (side_cb)
       FD_SET(CUPS_SC_FD, &input);
 
-    if (select(CUPS_SC_FD + 1, &input, NULL, NULL, NULL) < 0)
+    if (snmp_fd >= 0)
+    {
+      curtime         = time(NULL);
+      timeout.tv_sec  = curtime >= snmp_update ? 0 : snmp_update - curtime;
+      timeout.tv_usec = 0;
+
+      nfds = select(CUPS_SC_FD + 1, &input, NULL, NULL, &timeout);
+    }
+    else
+      nfds = select(CUPS_SC_FD + 1, &input, NULL, NULL, NULL);
+
+    if (nfds < 0)
     {
      /*
       * Pause printing to clear any pending errors...
@@ -501,10 +517,10 @@ backendWaitLoop(
     * Do SNMP updates periodically...
     */
 
-    if (snmp_fd >= 0 && time(&curtime) >= snmp_update)
+    if (snmp_fd >= 0 && curtime >= snmp_update)
     {
       if (backendSNMPSupplies(snmp_fd, addr, NULL, NULL))
-        snmp_update = INT_MAX;
+        snmp_fd = -1;
       else
         snmp_update = curtime + 5;
     }
index 0eaba065d0c662e7b35648ec309b923f8e8f170a..75dc9dc7a1b001ddec0e2aa8d68849c42790a3e4 100644 (file)
 #define CUPS_MAX_SUPPLIES      32      /* Maximum number of supplies for a printer */
 #define CUPS_SUPPLY_TIMEOUT    2.0     /* Timeout for SNMP lookups */
 
-#define CUPS_DEVELOPER_LOW             1
-#define CUPS_DEVELOPER_EMPTY           2
-#define CUPS_MARKER_SUPPLY_LOW         4
-#define CUPS_MARKER_SUPPLY_EMPTY       8
-#define CUPS_OPC_NEAR_EOL              16
-#define CUPS_OPC_LIFE_OVER             32
-#define CUPS_TONER_LOW                 64
-#define CUPS_TONER_EMPTY               128
+#define CUPS_DEVELOPER_LOW     0x0001
+#define CUPS_DEVELOPER_EMPTY   0x0002
+#define CUPS_MARKER_SUPPLY_LOW 0x0004
+#define CUPS_MARKER_SUPPLY_EMPTY 0x0008
+#define CUPS_OPC_NEAR_EOL      0x0010
+#define CUPS_OPC_LIFE_OVER     0x0020
+#define CUPS_TONER_LOW         0x0040
+#define CUPS_TONER_EMPTY       0x0080
+#define CUPS_WASTE_ALMOST_FULL 0x0100
+#define CUPS_WASTE_FULL                0x0200
+#define CUPS_CLEANER_NEAR_EOL  0x0400  /* Proposed JPS3 */
+#define CUPS_CLEANER_LIFE_OVER 0x0800  /* Proposed JPS3 */
 
 
 /*
@@ -146,6 +150,13 @@ static const int   prtMarkerSuppliesType[] =
                        (sizeof(prtMarkerSuppliesType) /
                         sizeof(prtMarkerSuppliesType[0]));
                                        /* Offset to supply index */
+static const int       prtMarkerSuppliesSupplyUnit[] =
+                       { CUPS_OID_prtMarkerSuppliesSupplyUnit, -1 },
+                                       /* Units OID */
+                       prtMarkerSuppliesSupplyUnitOffset =
+                       (sizeof(prtMarkerSuppliesSupplyUnit) /
+                        sizeof(prtMarkerSuppliesSupplyUnit[0]));
+                                       /* Offset to supply index */
 
 static const backend_state_t const printer_states[] =
                        {
@@ -173,7 +184,11 @@ static const backend_state_t const supply_states[] =
                          { CUPS_OPC_NEAR_EOL, "opc-near-eol-report" },
                          { CUPS_OPC_LIFE_OVER, "opc-life-over-warning" },
                          { CUPS_TONER_LOW, "toner-low-report" },
-                         { CUPS_TONER_EMPTY, "toner-empty-warning" }
+                         { CUPS_TONER_EMPTY, "toner-empty-warning" },
+                         { CUPS_WASTE_ALMOST_FULL, "waste-receptacle-almost-full-report" },
+                         { CUPS_WASTE_FULL, "waste-receptacle-full-warning" },
+                         { CUPS_CLEANER_NEAR_EOL, "cleaner-life-almost-over-report" },
+                         { CUPS_CLEANER_LIFE_OVER, "cleaner-life-over-warning" },
                        };
 
 
@@ -245,9 +260,6 @@ backendSNMPSupplies(
               else
                 new_supply_state |= CUPS_TONER_LOW;
               break;
-          case CUPS_TC_wasteToner :
-          case CUPS_TC_wasteInk :
-              break;
           case CUPS_TC_ink :
           case CUPS_TC_inkCartridge :
           case CUPS_TC_inkRibbon :
@@ -273,6 +285,23 @@ backendSNMPSupplies(
               else
                 new_supply_state |= CUPS_OPC_NEAR_EOL;
               break;
+          case CUPS_TC_wasteInk :
+          case CUPS_TC_wastePaper :
+          case CUPS_TC_wasteToner :
+          case CUPS_TC_wasteWater :
+          case CUPS_TC_wasteWax :
+              if (percent <= 1)
+                new_supply_state |= CUPS_WASTE_FULL;
+              else
+                new_supply_state |= CUPS_WASTE_ALMOST_FULL;
+              break;
+          case CUPS_TC_cleanerUnit :
+          case CUPS_TC_fuserCleaningPad :
+              if (percent <= 1)
+                new_supply_state |= CUPS_CLEANER_LIFE_OVER;
+              else
+                new_supply_state |= CUPS_CLEANER_NEAR_EOL;
+              break;
         }
       }
 
@@ -920,7 +949,9 @@ backend_walk_cb(cups_snmp_t *packet,        /* I - SNMP packet */
     if (i > num_supplies)
       num_supplies = i;
 
-    supplies[i - 1].max_capacity = packet->object_value.integer;
+    if (supplies[i - 1].max_capacity == 0 &&
+        packet->object_value.integer > 0)
+      supplies[i - 1].max_capacity = packet->object_value.integer;
   }
   else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesType))
   {
@@ -941,6 +972,26 @@ backend_walk_cb(cups_snmp_t *packet,       /* I - SNMP packet */
 
     supplies[i - 1].type = packet->object_value.integer;
   }
+  else if (_cupsSNMPIsOIDPrefixed(packet, prtMarkerSuppliesSupplyUnit))
+  {
+   /*
+    * Get units for capacity...
+    */
+
+    i = packet->object_name[prtMarkerSuppliesSupplyUnitOffset];
+    if (i < 1 || i > CUPS_MAX_SUPPLIES ||
+        packet->object_type != CUPS_ASN1_INTEGER)
+      return;
+
+    fprintf(stderr, "DEBUG2: prtMarkerSuppliesSupplyUnit.1.%d = %d\n", i,
+            packet->object_value.integer);
+
+    if (i > num_supplies)
+      num_supplies = i;
+
+    if (packet->object_value.integer == CUPS_TC_percent)
+      supplies[i - 1].max_capacity = 100;
+  }
 }
 
 
index a3a7d97e6d239e6d1f570d0a79f98fc0b8257923..454533f5dd36f334a98ad24e50d31c73850ab39b 100644 (file)
@@ -573,13 +573,13 @@ main(int  argc,                           /* I - Number of command-line args */
 
       length   = sizeof(buffer);
       scstatus = cupsSideChannelSNMPGet(oid, buffer, &length, 5.0);
-      printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %s\n", oid,
-            statuses[scstatus], buffer);
+      printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %d bytes (%s)\n", oid,
+            statuses[scstatus], (int)length, buffer);
 
       length   = sizeof(buffer);
       scstatus = cupsSideChannelSNMPGet(oid, buffer, &length, 5.0);
-      printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %s\n", oid,
-            statuses[scstatus], buffer);
+      printf("CUPS_SC_CMD_SNMP_GET %s returned %s, %d bytes (%s)\n", oid,
+            statuses[scstatus], (int)length, buffer);
     }
 
     length   = 0;
@@ -638,13 +638,13 @@ sigterm_handler(int sig)          /* I - Signal */
 static void
 usage(void)
 {
-  puts("Usage: testbackend [-cancel] [-d] [-ps | -pcl] [-s [-oid OID] "
+  puts("Usage: testbackend [-cancel] [-d] [-ps | -pcl] [-s [-get OID] "
        "[-walk OID]] [-t] device-uri job-id user title copies options [file]");
   puts("");
   puts("Options:");
   puts("  -cancel     Simulate a canceled print job after 2 seconds.");
   puts("  -d          Show log messages from backend.");
-  puts("  -oid OID    Lookup the specified SNMP OID.");
+  puts("  -get OID    Lookup the specified SNMP OID.");
   puts("              (.1.3.6.1.2.1.43.10.2.1.4.1.1 is a good one for printers)");
   puts("  -pcl        Send PCL+PJL query and test page to backend.");
   puts("  -ps         Send PostScript query and test page to backend.");
@@ -667,7 +667,7 @@ walk_cb(const char *oid,            /* I - OID */
        int        datalen,             /* I - Length of data */
        void       *context)            /* I - Context (unused) */
 {
-  printf("CUPS_SC_CMD_SNMP_WALK %s=%s (%d bytes)\n", oid, data, datalen);
+  printf("CUPS_SC_CMD_SNMP_WALK %s, %d bytes (%s)\n", oid, datalen, data);
 }
 
 
index 36d08bd6820fb63a5a8f723c069742278a75be5d..e1003b1b1c1a3882f805598ec1047cc09add86b9 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   "lpc" command for CUPS.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -364,7 +364,8 @@ show_status(http_t     *http,               /* I - HTTP connection to server */
 
          for (ptr = printer;
               *ptr != '\0' && *dptr != '\0' && *ptr == *dptr;
-              ptr ++, dptr ++);
+              ptr ++, dptr ++)
+           /* do nothing */;
 
           if (*ptr == '\0' && (*dptr == '\0' || *dptr == ',' ||
                               isspace(*dptr & 255)))
index 64a29bffd3a8e5f5d4be55f9ff31fd4231495ff7..dcfc2dc47d98d90913d2cde1f29183cf030a6060 100644 (file)
@@ -1557,6 +1557,8 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     int                        advanced,       /* Advanced settings shown? */
                        changed;        /* Have settings changed? */
     const char         *debug_logging, /* DEBUG_LOGGING value */
+                       *preserve_jobs = NULL,
+                                       /* PRESERVE_JOBS value */
                        *remote_admin,  /* REMOTE_ADMIN value */
                        *remote_any,    /* REMOTE_ANY value */
                        *share_printers,/* SHARE_PRINTERS value */
@@ -1611,19 +1613,36 @@ do_config_server(http_t *http)          /* I - HTTP connection */
       */
 
       browse_web_if        = cgiGetVariable("BROWSE_WEB_IF") ? "Yes" : "No";
-      preserve_job_history = cgiGetVariable("PRESERVE_JOB_HISTORY") ? "Yes" : "No";
-      preserve_job_files   = cgiGetVariable("PRESERVE_JOB_FILES") ? "Yes" : "No";
       max_clients          = cgiGetVariable("MAX_CLIENTS");
-      max_jobs             = cgiGetVariable("MAX_JOBS");
       max_log_size         = cgiGetVariable("MAX_LOG_SIZE");
+      preserve_jobs        = cgiGetVariable("PRESERVE_JOBS");
+
+      if (preserve_jobs)
+      {
+        max_jobs             = cgiGetVariable("MAX_JOBS");
+       preserve_job_history = cgiGetVariable("PRESERVE_JOB_HISTORY");
+       preserve_job_files   = cgiGetVariable("PRESERVE_JOB_FILES");
+
+       if (!max_jobs || atoi(max_jobs) < 0)
+         max_jobs = "500";
+
+       if (!preserve_job_history)
+         preserve_job_history = "On";
+
+       if (!preserve_job_files)
+         preserve_job_files = "1d";
+      }
+      else
+      {
+        max_jobs             = "0";
+        preserve_job_history = "No";
+        preserve_job_files   = "No";
+      }
 
       if (!max_clients || atoi(max_clients) <= 0)
        max_clients = "100";
 
-      if (!max_jobs || atoi(max_jobs) <= 0)
-       max_jobs = "500";
-
-      if (!max_log_size || atof(max_log_size) <= 0.0)
+      if (!max_log_size || atoi(max_log_size) <= 0.0)
        max_log_size = "1m";
     }
 
@@ -1674,7 +1693,7 @@ do_config_server(http_t *http)            /* I - HTTP connection */
     if ((current_preserve_job_files = cupsGetOption("PreserveJobFiles",
                                                     num_settings,
                                                    settings)) == NULL)
-      current_preserve_job_files = "No";
+      current_preserve_job_files = "1d";
 
     if ((current_max_clients = cupsGetOption("MaxClients", num_settings,
                                              settings)) == NULL)
@@ -2636,18 +2655,25 @@ do_menu(http_t *http)                   /* I - HTTP connection */
                            settings)) == NULL)
     val = "Yes";
 
-  if (!_cups_strcasecmp(val, "yes") || !_cups_strcasecmp(val, "on") ||
-      !_cups_strcasecmp(val, "true"))
+  if (val &&
+      (!_cups_strcasecmp(val, "0") || !_cups_strcasecmp(val, "no") ||
+       !_cups_strcasecmp(val, "off") || !_cups_strcasecmp(val, "false") ||
+       !_cups_strcasecmp(val, "disabled")))
   {
-    cgiSetVariable("PRESERVE_JOB_HISTORY", "CHECKED");
+    cgiSetVariable("PRESERVE_JOB_HISTORY", "0");
+    cgiSetVariable("PRESERVE_JOB_FILES", "0");
+  }
+  else
+  {
+    cgiSetVariable("PRESERVE_JOBS", "CHECKED");
+    cgiSetVariable("PRESERVE_JOB_HISTORY", val);
 
     if ((val = cupsGetOption("PreserveJobFiles", num_settings,
                             settings)) == NULL)
-      val = "No";
+      val = "1d";
+
+    cgiSetVariable("PRESERVE_JOB_FILES", val);
 
-    if (!_cups_strcasecmp(val, "yes") || !_cups_strcasecmp(val, "on") ||
-       !_cups_strcasecmp(val, "true"))
-      cgiSetVariable("PRESERVE_JOB_FILES", "CHECKED");
   }
 
   if ((val = cupsGetOption("MaxClients", num_settings, settings)) == NULL)
index 32b6db6939e772e937a8ccfe0ab314f23a6cbabf..215c98bc43e369eb3ee590caec6518b5f7f87f72 100644 (file)
@@ -39,7 +39,8 @@ main(int  argc,                               /* I - Number of command-line arguments */
   const char   *query;                 /* Search query */
   const char   *cache_dir;             /* CUPS_CACHEDIR environment variable */
   const char   *docroot;               /* CUPS_DOCROOT environment variable */
-  const char   *helpfile;              /* Current help file */
+  const char   *helpfile,              /* Current help file */
+               *helptitle = NULL;      /* Current help title */
   const char   *topic;                 /* Current topic */
   char         topic_data[1024];       /* Topic form data */
   const char   *section;               /* Current section */
@@ -88,7 +89,7 @@ main(int  argc,                               /* I - Number of command-line arguments */
     perror(filename);
 
     cgiStartHTML(cgiText(_("Online Help")));
-    cgiSetVariable("ERROR", "Unable to load help index!");
+    cgiSetVariable("ERROR", cgiText(_("Unable to load help index.")));
     cgiCopyTemplateLang("error.tmpl");
     cgiEndHTML();
 
@@ -129,7 +130,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
       perror(filename);
 
       cgiStartHTML(cgiText(_("Online Help")));
-      cgiSetVariable("ERROR", "Unable to access help file!");
+      cgiSetVariable("ERROR", cgiText(_("Unable to access help file.")));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
 
@@ -139,7 +140,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
     if ((n = helpFindNode(hi, helpfile, NULL)) == NULL)
     {
       cgiStartHTML(cgiText(_("Online Help")));
-      cgiSetVariable("ERROR", "Help file not in index!");
+      cgiSetVariable("ERROR", cgiText(_("Help file not in index.")));
       cgiCopyTemplateLang("error.tmpl");
       cgiEndHTML();
 
@@ -147,12 +148,11 @@ main(int  argc,                           /* I - Number of command-line arguments */
     }
 
    /*
-    * Set the page title and save the help file...
+    * Save the page title and help file...
     */
 
-    cgiSetVariable("HELPFILE", helpfile);
-    cgiSetVariable("HELPTITLE", n->text);
-    cgiSetVariable("TOPIC", n->section);
+    helptitle = n->text;
+    topic     = n->section;
 
    /*
     * Send a standard page header...
@@ -170,6 +170,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
     */
 
     cgiStartHTML(cgiText(_("Online Help")));
+
+    topic = cgiGetVariable("TOPIC");
   }
 
  /*
@@ -180,7 +182,6 @@ main(int  argc,                             /* I - Number of command-line arguments */
     cgiSetVariable("QUERY", "");
 
   query = cgiGetVariable("QUERY");
-  topic = cgiGetVariable("TOPIC");
   si    = helpSearchIndex(hi, query, topic, helpfile);
 
   cgiClearVariables();
@@ -188,6 +189,10 @@ main(int  argc,                            /* I - Number of command-line arguments */
     cgiSetVariable("QUERY", query);
   if (topic)
     cgiSetVariable("TOPIC", topic);
+  if (helpfile)
+    cgiSetVariable("HELPFILE", helpfile);
+  if (helptitle)
+    cgiSetVariable("HELPTITLE", helptitle);
 
   fprintf(stderr, "DEBUG: query=\"%s\", topic=\"%s\"\n",
           query ? query : "(null)", topic ? topic : "(null)");
@@ -356,7 +361,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
     else
     {
       perror(filename);
-      cgiSetVariable("ERROR", "Unable to open help file.");
+      cgiSetVariable("ERROR", cgiText(_("Unable to open help file.")));
       cgiCopyTemplateLang("error.tmpl");
     }
   }
index d5e58eb1e313784888fd49a48a77f17a915486e6..8b8c026c495f8781abd1e93ea726837e1842129e 100644 (file)
@@ -167,6 +167,8 @@ cgiClearVariables(void)
   _cgi_var_t   *v;                     /* Current variable */
 
 
+  fputs("DEBUG: cgiClearVariables called.\n", stderr);
+
   for (v = form_vars, i = form_count; i > 0; v ++, i --)
   {
     _cupsStrFree(v->name);
@@ -401,6 +403,8 @@ cgiSetArray(const char *name,               /* I - Name of variable */
   if (name == NULL || value == NULL || element < 0 || element > 100000)
     return;
 
+  fprintf(stderr, "DEBUG: cgiSetArray: %s[%d]=\"%s\"\n", name, element, value);
+
   if ((var = cgi_find_variable(name)) == NULL)
   {
     cgi_add_variable(name, element, value);
@@ -532,6 +536,8 @@ cgiSetVariable(const char *name,    /* I - Name of variable */
   if (name == NULL || value == NULL)
     return;
 
+  fprintf(stderr, "cgiSetVariable: %s=\"%s\"\n", name, value);
+
   if ((var = cgi_find_variable(name)) == NULL)
   {
     cgi_add_variable(name, 0, value);
index 9b8ac80aa03804f14880e0e033a9dc3c09645584..592e253bbbc370e360a927a1a1597c706681163a 100644 (file)
@@ -3,7 +3,7 @@ dnl "$Id: cups-common.m4 8781 2009-08-28 17:34:54Z mike $"
 dnl
 dnl   Common configuration stuff for CUPS.
 dnl
-dnl   Copyright 2007-2011 by Apple Inc.
+dnl   Copyright 2007-2012 by Apple Inc.
 dnl   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 dnl
 dnl   These coded instructions, statements, and computer programs are the
@@ -50,6 +50,7 @@ AC_PROG_CXX
 AC_PROG_RANLIB
 AC_PATH_PROG(AR,ar)
 AC_PATH_PROG(CHMOD,chmod)
+AC_PATH_PROG(GZIP,gzip)
 AC_PATH_PROG(HTMLDOC,htmldoc)
 AC_PATH_PROG(LD,ld)
 AC_PATH_PROG(LN,ln)
@@ -237,7 +238,7 @@ if test "x$PKGCONFIG" != x; then
                        AC_MSG_RESULT(no)
                fi
        fi
-elif x$enable_libusb = xyes; then
+elif test x$enable_libusb = xyes; then
        AC_MSG_ERROR(Need pkg-config to enable libusb support.)
 fi
 
@@ -255,12 +256,17 @@ if test x$enable_tcp_wrappers = xyes; then
 fi
 
 dnl ZLIB
+INSTALL_GZIP=""
 LIBZ=""
 AC_CHECK_HEADER(zlib.h,
     AC_CHECK_LIB(z, gzgets,
        AC_DEFINE(HAVE_LIBZ)
        LIBZ="-lz"
-       LIBS="$LIBS -lz"))
+       LIBS="$LIBS -lz"
+       if test "x$GZIP" != z; then
+               INSTALL_GZIP="-z"
+       fi))
+AC_SUBST(INSTALL_GZIP)
 AC_SUBST(LIBZ)
 
 dnl Flags for "ar" command...
@@ -411,6 +417,8 @@ case $uname in
                AC_CHECK_HEADER(xpc/xpc.h,
                        AC_DEFINE(HAVE_XPC)
                        INSTALLXPC="install-xpc")
+               AC_CHECK_HEADER(xpc/private.h,
+                       AC_DEFINE(HAVE_XPC_PRIVATE_H))
                 ;;
 esac
 
index c223d8db05f9e54a7e0101598f784312e8a76a43..69699fb85e383f6e01ffa507d82752c4cc1d5e83 100644 (file)
@@ -3,7 +3,7 @@ dnl "$Id: cups-defaults.m4 7959 2008-09-17 19:30:58Z mike $"
 dnl
 dnl   Default cupsd configuration settings for CUPS.
 dnl
-dnl   Copyright 2007-2011 by Apple Inc.
+dnl   Copyright 2007-2012 by Apple Inc.
 dnl   Copyright 2006-2007 by Easy Software Products, all rights reserved.
 dnl
 dnl   These coded instructions, statements, and computer programs are the
@@ -14,7 +14,7 @@ dnl   file is missing or damaged, see the license at "http://www.cups.org/".
 dnl
 
 dnl Default languages...
-LANGUAGES="`ls -1 locale/cups_*.po | sed -e '1,$s/locale\/cups_//' -e '1,$s/\.po//' | tr '\n' ' '`"
+LANGUAGES="`ls -1 locale/cups_*.po 2>/dev/null | sed -e '1,$s/locale\/cups_//' -e '1,$s/\.po//' | tr '\n' ' '`"
 
 AC_ARG_WITH(languages, [  --with-languages        set installed languages, default=all ],[
        case "$withval" in
@@ -25,7 +25,7 @@ AC_ARG_WITH(languages, [  --with-languages        set installed languages, defau
 AC_SUBST(LANGUAGES)
 
 dnl Mac OS X bundle-based localization support
-AC_ARG_WITH(bundledir, [  --with-bundledir     set Mac OS X localization bundle directory ],
+AC_ARG_WITH(bundledir, [  --with-bundledir        set Mac OS X localization bundle directory ],
        CUPS_BUNDLEDIR="$withval",
        if test "x$uname" = xDarwin -a $uversion -ge 100; then
                CUPS_BUNDLEDIR="/System/Library/Frameworks/ApplicationServices.framework/Versions/A/Frameworks/PrintCore.framework/Versions/A"
@@ -50,6 +50,12 @@ AC_ARG_WITH(config_file_perm, [  --with-config-file-perm set default ConfigFileP
 AC_SUBST(CUPS_CONFIG_FILE_PERM)
 AC_DEFINE_UNQUOTED(CUPS_DEFAULT_CONFIG_FILE_PERM, 0$CUPS_CONFIG_FILE_PERM)
 
+dnl Default permissions for cupsd
+AC_ARG_WITH(cupsd_file_perm, [  --with-cupsd-file-perm  set default cupsd permissions, default=0500],
+       CUPS_CUPSD_FILE_PERM="$withval",
+       CUPS_CUPSD_FILE_PERM="500")
+AC_SUBST(CUPS_CUPSD_FILE_PERM)
+
 dnl Default LogFilePerm
 AC_ARG_WITH(log_file_perm, [  --with-log-file-perm    set default LogFilePerm value, default=0644],
        CUPS_LOG_FILE_PERM="$withval",
index 48012d9264b4e840ddec393e3a608e445d4e4336..157ed0f42b891f774f6922df8d4d8f3652c4a6dc 100644 (file)
@@ -3,7 +3,7 @@ dnl "$Id: cups-ssl.m4 7241 2008-01-22 22:34:52Z mike $"
 dnl
 dnl   OpenSSL/GNUTLS stuff for CUPS.
 dnl
-dnl   Copyright 2007-2011 by Apple Inc.
+dnl   Copyright 2007-2012 by Apple Inc.
 dnl   Copyright 1997-2007 by Easy Software Products, all rights reserved.
 dnl
 dnl   These coded instructions, statements, and computer programs are the
@@ -136,9 +136,9 @@ if test x$enable_ssl != xno; then
            dnl case the RSAREF libraries are needed.
 
            for libcrypto in \
-               "-lcrypto" \
-               "-lcrypto -lrsaref" \
-               "-lcrypto -lRSAglue -lrsaref"
+               "-lcrypto" \
+               "-lcrypto -lrsaref" \
+               "-lcrypto -lRSAglue -lrsaref"
            do
                AC_CHECK_LIB(ssl,SSL_new,
                    [have_ssl=1
@@ -149,6 +149,9 @@ if test x$enable_ssl != xno; then
                    $libcrypto)
 
                if test "x${SSLLIBS}" != "x"; then
+                   LIBS="$SAVELIBS $SSLLIBS"
+                   AC_CHECK_FUNC(SSL_set_tlsext_host_name,
+                       AC_DEFINE(HAVE_SSL_SET_TLSEXT_HOST_NAME))
                    break
                fi
            done
@@ -173,7 +176,6 @@ AC_SUBST(SSLLIBS)
 EXPORT_SSLLIBS="$SSLLIBS"
 AC_SUBST(EXPORT_SSLLIBS)
 
-
 dnl
 dnl End of "$Id: cups-ssl.m4 7241 2008-01-22 22:34:52Z mike $".
 dnl
diff --git a/config-scripts/cups-ssl.m4.orig b/config-scripts/cups-ssl.m4.orig
new file mode 100644 (file)
index 0000000..48012d9
--- /dev/null
@@ -0,0 +1,179 @@
+dnl
+dnl "$Id: cups-ssl.m4 7241 2008-01-22 22:34:52Z mike $"
+dnl
+dnl   OpenSSL/GNUTLS stuff for CUPS.
+dnl
+dnl   Copyright 2007-2011 by Apple Inc.
+dnl   Copyright 1997-2007 by Easy Software Products, all rights reserved.
+dnl
+dnl   These coded instructions, statements, and computer programs are the
+dnl   property of Apple Inc. and are protected by Federal copyright
+dnl   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
+dnl   which should have been included with this file.  If this file is
+dnl   file is missing or damaged, see the license at "http://www.cups.org/".
+dnl
+
+AC_ARG_ENABLE(ssl, [  --disable-ssl           disable SSL/TLS support])
+AC_ARG_ENABLE(cdsassl, [  --enable-cdsassl        use CDSA for SSL/TLS support, default=first])
+AC_ARG_ENABLE(gnutls, [  --enable-gnutls         use GNU TLS for SSL/TLS support, default=second])
+AC_ARG_ENABLE(openssl, [  --enable-openssl        use OpenSSL for SSL/TLS support, default=third])
+AC_ARG_WITH(openssl-libs, [  --with-openssl-libs     set directory for OpenSSL library],
+    LDFLAGS="-L$withval $LDFLAGS"
+    DSOFLAGS="-L$withval $DSOFLAGS",)
+AC_ARG_WITH(openssl-includes, [  --with-openssl-includes set directory for OpenSSL includes],
+    CFLAGS="-I$withval $CFLAGS"
+    CPPFLAGS="-I$withval $CPPFLAGS",)
+
+SSLFLAGS=""
+SSLLIBS=""
+have_ssl=0
+
+if test x$enable_ssl != xno; then
+    dnl Look for CDSA...
+    if test $have_ssl = 0 -a "x$enable_cdsassl" != "xno"; then
+       if test $uname = Darwin; then
+           AC_CHECK_HEADER(Security/SecureTransport.h, [
+               have_ssl=1
+               AC_DEFINE(HAVE_SSL)
+               AC_DEFINE(HAVE_CDSASSL)
+
+               dnl Check for the various security headers...
+               AC_CHECK_HEADER(Security/SecureTransportPriv.h,
+                   AC_DEFINE(HAVE_SECURETRANSPORTPRIV_H))
+               AC_CHECK_HEADER(Security/SecCertificate.h,
+                   AC_DEFINE(HAVE_SECCERTIFICATE_H))
+               AC_CHECK_HEADER(Security/SecItem.h,
+                   AC_DEFINE(HAVE_SECITEM_H))
+               AC_CHECK_HEADER(Security/SecItemPriv.h,
+                   AC_DEFINE(HAVE_SECITEMPRIV_H),,
+                   [#include <Security/SecItem.h>])
+               AC_CHECK_HEADER(Security/SecPolicy.h,
+                   AC_DEFINE(HAVE_SECPOLICY_H))
+               AC_CHECK_HEADER(Security/SecPolicyPriv.h,
+                   AC_DEFINE(HAVE_SECPOLICYPRIV_H))
+               AC_CHECK_HEADER(Security/SecBasePriv.h,
+                   AC_DEFINE(HAVE_SECBASEPRIV_H))
+               AC_CHECK_HEADER(Security/SecIdentitySearchPriv.h,
+                   AC_DEFINE(HAVE_SECIDENTITYSEARCHPRIV_H))
+
+               dnl Check for SSLSetProtocolVersionMax...
+               SAVELIBS="$LIBS"
+               LIBS="$LIBS -framework Security"
+               AC_CHECK_FUNC(SSLSetProtocolVersionMax)
+               LIBS="$SAVELIBS"
+
+               dnl Check for SecCertificateCopyData..
+               AC_MSG_CHECKING(for SecCertificateCopyData)
+               if test $uversion -ge 100; then
+                   AC_DEFINE(HAVE_SECCERTIFICATECOPYDATA)
+                   AC_MSG_RESULT(yes)
+               else
+                   AC_MSG_RESULT(no)
+               fi
+
+               dnl Check for SecIdentitySearchCreateWithPolicy...
+               AC_MSG_CHECKING(for SecIdentitySearchCreateWithPolicy)
+               if test $uversion -ge 80; then
+                   AC_DEFINE(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
+                   AC_MSG_RESULT(yes)
+               else
+                   AC_MSG_RESULT(no)
+               fi
+
+               dnl Check for SecPolicyCreateSSL...
+               AC_MSG_CHECKING(for SecPolicyCreateSSL)
+               if test $uversion -ge 110; then
+                   AC_DEFINE(HAVE_SECPOLICYCREATESSL)
+                   AC_MSG_RESULT(yes)
+               else
+                   AC_MSG_RESULT(no)
+               fi])
+
+               AC_DEFINE(HAVE_CSSMERRORSTRING)
+       fi
+    fi
+
+    dnl Then look for GNU TLS...
+    if test $have_ssl = 0 -a "x$enable_gnutls" != "xno" -a "x$PKGCONFIG" != x; then
+       AC_PATH_PROG(LIBGNUTLSCONFIG,libgnutls-config)
+       AC_PATH_PROG(LIBGCRYPTCONFIG,libgcrypt-config)
+       if $PKGCONFIG --exists gnutls; then
+           have_ssl=1
+           SSLLIBS=`$PKGCONFIG --libs gnutls`
+           SSLFLAGS=`$PKGCONFIG --cflags gnutls`
+           AC_DEFINE(HAVE_SSL)
+           AC_DEFINE(HAVE_GNUTLS)
+       elif test "x$LIBGNUTLSCONFIG" != x; then
+           have_ssl=1
+           SSLLIBS=`$LIBGNUTLSCONFIG --libs`
+           SSLFLAGS=`$LIBGNUTLSCONFIG --cflags`
+           AC_DEFINE(HAVE_SSL)
+           AC_DEFINE(HAVE_GNUTLS)
+       fi
+
+       if test $have_ssl = 1; then
+            if $PKGCONFIG --exists gcrypt; then
+               SSLLIBS="$SSLLIBS `$PKGCONFIG --libs gcrypt`"
+               SSLFLAGS="$SSLFLAGS `$PKGCONFIG --cflags gcrypt`"
+           elif test "x$LIBGCRYPTCONFIG" != x; then
+               SSLLIBS="$SSLLIBS `$LIBGCRYPTCONFIG --libs`"
+               SSLFLAGS="$SSLFLAGS `$LIBGCRYPTCONFIG --cflags`"
+           fi
+       fi
+    fi
+
+    dnl Check for the OpenSSL library last...
+    if test $have_ssl = 0 -a "x$enable_openssl" != "xno"; then
+       AC_CHECK_HEADER(openssl/ssl.h,
+           dnl Save the current libraries so the crypto stuff isn't always
+           dnl included...
+           SAVELIBS="$LIBS"
+
+           dnl Some ELF systems can't resolve all the symbols in libcrypto
+           dnl if libcrypto was linked against RSAREF, and fail to link the
+           dnl test program correctly, even though a correct installation
+           dnl of OpenSSL exists.  So we test the linking three times in
+           dnl case the RSAREF libraries are needed.
+
+           for libcrypto in \
+               "-lcrypto" \
+               "-lcrypto -lrsaref" \
+               "-lcrypto -lRSAglue -lrsaref"
+           do
+               AC_CHECK_LIB(ssl,SSL_new,
+                   [have_ssl=1
+                    SSLFLAGS="-DOPENSSL_DISABLE_OLD_DES_SUPPORT"
+                    SSLLIBS="-lssl $libcrypto"
+                    AC_DEFINE(HAVE_SSL)
+                    AC_DEFINE(HAVE_LIBSSL)],,
+                   $libcrypto)
+
+               if test "x${SSLLIBS}" != "x"; then
+                   break
+               fi
+           done
+
+           LIBS="$SAVELIBS")
+    fi
+fi
+
+IPPALIASES="http"
+if test $have_ssl = 1; then
+    AC_MSG_RESULT([    Using SSLLIBS="$SSLLIBS"])
+    AC_MSG_RESULT([    Using SSLFLAGS="$SSLFLAGS"])
+    IPPALIASES="http https ipps"
+elif test x$enable_cdsa = xyes -o x$enable_gnutls = xyes -o x$enable_openssl = xyes; then
+    AC_MSG_ERROR([Unable to enable SSL support.])
+fi
+
+AC_SUBST(IPPALIASES)
+AC_SUBST(SSLFLAGS)
+AC_SUBST(SSLLIBS)
+
+EXPORT_SSLLIBS="$SSLLIBS"
+AC_SUBST(EXPORT_SSLLIBS)
+
+
+dnl
+dnl End of "$Id: cups-ssl.m4 7241 2008-01-22 22:34:52Z mike $".
+dnl
index 9c1faf9ab4601f3c17c1ebbb5c56911e59652d6b..4081f7db87e2ce6bed13d0d7adfae3ddf5c8e7a7 100644 (file)
 #undef HAVE_SSL
 
 
+/*
+ * Do we have the SSL_set_tlsext_host_name function?
+ */
+
+#undef HAVE_SSL_SET_TLSEXT_HOST_NAME
+
+
 /*
  * What Security framework headers do we have?
  */
  */
 
 #undef HAVE_XPC
+#undef HAVE_XPC_PRIVATE_H
 
 
 /*
index d90d847d8b844fb83c5b6e68e5d441a718720720..cd0fd53b5b134d49f3a122b546e4938f158c692f 100644 (file)
@@ -3,7 +3,7 @@
 
   HTTP and IPP API introduction for CUPS.
 
-  Copyright 2007-2011 by Apple Inc.
+  Copyright 2007-2012 by Apple Inc.
   Copyright 1997-2006 by Easy Software Products, all rights reserved.
 
   These coded instructions, statements, and computer programs are the
@@ -29,35 +29,20 @@ The constant <code>CUPS_HTTP_DEFAULT</code> can be used with all of the
 <code>cups</code> functions to refer to the default CUPS server - the functions
 create a per-thread <a href='#http_t'><code>http_t</code></a> as needed.</p>
 
-<p>The IPP APIs use two structures for requests (messages sent to the CUPS
-scheduler) and responses (messages sent back to your application from the
-scheduler). The <a href='#ipp_t'><code>ipp_t</code></a> structure holds a
-complete request or response and is allocated using the
-<a href='#ippNew'><code>ippNew</code></a> or
-<a href='#ippNewRequest'><code>ippNewRequest</code></a> functions and
-freed using the <a href='#ippDelete'><code>ippDelete</code></a> function.</p>
-
-<p>The second structure is called
-<a href='#ipp_attribute_t'><code>ipp_attribute_t</code></a> and holds a
-single IPP attribute which consists of a group tag (<code>group_tag</code>), a
-value type tag (<code>value_tag</code>), the attribute name (<code>name</code>),
-and 1 or more values (<code>values[]</code>). Attributes are added to an
-<a href='#ipp_t'><code>ipp_t</code></a> structure using one of the
-<code>ippAdd</code> functions. For example, use
-<a href='#ippAddString'><code>ippAddString</code></a> to add a
-"requesting-user-name" string attribute to a request:</p>
+<p>The IPP APIs use two opaque structures for requests (messages sent to the CUPS scheduler) and responses (messages sent back to your application from the scheduler). The <a href='#ipp_t'><code>ipp_t</code></a> type holds a complete request or response and is allocated using the <a href='#ippNew'><code>ippNew</code></a> or <a href='#ippNewRequest'><code>ippNewRequest</code></a> functions and freed using the <a href='#ippDelete'><code>ippDelete</code></a> function.</p>
+
+<p>The second opaque structure is called <a href='#ipp_attribute_t'><code>ipp_attribute_t</code></a> and holds a single IPP attribute which consists of a group tag (<a href='#ippGetGroupTag'><code>ippGetGroupTag</code></a>), a value type tag (<a href='#ippGetValueTag'><code>ippGetValueTag</code></a>), the attribute name (<a href='#ippGetName'><code>ippGetName</code></a>), and 1 or more values (<a href='#ippGetCount'><code>ippGetCount</code></a>, <a href='#ippGetBoolean'><code>ippGetBoolean</code></a>, <a href='#ippGetCollection'><code>ippGetCollection</code></a>, <a href='#ippGetDate'><code>ippGetDate</code></a>, <a href='#ippGetInteger'><code>ippGetInteger</code></a>, <a href='#ippGetRange'><code>ippGetRange</code></a>, <a href='#ippGetResolution'><code>ippGetResolution</code></a>, and <a href='#ippGetString'><code>ippGetString</code></a>). Attributes are added to an <a href='#ipp_t'><code>ipp_t</code></a> pointer using one of the <code>ippAdd</code> functions. For example, use <a href='#ippAddString'><code>ippAddString</code></a> to add the "printer-uri" and "requesting-user-name" string attributes to a request:</p>
 
 <pre class='example'>
 <a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(IPP_GET_JOBS);
 
+<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+             NULL, "ipp://localhost/printers/");
 <a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
              NULL, cupsUser());
 </pre>
 
-<p>Once you have created an IPP request, use the <code>cups</code>
-functions to send the request to and read the response from the server.
-For example, the <a href='#cupsDoRequest'><code>cupsDoRequest</code></a>
-function can be used for simple query operations that do not involve files:</p>
+<p>Once you have created an IPP request, use the <code>cups</code> functions to send the request to and read the response from the server. For example, the <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function can be used for simple query operations that do not involve files:</p>
 
 <pre class='example'>
 #include &lt;cups/cups.h&gt;
@@ -67,6 +52,8 @@ function can be used for simple query operations that do not involve files:</p>
 {
   <a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(IPP_GET_JOBS);
 
+  <a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, "ipp://localhost/printers/");
   <a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
                NULL, cupsUser());
 
@@ -74,13 +61,7 @@ function can be used for simple query operations that do not involve files:</p>
 }
 </pre>
 
-<p>The <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function frees
-the request structure and returns an IPP response structure or NULL pointer if
-the request could not be sent to the server. Once you have a response from
-the server, you can either use the
-<a href='#ippFindAttribute'><code>ippFindAttribute</code></a> and
-<a href='#ippFindNextAttribute'><code>ippFindNextAttribute</code></a> functions
-to find specific attributes, for example:</p>
+<p>The <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function frees the request and returns an IPP response or <code>NULL</code> pointer if the request could not be sent to the server. Once you have a response from the server, you can either use the <a href='#ippFindAttribute'><code>ippFindAttribute</code></a> and <a href='#ippFindNextAttribute'><code>ippFindNextAttribute</code></a> functions to find specific attributes, for example:</p>
 
 <pre class='example'>
 <a href='#ipp_t'>ipp_t</a> *response;
@@ -89,25 +70,20 @@ to find specific attributes, for example:</p>
 attr = <a href='#ippFindAttribute'>ippFindAttribute</a>(response, "printer-state", IPP_TAG_ENUM);
 </pre>
 
-<p>You can also walk the list of attributes with a simple <code>for</code> loop
-like this:</p>
+<p>You can also walk the list of attributes with a simple <code>for</code> loop like this:</p>
 
 <pre class='example'>
 <a href='#ipp_t'>ipp_t</a> *response;
 <a href='#ipp_attribute_t'>ipp_attribute_t</a> *attr;
 
-for (attr = response->attrs; attr != NULL; attr = attr->next)
-  if (attr->name == NULL)
+for (attr = <a href='#ippFirstAttribute'>ippFirstAttribute</a>(response); attr != NULL; attr = <a href='#ippNextAttribute'>ippNextAttribute</a>(response))
+  if (ippGetName(attr) == NULL)
     puts("--SEPARATOR--");
   else
-    puts(attr->name);
+    puts(ippGetName(attr));
 </pre>
 
-<p>The <code>for</code> loop approach is normally used when collecting
-attributes for multiple objects (jobs, printers, etc.) in a response. Attributes
-with <code>NULL</code> names indicate a separator between the attributes of
-each object. For example, the following code will list the jobs returned from
-our previous <a href='#get_jobs'><code>get_jobs</code></a> example code:</p>
+<p>The <code>for</code> loop approach is normally used when collecting attributes for multiple objects (jobs, printers, etc.) in a response. Attributes with <code>NULL</code> names indicate a separator between the attributes of each object. For example, the following code will list the jobs returned from our previous <a href='#get_jobs'><code>get_jobs</code></a> example code:</p>
 
 <pre class='example'>
 <a href='#ipp_t'>ipp_t</a> *response = <a href='#get_jobs'>get_jobs</a>();
@@ -115,37 +91,55 @@ our previous <a href='#get_jobs'><code>get_jobs</code></a> example code:</p>
 if (response != NULL)
 {
   <a href='#ipp_attribute_t'>ipp_attribute_t</a> *attr;
+  const char *attrname;
   int job_id = 0;
-  char *job_name = NULL;
-  char *job_originating_user_name = NULL;
+  const char *job_name = NULL;
+  const char *job_originating_user_name = NULL;
 
   puts("Job ID  Owner             Title");
   puts("------  ----------------  ---------------------------------");
 
-  for (attr = response->attrs; attr != NULL; attr = attr->next)
+  for (attr = <a href='#ippFirstAttribute'>ippFirstAttribute</a>(response); attr != NULL; attr = <a href='#ippNextAttribute'>ippNextAttribute</a>(response))
   {
    /* Attributes without names are separators between jobs */
-    if (attr->name == NULL)
+    attrname = ippGetName(attr);
+    if (attrname == NULL)
     {
-      if (job_id > 0 &amp;&amp; job_name != NULL &amp;&amp; job_originating_user_name != NULL)
+      if (job_id > 0)
+      {
+        if (job_name == NULL)
+          job_name = "(withheld)";
+
+        if (job_originating_user_name == NULL)
+          job_originating_user_name = "(withheld)";
+
         printf("%5d  %-16s  %s\n", job_id, job_originating_user_name, job_name);
+      }
 
       job_id = 0;
       job_name = NULL;
       job_originating_user_name = NULL;
       continue;
     }
-    else if (!strcmp(attr->name, "job-id") &amp;&amp; attr->value_tag == IPP_TAG_INTEGER)
-      job_id = attr->values[0].integer;
-    else if (!strcmp(attr->name, "job-name") &amp;&amp; attr->value_tag == IPP_TAG_NAME)
-      job_name = attr->values[0].string.text;
-    else if (!strcmp(attr->name, "job-originating-user-name") &amp;&amp;
-             attr->value_tag == IPP_TAG_NAME)
-      job_originating_user_name = attr->values[0].string.text;
+    else if (!strcmp(attrname, "job-id") &amp;&amp; ippGetValueTag(attr) == IPP_TAG_INTEGER)
+      job_id = ippGetInteger(attr, 0);
+    else if (!strcmp(attrname, "job-name") &amp;&amp; ippGetValueTag(attr) == IPP_TAG_NAME)
+      job_name = ippGetString(attr, 0, NULL);
+    else if (!strcmp(attrname, "job-originating-user-name") &amp;&amp;
+             ippGetValueTag(attr) == IPP_TAG_NAME)
+      job_originating_user_name = ippGetString(attr, 0, NULL);
   }
 
-  if (job_id > 0 &amp;&amp; job_name != NULL &amp;&amp; job_originating_user_name != NULL)
+  if (job_id > 0)
+  {
+    if (job_name == NULL)
+      job_name = "(withheld)";
+
+    if (job_originating_user_name == NULL)
+      job_originating_user_name = "(withheld)";
+
     printf("%5d  %-16s  %s\n", job_id, job_originating_user_name, job_name);
+  }
 }
 </pre>
 
index e2ae33741f85e5a26adadb1ecf852be9cfcd1c77..e2c0239ade498a282722dc2e3be34987bfb6f8a6 100644 (file)
  * Include necessary headers...
  */
 
-#  include <cups/cups.h>
 #  include "string-private.h"
 #  include "debug-private.h"
-#  include "ppd-private.h"
-#  include "http-private.h"
 #  include "ipp-private.h"
+#  include "http-private.h"
 #  include "language-private.h"
 #  include "pwg-private.h"
+#  include "ppd-private.h"
 #  include "thread-private.h"
+#  include <cups/cups.h>
 #  ifdef __APPLE__
 #    include <sys/cdefs.h>
 #    include <CoreFoundation/CoreFoundation.h>
index 685e544525d58596f6c3ba85e18e1131d01cc0b7..7425ce16e1ee0210f36ff2d20376b2f8a754fb8b 100644 (file)
@@ -513,7 +513,8 @@ extern int          cupsCheckDestSupported(http_t *http, cups_dest_t *dest,
                                               const char *option,
                                               const char *value) _CUPS_API_1_6;
 extern ipp_status_t    cupsCloseDestJob(http_t *http, cups_dest_t *dest,
-                                        int job_id) _CUPS_API_1_6;
+                                        cups_dinfo_t *info, int job_id)
+                                        _CUPS_API_1_6;
 extern http_t          *cupsConnectDest(cups_dest_t *dest, unsigned flags,
                                         int msec, int *cancel,
                                         char *resource, size_t resourcesize,
@@ -558,7 +559,9 @@ extern int          cupsEnumDestsBlock(unsigned flags, int msec,
                                           _CUPS_API_1_6;
 #  endif /* __BLOCKS__ */
 extern ipp_status_t    cupsFinishDestDocument(http_t *http,
-                                              cups_dest_t *dest) _CUPS_API_1_6;
+                                              cups_dest_t *dest,
+                                              cups_dinfo_t *info)
+                                              _CUPS_API_1_6;
 extern void            cupsFreeDestInfo(cups_dinfo_t *dinfo) _CUPS_API_1_6;
 extern int             cupsGetDestMediaByName(http_t *http, cups_dest_t *dest,
                                               cups_dinfo_t *dinfo,
index 31cac7903c11c3f429c394ab5652426e1a3630ae..01f8578e0d6c24a152feeec2dc488612c40de44c 100644 (file)
@@ -53,27 +53,92 @@ cupsCancelDestJob(http_t      *http,        /* I - Connection to destination */
  * 'cupsCloseDestJob()' - Close a job and start printing.
  *
  * Use when the last call to cupsStartDocument passed 0 for "last_document".
- * "job_id" is the job ID returned by cupsCreateDestJob. Returns IPP_OK on
- * success.
+ * "job_id" is the job ID returned by cupsCreateDestJob. Returns @code IPP_OK@
+ * on success.
  *
  * @since CUPS 1.6@
  */
 
-ipp_status_t
+ipp_status_t                           /* O - IPP status code */
 cupsCloseDestJob(
-    http_t      *http,                 /* I - Connection to destination */
-    cups_dest_t *dest,                 /* I - Destination */
-    int         job_id)                        /* I - Job ID */
+    http_t       *http,                        /* I - Connection to destination */
+    cups_dest_t  *dest,                        /* I - Destination */
+    cups_dinfo_t *info,                /* I - Destination information */
+    int          job_id)               /* I - Job ID */
 {
-  return (IPP_NOT_FOUND);
+  int                  i;              /* Looping var */
+  ipp_t                        *request = NULL;/* Close-Job/Send-Document request */
+  ipp_attribute_t      *attr;          /* operations-supported attribute */
+
+
+  DEBUG_printf(("cupsCloseDestJob(http=%p, dest=%p(%s/%s), info=%p, job_id=%d)",
+                http, dest, dest ? dest->name : NULL,
+                dest ? dest->instance : NULL, info, job_id));
+
+ /*
+  * Range check input...
+  */
+
+  if (!http || !dest || !info || job_id <= 0)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+    DEBUG_puts("1cupsCloseDestJob: Bad arguments.");
+    return (IPP_INTERNAL_ERROR);
+  }
+
+ /*
+  * Build a Close-Job or empty Send-Document request...
+  */
+
+  if ((attr = ippFindAttribute(info->attrs, "operations-supported",
+                               IPP_TAG_ENUM)) != NULL)
+  {
+    for (i = 0; i < attr->num_values; i ++)
+      if (attr->values[i].integer == IPP_CLOSE_JOB)
+      {
+        request = ippNewRequest(IPP_CLOSE_JOB);
+        break;
+      }
+  }
+
+  if (!request)
+    request = ippNewRequest(IPP_SEND_DOCUMENT);
+
+  if (!request)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(ENOMEM), 0);
+    DEBUG_puts("1cupsCloseDestJob: Unable to create Close-Job/Send-Document "
+               "request.");
+    return (IPP_INTERNAL_ERROR);
+  }
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, info->uri);
+  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id",
+                job_id);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+               NULL, cupsUser());
+  if (ippGetOperation(request) == IPP_SEND_DOCUMENT)
+    ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", 1);
+
+ /*
+  * Send the request and return the status...
+  */
+
+  ippDelete(cupsDoRequest(http, request, info->resource));
+
+  DEBUG_printf(("1cupsCloseDestJob: %s (%s)", ippErrorString(cupsLastError()),
+                cupsLastErrorString()));
+
+  return (cupsLastError());
 }
 
 
 /*
  * 'cupsCreateDestJob()' - Create a job on a destination.
  *
- * Returns IPP_OK or IPP_OK_SUBST on success, saving the job ID in the variable
- * pointed to by "job_id".
+ * Returns @code IPP_OK@ or @code IPP_OK_SUBST@ on success, saving the job ID
+ * in the variable pointed to by "job_id".
  *
  * @since CUPS 1.6@
  */
@@ -88,26 +153,115 @@ cupsCreateDestJob(
     int           num_options,         /* I - Number of job options */
     cups_option_t *options)            /* I - Job options */
 {
-  *job_id = 0;
+  ipp_t                        *request,       /* Create-Job request */
+                       *response;      /* Create-Job response */
+  ipp_attribute_t      *attr;          /* job-id attribute */
+
+
+  DEBUG_printf(("cupsCreateDestJob(http=%p, dest=%p(%s/%s), info=%p, "
+                "job_id=%p, title=\"%s\", num_options=%d, options=%p)",
+                http, dest, dest ? dest->name : NULL,
+                dest ? dest->instance : NULL, info, job_id, title, num_options,
+                options));
+
+ /*
+  * Range check input...
+  */
+
+  if (job_id)
+    *job_id = 0;
+
+  if (!http || !dest || !info || !job_id)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+    DEBUG_puts("1cupsCreateDestJob: Bad arguments.");
+    return (IPP_INTERNAL_ERROR);
+  }
+
+ /*
+  * Build a Create-Job request...
+  */
+
+  if ((request = ippNewRequest(IPP_CREATE_JOB)) == NULL)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(ENOMEM), 0);
+    DEBUG_puts("1cupsCreateDestJob: Unable to create Create-Job request.");
+    return (IPP_INTERNAL_ERROR);
+  }
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, info->uri);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+               NULL, cupsUser());
+  if (title)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "job-name", NULL,
+                 title);
+  cupsEncodeOptions(request, num_options, options);
+
+ /*
+  * Send the request and get the job-id...
+  */
 
-  return (IPP_NOT_POSSIBLE);
+  response = cupsDoRequest(http, request, info->resource);
+
+  if ((attr = ippFindAttribute(response, "job-id", IPP_TAG_INTEGER)) != NULL)
+  {
+    *job_id = attr->values[0].integer;
+    DEBUG_printf(("1cupsCreateDestJob: job-id=%d", *job_id));
+  }
+
+  ippDelete(response);
+
+ /*
+  * Return the status code from the Create-Job request...
+  */
+
+  DEBUG_printf(("1cupsCreateDestJob: %s (%s)", ippErrorString(cupsLastError()),
+                cupsLastErrorString()));
+
+  return (cupsLastError());
 }
 
 
 /*
  * 'cupsFinishDestDocument()' - Finish the current document.
  *
- * Returns IPP_OK on success.
+ * Returns @code IPP_OK@ or @code IPP_OK_SUBST@ on success.
  *
  * @since CUPS 1.6@
  */
 
-ipp_status_t
+ipp_status_t                           /* O - Status of document submission */
 cupsFinishDestDocument(
-    http_t      *http,                 /* I - Connection to destination */
-    cups_dest_t *dest)                 /* I - Destination */
+    http_t       *http,                        /* I - Connection to destination */
+    cups_dest_t  *dest,                        /* I - Destination */
+    cups_dinfo_t *info)                /* I - Destination information */
 {
-  return (IPP_NOT_FOUND);
+  DEBUG_printf(("cupsFinishDestDocument(http=%p, dest=%p(%s/%s), info=%p)",
+                http, dest, dest ? dest->name : NULL,
+                dest ? dest->instance : NULL, info));
+
+ /*
+  * Range check input...
+  */
+
+  if (!http || !dest || !info)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+    DEBUG_puts("1cupsFinishDestDocument: Bad arguments.");
+    return (IPP_INTERNAL_ERROR);
+  }
+
+ /*
+  * Get the response at the end of the document and return it...
+  */
+
+  ippDelete(cupsGetResponse(http, info->resource));
+
+  DEBUG_printf(("1cupsFinishDestDocument: %s (%s)",
+                ippErrorString(cupsLastError()), cupsLastErrorString()));
+
+  return (cupsLastError());
 }
 
 
@@ -119,12 +273,12 @@ cupsFinishDestDocument(
  * document (see CUPS_FORMAT_xxx constants), and "num_options" and "options"
  * are the options do be applied to the document. "last_document" should be 1
  * if this is the last document to be submitted in the job.  Returns
- * HTTP_CONTINUE on success.
+ * @code HTTP_CONTINUE@ on success.
  *
  * @since CUPS 1.6@
  */
 
-http_status_t
+http_status_t                          /* O - Status of document creation */
 cupsStartDestDocument(
     http_t        *http,               /* I - Connection to destination */
     cups_dest_t   *dest,               /* I - Destination */
@@ -136,7 +290,64 @@ cupsStartDestDocument(
     cups_option_t *options,            /* I - Document options */
     int           last_document)       /* I - 1 if this is the last document */
 {
-  return (HTTP_CONTINUE);
+  ipp_t                *request;               /* Send-Document request */
+  http_status_t        status;                 /* HTTP status */
+
+
+  DEBUG_printf(("cupsStartDestDocument(http=%p, dest=%p(%s/%s), info=%p, "
+                "job_id=%d, docname=\"%s\", format=\"%s\", num_options=%d, "
+                "options=%p, last_document=%d)",
+                http, dest, dest ? dest->name : NULL,
+                dest ? dest->instance : NULL, info, job_id, docname, format,
+                num_options, options, last_document));
+
+ /*
+  * Range check input...
+  */
+
+  if (!http || !dest || !info || job_id <= 0)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
+    DEBUG_puts("1cupsStartDestDocument: Bad arguments.");
+    return (HTTP_ERROR);
+  }
+
+ /*
+  * Create a Send-Document request...
+  */
+
+  if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
+  {
+    _cupsSetError(IPP_INTERNAL_ERROR, strerror(ENOMEM), 0);
+    DEBUG_puts("1cupsStartDestDocument: Unable to create Send-Document "
+               "request.");
+    return (HTTP_ERROR);
+  }
+
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, info->uri);
+  ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "job-id", job_id);
+  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
+               NULL, cupsUser());
+  if (docname)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "document-name",
+                 NULL, docname);
+  if (format)
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_MIMETYPE,
+                 "document-format", NULL, format);
+  ippAddBoolean(request, IPP_TAG_OPERATION, "last-document", last_document);
+
+  cupsEncodeOptions2(request, num_options, options, IPP_TAG_DOCUMENT);
+
+ /*
+  * Send and delete the request, then return the status...
+  */
+
+  status = cupsSendRequest(http, request, info->resource, CUPS_LENGTH_VARIABLE);
+
+  ippDelete(request);
+
+  return (status);
 }
 
 
index af5a26256312a0c8462f40694c660ecb9a01a1e0..a36b5334e8dce3ec574550a5faf69cacc544011c 100644 (file)
@@ -15,7 +15,7 @@
  *
  * Contents:
  *
- *   cupsCheckDestSupported() - Check that the option and value are supported
+*   cupsCheckDestSupported() - Check that the option and value are supported
  *                             by the destination.
  *   cupsCopyDestConflicts()  - Get conflicts and resolutions for a new
  *                             option/value pair.
@@ -292,7 +292,7 @@ cupsCopyDestConflicts(
     return (0);
 
  /*
-  * Check for an resolve any conflicts...
+  * Check for and resolve any conflicts...
   */
 
   /* TODO: implement me! */
@@ -821,7 +821,7 @@ cups_create_media_db(
     mdb.top    =
     mdb.bottom = 1270; /* Default 1/2" top/bottom margins */
 
-    for (i = media_col_db->num_values, val = media_col_db->values;
+    for (i = media_attr->num_values, val = media_attr->values;
          i > 0;
          i --, val ++)
     {
index c5f83a076687002039bc6569d587a0bcd58c4af3..bf9a0dcc46b35c0a70d724c32045e53f32093d8a 100644 (file)
@@ -348,11 +348,6 @@ _cupsAppleCopyDefaultPrinter(void)
     return (NULL);
   }
 
-//#  ifdef DEBUG
-//  CFStringGetCString(network, name, namesize, kCFStringEncodingUTF8);
-//  DEBUG_printf(("2_cupsUserDefault: network=\"%s\"", name));
-//#  endif /* DEBUG */
-
  /*
   * Lookup the network in the preferences...
   */
@@ -837,7 +832,7 @@ cupsEnumDests(
 {
   int                  i,              /* Looping var */
                        num_dests;      /* Number of destinations */
-  cups_dest_t          *dests,         /* Destinations */
+  cups_dest_t          *dests = NULL,  /* Destinations */
                        *dest;          /* Current destination */
 #ifdef HAVE_DNSSD
   int                  nfds,           /* Number of files responded */
@@ -1934,7 +1929,7 @@ cupsSetDests2(http_t      *http,  /* I - Connection to server or @code CUPS_HTTP_
 #endif /* WIN32 */
   char         filename[1024];         /* lpoptions file */
   int          num_temps;              /* Number of temporary destinations */
-  cups_dest_t  *temps,                 /* Temporary destinations */
+  cups_dest_t  *temps = NULL,          /* Temporary destinations */
                *temp;                  /* Current temporary dest */
   const char   *val;                   /* Value of temporary option */
   _cups_globals_t *cg = _cupsGlobals();        /* Pointer to library globals */
@@ -2801,11 +2796,9 @@ cups_dnssd_query_cb(
                        model[256],     /* Model */
                        uriname[1024],  /* Name for URI */
                        uri[1024];      /* Printer URI */
-    cups_ptype_t       type;           /* Device type */
 
     device->state     = _CUPS_DNSSD_PENDING;
     make_and_model[0] = '\0';
-    type              = CUPS_PRINTER_REMOTE;
 
     strcpy(model, "Unknown");
 
@@ -2881,7 +2874,6 @@ cups_dnssd_query_cb(
         device->dest.num_options = cupsAddOption("printer-type", value,
                                                  device->dest.num_options,
                                                  &device->dest.options);
-        type = strtol(value, NULL, 0);
       }
     }
 
index 917150e9cc87af80b54cd05426ac4abf484c4a56..93e4df58f59b800992dcfb2bbadcf0f6efa77487 100644 (file)
@@ -32,7 +32,9 @@
 #ifdef HAVE_POLL
 #  include <poll.h>
 #endif /* HAVE_POLL */
-#include <sys/fcntl.h>
+#ifndef WIN32
+#  include <sys/fcntl.h>
+#endif /* WIN32 */
 
 
 /*
index b886515bda7f6413e68497dde0e1801536110ea3..40c69826f349caef9da8b6c976cb338978209d91 100644 (file)
@@ -1508,8 +1508,7 @@ _httpResolveURI(
     {
       localref = ref;
       if (DNSServiceResolve(&localref,
-                            kDNSServiceFlagsShareConnection |
-                                kDNSServiceFlagsTimeout, 0, hostname, regtype,
+                            kDNSServiceFlagsShareConnection, 0, hostname, regtype,
                            "local.", http_resolve_cb,
                            &uribuf) == kDNSServiceErr_NoError)
       {
@@ -1547,7 +1546,11 @@ _httpResolveURI(
          FD_ZERO(&input_set);
          FD_SET(DNSServiceRefSockFD(ref), &input_set);
 
+#ifdef WIN32
+         stimeout.tv_sec  = (long)timeout;
+#else
          stimeout.tv_sec  = timeout;
+#endif /* WIN32 */
          stimeout.tv_usec = 0;
 
          fds = select(DNSServiceRefSockFD(ref)+1, &input_set, NULL, NULL,
@@ -1579,8 +1582,7 @@ _httpResolveURI(
 
              domainref = ref;
              if (DNSServiceResolve(&domainref,
-                                   kDNSServiceFlagsShareConnection |
-                                       kDNSServiceFlagsTimeout,
+                                   kDNSServiceFlagsShareConnection,
                                    0, hostname, regtype, domain,
                                    http_resolve_cb,
                                    &uribuf) == kDNSServiceErr_NoError)
index 1f2d826dda209811923a586c0183ff8be427fc81..b95baa9d06c4c0b998cf4a2950066336bb492b55 100644 (file)
@@ -4163,7 +4163,8 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
            break;
 
        case errSSLWouldBlock :
-           usleep(1000);
+           error = noErr;              /* Force a retry */
+           usleep(1000);               /* in 1 millisecond */
            break;
 
 #    ifdef HAVE_SECCERTIFICATECOPYDATA
@@ -4199,7 +4200,7 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
                  {
                    data = (CFDataRef)CFArrayGetValueAtIndex(dn_array, i);
 
-                   if ((credential = malloc(sizeof(*credential))))
+                   if ((credential = malloc(sizeof(*credential))) != NULL)
                    {
                      credential->datalen = CFDataGetLength(data);
                      if ((credential->data = malloc(credential->datalen)))
@@ -4520,7 +4521,8 @@ http_write(http_t     *http,              /* I - Connection to server */
        pfd.events = POLLOUT;
 
        while ((nfds = poll(&pfd, 1, http->wait_value)) < 0 &&
-              (errno == EINTR || errno == EAGAIN));
+              (errno == EINTR || errno == EAGAIN))
+         /* do nothing */;
 
 #else
        do
index 70729cf591ebb7058ea6a24c30f77365c1f9732c..1d3003c3f85b165bee6e89243fdf096d86bf64f8 100644 (file)
@@ -46,103 +46,6 @@ extern "C" {
  * Structures...
  */
 
-typedef union _ipp_request_u           /**** Request Header ****/
-{
-  struct                               /* Any Header */
-  {
-    ipp_uchar_t        version[2];             /* Protocol version number */
-    int                op_status;              /* Operation ID or status code*/
-    int                request_id;             /* Request ID */
-  }            any;
-
-  struct                               /* Operation Header */
-  {
-    ipp_uchar_t        version[2];             /* Protocol version number */
-    ipp_op_t   operation_id;           /* Operation ID */
-    int                request_id;             /* Request ID */
-  }            op;
-
-  struct                               /* Status Header */
-  {
-    ipp_uchar_t        version[2];             /* Protocol version number */
-    ipp_status_t status_code;          /* Status code */
-    int                request_id;             /* Request ID */
-  }            status;
-
-  /**** New in CUPS 1.1.19 ****/
-  struct                               /* Event Header @since CUPS 1.1.19/Mac OS X 10.3@ */
-  {
-    ipp_uchar_t        version[2];             /* Protocol version number */
-    ipp_status_t status_code;          /* Status code */
-    int                request_id;             /* Request ID */
-  }            event;
-} _ipp_request_t;
-
-/**** New in CUPS 1.1.19 ****/
-
-typedef union _ipp_value_u             /**** Attribute Value ****/
-{
-  int          integer;                /* Integer/enumerated value */
-
-  char         boolean;                /* Boolean value */
-
-  ipp_uchar_t  date[11];               /* Date/time value */
-
-  struct
-  {
-    int                xres,                   /* Horizontal resolution */
-               yres;                   /* Vertical resolution */
-    ipp_res_t  units;                  /* Resolution units */
-  }            resolution;             /* Resolution value */
-
-  struct
-  {
-    int                lower,                  /* Lower value */
-               upper;                  /* Upper value */
-  }            range;                  /* Range of integers value */
-
-  struct
-  {
-    char       *language;              /* Language code */
-    char       *text;                  /* String */
-  }            string;                 /* String with language value */
-
-  struct
-  {
-    int                length;                 /* Length of attribute */
-    void       *data;                  /* Data in attribute */
-  }            unknown;                /* Unknown attribute type */
-
-/**** New in CUPS 1.1.19 ****/
-  ipp_t                *collection;            /* Collection value @since CUPS 1.1.19/Mac OS X 10.3@ */
-} _ipp_value_t;
-
-struct _ipp_attribute_s                /**** Attribute ****/
-{
-  ipp_attribute_t *next;               /* Next attribute in list */
-  ipp_tag_t    group_tag,              /* Job/Printer/Operation group tag */
-               value_tag;              /* What type of value is it? */
-  char         *name;                  /* Name of attribute */
-  int          num_values;             /* Number of values */
-  _ipp_value_t values[1];              /* Values */
-};
-
-struct _ipp_s                          /**** IPP Request/Response/Notification ****/
-{
-  ipp_state_t          state;          /* State of request */
-  _ipp_request_t       request;        /* Request header */
-  ipp_attribute_t      *attrs;         /* Attributes */
-  ipp_attribute_t      *last;          /* Last attribute in list */
-  ipp_attribute_t      *current;       /* Current attribute (for read/write) */
-  ipp_tag_t            curtag;         /* Current attribute group tag */
-
-/**** New in CUPS 1.2 ****/
-  ipp_attribute_t      *prev;          /* Previous attribute (for read) @since CUPS 1.2/Mac OS X 10.5@ */
-
-/**** New in CUPS 1.4.4 ****/
-  int                  use;            /* Use count @since CUPS 1.4.4/Mac OS X 10.6.?@ */
-};
-
 typedef struct                         /**** Attribute mapping data ****/
 {
   int          multivalue;             /* Option has multiple values? */
index 362321a55392660cc62a999afaef3465592b7771..c20c110439cfb97a63a2aa5371dc3baa2a80eb99 100644 (file)
@@ -78,7 +78,11 @@ static const char * const ipp_status_oks[] = /* "OK" status codes */
                  "client-error-ignored-all-subscriptions",
                  "client-error-too-many-subscriptions",
                  "(client-error-ignored-all-notifications)",
-                 "(client-error-client-print-support-file-not-found)"
+                 "(client-error-client-print-support-file-not-found)",
+                 "client-error-document-password-error",
+                 "client-error-document-permission-error",
+                 "client-error-document-security-error",
+                 "client-error-document-unprintable-error"
                },
                * const ipp_status_500s[] =             /* Server errors */
                {
@@ -158,7 +162,7 @@ static const char * const ipp_std_ops[] =
                  "Suspend-Current-Job",
                  "Resume-Job",
 
-                 /* 0x0030 - 0x003b */
+                 /* 0x0030 - 0x003d */
                  "Promote-Job",
                  "Schedule-Job-After",
                  "0x32",
@@ -171,7 +175,8 @@ static const char * const ipp_std_ops[] =
                  "Cancel-My-Jobs",
                  "Resubmit-Job",
                  "Close-Job",
-                 "Identify-Printer"
+                 "Identify-Printer",
+                 "Validate-Document"
                },
                * const ipp_cups_ops[] =
                {
index 6b88d71de32409a888510e03e160cf7d30bd3fb2..ab5303c72fb4984ddf41169c1b018d42ef9d29a4 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Internet Printing Protocol functions for CUPS.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
  * Local functions...
  */
 
-static ipp_attribute_t *ipp_add_attr(ipp_t *ipp, const char *name, ipp_tag_t  group_tag,
-                                     ipp_tag_t value_tag, int num_values);
-static void            ipp_free_values(ipp_attribute_t *attr, int element, int count);
-static char            *ipp_get_code(const char *locale, char *buffer, size_t bufsize);
-static char            *ipp_lang_code(const char *locale, char *buffer, size_t bufsize);
+static ipp_attribute_t *ipp_add_attr(ipp_t *ipp, const char *name,
+                                     ipp_tag_t  group_tag, ipp_tag_t value_tag,
+                                     int num_values);
+static void            ipp_free_values(ipp_attribute_t *attr, int element,
+                                       int count);
+static char            *ipp_get_code(const char *locale, char *buffer,
+                                     size_t bufsize)
+                                     __attribute__((nonnull(1,2)));
+static char            *ipp_lang_code(const char *locale, char *buffer,
+                                      size_t bufsize)
+                                      __attribute__((nonnull(1,2)));
 static size_t          ipp_length(ipp_t *ipp, int collection);
 static ssize_t         ipp_read_http(http_t *http, ipp_uchar_t *buffer,
                                      size_t length);
 static ssize_t         ipp_read_file(int *fd, ipp_uchar_t *buffer,
                                      size_t length);
-static _ipp_value_t    *ipp_set_value(ipp_t *ipp, ipp_attribute_t **attr, int element);
+static _ipp_value_t    *ipp_set_value(ipp_t *ipp, ipp_attribute_t **attr,
+                                      int element);
 static ssize_t         ipp_write_file(int *fd, ipp_uchar_t *buffer,
                                       size_t length);
 
@@ -1058,14 +1065,17 @@ ippAddString(ipp_t      *ipp,           /* I - IPP message */
       attr->values[0].string.language = _cupsStrAlloc(ipp_lang_code(language, code,
                                                      sizeof(code)));
 
-    if (value_tag == IPP_TAG_CHARSET)
-      attr->values[0].string.text = _cupsStrAlloc(ipp_get_code(value, code,
-                                                               sizeof(code)));
-    else if (value_tag == IPP_TAG_LANGUAGE)
-      attr->values[0].string.text = _cupsStrAlloc(ipp_lang_code(value, code,
-                                                                sizeof(code)));
-    else
-      attr->values[0].string.text = _cupsStrAlloc(value);
+    if (value)
+    {
+      if (value_tag == IPP_TAG_CHARSET)
+       attr->values[0].string.text = _cupsStrAlloc(ipp_get_code(value, code,
+                                                                sizeof(code)));
+      else if (value_tag == IPP_TAG_LANGUAGE)
+       attr->values[0].string.text = _cupsStrAlloc(ipp_lang_code(value, code,
+                                                                 sizeof(code)));
+      else
+       attr->values[0].string.text = _cupsStrAlloc(value);
+    }
   }
 
   return (attr);
@@ -2467,7 +2477,7 @@ ippReadIO(void       *src,                /* I - Data source */
 
   DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
                 src, cb, blocking, parent, ipp));
-  DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp->state));
+  DEBUG_printf(("2ippReadIO: ipp->state=%d", ipp ? ipp->state : IPP_ERROR));
 
   if (!src || !ipp)
     return (IPP_ERROR);
@@ -5349,10 +5359,6 @@ ipp_read_http(http_t      *http, /* I - Client connection */
     }
     else
     {
-     /*
-      * Wait a maximum of 1 second for data...
-      */
-
       if (!http->blocking)
       {
        /*
index 950e4005c32ee8ca4048ea2a9cf3361239ed5d2e..d0556d363b115da7922ad18c58951bb5bf389e5b 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Internet Printing Protocol definitions for CUPS.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -188,6 +188,7 @@ typedef enum ipp_op_e                       /**** IPP operations ****/
   IPP_RESUBMIT_JOB,                    /* Resubmit-Job */
   IPP_CLOSE_JOB,                       /* Close-Job */
   IPP_IDENTIFY_PRINTER,                        /* Identify-Printer (proposed IPP JPS3) */
+  IPP_VALIDATE_DOCUMENT,               /* Validate-Document (proposed IPP JPS3) */
   IPP_PRIVATE = 0x4000,                        /* Reserved @private@ */
   CUPS_GET_DEFAULT,                    /* Get the default printer */
   CUPS_GET_PRINTERS,                   /* Get a list of printers and/or classes */
@@ -373,6 +374,129 @@ typedef ssize_t   (*ipp_iocb_t)(void *context, ipp_uchar_t *buffer, size_t bytes);
 typedef int (*ipp_copycb_t)(void *context, ipp_t *dst, ipp_attribute_t *attr);
 
 
+/*
+ * The following structures are PRIVATE starting with CUPS 1.6.  Please use the
+ * new accessor functions available in CUPS 1.6 and later, as these definitions
+ * will be moved to a private header file in a future release.
+ *
+ * Define _IPP_PRIVATE_STRUCTURES to cause the private IPP structures to be
+ * exposed in CUPS 1.6.
+ */
+
+#  if defined(_CUPS_SOURCE) || defined(_CUPS_IPP_PRIVATE_H_)
+     /* Building CUPS */
+#    define _IPP_PRIVATE_STRUCTURES 1
+#  elif defined(__APPLE__)
+#    if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
+       /* Building for 10.7 and earlier */
+#      define _IPP_PRIVATE_STRUCTURES 1
+#    elif !defined(MAC_OS_X_VERSION_10_8)
+       /* Building for 10.7 and earlier */
+#      define _IPP_PRIVATE_STRUCTURES 1
+#    endif /* MAC_OS_X_VERSION_10_8 && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 */
+#  endif /* _CUPS_SOURCE || _CUPS_IPP_PRIVATE_H_ */
+
+#  ifdef _IPP_PRIVATE_STRUCTURES
+typedef union _ipp_request_u           /**** Request Header ****/
+{
+  struct                               /* Any Header */
+  {
+    ipp_uchar_t        version[2];             /* Protocol version number */
+    int                op_status;              /* Operation ID or status code*/
+    int                request_id;             /* Request ID */
+  }            any;
+
+  struct                               /* Operation Header */
+  {
+    ipp_uchar_t        version[2];             /* Protocol version number */
+    ipp_op_t   operation_id;           /* Operation ID */
+    int                request_id;             /* Request ID */
+  }            op;
+
+  struct                               /* Status Header */
+  {
+    ipp_uchar_t        version[2];             /* Protocol version number */
+    ipp_status_t status_code;          /* Status code */
+    int                request_id;             /* Request ID */
+  }            status;
+
+  /**** New in CUPS 1.1.19 ****/
+  struct                               /* Event Header @since CUPS 1.1.19/Mac OS X 10.3@ */
+  {
+    ipp_uchar_t        version[2];             /* Protocol version number */
+    ipp_status_t status_code;          /* Status code */
+    int                request_id;             /* Request ID */
+  }            event;
+} _ipp_request_t;
+
+/**** New in CUPS 1.1.19 ****/
+
+typedef union _ipp_value_u             /**** Attribute Value ****/
+{
+  int          integer;                /* Integer/enumerated value */
+
+  char         boolean;                /* Boolean value */
+
+  ipp_uchar_t  date[11];               /* Date/time value */
+
+  struct
+  {
+    int                xres,                   /* Horizontal resolution */
+               yres;                   /* Vertical resolution */
+    ipp_res_t  units;                  /* Resolution units */
+  }            resolution;             /* Resolution value */
+
+  struct
+  {
+    int                lower,                  /* Lower value */
+               upper;                  /* Upper value */
+  }            range;                  /* Range of integers value */
+
+  struct
+  {
+    char       *language;              /* Language code */
+    char       *text;                  /* String */
+  }            string;                 /* String with language value */
+
+  struct
+  {
+    int                length;                 /* Length of attribute */
+    void       *data;                  /* Data in attribute */
+  }            unknown;                /* Unknown attribute type */
+
+/**** New in CUPS 1.1.19 ****/
+  ipp_t                *collection;            /* Collection value @since CUPS 1.1.19/Mac OS X 10.3@ */
+} _ipp_value_t;
+typedef _ipp_value_t ipp_value_t;      /**** Convenience typedef that will be removed @private@ ****/
+
+struct _ipp_attribute_s                        /**** Attribute ****/
+{
+  ipp_attribute_t *next;               /* Next attribute in list */
+  ipp_tag_t    group_tag,              /* Job/Printer/Operation group tag */
+               value_tag;              /* What type of value is it? */
+  char         *name;                  /* Name of attribute */
+  int          num_values;             /* Number of values */
+  _ipp_value_t values[1];              /* Values */
+};
+
+struct _ipp_s                          /**** IPP Request/Response/Notification ****/
+{
+  ipp_state_t          state;          /* State of request */
+  _ipp_request_t       request;        /* Request header */
+  ipp_attribute_t      *attrs;         /* Attributes */
+  ipp_attribute_t      *last;          /* Last attribute in list */
+  ipp_attribute_t      *current;       /* Current attribute (for read/write) */
+  ipp_tag_t            curtag;         /* Current attribute group tag */
+
+/**** New in CUPS 1.2 ****/
+  ipp_attribute_t      *prev;          /* Previous attribute (for read) @since CUPS 1.2/Mac OS X 10.5@ */
+
+/**** New in CUPS 1.4.4 ****/
+  int                  use;            /* Use count @since CUPS 1.4.4/Mac OS X 10.6.?@ */
+};
+#  endif /* _IPP_PRIVATE_STRUCTURES */
+
+
 /*
  * Prototypes...
  */
index 2e91ad9d4a16535bdccd7122befb570442f56b60..3e9db9ff80a903da4a87226480626de6dc776380 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   I18N/language support for CUPS.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -938,7 +938,23 @@ _cupsMessageLoad(const char *filename,     /* I - Message catalog to load */
       */
 
       if (m)
-        cupsArrayAdd(a, m);
+      {
+        if (m->str && m->str[0])
+        {
+          cupsArrayAdd(a, m);
+        }
+        else
+        {
+         /*
+          * Translation is empty, don't add it... (STR #4033)
+          */
+
+          free(m->id);
+          if (m->str)
+            free(m->str);
+          free(m);
+        }
+      }
 
      /*
       * Create a new message with the given msgid string...
@@ -968,6 +984,11 @@ _cupsMessageLoad(const char *filename,     /* I - Message catalog to load */
       if ((temp = realloc(m->str ? m->str : m->id,
                           length + strlen(ptr) + 1)) == NULL)
       {
+        if (m->str)
+         free(m->str);
+       free(m->id);
+        free(m);
+
        cupsFileClose(fp);
        return (a);
       }
@@ -1005,6 +1026,9 @@ _cupsMessageLoad(const char *filename,    /* I - Message catalog to load */
 
       if ((m->str = strdup(ptr)) == NULL)
       {
+       free(m->id);
+        free(m);
+
         cupsFileClose(fp);
        return (a);
       }
@@ -1016,7 +1040,23 @@ _cupsMessageLoad(const char *filename,   /* I - Message catalog to load */
   */
 
   if (m)
-    cupsArrayAdd(a, m);
+  {
+    if (m->str && m->str[0])
+    {
+      cupsArrayAdd(a, m);
+    }
+    else
+    {
+     /*
+      * Translation is empty, don't add it... (STR #4033)
+      */
+
+      free(m->id);
+      if (m->str)
+       free(m->str);
+      free(m);
+    }
+  }
 
  /*
   * Close the message catalog file and return the new array...
index cf34a00bd5dff9c2367701272d78eab656014f2f..d39bf14e5b2cd5ef8b87e7301c0643f8b03f1167 100644 (file)
@@ -753,12 +753,15 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)   /* I - PPD file */
     }
 
    /*
-    * 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.
+    * If we have a similar paper with non-zero margins then we only want to
+    * keep it if it has a larger imageable area length.  The NULL check is for
+    * dimensions that are <= 0...
     */
 
-    pwg_media      = _pwgMediaForSize(_PWG_FROMPTS(ppd_size->width),
-                                      _PWG_FROMPTS(ppd_size->length));
+    if ((pwg_media = _pwgMediaForSize(_PWG_FROMPTS(ppd_size->width),
+                                      _PWG_FROMPTS(ppd_size->length))) == NULL)
+      continue;
+
     new_width      = pwg_media->width;
     new_length     = pwg_media->length;
     new_left       = _PWG_FROMPTS(ppd_size->left);
index b3d4baeb8c6f0575641ca74832bd06be23e292f4..2c826ff1bae1e8d94234e1941400acf7ddbe20af 100644 (file)
@@ -462,8 +462,8 @@ _ppdOpen(
   ppd_attr_t           *custom_attr;   /* CustomFoo attribute */
   char                 ll[4],          /* Language + '.' */
                        ll_CC[7];       /* Language + country + '.' */
-  size_t               ll_len,         /* Language length */
-                       ll_CC_len;      /* Language + country length */
+  size_t               ll_len = 0,     /* Language length */
+                       ll_CC_len = 0;  /* Language + country length */
   static const char * const ui_keywords[] =
                        {
 #ifdef CUPS_USE_FULL_UI_KEYWORDS_LIST
index 2f9390fdda65647d4a43ce67a33af64ac1aca850..049340efc1d72df0e6b5c0c0d0bcd0d1f00306eb 100644 (file)
@@ -7,7 +7,7 @@
  *   -D_PPD_DEPRECATED="" TO YOUR COMPILE OPTIONS.  THIS HEADER AND THESE
  *   FUNCTIONS WILL BE REMOVED IN A FUTURE RELEASE OF CUPS.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -56,7 +56,19 @@ extern "C" {
  */
 
 #  ifndef _PPD_DEPRECATED
-#    define _PPD_DEPRECATED _CUPS_DEPRECATED
+#    if defined(__APPLE__)
+#      if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8
+         /* Building for 10.7 and earlier */
+#        define _PPD_DEPRECATED
+#      elif !defined(MAC_OS_X_VERSION_10_8)
+        /* Building for 10.7 and earlier */
+#        define _PPD_DEPRECATED
+#      else
+#        define _PPD_DEPRECATED _CUPS_DEPRECATED
+#      endif /* MAC_OS_X_VERSION_10_8 && MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_8 */
+#    else
+#      define _PPD_DEPRECATED _CUPS_DEPRECATED
+#    endif /* __APPLE__ */
 #  endif /* !_PPD_DEPRECATED */
 
 
index e99f57ff35451801c2fbe66eafa857b6ce584ef0..24528868cd5edcea8ae6a0ffc9724984a0bc56d2 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   PWG media name API implementation for CUPS.
  *
- *   Copyright 2009-2011 by Apple Inc.
+ *   Copyright 2009-2012 by Apple Inc.
  *
  *   These coded instructions, statements, and computer programs are the
  *   property of Apple Inc. and are protected by Federal copyright
index 9d004c39b31ff5e8b48de3161929e6e0142b57b0..b71f7ffb06e6c731f405af27773a9ddc560490e3 100644 (file)
@@ -643,11 +643,10 @@ cupsSendRequest(http_t     *http, /* I - Connection to server or @code CUPS_HTTP
   }
   else if (http->state != HTTP_WAITING)
   {
-    DEBUG_printf(("1cupsSendRequest: Unknown HTTP state (%d), bailing.",
-                  http->state));
-    _cupsSetError(IPP_INTERNAL_ERROR, strerror(EINVAL), 0);
-
-    return (HTTP_ERROR);
+    DEBUG_printf(("1cupsSendRequest: Unknown HTTP state (%d), "
+                  "reconnecting.", http->state));
+    if (httpReconnect(http))
+      return (HTTP_ERROR);
   }
 
 #ifdef HAVE_SSL
index da2f77a2be4df4ff5dac9c86c4217eda81fb947f..40091deca1aacd722bdd8d21b1e6db1ac5f091b6 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Side-channel API code for CUPS.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -150,7 +150,7 @@ cupsSideChannelRead(
   pfd.fd     = CUPS_SC_FD;
   pfd.events = POLLIN;
 
-  while ((nfds = poll(&pfd, 1, 
+  while ((nfds = poll(&pfd, 1,
                      timeout < 0.0 ? -1 : (long)(timeout * 1000))) < 0 &&
         (errno == EINTR || errno == EAGAIN))
     ;
@@ -162,14 +162,14 @@ cupsSideChannelRead(
   stimeout.tv_sec  = (int)timeout;
   stimeout.tv_usec = (int)(timeout * 1000000) % 1000000;
 
-  while ((nfds = select(CUPS_SC_FD + 1, &input_set, NULL, NULL, 
+  while ((nfds = select(CUPS_SC_FD + 1, &input_set, NULL, NULL,
                        timeout < 0.0 ? NULL : &stimeout)) < 0 &&
         (errno == EINTR || errno == EAGAIN))
     ;
 
 #endif /* HAVE_POLL */
 
-  if  (nfds < 1)
+  if (nfds < 1)
   {
     *command = CUPS_SC_CMD_NONE;
     *status  = nfds==0 ? CUPS_SC_STATUS_TIMEOUT : CUPS_SC_STATUS_IO_ERROR;
@@ -308,7 +308,7 @@ cupsSideChannelRead(
  * support SNMP queries.  @code CUPS_SC_STATUS_NO_RESPONSE@ is returned when
  * the printer does not respond to the SNMP query.
  *
- * @since CUPS 1.4/Mac OS X 10.6@ 
+ * @since CUPS 1.4/Mac OS X 10.6@
  */
 
 cups_sc_status_t                       /* O  - Query status */
@@ -414,7 +414,7 @@ cupsSideChannelSNMPGet(
  * support SNMP queries.  @code CUPS_SC_STATUS_NO_RESPONSE@ is returned when
  * the printer does not respond to the first SNMP query.
  *
- * @since CUPS 1.4/Mac OS X 10.6@ 
+ * @since CUPS 1.4/Mac OS X 10.6@
  */
 
 cups_sc_status_t                       /* O - Status of first query of @code CUPS_SC_STATUS_OK@ on success */
@@ -509,7 +509,7 @@ cupsSideChannelSNMPWalk(
       * Call the callback with the OID and data...
       */
 
-      (*cb)(real_data, real_data + real_oidlen, real_datalen, context); 
+      (*cb)(real_data, real_data + real_oidlen, real_datalen, context);
 
      /*
       * Update the current OID...
index 2c6d953719395b299a321baeb9f036a56fa52e21..fbd5467ab6189ae904eda6d42ceb7e96f0c5c1fd 100644 (file)
  */
 
 #define CUPS_SNMP_PORT         161     /* SNMP well-known port */
+#define CUPS_SNMP_MAX_COMMUNITY        512     /* Maximum size of community name */
 #define CUPS_SNMP_MAX_OID      128     /* Maximum number of OID numbers */
 #define CUPS_SNMP_MAX_PACKET   1472    /* Maximum size of SNMP packet */
-#define CUPS_SNMP_MAX_STRING   512     /* Maximum size of string */
+#define CUPS_SNMP_MAX_STRING   65536   /* Maximum size of string */
 #define CUPS_SNMP_VERSION_1    0       /* SNMPv1 */
 
 
@@ -84,7 +85,7 @@ typedef struct cups_snmp_s            /**** SNMP data packet ****/
   const char   *error;                 /* Encode/decode error */
   http_addr_t  address;                /* Source address */
   int          version;                /* Version number */
-  char         community[CUPS_SNMP_MAX_STRING];
+  char         community[CUPS_SNMP_MAX_COMMUNITY];
                                        /* Community name */
   cups_asn1_t  request_type;           /* Request type */
   int          request_id;             /* request-id value */
index 6f55f0ff42928811c9372e1e5e705d93891d9fbd..269c53ec3d31f93d4e6aa6facf2fae6128879d01 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   PPD constraint test program for CUPS.
  *
- *   Copyright 2008-2011 by Apple Inc.
+ *   Copyright 2008-2012 by Apple Inc.
  *
  *   These coded instructions, statements, and computer programs are the
  *   property of Apple Inc. and are protected by Federal copyright
@@ -91,7 +91,13 @@ main(int  argc,                              /* I - Number of command-line arguments */
     if (option)
     {
       free(option);
+      option = NULL;
+    }
+
+    if (choice)
+    {
       free(choice);
+      choice = NULL;
     }
 
     printf("\nNew Option(s): ");
@@ -118,6 +124,11 @@ main(int  argc,                            /* I - Number of command-line arguments */
     cupsFreeOptions(num_options, options);
   }
 
+  if (option)
+    free(option);
+  if (choice)
+    free(choice);
+
   return (0);
 }
 
index 8227f3e58eea4f13f4e613e5c03820f51650c5bb..e6fb06d0a405f8fcf55d5dda49f13d70925fb5cd 100644 (file)
@@ -1573,7 +1573,7 @@ cupsStartDocument(
   if ((request = ippNewRequest(IPP_SEND_DOCUMENT)) == NULL)
   {
     _cupsSetError(IPP_INTERNAL_ERROR, strerror(ENOMEM), 0);
-    return (0);
+    return (HTTP_ERROR);
   }
 
   httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
index b04021e9cc5a9d4d48f7a2213b73a2f9f3daff92..394be16cd779693aa833a4e6db8d6d04f53e2ca1 100644 (file)
@@ -595,7 +595,9 @@ are server-oriented...">http_state_t</a></li>
        <li><a href="#http_uri_status_t" title="URI separation status ">http_uri_status_t</a></li>
        <li><a href="#http_version_t" title="HTTP version numbers">http_version_t</a></li>
        <li><a href="#ipp_attribute_t" title="IPP attribute">ipp_attribute_t</a></li>
-       <li><a href="#ipp_copycb_t" title="Prototypes...">ipp_copycb_t</a></li>
+       <li><a href="#ipp_copycb_t" title="The following structures are PRIVATE starting with CUPS 1.6.  Please use the
+new accessor functions available in CUPS 1.6 and later, as these definitions
+will be moved to a private header file in a future release.">ipp_copycb_t</a></li>
        <li><a href="#ipp_dstate_t" title="Document states">ipp_dstate_t</a></li>
        <li><a href="#ipp_finish_t" title="Finishings">ipp_finish_t</a></li>
        <li><a href="#ipp_iocb_t" title="IPP IO Callback Function ">ipp_iocb_t</a></li>
@@ -647,7 +649,7 @@ are server-oriented...">http_state_e</a></li>
 
   HTTP and IPP API introduction for CUPS.
 
-  Copyright 2007-2011 by Apple Inc.
+  Copyright 2007-2012 by Apple Inc.
   Copyright 1997-2006 by Easy Software Products, all rights reserved.
 
   These coded instructions, statements, and computer programs are the
@@ -673,35 +675,20 @@ The constant <code>CUPS_HTTP_DEFAULT</code> can be used with all of the
 <code>cups</code> functions to refer to the default CUPS server - the functions
 create a per-thread <a href='#http_t'><code>http_t</code></a> as needed.</p>
 
-<p>The IPP APIs use two structures for requests (messages sent to the CUPS
-scheduler) and responses (messages sent back to your application from the
-scheduler). The <a href='#ipp_t'><code>ipp_t</code></a> structure holds a
-complete request or response and is allocated using the
-<a href='#ippNew'><code>ippNew</code></a> or
-<a href='#ippNewRequest'><code>ippNewRequest</code></a> functions and
-freed using the <a href='#ippDelete'><code>ippDelete</code></a> function.</p>
-
-<p>The second structure is called
-<a href='#ipp_attribute_t'><code>ipp_attribute_t</code></a> and holds a
-single IPP attribute which consists of a group tag (<code>group_tag</code>), a
-value type tag (<code>value_tag</code>), the attribute name (<code>name</code>),
-and 1 or more values (<code>values[]</code>). Attributes are added to an
-<a href='#ipp_t'><code>ipp_t</code></a> structure using one of the
-<code>ippAdd</code> functions. For example, use
-<a href='#ippAddString'><code>ippAddString</code></a> to add a
-"requesting-user-name" string attribute to a request:</p>
+<p>The IPP APIs use two opaque structures for requests (messages sent to the CUPS scheduler) and responses (messages sent back to your application from the scheduler). The <a href='#ipp_t'><code>ipp_t</code></a> type holds a complete request or response and is allocated using the <a href='#ippNew'><code>ippNew</code></a> or <a href='#ippNewRequest'><code>ippNewRequest</code></a> functions and freed using the <a href='#ippDelete'><code>ippDelete</code></a> function.</p>
+
+<p>The second opaque structure is called <a href='#ipp_attribute_t'><code>ipp_attribute_t</code></a> and holds a single IPP attribute which consists of a group tag (<a href='#ippGetGroupTag'><code>ippGetGroupTag</code></a>), a value type tag (<a href='#ippGetValueTag'><code>ippGetValueTag</code></a>), the attribute name (<a href='#ippGetName'><code>ippGetName</code></a>), and 1 or more values (<a href='#ippGetCount'><code>ippGetCount</code></a>, <a href='#ippGetBoolean'><code>ippGetBoolean</code></a>, <a href='#ippGetCollection'><code>ippGetCollection</code></a>, <a href='#ippGetDate'><code>ippGetDate</code></a>, <a href='#ippGetInteger'><code>ippGetInteger</code></a>, <a href='#ippGetRange'><code>ippGetRange</code></a>, <a href='#ippGetResolution'><code>ippGetResolution</code></a>, and <a href='#ippGetString'><code>ippGetString</code></a>). Attributes are added to an <a href='#ipp_t'><code>ipp_t</code></a> pointer using one of the <code>ippAdd</code> functions. For example, use <a href='#ippAddString'><code>ippAddString</code></a> to add the "printer-uri" and "requesting-user-name" string attributes to a request:</p>
 
 <pre class='example'>
 <a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(IPP_GET_JOBS);
 
+<a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+             NULL, "ipp://localhost/printers/");
 <a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
              NULL, cupsUser());
 </pre>
 
-<p>Once you have created an IPP request, use the <code>cups</code>
-functions to send the request to and read the response from the server.
-For example, the <a href='#cupsDoRequest'><code>cupsDoRequest</code></a>
-function can be used for simple query operations that do not involve files:</p>
+<p>Once you have created an IPP request, use the <code>cups</code> functions to send the request to and read the response from the server. For example, the <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function can be used for simple query operations that do not involve files:</p>
 
 <pre class='example'>
 #include &lt;cups/cups.h&gt;
@@ -711,6 +698,8 @@ function can be used for simple query operations that do not involve files:</p>
 {
   <a href='#ipp_t'>ipp_t</a> *request = <a href='#ippNewRequest'>ippNewRequest</a>(IPP_GET_JOBS);
 
+  <a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+               NULL, "ipp://localhost/printers/");
   <a href='#ippAddString'>ippAddString</a>(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name",
                NULL, cupsUser());
 
@@ -718,13 +707,7 @@ function can be used for simple query operations that do not involve files:</p>
 }
 </pre>
 
-<p>The <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function frees
-the request structure and returns an IPP response structure or NULL pointer if
-the request could not be sent to the server. Once you have a response from
-the server, you can either use the
-<a href='#ippFindAttribute'><code>ippFindAttribute</code></a> and
-<a href='#ippFindNextAttribute'><code>ippFindNextAttribute</code></a> functions
-to find specific attributes, for example:</p>
+<p>The <a href='#cupsDoRequest'><code>cupsDoRequest</code></a> function frees the request and returns an IPP response or <code>NULL</code> pointer if the request could not be sent to the server. Once you have a response from the server, you can either use the <a href='#ippFindAttribute'><code>ippFindAttribute</code></a> and <a href='#ippFindNextAttribute'><code>ippFindNextAttribute</code></a> functions to find specific attributes, for example:</p>
 
 <pre class='example'>
 <a href='#ipp_t'>ipp_t</a> *response;
@@ -733,25 +716,20 @@ to find specific attributes, for example:</p>
 attr = <a href='#ippFindAttribute'>ippFindAttribute</a>(response, "printer-state", IPP_TAG_ENUM);
 </pre>
 
-<p>You can also walk the list of attributes with a simple <code>for</code> loop
-like this:</p>
+<p>You can also walk the list of attributes with a simple <code>for</code> loop like this:</p>
 
 <pre class='example'>
 <a href='#ipp_t'>ipp_t</a> *response;
 <a href='#ipp_attribute_t'>ipp_attribute_t</a> *attr;
 
-for (attr = response->attrs; attr != NULL; attr = attr->next)
-  if (attr->name == NULL)
+for (attr = <a href='#ippFirstAttribute'>ippFirstAttribute</a>(response); attr != NULL; attr = <a href='#ippNextAttribute'>ippNextAttribute</a>(response))
+  if (ippGetName(attr) == NULL)
     puts("--SEPARATOR--");
   else
-    puts(attr->name);
+    puts(ippGetName(attr));
 </pre>
 
-<p>The <code>for</code> loop approach is normally used when collecting
-attributes for multiple objects (jobs, printers, etc.) in a response. Attributes
-with <code>NULL</code> names indicate a separator between the attributes of
-each object. For example, the following code will list the jobs returned from
-our previous <a href='#get_jobs'><code>get_jobs</code></a> example code:</p>
+<p>The <code>for</code> loop approach is normally used when collecting attributes for multiple objects (jobs, printers, etc.) in a response. Attributes with <code>NULL</code> names indicate a separator between the attributes of each object. For example, the following code will list the jobs returned from our previous <a href='#get_jobs'><code>get_jobs</code></a> example code:</p>
 
 <pre class='example'>
 <a href='#ipp_t'>ipp_t</a> *response = <a href='#get_jobs'>get_jobs</a>();
@@ -759,37 +737,55 @@ our previous <a href='#get_jobs'><code>get_jobs</code></a> example code:</p>
 if (response != NULL)
 {
   <a href='#ipp_attribute_t'>ipp_attribute_t</a> *attr;
+  const char *attrname;
   int job_id = 0;
-  char *job_name = NULL;
-  char *job_originating_user_name = NULL;
+  const char *job_name = NULL;
+  const char *job_originating_user_name = NULL;
 
   puts("Job ID  Owner             Title");
   puts("------  ----------------  ---------------------------------");
 
-  for (attr = response->attrs; attr != NULL; attr = attr->next)
+  for (attr = <a href='#ippFirstAttribute'>ippFirstAttribute</a>(response); attr != NULL; attr = <a href='#ippNextAttribute'>ippNextAttribute</a>(response))
   {
    /* Attributes without names are separators between jobs */
-    if (attr->name == NULL)
+    attrname = ippGetName(attr);
+    if (attrname == NULL)
     {
-      if (job_id > 0 &amp;&amp; job_name != NULL &amp;&amp; job_originating_user_name != NULL)
+      if (job_id > 0)
+      {
+        if (job_name == NULL)
+          job_name = "(withheld)";
+
+        if (job_originating_user_name == NULL)
+          job_originating_user_name = "(withheld)";
+
         printf("%5d  %-16s  %s\n", job_id, job_originating_user_name, job_name);
+      }
 
       job_id = 0;
       job_name = NULL;
       job_originating_user_name = NULL;
       continue;
     }
-    else if (!strcmp(attr->name, "job-id") &amp;&amp; attr->value_tag == IPP_TAG_INTEGER)
-      job_id = attr->values[0].integer;
-    else if (!strcmp(attr->name, "job-name") &amp;&amp; attr->value_tag == IPP_TAG_NAME)
-      job_name = attr->values[0].string.text;
-    else if (!strcmp(attr->name, "job-originating-user-name") &amp;&amp;
-             attr->value_tag == IPP_TAG_NAME)
-      job_originating_user_name = attr->values[0].string.text;
+    else if (!strcmp(attrname, "job-id") &amp;&amp; ippGetValueTag(attr) == IPP_TAG_INTEGER)
+      job_id = ippGetInteger(attr, 0);
+    else if (!strcmp(attrname, "job-name") &amp;&amp; ippGetValueTag(attr) == IPP_TAG_NAME)
+      job_name = ippGetString(attr, 0, NULL);
+    else if (!strcmp(attrname, "job-originating-user-name") &amp;&amp;
+             ippGetValueTag(attr) == IPP_TAG_NAME)
+      job_originating_user_name = ippGetString(attr, 0, NULL);
   }
 
-  if (job_id > 0 &amp;&amp; job_name != NULL &amp;&amp; job_originating_user_name != NULL)
+  if (job_id > 0)
+  {
+    if (job_name == NULL)
+      job_name = "(withheld)";
+
+    if (job_originating_user_name == NULL)
+      job_originating_user_name = "(withheld)";
+
     printf("%5d  %-16s  %s\n", job_id, job_originating_user_name, job_name);
+  }
 }
 </pre>
 
@@ -4640,7 +4636,9 @@ typedef enum <a href="#http_version_e">http_version_e</a> http_version_t;
 typedef struct _ipp_attribute_s ipp_attribute_t;
 </p>
 <h3 class="typedef"><a name="ipp_copycb_t">ipp_copycb_t</a></h3>
-<p class="description">Prototypes...</p>
+<p class="description">The following structures are PRIVATE starting with CUPS 1.6.  Please use the
+new accessor functions available in CUPS 1.6 and later, as these definitions
+will be moved to a private header file in a future release.</p>
 <p class="code">
 typedef int (*ipp_copycb_t)(void *context, <a href="#ipp_t">ipp_t</a> *dst, <a href="#ipp_attribute_t">ipp_attribute_t</a> *attr);
 </p>
@@ -5250,6 +5248,8 @@ are server-oriented...</p>
 <dd class="description">Add a file to a job</dd>
 <dt>IPP_SET_JOB_ATTRIBUTES </dt>
 <dd class="description">Set job attributes</dd>
+<dt>IPP_VALIDATE_DOCUMENT </dt>
+<dd class="description">Validate-Document (proposed IPP JPS3)</dd>
 <dt>IPP_VALIDATE_JOB </dt>
 <dd class="description">Validate job options</dd>
 </dl>
index 45877813986b11ab36a7153854f90e93cb617cba..e9c945b59b5fd207d747892a6335dcee851d4800 100644 (file)
@@ -1016,12 +1016,15 @@ void ~ppdcDriver (void);</p>
 <p class="description">// File</p>
 <p class="code">class ppdcFile {<br>
 &nbsp;&nbsp;public:<br>
+&nbsp;&nbsp;&nbsp;&nbsp;bool close_on_delete;<br>
 &nbsp;&nbsp;&nbsp;&nbsp;const char *filename;<br>
 &nbsp;&nbsp;&nbsp;&nbsp;cups_file_t *fp;<br>
 &nbsp;&nbsp;&nbsp;&nbsp;int line;<br>
 };</p>
 <h4 class="members">Members</h4>
 <dl>
+<dt>close_on_delete </dt>
+<dd class="description">Close file on delete?</dd>
 <dt>filename </dt>
 <dd class="description">Filename</dd>
 <dt>fp </dt>
index baab6fefba2bdd013ad03bfaa13efb4185756a4a..24b21335396a0e73a67c3bea2dacfeddea23f5c7 100644 (file)
@@ -336,16 +336,61 @@ matches or does not match.
 <dd>Requires the EXPECT attribute to have the same number of values as the specified
 parallel attribute.
 </dd>
+<dt>WITH-ALL-VALUES "literal string"
+</dt>
+<dd>Requires that all values of the EXPECT attribute match the literal string. Comparisons are case-sensitive.
+</dd>
+<dt>WITH-ALL-VALUES &lt;number
+</dt>
+<dd></dd>
+<dt>WITH-ALL-VALUES =number
+</dt>
+<dd></dd>
+<dt>WITH-ALL-VALUES >number
+</dt>
+<dd></dd>
+<dt>WITH-ALL-VALUES number[,number,...]
+</dt>
+<dd>Requires that all values of the EXPECT attribute match the number(s) or numeric comparison. When comparing rangeOfInteger values, the "&lt;" and ">" operators only check the upper bound of the range.
+</dd>
+<dt>WITH-ALL-VALUES "false"
+</dt>
+<dd></dd>
+<dt>WITH-ALL-VALUES "true"
+</dt>
+<dd>Requires that all values of the EXPECT attribute match the boolean value given.
+</dd>
+<dt>WITH-ALL-VALUES "/regular expression/"
+</dt>
+<dd>Requires that all values of the EXPECT attribute match the regular expression, which must conform to the POSIX regular expression syntax. Comparisons are case-sensitive.
+</dd>
 <dt>WITH-VALUE "literal string"
 </dt>
-<dd>Requires at least one value of the EXPECT attribute to match the literal string.
-Comparisons are case-sensitive.
+<dd>Requires that at least one value of the EXPECT attribute matches the literal string. Comparisons are case-sensitive.
+</dd>
+<dt>WITH-VALUE &lt;number
+</dt>
+<dd></dd>
+<dt>WITH-VALUE =number
+</dt>
+<dd></dd>
+<dt>WITH-VALUE >number
+</dt>
+<dd></dd>
+<dt>WITH-VALUE number[,number,...]
+</dt>
+<dd>Requires that at least one value of the EXPECT attribute matches the number(s) or numeric comparison. When comparing rangeOfInteger values, the "&lt;" and ">" operators only check the upper bound of the range.
+</dd>
+<dt>WITH-VALUE "false"
+</dt>
+<dd></dd>
+<dt>WITH-VALUE "true"
+</dt>
+<dd>Requires that at least one value of the EXPECT attribute matches the boolean value given.
 </dd>
 <dt>WITH-VALUE "/regular expression/"
 </dt>
-<dd>Requires that all values of the EXPECT attribute match the regular expression,
-which must conform to the POSIX regular expression syntax.
-Comparisons are case-sensitive.
+<dd>Requires that at least one value of the EXPECT attribute matches the regular expression, which must conform to the POSIX regular expression syntax. Comparisons are case-sensitive.
 
 </dd>
 </dl>
@@ -413,6 +458,7 @@ RFC 2911 and other IPP extension specifications. Here is a complete list:
     Get-Subscriptions
     Hold-Job
     Hold-New-Jobs
+    Identify-Printer
     Pause-Printer
     Pause-Printer-After-Current-Job
     Print-Job
@@ -437,6 +483,7 @@ RFC 2911 and other IPP extension specifications. Here is a complete list:
     Shutdown-Printer
     Startup-Printer
     Suspend-Current-Job
+    Validate-Document
     Validate-Job
 </pre>
 
@@ -454,6 +501,10 @@ Status codes correspond to the hexadecimal numbers (0xHHHH) and names from RFC
     client-error-document-access-error
     client-error-document-format-error
     client-error-document-format-not-supported
+    client-error-document-password-error
+    client-error-document-permission-error
+    client-error-document-security-error
+    client-error-document-unprintable-error
     client-error-forbidden
     client-error-gone
     client-error-ignored-all-notifications
@@ -601,7 +652,7 @@ no notify-subscription-id has been seen.
 <a href='http://localhost:631/help'>http://localhost:631/help</a>
 
 <h2 class="title"><a name="COPYRIGHT">Copyright</a></h2>
-Copyright 2007-2011 by Apple Inc.
+Copyright 2007-2012 by Apple Inc.
 
 </body>
 </html>
index 38f00d2a37295c34bcd61602c7a2b5df941ea842..ef666f32d85a6e4a0867a39692dfc3e2ea9daf78 100644 (file)
@@ -42,6 +42,12 @@ sudo launchctl load /System/Library/LaunchDaemons/org.cups.cupsd.plist
 <P>You can also edit this file from the CUPS web interface, which
 automatically handles restarting the scheduler.</P>
 
+<BLOCKQUOTE><B>Note:</B>
+
+<P>The specification of time units ("w" for weeks, "h" for hours, etc.) in the various time interval directives is new in CUPS 1.6. Prior releases of CUPS only supported time intervals in seconds.</P>
+
+</BLOCKQUOTE>
+
 
 <H2 CLASS="title"><A NAME="AccessLog">AccessLog</A></H2>
 
@@ -632,17 +638,19 @@ HREF="#Limit"><CODE>Limit</CODE></A> section.</P>
 <H3>Examples</H3>
 
 <PRE CLASS="command">
+DirtyCleanInterval 1w
+DirtyCleanInterval 1d
+DirtyCleanInterval 1h
+DirtyCleanInterval 1m
 DirtyCleanInterval 30
 DirtyCleanInterval 0
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>DirtyCleanInterval</CODE> directive specifies the number of
-seconds to wait before updating configuration and state files for printers,
-classes, subscriptions, and jobs. The default is 30 seconds. A value of 0
-causes the update to occur as soon as possible, typically within a few
-milliseconds.</P>
+<P>The <CODE>DirtyCleanInterval</CODE> directive specifies the amount of time to wait before updating configuration and state files for printers, classes, subscriptions, and jobs in seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix). A value of <CODE>0</CODE> causes the update to occur as soon as possible, typically within a few milliseconds.</P>
+
+<P>The default value is <CODE>30</CODE> (30 seconds).</P>
 
 
 <H2 CLASS="title"><A NAME="DocumentRoot">DocumentRoot</A></H2>
@@ -1011,7 +1019,7 @@ JobPrivateValues attribute-name-1 [ ... attribute-name-N ]
 
 <P>The <CODE>JobPrivateValues</CODE> directive specifies the list of job values
 to make private. The "default" values are "job-name",
-"job-originating-host-name", and "job-originating-user-name".</P>
+"job-originating-host-name", "job-originating-user-name", and "phone".</P>
 
 <P>The <CODE>JobPrivateValues</CODE> directive must appear inside a <A
 HREF="#Policy"><CODE>Policy</CODE></A> section.</P>
@@ -1022,17 +1030,18 @@ HREF="#Policy"><CODE>Policy</CODE></A> section.</P>
 <H3>Examples</H3>
 
 <PRE CLASS="command">
+JobRetryInterval 1w
+JobRetryInterval 1d
+JobRetryInterval 1h
+JobRetryInterval 1m
 JobRetryInterval 30
-JobRetryInterval 120
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>JobRetryInterval</CODE> directive specifies the
-number of seconds to wait before retrying a job. This is
-typically used for fax queues but can also be used with normal
-print queues whose error policy is <CODE>retry-job</CODE>. The
-default is 30 seconds.</P>
+<P>The <CODE>JobRetryInterval</CODE> directive specifies the amount of time to wait before retrying a job in seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix). This is typically used for fax queues but can also be used with normal print queues whose error policy is <CODE>retry-job</CODE> or <CODE>retry-current-job</CODE>.</P>
+
+<P>The default is <CODE>30</CODE> (30 seconds).</P>
 
 
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.4/Mac OS X 10.6</SPAN><A NAME="JobKillDelay">JobKillDelay</A></H2>
@@ -1040,15 +1049,18 @@ default is 30 seconds.</P>
 <H3>Examples</H3>
 
 <PRE CLASS="command">
+JobKillDelay 1w
+JobKillDelay 1d
+JobKillDelay 1h
+JobKillDelay 1m
 JobKillDelay 30
-JobKillDelay 120
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>JobKillDelay</CODE> directive specifies the number of seconds to
-wait before killing the filters and backend associated with a canceled or held
-job. The default is 30 seconds.</P>
+<P>The <CODE>JobKillDelay</CODE> directive specifies the amount of time to wait before killing the filters and backend associated with a canceled or held job in seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix).</P>
+
+<P>The default is <CODE>30</CODE> (30 seconds).</P>
 
 
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2/Mac OS X 10.5</SPAN><A NAME="JobRetryLimit">JobRetryLimit</A></H2>
@@ -1095,15 +1107,18 @@ field of each request.</P>
 <H3>Examples</H3>
 
 <PRE CLASS="command">
-KeepAliveTimeout 60
+KeepAliveTimeout 1w
+KeepAliveTimeout 1d
+KeepAliveTimeout 1h
+KeepAliveTimeout 1m
 KeepAliveTimeout 30
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>KeepAliveTimeout</CODE> directive controls how long
-a persistent HTTP connection will remain open after the last
-request. The default is 30 seconds.</P>
+<P>The <CODE>KeepAliveTimeout</CODE> directive controls how long a persistent HTTP connection will remain open after the last request in seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix).</P>
+
+<P>The default is <CODE>30</CODE> (30 seconds).</P>
 
 
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.7</SPAN><A NAME="Limit">Limit (Location)</A></H2>
@@ -1681,14 +1696,16 @@ copies to 100.</P>
 
 <PRE CLASS="command">
 MaxHoldTime 10800
+MaxHoldTime 3h
+MaxHoldTime 180m
 MaxHoldTime 0
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>MaxHoldTime</CODE> directive controls the maximum number of seconds allowed for a job to remain in the "indefinite" hold state. The job is canceled automatically if it remains held indefinitely longer than the specified number of seconds.</P>
+<P>The <CODE>MaxHoldTime</CODE> directive controls the maximum number of seconds allowed for a job to remain in the "indefinite" hold state. The job is canceled automatically if it remains held indefinitely longer than the specified time interval in seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix).</P>
 
-<p>The default setting is 0 which disables this functionality.</P>
+<p>The default setting is <CODE>0</CODE> which disables this functionality.</P>
 
 
 <H2 CLASS="title"><A NAME="MaxJobs">MaxJobs</A></H2>
@@ -1763,6 +1780,8 @@ default setting is 0.</P>
 
 <PRE CLASS="command">
 MaxJobTime 10800
+MaxJobTime 3h
+MaxJobTime 180m
 MaxJobTime 0
 </PRE>
 
@@ -1770,10 +1789,9 @@ MaxJobTime 0
 
 <P>The <CODE>MaxJobTime</CODE> directive controls the maximum number of
 seconds allowed for a job to complete printing before it is considered "stuck".
-The job is canceled automatically if it takes longer than the specified number of seconds to complete.</P>
+The job is canceled automatically if it takes longer than the specified time to complete in seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix).</P>
 
-<p>Setting the maximum time to 0 disables this functionality. The default
-setting is 10800 seconds (3 hours).</P>
+<p>Setting the maximum time to <CODE>0</CODE> disables this functionality. The default setting is <CODE>3h</CODE> (3 hours).</P>
 
 
 <H2 CLASS="title"><A NAME="MaxLogSize">MaxLogSize</A></H2>
@@ -1825,15 +1843,18 @@ directive instead.</P>
 <H3>Examples</H3>
 
 <PRE CLASS="command">
-MultipleOperationTimeout 60
+MultipleOperationTimeout 1w
+MultipleOperationTimeout 1d
+MultipleOperationTimeout 1h
+MultipleOperationTimeout 5m
 MultipleOperationTimeout 300
-MultipleOperationTimeout 86400
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>MultipleOperationTimeout</CODE> directive sets the maximum amount
-of time between files in a multi-file print job. The default is 300 seconds.</P>
+<P>The <CODE>MultipleOperationTimeout</CODE> directive sets the maximum amount of time between files in a multi-file print job in seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix).</P>
+
+<P>The default is <CODE>5m</CODE> (five minutes).</P>
 
 
 <H2 CLASS="title"><A NAME="Order">Order</A></H2>
@@ -2026,20 +2047,24 @@ the IPv4 and IPv6 wildcard address.</P>
 <PRE CLASS="command">
 PreserveJobHistory On
 PreserveJobHistory Off
+PreserveJobHistory 1w
+PreserveJobHistory 7d
+PreserveJobHistory 168h
+PreserveJobHistory 10080m
+PreserveJobHistory 604800
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>PreserveJobHistory</CODE> directive controls whether
-the history of completed, canceled, or aborted print jobs is
-stored on disk.</P>
+<P>The <CODE>PreserveJobHistory</CODE> directive controls whether the history of completed, canceled, or aborted print jobs is retained by the scheduler. A value of <CODE>On</CODE> preserves job information until the administrator purges it with the <CODE>cancel</CODE> command. A value of <CODE>Off</CODE> removes the job information as soon as each job is completed, canceled, or aborted. Numeric values preserve job information for the specified number of seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix).</P>
 
-<P>A value of <CODE>On</CODE> (the default) preserves job
-information until the administrator purges it with the
-<CODE>cancel</CODE> command.</P>
+<P>The default value is <CODE>On</CODE>.</P>
 
-<P>A value of <CODE>Off</CODE> removes the job information as
-soon as each job is completed, canceled, or aborted.</P>
+<BLOCKQUOTE><B>Note:</B>
+
+<P>The <A HREF="#MaxJobs"><CODE>MaxJobs</CODE></A>, <A HREF="#MaxJobsPerPrinter"><CODE>MaxJobsPerPrinter</CODE></A>, and <A HREF="#MaxJobsPerUser"><CODE>MaxJobsPerUser</CODE></A> directives can cause job history to be discarded to make room for new jobs.</P>
+
+</BLOCKQUOTE>
 
 
 <H2 CLASS="title"><A NAME="PreserveJobFiles">PreserveJobFiles</A></H2>
@@ -2049,21 +2074,26 @@ soon as each job is completed, canceled, or aborted.</P>
 <PRE CLASS="command">
 PreserveJobFiles On
 PreserveJobFiles Off
+PreserveJobFiles 1w
+PreserveJobFiles 7d
+PreserveJobFiles 168h
+PreserveJobFiles 10080m
+PreserveJobFiles 604800
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>PreserveJobFiles</CODE> directive controls whether
-the document files of completed, canceled, or aborted print jobs
-are stored on disk.</P>
+<P>The <CODE>PreserveJobFiles</CODE> directive controls whether the document files of completed, canceled, or aborted print jobs are retained. Jobs can be restarted (and reprinted) as desired until they are purged.</P>
+
+<P>A value of <CODE>On</CODE> preserves job files until the administrator purges them with the <CODE>cancel</CODE> command. A value of <CODE>Off</CODE> removes the job files as soon as each job is completed, canceled, or aborted. Numeric values preserve job files for the specified number of seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix).</P>
 
-<P>A value of <CODE>On</CODE> preserves job files until the
-administrator purges them with the <CODE>cancel</CODE> command.
-Jobs can be restarted (and reprinted) as desired until they are
-purged.</P>
+<P>The default value is <CODE>1d</CODE> (one day).</P>
 
-<P>A value of <CODE>Off</CODE> (the default) removes the job
-files as soon as each job is completed, canceled, or aborted.</P>
+<BLOCKQUOTE><B>Note:</B>
+
+<P>The <A HREF="#MaxJobs"><CODE>MaxJobs</CODE></A>, <A HREF="#MaxJobsPerPrinter"><CODE>MaxJobsPerPrinter</CODE></A>, <A HREF="#MaxJobsPerUser"><CODE>MaxJobsPerUser</CODE></A>, and <A HREF="#PreserveJobHistory"><CODE>PreserveJobHistory</CODE></A> directives can cause job files to be discarded sooner than specified.</P>
+
+</BLOCKQUOTE>
 
 
 <H2 CLASS="title"><A NAME="Printcap">Printcap</A></H2>
@@ -2239,17 +2269,18 @@ megabytes.</P>
 
 <PRE CLASS="command">
 RootCertDuration 0
+RootCertDuration 1w
+RootCertDuration 1d
+RootCertDuration 1h
+RootCertDuration 5m
 RootCertDuration 300
 </PRE>
 
 <H3>Description</H3>
 
-<P>The <CODE>RootCertDuration</CODE> directive specifies the
-number of seconds the <EM>root certificate</EM> remains valid.
-The scheduler will generate a new certificate as needed when the
-number of seconds has expired. If set to 0, the root certificate
-is generated only once on startup or on a restart. The default is
-300 seconds.</P>
+<P>The <CODE>RootCertDuration</CODE> directive specifies the amount of time the <EM>root certificate</EM> remains valid in seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix). The scheduler will generate a new certificate as needed when the given time interval has expired. If set to 0, the root certificate is generated only once on startup or on a restart.</P>
+
+<P>The default is <CODE>5m</CODE> (five minutes).</P>
 
 
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.1.7</SPAN><A NAME="Satisfy">Satisfy</A></H2>
@@ -2649,15 +2680,19 @@ an appropriate temporary directory called
 <H3>Examples</H3>
 
 <PRE CLASS="command">
+Timeout 1w
+Timeout 1d
+Timeout 1h
+Timeout 5m
 Timeout 300
-Timeout 90
 </PRE>
 
 <H3>Description</H3>
 
 <P>The <CODE>Timeout</CODE> directive controls the amount of time
-to wait before an active HTTP or IPP request times out. The
-default timeout is 300 seconds.</P>
+to wait before an active HTTP or IPP request times out in seconds (no suffix), minutes ("m" suffix), hours ("h" suffix), days ("d" suffix), or weeks ("w" suffix).</P>
+
+<P>The default timeout is <CODE>5m</CODE> (five minutes).</P>
 
 
 <H2 CLASS="title"><SPAN CLASS="info">CUPS 1.2/Mac OS X 10.5</SPAN><A NAME="UseNetworkDefault">UseNetworkDefault</A></H2>
index 4521543bc5314c835645b650a49b60bbecf5d40c..d291b49ed281b404f4a947d4372365f904d4bbad 100644 (file)
@@ -423,6 +423,7 @@ div.contents ul.subcontents li {
        <li><a href="#cupsSingleFile">cupsSingleFile</a></li>
        <li><a href="#cupsSNMPSupplies">cupsSNMPSupplies</a></li>
        <li><a href="#cupsVersion">cupsVersion</a></li>
+       <li><a href="#JCLToPDFInterpreter">JCLToPDFInterpreter</a></li>
 </ul></li>
 <li><a href="#MACOSX">Mac OS X Attributes</a><ul class="subcontents">
        <li><a href="#APDialogExtension">APDialogExtension</a></li>
@@ -1921,7 +1922,7 @@ the standard SNMP Printer MIB OIDs for supply levels. The default value is
 
 <p>This required keyword describes which version of the CUPS
 PPD file extensions was used. Currently it must be the string
-"1.0", "1.1", "1.2", or "1.3".</p>
+"1.0", "1.1", "1.2", "1.3", "1.4", "1.5", or "1.6".</p>
 
 <p>Example:</p>
 
@@ -1931,6 +1932,20 @@ PPD file extensions was used. Currently it must be the string
 </pre>
 
 
+<h3><span class="info">CUPS 1.6</span><a name="JCLToPDFInterpreter">JCLToPDFInterpreter</a></h3>
+
+<p class="summary">*JCLToPDFInterpreter: "JCL"</p>
+
+<p>This keyword provfides the JCL command to insert a PDF job file into a printer-ready data stream. The JCL command is added after the <tt>JCLBegin</tt> value and any commands for JCL options in the PPD file.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% PJL command to start the PDF interpreter</em>
+*JCLToPDFInterpreter: "@PJL ENTER LANGUAGE = PDF&lt;0A&gt;"
+</pre>
+
+
 <h2 class='title'><a name='MACOSX'>Mac OS X Attributes</a></h2>
 
 <h3><span class='info'>Mac OS X 10.3</span><a name='APDialogExtension'>APDialogExtension</a></h3>
@@ -2223,6 +2238,10 @@ the device.</p>
 
        <li>Added <a href="#cupsMaxCopies"><tt>cupsMaxCopies</tt></a> keyword.</li>
 
+       <li>Documented <a href="#JCLToPDFInterpreter"><tt>JCLToPDFInterpreter</tt></a> keyword.</li>
+
+       <li>Updated <a href="#cupsVersion"><tt>cupsVersion</tt></a> keyword documentation to list all current releases of CUPS.</li>
+
 </ul>
 
 
index 62bee6bdbe9b5d18f5c8567c1137c2241257a68b..03f23e9f990fcf2955da11d3d045909ace294167 100644 (file)
@@ -100,7 +100,7 @@ HEIGHT="128" ALT="CUPS"></A></TD>
 </TD></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR><TD CLASS="trailer">CUPS and the CUPS logo are trademarks of
-<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007-2011 Apple
+<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007-2012 Apple
 Inc. All rights reserved.</TD></TR>
 </TABLE>
 </BODY>
index 467d3d09250b66e6dc1035def6ca175948f7f78a..e49a443b65dbb1ae65a9b1a4a8d6a6045ed07ef1 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   PostScript command filter for CUPS.
  *
- *   Copyright 2008-2011 by Apple Inc.
+ *   Copyright 2008-2012 by Apple Inc.
  *
  *   These coded instructions, statements, and computer programs are the
  *   property of Apple Inc. and are protected by Federal copyright
@@ -36,7 +36,7 @@
  * Local functions...
  */
 
-static void    auto_configure(ppd_file_t *ppd, const char *user);
+static int     auto_configure(ppd_file_t *ppd, const char *user);
 static void    begin_ps(ppd_file_t *ppd, const char *user);
 static void    end_ps(ppd_file_t *ppd);
 static void    print_self_test_page(ppd_file_t *ppd, const char *user);
@@ -51,6 +51,7 @@ int                                   /* O - Exit status */
 main(int  argc,                                /* I - Number of command-line arguments */
      char *argv[])                     /* I - Command-line arguments */
 {
+  int          status = 0;             /* Exit status */
   cups_file_t  *fp;                    /* Command file */
   char         line[1024],             /* Line from file */
                *value;                 /* Value on line */
@@ -113,16 +114,20 @@ main(int  argc,                           /* I - Number of command-line arguments */
     */
 
     if (!_cups_strcasecmp(line, "AutoConfigure"))
-      auto_configure(ppd, argv[2]);
+      status |= auto_configure(ppd, argv[2]);
     else if (!_cups_strcasecmp(line, "PrintSelfTestPage"))
       print_self_test_page(ppd, argv[2]);
     else if (!_cups_strcasecmp(line, "ReportLevels"))
       report_levels(ppd, argv[2]);
     else
-      fprintf(stderr, "ERROR: Invalid printer command \"%s\"!\n", line);
+    {
+      _cupsLangPrintFilter(stderr, "ERROR",
+                           _("Invalid printer command \"%s\"."), line);
+      status = 1;
+    }
   }
 
-  return (0);
+  return (status);
 }
 
 
@@ -131,12 +136,14 @@ main(int  argc,                           /* I - Number of command-line arguments */
  *                      query commands and/or SNMP lookups.
  */
 
-static void
+static int                             /* O - Exit status */
 auto_configure(ppd_file_t *ppd,                /* I - PPD file */
                const char *user)       /* I - Printing user */
 {
+  int          status = 0;             /* Exit status */
   ppd_option_t *option;                /* Current option in PPD */
   ppd_attr_t   *attr;                  /* Query command attribute */
+  const char   *valptr;                /* Pointer into attribute value */
   char         buffer[1024],           /* String buffer */
                *bufptr;                /* Pointer into buffer */
   ssize_t      bytes;                  /* Number of bytes read */
@@ -154,7 +161,7 @@ auto_configure(ppd_file_t *ppd,             /* I - PPD file */
   {
     fputs("DEBUG: Unable to auto-configure PostScript Printer - no "
           "bidirectional I/O available!\n", stderr);
-    return;
+    return (1);
   }
 
  /*
@@ -162,6 +169,25 @@ auto_configure(ppd_file_t *ppd,            /* I - PPD file */
   */
 
   begin_ps(ppd, user);
+
+ /*
+  * (STR #4028)
+  *
+  * As a lot of PPDs contain bad PostScript query code, we need to prevent one
+  * bad query sequence from affecting all auto-configuration.  The following
+  * error handler allows us to log PostScript errors to cupsd.
+  */
+
+  puts("/cups_handleerror {\n"
+       "  $error /newerror false put\n"
+       "  (:PostScript error in \") print cups_query_keyword print (\": ) "
+       "print\n"
+       "  $error /errorname get 128 string cvs print\n"
+       "  (; offending command:) print $error /command get 128 string cvs "
+       "print (\n) print flush\n"
+       "} bind def\n"
+       "errordict /timeout {} put\n"
+       "/cups_query_keyword (?Unknown) def\n");
   fflush(stdout);
 
  /*
@@ -202,7 +228,76 @@ auto_configure(ppd_file_t *ppd,            /* I - PPD file */
     */
 
     fprintf(stderr, "DEBUG: Querying %s...\n", option->keyword);
-    fputs(attr->value, stdout);
+
+    for (bufptr = buffer, valptr = attr->value; *valptr; valptr ++)
+    {
+     /*
+      * Log the query code, breaking at newlines...
+      */
+
+      if (*valptr == '\n')
+      {
+        *bufptr = '\0';
+        fprintf(stderr, "DEBUG: %s\\n\n", buffer);
+        bufptr = buffer;
+      }
+      else if (*valptr < ' ')
+      {
+        if (bufptr >= (buffer + sizeof(buffer) - 4))
+        {
+         *bufptr = '\0';
+         fprintf(stderr, "DEBUG: %s\n", buffer);
+         bufptr = buffer;
+        }
+
+        if (*valptr == '\r')
+        {
+          *bufptr++ = '\\';
+          *bufptr++ = 'r';
+        }
+        else if (*valptr == '\t')
+        {
+          *bufptr++ = '\\';
+          *bufptr++ = 't';
+        }
+        else
+        {
+          *bufptr++ = '\\';
+          *bufptr++ = '0' + ((*valptr / 64) & 7);
+          *bufptr++ = '0' + ((*valptr / 8) & 7);
+          *bufptr++ = '0' + (*valptr & 7);
+        }
+      }
+      else
+      {
+        if (bufptr >= (buffer + sizeof(buffer) - 1))
+        {
+         *bufptr = '\0';
+         fprintf(stderr, "DEBUG: %s\n", buffer);
+         bufptr = buffer;
+        }
+
+       *bufptr++ = *valptr;
+      }
+    }
+
+    if (bufptr > buffer)
+    {
+      *bufptr = '\0';
+      fprintf(stderr, "DEBUG: %s\n", buffer);
+    }
+
+    printf("/cups_query_keyword (?%s) def\n", option->keyword);
+                                       /* Set keyword for error reporting */
+    fputs("{ (", stdout);
+    for (valptr = attr->value; *valptr; valptr ++)
+    {
+      if (*valptr == '(' || *valptr == ')' || *valptr == '\\')
+        putchar('\\');
+      putchar(*valptr);
+    }
+    fputs(") cvx exec } stopped { cups_handleerror } if clear\n", stdout);
+                                       /* Send query code */
     fflush(stdout);
 
     datalen = 0;
@@ -212,53 +307,119 @@ auto_configure(ppd_file_t *ppd,          /* I - PPD file */
     * Read the response data...
     */
 
-    while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer) - 1, 90.0)) > 0)
+    bufptr    = buffer;
+    buffer[0] = '\0';
+    while ((bytes = cupsBackChannelRead(bufptr,
+                                       sizeof(buffer) - (bufptr - buffer) - 1,
+                                       10.0)) > 0)
     {
      /*
-      * Trim whitespace from both ends...
+      * No newline at the end? Go on reading ...
       */
 
-      buffer[bytes] = '\0';
+      bufptr += bytes;
+      *bufptr = '\0';
+
+      if (bytes == 0 ||
+          (bufptr > buffer && bufptr[-1] != '\r' && bufptr[-1] != '\n'))
+       continue;
 
-      for (bufptr = buffer + bytes - 1; bufptr >= buffer; bufptr --)
-        if (isspace(*bufptr & 255))
+     /*
+      * Trim whitespace and control characters from both ends...
+      */
+
+      bytes = bufptr - buffer;
+
+      for (bufptr --; bufptr >= buffer; bufptr --)
+        if (isspace(*bufptr & 255) || iscntrl(*bufptr & 255))
          *bufptr = '\0';
        else
          break;
 
-      for (bufptr = buffer; isspace(*bufptr & 255); bufptr ++);
+      for (bufptr = buffer; isspace(*bufptr & 255) || iscntrl(*bufptr & 255);
+          bufptr ++);
+
+      if (bufptr > buffer)
+      {
+        _cups_strcpy(buffer, bufptr);
+       bufptr = buffer;
+      }
 
-      fprintf(stderr, "DEBUG: Got \"%s\" (%d bytes)\n", bufptr, (int)bytes);
+      fprintf(stderr, "DEBUG: Got %d bytes.\n", (int)bytes);
 
      /*
       * Skip blank lines...
       */
 
-      if (!*bufptr)
+      if (!buffer[0])
         continue;
 
+     /*
+      * Check the response...
+      */
+
+      if ((bufptr = strchr(buffer, ':')) != NULL)
+      {
+       /*
+        * PostScript code for this option in the PPD is broken; show the
+        * interpreter's error message that came back...
+        */
+
+       fprintf(stderr, "DEBUG%s\n", bufptr);
+       break;
+      }
+
      /*
       * Verify the result is a valid option choice...
       */
 
-      if (!ppdFindChoice(option, bufptr))
+      if (!ppdFindChoice(option, buffer))
+      {
+       if (!strcasecmp(buffer, "Unknown"))
+         break;
+
+       bufptr    = buffer;
+       buffer[0] = '\0';
         continue;
+      }
 
      /*
       * Write out the result and move on to the next option...
       */
 
-      fprintf(stderr, "DEBUG: Default%s=%s\n", option->keyword, bufptr);
-      fprintf(stderr, "PPD: Default%s=%s\n", option->keyword, bufptr);
+      fprintf(stderr, "PPD: Default%s=%s\n", option->keyword, buffer);
       break;
     }
+
+   /*
+    * Printer did not answer this option's query
+    */
+
+    if (bytes <= 0)
+    {
+      fprintf(stderr,
+             "DEBUG: No answer to query for option %s within 10 seconds.\n",
+             option->keyword);
+      status = 1;
+    }
   }
 
  /*
   * Finish the job...
   */
 
+  fflush(stdout);
   end_ps(ppd);
+
+ /*
+  * Return...
+  */
+
+  if (status)
+    _cupsLangPrintFilter(stderr, "WARNING",
+                         _("Unable to configure printer options."));
+
+  return (0);
 }
 
 
@@ -280,6 +441,7 @@ begin_ps(ppd_file_t *ppd,           /* I - PPD file */
 
   puts("%!");
   puts("userdict dup(\\004)cvn{}put (\\004\\004)cvn{}put\n");
+
   fflush(stdout);
 }
 
@@ -319,7 +481,12 @@ print_self_test_page(ppd_file_t *ppd,      /* I - PPD file */
   * the product/interpreter information...
   */
 
-  puts("% You are using the wrong driver for your printer!\n"
+  puts("\r%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+       "%%%%%%%%%%%%%\n"
+       "\r%%%% If you can read this, you are using the wrong driver for your "
+       "printer. %%%%\n"
+       "\r%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%"
+       "%%%%%%%%%%%%%\n"
        "0 setgray\n"
        "2 setlinewidth\n"
        "initclip newpath clippath gsave stroke grestore pathbbox\n"
index 6daa361fe5e48bd9543aedcf9b8cd0d6459b1a4d..5ef9f6a40ba667ea633c29c8ddc0c93d5787a9f1 100644 (file)
@@ -1481,7 +1481,7 @@ the standard SNMP Printer MIB OIDs for supply levels. The default value is
 
 <p>This required keyword describes which version of the CUPS
 PPD file extensions was used. Currently it must be the string
-"1.0", "1.1", "1.2", or "1.3".</p>
+"1.0", "1.1", "1.2", "1.3", "1.4", "1.5", or "1.6".</p>
 
 <p>Example:</p>
 
@@ -1491,6 +1491,20 @@ PPD file extensions was used. Currently it must be the string
 </pre>
 
 
+<h3><span class="info">CUPS 1.6</span><a name="JCLToPDFInterpreter">JCLToPDFInterpreter</a></h3>
+
+<p class="summary">*JCLToPDFInterpreter: "JCL"</p>
+
+<p>This keyword provfides the JCL command to insert a PDF job file into a printer-ready data stream. The JCL command is added after the <tt>JCLBegin</tt> value and any commands for JCL options in the PPD file.</p>
+
+<p>Example:</p>
+
+<pre class='command'>
+<em>*% PJL command to start the PDF interpreter</em>
+*JCLToPDFInterpreter: "@PJL ENTER LANGUAGE = PDF&lt;0A&gt;"
+</pre>
+
+
 <h2 class='title'><a name='MACOSX'>Mac OS X Attributes</a></h2>
 
 <h3><span class='info'>Mac OS X 10.3</span><a name='APDialogExtension'>APDialogExtension</a></h3>
@@ -1783,6 +1797,10 @@ the device.</p>
 
        <li>Added <a href="#cupsMaxCopies"><tt>cupsMaxCopies</tt></a> keyword.</li>
 
+       <li>Documented <a href="#JCLToPDFInterpreter"><tt>JCLToPDFInterpreter</tt></a> keyword.</li>
+
+       <li>Updated <a href="#cupsVersion"><tt>cupsVersion</tt></a> keyword documentation to list all current releases of CUPS.</li>
+
 </ul>
 
 
index 712bfc75824edf7676d4a336374bcdb471130bf8..bd8f459c75dec8f018235c3b3554823cb13ff225 100755 (executable)
@@ -4,7 +4,7 @@
 #
 # Install a program, script, or datafile.
 #
-# Copyright 2008-2009 by Apple Inc.
+# Copyright 2008-2012 by Apple Inc.
 #
 # This script is not compatible with BSD (or any other) install program, as it
 # allows owner and group changes to fail with a warning and makes sure that the
@@ -46,6 +46,7 @@ chgrpprog="${CHGRPPROG-chgrp}"
 stripprog="${STRIPPROG-strip}"
 rmprog="${RMPROG-rm}"
 mkdirprog="${MKDIRPROG-mkdir}"
+gzipprog="${GZIPPROG-gzip}"
 
 transformbasename=""
 transform_arg=""
@@ -60,6 +61,11 @@ src=""
 dst=""
 dir_arg=""
 
+function gzipcp {
+       # gzipcp from to
+       $gzipprog -9 <"$1" >"$2"
+}
+
 while [ x"$1" != x ]; do
        case $1 in
                -c)
@@ -101,6 +107,12 @@ while [ x"$1" != x ]; do
                continue
                ;;
 
+               -z)
+               instcmd="gzipcp"
+               shift
+               continue
+               ;;
+
                *)
                if [ x"$src" = x ]; then
                        src="$1"
@@ -121,7 +133,7 @@ fi
 if [ x"$dir_arg" != x ]; then
        dst="$src"
        src=""
-       
+
        if [ -d "$dst" ]; then
                instcmd=:
        else
@@ -129,13 +141,13 @@ if [ x"$dir_arg" != x ]; then
        fi
 else
        # Waiting for this to be detected by the "$instcmd $src $dsttmp" command
-       # might cause directories to be created, which would be especially bad 
+       # might cause directories to be created, which would be especially bad
        # if $src (and thus $dsttmp) contains '*'.
        if [ ! -f "$src" -a ! -d "$src" ]; then
                echo "install: $src does not exist"
                exit 1
        fi
-       
+
        if [ x"$dst" = x ]; then
                echo "install: No destination specified"
                exit 1
index ce1453865fb16835dd6f0864f48a2acc0490638d..c4a83b114c4a21b10dc3247b512249ddbc538743 100644 (file)
@@ -30,11 +30,10 @@ msgid ""
 msgstr ""
 "Project-Id-Version: CUPS 1.6\n"
 "Report-Msgid-Bugs-To: http://www.cups.org/str.php\n"
-"POT-Creation-Date: 2012-02-13 09:00-0800\n"
+"POT-Creation-Date: 2012-03-07 13:37-0800\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
-"Language: \n"
 "MIME-Version: 1.0\n"
 "Content-Type: text/plain; charset=CHARSET\n"
 "Content-Transfer-Encoding: 8bit\n"
@@ -192,61 +191,61 @@ msgstr ""
 msgid "\treason unknown"
 msgstr ""
 
-#: systemv/cupstestppd.c:436
+#: systemv/cupstestppd.c:454
 msgid ""
 "\n"
 "    DETAILED CONFORMANCE TEST RESULTS"
 msgstr ""
 
-#: systemv/cupstestppd.c:3780
+#: systemv/cupstestppd.c:3799
 msgid "                          Ignore specific warnings."
 msgstr ""
 
-#: systemv/cupstestppd.c:3784
+#: systemv/cupstestppd.c:3803
 msgid "                          Issue warnings instead of errors."
 msgstr ""
 
-#: systemv/cupstestppd.c:392 systemv/cupstestppd.c:397
+#: systemv/cupstestppd.c:410 systemv/cupstestppd.c:415
 msgid "                REF: Page 15, section 3.1."
 msgstr ""
 
-#: systemv/cupstestppd.c:387
+#: systemv/cupstestppd.c:405
 msgid "                REF: Page 15, section 3.2."
 msgstr ""
 
-#: systemv/cupstestppd.c:407
+#: systemv/cupstestppd.c:425
 msgid "                REF: Page 19, section 3.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:360
+#: systemv/cupstestppd.c:378
 msgid "                REF: Page 20, section 3.4."
 msgstr ""
 
-#: systemv/cupstestppd.c:412
+#: systemv/cupstestppd.c:430
 msgid "                REF: Page 27, section 3.5."
 msgstr ""
 
-#: systemv/cupstestppd.c:355
+#: systemv/cupstestppd.c:373
 msgid "                REF: Page 42, section 5.2."
 msgstr ""
 
-#: systemv/cupstestppd.c:402
+#: systemv/cupstestppd.c:420
 msgid "                REF: Pages 16-17, section 3.2."
 msgstr ""
 
-#: systemv/cupstestppd.c:372
+#: systemv/cupstestppd.c:390
 msgid "                REF: Pages 42-45, section 5.2."
 msgstr ""
 
-#: systemv/cupstestppd.c:366
+#: systemv/cupstestppd.c:384
 msgid "                REF: Pages 45-46, section 5.2."
 msgstr ""
 
-#: systemv/cupstestppd.c:377
+#: systemv/cupstestppd.c:395
 msgid "                REF: Pages 48-49, section 5.2."
 msgstr ""
 
-#: systemv/cupstestppd.c:382
+#: systemv/cupstestppd.c:400
 msgid "                REF: Pages 52-54, section 5.2."
 msgstr ""
 
@@ -255,147 +254,147 @@ msgstr ""
 msgid "        %-39.39s %.0f bytes"
 msgstr ""
 
-#: systemv/cupstestppd.c:571
+#: systemv/cupstestppd.c:589
 #, c-format
 msgid "        PASS    Default%s"
 msgstr ""
 
-#: systemv/cupstestppd.c:506
+#: systemv/cupstestppd.c:524
 msgid "        PASS    DefaultImageableArea"
 msgstr ""
 
-#: systemv/cupstestppd.c:540
+#: systemv/cupstestppd.c:558
 msgid "        PASS    DefaultPaperDimension"
 msgstr ""
 
-#: systemv/cupstestppd.c:613
+#: systemv/cupstestppd.c:631
 msgid "        PASS    FileVersion"
 msgstr ""
 
-#: systemv/cupstestppd.c:657
+#: systemv/cupstestppd.c:675
 msgid "        PASS    FormatVersion"
 msgstr ""
 
-#: systemv/cupstestppd.c:677
+#: systemv/cupstestppd.c:695
 msgid "        PASS    LanguageEncoding"
 msgstr ""
 
-#: systemv/cupstestppd.c:697
+#: systemv/cupstestppd.c:715
 msgid "        PASS    LanguageVersion"
 msgstr ""
 
-#: systemv/cupstestppd.c:749
+#: systemv/cupstestppd.c:767
 msgid "        PASS    Manufacturer"
 msgstr ""
 
-#: systemv/cupstestppd.c:789
+#: systemv/cupstestppd.c:807
 msgid "        PASS    ModelName"
 msgstr ""
 
-#: systemv/cupstestppd.c:809
+#: systemv/cupstestppd.c:827
 msgid "        PASS    NickName"
 msgstr ""
 
-#: systemv/cupstestppd.c:869
+#: systemv/cupstestppd.c:887
 msgid "        PASS    PCFileName"
 msgstr ""
 
-#: systemv/cupstestppd.c:944
+#: systemv/cupstestppd.c:962
 msgid "        PASS    PSVersion"
 msgstr ""
 
-#: systemv/cupstestppd.c:849
+#: systemv/cupstestppd.c:867
 msgid "        PASS    PageRegion"
 msgstr ""
 
-#: systemv/cupstestppd.c:829
+#: systemv/cupstestppd.c:847
 msgid "        PASS    PageSize"
 msgstr ""
 
-#: systemv/cupstestppd.c:904
+#: systemv/cupstestppd.c:922
 msgid "        PASS    Product"
 msgstr ""
 
-#: systemv/cupstestppd.c:979
+#: systemv/cupstestppd.c:997
 msgid "        PASS    ShortNickName"
 msgstr ""
 
-#: systemv/cupstestppd.c:1354
+#: systemv/cupstestppd.c:1372
 #, c-format
 msgid "        WARN    %s has no corresponding options."
 msgstr ""
 
-#: systemv/cupstestppd.c:1466
+#: systemv/cupstestppd.c:1484
 #, c-format
 msgid ""
 "        WARN    %s shares a common prefix with %s\n"
 "                REF: Page 15, section 3.2."
 msgstr ""
 
-#: systemv/cupstestppd.c:1325
+#: systemv/cupstestppd.c:1343
 #, c-format
 msgid ""
 "        WARN    Duplex option keyword %s may not work as expected and should be named Duplex.\n"
 "                REF: Page 122, section 5.17"
 msgstr ""
 
-#: systemv/cupstestppd.c:1724
+#: systemv/cupstestppd.c:1742
 msgid "        WARN    File contains a mix of CR, LF, and CR LF line endings."
 msgstr ""
 
-#: systemv/cupstestppd.c:1370
+#: systemv/cupstestppd.c:1388
 msgid ""
 "        WARN    LanguageEncoding required by PPD 4.3 spec.\n"
 "                REF: Pages 56-57, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:1706
+#: systemv/cupstestppd.c:1724
 #, c-format
 msgid "        WARN    Line %d only contains whitespace."
 msgstr ""
 
-#: systemv/cupstestppd.c:1378
+#: systemv/cupstestppd.c:1396
 msgid ""
 "        WARN    Manufacturer required by PPD 4.3 spec.\n"
 "                REF: Pages 58-59, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:1729
+#: systemv/cupstestppd.c:1747
 msgid "        WARN    Non-Windows PPD files should use lines ending with only LF, not CR LF."
 msgstr ""
 
-#: systemv/cupstestppd.c:1362
+#: systemv/cupstestppd.c:1380
 #, c-format
 msgid ""
 "        WARN    Obsolete PPD version %.1f.\n"
 "                REF: Page 42, section 5.2."
 msgstr ""
 
-#: systemv/cupstestppd.c:1393
+#: systemv/cupstestppd.c:1411
 msgid ""
 "        WARN    PCFileName longer than 8.3 in violation of PPD spec.\n"
 "                REF: Pages 61-62, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:1401
+#: systemv/cupstestppd.c:1419
 msgid ""
 "        WARN    PCFileName should contain a unique filename.\n"
 "                REF: Pages 61-62, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:1436
+#: systemv/cupstestppd.c:1454
 msgid ""
 "        WARN    Protocols contains PJL but JCL attributes are not set.\n"
 "                REF: Pages 78-79, section 5.7."
 msgstr ""
 
-#: systemv/cupstestppd.c:1427
+#: systemv/cupstestppd.c:1445
 msgid ""
 "        WARN    Protocols contains both PJL and BCP; expected TBCP.\n"
 "                REF: Pages 78-79, section 5.7."
 msgstr ""
 
-#: systemv/cupstestppd.c:1410
+#: systemv/cupstestppd.c:1428
 msgid ""
 "        WARN    ShortNickName required by PPD 4.3 spec.\n"
 "                REF: Pages 64-65, section 5.3."
@@ -409,381 +408,381 @@ msgstr ""
 msgid "       cupstestdsc [options] -"
 msgstr ""
 
-#: systemv/cupstestppd.c:3775
+#: systemv/cupstestppd.c:3794
 msgid "       program | cupstestppd [options] -"
 msgstr ""
 
-#: systemv/cupstestppd.c:3707
+#: systemv/cupstestppd.c:3726
 #, c-format
 msgid ""
 "      %s  \"%s %s\" conflicts with \"%s %s\"\n"
 "                (constraint=\"%s %s %s %s\")."
 msgstr ""
 
-#: systemv/cupstestppd.c:2228
+#: systemv/cupstestppd.c:2246
 #, c-format
 msgid "      %s  %s %s does not exist."
 msgstr ""
 
-#: systemv/cupstestppd.c:3864
+#: systemv/cupstestppd.c:3883
 #, c-format
 msgid "      %s  %s file \"%s\" has the wrong capitalization."
 msgstr ""
 
-#: systemv/cupstestppd.c:2298
+#: systemv/cupstestppd.c:2316
 #, c-format
 msgid ""
 "      %s  Bad %s choice %s.\n"
 "                REF: Page 122, section 5.17"
 msgstr ""
 
-#: systemv/cupstestppd.c:3467 systemv/cupstestppd.c:3516
-#: systemv/cupstestppd.c:3555
+#: systemv/cupstestppd.c:3486 systemv/cupstestppd.c:3535
+#: systemv/cupstestppd.c:3574
 #, c-format
 msgid "      %s  Bad UTF-8 \"%s\" translation string for option %s, choice %s."
 msgstr ""
 
-#: systemv/cupstestppd.c:3421
+#: systemv/cupstestppd.c:3440
 #, c-format
 msgid "      %s  Bad UTF-8 \"%s\" translation string for option %s."
 msgstr ""
 
-#: systemv/cupstestppd.c:2369
+#: systemv/cupstestppd.c:2387
 #, c-format
 msgid "      %s  Bad cupsFilter value \"%s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:2455
+#: systemv/cupstestppd.c:2473
 #, c-format
 msgid "      %s  Bad cupsFilter2 value \"%s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:2944
+#: systemv/cupstestppd.c:2962
 #, c-format
 msgid "      %s  Bad cupsICCProfile %s."
 msgstr ""
 
-#: systemv/cupstestppd.c:2551
+#: systemv/cupstestppd.c:2569
 #, c-format
 msgid "      %s  Bad cupsPreFilter value \"%s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:1802
+#: systemv/cupstestppd.c:1820
 #, c-format
 msgid "      %s  Bad cupsUIConstraints %s: \"%s\""
 msgstr ""
 
-#: systemv/cupstestppd.c:3371
+#: systemv/cupstestppd.c:3390
 #, c-format
 msgid "      %s  Bad language \"%s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:2413 systemv/cupstestppd.c:2509
-#: systemv/cupstestppd.c:2595 systemv/cupstestppd.c:2653
-#: systemv/cupstestppd.c:2708 systemv/cupstestppd.c:2763
-#: systemv/cupstestppd.c:2818 systemv/cupstestppd.c:2871
-#: systemv/cupstestppd.c:2993
+#: systemv/cupstestppd.c:2431 systemv/cupstestppd.c:2527
+#: systemv/cupstestppd.c:2613 systemv/cupstestppd.c:2671
+#: systemv/cupstestppd.c:2726 systemv/cupstestppd.c:2781
+#: systemv/cupstestppd.c:2836 systemv/cupstestppd.c:2889
+#: systemv/cupstestppd.c:3011
 #, c-format
 msgid "      %s  Bad permissions on %s file \"%s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:2353 systemv/cupstestppd.c:2439
-#: systemv/cupstestppd.c:2535 systemv/cupstestppd.c:2622
-#: systemv/cupstestppd.c:2677 systemv/cupstestppd.c:2732
-#: systemv/cupstestppd.c:2787 systemv/cupstestppd.c:2842
+#: systemv/cupstestppd.c:2371 systemv/cupstestppd.c:2457
+#: systemv/cupstestppd.c:2553 systemv/cupstestppd.c:2640
+#: systemv/cupstestppd.c:2695 systemv/cupstestppd.c:2750
+#: systemv/cupstestppd.c:2805 systemv/cupstestppd.c:2860
 #, c-format
 msgid "      %s  Bad spelling of %s - should be %s."
 msgstr ""
 
-#: systemv/cupstestppd.c:2887
+#: systemv/cupstestppd.c:2905
 #, c-format
 msgid "      %s  Cannot provide both APScanAppPath and APScanAppBundleID."
 msgstr ""
 
-#: systemv/cupstestppd.c:2185
+#: systemv/cupstestppd.c:2203
 #, c-format
 msgid "      %s  Default choices conflicting."
 msgstr ""
 
-#: systemv/cupstestppd.c:1783
+#: systemv/cupstestppd.c:1801
 #, c-format
 msgid "      %s  Empty cupsUIConstraints %s"
 msgstr ""
 
-#: systemv/cupstestppd.c:3499 systemv/cupstestppd.c:3539
+#: systemv/cupstestppd.c:3518 systemv/cupstestppd.c:3558
 #, c-format
 msgid "      %s  Missing \"%s\" translation string for option %s, choice %s."
 msgstr ""
 
-#: systemv/cupstestppd.c:3407
+#: systemv/cupstestppd.c:3426
 #, c-format
 msgid "      %s  Missing \"%s\" translation string for option %s."
 msgstr ""
 
-#: systemv/cupstestppd.c:2398 systemv/cupstestppd.c:2494
-#: systemv/cupstestppd.c:2580 systemv/cupstestppd.c:2638
-#: systemv/cupstestppd.c:2693 systemv/cupstestppd.c:2748
-#: systemv/cupstestppd.c:2803 systemv/cupstestppd.c:2855
-#: systemv/cupstestppd.c:2978
+#: systemv/cupstestppd.c:2416 systemv/cupstestppd.c:2512
+#: systemv/cupstestppd.c:2598 systemv/cupstestppd.c:2656
+#: systemv/cupstestppd.c:2711 systemv/cupstestppd.c:2766
+#: systemv/cupstestppd.c:2821 systemv/cupstestppd.c:2873
+#: systemv/cupstestppd.c:2996
 #, c-format
 msgid "      %s  Missing %s file \"%s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:3101
+#: systemv/cupstestppd.c:3119
 #, c-format
 msgid ""
 "      %s  Missing REQUIRED PageRegion option.\n"
 "                REF: Page 100, section 5.14."
 msgstr ""
 
-#: systemv/cupstestppd.c:3086
+#: systemv/cupstestppd.c:3104
 #, c-format
 msgid ""
 "      %s  Missing REQUIRED PageSize option.\n"
 "                REF: Page 99, section 5.14."
 msgstr ""
 
-#: systemv/cupstestppd.c:1993 systemv/cupstestppd.c:2034
+#: systemv/cupstestppd.c:2011 systemv/cupstestppd.c:2052
 #, c-format
 msgid "      %s  Missing choice *%s %s in UIConstraints \"*%s %s *%s %s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:1888
+#: systemv/cupstestppd.c:1906
 #, c-format
 msgid "      %s  Missing choice *%s %s in cupsUIConstraints %s: \"%s\""
 msgstr ""
 
-#: systemv/cupstestppd.c:1820
+#: systemv/cupstestppd.c:1838
 #, c-format
 msgid "      %s  Missing cupsUIResolver %s"
 msgstr ""
 
-#: systemv/cupstestppd.c:1979 systemv/cupstestppd.c:2020
+#: systemv/cupstestppd.c:1997 systemv/cupstestppd.c:2038
 #, c-format
 msgid "      %s  Missing option %s in UIConstraints \"*%s %s *%s %s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:1872
+#: systemv/cupstestppd.c:1890
 #, c-format
 msgid "      %s  Missing option %s in cupsUIConstraints %s: \"%s\""
 msgstr ""
 
-#: systemv/cupstestppd.c:3593
+#: systemv/cupstestppd.c:3612
 #, c-format
 msgid "      %s  No base translation \"%s\" is included in file."
 msgstr ""
 
-#: systemv/cupstestppd.c:2274
+#: systemv/cupstestppd.c:2292
 #, c-format
 msgid ""
 "      %s  REQUIRED %s does not define choice None.\n"
 "                REF: Page 122, section 5.17"
 msgstr ""
 
-#: systemv/cupstestppd.c:3159 systemv/cupstestppd.c:3173
+#: systemv/cupstestppd.c:3177 systemv/cupstestppd.c:3191
 #, c-format
 msgid "      %s  Size \"%s\" defined for %s but not for %s."
 msgstr ""
 
-#: systemv/cupstestppd.c:3139
+#: systemv/cupstestppd.c:3157
 #, c-format
 msgid "      %s  Size \"%s\" has unexpected dimensions (%gx%g)."
 msgstr ""
 
-#: systemv/cupstestppd.c:3312
+#: systemv/cupstestppd.c:3331
 #, c-format
 msgid "      %s  Size \"%s\" should be \"%s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:3273
+#: systemv/cupstestppd.c:3292
 #, c-format
 msgid "      %s  Size \"%s\" should be the Adobe standard name \"%s\"."
 msgstr ""
 
-#: systemv/cupstestppd.c:3021
+#: systemv/cupstestppd.c:3039
 #, c-format
 msgid "      %s  cupsICCProfile %s hash value collides with %s."
 msgstr ""
 
-#: systemv/cupstestppd.c:1943
+#: systemv/cupstestppd.c:1961
 #, c-format
 msgid "      %s  cupsUIResolver %s causes a loop."
 msgstr ""
 
-#: systemv/cupstestppd.c:1925
+#: systemv/cupstestppd.c:1943
 #, c-format
 msgid "      %s  cupsUIResolver %s does not list at least two different options."
 msgstr ""
 
-#: systemv/cupstestppd.c:2143
+#: systemv/cupstestppd.c:2161
 #, c-format
 msgid "      **FAIL**  %s choice names %s and %s differ only by case."
 msgstr ""
 
-#: systemv/cupstestppd.c:1148
+#: systemv/cupstestppd.c:1166
 #, c-format
 msgid ""
 "      **FAIL**  %s must be 1284DeviceID\n"
 "                REF: Page 72, section 5.5"
 msgstr ""
 
-#: systemv/cupstestppd.c:562
+#: systemv/cupstestppd.c:580
 #, c-format
 msgid ""
 "      **FAIL**  BAD Default%s %s\n"
 "                REF: Page 40, section 4.5."
 msgstr ""
 
-#: systemv/cupstestppd.c:496
+#: systemv/cupstestppd.c:514
 #, c-format
 msgid ""
 "      **FAIL**  BAD DefaultImageableArea %s\n"
 "                REF: Page 102, section 5.15."
 msgstr ""
 
-#: systemv/cupstestppd.c:532
+#: systemv/cupstestppd.c:550
 #, c-format
 msgid ""
 "      **FAIL**  BAD DefaultPaperDimension %s\n"
 "                REF: Page 103, section 5.15."
 msgstr ""
 
-#: systemv/cupstestppd.c:1005
+#: systemv/cupstestppd.c:1023
 msgid ""
 "      **FAIL**  BAD JobPatchFile attribute in file\n"
 "                REF: Page 24, section 3.4."
 msgstr ""
 
-#: systemv/cupstestppd.c:725
+#: systemv/cupstestppd.c:743
 msgid ""
 "      **FAIL**  BAD Manufacturer (should be \"HP\")\n"
 "                REF: Page 211, table D.1."
 msgstr ""
 
-#: systemv/cupstestppd.c:741
+#: systemv/cupstestppd.c:759
 msgid ""
 "      **FAIL**  BAD Manufacturer (should be \"Oki\")\n"
 "                REF: Page 211, table D.1."
 msgstr ""
 
-#: systemv/cupstestppd.c:780
+#: systemv/cupstestppd.c:798
 #, c-format
 msgid ""
 "      **FAIL**  BAD ModelName - \"%c\" not allowed in string.\n"
 "                REF: Pages 59-60, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:936
+#: systemv/cupstestppd.c:954
 msgid ""
 "      **FAIL**  BAD PSVersion - not \"(string) int\".\n"
 "                REF: Pages 62-64, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:897
+#: systemv/cupstestppd.c:915
 msgid ""
 "      **FAIL**  BAD Product - not \"(string)\".\n"
 "                REF: Page 62, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:971
+#: systemv/cupstestppd.c:989
 msgid ""
 "      **FAIL**  BAD ShortNickName - longer than 31 chars.\n"
 "                REF: Pages 64-65, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:1129
+#: systemv/cupstestppd.c:1147
 #, c-format
 msgid ""
 "      **FAIL**  Bad %s choice %s\n"
 "                REF: Page 84, section 5.9"
 msgstr ""
 
-#: systemv/cupstestppd.c:605
+#: systemv/cupstestppd.c:623
 #, c-format
 msgid ""
 "      **FAIL**  Bad FileVersion \"%s\"\n"
 "                REF: Page 56, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:649
+#: systemv/cupstestppd.c:667
 #, c-format
 msgid ""
 "      **FAIL**  Bad FormatVersion \"%s\"\n"
 "                REF: Page 56, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:1193
+#: systemv/cupstestppd.c:1211
 #, c-format
 msgid "      **FAIL**  Bad LanguageEncoding %s - must be ISOLatin1."
 msgstr ""
 
-#: systemv/cupstestppd.c:1207
+#: systemv/cupstestppd.c:1225
 #, c-format
 msgid "      **FAIL**  Bad LanguageVersion %s - must be English."
 msgstr ""
 
-#: systemv/cupstestppd.c:3734 systemv/cupstestppd.c:3756
+#: systemv/cupstestppd.c:3753 systemv/cupstestppd.c:3775
 #, c-format
 msgid "      **FAIL**  Default option code cannot be interpreted: %s"
 msgstr ""
 
-#: systemv/cupstestppd.c:1266
+#: systemv/cupstestppd.c:1284
 #, c-format
 msgid "      **FAIL**  Default translation string for option %s choice %s contains 8-bit characters."
 msgstr ""
 
-#: systemv/cupstestppd.c:1239
+#: systemv/cupstestppd.c:1257
 #, c-format
 msgid "      **FAIL**  Default translation string for option %s contains 8-bit characters."
 msgstr ""
 
-#: systemv/cupstestppd.c:2081
+#: systemv/cupstestppd.c:2099
 #, c-format
 msgid "      **FAIL**  Group names %s and %s differ only by case."
 msgstr ""
 
-#: systemv/cupstestppd.c:2126
+#: systemv/cupstestppd.c:2144
 #, c-format
 msgid "      **FAIL**  Multiple occurrences of %s choice name %s."
 msgstr ""
 
-#: systemv/cupstestppd.c:2103
+#: systemv/cupstestppd.c:2121
 #, c-format
 msgid "      **FAIL**  Option names %s and %s differ only by case."
 msgstr ""
 
-#: systemv/cupstestppd.c:582
+#: systemv/cupstestppd.c:600
 #, c-format
 msgid ""
 "      **FAIL**  REQUIRED Default%s\n"
 "                REF: Page 40, section 4.5."
 msgstr ""
 
-#: systemv/cupstestppd.c:481
+#: systemv/cupstestppd.c:499
 msgid ""
 "      **FAIL**  REQUIRED DefaultImageableArea\n"
 "                REF: Page 102, section 5.15."
 msgstr ""
 
-#: systemv/cupstestppd.c:517
+#: systemv/cupstestppd.c:535
 msgid ""
 "      **FAIL**  REQUIRED DefaultPaperDimension\n"
 "                REF: Page 103, section 5.15."
 msgstr ""
 
-#: systemv/cupstestppd.c:623
+#: systemv/cupstestppd.c:641
 msgid ""
 "      **FAIL**  REQUIRED FileVersion\n"
 "                REF: Page 56, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:667
+#: systemv/cupstestppd.c:685
 msgid ""
 "      **FAIL**  REQUIRED FormatVersion\n"
 "                REF: Page 56, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:1056
+#: systemv/cupstestppd.c:1074
 #, c-format
 msgid ""
 "      **FAIL**  REQUIRED ImageableArea for PageSize %s\n"
@@ -791,68 +790,68 @@ msgid ""
 "                REF: Page 102, section 5.15."
 msgstr ""
 
-#: systemv/cupstestppd.c:687
+#: systemv/cupstestppd.c:705
 msgid ""
 "      **FAIL**  REQUIRED LanguageEncoding\n"
 "                REF: Pages 56-57, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:707
+#: systemv/cupstestppd.c:725
 msgid ""
 "      **FAIL**  REQUIRED LanguageVersion\n"
 "                REF: Pages 57-58, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:759
+#: systemv/cupstestppd.c:777
 msgid ""
 "      **FAIL**  REQUIRED Manufacturer\n"
 "                REF: Pages 58-59, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:799
+#: systemv/cupstestppd.c:817
 msgid ""
 "      **FAIL**  REQUIRED ModelName\n"
 "                REF: Pages 59-60, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:819
+#: systemv/cupstestppd.c:837
 msgid ""
 "      **FAIL**  REQUIRED NickName\n"
 "                REF: Page 60, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:879
+#: systemv/cupstestppd.c:897
 msgid ""
 "      **FAIL**  REQUIRED PCFileName\n"
 "                REF: Pages 61-62, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:954
+#: systemv/cupstestppd.c:972
 msgid ""
 "      **FAIL**  REQUIRED PSVersion\n"
 "                REF: Pages 62-64, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:859
+#: systemv/cupstestppd.c:877
 msgid ""
 "      **FAIL**  REQUIRED PageRegion\n"
 "                REF: Page 100, section 5.14."
 msgstr ""
 
-#: systemv/cupstestppd.c:1025
+#: systemv/cupstestppd.c:1043
 msgid ""
 "      **FAIL**  REQUIRED PageSize\n"
 "                REF: Page 41, section 5.\n"
 "                REF: Page 99, section 5.14."
 msgstr ""
 
-#: systemv/cupstestppd.c:839
+#: systemv/cupstestppd.c:857
 msgid ""
 "      **FAIL**  REQUIRED PageSize\n"
 "                REF: Pages 99-100, section 5.14."
 msgstr ""
 
-#: systemv/cupstestppd.c:1078
+#: systemv/cupstestppd.c:1096
 #, c-format
 msgid ""
 "      **FAIL**  REQUIRED PaperDimension for PageSize %s\n"
@@ -860,29 +859,29 @@ msgid ""
 "                REF: Page 103, section 5.15."
 msgstr ""
 
-#: systemv/cupstestppd.c:914
+#: systemv/cupstestppd.c:932
 msgid ""
 "      **FAIL**  REQUIRED Product\n"
 "                REF: Page 62, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:989
+#: systemv/cupstestppd.c:1007
 msgid ""
 "      **FAIL**  REQUIRED ShortNickName\n"
 "                REF: Page 64-65, section 5.3."
 msgstr ""
 
-#: systemv/cupstestppd.c:335
+#: systemv/cupstestppd.c:334 systemv/cupstestppd.c:353
 #, c-format
 msgid "      **FAIL**  Unable to open PPD file - %s"
 msgstr ""
 
-#: systemv/cupstestppd.c:347
+#: systemv/cupstestppd.c:365
 #, c-format
 msgid "      **FAIL**  Unable to open PPD file - %s on line %d."
 msgstr ""
 
-#: systemv/cupstestppd.c:1478
+#: systemv/cupstestppd.c:1496
 #, c-format
 msgid "    %d ERRORS FOUND"
 msgstr ""
@@ -951,7 +950,7 @@ msgid ""
 "        REF: Page 43, %%Pages:"
 msgstr ""
 
-#: systemv/cupstestppd.c:1480
+#: systemv/cupstestppd.c:1498
 msgid "    NO ERRORS FOUND"
 msgstr ""
 
@@ -1016,15 +1015,15 @@ msgstr ""
 msgid "  --lf                    End lines with LF (UNIX/Linux/Mac OS X)."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4291 test/ipptool.c:4312
+#: test/ipptool.c:4337
 msgid "  -4                      Connect using IPv4."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4292 test/ipptool.c:4313
+#: test/ipptool.c:4338
 msgid "  -6                      Connect using IPv6."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4293 test/ipptool.c:4314
+#: test/ipptool.c:4339
 msgid "  -C                      Send requests using chunking (default)."
 msgstr ""
 
@@ -1044,11 +1043,11 @@ msgstr ""
 msgid "  -E                      Encrypt the connection to the server."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4295 test/ipptool.c:4316
+#: test/ipptool.c:4341
 msgid "  -E                      Test with TLS encryption."
 msgstr ""
 
-#: scheduler/main.c:1992
+#: scheduler/main.c:2023
 msgid "  -F                      Run in the foreground but detach from console."
 msgstr ""
 
@@ -1056,7 +1055,7 @@ msgstr ""
 msgid "  -H samba-server         Use the named SAMBA server."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4297 test/ipptool.c:4318
+#: test/ipptool.c:4343
 msgid "  -I                      Ignore errors."
 msgstr ""
 
@@ -1064,7 +1063,7 @@ msgstr ""
 msgid "  -I include-dir          Add include directory to search path."
 msgstr ""
 
-#: systemv/cupstestppd.c:3779
+#: systemv/cupstestppd.c:3798
 msgid "  -I {filename,filters,none,profiles}"
 msgstr ""
 
@@ -1072,7 +1071,7 @@ msgstr ""
 msgid "  -J title                Set title."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4298 test/ipptool.c:4319
+#: test/ipptool.c:4344
 msgid "  -L                      Send requests using content-length."
 msgstr ""
 
@@ -1080,19 +1079,15 @@ msgstr ""
 msgid "  -P filename.ppd         Set PPD file."
 msgstr ""
 
-#: systemv/cupstestppd.c:3781
+#: systemv/cupstestppd.c:3800
 msgid "  -R root-directory       Set alternate root."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4300 test/ipptool.c:4321
+#: test/ipptool.c:4346
 msgid "  -S                      Test with SSL encryption."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4302
-msgid "  -T                      Set the receive/send timeout in seconds."
-msgstr ""
-
-#: test/ipptool.c:4323
+#: test/ipptool.c:4348
 msgid "  -T seconds              Set the receive/send timeout in seconds."
 msgstr ""
 
@@ -1108,15 +1103,15 @@ msgstr ""
 msgid "  -U username             Specify username."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4304 test/ipptool.c:4325
+#: test/ipptool.c:4350
 msgid "  -V version              Set default IPP version."
 msgstr ""
 
-#: systemv/cupstestppd.c:3782
+#: systemv/cupstestppd.c:3801
 msgid "  -W {all,none,constraints,defaults,duplex,filters,profiles,sizes,translations}"
 msgstr ""
 
-#: test/ipptool-with-progress.c:4306 test/ipptool.c:4327
+#: test/ipptool.c:4352
 msgid "  -X                      Produce XML plist instead of plain text."
 msgstr ""
 
@@ -1132,7 +1127,7 @@ msgstr ""
 msgid "  -c catalog.po           Load the specified message catalog."
 msgstr ""
 
-#: scheduler/main.c:1989
+#: scheduler/main.c:2020
 msgid "  -c config-file          Load alternate configuration file."
 msgstr ""
 
@@ -1144,7 +1139,7 @@ msgstr ""
 msgid "  -c cupsd.conf           Set cupsd.conf file to use."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4308 test/ipptool.c:4329
+#: test/ipptool.c:4354
 msgid "  -d name=value           Set named variable to value."
 msgstr ""
 
@@ -1160,11 +1155,11 @@ msgstr ""
 msgid "  -e                      Use every filter from the PPD file."
 msgstr ""
 
-#: scheduler/main.c:1991
+#: scheduler/main.c:2022
 msgid "  -f                      Run in the foreground."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4310 test/ipptool.c:4331
+#: test/ipptool.c:4356
 msgid "  -f filename             Set default request filename."
 msgstr ""
 
@@ -1172,7 +1167,7 @@ msgstr ""
 msgid "  -f filename             Set file to be converted (otherwise stdin)."
 msgstr ""
 
-#: scheduler/main.c:1994
+#: scheduler/main.c:2025
 msgid "  -h                      Show this usage message."
 msgstr ""
 
@@ -1188,7 +1183,7 @@ msgstr ""
 msgid "  -i mime/type            Set input MIME type (otherwise auto-typed)."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4312 test/ipptool.c:4333
+#: test/ipptool.c:4358
 msgid "  -i seconds              Repeat the last file with the given time interval."
 msgstr ""
 
@@ -1200,7 +1195,7 @@ msgstr ""
 msgid "  -j mime/type            Set output MIME type (otherwise application/pdf)."
 msgstr ""
 
-#: scheduler/main.c:1995
+#: scheduler/main.c:2026
 msgid "  -l                      Run cupsd from launchd(8)."
 msgstr ""
 
@@ -1220,7 +1215,7 @@ msgstr ""
 msgid "  -n copies               Set number of copies."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4314 test/ipptool.c:4335
+#: test/ipptool.c:4360
 msgid "  -n count                Repeat the last file the given number of times."
 msgstr ""
 
@@ -1244,19 +1239,19 @@ msgstr ""
 msgid "  -p filename.ppd         Set PPD file."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4316 test/ipptool.c:4337
+#: test/ipptool.c:4362
 msgid "  -q                      Be quiet - no output except errors."
 msgstr ""
 
-#: systemv/cupstestppd.c:3786
+#: systemv/cupstestppd.c:3805
 msgid "  -q                      Run silently."
 msgstr ""
 
-#: systemv/cupstestppd.c:3787
+#: systemv/cupstestppd.c:3806
 msgid "  -r                      Use 'relaxed' open mode."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4318 test/ipptool.c:4339
+#: test/ipptool.c:4364
 msgid "  -t                      Produce a test report."
 msgstr ""
 
@@ -1264,7 +1259,7 @@ msgstr ""
 msgid "  -t                      Test PPDs instead of generating them."
 msgstr ""
 
-#: scheduler/main.c:1996
+#: scheduler/main.c:2027
 msgid "  -t                      Test the configuration file."
 msgstr ""
 
@@ -1276,7 +1271,7 @@ msgstr ""
 msgid "  -u                      Remove the PPD file when finished."
 msgstr ""
 
-#: systemv/cupstestppd.c:3788
+#: systemv/cupstestppd.c:3807
 msgid "  -v                      Be slightly verbose."
 msgstr ""
 
@@ -1288,11 +1283,11 @@ msgstr ""
 msgid "  -v                      Be verbose (show commands)."
 msgstr ""
 
-#: test/ipptool-with-progress.c:4319 test/ipptool.c:4340
+#: test/ipptool.c:4365
 msgid "  -v                      Show all attributes sent and received."
 msgstr ""
 
-#: systemv/cupstestppd.c:3789
+#: systemv/cupstestppd.c:3808
 msgid "  -vv                     Be very verbose."
 msgstr ""
 
@@ -1300,64 +1295,64 @@ msgstr ""
 msgid "  -z                      Compress PPD files using GNU zip."
 msgstr ""
 
-#: systemv/cupstestppd.c:333 systemv/cupstestppd.c:345
-#: systemv/cupstestppd.c:478 systemv/cupstestppd.c:493
-#: systemv/cupstestppd.c:514 systemv/cupstestppd.c:529
-#: systemv/cupstestppd.c:559 systemv/cupstestppd.c:579
-#: systemv/cupstestppd.c:602 systemv/cupstestppd.c:620
-#: systemv/cupstestppd.c:646 systemv/cupstestppd.c:664
-#: systemv/cupstestppd.c:684 systemv/cupstestppd.c:704
-#: systemv/cupstestppd.c:722 systemv/cupstestppd.c:738
-#: systemv/cupstestppd.c:756 systemv/cupstestppd.c:777
-#: systemv/cupstestppd.c:796 systemv/cupstestppd.c:816
-#: systemv/cupstestppd.c:836 systemv/cupstestppd.c:856
-#: systemv/cupstestppd.c:876 systemv/cupstestppd.c:894
-#: systemv/cupstestppd.c:911 systemv/cupstestppd.c:933
-#: systemv/cupstestppd.c:951 systemv/cupstestppd.c:968
-#: systemv/cupstestppd.c:986 systemv/cupstestppd.c:1002
-#: systemv/cupstestppd.c:1022 systemv/cupstestppd.c:1053
-#: systemv/cupstestppd.c:1075 systemv/cupstestppd.c:1126
-#: systemv/cupstestppd.c:1145 systemv/cupstestppd.c:1189
-#: systemv/cupstestppd.c:1203 systemv/cupstestppd.c:1235
-#: systemv/cupstestppd.c:1262 systemv/cupstestppd.c:1780
-#: systemv/cupstestppd.c:1799 systemv/cupstestppd.c:1817
-#: systemv/cupstestppd.c:1869 systemv/cupstestppd.c:1885
-#: systemv/cupstestppd.c:1922 systemv/cupstestppd.c:1940
-#: systemv/cupstestppd.c:1976 systemv/cupstestppd.c:1990
-#: systemv/cupstestppd.c:2017 systemv/cupstestppd.c:2031
-#: systemv/cupstestppd.c:2077 systemv/cupstestppd.c:2099
-#: systemv/cupstestppd.c:2122 systemv/cupstestppd.c:2139
-#: systemv/cupstestppd.c:2181 systemv/cupstestppd.c:2224
-#: systemv/cupstestppd.c:2271 systemv/cupstestppd.c:2295
-#: systemv/cupstestppd.c:2349 systemv/cupstestppd.c:2365
-#: systemv/cupstestppd.c:2395 systemv/cupstestppd.c:2409
-#: systemv/cupstestppd.c:2435 systemv/cupstestppd.c:2451
-#: systemv/cupstestppd.c:2491 systemv/cupstestppd.c:2505
-#: systemv/cupstestppd.c:2531 systemv/cupstestppd.c:2547
-#: systemv/cupstestppd.c:2577 systemv/cupstestppd.c:2591
-#: systemv/cupstestppd.c:2618 systemv/cupstestppd.c:2635
-#: systemv/cupstestppd.c:2649 systemv/cupstestppd.c:2673
-#: systemv/cupstestppd.c:2690 systemv/cupstestppd.c:2704
-#: systemv/cupstestppd.c:2728 systemv/cupstestppd.c:2745
-#: systemv/cupstestppd.c:2759 systemv/cupstestppd.c:2783
-#: systemv/cupstestppd.c:2800 systemv/cupstestppd.c:2814
-#: systemv/cupstestppd.c:2838 systemv/cupstestppd.c:2852
-#: systemv/cupstestppd.c:2867 systemv/cupstestppd.c:2884
-#: systemv/cupstestppd.c:2940 systemv/cupstestppd.c:2975
-#: systemv/cupstestppd.c:2989 systemv/cupstestppd.c:3017
-#: systemv/cupstestppd.c:3082 systemv/cupstestppd.c:3097
-#: systemv/cupstestppd.c:3135 systemv/cupstestppd.c:3155
-#: systemv/cupstestppd.c:3169 systemv/cupstestppd.c:3367
-#: systemv/cupstestppd.c:3403 systemv/cupstestppd.c:3417
-#: systemv/cupstestppd.c:3463 systemv/cupstestppd.c:3495
-#: systemv/cupstestppd.c:3512 systemv/cupstestppd.c:3535
-#: systemv/cupstestppd.c:3551 systemv/cupstestppd.c:3589
-#: systemv/cupstestppd.c:3730 systemv/cupstestppd.c:3752
-#: systemv/cupstestppd.c:3860
+#: systemv/cupstestppd.c:332 systemv/cupstestppd.c:351
+#: systemv/cupstestppd.c:363 systemv/cupstestppd.c:496
+#: systemv/cupstestppd.c:511 systemv/cupstestppd.c:532
+#: systemv/cupstestppd.c:547 systemv/cupstestppd.c:577
+#: systemv/cupstestppd.c:597 systemv/cupstestppd.c:620
+#: systemv/cupstestppd.c:638 systemv/cupstestppd.c:664
+#: systemv/cupstestppd.c:682 systemv/cupstestppd.c:702
+#: systemv/cupstestppd.c:722 systemv/cupstestppd.c:740
+#: systemv/cupstestppd.c:756 systemv/cupstestppd.c:774
+#: systemv/cupstestppd.c:795 systemv/cupstestppd.c:814
+#: systemv/cupstestppd.c:834 systemv/cupstestppd.c:854
+#: systemv/cupstestppd.c:874 systemv/cupstestppd.c:894
+#: systemv/cupstestppd.c:912 systemv/cupstestppd.c:929
+#: systemv/cupstestppd.c:951 systemv/cupstestppd.c:969
+#: systemv/cupstestppd.c:986 systemv/cupstestppd.c:1004
+#: systemv/cupstestppd.c:1020 systemv/cupstestppd.c:1040
+#: systemv/cupstestppd.c:1071 systemv/cupstestppd.c:1093
+#: systemv/cupstestppd.c:1144 systemv/cupstestppd.c:1163
+#: systemv/cupstestppd.c:1207 systemv/cupstestppd.c:1221
+#: systemv/cupstestppd.c:1253 systemv/cupstestppd.c:1280
+#: systemv/cupstestppd.c:1798 systemv/cupstestppd.c:1817
+#: systemv/cupstestppd.c:1835 systemv/cupstestppd.c:1887
+#: systemv/cupstestppd.c:1903 systemv/cupstestppd.c:1940
+#: systemv/cupstestppd.c:1958 systemv/cupstestppd.c:1994
+#: systemv/cupstestppd.c:2008 systemv/cupstestppd.c:2035
+#: systemv/cupstestppd.c:2049 systemv/cupstestppd.c:2095
+#: systemv/cupstestppd.c:2117 systemv/cupstestppd.c:2140
+#: systemv/cupstestppd.c:2157 systemv/cupstestppd.c:2199
+#: systemv/cupstestppd.c:2242 systemv/cupstestppd.c:2289
+#: systemv/cupstestppd.c:2313 systemv/cupstestppd.c:2367
+#: systemv/cupstestppd.c:2383 systemv/cupstestppd.c:2413
+#: systemv/cupstestppd.c:2427 systemv/cupstestppd.c:2453
+#: systemv/cupstestppd.c:2469 systemv/cupstestppd.c:2509
+#: systemv/cupstestppd.c:2523 systemv/cupstestppd.c:2549
+#: systemv/cupstestppd.c:2565 systemv/cupstestppd.c:2595
+#: systemv/cupstestppd.c:2609 systemv/cupstestppd.c:2636
+#: systemv/cupstestppd.c:2653 systemv/cupstestppd.c:2667
+#: systemv/cupstestppd.c:2691 systemv/cupstestppd.c:2708
+#: systemv/cupstestppd.c:2722 systemv/cupstestppd.c:2746
+#: systemv/cupstestppd.c:2763 systemv/cupstestppd.c:2777
+#: systemv/cupstestppd.c:2801 systemv/cupstestppd.c:2818
+#: systemv/cupstestppd.c:2832 systemv/cupstestppd.c:2856
+#: systemv/cupstestppd.c:2870 systemv/cupstestppd.c:2885
+#: systemv/cupstestppd.c:2902 systemv/cupstestppd.c:2958
+#: systemv/cupstestppd.c:2993 systemv/cupstestppd.c:3007
+#: systemv/cupstestppd.c:3035 systemv/cupstestppd.c:3100
+#: systemv/cupstestppd.c:3115 systemv/cupstestppd.c:3153
+#: systemv/cupstestppd.c:3173 systemv/cupstestppd.c:3187
+#: systemv/cupstestppd.c:3386 systemv/cupstestppd.c:3422
+#: systemv/cupstestppd.c:3436 systemv/cupstestppd.c:3482
+#: systemv/cupstestppd.c:3514 systemv/cupstestppd.c:3531
+#: systemv/cupstestppd.c:3554 systemv/cupstestppd.c:3570
+#: systemv/cupstestppd.c:3608 systemv/cupstestppd.c:3749
+#: systemv/cupstestppd.c:3771 systemv/cupstestppd.c:3879
 msgid " FAIL"
 msgstr ""
 
-#: systemv/cupstestppd.c:1286
+#: systemv/cupstestppd.c:1304
 msgid " PASS"
 msgstr ""
 
@@ -1376,7 +1371,7 @@ msgstr ""
 msgid "%s accepting requests since %s"
 msgstr ""
 
-#: scheduler/ipp.c:10921
+#: scheduler/ipp.c:10739
 #, c-format
 msgid "%s cannot be changed."
 msgstr ""
@@ -1412,7 +1407,7 @@ msgstr ""
 msgid "%s not accepting requests since %s -"
 msgstr ""
 
-#: scheduler/ipp.c:709
+#: scheduler/ipp.c:703
 #, c-format
 msgid "%s not supported."
 msgstr ""
@@ -1668,8 +1663,7 @@ msgstr ""
 #: berkeley/lpq.c:97 berkeley/lpr.c:70 berkeley/lprm.c:67 systemv/cancel.c:81
 #: systemv/cupsaccept.c:88 systemv/cupsaddsmb.c:86 systemv/lp.c:102
 #: systemv/lpadmin.c:239 systemv/lpinfo.c:88 systemv/lpmove.c:73
-#: systemv/lpstat.c:102 test/ipptool-with-progress.c:295
-#: test/ipptool-with-progress.c:312 test/ipptool.c:295 test/ipptool.c:312
+#: systemv/lpstat.c:102 test/ipptool.c:302 test/ipptool.c:319
 #, c-format
 msgid "%s: Sorry, no encryption support."
 msgstr ""
@@ -2558,12 +2552,12 @@ msgstr ""
 msgid "A Samba username is required to export printer drivers"
 msgstr ""
 
-#: scheduler/ipp.c:2301
+#: scheduler/ipp.c:2295
 #, c-format
 msgid "A class named \"%s\" already exists."
 msgstr ""
 
-#: scheduler/ipp.c:1022
+#: scheduler/ipp.c:1016
 #, c-format
 msgid "A printer named \"%s\" already exists."
 msgstr ""
@@ -2708,7 +2702,7 @@ msgstr ""
 msgid "Accept Jobs"
 msgstr ""
 
-#: cups/http-support.c:1254
+#: cups/http-support.c:1257
 msgid "Accepted"
 msgstr ""
 
@@ -2749,12 +2743,12 @@ msgstr ""
 msgid "Applicator"
 msgstr ""
 
-#: scheduler/ipp.c:1097
+#: scheduler/ipp.c:1091
 #, c-format
 msgid "Attempt to set %s printer-state to bad value %d."
 msgstr ""
 
-#: scheduler/ipp.c:343
+#: scheduler/ipp.c:337
 #, c-format
 msgid "Attribute groups are out of order (%x < %x)."
 msgstr ""
@@ -2823,20 +2817,20 @@ msgstr ""
 msgid "Bad OrderDependency"
 msgstr ""
 
-#: cups/ppd-cache.c:148 cups/ppd-cache.c:193 cups/ppd-cache.c:231
-#: cups/ppd-cache.c:237 cups/ppd-cache.c:253 cups/ppd-cache.c:269
-#: cups/ppd-cache.c:278 cups/ppd-cache.c:286 cups/ppd-cache.c:303
-#: cups/ppd-cache.c:311 cups/ppd-cache.c:326 cups/ppd-cache.c:334
-#: cups/ppd-cache.c:352 cups/ppd-cache.c:364 cups/ppd-cache.c:379
-#: cups/ppd-cache.c:391 cups/ppd-cache.c:413 cups/ppd-cache.c:421
-#: cups/ppd-cache.c:439 cups/ppd-cache.c:447 cups/ppd-cache.c:462
-#: cups/ppd-cache.c:470 cups/ppd-cache.c:488 cups/ppd-cache.c:496
-#: cups/ppd-cache.c:523 cups/ppd-cache.c:567 cups/ppd-cache.c:575
-#: cups/ppd-cache.c:583
+#: cups/ppd-cache.c:148 cups/ppd-cache.c:195 cups/ppd-cache.c:233
+#: cups/ppd-cache.c:239 cups/ppd-cache.c:255 cups/ppd-cache.c:271
+#: cups/ppd-cache.c:280 cups/ppd-cache.c:288 cups/ppd-cache.c:305
+#: cups/ppd-cache.c:313 cups/ppd-cache.c:328 cups/ppd-cache.c:336
+#: cups/ppd-cache.c:354 cups/ppd-cache.c:366 cups/ppd-cache.c:381
+#: cups/ppd-cache.c:393 cups/ppd-cache.c:415 cups/ppd-cache.c:423
+#: cups/ppd-cache.c:441 cups/ppd-cache.c:449 cups/ppd-cache.c:464
+#: cups/ppd-cache.c:472 cups/ppd-cache.c:490 cups/ppd-cache.c:498
+#: cups/ppd-cache.c:525 cups/ppd-cache.c:571 cups/ppd-cache.c:579
+#: cups/ppd-cache.c:587
 msgid "Bad PPD cache file."
 msgstr ""
 
-#: cups/http-support.c:1269
+#: cups/http-support.c:1272
 msgid "Bad Request"
 msgstr ""
 
@@ -2848,7 +2842,7 @@ msgstr ""
 msgid "Bad UIConstraints"
 msgstr ""
 
-#: scheduler/ipp.c:1398
+#: scheduler/ipp.c:1392
 #, c-format
 msgid "Bad copies value %d."
 msgstr ""
@@ -2857,23 +2851,23 @@ msgstr ""
 msgid "Bad custom parameter"
 msgstr ""
 
-#: cups/http-support.c:1421 scheduler/ipp.c:2368
+#: cups/http-support.c:1424 scheduler/ipp.c:2362
 #, c-format
 msgid "Bad device-uri \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:2409
+#: scheduler/ipp.c:2403
 #, c-format
 msgid "Bad device-uri scheme \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:9101 scheduler/ipp.c:9117 scheduler/ipp.c:10330
-#: scheduler/ipp.c:11844
+#: scheduler/ipp.c:8918 scheduler/ipp.c:8934 scheduler/ipp.c:10148
+#: scheduler/ipp.c:11662
 #, c-format
 msgid "Bad document-format \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:10346
+#: scheduler/ipp.c:10164
 #, c-format
 msgid "Bad document-format-default \"%s\"."
 msgstr ""
@@ -2882,42 +2876,42 @@ msgstr ""
 msgid "Bad filename buffer"
 msgstr ""
 
-#: scheduler/ipp.c:10936
+#: scheduler/ipp.c:10754
 msgid "Bad job-priority value."
 msgstr ""
 
-#: scheduler/ipp.c:1428
+#: scheduler/ipp.c:1422
 #, c-format
 msgid "Bad job-sheets value \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:1412
+#: scheduler/ipp.c:1406
 msgid "Bad job-sheets value type."
 msgstr ""
 
-#: scheduler/ipp.c:10966
+#: scheduler/ipp.c:10784
 msgid "Bad job-state value."
 msgstr ""
 
-#: scheduler/ipp.c:3880 scheduler/ipp.c:4332 scheduler/ipp.c:6955
-#: scheduler/ipp.c:7102 scheduler/ipp.c:8535 scheduler/ipp.c:8804
-#: scheduler/ipp.c:9652 scheduler/ipp.c:9877 scheduler/ipp.c:10226
-#: scheduler/ipp.c:10829
+#: scheduler/ipp.c:3697 scheduler/ipp.c:4149 scheduler/ipp.c:6772
+#: scheduler/ipp.c:6919 scheduler/ipp.c:8352 scheduler/ipp.c:8621
+#: scheduler/ipp.c:9469 scheduler/ipp.c:9695 scheduler/ipp.c:10044
+#: scheduler/ipp.c:10647
 #, c-format
 msgid "Bad job-uri \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:2067 scheduler/ipp.c:6497
+#: scheduler/ipp.c:2061 scheduler/ipp.c:6314
 #, c-format
 msgid "Bad notify-pull-method \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:2031 scheduler/ipp.c:6461
+#: scheduler/ipp.c:2025 scheduler/ipp.c:6278
 #, c-format
 msgid "Bad notify-recipient-uri \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:1444
+#: scheduler/ipp.c:1438
 #, c-format
 msgid "Bad number-up value %d."
 msgstr ""
@@ -2927,12 +2921,12 @@ msgstr ""
 msgid "Bad option + choice on line %d."
 msgstr ""
 
-#: scheduler/ipp.c:1461
+#: scheduler/ipp.c:1455
 #, c-format
 msgid "Bad page-ranges values %d-%d."
 msgstr ""
 
-#: scheduler/ipp.c:2452
+#: scheduler/ipp.c:2446
 #, c-format
 msgid "Bad port-monitor \"%s\"."
 msgstr ""
@@ -2941,17 +2935,17 @@ msgstr ""
 msgid "Bad printer URI."
 msgstr ""
 
-#: scheduler/ipp.c:2513
+#: scheduler/ipp.c:2507
 #, c-format
 msgid "Bad printer-state value %d."
 msgstr ""
 
-#: scheduler/ipp.c:311
+#: scheduler/ipp.c:305
 #, c-format
 msgid "Bad request ID %d."
 msgstr ""
 
-#: scheduler/ipp.c:296
+#: scheduler/ipp.c:290
 #, c-format
 msgid "Bad request version number %d.%d."
 msgstr ""
@@ -2993,11 +2987,11 @@ msgstr ""
 msgid "Cancel RSS Subscription"
 msgstr ""
 
-#: backend/ipp.c:1892
+#: backend/ipp.c:1903
 msgid "Canceling print job."
 msgstr ""
 
-#: scheduler/ipp.c:2493
+#: scheduler/ipp.c:2487
 msgid "Cannot share a remote Kerberized printer."
 msgstr ""
 
@@ -3010,7 +3004,7 @@ msgstr ""
 msgid "Change Settings"
 msgstr ""
 
-#: scheduler/ipp.c:2079 scheduler/ipp.c:6509
+#: scheduler/ipp.c:2073 scheduler/ipp.c:6326
 #, c-format
 msgid "Character set \"%s\" not supported."
 msgstr ""
@@ -3023,7 +3017,7 @@ msgstr ""
 msgid "Clean Print Heads"
 msgstr ""
 
-#: scheduler/ipp.c:4784
+#: scheduler/ipp.c:4601
 msgid "Close-Job doesn't support the job-uri attribute."
 msgstr ""
 
@@ -3046,15 +3040,15 @@ msgstr ""
 msgid "Community name uses indefinite length"
 msgstr ""
 
-#: backend/ipp.c:773 backend/lpd.c:862 backend/socket.c:395
+#: backend/ipp.c:779 backend/lpd.c:871 backend/socket.c:395
 msgid "Connected to printer."
 msgstr ""
 
-#: backend/ipp.c:680 backend/lpd.c:685 backend/socket.c:314
+#: backend/ipp.c:686 backend/lpd.c:694 backend/socket.c:314
 msgid "Connecting to printer."
 msgstr ""
 
-#: cups/http-support.c:1242
+#: cups/http-support.c:1245
 msgid "Continue"
 msgstr ""
 
@@ -3062,15 +3056,15 @@ msgstr ""
 msgid "Continuous"
 msgstr ""
 
-#: backend/lpd.c:1008 backend/lpd.c:1140
+#: backend/lpd.c:1020 backend/lpd.c:1152
 msgid "Control file sent successfully."
 msgstr ""
 
-#: backend/ipp.c:1224 backend/lpd.c:460
+#: backend/ipp.c:1223 backend/lpd.c:464
 msgid "Copying print data."
 msgstr ""
 
-#: cups/http-support.c:1251
+#: cups/http-support.c:1254
 msgid "Created"
 msgstr ""
 
@@ -3102,7 +3096,7 @@ msgstr ""
 msgid "Darkness"
 msgstr ""
 
-#: backend/lpd.c:1093
+#: backend/lpd.c:1105
 msgid "Data file sent successfully."
 msgstr ""
 
@@ -3118,7 +3112,7 @@ msgstr ""
 msgid "DeskJet Series"
 msgstr ""
 
-#: scheduler/ipp.c:1364
+#: scheduler/ipp.c:1358
 #, c-format
 msgid "Destination \"%s\" is not accepting jobs."
 msgstr ""
@@ -3167,7 +3161,7 @@ msgstr ""
 msgid "Disabled"
 msgstr ""
 
-#: scheduler/ipp.c:7004
+#: scheduler/ipp.c:6821
 #, c-format
 msgid "Document #%d does not exist in job #%d."
 msgstr ""
@@ -3496,7 +3490,7 @@ msgstr ""
 msgid "Executive"
 msgstr ""
 
-#: cups/http-support.c:1297
+#: cups/http-support.c:1300
 msgid "Expectation Failed"
 msgstr ""
 
@@ -3559,7 +3553,7 @@ msgstr ""
 msgid "File Folder - 9/16 x 3 7/16\""
 msgstr ""
 
-#: scheduler/ipp.c:2388
+#: scheduler/ipp.c:2382
 #, c-format
 msgid "File device URIs have been disabled. To enable, see the FileDevice directive in \"%s/cupsd.conf\"."
 msgstr ""
@@ -3574,7 +3568,7 @@ msgstr ""
 msgid "Folio"
 msgstr ""
 
-#: cups/http-support.c:1276
+#: cups/http-support.c:1279
 msgid "Forbidden"
 msgstr ""
 
@@ -3594,10 +3588,10 @@ msgstr ""
 msgid "Glossy Paper"
 msgstr ""
 
-#: scheduler/ipp.c:3858 scheduler/ipp.c:4258 scheduler/ipp.c:4796
-#: scheduler/ipp.c:6933 scheduler/ipp.c:7080 scheduler/ipp.c:8512
-#: scheduler/ipp.c:9630 scheduler/ipp.c:9855 scheduler/ipp.c:10204
-#: scheduler/ipp.c:10807
+#: scheduler/ipp.c:3675 scheduler/ipp.c:4075 scheduler/ipp.c:4613
+#: scheduler/ipp.c:6750 scheduler/ipp.c:6897 scheduler/ipp.c:8329
+#: scheduler/ipp.c:9447 scheduler/ipp.c:9673 scheduler/ipp.c:10022
+#: scheduler/ipp.c:10625
 msgid "Got a printer-uri attribute but no job-id."
 msgstr ""
 
@@ -3625,7 +3619,7 @@ msgstr ""
 msgid "IPP attribute has no name."
 msgstr ""
 
-#: cups/ipp.c:5515
+#: cups/ipp.c:5519
 msgid "IPP attribute is not a member of the message."
 msgstr ""
 
@@ -3733,7 +3727,7 @@ msgstr ""
 msgid "Intellitech"
 msgstr ""
 
-#: cups/http-support.c:1303
+#: cups/http-support.c:1306
 msgid "Internal Server Error"
 msgstr ""
 
@@ -3757,7 +3751,7 @@ msgstr ""
 msgid "Internet Postage 3-Part - 2 1/4 x 7\""
 msgstr ""
 
-#: backend/ipp.c:302
+#: backend/ipp.c:305
 msgid "Internet Printing Protocol"
 msgstr ""
 
@@ -3765,6 +3759,11 @@ msgstr ""
 msgid "Invalid media size."
 msgstr ""
 
+#: filter/commandtops.c:125
+#, c-format
+msgid "Invalid printer command \"%s\"."
+msgstr ""
+
 #: cups/ppd.c:1420
 msgid "JCL"
 msgstr ""
@@ -3825,52 +3824,52 @@ msgstr ""
 msgid "JIS B9"
 msgstr ""
 
-#: scheduler/ipp.c:9927
+#: scheduler/ipp.c:9745
 #, c-format
 msgid "Job #%d cannot be restarted - no files."
 msgstr ""
 
-#: scheduler/ipp.c:3898 scheduler/ipp.c:4128 scheduler/ipp.c:4183
-#: scheduler/ipp.c:4360 scheduler/ipp.c:4806 scheduler/ipp.c:6595
-#: scheduler/ipp.c:6973 scheduler/ipp.c:7120 scheduler/ipp.c:7420
-#: scheduler/ipp.c:8359 scheduler/ipp.c:8381 scheduler/ipp.c:8553
-#: scheduler/ipp.c:8778 scheduler/ipp.c:8821 scheduler/ipp.c:9670
-#: scheduler/ipp.c:9895 scheduler/ipp.c:10244 scheduler/ipp.c:10847
+#: scheduler/ipp.c:3715 scheduler/ipp.c:3945 scheduler/ipp.c:4000
+#: scheduler/ipp.c:4177 scheduler/ipp.c:4623 scheduler/ipp.c:6412
+#: scheduler/ipp.c:6790 scheduler/ipp.c:6937 scheduler/ipp.c:7237
+#: scheduler/ipp.c:8176 scheduler/ipp.c:8198 scheduler/ipp.c:8370
+#: scheduler/ipp.c:8595 scheduler/ipp.c:8638 scheduler/ipp.c:9487
+#: scheduler/ipp.c:9713 scheduler/ipp.c:10062 scheduler/ipp.c:10665
 #, c-format
 msgid "Job #%d does not exist."
 msgstr ""
 
-#: scheduler/ipp.c:4392
+#: scheduler/ipp.c:4209
 #, c-format
 msgid "Job #%d is already aborted - can't cancel."
 msgstr ""
 
-#: scheduler/ipp.c:4386
+#: scheduler/ipp.c:4203
 #, c-format
 msgid "Job #%d is already canceled - can't cancel."
 msgstr ""
 
-#: scheduler/ipp.c:4398
+#: scheduler/ipp.c:4215
 #, c-format
 msgid "Job #%d is already completed - can't cancel."
 msgstr ""
 
-#: scheduler/ipp.c:8579 scheduler/ipp.c:8863 scheduler/ipp.c:10862
+#: scheduler/ipp.c:8396 scheduler/ipp.c:8680 scheduler/ipp.c:10680
 #, c-format
 msgid "Job #%d is finished and cannot be altered."
 msgstr ""
 
-#: scheduler/ipp.c:9909
+#: scheduler/ipp.c:9727
 #, c-format
 msgid "Job #%d is not complete."
 msgstr ""
 
-#: scheduler/ipp.c:3913
+#: scheduler/ipp.c:3730
 #, c-format
 msgid "Job #%d is not held for authentication."
 msgstr ""
 
-#: scheduler/ipp.c:9684
+#: scheduler/ipp.c:9501
 #, c-format
 msgid "Job #%d is not held."
 msgstr ""
@@ -3891,7 +3890,7 @@ msgstr ""
 msgid "Job Stopped"
 msgstr ""
 
-#: scheduler/ipp.c:10944
+#: scheduler/ipp.c:10762
 msgid "Job is completed and cannot be changed."
 msgstr ""
 
@@ -3899,11 +3898,11 @@ msgstr ""
 msgid "Job operation failed:"
 msgstr ""
 
-#: scheduler/ipp.c:10980 scheduler/ipp.c:10999 scheduler/ipp.c:11010
+#: scheduler/ipp.c:10798 scheduler/ipp.c:10817 scheduler/ipp.c:10828
 msgid "Job state cannot be changed."
 msgstr ""
 
-#: scheduler/ipp.c:9775
+#: scheduler/ipp.c:9593
 msgid "Job subscriptions cannot be renewed."
 msgstr ""
 
@@ -3911,7 +3910,7 @@ msgstr ""
 msgid "Jobs"
 msgstr ""
 
-#: backend/lpd.c:183
+#: backend/lpd.c:185
 msgid "LPD/LPR Host or Printer"
 msgstr ""
 
@@ -3923,7 +3922,7 @@ msgstr ""
 msgid "Label Top"
 msgstr ""
 
-#: scheduler/ipp.c:2088 scheduler/ipp.c:6518
+#: scheduler/ipp.c:2082 scheduler/ipp.c:6335
 #, c-format
 msgid "Language \"%s\" not supported."
 msgstr ""
@@ -3964,7 +3963,7 @@ msgstr ""
 msgid "Long-Edge (Portrait)"
 msgstr ""
 
-#: cups/http-support.c:1518
+#: cups/http-support.c:1525
 msgid "Looking for printer."
 msgstr ""
 
@@ -4008,7 +4007,7 @@ msgstr ""
 msgid "Missing asterisk in column 1"
 msgstr ""
 
-#: scheduler/ipp.c:6996
+#: scheduler/ipp.c:6813
 msgid "Missing document-number attribute."
 msgstr ""
 
@@ -4023,7 +4022,7 @@ msgstr ""
 msgid "Missing form variable"
 msgstr ""
 
-#: scheduler/ipp.c:10298
+#: scheduler/ipp.c:10116
 msgid "Missing last-document attribute in request."
 msgstr ""
 
@@ -4035,7 +4034,7 @@ msgstr ""
 msgid "Missing media-size in media-col."
 msgstr ""
 
-#: scheduler/ipp.c:7550
+#: scheduler/ipp.c:7367
 msgid "Missing notify-subscription-ids attribute."
 msgstr ""
 
@@ -4043,11 +4042,11 @@ msgstr ""
 msgid "Missing option keyword"
 msgstr ""
 
-#: scheduler/ipp.c:4039 scheduler/ipp.c:4064
+#: scheduler/ipp.c:3856 scheduler/ipp.c:3881
 msgid "Missing requesting-user-name attribute."
 msgstr ""
 
-#: scheduler/ipp.c:479
+#: scheduler/ipp.c:473
 msgid "Missing required attributes."
 msgstr ""
 
@@ -4093,7 +4092,7 @@ msgstr ""
 msgid "Move Job"
 msgstr ""
 
-#: cups/http-support.c:1260
+#: cups/http-support.c:1263
 msgid "Moved Permanently"
 msgstr ""
 
@@ -4105,7 +4104,7 @@ msgstr ""
 msgid "Name OID uses indefinite length"
 msgstr ""
 
-#: scheduler/ipp.c:1160
+#: scheduler/ipp.c:1154
 msgid "Nested classes are not allowed."
 msgstr ""
 
@@ -4125,7 +4124,7 @@ msgstr ""
 msgid "No"
 msgstr ""
 
-#: cups/http-support.c:1257
+#: cups/http-support.c:1260
 msgid "No Content"
 msgstr ""
 
@@ -4145,16 +4144,16 @@ msgstr ""
 msgid "No active connection"
 msgstr ""
 
-#: scheduler/ipp.c:4309
+#: scheduler/ipp.c:4126
 #, c-format
 msgid "No active jobs on %s."
 msgstr ""
 
-#: scheduler/ipp.c:320
+#: scheduler/ipp.c:314
 msgid "No attributes in request."
 msgstr ""
 
-#: scheduler/ipp.c:3940
+#: scheduler/ipp.c:3757
 msgid "No authentication information provided."
 msgstr ""
 
@@ -4162,11 +4161,11 @@ msgstr ""
 msgid "No community name"
 msgstr ""
 
-#: scheduler/ipp.c:6796
+#: scheduler/ipp.c:6613
 msgid "No default printer."
 msgstr ""
 
-#: cgi-bin/ipp-var.c:436 scheduler/ipp.c:8125
+#: cgi-bin/ipp-var.c:436 scheduler/ipp.c:7942
 msgid "No destinations added."
 msgstr ""
 
@@ -4182,7 +4181,7 @@ msgstr ""
 msgid "No error-status"
 msgstr ""
 
-#: scheduler/ipp.c:9067 scheduler/ipp.c:10312
+#: scheduler/ipp.c:8884 scheduler/ipp.c:10130
 msgid "No file in print request."
 msgstr ""
 
@@ -4211,7 +4210,7 @@ msgstr ""
 msgid "No printer-uri found for class"
 msgstr ""
 
-#: scheduler/ipp.c:7199
+#: scheduler/ipp.c:7016
 msgid "No printer-uri in request."
 msgstr ""
 
@@ -4219,11 +4218,11 @@ msgstr ""
 msgid "No request-id"
 msgstr ""
 
-#: scheduler/ipp.c:6403
+#: scheduler/ipp.c:6220
 msgid "No subscription attributes in request."
 msgstr ""
 
-#: scheduler/ipp.c:8452
+#: scheduler/ipp.c:8269
 msgid "No subscriptions found."
 msgstr ""
 
@@ -4247,11 +4246,11 @@ msgstr ""
 msgid "Normal"
 msgstr ""
 
-#: cups/http-support.c:1279
+#: cups/http-support.c:1282
 msgid "Not Found"
 msgstr ""
 
-#: cups/http-support.c:1291
+#: cups/http-support.c:1294
 msgid "Not Implemented"
 msgstr ""
 
@@ -4259,15 +4258,15 @@ msgstr ""
 msgid "Not Installed"
 msgstr ""
 
-#: cups/http-support.c:1266
+#: cups/http-support.c:1269
 msgid "Not Modified"
 msgstr ""
 
-#: cups/http-support.c:1294
+#: cups/http-support.c:1297
 msgid "Not Supported"
 msgstr ""
 
-#: scheduler/ipp.c:1536 scheduler/ipp.c:11542
+#: scheduler/ipp.c:1530 scheduler/ipp.c:11360
 msgid "Not allowed to print."
 msgstr ""
 
@@ -4279,7 +4278,7 @@ msgstr ""
 msgid "Note: this program only validates the DSC comments, not the PostScript itself."
 msgstr ""
 
-#: cups/http-support.c:1248 cups/ppd.c:338
+#: cups/http-support.c:1251 cups/ppd.c:338
 msgid "OK"
 msgstr ""
 
@@ -4322,11 +4321,10 @@ msgid "Options Installed"
 msgstr ""
 
 #: scheduler/cupsfilter.c:1438 scheduler/cupsfilter.c:1465
-#: scheduler/main.c:1988 systemv/cupsaddsmb.c:284 systemv/cupsctl.c:203
-#: systemv/cupstestdsc.c:429 systemv/cupstestppd.c:3777
-#: test/ipptool-with-progress.c:4290 test/ipptool.c:4311 ppdc/ppdc.cxx:437
-#: ppdc/ppdhtml.cxx:174 ppdc/ppdi.cxx:130 ppdc/ppdmerge.cxx:369
-#: ppdc/ppdpo.cxx:254
+#: scheduler/main.c:2019 systemv/cupsaddsmb.c:284 systemv/cupsctl.c:203
+#: systemv/cupstestdsc.c:429 systemv/cupstestppd.c:3796 test/ipptool.c:4336
+#: ppdc/ppdc.cxx:437 ppdc/ppdhtml.cxx:174 ppdc/ppdi.cxx:130
+#: ppdc/ppdmerge.cxx:369 ppdc/ppdpo.cxx:254
 msgid "Options:"
 msgstr ""
 
@@ -4334,7 +4332,7 @@ msgstr ""
 msgid "Out of date PPD cache file."
 msgstr ""
 
-#: cups/ppd-cache.c:1363
+#: cups/ppd-cache.c:1381
 msgid "Out of memory."
 msgstr ""
 
@@ -4410,7 +4408,7 @@ msgstr ""
 msgid "ParamCustominTearInterval"
 msgstr ""
 
-#: cups/auth.c:196 cups/auth.c:365
+#: cups/auth.c:199 cups/auth.c:367
 #, c-format
 msgid "Password for %s on %s? "
 msgstr ""
@@ -4508,12 +4506,12 @@ msgstr ""
 msgid "Print and Tear"
 msgstr ""
 
-#: backend/ipp.c:1520
+#: backend/ipp.c:1523
 #, c-format
 msgid "Print file accepted - job ID %d."
 msgstr ""
 
-#: backend/ipp.c:1511
+#: backend/ipp.c:1513
 msgid "Print file accepted - job ID unknown."
 msgstr ""
 
@@ -4521,11 +4519,11 @@ msgstr ""
 msgid "Print file sent."
 msgstr ""
 
-#: backend/ipp.c:1473
+#: backend/ipp.c:1474
 msgid "Print file was not accepted."
 msgstr ""
 
-#: backend/ipp.c:1864
+#: backend/ipp.c:1875
 msgid "Print job too large."
 msgstr ""
 
@@ -4557,11 +4555,11 @@ msgstr ""
 msgid "Printer busy, will retry in 10 seconds."
 msgstr ""
 
-#: backend/lpd.c:611 backend/lpd.c:997 backend/lpd.c:1079 backend/lpd.c:1129
+#: backend/lpd.c:619 backend/lpd.c:1009 backend/lpd.c:1091 backend/lpd.c:1141
 msgid "Printer did not respond."
 msgstr ""
 
-#: backend/ipp.c:877 backend/ipp.c:884
+#: backend/ipp.c:885 backend/ipp.c:892
 #, c-format
 msgid "Printer does not support IPP/%d.%d, trying IPP/%s."
 msgstr ""
@@ -4612,7 +4610,7 @@ msgstr ""
 msgid "Quarto"
 msgstr ""
 
-#: scheduler/ipp.c:1531 scheduler/ipp.c:11537
+#: scheduler/ipp.c:1525 scheduler/ipp.c:11355
 msgid "Quota limit reached."
 msgstr ""
 
@@ -4625,7 +4623,7 @@ msgstr ""
 msgid "Rank   Owner      Pri  Job        Files                       Total Size"
 msgstr ""
 
-#: backend/ipp.c:1871 backend/socket.c:475 filter/rastertoepson.c:1152
+#: backend/ipp.c:1882 backend/socket.c:475 filter/rastertoepson.c:1152
 #: filter/rastertohp.c:881 filter/rastertolabel.c:1307
 msgid "Ready to print."
 msgstr ""
@@ -4634,12 +4632,12 @@ msgstr ""
 msgid "Reject Jobs"
 msgstr ""
 
-#: backend/lpd.c:1004 backend/lpd.c:1136
+#: backend/lpd.c:1016 backend/lpd.c:1148
 #, c-format
 msgid "Remote host did not accept control file (%d)."
 msgstr ""
 
-#: backend/lpd.c:1089
+#: backend/lpd.c:1101
 #, c-format
 msgid "Remote host did not accept data file (%d)."
 msgstr ""
@@ -4648,7 +4646,7 @@ msgstr ""
 msgid "Reprint After Error"
 msgstr ""
 
-#: cups/http-support.c:1282
+#: cups/http-support.c:1285
 msgid "Request Entity Too Large"
 msgstr ""
 
@@ -4685,15 +4683,15 @@ msgstr ""
 msgid "SEQUENCE uses indefinite length"
 msgstr ""
 
-#: cups/http-support.c:1306
+#: cups/http-support.c:1309
 msgid "SSL/TLS Negotiation Error"
 msgstr ""
 
-#: cups/http-support.c:1263
+#: cups/http-support.c:1266
 msgid "See Other"
 msgstr ""
 
-#: backend/usb-darwin.c:543 backend/usb-libusb.c:273 patches/usb-libusb.c:289
+#: backend/usb-darwin.c:543 backend/usb-libusb.c:273
 msgid "Sending data to printer."
 msgstr ""
 
@@ -4713,7 +4711,7 @@ msgstr ""
 msgid "Server Stopped"
 msgstr ""
 
-#: cups/http-support.c:1300
+#: cups/http-support.c:1303
 msgid "Service Unavailable"
 msgstr ""
 
@@ -4754,7 +4752,7 @@ msgstr ""
 msgid "Special Paper"
 msgstr ""
 
-#: backend/lpd.c:1045
+#: backend/lpd.c:1057
 #, c-format
 msgid "Spooling job, %.0f%% complete."
 msgstr ""
@@ -4786,8 +4784,8 @@ msgstr ""
 msgid "Stylus Photo Series"
 msgstr ""
 
-#: scheduler/ipp.c:4455 scheduler/ipp.c:7566 scheduler/ipp.c:8265
-#: scheduler/ipp.c:9763
+#: scheduler/ipp.c:4272 scheduler/ipp.c:7383 scheduler/ipp.c:8082
+#: scheduler/ipp.c:9581
 #, c-format
 msgid "Subscription #%d does not exist."
 msgstr ""
@@ -4804,7 +4802,7 @@ msgstr ""
 msgid "Super B/A3"
 msgstr ""
 
-#: cups/http-support.c:1245
+#: cups/http-support.c:1248
 msgid "Switching Protocols"
 msgstr ""
 
@@ -4832,18 +4830,18 @@ msgstr ""
 msgid "Tear-Off Adjust Position"
 msgstr ""
 
-#: scheduler/ipp.c:7270 scheduler/ipp.c:7348 scheduler/ipp.c:7364
-#: scheduler/ipp.c:7382
+#: scheduler/ipp.c:7087 scheduler/ipp.c:7165 scheduler/ipp.c:7181
+#: scheduler/ipp.c:7199
 #, c-format
 msgid "The %s attribute cannot be provided with job-ids."
 msgstr ""
 
-#: scheduler/ipp.c:7796
+#: scheduler/ipp.c:7613
 #, c-format
 msgid "The PPD file \"%s\" could not be found."
 msgstr ""
 
-#: scheduler/ipp.c:7783
+#: scheduler/ipp.c:7600
 #, c-format
 msgid "The PPD file \"%s\" could not be opened: %s"
 msgstr ""
@@ -4873,11 +4871,11 @@ msgstr ""
 msgid "The fuser's temperature is low."
 msgstr ""
 
-#: scheduler/ipp.c:2115
+#: scheduler/ipp.c:2109
 msgid "The notify-lease-duration attribute cannot be used with job subscriptions."
 msgstr ""
 
-#: scheduler/ipp.c:2098 scheduler/ipp.c:6528
+#: scheduler/ipp.c:2092 scheduler/ipp.c:6345
 #, c-format
 msgid "The notify-user-data value is too large (%d > 63 octets)."
 msgstr ""
@@ -4918,37 +4916,33 @@ msgstr ""
 msgid "The paper tray needs to be filled."
 msgstr ""
 
-#: backend/ipp.c:894
+#: backend/ipp.c:902
 msgid "The printer URI is incorrect or no longer exists."
 msgstr ""
 
-#: backend/ipp.c:746 backend/ipp.c:859 backend/ipp.c:964 backend/ipp.c:1303
-#: backend/ipp.c:1451 backend/lpd.c:819 backend/socket.c:374
+#: backend/ipp.c:752 backend/ipp.c:867 backend/ipp.c:973 backend/ipp.c:1302
+#: backend/ipp.c:1450 backend/lpd.c:828 backend/socket.c:374
 msgid "The printer is busy."
 msgstr ""
 
-#: cups/localize.c:313
-msgid "The printer is low on toner."
-msgstr ""
-
 #: cups/localize.c:311
 msgid "The printer is not connected."
 msgstr ""
 
-#: backend/ipp.c:724 backend/ipp.c:757 backend/ipp.c:855 backend/lpd.c:798
-#: backend/lpd.c:839 backend/socket.c:353 backend/socket.c:386
+#: backend/ipp.c:730 backend/ipp.c:763 backend/ipp.c:863 backend/lpd.c:807
+#: backend/lpd.c:848 backend/socket.c:353 backend/socket.c:386
 msgid "The printer is not responding."
 msgstr ""
 
-#: cups/localize.c:315
-msgid "The printer is out of toner."
-msgstr ""
-
 #: cups/localize.c:335
 msgid "The printer is running low on ink."
 msgstr ""
 
-#: backend/ipp.c:739 backend/lpd.c:812 backend/socket.c:367
+#: cups/localize.c:313
+msgid "The printer is running low on toner."
+msgstr ""
+
+#: backend/ipp.c:745 backend/lpd.c:821 backend/socket.c:367
 msgid "The printer is unreachable at this time."
 msgstr ""
 
@@ -4956,7 +4950,11 @@ msgstr ""
 msgid "The printer may be out of ink."
 msgstr ""
 
-#: backend/ipp.c:733 backend/lpd.c:806 backend/socket.c:361
+#: cups/localize.c:315
+msgid "The printer may be out of toner."
+msgstr ""
+
+#: backend/ipp.c:739 backend/lpd.c:815 backend/socket.c:361
 msgid "The printer may not exist or is unavailable at this time."
 msgstr ""
 
@@ -4964,18 +4962,18 @@ msgstr ""
 msgid "The printer name may only contain up to 127 printable characters and may not contain spaces, slashes (/), or the pound sign (#)."
 msgstr ""
 
-#: scheduler/ipp.c:894 scheduler/ipp.c:1154 scheduler/ipp.c:4104
-#: scheduler/ipp.c:4275 scheduler/ipp.c:5999 scheduler/ipp.c:6362
-#: scheduler/ipp.c:6676 scheduler/ipp.c:7236 scheduler/ipp.c:8001
-#: scheduler/ipp.c:8057 scheduler/ipp.c:8371 scheduler/ipp.c:8637
-#: scheduler/ipp.c:8726 scheduler/ipp.c:8759 scheduler/ipp.c:9082
-#: scheduler/ipp.c:9475 scheduler/ipp.c:9556 scheduler/ipp.c:10716
-#: scheduler/ipp.c:11170 scheduler/ipp.c:11500 scheduler/ipp.c:11582
-#: scheduler/ipp.c:11874
+#: scheduler/ipp.c:888 scheduler/ipp.c:1148 scheduler/ipp.c:3921
+#: scheduler/ipp.c:4092 scheduler/ipp.c:5816 scheduler/ipp.c:6179
+#: scheduler/ipp.c:6493 scheduler/ipp.c:7053 scheduler/ipp.c:7818
+#: scheduler/ipp.c:7874 scheduler/ipp.c:8188 scheduler/ipp.c:8454
+#: scheduler/ipp.c:8543 scheduler/ipp.c:8576 scheduler/ipp.c:8899
+#: scheduler/ipp.c:9292 scheduler/ipp.c:9373 scheduler/ipp.c:10534
+#: scheduler/ipp.c:10988 scheduler/ipp.c:11318 scheduler/ipp.c:11400
+#: scheduler/ipp.c:11692
 msgid "The printer or class does not exist."
 msgstr ""
 
-#: scheduler/ipp.c:1322
+#: scheduler/ipp.c:1316
 msgid "The printer or class is not shared."
 msgstr ""
 
@@ -4999,20 +4997,20 @@ msgstr ""
 msgid "The printer's waste bin is full."
 msgstr ""
 
-#: scheduler/ipp.c:1000 scheduler/ipp.c:2279
+#: scheduler/ipp.c:994 scheduler/ipp.c:2273
 #, c-format
 msgid "The printer-uri \"%s\" contains invalid characters."
 msgstr ""
 
-#: scheduler/ipp.c:4081
+#: scheduler/ipp.c:3898
 msgid "The printer-uri attribute is required."
 msgstr ""
 
-#: scheduler/ipp.c:984
+#: scheduler/ipp.c:978
 msgid "The printer-uri must be of the form \"ipp://HOSTNAME/classes/CLASSNAME\"."
 msgstr ""
 
-#: scheduler/ipp.c:2263
+#: scheduler/ipp.c:2257
 msgid "The printer-uri must be of the form \"ipp://HOSTNAME/printers/PRINTERNAME\"."
 msgstr ""
 
@@ -5024,12 +5022,12 @@ msgstr ""
 msgid "The web interface is currently disabled. Run \"cupsctl WebInterface=yes\" to enable it."
 msgstr ""
 
-#: scheduler/ipp.c:7331
+#: scheduler/ipp.c:7148
 #, c-format
 msgid "The which-jobs value \"%s\" is not supported."
 msgstr ""
 
-#: scheduler/ipp.c:6606
+#: scheduler/ipp.c:6423
 msgid "There are too many subscriptions."
 msgstr ""
 
@@ -5039,7 +5037,6 @@ msgstr ""
 
 #: backend/usb-darwin.c:379 backend/usb-darwin.c:438 backend/usb-darwin.c:505
 #: backend/usb-darwin.c:526 backend/usb-libusb.c:235 backend/usb-libusb.c:256
-#: patches/usb-libusb.c:251 patches/usb-libusb.c:272
 msgid "There was an unrecoverable USB error."
 msgstr ""
 
@@ -5047,16 +5044,16 @@ msgstr ""
 msgid "Thermal Transfer Media"
 msgstr ""
 
-#: scheduler/ipp.c:1525
+#: scheduler/ipp.c:1519
 msgid "Too many active jobs."
 msgstr ""
 
-#: scheduler/ipp.c:1419
+#: scheduler/ipp.c:1413
 #, c-format
 msgid "Too many job-sheets values (%d > 2)."
 msgstr ""
 
-#: scheduler/ipp.c:2547
+#: scheduler/ipp.c:2541
 #, c-format
 msgid "Too many printer-state-reasons values (%d > %d)."
 msgstr ""
@@ -5085,7 +5082,7 @@ msgstr ""
 msgid "Tray 4"
 msgstr ""
 
-#: cups/http-support.c:1285
+#: cups/http-support.c:1288
 msgid "URI Too Long"
 msgstr ""
 
@@ -5133,11 +5130,11 @@ msgstr ""
 msgid "Unable to add class:"
 msgstr ""
 
-#: backend/ipp.c:1616
+#: backend/ipp.c:1620
 msgid "Unable to add document to print job."
 msgstr ""
 
-#: scheduler/ipp.c:1566
+#: scheduler/ipp.c:1560
 #, c-format
 msgid "Unable to add job for destination \"%s\"."
 msgstr ""
@@ -5146,7 +5143,7 @@ msgstr ""
 msgid "Unable to add printer:"
 msgstr ""
 
-#: scheduler/ipp.c:1264
+#: scheduler/ipp.c:1258
 msgid "Unable to allocate memory for file types."
 msgstr ""
 
@@ -5162,7 +5159,7 @@ msgstr ""
 msgid "Unable to cancel RSS subscription:"
 msgstr ""
 
-#: backend/ipp.c:1913
+#: backend/ipp.c:1924
 msgid "Unable to cancel print job."
 msgstr ""
 
@@ -5178,11 +5175,15 @@ msgstr ""
 msgid "Unable to change server settings:"
 msgstr ""
 
+#: filter/commandtops.c:421
+msgid "Unable to configure printer options."
+msgstr ""
+
 #: cups/adminutil.c:911 cups/request.c:1022
 msgid "Unable to connect to host."
 msgstr ""
 
-#: backend/ipp.c:702 backend/ipp.c:1124 backend/lpd.c:778 backend/socket.c:333
+#: backend/ipp.c:708 backend/ipp.c:1123 backend/lpd.c:787 backend/socket.c:333
 #: backend/usb-unix.c:117
 msgid "Unable to contact printer, queuing on next printer in class."
 msgstr ""
@@ -5202,12 +5203,12 @@ msgstr ""
 msgid "Unable to copy CUPS printer driver files (%d)."
 msgstr ""
 
-#: scheduler/ipp.c:2667
+#: scheduler/ipp.c:2661
 #, c-format
 msgid "Unable to copy PPD file - %s"
 msgstr ""
 
-#: scheduler/ipp.c:2722
+#: scheduler/ipp.c:2716
 msgid "Unable to copy PPD file."
 msgstr ""
 
@@ -5221,12 +5222,12 @@ msgstr ""
 msgid "Unable to copy Windows 9x printer driver files (%d)."
 msgstr ""
 
-#: scheduler/ipp.c:2644
+#: scheduler/ipp.c:2638
 #, c-format
 msgid "Unable to copy interface script - %s"
 msgstr ""
 
-#: backend/ipp.c:2002
+#: backend/ipp.c:2016
 msgid "Unable to create compressed print file"
 msgstr ""
 
@@ -5258,35 +5259,35 @@ msgstr ""
 msgid "Unable to edit cupsd.conf files larger than 1MB"
 msgstr ""
 
-#: cups/http.c:4235
+#: cups/http.c:4258
 msgid "Unable to establish a secure connection to host (certificate chain invalid)."
 msgstr ""
 
-#: cups/http.c:4225
+#: cups/http.c:4248
 msgid "Unable to establish a secure connection to host (certificate not yet valid)."
 msgstr ""
 
-#: cups/http.c:4220
+#: cups/http.c:4243
 msgid "Unable to establish a secure connection to host (expired certificate)."
 msgstr ""
 
-#: cups/http.c:4230
+#: cups/http.c:4253
 msgid "Unable to establish a secure connection to host (host name mismatch)."
 msgstr ""
 
-#: cups/http.c:4240
+#: cups/http.c:4263
 msgid "Unable to establish a secure connection to host (peer dropped connection before responding)."
 msgstr ""
 
-#: cups/http.c:4215
+#: cups/http.c:4238
 msgid "Unable to establish a secure connection to host (self-signed certificate)."
 msgstr ""
 
-#: cups/http.c:4210
+#: cups/http.c:4233
 msgid "Unable to establish a secure connection to host (untrusted certificate)."
 msgstr ""
 
-#: cups/http.c:3972 cups/http.c:4267 cups/http.c:4300 cups/http.c:4317
+#: cups/http.c:3995 cups/http.c:4290 cups/http.c:4323 cups/http.c:4340
 msgid "Unable to establish a secure connection to host."
 msgstr ""
 
@@ -5294,15 +5295,15 @@ msgstr ""
 msgid "Unable to find destination for job"
 msgstr ""
 
-#: cups/http-support.c:1631
+#: cups/http-support.c:1644
 msgid "Unable to find printer."
 msgstr ""
 
-#: backend/ipp.c:2024
+#: backend/ipp.c:2038
 msgid "Unable to generate compressed print file"
 msgstr ""
 
-#: backend/ipp.c:2920
+#: backend/ipp.c:2945
 msgid "Unable to get backend exit status."
 msgstr ""
 
@@ -5326,7 +5327,7 @@ msgstr ""
 msgid "Unable to get printer list:"
 msgstr ""
 
-#: backend/ipp.c:917
+#: backend/ipp.c:926
 msgid "Unable to get printer status."
 msgstr ""
 
@@ -5344,12 +5345,12 @@ msgstr ""
 msgid "Unable to install Windows 9x printer driver files (%d)."
 msgstr ""
 
-#: backend/ipp.c:634 backend/lpd.c:417 backend/socket.c:275
+#: backend/ipp.c:640 backend/lpd.c:421 backend/socket.c:275
 #, c-format
 msgid "Unable to locate printer \"%s\"."
 msgstr ""
 
-#: backend/dnssd.c:529 backend/ipp.c:319 backend/lpd.c:200
+#: backend/dnssd.c:529 backend/ipp.c:322 backend/lpd.c:204
 #: backend/socket.c:171
 msgid "Unable to locate printer."
 msgstr ""
@@ -5378,7 +5379,7 @@ msgstr ""
 msgid "Unable to open PPD file:"
 msgstr ""
 
-#: backend/ipp.c:2008
+#: backend/ipp.c:2022
 msgid "Unable to open compressed print file"
 msgstr ""
 
@@ -5390,13 +5391,13 @@ msgstr ""
 msgid "Unable to open device file"
 msgstr ""
 
-#: scheduler/ipp.c:7017
+#: scheduler/ipp.c:6834
 #, c-format
 msgid "Unable to open document #%d in job #%d."
 msgstr ""
 
-#: backend/ipp.c:360 backend/ipp.c:1385 backend/ipp.c:1576 backend/ipp.c:2014
-#: backend/lpd.c:484 backend/socket.c:158 backend/usb.c:237
+#: backend/ipp.c:363 backend/ipp.c:1384 backend/ipp.c:1580 backend/ipp.c:2028
+#: backend/lpd.c:488 backend/socket.c:158 backend/usb.c:237
 #: filter/gziptoany.c:71 filter/pstops.c:300
 msgid "Unable to open print file"
 msgstr ""
@@ -5415,7 +5416,7 @@ msgid "Unable to read print data"
 msgstr ""
 
 #: backend/usb-darwin.c:613 backend/usb-darwin.c:657 backend/usb-libusb.c:343
-#: backend/usb-libusb.c:378 patches/usb-libusb.c:359 patches/usb-libusb.c:403
+#: backend/usb-libusb.c:378
 msgid "Unable to read print data."
 msgstr ""
 
@@ -5436,7 +5437,7 @@ msgstr ""
 msgid "Unable to send command to printer driver"
 msgstr ""
 
-#: backend/usb-darwin.c:735 backend/usb-libusb.c:454 patches/usb-libusb.c:483
+#: backend/usb-darwin.c:735 backend/usb-libusb.c:454
 msgid "Unable to send data to printer."
 msgstr ""
 
@@ -5453,7 +5454,7 @@ msgstr ""
 msgid "Unable to set server default:"
 msgstr ""
 
-#: backend/ipp.c:2779 backend/ipp.c:2856 backend/ipp.c:2864
+#: backend/ipp.c:2804 backend/ipp.c:2881 backend/ipp.c:2889
 msgid "Unable to start backend process."
 msgstr ""
 
@@ -5474,7 +5475,7 @@ msgstr ""
 msgid "Unable to write uncompressed print data: %s"
 msgstr ""
 
-#: cups/http-support.c:1273
+#: cups/http-support.c:1276
 msgid "Unauthorized"
 msgstr ""
 
@@ -5482,7 +5483,7 @@ msgstr ""
 msgid "Units"
 msgstr ""
 
-#: cups/http-support.c:1313 cups/ppd.c:366
+#: cups/http-support.c:1316 cups/ppd.c:366
 msgid "Unknown"
 msgstr ""
 
@@ -5491,17 +5492,17 @@ msgstr ""
 msgid "Unknown choice \"%s\" for option \"%s\"."
 msgstr ""
 
-#: backend/ipp.c:502
+#: backend/ipp.c:505
 #, c-format
 msgid "Unknown encryption option value: \"%s\"."
 msgstr ""
 
-#: backend/lpd.c:346
+#: backend/lpd.c:350
 #, c-format
 msgid "Unknown file order: \"%s\"."
 msgstr ""
 
-#: backend/lpd.c:317
+#: backend/lpd.c:321
 #, c-format
 msgid "Unknown format character: \"%c\"."
 msgstr ""
@@ -5510,7 +5511,7 @@ msgstr ""
 msgid "Unknown media size name."
 msgstr ""
 
-#: backend/ipp.c:549
+#: backend/ipp.c:552
 #, c-format
 msgid "Unknown option \"%s\" with value \"%s\"."
 msgstr ""
@@ -5520,17 +5521,17 @@ msgstr ""
 msgid "Unknown option \"%s\"."
 msgstr ""
 
-#: backend/lpd.c:332
+#: backend/lpd.c:336
 #, c-format
 msgid "Unknown print mode: \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:11372
+#: scheduler/ipp.c:11190
 #, c-format
 msgid "Unknown printer-error-policy \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:11355
+#: scheduler/ipp.c:11173
 #, c-format
 msgid "Unknown printer-op-policy \"%s\"."
 msgstr ""
@@ -5539,37 +5540,37 @@ msgstr ""
 msgid "Unknown service name."
 msgstr ""
 
-#: backend/ipp.c:521
+#: backend/ipp.c:524
 #, c-format
 msgid "Unknown version option value: \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:420
+#: scheduler/ipp.c:414
 #, c-format
 msgid "Unsupported character set \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:9048 scheduler/ipp.c:10277 scheduler/ipp.c:11826
+#: scheduler/ipp.c:8865 scheduler/ipp.c:10095 scheduler/ipp.c:11644
 #, c-format
 msgid "Unsupported compression \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:9182 scheduler/ipp.c:10427 scheduler/ipp.c:11855
+#: scheduler/ipp.c:8999 scheduler/ipp.c:10245 scheduler/ipp.c:11673
 #, c-format
 msgid "Unsupported document-format \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:10410
+#: scheduler/ipp.c:10228
 #, c-format
 msgid "Unsupported document-format \"%s/%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:1385
+#: scheduler/ipp.c:1379
 #, c-format
 msgid "Unsupported format \"%s\"."
 msgstr ""
 
-#: scheduler/ipp.c:1483
+#: scheduler/ipp.c:1477
 msgid "Unsupported margins."
 msgstr ""
 
@@ -5577,17 +5578,17 @@ msgstr ""
 msgid "Unsupported media value."
 msgstr ""
 
-#: filter/pstops.c:2480
+#: filter/pstops.c:2478
 #, c-format
 msgid "Unsupported number-up value %d, using number-up=1."
 msgstr ""
 
-#: filter/pstops.c:2514
+#: filter/pstops.c:2512
 #, c-format
 msgid "Unsupported number-up-layout value %s, using number-up-layout=lrtb."
 msgstr ""
 
-#: filter/pstops.c:2565
+#: filter/pstops.c:2563
 #, c-format
 msgid "Unsupported page-border value %s, using page-border=none."
 msgstr ""
@@ -5600,7 +5601,7 @@ msgstr ""
 msgid "Unsupported value type"
 msgstr ""
 
-#: cups/http-support.c:1288
+#: cups/http-support.c:1291
 msgid "Upgrade Required"
 msgstr ""
 
@@ -5616,13 +5617,13 @@ msgid ""
 "                       [-u allow:user,user] [-u deny:user,user]"
 msgstr ""
 
-#: backend/dnssd.c:174 backend/ipp.c:308 backend/lpd.c:189
+#: backend/dnssd.c:174 backend/ipp.c:311 backend/lpd.c:191
 #: backend/socket.c:135 backend/usb.c:183 monitor/bcp.c:62 monitor/tbcp.c:61
 #, c-format
 msgid "Usage: %s job-id user title copies options [file]"
 msgstr ""
 
-#: filter/commandtops.c:73 filter/gziptoany.c:50 filter/pstops.c:264
+#: filter/commandtops.c:74 filter/gziptoany.c:50 filter/pstops.c:264
 #, c-format
 msgid "Usage: %s job-id user title copies options file"
 msgstr ""
@@ -5639,7 +5640,7 @@ msgstr ""
 msgid "Usage: cupsctl [options] [param=value ... paramN=valueN]"
 msgstr ""
 
-#: scheduler/main.c:1987
+#: scheduler/main.c:2018
 msgid "Usage: cupsd [options]"
 msgstr ""
 
@@ -5651,11 +5652,11 @@ msgstr ""
 msgid "Usage: cupstestdsc [options] filename.ps [... filename.ps]"
 msgstr ""
 
-#: systemv/cupstestppd.c:3773
+#: systemv/cupstestppd.c:3792
 msgid "Usage: cupstestppd [options] filename1.ppd[.gz] [... filenameN.ppd[.gz]]"
 msgstr ""
 
-#: test/ipptool-with-progress.c:4288 test/ipptool.c:4309
+#: test/ipptool.c:4334
 msgid "Usage: ipptool [options] URI filename [ ... filenameN ]"
 msgstr ""
 
@@ -5722,11 +5723,11 @@ msgstr ""
 msgid "Version uses indefinite length"
 msgstr ""
 
-#: backend/ipp.c:1651
+#: backend/ipp.c:1660
 msgid "Waiting for job to complete."
 msgstr ""
 
-#: backend/usb-darwin.c:457 backend/usb-libusb.c:193 patches/usb-libusb.c:209
+#: backend/usb-darwin.c:457 backend/usb-libusb.c:193
 msgid "Waiting for printer to become available."
 msgstr ""
 
@@ -5738,7 +5739,7 @@ msgstr ""
 msgid "Warning, no Windows 2000 printer drivers are installed."
 msgstr ""
 
-#: cups/http-support.c:1309
+#: cups/http-support.c:1312
 msgid "Web Interface is Disabled"
 msgstr ""
 
@@ -5779,11 +5780,11 @@ msgstr ""
 msgid "convert: Use the -f option to specify a file to convert."
 msgstr ""
 
-#: scheduler/ipp.c:6889
+#: scheduler/ipp.c:6706
 msgid "cups-deviced failed to execute."
 msgstr ""
 
-#: scheduler/ipp.c:7719 scheduler/ipp.c:7968
+#: scheduler/ipp.c:7536 scheduler/ipp.c:7785
 msgid "cups-driverd failed to execute."
 msgstr ""
 
@@ -5811,25 +5812,25 @@ msgstr ""
 msgid "cupsctl: Unknown option \"-%c\""
 msgstr ""
 
-#: scheduler/main.c:189
+#: scheduler/main.c:193
 msgid "cupsd: Expected config filename after \"-c\" option."
 msgstr ""
 
-#: scheduler/main.c:221 scheduler/main.c:228
+#: scheduler/main.c:225 scheduler/main.c:232
 msgid "cupsd: Unable to get current directory."
 msgstr ""
 
-#: scheduler/main.c:295
+#: scheduler/main.c:299
 #, c-format
 msgid "cupsd: Unknown argument \"%s\" - aborting."
 msgstr ""
 
-#: scheduler/main.c:288
+#: scheduler/main.c:292
 #, c-format
 msgid "cupsd: Unknown option \"%c\" - aborting."
 msgstr ""
 
-#: scheduler/main.c:255
+#: scheduler/main.c:259
 msgid "cupsd: launchd(8) support not compiled in, running in normal mode."
 msgstr ""
 
@@ -5852,11 +5853,11 @@ msgstr ""
 msgid "cupsfilter: Unable to get job file - %s"
 msgstr ""
 
-#: systemv/cupstestppd.c:260
+#: systemv/cupstestppd.c:261
 msgid "cupstestppd: The -q option is incompatible with the -v option."
 msgstr ""
 
-#: systemv/cupstestppd.c:276
+#: systemv/cupstestppd.c:277
 msgid "cupstestppd: The -v option is incompatible with the -q option."
 msgstr ""
 
@@ -5890,70 +5891,70 @@ msgstr ""
 msgid "idle"
 msgstr ""
 
-#: test/ipptool-with-progress.c:364 test/ipptool.c:364
+#: test/ipptool.c:371
 msgid "ipptool: \"-i\" and \"-n\" are incompatible with -X\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:499 test/ipptool.c:503
+#: test/ipptool.c:510
 msgid "ipptool: \"-i\" is incompatible with \"-X\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:523 test/ipptool.c:527
+#: test/ipptool.c:534
 msgid "ipptool: \"-n\" is incompatible with \"-X\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:581 test/ipptool.c:585
+#: test/ipptool.c:592
 #, c-format
 msgid "ipptool: Bad URI - %s."
 msgstr ""
 
-#: test/ipptool-with-progress.c:353 test/ipptool.c:353
+#: test/ipptool.c:360
 #, c-format
 msgid "ipptool: Bad version %s for \"-V\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:492 test/ipptool.c:496
+#: test/ipptool.c:503
 msgid "ipptool: Invalid seconds for \"-i\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:562 test/ipptool.c:566
+#: test/ipptool.c:573
 msgid "ipptool: May only specify a single URI."
 msgstr ""
 
-#: test/ipptool-with-progress.c:515 test/ipptool.c:519
+#: test/ipptool.c:526
 msgid "ipptool: Missing count for \"-n\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:399 test/ipptool.c:399
+#: test/ipptool.c:406
 msgid "ipptool: Missing filename for \"-f\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:380 test/ipptool.c:380
+#: test/ipptool.c:387
 msgid "ipptool: Missing name=value for \"-d\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:482 test/ipptool.c:486
+#: test/ipptool.c:493
 msgid "ipptool: Missing seconds for \"-i\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:323 test/ipptool.c:323
+#: test/ipptool.c:330
 msgid "ipptool: Missing timeout for \"-T\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:336 test/ipptool.c:336
+#: test/ipptool.c:343
 msgid "ipptool: Missing version for \"-V\"."
 msgstr ""
 
-#: test/ipptool-with-progress.c:608 test/ipptool.c:612
+#: test/ipptool.c:619
 msgid "ipptool: URI required before test file."
 msgstr ""
 
-#: test/ipptool-with-progress.c:542 test/ipptool.c:546
+#: test/ipptool.c:553
 #, c-format
 msgid "ipptool: Unknown option \"-%c\"."
 msgstr ""
 
-#: scheduler/ipp.c:8715
+#: scheduler/ipp.c:8532
 msgid "job-printer-uri attribute missing."
 msgstr ""
 
@@ -6259,16 +6260,16 @@ msgstr ""
 msgid "no system default destination"
 msgstr ""
 
-#: scheduler/ipp.c:6577
+#: scheduler/ipp.c:6394
 msgid "notify-events not specified."
 msgstr ""
 
-#: scheduler/ipp.c:2052 scheduler/ipp.c:6482
+#: scheduler/ipp.c:2046 scheduler/ipp.c:6299
 #, c-format
 msgid "notify-recipient-uri URI \"%s\" is already used."
 msgstr ""
 
-#: scheduler/ipp.c:2042 scheduler/ipp.c:6472
+#: scheduler/ipp.c:2036 scheduler/ipp.c:6289
 #, c-format
 msgid "notify-recipient-uri URI \"%s\" uses unknown scheme."
 msgstr ""
@@ -6670,7 +6671,7 @@ msgstr ""
 msgid "ppdc: Unable to load localization file \"%s\" - %s"
 msgstr ""
 
-#: ppdc/ppdc-file.cxx:49
+#: ppdc/ppdc-file.cxx:50
 #, c-format
 msgid "ppdc: Unable to open %s: %s"
 msgstr ""
index e45557c0ad9afffcc36de67afed3d9cd3e10c4da..f754f3e7dde075cbb48e65e948929bf39703df39 100644 (file)
 "  -P filename.ppd         Set PPD file." = "  -P filename.ppd         Set PPD file.";
 "  -R root-directory       Set alternate root." = "  -R root-directory       Set alternate root.";
 "  -S                      Test with SSL encryption." = "  -S                      Test with SSL encryption.";
-"  -T                      Set the receive/send timeout in seconds." = "  -T                      Set the receive/send timeout in seconds.";
 "  -T seconds              Set the receive/send timeout in seconds." = "  -T seconds              Set the receive/send timeout in seconds.";
 "  -U samba-user           Authenticate using the named SAMBA user." = "  -U samba-user           Authenticate using the named SAMBA user.";
 "  -U username             Set username for job." = "  -U username             Set username for job.";
 "Internet Postage 3-Part - 2 1/4 x 7\"" = "Internet Postage 3-Part - 2 1/4 x 7\"";
 "Internet Printing Protocol" = "Internet Printing Protocol";
 "Invalid media size." = "Invalid media size.";
+"Invalid printer command \"%s\"." = "Invalid printer command \"%s\".";
 "JCL" = "JCL";
 "JIS B0" = "JIS B0";
 "JIS B1" = "JIS B1";
 "The paper tray needs to be filled." = "The paper tray needs to be filled.";
 "The printer URI is incorrect or no longer exists." = "The printer URI is incorrect or no longer exists.";
 "The printer is busy." = "The printer is busy.";
-"The printer is low on toner." = "The printer is low on toner.";
 "The printer is not connected." = "The printer is not connected.";
 "The printer is not responding." = "The printer is not responding.";
-"The printer is out of toner." = "The printer is out of toner.";
 "The printer is running low on ink." = "The printer is running low on ink.";
+"The printer is running low on toner." = "The printer is running low on toner.";
 "The printer is unreachable at this time." = "The printer is unreachable at this time.";
 "The printer may be out of ink." = "The printer may be out of ink.";
+"The printer may be out of toner." = "The printer may be out of toner.";
 "The printer may not exist or is unavailable at this time." = "The printer may not exist or is unavailable at this time.";
 "The printer name may only contain up to 127 printable characters and may not contain spaces, slashes (/), or the pound sign (#)." = "The printer name may only contain up to 127 printable characters and may not contain spaces, slashes (/), or the pound sign (#).";
 "The printer or class does not exist." = "The printer or class does not exist.";
 "Unable to change printer-is-shared attribute:" = "Unable to change printer-is-shared attribute:";
 "Unable to change printer:" = "Unable to change printer:";
 "Unable to change server settings:" = "Unable to change server settings:";
+"Unable to configure printer options." = "Unable to configure printer options.";
 "Unable to connect to host." = "Unable to connect to host.";
 "Unable to contact printer, queuing on next printer in class." = "Unable to contact printer, queuing on next printer in class.";
 "Unable to copy 64-bit CUPS printer driver files (%d)." = "Unable to copy 64-bit CUPS printer driver files (%d).";
index 97f9cc337c2d17151c1e1596825e63fcf761c26a..0b7d1f32fb751f90a9193125e74343456fb0fc82 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Convert a GNU gettext .po file to an Apple .strings file.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *
  *   These coded instructions, statements, and computer programs are the
  *   property of Apple Inc. and are protected by Federal copyright
@@ -175,7 +175,7 @@ main(int  argc,                             /* I - Number of command-line args */
      /*
       * Find start of value...
       */
-      
+
       if ((ptr = strchr(s, '\"')) == NULL)
        continue;
 
@@ -196,15 +196,18 @@ main(int  argc,                           /* I - Number of command-line args */
          if (*msgid)
             cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
                           (use_msgid || !*msgstr) ? msgid : msgstr);
+       }
 
+       if (msgid)
          free(msgid);
+
+       if (msgstr)
          free(msgstr);
-       }
 
         msgid  = strdup(ptr);
        msgstr = NULL;
       }
-      else if (s[0] == '\"' )
+      else if (s[0] == '\"' && (msgid || msgstr))
       {
        /*
        * Append to current string...
@@ -215,6 +218,9 @@ main(int  argc,                             /* I - Number of command-line args */
        if ((temp = realloc(msgstr ? msgstr : msgid,
                            length + strlen(ptr) + 1)) == NULL)
        {
+         free(msgid);
+         if (msgstr)
+           free(msgstr);
          perror("Unable to allocate string");
          return (1);
        }
@@ -250,8 +256,12 @@ main(int  argc,                            /* I - Number of command-line args */
        * Set the string...
        */
 
+        if (msgstr)
+          free(msgstr);
+
        if ((msgstr = strdup(ptr)) == NULL)
        {
+         free(msgid);
          perror("Unable to allocate msgstr");
          return (1);
        }
@@ -264,10 +274,13 @@ main(int  argc,                           /* I - Number of command-line args */
     if (*msgid)
       cupsFilePrintf(strings, "\"%s\" = \"%s\";\n", msgid,
                     (use_msgid || !*msgstr) ? msgid : msgstr);
+  }
 
+  if (msgid)
     free(msgid);
+
+  if (msgstr)
     free(msgstr);
-  }
 
   cupsFileClose(po);
   cupsFileClose(strings);
index c379c0477b38d5880969d2ab6c676fa94cff8522..00a6df7f9a4cef3fc43ec01a09e533154fcb42c3 100644 (file)
@@ -3,7 +3,7 @@
 .\"
 .\"   ipptoolfile man page for CUPS.
 .\"
-.\"   Copyright 2010-2011 by Apple Inc.
+.\"   Copyright 2010-2012 by Apple Inc.
 .\"
 .\"   These coded instructions, statements, and computer programs are the
 .\"   property of Apple Inc. and are protected by Federal copyright
@@ -11,7 +11,7 @@
 .\"   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/".
 .\"
-.TH ipptoolfile 5 "CUPS" "28 September 2011" "Apple Inc."
+.TH ipptoolfile 5 "CUPS" "14 March 2012" "Apple Inc."
 .SH NAME
 ipptoolfile \- ipptool file format
 
@@ -276,14 +276,45 @@ SAME-COUNT-AS attribute-name
 Requires the EXPECT attribute to have the same number of values as the specified
 parallel attribute.
 .TP 5
+WITH-ALL-VALUES "literal string"
+Requires that all values of the EXPECT attribute match the literal string. Comparisons are case-sensitive.
+.TP 5
+WITH-ALL-VALUES <number
+.TP 5
+WITH-ALL-VALUES =number
+.TP 5
+WITH-ALL-VALUES >number
+.TP 5
+WITH-ALL-VALUES number[,number,...]
+Requires that all values of the EXPECT attribute match the number(s) or numeric comparison. When comparing rangeOfInteger values, the "<" and ">" operators only check the upper bound of the range.
+.TP 5
+WITH-ALL-VALUES "false"
+.TP 5
+WITH-ALL-VALUES "true"
+Requires that all values of the EXPECT attribute match the boolean value given.
+.TP 5
+WITH-ALL-VALUES "/regular expression/"
+Requires that all values of the EXPECT attribute match the regular expression, which must conform to the POSIX regular expression syntax. Comparisons are case-sensitive.
+.TP 5
 WITH-VALUE "literal string"
-Requires at least one value of the EXPECT attribute to match the literal string.
-Comparisons are case-sensitive.
+Requires that at least one value of the EXPECT attribute matches the literal string. Comparisons are case-sensitive.
+.TP 5
+WITH-VALUE <number
+.TP 5
+WITH-VALUE =number
+.TP 5
+WITH-VALUE >number
+.TP 5
+WITH-VALUE number[,number,...]
+Requires that at least one value of the EXPECT attribute matches the number(s) or numeric comparison. When comparing rangeOfInteger values, the "<" and ">" operators only check the upper bound of the range.
+.TP 5
+WITH-VALUE "false"
+.TP 5
+WITH-VALUE "true"
+Requires that at least one value of the EXPECT attribute matches the boolean value given.
 .TP 5
 WITH-VALUE "/regular expression/"
-Requires that all values of the EXPECT attribute match the regular expression,
-which must conform to the POSIX regular expression syntax.
-Comparisons are case-sensitive.
+Requires that at least one value of the EXPECT attribute matches the regular expression, which must conform to the POSIX regular expression syntax. Comparisons are case-sensitive.
 
 .SH STATUS PREDICATES
 The following predicates are understood following the STATUS test directive:
@@ -343,6 +374,7 @@ RFC 2911 and other IPP extension specifications. Here is a complete list:
     Get-Subscriptions
     Hold-Job
     Hold-New-Jobs
+    Identify-Printer
     Pause-Printer
     Pause-Printer-After-Current-Job
     Print-Job
@@ -367,6 +399,7 @@ RFC 2911 and other IPP extension specifications. Here is a complete list:
     Shutdown-Printer
     Startup-Printer
     Suspend-Current-Job
+    Validate-Document
     Validate-Job
 .fi
 
@@ -384,6 +417,10 @@ Status codes correspond to the hexadecimal numbers (0xHHHH) and names from RFC
     client-error-document-access-error
     client-error-document-format-error
     client-error-document-format-not-supported
+    client-error-document-password-error
+    client-error-document-permission-error
+    client-error-document-security-error
+    client-error-document-unprintable-error
     client-error-forbidden
     client-error-gone
     client-error-ignored-all-notifications
@@ -517,7 +554,7 @@ Inserts the username from the URI provided to \fIipptool\fR, if any.
 http://localhost:631/help
 
 .SH COPYRIGHT
-Copyright 2007-2011 by Apple Inc.
+Copyright 2007-2012 by Apple Inc.
 .\"
 .\" End of "$Id$".
 .\"
index f42c921a2cc293d5187296e6cec953614f2643ab..deee6b5b71c7929d69a6070b2efa61b6f09d0fd5 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   RSS notifier for CUPS.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -252,7 +252,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
     {
      /*
       * Save the messages to the file again, uploading as needed...
-      */ 
+      */
 
       if (save_rss(rss, newname, baseurl))
       {
@@ -554,6 +554,15 @@ load_rss(cups_array_t *rss,                /* I - RSS messages */
       sequence_number = atoi(start + 6);
   }
 
+  if (subject)
+    free(subject);
+
+  if (text)
+    free(text);
+
+  if (link_url)
+    free(link_url);
+
   fclose(fp);
 }
 
index 3d4520eb093ebd025620f1627a1748ad4a89a649..1f1d9a84e1980c3d13b532683a8be902b3f24a42 100644 (file)
@@ -42,8 +42,9 @@ ppdcFile::ppdcFile(const char  *f,            // I - File to open
   else
     fp = cupsFileOpen(f, "r");
 
-  filename = f;
-  line     = 1;
+  close_on_delete = !ffp;
+  filename        = f;
+  line            = 1;
 
   if (!fp)
     _cupsLangPrintf(stderr, _("ppdc: Unable to open %s: %s"), f,
@@ -57,7 +58,7 @@ ppdcFile::ppdcFile(const char  *f,            // I - File to open
 
 ppdcFile::~ppdcFile()
 {
-  if (fp)
+  if (close_on_delete && fp)
     cupsFileClose(fp);
 }
 
index e806d24499be6548715a276b992bc3c26c8bcab2..78e97adc8fbfdce7fd4ba49ef42609242c41ab70 100644 (file)
@@ -3,7 +3,7 @@
 //
 //   Source class for the CUPS PPD Compiler.
 //
-//   Copyright 2007-2011 by Apple Inc.
+//   Copyright 2007-2012 by Apple Inc.
 //   Copyright 2002-2007 by Easy Software Products.
 //
 //   These coded instructions, statements, and computer programs are the
@@ -1338,7 +1338,8 @@ ppdcSource::get_integer(const char *v)    // I - Value string
         // NAME logicop value
        for (newv = (char *)v + 1;
             *newv && (isalnum(*newv & 255) || *newv == '_');
-            newv ++);
+            newv ++)
+         /* do nothing */;
 
         ch    = *newv;
        *newv = '\0';
index 24c9f2c269ef15d1ad80167a556c441041d2bd4b..c940e00a06220fd51d5b64fe11a637d7f6ccb255 100644 (file)
@@ -447,6 +447,7 @@ class ppdcFile                              //// File
 {
   public:
 
+  bool         close_on_delete;        // Close file on delete?
   cups_file_t  *fp;                    // File pointer
   const char   *filename;              // Filename
   int          line;                   // Line in file
index 72c7f6488465752e28e20f2bfb73b016673d0815..53b2bfc72d15ee83b7df0832b1ba1c5ca422331e 100644 (file)
@@ -41,7 +41,8 @@ CUPSDOBJS =   \
                statbuf.o \
                subscriptions.o \
                sysman.o \
-               timeout.o
+               timeout.o \
+               tls.o
 LIBOBJS =      \
                filter.o \
                mime.o \
@@ -211,7 +212,7 @@ install-data:
 install-exec:
        echo Installing programs in $(SBINDIR)...
        $(INSTALL_DIR) -m 755 $(SBINDIR)
-       $(INSTALL_BIN) -m 500 cupsd $(SBINDIR)
+       $(INSTALL_BIN) -m $(CUPS_CUPSD_FILE_PERM) cupsd $(SBINDIR)
        $(INSTALL_BIN) cupsfilter $(SBINDIR)
        echo Installing programs in $(SERVERBIN)/daemon...
        $(INSTALL_DIR) -m 755 $(SERVERBIN)
@@ -381,6 +382,8 @@ cupsd-static:       $(CUPSDOBJS) libcupsmime.a ../cups/$(LIBCUPSSTATIC)
                $(LIBMALLOC) $(SERVERLIBS) $(DNSSDLIBS) $(LIBGSSAPI) \
                $(LIBWRAP)
 
+tls.o: tls-darwin.c tls-gnutls.c tls-openssl.c
+
 
 #
 # Make the cupsfilter utility.
index 732fc324e77b863cff56976b2ab11ee39901ddb4..00b5960f8f49d2fbb2c731240906e338a62fc9ee 100644 (file)
@@ -847,8 +847,8 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */
              */
 
              cupsdLogMessage(CUPSD_LOG_ERROR,
-                             "Username \"%s\" has no password.", con->http.fd,
-                             username);
+                             "[Client %d] Username \"%s\" has no password.",
+                             con->http.fd, username);
              return;
            }
 
index fbf1e725299208dec060436345591d7aec8443b8..17e1312af94f74037554d9d7a944ef66514a8da2 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Client routines for the CUPS scheduler.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   This file contains Kerberos support code, copyright 2006 by
  *
  * Contents:
  *
- *   cupsdAcceptClient()     - Accept a new client.
- *   cupsdCloseAllClients()  - Close all remote clients immediately.
- *   cupsdCloseClient()      - Close a remote client.
- *   cupsdFlushHeader()      - Flush the header fields to the client.
- *   cupsdReadClient()       - Read data from a client.
- *   cupsdSendCommand()      - Send output from a command via HTTP.
- *   cupsdSendError()        - Send an error message via HTTP.
- *   cupsdSendHeader()       - Send an HTTP request.
- *   cupsdUpdateCGI()        - Read status messages from CGI scripts and
- *                             programs.
- *   cupsdWriteClient()      - Write data to a client as needed.
- *   check_if_modified()     - Decode an "If-Modified-Since" line.
- *   compare_clients()       - Compare two client connections.
- *   copy_cdsa_certificate() - Copy a SSL/TLS certificate from the System
- *                             keychain.
- *   data_ready()            - Check whether data is available from a client.
- *   encrypt_client()        - Enable encryption for the client...
- *   get_file()              - Get a filename and state info.
- *   install_conf_file()     - Install a configuration file.
- *   is_cgi()                - Is the resource a CGI script/program?
- *   is_path_absolute()      - Is a path absolute and free of relative elements
- *                             (i.e. "..").
- *   make_certificate()      - Make a self-signed SSL/TLS certificate.
- *   pipe_command()          - Pipe the output of a command to the remote
- *                             client.
- *   valid_host()            - Is the Host: field valid?
- *   write_file()            - Send a file via HTTP.
- *   write_pipe()            - Flag that data is available on the CGI pipe.
+ *   cupsdAcceptClient()    - Accept a new client.
+ *   cupsdCloseAllClients() - Close all remote clients immediately.
+ *   cupsdCloseClient()     - Close a remote client.
+ *   cupsdFlushHeader()     - Flush the header fields to the client.
+ *   cupsdReadClient()     - Read data from a client.
+ *   cupsdSendCommand()     - Send output from a command via HTTP.
+ *   cupsdSendError()      - Send an error message via HTTP.
+ *   cupsdSendHeader()     - Send an HTTP request.
+ *   cupsdUpdateCGI()      - Read status messages from CGI scripts and
+ *                           programs.
+ *   cupsdWriteClient()     - Write data to a client as needed.
+ *   check_if_modified()    - Decode an "If-Modified-Since" line.
+ *   compare_clients()     - Compare two client connections.
+ *   data_ready()          - Check whether data is available from a client.
+ *   get_file()            - Get a filename and state info.
+ *   install_conf_file()    - Install a configuration file.
+ *   is_cgi()              - Is the resource a CGI script/program?
+ *   is_path_absolute()     - Is a path absolute and free of relative elements
+ *                           (i.e. "..").
+ *   pipe_command()        - Pipe the output of a command to the remote
+ *                           client.
+ *   valid_host()          - Is the Host: field valid?
+ *   write_file()          - Send a file via HTTP.
+ *   write_pipe()          - Flag that data is available on the CGI pipe.
  */
 
 /*
@@ -96,22 +92,13 @@ static int          check_if_modified(cupsd_client_t *con,
                                          struct stat *filestats);
 static int             compare_clients(cupsd_client_t *a, cupsd_client_t *b,
                                        void *data);
-#ifdef HAVE_CDSASSL
-static CFArrayRef      copy_cdsa_certificate(cupsd_client_t *con);
-#endif /* HAVE_CDSASSL */
 static int             data_ready(cupsd_client_t *con);
-#ifdef HAVE_SSL
-static int             encrypt_client(cupsd_client_t *con);
-#endif /* HAVE_SSL */
 static char            *get_file(cupsd_client_t *con, struct stat *filestats,
                                  char *filename, int len);
 static http_status_t   install_conf_file(cupsd_client_t *con);
 static int             is_cgi(cupsd_client_t *con, const char *filename,
                               struct stat *filestats, mime_type_t *type);
 static int             is_path_absolute(const char *path);
-#ifdef HAVE_SSL
-static int             make_certificate(cupsd_client_t *con);
-#endif /* HAVE_SSL */
 static int             pipe_command(cupsd_client_t *con, int infile, int *outfile,
                                     char *command, char *options, int root);
 static int             valid_host(cupsd_client_t *con);
@@ -474,7 +461,7 @@ cupsdAcceptClient(cupsd_listener_t *lis)/* I - Listener socket */
 
     con->http.encryption = HTTP_ENCRYPT_ALWAYS;
 
-    if (!encrypt_client(con))
+    if (!cupsdStartTLS(con))
       cupsdCloseClient(con);
   }
   else
@@ -513,12 +500,7 @@ cupsdCloseClient(cupsd_client_t *con)      /* I - Client to close */
 {
   int          partial;                /* Do partial close for SSL? */
 #ifdef HAVE_LIBSSL
-  SSL_CTX      *context;               /* Context for encryption */
-  unsigned long        error;                  /* Error code */
 #elif defined(HAVE_GNUTLS)
-  int          error;                  /* Error code */
-  gnutls_certificate_server_credentials *credentials;
-                                       /* TLS credentials */
 #  elif defined(HAVE_CDSASSL)
 #endif /* HAVE_LIBSSL */
 
@@ -543,60 +525,7 @@ cupsdCloseClient(cupsd_client_t *con)      /* I - Client to close */
   {
     partial = 1;
 
-#  ifdef HAVE_LIBSSL
-    context = SSL_get_SSL_CTX(con->http.tls);
-
-    switch (SSL_shutdown(con->http.tls))
-    {
-      case 1 :
-          cupsdLogMessage(CUPSD_LOG_DEBUG,
-                         "SSL shutdown successful!");
-         break;
-      case -1 :
-          cupsdLogMessage(CUPSD_LOG_ERROR,
-                         "Fatal error during SSL shutdown!");
-      default :
-         while ((error = ERR_get_error()) != 0)
-           cupsdLogMessage(CUPSD_LOG_ERROR, "SSL shutdown failed: %s",
-                           ERR_error_string(error, NULL));
-          break;
-    }
-
-    SSL_CTX_free(context);
-    SSL_free(con->http.tls);
-
-#  elif defined(HAVE_GNUTLS)
-    credentials = (gnutls_certificate_server_credentials *)(con->http.tls_credentials);
-
-    error = gnutls_bye(con->http.tls, GNUTLS_SHUT_WR);
-    switch (error)
-    {
-      case GNUTLS_E_SUCCESS:
-       cupsdLogMessage(CUPSD_LOG_DEBUG,
-                       "SSL shutdown successful!");
-       break;
-      default:
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "SSL shutdown failed: %s", gnutls_strerror(error));
-       break;
-    }
-
-    gnutls_deinit(con->http.tls);
-    gnutls_certificate_free_credentials(*credentials);
-    free(credentials);
-
-#  elif defined(HAVE_CDSASSL)
-    while (SSLClose(con->http.tls) == errSSLWouldBlock)
-      usleep(1000);
-
-    SSLDisposeContext(con->http.tls);
-
-    if (con->http.tls_credentials)
-      CFRelease(con->http.tls_credentials);
-
-#  endif /* HAVE_LIBSSL */
-
-    con->http.tls = NULL;
+    cupsdEndTLS(con);
   }
 #endif /* HAVE_SSL */
 
@@ -791,7 +720,7 @@ cupsdReadClient(cupsd_client_t *con)        /* I - Client to read from */
                       "[Client %d] Saw first byte %02X, auto-negotiating "
                      "SSL/TLS session.", con->http.fd, buf[0] & 255);
 
-      if (!encrypt_client(con))
+      if (!cupsdStartTLS(con))
         cupsdCloseClient(con);
 
       return;
@@ -1205,7 +1134,7 @@ cupsdReadClient(cupsd_client_t *con)      /* I - Client to read from */
          return;
        }
 
-        if (!encrypt_client(con))
+        if (!cupsdStartTLS(con))
         {
          cupsdCloseClient(con);
          return;
@@ -1279,7 +1208,7 @@ cupsdReadClient(cupsd_client_t *con)      /* I - Client to read from */
          return;
        }
 
-        if (!encrypt_client(con))
+        if (!cupsdStartTLS(con))
         {
          cupsdCloseClient(con);
          return;
@@ -3146,274 +3075,6 @@ compare_clients(cupsd_client_t *a,      /* I - First client */
 }
 
 
-#ifdef HAVE_CDSASSL
-/*
- * 'copy_cdsa_certificate()' - Copy a SSL/TLS certificate from the System
- *                             keychain.
- */
-
-static CFArrayRef                              /* O - Array of certificates */
-copy_cdsa_certificate(
-    cupsd_client_t *con)                       /* I - Client connection */
-{
-  OSStatus             err;            /* Error info */
-  SecKeychainRef       keychain = NULL;/* Keychain reference */
-  SecIdentitySearchRef search = NULL;  /* Search reference */
-  SecIdentityRef       identity = NULL;/* Identity */
-  CFArrayRef           certificates = NULL;
-                                       /* Certificate array */
-#  if HAVE_SECPOLICYCREATESSL
-  SecPolicyRef         policy = NULL;  /* Policy ref */
-  CFStringRef          servername = NULL;
-                                       /* Server name */
-  CFMutableDictionaryRef query = NULL; /* Query qualifiers */
-  char                 localname[1024];/* Local hostname */
-#  elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
-  SecPolicyRef         policy = NULL;  /* Policy ref */
-  SecPolicySearchRef   policy_search = NULL;
-                                       /* Policy search ref */
-  CSSM_DATA            options;        /* Policy options */
-  CSSM_APPLE_TP_SSL_OPTIONS
-                       ssl_options;    /* SSL Option for hostname */
-  char                 localname[1024];/* Local hostname */
-#  endif /* HAVE_SECPOLICYCREATESSL */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG,
-                  "copy_cdsa_certificate: Looking for certs for \"%s\"...",
-                 con->servername);
-
-  if ((err = SecKeychainOpen(ServerCertificate, &keychain)))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\" - %s (%d)",
-                   ServerCertificate, cssmErrorString(err), (int)err);
-    goto cleanup;
-  }
-
-#  if HAVE_SECPOLICYCREATESSL
-  servername = CFStringCreateWithCString(kCFAllocatorDefault, con->servername,
-                                        kCFStringEncodingUTF8);
-
-  policy = SecPolicyCreateSSL(1, servername);
-
-  if (servername)
-    CFRelease(servername);
-
-  if (!policy)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference");
-    goto cleanup;
-  }
-
-  if (!(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
-                                         &kCFTypeDictionaryKeyCallBacks,
-                                         &kCFTypeDictionaryValueCallBacks)))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create query dictionary");
-    goto cleanup;
-  }
-
-  CFDictionaryAddValue(query, kSecClass, kSecClassIdentity);
-  CFDictionaryAddValue(query, kSecMatchPolicy, policy);
-  CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue);
-  CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne);
-
-  err = SecItemCopyMatching(query, (CFTypeRef *)&identity);
-
-  if (err && DNSSDHostName)
-  {
-   /*
-    * Search for the connection server name failed; try the DNS-SD .local
-    * hostname instead...
-    */
-
-    snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "copy_cdsa_certificate: Looking for certs for \"%s\"...",
-                   localname);
-
-    servername = CFStringCreateWithCString(kCFAllocatorDefault, localname,
-                                          kCFStringEncodingUTF8);
-
-    CFRelease(policy);
-
-    policy = SecPolicyCreateSSL(1, servername);
-
-    if (servername)
-      CFRelease(servername);
-
-    if (!policy)
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference");
-      goto cleanup;
-    }
-
-    CFDictionarySetValue(query, kSecMatchPolicy, policy);
-
-    err = SecItemCopyMatching(query, (CFTypeRef *)&identity);
-  }
-
-  if (err)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "Cannot find signing key in keychain \"%s\": %s (%d)",
-                   ServerCertificate, cssmErrorString(err), (int)err);
-    goto cleanup;
-  }
-
-#  elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
- /*
-  * Use a policy to search for valid certificates whose common name matches the
-  * servername...
-  */
-
-  if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL,
-                           NULL, &policy_search))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create a policy search reference");
-    goto cleanup;
-  }
-
-  if (SecPolicySearchCopyNext(policy_search, &policy))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                   "Cannot find a policy to use for searching");
-    goto cleanup;
-  }
-
-  memset(&ssl_options, 0, sizeof(ssl_options));
-  ssl_options.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION;
-  ssl_options.ServerName = con->servername;
-  ssl_options.ServerNameLen = strlen(con->servername);
-
-  options.Data = (uint8 *)&ssl_options;
-  options.Length = sizeof(ssl_options);
-
-  if (SecPolicySetValue(policy, &options))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                   "Cannot set policy value to use for searching");
-    goto cleanup;
-  }
-
-  if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN,
-                                              keychain, FALSE, &search)))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                   "Cannot create identity search reference: %s (%d)",
-                   cssmErrorString(err), (int)err);
-    goto cleanup;
-  }
-
-  err = SecIdentitySearchCopyNext(search, &identity);
-
-  if (err && DNSSDHostName)
-  {
-   /*
-    * Search for the connection server name failed; try the DNS-SD .local
-    * hostname instead...
-    */
-
-    snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
-
-    ssl_options.ServerName    = localname;
-    ssl_options.ServerNameLen = strlen(localname);
-
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "copy_cdsa_certificate: Looking for certs for \"%s\"...",
-                   localname);
-
-    if (SecPolicySetValue(policy, &options))
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                     "Cannot set policy value to use for searching");
-      goto cleanup;
-    }
-
-    CFRelease(search);
-    search = NULL;
-    if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN,
-                                              keychain, FALSE, &search)))
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                     "Cannot create identity search reference: %s (%d)",
-                     cssmErrorString(err), (int)err);
-      goto cleanup;
-    }
-
-    err = SecIdentitySearchCopyNext(search, &identity);
-
-  }
-
-  if (err)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "Cannot find signing key in keychain \"%s\": %s (%d)",
-                   ServerCertificate, cssmErrorString(err), (int)err);
-    goto cleanup;
-  }
-
-#  else
- /*
-  * Assume there is exactly one SecIdentity in the keychain...
-  */
-
-  if ((err = SecIdentitySearchCreate(keychain, CSSM_KEYUSE_SIGN, &search)))
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "Cannot create identity search reference (%d)", (int)err);
-    goto cleanup;
-  }
-
-  if ((err = SecIdentitySearchCopyNext(search, &identity)))
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG,
-                   "Cannot find signing key in keychain \"%s\": %s (%d)",
-                   ServerCertificate, cssmErrorString(err), (int)err);
-    goto cleanup;
-  }
-#  endif /* HAVE_SECPOLICYCREATESSL */
-
-  if (CFGetTypeID(identity) != SecIdentityGetTypeID())
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure!");
-    goto cleanup;
-  }
-
-  if ((certificates = CFArrayCreate(NULL, (const void **)&identity,
-                                 1, &kCFTypeArrayCallBacks)) == NULL)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array");
-    goto cleanup;
-  }
-
-  cleanup :
-
-  if (keychain)
-    CFRelease(keychain);
-  if (search)
-    CFRelease(search);
-  if (identity)
-    CFRelease(identity);
-
-#  if HAVE_SECPOLICYCREATESSL
-  if (policy)
-    CFRelease(policy);
-  if (query)
-    CFRelease(query);
-#  elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
-  if (policy)
-    CFRelease(policy);
-  if (policy_search)
-    CFRelease(policy_search);
-#  endif /* HAVE_SECPOLICYCREATESSL */
-
-  return (certificates);
-}
-#endif /* HAVE_CDSASSL */
-
-
 /*
  * 'data_ready()' - Check whether data is available from a client.
  */
@@ -3445,245 +3106,6 @@ data_ready(cupsd_client_t *con)         /* I - Client */
 }
 
 
-#ifdef HAVE_SSL
-/*
- * 'encrypt_client()' - Enable encryption for the client...
- */
-
-static int                             /* O - 1 on success, 0 on error */
-encrypt_client(cupsd_client_t *con)    /* I - Client to encrypt */
-{
-#  ifdef HAVE_LIBSSL
-  SSL_CTX      *context;               /* Context for encryption */
-  BIO          *bio;                   /* BIO data */
-  unsigned long        error;                  /* Error code */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.",
-                  con->http.fd);
-
- /*
-  * Verify that we have a certificate...
-  */
-
-  if (access(ServerKey, 0) || access(ServerCertificate, 0))
-  {
-   /*
-    * Nope, make a self-signed certificate...
-    */
-
-    if (!make_certificate(con))
-      return (0);
-  }
-
- /*
-  * Create the SSL context and accept the connection...
-  */
-
-  context = SSL_CTX_new(SSLv23_server_method());
-
-  SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
-  if (SSLOptions & CUPSD_SSL_NOEMPTY)
-    SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
-  SSL_CTX_use_PrivateKey_file(context, ServerKey, SSL_FILETYPE_PEM);
-  SSL_CTX_use_certificate_chain_file(context, ServerCertificate);
-
-  bio = BIO_new(_httpBIOMethods());
-  BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)HTTP(con));
-
-  con->http.tls = SSL_new(context);
-  SSL_set_bio(con->http.tls, bio, bio);
-
-  if (SSL_accept(con->http.tls) != 1)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to encrypt connection from %s.",
-                    con->http.hostname);
-
-    while ((error = ERR_get_error()) != 0)
-      cupsdLogMessage(CUPSD_LOG_ERROR, "%s", ERR_error_string(error, NULL));
-
-    SSL_CTX_free(context);
-    SSL_free(con->http.tls);
-    con->http.tls = NULL;
-    return (0);
-  }
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
-                  con->http.hostname);
-
-  return (1);
-
-#  elif defined(HAVE_GNUTLS)
-  int          status;                 /* Error code */
-  gnutls_certificate_server_credentials *credentials;
-                                       /* TLS credentials */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.",
-                  con->http.fd);
-
- /*
-  * Verify that we have a certificate...
-  */
-
-  if (access(ServerKey, 0) || access(ServerCertificate, 0))
-  {
-   /*
-    * Nope, make a self-signed certificate...
-    */
-
-    if (!make_certificate(con))
-      return (0);
-  }
-
- /*
-  * Create the SSL object and perform the SSL handshake...
-  */
-
-  credentials = (gnutls_certificate_server_credentials *)
-                    malloc(sizeof(gnutls_certificate_server_credentials));
-  if (credentials == NULL)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unable to encrypt connection from %s - %s",
-                    con->http.hostname, strerror(errno));
-
-    return (0);
-  }
-
-  gnutls_certificate_allocate_credentials(credentials);
-  gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate,
-                                      ServerKey, GNUTLS_X509_FMT_PEM);
-
-  gnutls_init(&con->http.tls, GNUTLS_SERVER);
-  gnutls_set_default_priority(con->http.tls);
-
-  gnutls_credentials_set(con->http.tls, GNUTLS_CRD_CERTIFICATE, *credentials);
-  gnutls_transport_set_ptr(con->http.tls, (gnutls_transport_ptr)HTTP(con));
-  gnutls_transport_set_pull_function(con->http.tls, _httpReadGNUTLS);
-  gnutls_transport_set_push_function(con->http.tls, _httpWriteGNUTLS);
-
-  while ((status = gnutls_handshake(con->http.tls)) != GNUTLS_E_SUCCESS)
-  {
-    if (gnutls_error_is_fatal(status))
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to encrypt connection from %s - %s",
-                      con->http.hostname, gnutls_strerror(status));
-
-      gnutls_deinit(con->http.tls);
-      gnutls_certificate_free_credentials(*credentials);
-      con->http.tls = NULL;
-      free(credentials);
-      return (0);
-    }
-  }
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
-                  con->http.hostname);
-
-  con->http.tls_credentials = credentials;
-  return (1);
-
-#  elif defined(HAVE_CDSASSL)
-  OSStatus     error = 0;              /* Error code */
-  CFArrayRef   peerCerts;              /* Peer certificates */
-
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.",
-                  con->http.fd);
-
-  con->http.tls_credentials = copy_cdsa_certificate(con);
-
-  if (!con->http.tls_credentials)
-  {
-   /*
-    * No keychain (yet), make a self-signed certificate...
-    */
-
-    if (make_certificate(con))
-      con->http.tls_credentials = copy_cdsa_certificate(con);
-  }
-
-  if (!con->http.tls_credentials)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                   "Could not find signing key in keychain \"%s\"",
-                   ServerCertificate);
-    error = errSSLBadCert; /* errSSLBadConfiguration is a better choice, but not available on 10.2.x */
-  }
-
-  if (!error)
-    error = SSLNewContext(true, &con->http.tls);
-
-  if (!error)
-    error = SSLSetIOFuncs(con->http.tls, _httpReadCDSA, _httpWriteCDSA);
-
-  if (!error)
-    error = SSLSetConnection(con->http.tls, HTTP(con));
-
-  if (!error)
-    error = SSLSetAllowsExpiredCerts(con->http.tls, true);
-
-  if (!error)
-    error = SSLSetAllowsAnyRoot(con->http.tls, true);
-
-  if (!error)
-    error = SSLSetCertificate(con->http.tls, con->http.tls_credentials);
-
-  if (!error)
-  {
-   /*
-    * Perform SSL/TLS handshake
-    */
-
-    while ((error = SSLHandshake(con->http.tls)) == errSSLWouldBlock)
-      usleep(1000);
-  }
-
-  if (error)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unable to encrypt connection from %s - %s (%d)",
-                    con->http.hostname, cssmErrorString(error), (int)error);
-
-    con->http.error  = error;
-    con->http.status = HTTP_ERROR;
-
-    if (con->http.tls)
-    {
-      SSLDisposeContext(con->http.tls);
-      con->http.tls = NULL;
-    }
-
-    if (con->http.tls_credentials)
-    {
-      CFRelease(con->http.tls_credentials);
-      con->http.tls_credentials = NULL;
-    }
-
-    return (0);
-  }
-
-  cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
-                  con->http.hostname);
-
-  if (!SSLCopyPeerCertificates(con->http.tls, &peerCerts) && peerCerts)
-  {
-    cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates!",
-                   (int)CFArrayGetCount(peerCerts));
-    CFRelease(peerCerts);
-  }
-  else
-    cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates!");
-
-  return (1);
-
-#  endif /* HAVE_LIBSSL */
-}
-#endif /* HAVE_SSL */
-
-
 /*
  * 'get_file()' - Get a filename and state info.
  */
@@ -4160,461 +3582,6 @@ is_path_absolute(const char *path)      /* I - Input path */
 }
 
 
-#ifdef HAVE_SSL
-/*
- * 'make_certificate()' - Make a self-signed SSL/TLS certificate.
- */
-
-static int                             /* O - 1 on success, 0 on failure */
-make_certificate(cupsd_client_t *con)  /* I - Client connection */
-{
-#if defined(HAVE_LIBSSL) && defined(HAVE_WAITPID)
-  int          pid,                    /* Process ID of command */
-               status;                 /* Status of command */
-  char         command[1024],          /* Command */
-               *argv[12],              /* Command-line arguments */
-               *envp[MAX_ENV + 1],     /* Environment variables */
-               infofile[1024],         /* Type-in information for cert */
-               seedfile[1024];         /* Random number seed file */
-  int          envc,                   /* Number of environment variables */
-               bytes;                  /* Bytes written */
-  cups_file_t  *fp;                    /* Seed/info file */
-  int          infofd;                 /* Info file descriptor */
-
-
- /*
-  * Run the "openssl" command to seed the random number generator and
-  * generate a self-signed certificate that is good for 10 years:
-  *
-  *     openssl rand -rand seedfile 1
-  *
-  *     openssl req -new -x509 -keyout ServerKey \
-  *             -out ServerCertificate -days 3650 -nodes
-  *
-  * The seeding step is crucial in ensuring that the openssl command
-  * does not block on systems without sufficient entropy...
-  */
-
-  if (!cupsFileFind("openssl", getenv("PATH"), 1, command, sizeof(command)))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "No SSL certificate and openssl command not found!");
-    return (0);
-  }
-
-  if (access("/dev/urandom", 0))
-  {
-   /*
-    * If the system doesn't provide /dev/urandom, then any random source
-    * will probably be blocking-style, so generate some random data to
-    * use as a seed for the certificate.  Note that we have already
-    * seeded the random number generator in cupsdInitCerts()...
-    */
-
-    cupsdLogMessage(CUPSD_LOG_INFO,
-                    "Seeding the random number generator...");
-
-   /*
-    * Write the seed file...
-    */
-
-    if ((fp = cupsTempFile2(seedfile, sizeof(seedfile))) == NULL)
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create seed file %s - %s",
-                      seedfile, strerror(errno));
-      return (0);
-    }
-
-    for (bytes = 0; bytes < 262144; bytes ++)
-      cupsFilePutChar(fp, random());
-
-    cupsFileClose(fp);
-
-   /*
-    * Run the openssl command to seed its random number generator...
-    */
-
-    argv[0] = "openssl";
-    argv[1] = "rand";
-    argv[2] = "-rand";
-    argv[3] = seedfile;
-    argv[4] = "1";
-    argv[5] = NULL;
-
-    envc = cupsdLoadEnv(envp, MAX_ENV);
-    envp[envc] = NULL;
-
-    if (!cupsdStartProcess(command, argv, envp, -1, -1, -1, -1, -1, 1, NULL,
-                           NULL, &pid))
-    {
-      unlink(seedfile);
-      return (0);
-    }
-
-    while (waitpid(pid, &status, 0) < 0)
-      if (errno != EINTR)
-      {
-       status = 1;
-       break;
-      }
-
-    cupsdFinishProcess(pid, command, sizeof(command), NULL);
-
-   /*
-    * Remove the seed file, as it is no longer needed...
-    */
-
-    unlink(seedfile);
-
-    if (status)
-    {
-      if (WIFEXITED(status))
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to seed random number generator - "
-                       "the openssl command stopped with status %d!",
-                       WEXITSTATUS(status));
-      else
-       cupsdLogMessage(CUPSD_LOG_ERROR,
-                       "Unable to seed random number generator - "
-                       "the openssl command crashed on signal %d!",
-                       WTERMSIG(status));
-
-      return (0);
-    }
-  }
-
- /*
-  * Create a file with the certificate information fields...
-  *
-  * Note: This assumes that the default questions are asked by the openssl
-  * command...
-  */
-
-  if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unable to create certificate information file %s - %s",
-                    infofile, strerror(errno));
-    return (0);
-  }
-
-  cupsFilePrintf(fp, ".\n.\n.\n%s\n.\n%s\n%s\n",
-                 ServerName, ServerName, ServerAdmin);
-  cupsFileClose(fp);
-
-  cupsdLogMessage(CUPSD_LOG_INFO,
-                  "Generating SSL server key and certificate...");
-
-  argv[0]  = "openssl";
-  argv[1]  = "req";
-  argv[2]  = "-new";
-  argv[3]  = "-x509";
-  argv[4]  = "-keyout";
-  argv[5]  = ServerKey;
-  argv[6]  = "-out";
-  argv[7]  = ServerCertificate;
-  argv[8]  = "-days";
-  argv[9]  = "3650";
-  argv[10] = "-nodes";
-  argv[11] = NULL;
-
-  cupsdLoadEnv(envp, MAX_ENV);
-
-  infofd = open(infofile, O_RDONLY);
-
-  if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL,
-                         NULL, &pid))
-  {
-    close(infofd);
-    unlink(infofile);
-    return (0);
-  }
-
-  close(infofd);
-  unlink(infofile);
-
-  while (waitpid(pid, &status, 0) < 0)
-    if (errno != EINTR)
-    {
-      status = 1;
-      break;
-    }
-
-  cupsdFinishProcess(pid, command, sizeof(command), NULL);
-
-  if (status)
-  {
-    if (WIFEXITED(status))
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to create SSL server key and certificate - "
-                     "the openssl command stopped with status %d!",
-                     WEXITSTATUS(status));
-    else
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to create SSL server key and certificate - "
-                     "the openssl command crashed on signal %d!",
-                     WTERMSIG(status));
-  }
-  else
-  {
-    cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...",
-                   ServerKey);
-    cupsdLogMessage(CUPSD_LOG_INFO,
-                    "Created SSL server certificate file \"%s\"...",
-                   ServerCertificate);
-  }
-
-  return (!status);
-
-#elif defined(HAVE_GNUTLS)
-  gnutls_x509_crt      crt;            /* Self-signed certificate */
-  gnutls_x509_privkey  key;            /* Encryption key */
-  cups_lang_t          *language;      /* Default language info */
-  cups_file_t          *fp;            /* Key/cert file */
-  unsigned char                buffer[8192];   /* Buffer for x509 data */
-  size_t               bytes;          /* Number of bytes of data */
-  unsigned char                serial[4];      /* Serial number buffer */
-  time_t               curtime;        /* Current time */
-  int                  result;         /* Result of GNU TLS calls */
-
-
- /*
-  * Create the encryption key...
-  */
-
-  cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key...");
-
-  gnutls_x509_privkey_init(&key);
-  gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0);
-
- /*
-  * Save it...
-  */
-
-  bytes = sizeof(buffer);
-
-  if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM,
-                                           buffer, &bytes)) < 0)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to export SSL server key - %s",
-                    gnutls_strerror(result));
-    gnutls_x509_privkey_deinit(key);
-    return (0);
-  }
-  else if ((fp = cupsFileOpen(ServerKey, "w")) != NULL)
-  {
-    cupsFileWrite(fp, (char *)buffer, bytes);
-    cupsFileClose(fp);
-
-    cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...",
-                   ServerKey);
-  }
-  else
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unable to create SSL server key file \"%s\" - %s",
-                   ServerKey, strerror(errno));
-    gnutls_x509_privkey_deinit(key);
-    return (0);
-  }
-
- /*
-  * Create the self-signed certificate...
-  */
-
-  cupsdLogMessage(CUPSD_LOG_INFO, "Generating self-signed SSL certificate...");
-
-  language  = cupsLangDefault();
-  curtime   = time(NULL);
-  serial[0] = curtime >> 24;
-  serial[1] = curtime >> 16;
-  serial[2] = curtime >> 8;
-  serial[3] = curtime;
-
-  gnutls_x509_crt_init(&crt);
-  if (strlen(language->language) == 5)
-    gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
-                                  language->language + 3, 2);
-  else
-    gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
-                                  "US", 2);
-  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0,
-                                ServerName, strlen(ServerName));
-  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0,
-                                ServerName, strlen(ServerName));
-  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME,
-                                0, "Unknown", 7);
-  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0,
-                                "Unknown", 7);
-  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0,
-                                "Unknown", 7);
-  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0,
-                                ServerAdmin, strlen(ServerAdmin));
-  gnutls_x509_crt_set_key(crt, key);
-  gnutls_x509_crt_set_serial(crt, serial, sizeof(serial));
-  gnutls_x509_crt_set_activation_time(crt, curtime);
-  gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400);
-  gnutls_x509_crt_set_ca_status(crt, 0);
-  gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME,
-                                               ServerName);
-  gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0);
-  gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT);
-  gnutls_x509_crt_set_version(crt, 3);
-
-  bytes = sizeof(buffer);
-  if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0)
-    gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes);
-
-  gnutls_x509_crt_sign(crt, crt, key);
-
- /*
-  * Save it...
-  */
-
-  bytes = sizeof(buffer);
-  if ((result = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM,
-                                       buffer, &bytes)) < 0)
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unable to export SSL server certificate - %s",
-                   gnutls_strerror(result));
-  else if ((fp = cupsFileOpen(ServerCertificate, "w")) != NULL)
-  {
-    cupsFileWrite(fp, (char *)buffer, bytes);
-    cupsFileClose(fp);
-
-    cupsdLogMessage(CUPSD_LOG_INFO,
-                    "Created SSL server certificate file \"%s\"...",
-                   ServerCertificate);
-  }
-  else
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unable to create SSL server certificate file \"%s\" - %s",
-                   ServerCertificate, strerror(errno));
-
- /*
-  * Cleanup...
-  */
-
-  gnutls_x509_crt_deinit(crt);
-  gnutls_x509_privkey_deinit(key);
-
-  return (1);
-
-#elif defined(HAVE_CDSASSL) && defined(HAVE_WAITPID)
-  int          pid,                    /* Process ID of command */
-               status;                 /* Status of command */
-  char         command[1024],          /* Command */
-               *argv[4],               /* Command-line arguments */
-               *envp[MAX_ENV + 1],     /* Environment variables */
-               keychain[1024],         /* Keychain argument */
-               infofile[1024],         /* Type-in information for cert */
-               localname[1024],        /* Local hostname */
-               *servername;            /* Name of server in cert */
-  cups_file_t  *fp;                    /* Seed/info file */
-  int          infofd;                 /* Info file descriptor */
-
-
-  if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName)
-  {
-    snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
-    servername = localname;
-  }
-  else
-    servername = con->servername;
-
- /*
-  * Run the "certtool" command to generate a self-signed certificate...
-  */
-
-  if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command)))
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "No SSL certificate and certtool command not found!");
-    return (0);
-  }
-
- /*
-  * Create a file with the certificate information fields...
-  *
-  * Note: This assumes that the default questions are asked by the certtool
-  * command...
-  */
-
-  if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                    "Unable to create certificate information file %s - %s",
-                    infofile, strerror(errno));
-    return (0);
-  }
-
-  cupsFilePrintf(fp, "%s\nr\n\ny\nb\ns\ny\n%s\n\n\n\n\n%s\ny\n",
-                servername, servername, ServerAdmin);
-  cupsFileClose(fp);
-
-  cupsdLogMessage(CUPSD_LOG_INFO,
-                  "Generating SSL server key and certificate...");
-
-  snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate);
-
-  argv[0] = "certtool";
-  argv[1] = "c";
-  argv[2] = keychain;
-  argv[3] = NULL;
-
-  cupsdLoadEnv(envp, MAX_ENV);
-
-  infofd = open(infofile, O_RDONLY);
-
-  if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL,
-                         NULL, &pid))
-  {
-    close(infofd);
-    unlink(infofile);
-    return (0);
-  }
-
-  close(infofd);
-  unlink(infofile);
-
-  while (waitpid(pid, &status, 0) < 0)
-    if (errno != EINTR)
-    {
-      status = 1;
-      break;
-    }
-
-  cupsdFinishProcess(pid, command, sizeof(command), NULL);
-
-  if (status)
-  {
-    if (WIFEXITED(status))
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to create SSL server key and certificate - "
-                     "the certtool command stopped with status %d!",
-                     WEXITSTATUS(status));
-    else
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "Unable to create SSL server key and certificate - "
-                     "the certtool command crashed on signal %d!",
-                     WTERMSIG(status));
-  }
-  else
-  {
-    cupsdLogMessage(CUPSD_LOG_INFO,
-                    "Created SSL server certificate file \"%s\"...",
-                   ServerCertificate);
-  }
-
-  return (!status);
-
-#else
-  return (0);
-#endif /* HAVE_LIBSSL && HAVE_WAITPID */
-}
-#endif /* HAVE_SSL */
-
-
 /*
  * 'pipe_command()' - Pipe the output of a command to the remote client.
  */
index ff1bfc0c99ceaa00fbb3f4faa350130f00f68176..3f5475f0bbd509fd4be6e6763a75dee4e84974a4 100644 (file)
@@ -133,6 +133,11 @@ extern void        cupsdStopListening(void);
 extern void    cupsdUpdateCGI(void);
 extern void    cupsdWriteClient(cupsd_client_t *con);
 
+#ifdef HAVE_SSL
+extern int     cupsdEndTLS(cupsd_client_t *con);
+extern int     cupsdStartTLS(cupsd_client_t *con);
+#endif /* HAVE_SSL */
+
 
 /*
  * End of "$Id: client.h 7935 2008-09-11 01:54:11Z mike $".
diff --git a/scheduler/client.h.orig b/scheduler/client.h.orig
new file mode 100644 (file)
index 0000000..ff1bfc0
--- /dev/null
@@ -0,0 +1,139 @@
+/*
+ * "$Id: client.h 7935 2008-09-11 01:54:11Z mike $"
+ *
+ *   Client definitions for the CUPS scheduler.
+ *
+ *   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
+ *   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/".
+ */
+
+#ifdef HAVE_AUTHORIZATION_H
+#  include <Security/Authorization.h>
+#endif /* HAVE_AUTHORIZATION_H */
+
+
+/*
+ * HTTP client structure...
+ */
+
+struct cupsd_client_s
+{
+  http_t               http;           /* HTTP client connection */
+  ipp_t                        *request,       /* IPP request information */
+                       *response;      /* IPP response information */
+  cupsd_location_t     *best;          /* Best match for AAA */
+  struct timeval       start;          /* Request start time */
+  http_state_t         operation;      /* Request operation */
+  off_t                        bytes;          /* Bytes transferred for this request */
+  int                  type;           /* AuthType for username */
+  char                 username[HTTP_MAX_VALUE],
+                                       /* Username from Authorization: line */
+                       password[HTTP_MAX_VALUE],
+                                       /* Password from Authorization: line */
+                       uri[HTTP_MAX_URI],
+                                       /* Localized URL/URI for GET/PUT */
+                       *filename,      /* Filename of output file */
+                       *command,       /* Command to run */
+                       *options,       /* Options for command */
+                       *query_string;  /* QUERY_STRING environment variable */
+  int                  file;           /* Input/output file */
+  int                  file_ready;     /* Input ready on file/pipe? */
+  int                  pipe_pid;       /* Pipe process ID (or 0 if not a pipe) */
+  int                  sent_header,    /* Non-zero if sent HTTP header */
+                       got_fields,     /* Non-zero if all fields seen */
+                       header_used;    /* Number of header bytes used */
+  char                 header[2048];   /* Header from CGI program */
+  cups_lang_t          *language;      /* Language to use */
+#ifdef HAVE_SSL
+  int                  auto_ssl;       /* Automatic test for SSL/TLS */
+#endif /* HAVE_SSL */
+  http_addr_t          clientaddr;     /* Client address */
+  char                 servername[256];/* Server name for connection */
+  int                  serverport;     /* Server port for connection */
+#ifdef HAVE_GSSAPI
+  int                  have_gss;       /* Have GSS credentials? */
+  uid_t                        gss_uid;        /* User ID for local prints */
+#endif /* HAVE_GSSAPI */
+#ifdef HAVE_AUTHORIZATION_H
+  AuthorizationRef     authref;        /* Authorization ref */
+#endif /* HAVE_AUTHORIZATION_H */
+};
+
+#define HTTP(con) &((con)->http)
+
+
+/*
+ * HTTP listener structure...
+ */
+
+typedef struct
+{
+  int                  fd;             /* File descriptor for this server */
+  http_addr_t          address;        /* Bind address of socket */
+  http_encryption_t    encryption;     /* To encrypt or not to encrypt... */
+} cupsd_listener_t;
+
+
+/*
+ * Globals...
+ */
+
+VAR int                        ListenBackLog   VALUE(SOMAXCONN),
+                                       /* Max backlog of pending connections */
+                       LocalPort       VALUE(631),
+                                       /* Local port to use */
+                       RemotePort      VALUE(0);
+                                       /* Remote port to use */
+VAR http_encryption_t  LocalEncryption VALUE(HTTP_ENCRYPT_IF_REQUESTED);
+                                       /* Local port encryption to use */
+VAR cups_array_t       *Listeners      VALUE(NULL);
+                                       /* Listening sockets */
+VAR time_t             ListeningPaused VALUE(0);
+                                       /* Time when listening was paused */
+VAR cups_array_t       *Clients        VALUE(NULL),
+                                       /* HTTP clients */
+                       *ActiveClients  VALUE(NULL);
+                                       /* Active HTTP clients */
+VAR char               *ServerHeader   VALUE(NULL);
+                                       /* Server header in requests */
+VAR int                        CGIPipes[2]     VALUE2(-1,-1);
+                                       /* Pipes for CGI error/debug output */
+VAR cupsd_statbuf_t    *CGIStatusBuffer VALUE(NULL);
+                                       /* Status buffer for pipes */
+
+
+/*
+ * Prototypes...
+ */
+
+extern void    cupsdAcceptClient(cupsd_listener_t *lis);
+extern void    cupsdCloseAllClients(void);
+extern int     cupsdCloseClient(cupsd_client_t *con);
+extern void    cupsdDeleteAllListeners(void);
+extern int     cupsdFlushHeader(cupsd_client_t *con);
+extern void    cupsdPauseListening(void);
+extern int     cupsdProcessIPPRequest(cupsd_client_t *con);
+extern void    cupsdReadClient(cupsd_client_t *con);
+extern void    cupsdResumeListening(void);
+extern int     cupsdSendCommand(cupsd_client_t *con, char *command,
+                                char *options, int root);
+extern int     cupsdSendError(cupsd_client_t *con, http_status_t code,
+                              int auth_type);
+extern int     cupsdSendHeader(cupsd_client_t *con, http_status_t code,
+                               char *type, int auth_type);
+extern void    cupsdShutdownClient(cupsd_client_t *con);
+extern void    cupsdStartListening(void);
+extern void    cupsdStopListening(void);
+extern void    cupsdUpdateCGI(void);
+extern void    cupsdWriteClient(cupsd_client_t *con);
+
+
+/*
+ * End of "$Id: client.h 7935 2008-09-11 01:54:11Z mike $".
+ */
index de9d80c0ef8029220ce85a83b2220581db18b714..999e4719cfeec441a91a6aac82a52b3fff1bc34f 100644 (file)
@@ -65,6 +65,7 @@
 typedef enum
 {
   CUPSD_VARTYPE_INTEGER,               /* Integer option */
+  CUPSD_VARTYPE_TIME,                  /* Time interval option */
   CUPSD_VARTYPE_STRING,                        /* String option */
   CUPSD_VARTYPE_BOOLEAN,               /* Boolean option */
   CUPSD_VARTYPE_PATHNAME               /* File/directory name option */
@@ -99,11 +100,11 @@ static const cupsd_var_t   variables[] =
   { "ConfigFilePerm",          &ConfigFilePerm,        CUPSD_VARTYPE_INTEGER },
   { "DataDir",                 &DataDir,               CUPSD_VARTYPE_STRING },
   { "DefaultLanguage",         &DefaultLanguage,       CUPSD_VARTYPE_STRING },
-  { "DefaultLeaseDuration",    &DefaultLeaseDuration,  CUPSD_VARTYPE_INTEGER },
+  { "DefaultLeaseDuration",    &DefaultLeaseDuration,  CUPSD_VARTYPE_TIME },
   { "DefaultPaperSize",                &DefaultPaperSize,      CUPSD_VARTYPE_STRING },
   { "DefaultPolicy",           &DefaultPolicy,         CUPSD_VARTYPE_STRING },
   { "DefaultShared",           &DefaultShared,         CUPSD_VARTYPE_BOOLEAN },
-  { "DirtyCleanInterval",      &DirtyCleanInterval,    CUPSD_VARTYPE_INTEGER },
+  { "DirtyCleanInterval",      &DirtyCleanInterval,    CUPSD_VARTYPE_TIME },
   { "DocumentRoot",            &DocumentRoot,          CUPSD_VARTYPE_STRING },
   { "ErrorLog",                        &ErrorLog,              CUPSD_VARTYPE_STRING },
   { "ErrorPolicy",             &ErrorPolicy,           CUPSD_VARTYPE_STRING },
@@ -114,13 +115,13 @@ static const cupsd_var_t  variables[] =
 #ifdef HAVE_GSSAPI
   { "GSSServiceName",          &GSSServiceName,        CUPSD_VARTYPE_STRING },
 #endif /* HAVE_GSSAPI */
-  { "JobKillDelay",            &JobKillDelay,          CUPSD_VARTYPE_INTEGER },
+  { "JobKillDelay",            &JobKillDelay,          CUPSD_VARTYPE_TIME },
   { "JobRetryLimit",           &JobRetryLimit,         CUPSD_VARTYPE_INTEGER },
-  { "JobRetryInterval",                &JobRetryInterval,      CUPSD_VARTYPE_INTEGER },
-  { "KeepAliveTimeout",                &KeepAliveTimeout,      CUPSD_VARTYPE_INTEGER },
+  { "JobRetryInterval",                &JobRetryInterval,      CUPSD_VARTYPE_TIME },
+  { "KeepAliveTimeout",                &KeepAliveTimeout,      CUPSD_VARTYPE_TIME },
   { "KeepAlive",               &KeepAlive,             CUPSD_VARTYPE_BOOLEAN },
 #ifdef HAVE_LAUNCHD
-  { "LaunchdTimeout",          &LaunchdTimeout,        CUPSD_VARTYPE_INTEGER },
+  { "LaunchdTimeout",          &LaunchdTimeout,        CUPSD_VARTYPE_TIME },
 #endif /* HAVE_LAUNCHD */
   { "LimitRequestBody",                &MaxRequestSize,        CUPSD_VARTYPE_INTEGER },
   { "ListenBackLog",           &ListenBackLog,         CUPSD_VARTYPE_INTEGER },
@@ -132,30 +133,30 @@ static const cupsd_var_t  variables[] =
   { "MaxClientsPerHost",       &MaxClientsPerHost,     CUPSD_VARTYPE_INTEGER },
   { "MaxCopies",               &MaxCopies,             CUPSD_VARTYPE_INTEGER },
   { "MaxEvents",               &MaxEvents,             CUPSD_VARTYPE_INTEGER },
-  { "MaxHoldTime",             &MaxHoldTime,           CUPSD_VARTYPE_INTEGER },
+  { "MaxHoldTime",             &MaxHoldTime,           CUPSD_VARTYPE_TIME },
   { "MaxJobs",                 &MaxJobs,               CUPSD_VARTYPE_INTEGER },
   { "MaxJobsPerPrinter",       &MaxJobsPerPrinter,     CUPSD_VARTYPE_INTEGER },
   { "MaxJobsPerUser",          &MaxJobsPerUser,        CUPSD_VARTYPE_INTEGER },
   { "MaxJobTime",              &MaxJobTime,            CUPSD_VARTYPE_INTEGER },
-  { "MaxLeaseDuration",                &MaxLeaseDuration,      CUPSD_VARTYPE_INTEGER },
+  { "MaxLeaseDuration",                &MaxLeaseDuration,      CUPSD_VARTYPE_TIME },
   { "MaxLogSize",              &MaxLogSize,            CUPSD_VARTYPE_INTEGER },
   { "MaxRequestSize",          &MaxRequestSize,        CUPSD_VARTYPE_INTEGER },
   { "MaxSubscriptions",                &MaxSubscriptions,      CUPSD_VARTYPE_INTEGER },
   { "MaxSubscriptionsPerJob",  &MaxSubscriptionsPerJob,        CUPSD_VARTYPE_INTEGER },
   { "MaxSubscriptionsPerPrinter",&MaxSubscriptionsPerPrinter,  CUPSD_VARTYPE_INTEGER },
   { "MaxSubscriptionsPerUser", &MaxSubscriptionsPerUser,       CUPSD_VARTYPE_INTEGER },
-  { "MultipleOperationTimeout",        &MultipleOperationTimeout,      CUPSD_VARTYPE_INTEGER },
+  { "MultipleOperationTimeout",        &MultipleOperationTimeout,      CUPSD_VARTYPE_TIME },
   { "PageLog",                 &PageLog,               CUPSD_VARTYPE_STRING },
   { "PageLogFormat",           &PageLogFormat,         CUPSD_VARTYPE_STRING },
-  { "PreserveJobFiles",                &JobFiles,              CUPSD_VARTYPE_BOOLEAN },
-  { "PreserveJobHistory",      &JobHistory,            CUPSD_VARTYPE_BOOLEAN },
+  { "PreserveJobFiles",                &JobFiles,              CUPSD_VARTYPE_TIME },
+  { "PreserveJobHistory",      &JobHistory,            CUPSD_VARTYPE_TIME },
   { "Printcap",                        &Printcap,              CUPSD_VARTYPE_STRING },
   { "PrintcapGUI",             &PrintcapGUI,           CUPSD_VARTYPE_STRING },
-  { "ReloadTimeout",           &ReloadTimeout,         CUPSD_VARTYPE_INTEGER },
+  { "ReloadTimeout",           &ReloadTimeout,         CUPSD_VARTYPE_TIME },
   { "RemoteRoot",              &RemoteRoot,            CUPSD_VARTYPE_STRING },
   { "RequestRoot",             &RequestRoot,           CUPSD_VARTYPE_STRING },
   { "RIPCache",                        &RIPCache,              CUPSD_VARTYPE_STRING },
-  { "RootCertDuration",                &RootCertDuration,      CUPSD_VARTYPE_INTEGER },
+  { "RootCertDuration",                &RootCertDuration,      CUPSD_VARTYPE_TIME },
   { "ServerAdmin",             &ServerAdmin,           CUPSD_VARTYPE_STRING },
   { "ServerBin",               &ServerBin,             CUPSD_VARTYPE_PATHNAME },
 #ifdef HAVE_SSL
@@ -172,7 +173,7 @@ static const cupsd_var_t    variables[] =
   { "SystemGroupAuthKey",      &SystemGroupAuthKey,    CUPSD_VARTYPE_STRING },
 #endif /* HAVE_AUTHORIZATION_H */
   { "TempDir",                 &TempDir,               CUPSD_VARTYPE_PATHNAME },
-  { "Timeout",                 &Timeout,               CUPSD_VARTYPE_INTEGER },
+  { "Timeout",                 &Timeout,               CUPSD_VARTYPE_TIME },
   { "WebInterface",            &WebInterface,          CUPSD_VARTYPE_BOOLEAN }
 };
 #define NUM_VARS       (sizeof(variables) / sizeof(variables[0]))
@@ -1557,6 +1558,12 @@ cupsdReadConfiguration(void)
 
     cupsdCreateCommonData();
 
+   /*
+    * Update all jobs as needed...
+    */
+
+    cupsdUpdateJobs();
+
    /*
     * Update all printers as needed...
     */
@@ -3140,12 +3147,15 @@ read_configuration(cups_file_t *fp)     /* I - File to read from */
              cupsdLogMessage(CUPSD_LOG_ERROR,
                              "Missing integer value for %s on line %d.",
                              line, linenum);
+           else if (!isdigit(*value & 255))
+             cupsdLogMessage(CUPSD_LOG_ERROR,
+                             "Bad integer value for %s on line %d.",
+                             line, linenum);
            else
            {
              int       n;              /* Number */
              char      *units;         /* Units */
 
-
               n = strtol(value, &units, 0);
 
              if (units && *units)
@@ -3158,6 +3168,13 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
                  n *= 1024;
                else if (tolower(units[0] & 255) == 't')
                  n *= 262144;
+               else
+               {
+                 cupsdLogMessage(CUPSD_LOG_ERROR,
+                                 "Unknown integer value for %s on line %d.",
+                                 line, linenum);
+                 break;
+               }
              }
 
               if (n < 0)
@@ -3169,6 +3186,61 @@ read_configuration(cups_file_t *fp)      /* I - File to read from */
            }
            break;
 
+        case CUPSD_VARTYPE_TIME :
+           if (!value)
+             cupsdLogMessage(CUPSD_LOG_ERROR,
+                             "Missing time interval value for %s on line %d.",
+                             line, linenum);
+           else if (!_cups_strncasecmp(line, "PreserveJob", 11) &&
+                    (!_cups_strcasecmp(value, "true") ||
+                     !_cups_strcasecmp(value, "on") ||
+                     !_cups_strcasecmp(value, "enabled") ||
+                     !_cups_strcasecmp(value, "yes")))
+             *((int *)var->ptr) = INT_MAX;
+           else if (!_cups_strcasecmp(value, "false") ||
+                    !_cups_strcasecmp(value, "off") ||
+                    !_cups_strcasecmp(value, "disabled") ||
+                    !_cups_strcasecmp(value, "no"))
+             *((int *)var->ptr) = 0;
+           else if (!isdigit(*value & 255))
+             cupsdLogMessage(CUPSD_LOG_ERROR,
+                             "Unknown time interval value for %s on line %d.",
+                             line, linenum);
+           else
+           {
+             double    n;              /* Number */
+             char      *units;         /* Units */
+
+              n = strtod(value, &units);
+
+             if (units && *units)
+             {
+               if (tolower(units[0] & 255) == 'w')
+                 n *= 7 * 24 * 60 * 60;
+               else if (tolower(units[0] & 255) == 'd')
+                 n *= 24 * 60 * 60;
+               else if (tolower(units[0] & 255) == 'h')
+                 n *= 60 * 60;
+               else if (tolower(units[0] & 255) == 'm')
+                 n *= 60;
+               else
+               {
+                 cupsdLogMessage(CUPSD_LOG_ERROR,
+                                 "Unknown time interval value for %s on line "
+                                 "%d.", line, linenum);
+                 break;
+               }
+             }
+
+              if (n < 0.0 || n > INT_MAX)
+               cupsdLogMessage(CUPSD_LOG_ERROR,
+                               "Bad time value for %s on line %d.",
+                               line, linenum);
+             else
+               *((int *)var->ptr) = (int)n;
+           }
+           break;
+
        case CUPSD_VARTYPE_BOOLEAN :
            if (!value)
              cupsdLogMessage(CUPSD_LOG_ERROR,
@@ -3538,6 +3610,7 @@ read_policy(cups_file_t *fp,              /* I - Configuration file */
              cupsdAddString(&(pol->job_attrs), "job-name");
              cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
              cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
+             cupsdAddString(&(pol->job_attrs), "phone");
            }
            else
              cupsdAddString(&(pol->job_attrs), value);
@@ -3762,6 +3835,7 @@ set_policy_defaults(cupsd_policy_t *pol)/* I - Policy */
     cupsdAddString(&(pol->job_attrs), "job-name");
     cupsdAddString(&(pol->job_attrs), "job-originating-host-name");
     cupsdAddString(&(pol->job_attrs), "job-originating-user-name");
+    cupsdAddString(&(pol->job_attrs), "phone");
   }
 
   if (!pol->sub_access)
index 95f6b3a316216768aa21032297312269840684e6..be3075b9815d52d28afe308ac35c238dc80189b1 100644 (file)
  *
  * Contents:
  *
- *   main()            - Scan for drivers and return an IPP response.
- *   add_ppd()         - Add a PPD file.
- *   cat_drv()         - Generate a PPD from a driver info file.
- *   cat_ppd()         - Copy a PPD file to stdout.
+ *   main()        - Scan for drivers and return an IPP response.
+ *   add_ppd()        - Add a PPD file.
+ *   cat_drv()        - Generate a PPD from a driver info file.
+ *   cat_ppd()        - Copy a PPD file to stdout.
  *   copy_static()     - Copy a static PPD file to stdout.
+ *   cat_tar()        - Copy an archived PPD file to stdout.
  *   compare_inodes()  - Compare two inodes.
  *   compare_matches() - Compare PPD match scores for sorting.
  *   compare_names()   - Compare PPD filenames for sorting.
  *   compare_ppds()    - Compare PPD file make and model names for sorting.
  *   dump_ppds_dat()   - Dump the contents of the ppds.dat file.
  *   free_array()      - Free an array of strings.
+ *   get_file()        - Get the filename associated with a request.
  *   list_ppds()       - List PPD files.
  *   load_drv()        - Load the PPDs from a driver information file.
  *   load_drivers()    - Load driver-generated PPD files.
+ *   load_ppd()        - Load a PPD file.
  *   load_ppds()       - Load PPD files recursively.
  *   load_ppds_dat()   - Load the ppds.dat file.
+ *   load_tar()        - Load archived PPD files.
+ *   read_tar()        - Read a file header from an archive.
  *   regex_device_id() - Compile a regular expression based on the 1284 device
- *                       ID.
+ *                      ID.
  *   regex_string()    - Construct a regular expression to compare a simple
- *                       string.
+ *                      string.
  */
 
 /*
 #define PPD_TYPE_FAX           3       /* Facsimile/MFD PPD */
 #define PPD_TYPE_UNKNOWN       4       /* Other/hybrid PPD */
 #define PPD_TYPE_DRV           5       /* Driver info file */
+#define PPD_TYPE_ARCHIVE       6       /* Archive file */
 
-static const char * const ppd_types[] =        /* ppd-type values */
-{
-  "postscript",
-  "pdf",
-  "raster",
-  "fax",
-  "unknown",
-  "drv"
-};
+#define TAR_BLOCK      512             /* Number of bytes in a block */
+#define TAR_BLOCKS     10              /* Blocking factor */
+
+#define TAR_MAGIC      "ustar"         /* 5 chars and a null */
+#define TAR_VERSION    "00"            /* POSIX tar version */
+
+#define TAR_OLDNORMAL  '\0'            /* Normal disk file, Unix compat */
+#define TAR_NORMAL     '0'             /* Normal disk file */
+#define TAR_LINK       '1'             /* Link to previously dumped file */
+#define TAR_SYMLINK    '2'             /* Symbolic link */
+#define TAR_CHR                '3'             /* Character special file */
+#define TAR_BLK                '4'             /* Block special file */
+#define TAR_DIR                '5'             /* Directory */
+#define TAR_FIFO       '6'             /* FIFO special file */
+#define TAR_CONTIG     '7'             /* Contiguous file */
 
 
 /*
@@ -110,15 +122,51 @@ typedef struct                            /**** In-memory record ****/
   ppd_rec_t    record;                 /* PPDs.dat record */
 } ppd_info_t;
 
+typedef union                          /**** TAR record format ****/
+{
+  unsigned char        all[TAR_BLOCK];         /* Raw data block */
+  struct
+  {
+    char       pathname[100],          /* Destination path */
+               mode[8],                /* Octal file permissions */
+               uid[8],                 /* Octal user ID */
+               gid[8],                 /* Octal group ID */
+               size[12],               /* Octal size in bytes */
+               mtime[12],              /* Octal modification time */
+               chksum[8],              /* Octal checksum value */
+               linkflag,               /* File type */
+               linkname[100],          /* Source path for link */
+               magic[6],               /* Magic string */
+               version[2],             /* Format version */
+               uname[32],              /* User name */
+               gname[32],              /* Group name */
+               devmajor[8],            /* Octal device major number */
+               devminor[8],            /* Octal device minor number */
+               prefix[155];            /* Prefix for long filenames */
+  }    header;
+} tar_rec_t;
+
 
 /*
  * Globals...
  */
 
-cups_array_t   *Inodes = NULL,         /* Inodes of directories we've visited */
-               *PPDsByName = NULL,     /* PPD files sorted by filename and name */
-               *PPDsByMakeModel = NULL;/* PPD files sorted by make and model */
-int            ChangedPPD;             /* Did we change the PPD database? */
+static cups_array_t    *Inodes = NULL, /* Inodes of directories we've visited */
+                       *PPDsByName = NULL,
+                                       /* PPD files sorted by filename and name */
+                       *PPDsByMakeModel = NULL;
+                                       /* PPD files sorted by make and model */
+static int             ChangedPPD;     /* Did we change the PPD database? */
+static const char * const PPDTypes[] = /* ppd-type values */
+                       {
+                         "postscript",
+                         "pdf",
+                         "raster",
+                         "fax",
+                         "unknown",
+                         "drv",
+                         "archive"
+                       };
 
 
 /*
@@ -135,6 +183,7 @@ static ppd_info_t   *add_ppd(const char *filename, const char *name,
 static int             cat_drv(const char *name, int request_id);
 static int             cat_ppd(const char *name, int request_id);
 static int             cat_static(const char *name, int request_id);
+static int             cat_tar(const char *name, int request_id);
 static int             compare_inodes(struct stat *a, struct stat *b);
 static int             compare_matches(const ppd_info_t *p0,
                                        const ppd_info_t *p1);
@@ -144,14 +193,24 @@ static int                compare_ppds(const ppd_info_t *p0,
                                     const ppd_info_t *p1);
 static int             dump_ppds_dat(const char *filename);
 static void            free_array(cups_array_t *a);
+static cups_file_t     *get_file(const char *name, int request_id,
+                                 const char *subdir, char *buffer,
+                                 size_t bufsize, char **subfile);
 static int             list_ppds(int request_id, int limit, const char *opt);
 static int             load_drivers(cups_array_t *include,
                                     cups_array_t *exclude);
 static int             load_drv(const char *filename, const char *name,
                                 cups_file_t *fp, time_t mtime, off_t size);
+static void            load_ppd(const char *filename, const char *name,
+                                const char *scheme, struct stat *fileinfo,
+                                ppd_info_t *ppd, cups_file_t *fp, off_t end);
 static int             load_ppds(const char *d, const char *p, int descend);
 static void            load_ppds_dat(char *filename, size_t filesize,
                                      int verbose);
+static int             load_tar(const char *filename, const char *name,
+                                cups_file_t *fp, time_t mtime, off_t size);
+static int             read_tar(cups_file_t *fp, char *name, size_t namesize,
+                                struct stat *info);
 static regex_t         *regex_device_id(const char *device_id);
 static regex_t         *regex_string(const char *s);
 
@@ -281,7 +340,7 @@ static int                          /* O - Exit code */
 cat_drv(const char *name,              /* I - PPD name */
         int        request_id)         /* I - Request ID for response? */
 {
-  const char   *datadir;               // CUPS_DATADIR env var
+  cups_file_t  *fp;                    // File pointer
   ppdcSource   *src;                   // PPD source file data
   ppdcDriver   *d;                     // Current driver
   cups_file_t  *out;                   // Stdout via CUPS file API
@@ -295,23 +354,16 @@ cat_drv(const char *name,         /* I - PPD name */
   int          port;                   // Port number (unused)
 
 
-  // Determine where CUPS has installed the data files...
-  if ((datadir = getenv("CUPS_DATADIR")) == NULL)
-    datadir = CUPS_DATADIR;
-
   // Pull out the path to the .drv file...
   if (httpSeparateURI(HTTP_URI_CODING_ALL, name, scheme, sizeof(scheme),
                       userpass, sizeof(userpass), host, sizeof(host), &port,
-                     resource, sizeof(resource)) < HTTP_URI_OK ||
-      strstr(resource, "../") ||
-      (pc_file_name = strrchr(resource, '/')) == NULL ||
-      pc_file_name == resource)
+                     resource, sizeof(resource)) < HTTP_URI_OK)
   {
-    fprintf(stderr, "ERROR: Bad PPD name \"%s\"!\n", name);
+    fprintf(stderr, "ERROR: Bad PPD name \"%s\".\n", name);
 
     if (request_id)
     {
-      snprintf(message, sizeof(message), "Bad PPD name \"%s\"!", name);
+      snprintf(message, sizeof(message), "Bad PPD name \"%s\".", name);
 
       cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
       cupsdSendIPPGroup(IPP_TAG_OPERATION);
@@ -325,21 +377,11 @@ cat_drv(const char *name,         /* I - PPD name */
     return (1);
   }
 
-  *pc_file_name++ = '\0';
-
-#ifdef __APPLE__
-  if (!strncmp(resource, "/Library/Printers/PPDs/Contents/Resources/", 42) ||
-      !strncmp(resource, "/System/Library/Printers/PPDs/Contents/Resources/", 49))
-    strlcpy(filename, resource, sizeof(filename));
-  else
-#endif // __APPLE__
-  {
-    snprintf(filename, sizeof(filename), "%s/drv%s", datadir, resource);
-    if (access(filename, 0))
-      snprintf(filename, sizeof(filename), "%s/model%s", datadir, resource);
-  }
+  if ((fp = get_file(resource, request_id, "drv", filename, sizeof(filename),
+                     &pc_file_name)) == NULL)
+    return (1);
 
-  src = new ppdcSource(filename);
+  src = new ppdcSource(filename, fp);
 
   for (d = (ppdcDriver *)src->drivers->first();
        d;
@@ -387,11 +429,11 @@ cat_drv(const char *name,         /* I - PPD name */
   }
   else
   {
-    fprintf(stderr, "ERROR: PPD \"%s\" not found!\n", name);
+    fprintf(stderr, "ERROR: PPD \"%s\" not found.\n", name);
 
     if (request_id)
     {
-      snprintf(message, sizeof(message), "PPD \"%s\" not found!", name);
+      snprintf(message, sizeof(message), "PPD \"%s\" not found.", name);
 
       cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
       cupsdSendIPPGroup(IPP_TAG_OPERATION);
@@ -404,6 +446,7 @@ cat_drv(const char *name,           /* I - PPD name */
   }
 
   src->release();
+  cupsFileClose(fp);
 
   return (!d);
 }
@@ -439,7 +482,12 @@ cat_ppd(const char *name,          /* I - PPD name */
       */
 
       name += 5;
-      scheme[0] = '\0';
+
+      while (*name == '/')
+        name ++;
+
+      if (!strstr(name, ".tar/") && !strstr(name, ".tar.gz/"))
+       scheme[0] = '\0';
     }
   }
   else
@@ -452,6 +500,8 @@ cat_ppd(const char *name,           /* I - PPD name */
     return (cat_static(name, request_id));
   else if (!strcmp(scheme, "drv"))
     return (cat_drv(name, request_id));
+  else if (!strcmp(scheme, "file"))
+    return (cat_tar(name, request_id));
   else
   {
    /*
@@ -540,144 +590,132 @@ cat_static(const char *name,            /* I - PPD name */
            int        request_id)      /* I - Request ID for response? */
 {
   cups_file_t  *fp;                    /* PPD file */
-  const char   *datadir;               /* CUPS_DATADIR env var */
-  char         line[1024],             /* Line/filename */
-               message[2048];          /* status-message */
-#ifdef __APPLE__
-  const char   *printerDriver,         /* Pointer to .printerDriver extension */
-               *slash;                 /* Pointer to next slash */
-#endif /* __APPLE__ */
-
-
-  if (name[0] == '/' || strstr(name, "../") || strstr(name, "/.."))
-  {
-   /*
-    * Bad name...
-    */
-
-    fprintf(stderr, "ERROR: [cups-driverd] Bad PPD name \"%s\"!\n", name);
+  char         filename[1024],         /* PPD filename */
+               line[1024];             /* Line buffer */
 
-    if (request_id)
-    {
-      snprintf(message, sizeof(message), "Bad PPD name \"%s\"!", name);
-
-      cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
-      cupsdSendIPPGroup(IPP_TAG_OPERATION);
-      cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
-      cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
-                        "en-US");
-      cupsdSendIPPString(IPP_TAG_TEXT, "status-message", message);
-      cupsdSendIPPTrailer();
-    }
 
+  if ((fp = get_file(name, request_id, "model", filename, sizeof(filename),
+                     NULL)) == NULL)
     return (1);
+
+  if (request_id)
+  {
+    cupsdSendIPPHeader(IPP_OK, request_id);
+    cupsdSendIPPGroup(IPP_TAG_OPERATION);
+    cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
+    cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
+                      "en-US");
+    cupsdSendIPPTrailer();
   }
 
  /*
-  * Try opening the file...
+  * Now copy the file to stdout...
   */
 
-#ifdef __APPLE__
-  if (!strncmp(name, "System/Library/Printers/PPDs/Contents/Resources/", 48) ||
-      !strncmp(name, "Library/Printers/PPDs/Contents/Resources/", 41) ||
-      (!strncmp(name, "System/Library/Printers/", 24) &&
-       (printerDriver =
-           strstr(name + 24,
-                  ".printerDriver/Contents/Resources/PPDs")) != NULL &&
-       (slash = strchr(name + 24, '/')) != NULL &&
-       slash > printerDriver) ||
-      (!strncmp(name, "Library/Printers/", 17) &&
-       (printerDriver =
-           strstr(name + 17,
-                  ".printerDriver/Contents/Resources/PPDs")) != NULL &&
-       (slash = strchr(name + 17, '/')) != NULL &&
-       slash > printerDriver))
-  {
-   /*
-    * Map ppd-name to Mac OS X standard locations...
-    */
+  while (cupsFileGets(fp, line, sizeof(line)))
+    puts(line);
 
-    snprintf(line, sizeof(line), "/%s", name);
-  }
-  else
+  cupsFileClose(fp);
 
-#elif defined(__linux)
-  if (!strncmp(name, "lsb/usr/", 8))
-  {
-   /*
-    * Map ppd-name to LSB standard /usr/share/ppd location...
-    */
+  return (0);
+}
 
-    snprintf(line, sizeof(line), "/usr/share/ppd/%s", name + 8);
-  }
-  else if (!strncmp(name, "lsb/opt/", 8))
-  {
-   /*
-    * Map ppd-name to LSB standard /opt/share/ppd location...
-    */
 
-    snprintf(line, sizeof(line), "/opt/share/ppd/%s", name + 8);
-  }
-  else if (!strncmp(name, "lsb/local/", 10))
-  {
-   /*
-    * Map ppd-name to LSB standard /usr/local/share/ppd location...
-    */
+/*
+ * 'cat_tar()' - Copy an archived PPD file to stdout.
+ */
 
-    snprintf(line, sizeof(line), "/usr/local/share/ppd/%s", name + 10);
-  }
-  else
+static int                             /* O - Exit code */
+cat_tar(const char *name,              /* I - PPD name */
+        int        request_id)         /* I - Request ID */
+{
+  cups_file_t  *fp;                    /* Archive file pointer */
+  char         filename[1024],         /* Archive filename */
+               *ppdname,               /* PPD filename in archive */
+               curname[256],           /* Current name in archive */
+               buffer[8192];           /* Copy buffer */
+  struct stat  curinfo;                /* Current file info in archive */
+  off_t                total,                  /* Total bytes copied */
+               next;                   /* Offset for next record in archive */
+  ssize_t      bytes;                  /* Bytes read */
 
-#endif /* __APPLE__ */
-  {
-    if ((datadir = getenv("CUPS_DATADIR")) == NULL)
-      datadir = CUPS_DATADIR;
 
-    snprintf(line, sizeof(line), "%s/model/%s", datadir, name);
-  }
+ /*
+  * Open the archive file...
+  */
+
+  if ((fp = get_file(name, request_id, "model", filename, sizeof(filename),
+                     &ppdname)) == NULL)
+    return (1);
+
+ /*
+  * Scan the archive for the PPD...
+  */
 
-  if ((fp = cupsFileOpen(line, "r")) == NULL)
+  while (read_tar(fp, curname, sizeof(curname), &curinfo))
   {
-    fprintf(stderr, "ERROR: [cups-driverd] Unable to open \"%s\" - %s\n",
-           line, strerror(errno));
+    next = cupsFileTell(fp) + ((curinfo.st_size + TAR_BLOCK - 1) &
+                               ~(TAR_BLOCK - 1));
 
-    if (request_id)
+    if (!strcmp(ppdname, curname))
     {
-      snprintf(message, sizeof(message), "Unable to open \"%s\" - %s",
-              line, strerror(errno));
+      if (request_id)
+      {
+       cupsdSendIPPHeader(IPP_OK, request_id);
+       cupsdSendIPPGroup(IPP_TAG_OPERATION);
+       cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
+       cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
+                          "en-US");
+       cupsdSendIPPTrailer();
+      }
 
-      cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
-      cupsdSendIPPGroup(IPP_TAG_OPERATION);
-      cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
-      cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
-                        "en-US");
-      cupsdSendIPPString(IPP_TAG_TEXT, "status-message", message);
-      cupsdSendIPPTrailer();
+      for (total = 0; total < curinfo.st_size; total += bytes)
+      {
+        if ((bytes = (curinfo.st_size - total)) > sizeof(buffer))
+          bytes = sizeof(buffer);
+
+        if ((bytes = cupsFileRead(fp, buffer, bytes)) < 0)
+        {
+          if (errno == EINTR || errno == EAGAIN)
+          {
+            bytes = 0;
+          }
+          else
+          {
+            perror("ERROR: [cups-driverd] Read error");
+            break;
+          }
+        }
+        else if (bytes > 0 && fwrite(buffer, bytes, 1, stdout) != 1)
+          break;
+      }
+
+      cupsFileClose(fp);
+      return (0);
     }
 
-    return (1);
+    if (cupsFileTell(fp) != next)
+      cupsFileSeek(fp, next);
   }
 
+  cupsFileClose(fp);
+
+  fprintf(stderr, "ERROR: PPD \"%s\" not found.\n", name);
+
   if (request_id)
   {
-    cupsdSendIPPHeader(IPP_OK, request_id);
+    snprintf(buffer, sizeof(buffer), "PPD \"%s\" not found.", name);
+
+    cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
     cupsdSendIPPGroup(IPP_TAG_OPERATION);
     cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
     cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
                       "en-US");
+    cupsdSendIPPString(IPP_TAG_TEXT, "status-message", buffer);
     cupsdSendIPPTrailer();
   }
 
- /*
-  * Now copy the file to stdout...
-  */
-
-  while (cupsFileGets(fp, line, sizeof(line)))
-    puts(line);
-
-  cupsFileClose(fp);
-
-  return (0);
+  return (1);
 }
 
 
@@ -818,96 +856,263 @@ free_array(cups_array_t *a)              /* I - Array to free */
 
 
 /*
- * 'list_ppds()' - List PPD files.
+ * 'get_file()' - Get the filename associated with a request.
  */
 
-static int                             /* O - Exit code */
-list_ppds(int        request_id,       /* I - Request ID */
-          int        limit,            /* I - Limit */
-         const char *opt)              /* I - Option argument */
+static cups_file_t *                   /* O - File pointer or NULL */
+get_file(const char *name,             /* I - Name */
+        int        request_id,         /* I - Request ID */
+        const char *subdir,            /* I - Subdirectory for file */
+        char       *buffer,            /* I - Filename buffer */
+        size_t     bufsize,            /* I - Size of filename buffer */
+        char       **subfile)          /* O - Sub-filename */
 {
-  int          i;                      /* Looping vars */
-  int          count;                  /* Number of PPDs to send */
-  ppd_info_t   *ppd;                   /* Current PPD file */
-  cups_file_t  *fp;                    /* ppds.dat file */
-  char         filename[1024],         /* ppds.dat filename */
-               model[1024];            /* Model directory */
-  const char   *cups_datadir;          /* CUPS_DATADIR environment variable */
-  int          num_options;            /* Number of options */
-  cups_option_t        *options;               /* Options */
-  cups_array_t *requested,             /* requested-attributes values */
-               *include,               /* PPD schemes to include */
-               *exclude;               /* PPD schemes to exclude */
-  const char   *device_id,             /* ppd-device-id option */
-               *language,              /* ppd-natural-language option */
-               *make,                  /* ppd-make option */
-               *make_and_model,        /* ppd-make-and-model option */
-               *model_number_str,      /* ppd-model-number option */
-               *product,               /* ppd-product option */
-               *psversion,             /* ppd-psversion option */
-               *type_str;              /* ppd-type option */
-  int          model_number,           /* ppd-model-number value */
-               type,                   /* ppd-type value */
-               make_and_model_len,     /* Length of ppd-make-and-model */
-               product_len,            /* Length of ppd-product */
-               send_device_id,         /* Send ppd-device-id? */
-               send_make,              /* Send ppd-make? */
-               send_make_and_model,    /* Send ppd-make-and-model? */
-               send_model_number,      /* Send ppd-model-number? */
-               send_name,              /* Send ppd-name? */
-               send_natural_language,  /* Send ppd-natural-language? */
-               send_product,           /* Send ppd-product? */
-               send_psversion,         /* Send ppd-psversion? */
-               send_type,              /* Send ppd-type? */
-               sent_header;            /* Sent the IPP header? */
-  regex_t      *device_id_re,          /* Regular expression for matching device ID */
-               *make_and_model_re;     /* Regular expression for matching make and model */
-  regmatch_t   re_matches[6];          /* Regular expression matches */
-  cups_array_t *matches;               /* Matching PPDs */
-
+  cups_file_t  *fp;                    /* File pointer */
+  const char   *datadir;               /* CUPS_DATADIR env var */
+  char         *bufptr,                /* Pointer into filename buffer */
+               message[2048];          /* status-message */
+#ifdef __APPLE__
+  const char   *printerDriver,         /* Pointer to .printerDriver extension */
+               *slash;                 /* Pointer to next slash */
+#endif /* __APPLE__ */
 
-  fprintf(stderr,
-          "DEBUG2: [cups-driverd] list_ppds(request_id=%d, limit=%d, "
-          "opt=\"%s\"\n", request_id, limit, opt);
 
- /*
-  * See if we a PPD database file...
-  */
+  if (subfile)
+    *subfile = NULL;
 
-  filename[0] = '\0';
-  load_ppds_dat(filename, sizeof(filename), 1);
+  while (*name == '/')
+    name ++;
 
- /*
-  * Load all PPDs in the specified directory and below...
-  */
+  if (strstr(name, "../") || strstr(name, "/.."))
+  {
+   /*
+    * Bad name...
+    */
 
-  if ((cups_datadir = getenv("CUPS_DATADIR")) == NULL)
-    cups_datadir = CUPS_DATADIR;
+    fprintf(stderr, "ERROR: [cups-driverd] Bad PPD name \"%s\".\n", name);
 
-  Inodes = cupsArrayNew((cups_array_func_t)compare_inodes, NULL);
+    if (request_id)
+    {
+      snprintf(message, sizeof(message), "Bad PPD name \"%s\".", name);
 
-  snprintf(model, sizeof(model), "%s/model", cups_datadir);
-  load_ppds(model, "", 1);
+      cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
+      cupsdSendIPPGroup(IPP_TAG_OPERATION);
+      cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
+      cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
+                        "en-US");
+      cupsdSendIPPString(IPP_TAG_TEXT, "status-message", message);
+      cupsdSendIPPTrailer();
+    }
 
-  snprintf(model, sizeof(model), "%s/drv", cups_datadir);
-  load_ppds(model, "", 1);
+    return (NULL);
+  }
 
-#ifdef __APPLE__
  /*
-  * Load PPDs from standard Mac OS X locations...
+  * Try opening the file...
   */
 
-  load_ppds("/Library/Printers",
-            "Library/Printers", 0);
-  load_ppds("/Library/Printers/PPDs/Contents/Resources",
-            "Library/Printers/PPDs/Contents/Resources", 0);
-  load_ppds("/Library/Printers/PPDs/Contents/Resources/en.lproj",
-            "Library/Printers/PPDs/Contents/Resources/en.lproj", 0);
-  load_ppds("/System/Library/Printers",
-            "System/Library/Printers", 0);
-  load_ppds("/System/Library/Printers/PPDs/Contents/Resources",
-            "System/Library/Printers/PPDs/Contents/Resources", 0);
-  load_ppds("/System/Library/Printers/PPDs/Contents/Resources/en.lproj",
+#ifdef __APPLE__
+  if (!strncmp(name, "System/Library/Printers/PPDs/Contents/Resources/", 48) ||
+      !strncmp(name, "Library/Printers/PPDs/Contents/Resources/", 41) ||
+      (!strncmp(name, "System/Library/Printers/", 24) &&
+       (printerDriver =
+           strstr(name + 24,
+                  ".printerDriver/Contents/Resources/PPDs")) != NULL &&
+       (slash = strchr(name + 24, '/')) != NULL &&
+       slash > printerDriver) ||
+      (!strncmp(name, "Library/Printers/", 17) &&
+       (printerDriver =
+           strstr(name + 17,
+                  ".printerDriver/Contents/Resources/PPDs")) != NULL &&
+       (slash = strchr(name + 17, '/')) != NULL &&
+       slash > printerDriver))
+  {
+   /*
+    * Map ppd-name to Mac OS X standard locations...
+    */
+
+    snprintf(buffer, bufsize, "/%s", name);
+  }
+  else
+
+#elif defined(__linux)
+  if (!strncmp(name, "lsb/usr/", 8))
+  {
+   /*
+    * Map ppd-name to LSB standard /usr/share/ppd location...
+    */
+
+    snprintf(buffer, bufsize, "/usr/share/ppd/%s", name + 8);
+  }
+  else if (!strncmp(name, "lsb/opt/", 8))
+  {
+   /*
+    * Map ppd-name to LSB standard /opt/share/ppd location...
+    */
+
+    snprintf(buffer, bufsize, "/opt/share/ppd/%s", name + 8);
+  }
+  else if (!strncmp(name, "lsb/local/", 10))
+  {
+   /*
+    * Map ppd-name to LSB standard /usr/local/share/ppd location...
+    */
+
+    snprintf(buffer, bufsize, "/usr/local/share/ppd/%s", name + 10);
+  }
+  else
+
+#endif /* __APPLE__ */
+  {
+    if ((datadir = getenv("CUPS_DATADIR")) == NULL)
+      datadir = CUPS_DATADIR;
+
+    snprintf(buffer, bufsize, "%s/%s/%s", datadir, subdir, name);
+  }
+
+ /*
+  * Strip anything after ".drv/", ".drv.gz/", ".tar/",  or ".tar.gz/"...
+  */
+
+  if (subfile)
+  {
+    if ((bufptr = strstr(buffer, ".drv/")) != NULL)
+      bufptr += 4;
+    else if ((bufptr = strstr(buffer, ".drv.gz/")) != NULL)
+      bufptr += 7;
+    else if ((bufptr = strstr(buffer, ".tar/")) != NULL)
+      bufptr += 4;
+    else if ((bufptr = strstr(buffer, ".tar.gz/")) != NULL)
+      bufptr += 7;
+
+    if (bufptr)
+    {
+      *bufptr++ = '\0';
+      *subfile  = bufptr;
+    }
+  }
+
+ /*
+  * Try opening the file...
+  */
+
+  if ((fp = cupsFileOpen(buffer, "r")) == NULL)
+  {
+    fprintf(stderr, "ERROR: [cups-driverd] Unable to open \"%s\" - %s\n",
+           buffer, strerror(errno));
+
+    if (request_id)
+    {
+      snprintf(message, sizeof(message), "Unable to open \"%s\" - %s",
+              buffer, strerror(errno));
+
+      cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
+      cupsdSendIPPGroup(IPP_TAG_OPERATION);
+      cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
+      cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
+                        "en-US");
+      cupsdSendIPPString(IPP_TAG_TEXT, "status-message", message);
+      cupsdSendIPPTrailer();
+    }
+
+    return (NULL);
+  }
+
+  return (fp);
+}
+
+
+/*
+ * 'list_ppds()' - List PPD files.
+ */
+
+static int                             /* O - Exit code */
+list_ppds(int        request_id,       /* I - Request ID */
+          int        limit,            /* I - Limit */
+         const char *opt)              /* I - Option argument */
+{
+  int          i;                      /* Looping vars */
+  int          count;                  /* Number of PPDs to send */
+  ppd_info_t   *ppd;                   /* Current PPD file */
+  cups_file_t  *fp;                    /* ppds.dat file */
+  char         filename[1024],         /* ppds.dat filename */
+               model[1024];            /* Model directory */
+  const char   *cups_datadir;          /* CUPS_DATADIR environment variable */
+  int          num_options;            /* Number of options */
+  cups_option_t        *options;               /* Options */
+  cups_array_t *requested,             /* requested-attributes values */
+               *include,               /* PPD schemes to include */
+               *exclude;               /* PPD schemes to exclude */
+  const char   *device_id,             /* ppd-device-id option */
+               *language,              /* ppd-natural-language option */
+               *make,                  /* ppd-make option */
+               *make_and_model,        /* ppd-make-and-model option */
+               *model_number_str,      /* ppd-model-number option */
+               *product,               /* ppd-product option */
+               *psversion,             /* ppd-psversion option */
+               *type_str;              /* ppd-type option */
+  int          model_number,           /* ppd-model-number value */
+               type,                   /* ppd-type value */
+               make_and_model_len,     /* Length of ppd-make-and-model */
+               product_len,            /* Length of ppd-product */
+               send_device_id,         /* Send ppd-device-id? */
+               send_make,              /* Send ppd-make? */
+               send_make_and_model,    /* Send ppd-make-and-model? */
+               send_model_number,      /* Send ppd-model-number? */
+               send_name,              /* Send ppd-name? */
+               send_natural_language,  /* Send ppd-natural-language? */
+               send_product,           /* Send ppd-product? */
+               send_psversion,         /* Send ppd-psversion? */
+               send_type,              /* Send ppd-type? */
+               sent_header;            /* Sent the IPP header? */
+  regex_t      *device_id_re,          /* Regular expression for matching device ID */
+               *make_and_model_re;     /* Regular expression for matching make and model */
+  regmatch_t   re_matches[6];          /* Regular expression matches */
+  cups_array_t *matches;               /* Matching PPDs */
+
+
+  fprintf(stderr,
+          "DEBUG2: [cups-driverd] list_ppds(request_id=%d, limit=%d, "
+          "opt=\"%s\"\n", request_id, limit, opt);
+
+ /*
+  * See if we a PPD database file...
+  */
+
+  filename[0] = '\0';
+  load_ppds_dat(filename, sizeof(filename), 1);
+
+ /*
+  * Load all PPDs in the specified directory and below...
+  */
+
+  if ((cups_datadir = getenv("CUPS_DATADIR")) == NULL)
+    cups_datadir = CUPS_DATADIR;
+
+  Inodes = cupsArrayNew((cups_array_func_t)compare_inodes, NULL);
+
+  snprintf(model, sizeof(model), "%s/model", cups_datadir);
+  load_ppds(model, "", 1);
+
+  snprintf(model, sizeof(model), "%s/drv", cups_datadir);
+  load_ppds(model, "", 1);
+
+#ifdef __APPLE__
+ /*
+  * Load PPDs from standard Mac OS X locations...
+  */
+
+  load_ppds("/Library/Printers",
+            "Library/Printers", 0);
+  load_ppds("/Library/Printers/PPDs/Contents/Resources",
+            "Library/Printers/PPDs/Contents/Resources", 0);
+  load_ppds("/Library/Printers/PPDs/Contents/Resources/en.lproj",
+            "Library/Printers/PPDs/Contents/Resources/en.lproj", 0);
+  load_ppds("/System/Library/Printers",
+            "System/Library/Printers", 0);
+  load_ppds("/System/Library/Printers/PPDs/Contents/Resources",
+            "System/Library/Printers/PPDs/Contents/Resources", 0);
+  load_ppds("/System/Library/Printers/PPDs/Contents/Resources/en.lproj",
             "System/Library/Printers/PPDs/Contents/Resources/en.lproj", 0);
 
 #elif defined(__linux)
@@ -1035,12 +1240,12 @@ list_ppds(int        request_id,        /* I - Request ID */
   if (type_str)
   {
     for (type = 0;
-         type < (int)(sizeof(ppd_types) / sizeof(ppd_types[0]));
+         type < (int)(sizeof(PPDTypes) / sizeof(PPDTypes[0]));
         type ++)
-      if (!strcmp(type_str, ppd_types[type]))
+      if (!strcmp(type_str, PPDTypes[type]))
         break;
 
-    if (type >= (int)(sizeof(ppd_types) / sizeof(ppd_types[0])))
+    if (type >= (int)(sizeof(PPDTypes) / sizeof(PPDTypes[0])))
     {
       fprintf(stderr, "ERROR: [cups-driverd] Bad ppd-type=\"%s\" ignored!\n",
               type_str);
@@ -1279,11 +1484,14 @@ list_ppds(int        request_id,        /* I - Request ID */
     {
       sent_header = 1;
 
-      cupsdSendIPPHeader(IPP_OK, request_id);
-      cupsdSendIPPGroup(IPP_TAG_OPERATION);
-      cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
-      cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
-                         "en-US");
+      if (request_id)
+      {
+       cupsdSendIPPHeader(IPP_OK, request_id);
+       cupsdSendIPPGroup(IPP_TAG_OPERATION);
+       cupsdSendIPPString(IPP_TAG_CHARSET, "attributes-charset", "utf-8");
+       cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language",
+                          "en-US");
+      }
     }
 
     fprintf(stderr, "DEBUG2: [cups-driverd] Sending %s (%s)...\n",
@@ -1291,56 +1499,61 @@ list_ppds(int        request_id,        /* I - Request ID */
 
     count --;
 
-    cupsdSendIPPGroup(IPP_TAG_PRINTER);
-
-    if (send_name)
-      cupsdSendIPPString(IPP_TAG_NAME, "ppd-name", ppd->record.name);
-
-    if (send_natural_language)
-    {
-      cupsdSendIPPString(IPP_TAG_LANGUAGE, "ppd-natural-language",
-                        ppd->record.languages[0]);
-
-      for (i = 1; i < PPD_MAX_LANG && ppd->record.languages[i][0]; i ++)
-       cupsdSendIPPString(IPP_TAG_LANGUAGE, "", ppd->record.languages[i]);
-    }
-
-    if (send_make)
-      cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make", ppd->record.make);
-
-    if (send_make_and_model)
-      cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make-and-model",
-                        ppd->record.make_and_model);
-
-    if (send_device_id)
-      cupsdSendIPPString(IPP_TAG_TEXT, "ppd-device-id",
-                        ppd->record.device_id);
-
-    if (send_product)
-    {
-      cupsdSendIPPString(IPP_TAG_TEXT, "ppd-product",
-                        ppd->record.products[0]);
-
-      for (i = 1; i < PPD_MAX_PROD && ppd->record.products[i][0]; i ++)
-       cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.products[i]);
-    }
-
-    if (send_psversion)
+    if (request_id)
     {
-      cupsdSendIPPString(IPP_TAG_TEXT, "ppd-psversion",
-                        ppd->record.psversions[0]);
-
-      for (i = 1; i < PPD_MAX_VERS && ppd->record.psversions[i][0]; i ++)
-       cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.psversions[i]);
+      cupsdSendIPPGroup(IPP_TAG_PRINTER);
+  
+      if (send_name)
+       cupsdSendIPPString(IPP_TAG_NAME, "ppd-name", ppd->record.name);
+  
+      if (send_natural_language)
+      {
+       cupsdSendIPPString(IPP_TAG_LANGUAGE, "ppd-natural-language",
+                          ppd->record.languages[0]);
+  
+       for (i = 1; i < PPD_MAX_LANG && ppd->record.languages[i][0]; i ++)
+         cupsdSendIPPString(IPP_TAG_LANGUAGE, "", ppd->record.languages[i]);
+      }
+  
+      if (send_make)
+       cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make", ppd->record.make);
+  
+      if (send_make_and_model)
+       cupsdSendIPPString(IPP_TAG_TEXT, "ppd-make-and-model",
+                          ppd->record.make_and_model);
+  
+      if (send_device_id)
+       cupsdSendIPPString(IPP_TAG_TEXT, "ppd-device-id",
+                          ppd->record.device_id);
+  
+      if (send_product)
+      {
+       cupsdSendIPPString(IPP_TAG_TEXT, "ppd-product",
+                          ppd->record.products[0]);
+  
+       for (i = 1; i < PPD_MAX_PROD && ppd->record.products[i][0]; i ++)
+         cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.products[i]);
+      }
+  
+      if (send_psversion)
+      {
+       cupsdSendIPPString(IPP_TAG_TEXT, "ppd-psversion",
+                          ppd->record.psversions[0]);
+  
+       for (i = 1; i < PPD_MAX_VERS && ppd->record.psversions[i][0]; i ++)
+         cupsdSendIPPString(IPP_TAG_TEXT, "", ppd->record.psversions[i]);
+      }
+  
+      if (send_type)
+       cupsdSendIPPString(IPP_TAG_KEYWORD, "ppd-type",
+                          PPDTypes[ppd->record.type]);
+  
+      if (send_model_number)
+       cupsdSendIPPInteger(IPP_TAG_INTEGER, "ppd-model-number",
+                           ppd->record.model_number);
     }
-
-    if (send_type)
-      cupsdSendIPPString(IPP_TAG_KEYWORD, "ppd-type",
-                        ppd_types[ppd->record.type]);
-
-    if (send_model_number)
-      cupsdSendIPPInteger(IPP_TAG_INTEGER, "ppd-model-number",
-                         ppd->record.model_number);
+    else
+      printf("%s (%s)\n", ppd->record.name, ppd->record.make_and_model);
 
    /*
     * If we have only requested the ppd-make attribute, then skip
@@ -1364,7 +1577,7 @@ list_ppds(int        request_id,  /* I - Request ID */
     }
   }
 
-  if (!sent_header)
+  if (!sent_header && request_id)
   {
     cupsdSendIPPHeader(IPP_NOT_FOUND, request_id);
     cupsdSendIPPGroup(IPP_TAG_OPERATION);
@@ -1372,7 +1585,8 @@ list_ppds(int        request_id,  /* I - Request ID */
     cupsdSendIPPString(IPP_TAG_LANGUAGE, "attributes-natural-language", "en-US");
   }
 
-  cupsdSendIPPTrailer();
+  if (request_id)
+    cupsdSendIPPTrailer();
 
   return (0);
 }
@@ -1693,12 +1907,12 @@ load_drivers(cups_array_t *include,     /* I - Drivers to include */
            *start++ = '\0';
 
          for (type = 0;
-               type < (int)(sizeof(ppd_types) / sizeof(ppd_types[0]));
+               type < (int)(sizeof(PPDTypes) / sizeof(PPDTypes[0]));
               type ++)
-           if (!strcmp(type_str, ppd_types[type]))
+           if (!strcmp(type_str, PPDTypes[type]))
               break;
 
-         if (type >= (int)(sizeof(ppd_types) / sizeof(ppd_types[0])))
+         if (type >= (int)(sizeof(PPDTypes) / sizeof(PPDTypes[0])))
          {
            fprintf(stderr,
                    "ERROR: [cups-driverd] Bad ppd-type \"%s\" ignored!\n",
@@ -1751,24 +1965,21 @@ load_drivers(cups_array_t *include,     /* I - Drivers to include */
 
 
 /*
- * 'load_ppds()' - Load PPD files recursively.
+ * 'load_ppd()' - Load a PPD file.
  */
 
-static int                             /* O - 1 on success, 0 on failure */
-load_ppds(const char *d,               /* I - Actual directory */
-          const char *p,               /* I - Virtual path in name */
-         int        descend)           /* I - Descend into directories? */
+static void
+load_ppd(const char  *filename,                /* I - Real filename */
+         const char  *name,            /* I - Virtual filename */
+         const char  *scheme,          /* I - PPD scheme */
+         struct stat *fileinfo,                /* I - File information */
+         ppd_info_t  *ppd,             /* I - Existing PPD file or NULL */
+         cups_file_t *fp,              /* I - File to read from */
+         off_t       end)              /* I - End of file position or 0 */
 {
-  struct stat  dinfo,                  /* Directory information */
-               *dinfoptr;              /* Pointer to match */
   int          i;                      /* Looping var */
-  cups_file_t  *fp;                    /* Pointer to file */
-  cups_dir_t   *dir;                   /* Directory pointer */
-  cups_dentry_t        *dent;                  /* Directory entry */
-  char         filename[1024],         /* Name of PPD or directory */
-               line[256],              /* Line from backend */
-               *ptr,                   /* Pointer into name */
-               name[128],              /* Name of PPD file */
+  char         line[256],              /* Line from file */
+               *ptr,                   /* Pointer into line */
                lang_version[64],       /* PPD LanguageVersion */
                lang_encoding[64],      /* PPD LanguageEncoding */
                country[64],            /* Country code */
@@ -1786,9 +1997,7 @@ load_ppds(const char *d,          /* I - Actual directory */
   cups_array_t *products,              /* Product array */
                *psversions,            /* PSVersion array */
                *cups_languages;        /* cupsLanguages array */
-  ppd_info_t   *ppd,                   /* New PPD file */
-               key;                    /* Search key */
-  int          new_ppd;                /* Is this a new PPD? */
+  int          new_ppd = !ppd;         /* Is this a new PPD? */
   struct                               /* LanguageVersion translation table */
   {
     const char *version,               /* LanguageVersion string */
@@ -1822,29 +2031,402 @@ load_ppds(const char *d,               /* I - Actual directory */
 
 
  /*
-  * See if we've loaded this directory before...
+  * Now read until we get the required fields...
   */
 
-  if (stat(d, &dinfo))
+  cups_languages = cupsArrayNew(NULL, NULL);
+  products       = cupsArrayNew(NULL, NULL);
+  psversions     = cupsArrayNew(NULL, NULL);
+
+  model_name[0]    = '\0';
+  nick_name[0]     = '\0';
+  manufacturer[0]  = '\0';
+  device_id[0]     = '\0';
+  lang_encoding[0] = '\0';
+  strcpy(lang_version, "en");
+  model_number     = 0;
+  install_group    = 0;
+  type             = PPD_TYPE_POSTSCRIPT;
+
+  while ((end == 0 || cupsFileTell(fp) < end) &&
+        cupsFileGets(fp, line, sizeof(line)))
   {
-    if (errno != ENOENT)
-      fprintf(stderr, "ERROR: [cups-driverd] Unable to stat \"%s\": %s\n", d,
-             strerror(errno));
+    if (!strncmp(line, "*Manufacturer:", 14))
+      sscanf(line, "%*[^\"]\"%255[^\"]", manufacturer);
+    else if (!strncmp(line, "*ModelName:", 11))
+      sscanf(line, "%*[^\"]\"%127[^\"]", model_name);
+    else if (!strncmp(line, "*LanguageEncoding:", 18))
+      sscanf(line, "%*[^:]:%63s", lang_encoding);
+    else if (!strncmp(line, "*LanguageVersion:", 17))
+      sscanf(line, "%*[^:]:%63s", lang_version);
+    else if (!strncmp(line, "*NickName:", 10))
+      sscanf(line, "%*[^\"]\"%255[^\"]", nick_name);
+    else if (!_cups_strncasecmp(line, "*1284DeviceID:", 14))
+    {
+      sscanf(line, "%*[^\"]\"%255[^\"]", device_id);
 
-    return (0);
-  }
-  else if (cupsArrayFind(Inodes, &dinfo))
-  {
-    fprintf(stderr, "ERROR: [cups-driverd] Skipping \"%s\": loop detected!\n",
-            d);
-    return (0);
-  }
+      // Make sure device ID ends with a semicolon...
+      if (device_id[0] && device_id[strlen(device_id) - 1] != ';')
+       strlcat(device_id, ";", sizeof(device_id));
+    }
+    else if (!strncmp(line, "*Product:", 9))
+    {
+      if (sscanf(line, "%*[^\"]\"(%255[^\"]", product) == 1)
+      {
+       /*
+       * Make sure the value ends with a right parenthesis - can't stop at
+       * the first right paren since the product name may contain escaped
+       * parenthesis...
+       */
 
- /*
-  * Nope, add it to the Inodes array and continue...
-  */
+       ptr = product + strlen(product) - 1;
+       if (ptr > product && *ptr == ')')
+       {
+        /*
+         * Yes, ends with a parenthesis, so remove it from the end and
+         * add the product to the list...
+         */
 
-  dinfoptr = (struct stat *)malloc(sizeof(struct stat));
+         *ptr = '\0';
+         cupsArrayAdd(products, strdup(product));
+       }
+      }
+    }
+    else if (!strncmp(line, "*PSVersion:", 11))
+    {
+      sscanf(line, "%*[^\"]\"%255[^\"]", psversion);
+      cupsArrayAdd(psversions, strdup(psversion));
+    }
+    else if (!strncmp(line, "*cupsLanguages:", 15))
+    {
+      char     *start;                 /* Start of language */
+
+
+      for (start = line + 15; *start && isspace(*start & 255); start ++);
+
+      if (*start++ == '\"')
+      {
+       while (*start)
+       {
+         for (ptr = start + 1;
+              *ptr && *ptr != '\"' && !isspace(*ptr & 255);
+              ptr ++);
+
+         if (*ptr)
+         {
+           *ptr++ = '\0';
+
+           while (isspace(*ptr & 255))
+             *ptr++ = '\0';
+         }
+
+         cupsArrayAdd(cups_languages, strdup(start));
+         start = ptr;
+       }
+      }
+    }
+    else if (!strncmp(line, "*cupsFax:", 9))
+    {
+      for (ptr = line + 9; isspace(*ptr & 255); ptr ++);
+
+      if (!_cups_strncasecmp(ptr, "true", 4))
+       type = PPD_TYPE_FAX;
+    }
+    else if (!strncmp(line, "*cupsFilter:", 12) && type == PPD_TYPE_POSTSCRIPT)
+    {
+      if (strstr(line + 12, "application/vnd.cups-raster"))
+       type = PPD_TYPE_RASTER;
+      else if (strstr(line + 12, "application/vnd.cups-pdf"))
+       type = PPD_TYPE_PDF;
+    }
+    else if (!strncmp(line, "*cupsModelNumber:", 17))
+      sscanf(line, "*cupsModelNumber:%d", &model_number);
+    else if (!strncmp(line, "*OpenGroup: Installable", 23))
+      install_group = 1;
+    else if (!strncmp(line, "*CloseGroup:", 12))
+      install_group = 0;
+    else if (!strncmp(line, "*OpenUI", 7))
+    {
+     /*
+      * Stop early if we have a NickName or ModelName attributes
+      * before the first non-installable OpenUI...
+      */
+
+      if (!install_group && (model_name[0] || nick_name[0]) &&
+         cupsArrayCount(products) > 0 && cupsArrayCount(psversions) > 0)
+       break;
+    }
+  }
+
+ /*
+  * See if we got all of the required info...
+  */
+
+  if (nick_name[0])
+    cupsCharsetToUTF8((cups_utf8_t *)make_model, nick_name,
+                     sizeof(make_model), _ppdGetEncoding(lang_encoding));
+  else
+    strcpy(make_model, model_name);
+
+  while (isspace(make_model[0] & 255))
+    _cups_strcpy(make_model, make_model + 1);
+
+  if (!make_model[0] || cupsArrayCount(products) == 0 ||
+      cupsArrayCount(psversions) == 0)
+  {
+   /*
+    * We don't have all the info needed, so skip this file...
+    */
+
+    if (!make_model[0])
+      fprintf(stderr, "WARNING: Missing NickName and ModelName in %s!\n",
+             filename);
+
+    if (cupsArrayCount(products) == 0)
+      fprintf(stderr, "WARNING: Missing Product in %s!\n", filename);
+
+    if (cupsArrayCount(psversions) == 0)
+      fprintf(stderr, "WARNING: Missing PSVersion in %s!\n", filename);
+
+    free_array(products);
+    free_array(psversions);
+    free_array(cups_languages);
+
+    return;
+  }
+
+  if (model_name[0])
+    cupsArrayAdd(products, strdup(model_name));
+
+ /*
+  * Normalize the make and model string...
+  */
+
+  while (isspace(manufacturer[0] & 255))
+    _cups_strcpy(manufacturer, manufacturer + 1);
+
+  if (!_cups_strncasecmp(make_model, manufacturer, strlen(manufacturer)))
+    strlcpy(temp, make_model, sizeof(temp));
+  else
+    snprintf(temp, sizeof(temp), "%s %s", manufacturer, make_model);
+
+  _ppdNormalizeMakeAndModel(temp, make_model, sizeof(make_model));
+
+ /*
+  * See if we got a manufacturer...
+  */
+
+  if (!manufacturer[0] || !strcmp(manufacturer, "ESP"))
+  {
+   /*
+    * Nope, copy the first part of the make and model then...
+    */
+
+    strlcpy(manufacturer, make_model, sizeof(manufacturer));
+
+   /*
+    * Truncate at the first space, dash, or slash, or make the
+    * manufacturer "Other"...
+    */
+
+    for (ptr = manufacturer; *ptr; ptr ++)
+      if (*ptr == ' ' || *ptr == '-' || *ptr == '/')
+       break;
+
+    if (*ptr && ptr > manufacturer)
+      *ptr = '\0';
+    else
+      strcpy(manufacturer, "Other");
+  }
+  else if (!_cups_strncasecmp(manufacturer, "LHAG", 4) ||
+          !_cups_strncasecmp(manufacturer, "linotype", 8))
+    strcpy(manufacturer, "LHAG");
+  else if (!_cups_strncasecmp(manufacturer, "Hewlett", 7))
+    strcpy(manufacturer, "HP");
+
+ /*
+  * Fix the lang_version as needed...
+  */
+
+  if ((ptr = strchr(lang_version, '-')) != NULL)
+    *ptr++ = '\0';
+  else if ((ptr = strchr(lang_version, '_')) != NULL)
+    *ptr++ = '\0';
+
+  if (ptr)
+  {
+   /*
+    * Setup the country suffix...
+    */
+
+    country[0] = '_';
+    _cups_strcpy(country + 1, ptr);
+  }
+  else
+  {
+   /*
+    * No country suffix...
+    */
+
+    country[0] = '\0';
+  }
+
+  for (i = 0; i < (int)(sizeof(languages) / sizeof(languages[0])); i ++)
+    if (!_cups_strcasecmp(languages[i].version, lang_version))
+      break;
+
+  if (i < (int)(sizeof(languages) / sizeof(languages[0])))
+  {
+   /*
+    * Found a known language...
+    */
+
+    snprintf(lang_version, sizeof(lang_version), "%s%s",
+            languages[i].language, country);
+  }
+  else
+  {
+   /*
+    * Unknown language; use "xx"...
+    */
+
+    strcpy(lang_version, "xx");
+  }
+
+ /*
+  * Record the PPD file...
+  */
+
+  new_ppd = !ppd;
+
+  if (new_ppd)
+  {
+   /*
+    * Add new PPD file...
+    */
+
+    fprintf(stderr, "DEBUG2: [cups-driverd] Adding ppd \"%s\"...\n", name);
+
+    ppd = add_ppd(name, name, lang_version, manufacturer, make_model,
+                 device_id, (char *)cupsArrayFirst(products),
+                 (char *)cupsArrayFirst(psversions),
+                 fileinfo->st_mtime, fileinfo->st_size,
+                 model_number, type, scheme);
+
+    if (!ppd)
+      return;
+  }
+  else
+  {
+   /*
+    * Update existing record...
+    */
+
+    fprintf(stderr, "DEBUG2: [cups-driverd] Updating ppd \"%s\"...\n", name);
+
+    memset(ppd, 0, sizeof(ppd_info_t));
+
+    ppd->found               = 1;
+    ppd->record.mtime        = fileinfo->st_mtime;
+    ppd->record.size         = fileinfo->st_size;
+    ppd->record.model_number = model_number;
+    ppd->record.type         = type;
+
+    strlcpy(ppd->record.filename, name, sizeof(ppd->record.filename));
+    strlcpy(ppd->record.name, name, sizeof(ppd->record.name));
+    strlcpy(ppd->record.languages[0], lang_version,
+           sizeof(ppd->record.languages[0]));
+    strlcpy(ppd->record.products[0], (char *)cupsArrayFirst(products),
+           sizeof(ppd->record.products[0]));
+    strlcpy(ppd->record.psversions[0], (char *)cupsArrayFirst(psversions),
+           sizeof(ppd->record.psversions[0]));
+    strlcpy(ppd->record.make, manufacturer, sizeof(ppd->record.make));
+    strlcpy(ppd->record.make_and_model, make_model,
+           sizeof(ppd->record.make_and_model));
+    strlcpy(ppd->record.device_id, device_id, sizeof(ppd->record.device_id));
+    strlcpy(ppd->record.scheme, scheme, sizeof(ppd->record.scheme));
+  }
+
+ /*
+  * Add remaining products, versions, and languages...
+  */
+
+  for (i = 1;
+       i < PPD_MAX_PROD && (ptr = (char *)cupsArrayNext(products)) != NULL;
+       i ++)
+    strlcpy(ppd->record.products[i], ptr,
+           sizeof(ppd->record.products[0]));
+
+  for (i = 1;
+       i < PPD_MAX_VERS && (ptr = (char *)cupsArrayNext(psversions)) != NULL;
+       i ++)
+    strlcpy(ppd->record.psversions[i], ptr,
+           sizeof(ppd->record.psversions[0]));
+
+  for (i = 1, ptr = (char *)cupsArrayFirst(cups_languages);
+       i < PPD_MAX_LANG && ptr;
+       i ++, ptr = (char *)cupsArrayNext(cups_languages))
+    strlcpy(ppd->record.languages[i], ptr,
+           sizeof(ppd->record.languages[0]));
+
+ /*
+  * Free products, versions, and languages...
+  */
+
+  free_array(cups_languages);
+  free_array(products);
+  free_array(psversions);
+
+  ChangedPPD = 1;
+}
+
+
+/*
+ * 'load_ppds()' - Load PPD files recursively.
+ */
+
+static int                             /* O - 1 on success, 0 on failure */
+load_ppds(const char *d,               /* I - Actual directory */
+          const char *p,               /* I - Virtual path in name */
+         int        descend)           /* I - Descend into directories? */
+{
+  struct stat  dinfo,                  /* Directory information */
+               *dinfoptr;              /* Pointer to match */
+  cups_file_t  *fp;                    /* Pointer to file */
+  cups_dir_t   *dir;                   /* Directory pointer */
+  cups_dentry_t        *dent;                  /* Directory entry */
+  char         filename[1024],         /* Name of PPD or directory */
+               line[256],              /* Line from file */
+               *ptr,                   /* Pointer into name */
+               name[128];              /* Name of PPD file */
+  ppd_info_t   *ppd,                   /* New PPD file */
+               key;                    /* Search key */
+
+
+ /*
+  * See if we've loaded this directory before...
+  */
+
+  if (stat(d, &dinfo))
+  {
+    if (errno != ENOENT)
+      fprintf(stderr, "ERROR: [cups-driverd] Unable to stat \"%s\": %s\n", d,
+             strerror(errno));
+
+    return (0);
+  }
+  else if (cupsArrayFind(Inodes, &dinfo))
+  {
+    fprintf(stderr, "ERROR: [cups-driverd] Skipping \"%s\": loop detected!\n",
+            d);
+    return (0);
+  }
+
+ /*
+  * Nope, add it to the Inodes array and continue...
+  */
+
+  dinfoptr = (struct stat *)malloc(sizeof(struct stat));
   memcpy(dinfoptr, &dinfo, sizeof(struct stat));
   cupsArrayAdd(Inodes, dinfoptr);
 
@@ -1978,373 +2560,36 @@ load_ppds(const char *d,               /* I - Actual directory */
     line[0] = '\0';
     cupsFileGets(fp, line, sizeof(line));
 
-    if (strncmp(line, "*PPD-Adobe:", 11))
-    {
-     /*
-      * Nope, treat it as a driver information file...
-      */
-
-      load_drv(filename, name, fp, dent->fileinfo.st_mtime,
-               dent->fileinfo.st_size);
-      continue;
-    }
-
-   /*
-    * Now read until we get the NickName field...
-    */
-
-    cups_languages = cupsArrayNew(NULL, NULL);
-    products       = cupsArrayNew(NULL, NULL);
-    psversions     = cupsArrayNew(NULL, NULL);
-
-    model_name[0]    = '\0';
-    nick_name[0]     = '\0';
-    manufacturer[0]  = '\0';
-    device_id[0]     = '\0';
-    lang_encoding[0] = '\0';
-    strcpy(lang_version, "en");
-    model_number     = 0;
-    install_group    = 0;
-    type             = PPD_TYPE_POSTSCRIPT;
-
-    while (cupsFileGets(fp, line, sizeof(line)) != NULL)
-    {
-      if (!strncmp(line, "*Manufacturer:", 14))
-       sscanf(line, "%*[^\"]\"%255[^\"]", manufacturer);
-      else if (!strncmp(line, "*ModelName:", 11))
-       sscanf(line, "%*[^\"]\"%127[^\"]", model_name);
-      else if (!strncmp(line, "*LanguageEncoding:", 18))
-       sscanf(line, "%*[^:]:%63s", lang_encoding);
-      else if (!strncmp(line, "*LanguageVersion:", 17))
-       sscanf(line, "%*[^:]:%63s", lang_version);
-      else if (!strncmp(line, "*NickName:", 10))
-       sscanf(line, "%*[^\"]\"%255[^\"]", nick_name);
-      else if (!_cups_strncasecmp(line, "*1284DeviceID:", 14))
-      {
-       sscanf(line, "%*[^\"]\"%255[^\"]", device_id);
-
-        // Make sure device ID ends with a semicolon...
-       if (device_id[0] && device_id[strlen(device_id) - 1] != ';')
-         strlcat(device_id, ";", sizeof(device_id));
-      }
-      else if (!strncmp(line, "*Product:", 9))
-      {
-       if (sscanf(line, "%*[^\"]\"(%255[^\"]", product) == 1)
-       {
-        /*
-         * Make sure the value ends with a right parenthesis - can't stop at
-         * the first right paren since the product name may contain escaped
-         * parenthesis...
-         */
-
-         ptr = product + strlen(product) - 1;
-         if (ptr > product && *ptr == ')')
-         {
-          /*
-           * Yes, ends with a parenthesis, so remove it from the end and
-           * add the product to the list...
-           */
-
-           *ptr = '\0';
-           cupsArrayAdd(products, strdup(product));
-         }
-       }
-      }
-      else if (!strncmp(line, "*PSVersion:", 11))
-      {
-       sscanf(line, "%*[^\"]\"%255[^\"]", psversion);
-       cupsArrayAdd(psversions, strdup(psversion));
-      }
-      else if (!strncmp(line, "*cupsLanguages:", 15))
-      {
-        char   *start;                 /* Start of language */
-
-
-        for (start = line + 15; *start && isspace(*start & 255); start ++);
-
-       if (*start++ == '\"')
-       {
-         while (*start)
-         {
-           for (ptr = start + 1;
-                *ptr && *ptr != '\"' && !isspace(*ptr & 255);
-                ptr ++);
-
-            if (*ptr)
-           {
-             *ptr++ = '\0';
-
-             while (isspace(*ptr & 255))
-               *ptr++ = '\0';
-            }
-
-            cupsArrayAdd(cups_languages, strdup(start));
-           start = ptr;
-         }
-       }
-      }
-      else if (!strncmp(line, "*cupsFax:", 9))
-      {
-        for (ptr = line + 9; isspace(*ptr & 255); ptr ++);
-
-       if (!_cups_strncasecmp(ptr, "true", 4))
-          type = PPD_TYPE_FAX;
-      }
-      else if (!strncmp(line, "*cupsFilter:", 12) && type == PPD_TYPE_POSTSCRIPT)
-      {
-        if (strstr(line + 12, "application/vnd.cups-raster"))
-         type = PPD_TYPE_RASTER;
-        else if (strstr(line + 12, "application/vnd.cups-pdf"))
-         type = PPD_TYPE_PDF;
-      }
-      else if (!strncmp(line, "*cupsModelNumber:", 17))
-        sscanf(line, "*cupsModelNumber:%d", &model_number);
-      else if (!strncmp(line, "*OpenGroup: Installable", 23))
-        install_group = 1;
-      else if (!strncmp(line, "*CloseGroup:", 12))
-        install_group = 0;
-      else if (!strncmp(line, "*OpenUI", 7))
-      {
-       /*
-        * Stop early if we have a NickName or ModelName attributes
-       * before the first non-installable OpenUI...
-       */
-
-        if (!install_group && (model_name[0] || nick_name[0]) &&
-            cupsArrayCount(products) > 0 && cupsArrayCount(psversions) > 0)
-         break;
-      }
-    }
-
-   /*
-    * Close the file...
-    */
-
-    cupsFileClose(fp);
-
-   /*
-    * See if we got all of the required info...
-    */
-
-    if (nick_name[0])
-      cupsCharsetToUTF8((cups_utf8_t *)make_model, nick_name,
-                        sizeof(make_model), _ppdGetEncoding(lang_encoding));
-    else
-      strcpy(make_model, model_name);
-
-    while (isspace(make_model[0] & 255))
-      _cups_strcpy(make_model, make_model + 1);
-
-    if (!make_model[0] || cupsArrayCount(products) == 0 ||
-        cupsArrayCount(psversions) == 0)
+    if (!strncmp(line, "*PPD-Adobe:", 11))
     {
      /*
-      * We don't have all the info needed, so skip this file...
+      * Yes, load it...
       */
 
-      if (!make_model[0])
-        fprintf(stderr, "WARNING: Missing NickName and ModelName in %s!\n",
-               filename);
-
-      if (cupsArrayCount(products) == 0)
-        fprintf(stderr, "WARNING: Missing Product in %s!\n", filename);
-
-      if (cupsArrayCount(psversions) == 0)
-        fprintf(stderr, "WARNING: Missing PSVersion in %s!\n", filename);
-
-      free_array(products);
-      free_array(psversions);
-      free_array(cups_languages);
-
-      continue;
+      load_ppd(filename, name, "file", &dent->fileinfo, ppd, fp, 0);
     }
-
-    if (model_name[0])
-      cupsArrayAdd(products, strdup(model_name));
-
-   /*
-    * Normalize the make and model string...
-    */
-
-    while (isspace(manufacturer[0] & 255))
-      _cups_strcpy(manufacturer, manufacturer + 1);
-
-    if (!_cups_strncasecmp(make_model, manufacturer, strlen(manufacturer)))
-      strlcpy(temp, make_model, sizeof(temp));
     else
-      snprintf(temp, sizeof(temp), "%s %s", manufacturer, make_model);
-
-    _ppdNormalizeMakeAndModel(temp, make_model, sizeof(make_model));
-
-   /*
-    * See if we got a manufacturer...
-    */
-
-    if (!manufacturer[0] || !strcmp(manufacturer, "ESP"))
     {
      /*
-      * Nope, copy the first part of the make and model then...
-      */
-
-      strlcpy(manufacturer, make_model, sizeof(manufacturer));
-
-     /*
-      * Truncate at the first space, dash, or slash, or make the
-      * manufacturer "Other"...
+      * Nope, treat it as a driver information file or archive...
       */
 
-      for (ptr = manufacturer; *ptr; ptr ++)
-       if (*ptr == ' ' || *ptr == '-' || *ptr == '/')
-         break;
+      cupsFileRewind(fp);
 
-      if (*ptr && ptr > manufacturer)
-       *ptr = '\0';
+      if ((ptr = strstr(filename, ".tar")) != NULL &&
+          (!strcmp(ptr, ".tar") || !strcmp(ptr, ".tar.gz")))
+        load_tar(filename, name, fp, dent->fileinfo.st_mtime,
+                 dent->fileinfo.st_size);
       else
-       strcpy(manufacturer, "Other");
-    }
-    else if (!_cups_strncasecmp(manufacturer, "LHAG", 4) ||
-             !_cups_strncasecmp(manufacturer, "linotype", 8))
-      strcpy(manufacturer, "LHAG");
-    else if (!_cups_strncasecmp(manufacturer, "Hewlett", 7))
-      strcpy(manufacturer, "HP");
-
-   /*
-    * Fix the lang_version as needed...
-    */
-
-    if ((ptr = strchr(lang_version, '-')) != NULL)
-      *ptr++ = '\0';
-    else if ((ptr = strchr(lang_version, '_')) != NULL)
-      *ptr++ = '\0';
-
-    if (ptr)
-    {
-     /*
-      * Setup the country suffix...
-      */
-
-      country[0] = '_';
-      _cups_strcpy(country + 1, ptr);
-    }
-    else
-    {
-     /*
-      * No country suffix...
-      */
-
-      country[0] = '\0';
-    }
-
-    for (i = 0; i < (int)(sizeof(languages) / sizeof(languages[0])); i ++)
-      if (!_cups_strcasecmp(languages[i].version, lang_version))
-        break;
-
-    if (i < (int)(sizeof(languages) / sizeof(languages[0])))
-    {
-     /*
-      * Found a known language...
-      */
-
-      snprintf(lang_version, sizeof(lang_version), "%s%s",
-               languages[i].language, country);
-    }
-    else
-    {
-     /*
-      * Unknown language; use "xx"...
-      */
-
-      strcpy(lang_version, "xx");
+       load_drv(filename, name, fp, dent->fileinfo.st_mtime,
+                dent->fileinfo.st_size);
     }
 
    /*
-    * Record the PPD file...
-    */
-
-    new_ppd = !ppd;
-
-    if (new_ppd)
-    {
-     /*
-      * Add new PPD file...
-      */
-
-      fprintf(stderr, "DEBUG2: [cups-driverd] Adding ppd \"%s\"...\n", name);
-
-      ppd = add_ppd(name, name, lang_version, manufacturer, make_model,
-                    device_id, (char *)cupsArrayFirst(products),
-                    (char *)cupsArrayFirst(psversions),
-                    dent->fileinfo.st_mtime, dent->fileinfo.st_size,
-                   model_number, type, "file");
-
-      if (!ppd)
-      {
-        cupsDirClose(dir);
-       return (0);
-      }
-    }
-    else
-    {
-     /*
-      * Update existing record...
-      */
-
-      fprintf(stderr, "DEBUG2: [cups-driverd] Updating ppd \"%s\"...\n", name);
-
-      memset(ppd, 0, sizeof(ppd_info_t));
-
-      ppd->found               = 1;
-      ppd->record.mtime        = dent->fileinfo.st_mtime;
-      ppd->record.size         = dent->fileinfo.st_size;
-      ppd->record.model_number = model_number;
-      ppd->record.type         = type;
-
-      strlcpy(ppd->record.filename, name, sizeof(ppd->record.filename));
-      strlcpy(ppd->record.name, name, sizeof(ppd->record.name));
-      strlcpy(ppd->record.languages[0], lang_version,
-              sizeof(ppd->record.languages[0]));
-      strlcpy(ppd->record.products[0], (char *)cupsArrayFirst(products),
-              sizeof(ppd->record.products[0]));
-      strlcpy(ppd->record.psversions[0], (char *)cupsArrayFirst(psversions),
-              sizeof(ppd->record.psversions[0]));
-      strlcpy(ppd->record.make, manufacturer, sizeof(ppd->record.make));
-      strlcpy(ppd->record.make_and_model, make_model,
-              sizeof(ppd->record.make_and_model));
-      strlcpy(ppd->record.device_id, device_id, sizeof(ppd->record.device_id));
-      strlcpy(ppd->record.scheme, "file", sizeof(ppd->record.scheme));
-    }
-
-   /*
-    * Add remaining products, versions, and languages...
-    */
-
-    for (i = 1;
-         i < PPD_MAX_PROD && (ptr = (char *)cupsArrayNext(products)) != NULL;
-        i ++)
-      strlcpy(ppd->record.products[i], ptr,
-              sizeof(ppd->record.products[0]));
-
-    for (i = 1;
-         i < PPD_MAX_VERS && (ptr = (char *)cupsArrayNext(psversions)) != NULL;
-        i ++)
-      strlcpy(ppd->record.psversions[i], ptr,
-              sizeof(ppd->record.psversions[0]));
-
-    for (i = 1, ptr = (char *)cupsArrayFirst(cups_languages);
-         i < PPD_MAX_LANG && ptr;
-        i ++, ptr = (char *)cupsArrayNext(cups_languages))
-      strlcpy(ppd->record.languages[i], ptr,
-              sizeof(ppd->record.languages[0]));
-
-   /*
-    * Free products, versions, and languages...
+    * Close the file...
     */
 
-    free_array(cups_languages);
-    free_array(products);
-    free_array(psversions);
-
-    ChangedPPD = 1;
+    cupsFileClose(fp);
   }
 
   cupsDirClose(dir);
@@ -2433,6 +2678,115 @@ load_ppds_dat(char   *filename,         /* I - Filename buffer */
 }
 
 
+/*
+ * 'load_tar()' - Load archived PPD files.
+ */
+
+static int                             /* O - 1 on success, 0 on failure */
+load_tar(const char  *filename,                /* I - Actual filename */
+         const char  *name,            /* I - Name to the rest of the world */
+         cups_file_t *fp,              /* I - File to read from */
+        time_t      mtime,             /* I - Mod time of driver info file */
+        off_t       size)              /* I - Size of driver info file */
+{
+  char         curname[256],           /* Current archive file name */
+               uri[1024];              /* Virtual file URI */
+  const char   *curext;                /* Extension on file */
+  struct stat  curinfo;                /* Current archive file information */
+  off_t                next;                   /* Position for next header */
+
+
+ /*
+  * Add a dummy entry for the file...
+  */
+
+  add_ppd(name, name, "", "", "", "", "", "", mtime, size, 0,
+          PPD_TYPE_ARCHIVE, "file");
+  ChangedPPD = 1;
+
+ /*
+  * Scan for PPDs in the archive...
+  */
+
+  while (read_tar(fp, curname, sizeof(curname), &curinfo))
+  {
+    next = cupsFileTell(fp) + ((curinfo.st_size + TAR_BLOCK - 1) &
+                               ~(TAR_BLOCK - 1));
+
+    if ((curext = strrchr(curname, '.')) != NULL &&
+        !_cups_strcasecmp(curext, ".ppd"))
+    {
+      httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "file", "", "",
+                       0, "/%s/%s", name, curname);
+      load_ppd(name, uri, "file", &curinfo, NULL, fp, next);
+    }
+
+    if (cupsFileTell(fp) != next)
+      cupsFileSeek(fp, next);
+  }
+
+  return (1);
+}
+
+
+/*
+ * 'read_tar()' - Read a file header from an archive.
+ *
+ * This function skips all directories and special files.
+ */
+
+static int                             /* O - 1 if found, 0 on EOF */
+read_tar(cups_file_t *fp,              /* I - Archive to read */
+         char        *name,            /* I - Filename buffer */
+         size_t      namesize,         /* I - Size of filename buffer */
+         struct stat *info)            /* O - File information */
+{
+  tar_rec_t    record;                 /* Record from file */
+
+
+  while (cupsFileRead(fp, (char *)&record, sizeof(record)) == sizeof(record))
+  {
+   /*
+    * Check for a valid tar header...
+    */
+
+    if (memcmp(record.header.magic, TAR_MAGIC, 6) ||
+        memcmp(record.header.version, TAR_VERSION, 2))
+    {
+      if (record.header.magic[0] ||
+          memcmp(record.header.magic, record.header.magic + 1, 5))
+       fputs("ERROR: [cups-driverd] Bad tar magic/version.\n", stderr);
+      break;
+    }
+
+   /*
+    * Ignore non-files...
+    */
+
+    if (record.header.linkflag != TAR_OLDNORMAL &&
+        record.header.linkflag != TAR_NORMAL)
+      continue;
+
+   /*
+    * Grab size and name from tar header and return...
+    */
+
+    if (record.header.prefix[0])
+      snprintf(name, namesize, "%s/%s", record.header.prefix,
+               record.header.pathname);
+    else
+      strlcpy(name, record.header.pathname, namesize);
+
+    info->st_mtime = strtol(record.header.mtime, NULL, 8);
+    info->st_size  = strtoll(record.header.size, NULL, 8);
+
+    return (1);
+  }
+
+  return (0);
+}
+
+
 /*
  * 'regex_device_id()' - Compile a regular expression based on the 1284 device
  *                       ID.
index a4cc377af3b57d869abee6bc9b200886ccf8bfb4..49bfe8122fc33196f7b063e0c61a3b768013f70c 100644 (file)
@@ -237,7 +237,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
     list = NULL;
   else
   {
-    for (list = dest + 1; *list && !isspace(*list & 255); list ++);
+    for (list = dest; *list && !isspace(*list & 255); list ++);
 
     while (isspace(*list & 255))
       *list++ = '\0';
index 8d7117bb2b78d254fb292166cf0227df4dcb68f6..12869a81b7864ef8fc17ce972617fd1e3bb35cb0 100644 (file)
@@ -82,12 +82,10 @@ extern const char *cups_hstrerror(int);
  * Defaults...
  */
 
-#define DEFAULT_HISTORY                1       /* Preserve job history? */
-#define DEFAULT_FILES          0       /* Preserve job files? */
+#define DEFAULT_HISTORY                INT_MAX /* Preserve job history? */
+#define DEFAULT_FILES          86400   /* Preserve job files? */
 #define DEFAULT_TIMEOUT                300     /* Timeout during requests/updates */
 #define DEFAULT_KEEPALIVE      30      /* Timeout between requests */
-#define DEFAULT_INTERVAL       30      /* Interval between browse updates */
-#define DEFAULT_CHARSET                "utf-8" /* Default charset */
 
 
 /*
index a9c07aa07db065dc4dc5769bda8c734595583350..53968b897b034f55637eef7f4eb3c34d6be5aa60 100644 (file)
  *
  * Contents:
  *
- *   cupsdAddJob()              - Add a new job to the job queue.
- *   cupsdCancelJobs()          - Cancel all jobs for the given
- *                                destination/user.
- *   cupsdCheckJobs()           - Check the pending jobs and start any if the
- *                                destination is available.
- *   cupsdCleanJobs()           - Clean out old jobs.
- *   cupsdContinueJob()         - Continue printing with the next file in a job.
- *   cupsdDeleteJob()           - Free all memory used by a job.
- *   cupsdFreeAllJobs()         - Free all jobs from memory.
- *   cupsdFindJob()             - Find the specified job.
- *   cupsdGetPrinterJobCount()  - Get the number of pending, processing, or held
- *                                jobs in a printer or class.
- *   cupsdGetUserJobCount()     - Get the number of pending, processing, or held
- *                                jobs for a user.
- *   cupsdLoadAllJobs()         - Load all jobs from disk.
- *   cupsdLoadJob()             - Load a single job.
- *   cupsdMoveJob()             - Move the specified job to a different
- *                                destination.
- *   cupsdReleaseJob()          - Release the specified job.
- *   cupsdRestartJob()          - Restart the specified job.
- *   cupsdSaveAllJobs()         - Save a summary of all jobs to disk.
- *   cupsdSaveJob()             - Save a job to disk.
- *   cupsdSetJobHoldUntil()     - Set the hold time for a job.
- *   cupsdSetJobPriority()      - Set the priority of a job, moving it up/down
- *                                in the list as needed.
- *   cupsdSetJobState()         - Set the state of the specified print job.
- *   cupsdStopAllJobs()         - Stop all print jobs.
+*   cupsdAddJob()           - Add a new job to the job queue.
+ *   cupsdCancelJobs()         - Cancel all jobs for the given
+ *                               destination/user.
+ *   cupsdCheckJobs()          - Check the pending jobs and start any if the
+ *                               destination is available.
+ *   cupsdCleanJobs()          - Clean out old jobs.
+ *   cupsdContinueJob()        - Continue printing with the next file in a
+ *                               job.
+ *   cupsdDeleteJob()          - Free all memory used by a job.
+ *   cupsdFreeAllJobs()        - Free all jobs from memory.
+ *   cupsdFindJob()            - Find the specified job.
+ *   cupsdGetPrinterJobCount() - Get the number of pending, processing, or
+ *                               held jobs in a printer or class.
+ *   cupsdGetUserJobCount()    - Get the number of pending, processing, or
+ *                               held jobs for a user.
+ *   cupsdLoadAllJobs()        - Load all jobs from disk.
+ *   cupsdLoadJob()            - Load a single job.
+ *   cupsdMoveJob()            - Move the specified job to a different
+ *                               destination.
+ *   cupsdReleaseJob()         - Release the specified job.
+ *   cupsdRestartJob()         - Restart the specified job.
+ *   cupsdSaveAllJobs()        - Save a summary of all jobs to disk.
+ *   cupsdSaveJob()            - Save a job to disk.
+ *   cupsdSetJobHoldUntil()    - Set the hold time for a job.
+ *   cupsdSetJobPriority()     - Set the priority of a job, moving it up/down
+ *                               in the list as needed.
+ *   cupsdSetJobState()        - Set the state of the specified print job.
+ *   cupsdStopAllJobs()        - Stop all print jobs.
  *   cupsdUnloadCompletedJobs() - Flush completed job history from memory.
- *   compare_active_jobs()      - Compare the job IDs and priorities of two
- *                                jobs.
- *   compare_jobs()             - Compare the job IDs of two jobs.
- *   dump_job_history()         - Dump any debug messages for a job.
- *   free_job_history()         - Free any log history.
- *   finalize_job()             - Cleanup after job filter processes and support
- *                                data.
- *   get_options()              - Get a string containing the job options.
- *   ipp_length()               - Compute the size of the buffer needed to hold
- *                                the textual IPP attributes.
- *   load_job_cache()           - Load jobs from the job.cache file.
- *   load_next_job_id()         - Load the NextJobId value from the job.cache
- *                                file.
- *   load_request_root()        - Load jobs from the RequestRoot directory.
- *   set_time()                 - Set one of the "time-at-xyz" attributes.
- *   start_job()                - Start a print job.
- *   stop_job()                 - Stop a print job.
- *   unload_job()               - Unload a job from memory.
- *   update_job()               - Read a status update from a job's filters.
- *   update_job_attrs()         - Update the job-printer-* attributes.
+ *   cupsdUpdateJobs()          - Update the history/file files for all jobs.
+ *   compare_active_jobs()     - Compare the job IDs and priorities of two
+ *                               jobs.
+ *   compare_jobs()            - Compare the job IDs of two jobs.
+ *   dump_job_history()        - Dump any debug messages for a job.
+ *   free_job_history()        - Free any log history.
+ *   finalize_job()            - Cleanup after job filter processes and
+ *                               support data.
+ *   get_options()             - Get a string containing the job options.
+ *   ipp_length()              - Compute the size of the buffer needed to hold
+ *                               the textual IPP attributes.
+ *   load_job_cache()          - Load jobs from the job.cache file.
+ *   load_next_job_id()        - Load the NextJobId value from the job.cache
+ *                               file.
+ *   load_request_root()       - Load jobs from the RequestRoot directory.
+ *   remove_job_files()        - Remove the document files for a job.
+ *   remove_job_history()      - Remove the control file for a job.
+ *   set_time()                - Set one of the "time-at-xyz" attributes.
+ *   start_job()               - Start a print job.
+ *   stop_job()                - Stop a print job.
+ *   unload_job()              - Unload a job from memory.
+ *   update_job()              - Read a status update from a job's filters.
+ *   update_job_attrs()        - Update the job-printer-* attributes.
  */
 
 /*
@@ -181,6 +185,8 @@ static size_t       ipp_length(ipp_t *ipp);
 static void    load_job_cache(const char *filename);
 static void    load_next_job_id(const char *filename);
 static void    load_request_root(void);
+static void    remove_job_files(cupsd_job_t *job);
+static void    remove_job_history(cupsd_job_t *job);
 static void    set_time(cupsd_job_t *job, const char *name);
 static void    start_job(cupsd_job_t *job, cupsd_printer_t *printer);
 static void    stop_job(cupsd_job_t *job, cupsd_jobaction_t action);
@@ -447,16 +453,56 @@ void
 cupsdCleanJobs(void)
 {
   cupsd_job_t  *job;                   /* Current job */
+  time_t       curtime;                /* Current time */
+
 
+  cupsdLogMessage(CUPSD_LOG_DEBUG2,
+                  "cupsdCleanJobs: MaxJobs=%d, JobHistory=%d, JobFiles=%d",
+                  MaxJobs, JobHistory, JobFiles);
 
-  if (MaxJobs <= 0 && JobHistory)
+  if (MaxJobs <= 0 && JobHistory == INT_MAX && JobFiles == INT_MAX)
     return;
 
+  curtime          = time(NULL);
+  JobHistoryUpdate = 0;
+
   for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
-       job && (cupsArrayCount(Jobs) >= MaxJobs || !JobHistory);
+       job;
        job = (cupsd_job_t *)cupsArrayNext(Jobs))
+  {
     if (job->state_value >= IPP_JOB_CANCELED && !job->printer)
-      cupsdDeleteJob(job, CUPSD_JOB_PURGE);
+    {
+     /*
+      * Expire old jobs (or job files)...
+      */
+
+      if ((MaxJobs > 0 && cupsArrayCount(Jobs) >= MaxJobs) ||
+          (job->history_time && job->history_time <= curtime))
+      {
+        cupsdLogJob(job, CUPSD_LOG_DEBUG, "Removing from history.");
+       cupsdDeleteJob(job, CUPSD_JOB_PURGE);
+      }
+      else if (job->file_time && job->file_time <= curtime)
+      {
+        cupsdLogJob(job, CUPSD_LOG_DEBUG, "Removing document files.");
+        remove_job_files(job);
+
+        if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+         JobHistoryUpdate = job->history_time;
+      }
+      else
+      {
+        if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+         JobHistoryUpdate = job->history_time;
+
+       if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
+         JobHistoryUpdate = job->file_time;
+      }
+    }
+  }
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdCleanJobs: JobHistoryUpdate=%ld",
+                  (long)JobHistoryUpdate);
 }
 
 
@@ -1327,25 +1373,13 @@ cupsdDeleteJob(cupsd_job_t       *job,  /* I - Job */
                cupsd_jobaction_t action)/* I - Action */
 {
   int  i;                              /* Looping var */
-  char filename[1024];                 /* Job filename */
 
 
   if (job->printer)
     finalize_job(job, 1);
 
   if (action == CUPSD_JOB_PURGE)
-  {
-   /*
-    * Remove the job info file...
-    */
-
-    snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot,
-            job->id);
-    if (Classification)
-      cupsdRemoveFile(filename);
-    else
-      unlink(filename);
-  }
+    remove_job_history(job);
 
   cupsdClearString(&job->username);
   cupsdClearString(&job->dest);
@@ -1355,27 +1389,14 @@ cupsdDeleteJob(cupsd_job_t       *job,  /* I - Job */
     cupsdClearString(job->auth_env + i);
   cupsdClearString(&job->auth_uid);
 
-  if (job->num_files > 0)
+  if (action == CUPSD_JOB_PURGE)
+    remove_job_files(job);
+  else if (job->num_files > 0)
   {
     free(job->compressions);
     free(job->filetypes);
 
-    if (action == CUPSD_JOB_PURGE)
-    {
-      while (job->num_files > 0)
-      {
-       snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
-                job->id, job->num_files);
-       if (Classification)
-         cupsdRemoveFile(filename);
-       else
-         unlink(filename);
-
-       job->num_files --;
-      }
-    }
-    else
-      job->num_files = 0;
+    job->num_files = 0;
   }
 
   if (job->history)
@@ -1593,22 +1614,8 @@ cupsdLoadJob(cupsd_job_t *job)           /* I - Job */
   cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] Loading attributes...", job->id);
 
   snprintf(jobfile, sizeof(jobfile), "%s/c%05d", RequestRoot, job->id);
-  if ((fp = cupsFileOpen(jobfile, "r")) == NULL)
-  {
-    char newfile[1024];                        /* New job filename */
-
-    snprintf(newfile, sizeof(newfile), "%s/c%05d.N", RequestRoot, job->id);
-    if ((fp = cupsFileOpen(newfile, "r")) == NULL)
-    {
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                     "[Job %d] Unable to open job control file \"%s\": %s",
-                     job->id, jobfile, strerror(errno));
-      goto error;
-    }
-
-    unlink(jobfile);
-    rename(newfile, jobfile);
-  }
+  if ((fp = cupsdOpenConfFile(jobfile)) == NULL)
+    goto error;
 
   if (ippReadIO(fp, (ipp_iocb_t)cupsFileRead, 1, NULL, job->attrs) != IPP_DATA)
   {
@@ -1642,7 +1649,36 @@ cupsdLoadJob(cupsd_job_t *job)           /* I - Job */
     goto error;
   }
 
-  job->state_value = (ipp_jstate_t)job->state->values[0].integer;
+  job->state_value  = (ipp_jstate_t)job->state->values[0].integer;
+  job->file_time    = 0;
+  job->history_time = 0;
+
+  if (job->state_value >= IPP_JOB_CANCELED &&
+      (attr = ippFindAttribute(job->attrs, "time-at-completed",
+                              IPP_TAG_INTEGER)) != NULL)
+  {
+    if (JobHistory < INT_MAX)
+      job->history_time = attr->values[0].integer + JobHistory;
+    else
+      job->history_time = INT_MAX;
+
+    if (job->history_time < time(NULL))
+      goto error;                      /* Expired, remove from history */
+
+    if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+      JobHistoryUpdate = job->history_time;
+
+    if (JobFiles < INT_MAX)
+      job->file_time = attr->values[0].integer + JobFiles;
+    else
+      job->file_time = INT_MAX;
+
+    if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
+      JobHistoryUpdate = job->file_time;
+
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdLoadJob: JobHistoryUpdate=%ld",
+                   (long)JobHistoryUpdate);
+  }
 
   if (!job->dest)
   {
@@ -1685,6 +1721,7 @@ cupsdLoadJob(cupsd_job_t *job)            /* I - Job */
 
     switch (job->state_value)
     {
+      default :
       case IPP_JOB_PENDING :
           if (destptr->state == IPP_PRINTER_STOPPED)
             reason = "printer-stopped";
@@ -1950,24 +1987,8 @@ cupsdLoadJob(cupsd_job_t *job)           /* I - Job */
   ippDelete(job->attrs);
   job->attrs = NULL;
 
-  if (job->compressions)
-  {
-    free(job->compressions);
-    job->compressions = NULL;
-  }
-
-  if (job->filetypes)
-  {
-    free(job->filetypes);
-    job->filetypes = NULL;
-  }
-
-  job->num_files = 0;
-
-  if (Classification)
-    cupsdRemoveFile(jobfile);
-  else
-    unlink(jobfile);
+  remove_job_history(job);
+  remove_job_files(job);
 
   return (0);
 }
@@ -2140,8 +2161,7 @@ cupsdSaveAllJobs(void)
 void
 cupsdSaveJob(cupsd_job_t *job)         /* I - Job */
 {
-  char         filename[1024],         /* Job control filename */
-               newfile[1024];          /* New job control filename */
+  char         filename[1024];         /* Job control filename */
   cups_file_t  *fp;                    /* Job file */
 
 
@@ -2149,17 +2169,10 @@ cupsdSaveJob(cupsd_job_t *job)          /* I - Job */
                   job, job->id, job->attrs);
 
   snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot, job->id);
-  snprintf(newfile, sizeof(newfile), "%s/c%05d.N", RequestRoot, job->id);
 
-  if ((fp = cupsFileOpen(newfile, "w")) == NULL)
-  {
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                   "[Job %d] Unable to create job control file \"%s\": %s",
-                   job->id, newfile, strerror(errno));
+  if ((fp = cupsdCreateConfFile(filename, ConfigFilePerm & 0600)) == NULL)
     return;
-  }
 
-  fchmod(cupsFileNumber(fp), 0600);
   fchown(cupsFileNumber(fp), RunUser, Group);
 
   job->attrs->state = IPP_IDLE;
@@ -2170,24 +2183,11 @@ cupsdSaveJob(cupsd_job_t *job)          /* I - Job */
     cupsdLogMessage(CUPSD_LOG_ERROR,
                     "[Job %d] Unable to write job control file.", job->id);
     cupsFileClose(fp);
-    unlink(newfile);
     return;
   }
 
-  if (cupsFileClose(fp))
-    cupsdLogMessage(CUPSD_LOG_ERROR,
-                   "[Job %d] Unable to close job control file: %s",
-                   job->id, strerror(errno));
-  else
-  {
-    unlink(filename);
-    if (rename(newfile, filename))
-      cupsdLogMessage(CUPSD_LOG_ERROR,
-                      "[Job %d] Unable to finalize job control file: %s",
-                     job->id, strerror(errno));
-    else
-      job->dirty = 0;
-  }
+  if (!cupsdCloseCreatedConfFile(fp, filename))
+    job->dirty = 0;
 }
 
 
@@ -2616,27 +2616,7 @@ cupsdSetJobState(
        */
 
        if (!JobHistory || !JobFiles || action == CUPSD_JOB_PURGE)
-       {
-         for (i = 1; i <= job->num_files; i ++)
-         {
-           snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
-                    job->id, i);
-           if (Classification)
-             cupsdRemoveFile(filename);
-           else
-             unlink(filename);
-         }
-
-         if (job->num_files > 0)
-         {
-           free(job->filetypes);
-           free(job->compressions);
-
-           job->num_files    = 0;
-           job->filetypes    = NULL;
-           job->compressions = NULL;
-         }
-       }
+         remove_job_files(job);
 
        if (JobHistory && action != CUPSD_JOB_PURGE)
        {
@@ -2727,6 +2707,62 @@ cupsdUnloadCompletedJobs(void)
 }
 
 
+/*
+ * 'cupsdUpdateJobs()' - Update the history/file files for all jobs.
+ */
+
+void
+cupsdUpdateJobs(void)
+{
+  cupsd_job_t          *job;           /* Current job */
+  time_t               curtime;        /* Current time */
+  ipp_attribute_t      *attr;          /* time-at-completed attribute */
+
+
+  curtime          = time(NULL);
+  JobHistoryUpdate = 0;
+
+  for (job = (cupsd_job_t *)cupsArrayFirst(Jobs);
+       job;
+       job = (cupsd_job_t *)cupsArrayNext(Jobs))
+  {
+    if (job->state_value >= IPP_JOB_CANCELED &&
+        (attr = ippFindAttribute(job->attrs, "time-at-completed",
+                                 IPP_TAG_INTEGER)) != NULL)
+    {
+     /*
+      * Update history/file expiration times...
+      */
+
+      if (JobHistory < INT_MAX)
+       job->history_time = attr->values[0].integer + JobHistory;
+      else
+       job->history_time = INT_MAX;
+
+      if (job->history_time < curtime)
+      {
+        cupsdDeleteJob(job, CUPSD_JOB_PURGE);
+        continue;
+      }
+
+      if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+       JobHistoryUpdate = job->history_time;
+
+      if (JobFiles < INT_MAX)
+       job->file_time = attr->values[0].integer + JobFiles;
+      else
+       job->file_time = INT_MAX;
+
+      if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
+       JobHistoryUpdate = job->file_time;
+    }
+  }
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdUpdateAllJobs: JobHistoryUpdate=%ld",
+                  (long)JobHistoryUpdate);
+}
+
+
 /*
  * 'compare_active_jobs()' - Compare the job IDs and priorities of two jobs.
  */
@@ -4220,6 +4256,67 @@ load_request_root(void)
 }
 
 
+/*
+ * 'remove_job_files()' - Remove the document files for a job.
+ */
+
+static void
+remove_job_files(cupsd_job_t *job)     /* I - Job */
+{
+  int  i;                              /* Looping var */
+  char filename[1024];                 /* Document filename */
+
+
+  if (job->num_files <= 0)
+    return;
+
+  for (i = 1; i <= job->num_files; i ++)
+  {
+    snprintf(filename, sizeof(filename), "%s/d%05d-%03d", RequestRoot,
+            job->id, i);
+    if (Classification)
+      cupsdRemoveFile(filename);
+    else
+      unlink(filename);
+  }
+
+  free(job->filetypes);
+  free(job->compressions);
+
+  job->file_time    = 0;
+  job->num_files    = 0;
+  job->filetypes    = NULL;
+  job->compressions = NULL;
+
+  LastEvent |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+}
+
+
+/*
+ * 'remove_job_history()' - Remove the control file for a job.
+ */
+
+static void
+remove_job_history(cupsd_job_t *job)   /* I - Job */
+{
+  char filename[1024];                 /* Control filename */
+
+
+ /*
+  * Remove the job info file...
+  */
+
+  snprintf(filename, sizeof(filename), "%s/c%05d", RequestRoot,
+          job->id);
+  if (Classification)
+    cupsdRemoveFile(filename);
+  else
+    unlink(filename);
+
+  LastEvent |= CUPSD_EVENT_PRINTER_STATE_CHANGED;
+}
+
+
 /*
  * 'set_time()' - Set one of the "time-at-xyz" attributes.
  */
@@ -4229,12 +4326,39 @@ set_time(cupsd_job_t *job,              /* I - Job to update */
          const char  *name)            /* I - Name of attribute */
 {
   ipp_attribute_t      *attr;          /* Time attribute */
+  time_t               curtime;        /* Current time */
+
 
+  curtime = time(NULL);
+
+  cupsdLogJob(job, CUPSD_LOG_DEBUG, "%s=%ld", name, (long)curtime);
 
   if ((attr = ippFindAttribute(job->attrs, name, IPP_TAG_ZERO)) != NULL)
   {
     attr->value_tag         = IPP_TAG_INTEGER;
-    attr->values[0].integer = time(NULL);
+    attr->values[0].integer = curtime;
+  }
+
+  if (!strcmp(name, "time-at-completed"))
+  {
+    if (JobHistory < INT_MAX)
+      job->history_time = attr->values[0].integer + JobHistory;
+    else
+      job->history_time = INT_MAX;
+
+    if (job->history_time < JobHistoryUpdate || !JobHistoryUpdate)
+      JobHistoryUpdate = job->history_time;
+
+    if (JobFiles < INT_MAX)
+      job->file_time = attr->values[0].integer + JobFiles;
+    else
+      job->file_time = INT_MAX;
+
+    if (job->file_time < JobHistoryUpdate || !JobHistoryUpdate)
+      JobHistoryUpdate = job->file_time;
+
+    cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_time: JobHistoryUpdate=%ld",
+                   (long)JobHistoryUpdate);
   }
 }
 
@@ -4289,6 +4413,8 @@ start_job(cupsd_job_t     *job,           /* I - Job ID */
 
   job->cost         = 0;
   job->current_file = 0;
+  job->file_time    = 0;
+  job->history_time = 0;
   job->progress     = 0;
   job->printer      = printer;
   printer->job      = job;
index b34f91e165b02513b9535ec262c2981c53930674..e0b3a763ee031a4f0a59382965583aac57e009cb 100644 (file)
@@ -47,8 +47,10 @@ struct cupsd_job_s                   /**** Job request ****/
   ipp_attribute_t      *sheets;        /* job-media-sheets-completed */
   time_t               access_time,    /* Last access time */
                        cancel_time,    /* When to cancel/send SIGTERM */
-                       kill_time,      /* When to send SIGKILL */
-                       hold_until;     /* Hold expiration date/time */
+                       file_time,      /* Job file retain time */
+                       history_time,   /* Job history retain time */
+                       hold_until,     /* Hold expiration date/time */
+                       kill_time;      /* When to send SIGKILL */
   ipp_attribute_t      *state;         /* Job state */
   ipp_attribute_t      *reasons;       /* Job state reasons */
   ipp_attribute_t      *job_sheets;    /* Job sheets (NULL if none) */
@@ -91,10 +93,12 @@ typedef struct cupsd_joblog_s               /**** Job log message ****/
  * Globals...
  */
 
-VAR int                        JobHistory      VALUE(1);
+VAR int                        JobHistory      VALUE(INT_MAX);
                                        /* Preserve job history? */
-VAR int                        JobFiles        VALUE(0);
+VAR int                        JobFiles        VALUE(86400);
                                        /* Preserve job files? */
+VAR time_t             JobHistoryUpdate VALUE(0);
+                                       /* Time for next job history update */
 VAR int                        MaxJobs         VALUE(0),
                                        /* Max number of jobs */
                        MaxActiveJobs   VALUE(0),
@@ -161,6 +165,7 @@ extern void         cupsdStopAllJobs(cupsd_jobaction_t action,
                                         int kill_delay);
 extern int             cupsdTimeoutJob(cupsd_job_t *job);
 extern void            cupsdUnloadCompletedJobs(void);
+extern void            cupsdUpdateJobs(void);
 
 
 /*
index e0de67e4b69fb9074dcfbb6f6caf36114513fa35..c61246509d84b811d17702bc19da01f3bc9f8058 100644 (file)
@@ -981,10 +981,16 @@ main(int  argc,                           /* I - Number of command-line args */
     if ((current_time - senddoc_time) >= 10)
     {
       cupsdCheckJobs();
-      cupsdCleanJobs();
       senddoc_time = current_time;
     }
 
+   /*
+    * Clean job history...
+    */
+
+    if (JobHistoryUpdate && current_time >= JobHistoryUpdate)
+      cupsdCleanJobs();
+
    /*
     * Log statistics at most once a minute when in debug mode...
     */
@@ -1773,6 +1779,9 @@ select_timeout(int fds)                   /* I - Number of descriptors returned */
 #endif /* HAVE_AVAHI */
 
 
+  cupsdLogMessage(CUPSD_LOG_DEBUG2, "select_timeout: JobHistoryUpdate=%ld",
+                 (long)JobHistoryUpdate);
+
  /*
   * Check to see if any of the clients have pending data to be
   * processed; if so, the timeout should be 0...
@@ -1865,29 +1874,38 @@ select_timeout(int fds)                 /* I - Number of descriptors returned */
   }
 
  /*
-  * Check for any active jobs...
+  * Check for any job activity...
   */
 
+  if (JobHistoryUpdate && timeout > JobHistoryUpdate)
+  {
+    timeout = JobHistoryUpdate;
+    why     = "update job history";
+  }
+
   for (job = (cupsd_job_t *)cupsArrayFirst(ActiveJobs);
        job;
        job = (cupsd_job_t *)cupsArrayNext(ActiveJobs))
   {
+    if (job->cancel_time && job->cancel_time < timeout)
+    {
+      timeout = job->cancel_time;
+      why     = "cancel stuck jobs";
+    }
+
     if (job->kill_time && job->kill_time < timeout)
     {
       timeout = job->kill_time;
       why     = "kill unresponsive jobs";
     }
-    else if (job->cancel_time && job->cancel_time < timeout)
-    {
-      timeout = job->cancel_time;
-      why     = "cancel stuck jobs";
-    }
-    else if (job->state_value == IPP_JOB_HELD && job->hold_until < timeout)
+
+    if (job->state_value == IPP_JOB_HELD && job->hold_until < timeout)
     {
       timeout = job->hold_until;
       why     = "release held jobs";
     }
-    else if (job->state_value == IPP_JOB_PENDING && timeout > (now + 10))
+
+    if (job->state_value == IPP_JOB_PENDING && timeout > (now + 10))
     {
       timeout = now + 10;
       why     = "start pending jobs";
index 9048ad599fb4806e187f7d997d280f9d31a8f313..87e660ce312b91a7084e8d0a5d3af1efdf7128bd 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Network interface functions for the CUPS scheduler.
  *
- *   Copyright 2007-2010 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -166,7 +166,7 @@ cupsdNetIFUpdate(void)
       */
 
       if (httpAddrLocalhost((http_addr_t *)(addr->ifa_addr)))
-        strcpy(hostname, "localhost");
+        strlcpy(hostname, "localhost", sizeof(hostname));
       else
        httpAddrString((http_addr_t *)(addr->ifa_addr), hostname,
                       sizeof(hostname));
@@ -186,7 +186,7 @@ cupsdNetIFUpdate(void)
 
     strlcpy(temp->name, addr->ifa_name, sizeof(temp->name));
     temp->hostlen = hostlen;
-    strcpy(temp->hostname, hostname);  /* Safe because hostname is allocated */
+    memcpy(temp->hostname, hostname, hostlen + 1);
 
     if (addr->ifa_addr->sa_family == AF_INET)
     {
index 293b64d31f56bd64f2eb4b4309dde47352b143c6..3189444166eed91cffa9cd6a1f6d7c1dbf052999 100644 (file)
@@ -640,8 +640,7 @@ cupsdCreateCommonData(void)
 
   /* operations-supported */
   ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
-                 "operations-supported",
-                 sizeof(ops) / sizeof(ops[0]) + JobFiles - 1, ops);
+                 "operations-supported", sizeof(ops) / sizeof(ops[0]), ops);
 
   /* orientation-requested-supported */
   ippAddIntegers(CommonData, IPP_TAG_PRINTER, IPP_TAG_ENUM,
diff --git a/scheduler/tls-darwin.c b/scheduler/tls-darwin.c
new file mode 100644 (file)
index 0000000..6d53d63
--- /dev/null
@@ -0,0 +1,560 @@
+/*
+ * "$Id$"
+ *
+ *   TLS support code for the CUPS scheduler on OS X.
+ *
+ *   Copyright 2007-2012 by Apple Inc.
+ *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ *
+ *   These coded instructions, statements, and computer programs are the
+ *   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/".
+ *
+ * Contents:
+ *
+ *   cupsdEndTLS()          - Shutdown a secure session with the client.
+ *   cupsdStartTLS()        - Start a secure session with the client.
+ *   copy_cdsa_certificate() - Copy a SSL/TLS certificate from the System
+ *                            keychain.
+ *   make_certificate()      - Make a self-signed SSL/TLS certificate.
+ */
+
+
+/*
+ * Local functions...
+ */
+
+static CFArrayRef      copy_cdsa_certificate(cupsd_client_t *con);
+static int             make_certificate(cupsd_client_t *con);
+
+
+/*
+ * 'cupsdEndTLS()' - Shutdown a secure session with the client.
+ */
+
+int                                    /* O - 1 on success, 0 on error */
+cupsdEndTLS(cupsd_client_t *con)       /* I - Client connection */
+{
+  while (SSLClose(con->http.tls) == errSSLWouldBlock)
+    usleep(1000);
+
+  SSLDisposeContext(con->http.tls);
+  con->http.tls = NULL;
+
+  if (con->http.tls_credentials)
+    CFRelease(con->http.tls_credentials);
+
+  return (1);
+}
+
+
+/*
+ * 'cupsdStartTLS()' - Start a secure session with the client.
+ */
+
+int                                    /* O - 1 on success, 0 on error */
+cupsdStartTLS(cupsd_client_t *con)     /* I - Client connection */
+{
+  OSStatus     error = 0;              /* Error code */
+  CFArrayRef   peerCerts;              /* Peer certificates */
+
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.",
+                  con->http.fd);
+
+  con->http.tls_credentials = copy_cdsa_certificate(con);
+
+  if (!con->http.tls_credentials)
+  {
+   /*
+    * No keychain (yet), make a self-signed certificate...
+    */
+
+    if (make_certificate(con))
+      con->http.tls_credentials = copy_cdsa_certificate(con);
+  }
+
+  if (!con->http.tls_credentials)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                   "Could not find signing key in keychain \"%s\"",
+                   ServerCertificate);
+    error = errSSLBadConfiguration;
+  }
+
+  if (!error)
+    error = SSLNewContext(true, &con->http.tls);
+
+  if (!error)
+    error = SSLSetIOFuncs(con->http.tls, _httpReadCDSA, _httpWriteCDSA);
+
+  if (!error)
+    error = SSLSetConnection(con->http.tls, HTTP(con));
+
+  if (!error)
+    error = SSLSetAllowsExpiredCerts(con->http.tls, true);
+
+  if (!error)
+    error = SSLSetAllowsAnyRoot(con->http.tls, true);
+
+  if (!error)
+    error = SSLSetCertificate(con->http.tls, con->http.tls_credentials);
+
+  if (!error)
+  {
+   /*
+    * Perform SSL/TLS handshake
+    */
+
+    while ((error = SSLHandshake(con->http.tls)) == errSSLWouldBlock)
+      usleep(1000);
+  }
+
+  if (error)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Unable to encrypt connection from %s - %s (%d)",
+                    con->http.hostname, cssmErrorString(error), (int)error);
+
+    con->http.error  = error;
+    con->http.status = HTTP_ERROR;
+
+    if (con->http.tls)
+    {
+      SSLDisposeContext(con->http.tls);
+      con->http.tls = NULL;
+    }
+
+    if (con->http.tls_credentials)
+    {
+      CFRelease(con->http.tls_credentials);
+      con->http.tls_credentials = NULL;
+    }
+
+    return (0);
+  }
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
+                  con->http.hostname);
+
+  if (!SSLCopyPeerCertificates(con->http.tls, &peerCerts) && peerCerts)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG, "Received %d peer certificates!",
+                   (int)CFArrayGetCount(peerCerts));
+    CFRelease(peerCerts);
+  }
+  else
+    cupsdLogMessage(CUPSD_LOG_DEBUG, "Received NO peer certificates!");
+
+  return (1);
+}
+
+
+/*
+ * 'copy_cdsa_certificate()' - Copy a SSL/TLS certificate from the System
+ *                             keychain.
+ */
+
+static CFArrayRef                              /* O - Array of certificates */
+copy_cdsa_certificate(
+    cupsd_client_t *con)                       /* I - Client connection */
+{
+  OSStatus             err;            /* Error info */
+  SecKeychainRef       keychain = NULL;/* Keychain reference */
+  SecIdentitySearchRef search = NULL;  /* Search reference */
+  SecIdentityRef       identity = NULL;/* Identity */
+  CFArrayRef           certificates = NULL;
+                                       /* Certificate array */
+#  if HAVE_SECPOLICYCREATESSL
+  SecPolicyRef         policy = NULL;  /* Policy ref */
+  CFStringRef          servername = NULL;
+                                       /* Server name */
+  CFMutableDictionaryRef query = NULL; /* Query qualifiers */
+  CFArrayRef           list = NULL;    /* Keychain list */
+  char                 localname[1024];/* Local hostname */
+#  elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
+  SecPolicyRef         policy = NULL;  /* Policy ref */
+  SecPolicySearchRef   policy_search = NULL;
+                                       /* Policy search ref */
+  CSSM_DATA            options;        /* Policy options */
+  CSSM_APPLE_TP_SSL_OPTIONS
+                       ssl_options;    /* SSL Option for hostname */
+  char                 localname[1024];/* Local hostname */
+#  endif /* HAVE_SECPOLICYCREATESSL */
+
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG,
+                  "copy_cdsa_certificate: Looking for certs for \"%s\"...",
+                 con->servername);
+
+  if ((err = SecKeychainOpen(ServerCertificate, &keychain)))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\" - %s (%d)",
+                   ServerCertificate, cssmErrorString(err), (int)err);
+    goto cleanup;
+  }
+
+#  if HAVE_SECPOLICYCREATESSL
+  servername = CFStringCreateWithCString(kCFAllocatorDefault, con->servername,
+                                        kCFStringEncodingUTF8);
+
+  policy = SecPolicyCreateSSL(1, servername);
+
+  if (servername)
+    CFRelease(servername);
+
+  if (!policy)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference");
+    goto cleanup;
+  }
+
+  if (!(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0,
+                                         &kCFTypeDictionaryKeyCallBacks,
+                                         &kCFTypeDictionaryValueCallBacks)))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create query dictionary");
+    goto cleanup;
+  }
+
+  list = CFArrayCreate(kCFAllocatorDefault, (const void **)&keychain, 1,
+                       &kCFTypeArrayCallBacks);
+
+  CFDictionaryAddValue(query, kSecClass, kSecClassIdentity);
+  CFDictionaryAddValue(query, kSecMatchPolicy, policy);
+  CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue);
+  CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne);
+  CFDictionaryAddValue(query, kSecMatchSearchList, list);
+
+  CFRelease(list);
+
+  err = SecItemCopyMatching(query, (CFTypeRef *)&identity);
+
+  if (err && DNSSDHostName)
+  {
+   /*
+    * Search for the connection server name failed; try the DNS-SD .local
+    * hostname instead...
+    */
+
+    snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
+
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+                   "copy_cdsa_certificate: Looking for certs for \"%s\"...",
+                   localname);
+
+    servername = CFStringCreateWithCString(kCFAllocatorDefault, localname,
+                                          kCFStringEncodingUTF8);
+
+    CFRelease(policy);
+
+    policy = SecPolicyCreateSSL(1, servername);
+
+    if (servername)
+      CFRelease(servername);
+
+    if (!policy)
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference");
+      goto cleanup;
+    }
+
+    CFDictionarySetValue(query, kSecMatchPolicy, policy);
+
+    err = SecItemCopyMatching(query, (CFTypeRef *)&identity);
+  }
+
+  if (err)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+                   "Cannot find signing key in keychain \"%s\": %s (%d)",
+                   ServerCertificate, cssmErrorString(err), (int)err);
+    goto cleanup;
+  }
+
+#  elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
+ /*
+  * Use a policy to search for valid certificates whose common name matches the
+  * servername...
+  */
+
+  if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL,
+                           NULL, &policy_search))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create a policy search reference");
+    goto cleanup;
+  }
+
+  if (SecPolicySearchCopyNext(policy_search, &policy))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                   "Cannot find a policy to use for searching");
+    goto cleanup;
+  }
+
+  memset(&ssl_options, 0, sizeof(ssl_options));
+  ssl_options.Version = CSSM_APPLE_TP_SSL_OPTS_VERSION;
+  ssl_options.ServerName = con->servername;
+  ssl_options.ServerNameLen = strlen(con->servername);
+
+  options.Data = (uint8 *)&ssl_options;
+  options.Length = sizeof(ssl_options);
+
+  if (SecPolicySetValue(policy, &options))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                   "Cannot set policy value to use for searching");
+    goto cleanup;
+  }
+
+  if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN,
+                                              keychain, FALSE, &search)))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                   "Cannot create identity search reference: %s (%d)",
+                   cssmErrorString(err), (int)err);
+    goto cleanup;
+  }
+
+  err = SecIdentitySearchCopyNext(search, &identity);
+
+  if (err && DNSSDHostName)
+  {
+   /*
+    * Search for the connection server name failed; try the DNS-SD .local
+    * hostname instead...
+    */
+
+    snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
+
+    ssl_options.ServerName    = localname;
+    ssl_options.ServerNameLen = strlen(localname);
+
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+                   "copy_cdsa_certificate: Looking for certs for \"%s\"...",
+                   localname);
+
+    if (SecPolicySetValue(policy, &options))
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "Cannot set policy value to use for searching");
+      goto cleanup;
+    }
+
+    CFRelease(search);
+    search = NULL;
+    if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN,
+                                              keychain, FALSE, &search)))
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "Cannot create identity search reference: %s (%d)",
+                     cssmErrorString(err), (int)err);
+      goto cleanup;
+    }
+
+    err = SecIdentitySearchCopyNext(search, &identity);
+
+  }
+
+  if (err)
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+                   "Cannot find signing key in keychain \"%s\": %s (%d)",
+                   ServerCertificate, cssmErrorString(err), (int)err);
+    goto cleanup;
+  }
+
+#  else
+ /*
+  * Assume there is exactly one SecIdentity in the keychain...
+  */
+
+  if ((err = SecIdentitySearchCreate(keychain, CSSM_KEYUSE_SIGN, &search)))
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+                   "Cannot create identity search reference (%d)", (int)err);
+    goto cleanup;
+  }
+
+  if ((err = SecIdentitySearchCopyNext(search, &identity)))
+  {
+    cupsdLogMessage(CUPSD_LOG_DEBUG,
+                   "Cannot find signing key in keychain \"%s\": %s (%d)",
+                   ServerCertificate, cssmErrorString(err), (int)err);
+    goto cleanup;
+  }
+#  endif /* HAVE_SECPOLICYCREATESSL */
+
+  if (CFGetTypeID(identity) != SecIdentityGetTypeID())
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure!");
+    goto cleanup;
+  }
+
+  if ((certificates = CFArrayCreate(NULL, (const void **)&identity,
+                                 1, &kCFTypeArrayCallBacks)) == NULL)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array");
+    goto cleanup;
+  }
+
+  cleanup :
+
+  if (keychain)
+    CFRelease(keychain);
+  if (search)
+    CFRelease(search);
+  if (identity)
+    CFRelease(identity);
+
+#  if HAVE_SECPOLICYCREATESSL
+  if (policy)
+    CFRelease(policy);
+  if (query)
+    CFRelease(query);
+#  elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
+  if (policy)
+    CFRelease(policy);
+  if (policy_search)
+    CFRelease(policy_search);
+#  endif /* HAVE_SECPOLICYCREATESSL */
+
+  return (certificates);
+}
+
+
+/*
+ * 'make_certificate()' - Make a self-signed SSL/TLS certificate.
+ */
+
+static int                             /* O - 1 on success, 0 on failure */
+make_certificate(cupsd_client_t *con)  /* I - Client connection */
+{
+  int          pid,                    /* Process ID of command */
+               status;                 /* Status of command */
+  char         command[1024],          /* Command */
+               *argv[4],               /* Command-line arguments */
+               *envp[MAX_ENV + 1],     /* Environment variables */
+               keychain[1024],         /* Keychain argument */
+               infofile[1024],         /* Type-in information for cert */
+               localname[1024],        /* Local hostname */
+               *servername;            /* Name of server in cert */
+  cups_file_t  *fp;                    /* Seed/info file */
+  int          infofd;                 /* Info file descriptor */
+
+
+  if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName)
+  {
+    snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName);
+    servername = localname;
+  }
+  else
+    servername = con->servername;
+
+ /*
+  * Run the "certtool" command to generate a self-signed certificate...
+  */
+
+  if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command)))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "No SSL certificate and certtool command not found!");
+    return (0);
+  }
+
+ /*
+  * Create a file with the certificate information fields...
+  *
+  * Note: This assumes that the default questions are asked by the certtool
+  * command...
+  */
+
+  if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Unable to create certificate information file %s - %s",
+                    infofile, strerror(errno));
+    return (0);
+  }
+
+  cupsFilePrintf(fp,
+                 "%s\n"                        /* Enter key and certificate label */
+                 "r\n"                 /* Generate RSA key pair */
+                 "2048\n"              /* Key size in bits */
+                 "y\n"                 /* OK (y = yes) */
+                 "b\n"                 /* Usage (b=signing/encryption) */
+                 "s\n"                 /* Sign with SHA1 */
+                 "y\n"                 /* OK (y = yes) */
+                 "%s\n"                        /* Common name */
+                 "\n"                  /* Country (default) */
+                 "\n"                  /* Organization (default) */
+                 "\n"                  /* Organizational unit (default) */
+                 "\n"                  /* State/Province (default) */
+                 "%s\n"                        /* Email address */
+                 "y\n",                        /* OK (y = yes) */
+                servername, servername, ServerAdmin);
+  cupsFileClose(fp);
+
+  cupsdLogMessage(CUPSD_LOG_INFO,
+                  "Generating SSL server key and certificate...");
+
+  snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate);
+
+  argv[0] = "certtool";
+  argv[1] = "c";
+  argv[2] = keychain;
+  argv[3] = NULL;
+
+  cupsdLoadEnv(envp, MAX_ENV);
+
+  infofd = open(infofile, O_RDONLY);
+
+  if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL,
+                         NULL, &pid))
+  {
+    close(infofd);
+    unlink(infofile);
+    return (0);
+  }
+
+  close(infofd);
+  unlink(infofile);
+
+  while (waitpid(pid, &status, 0) < 0)
+    if (errno != EINTR)
+    {
+      status = 1;
+      break;
+    }
+
+  cupsdFinishProcess(pid, command, sizeof(command), NULL);
+
+  if (status)
+  {
+    if (WIFEXITED(status))
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                      "Unable to create SSL server key and certificate - "
+                     "the certtool command stopped with status %d!",
+                     WEXITSTATUS(status));
+    else
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                      "Unable to create SSL server key and certificate - "
+                     "the certtool command crashed on signal %d!",
+                     WTERMSIG(status));
+  }
+  else
+  {
+    cupsdLogMessage(CUPSD_LOG_INFO,
+                    "Created SSL server certificate file \"%s\"...",
+                   ServerCertificate);
+  }
+
+  return (!status);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/tls-gnutls.c b/scheduler/tls-gnutls.c
new file mode 100644 (file)
index 0000000..36518cd
--- /dev/null
@@ -0,0 +1,292 @@
+/*
+ * "$Id$"
+ *
+ *   TLS support code for the CUPS scheduler using GNU TLS.
+ *
+ *   Copyright 2007-2012 by Apple Inc.
+ *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ *
+ *   These coded instructions, statements, and computer programs are the
+ *   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/".
+ *
+ * Contents:
+ *
+ *   cupsdEndTLS()     - Shutdown a secure session with the client.
+ *   cupsdStartTLS()   - Start a secure session with the client.
+ *   make_certificate() - Make a self-signed SSL/TLS certificate.
+ */
+
+
+/*
+ * Local functions...
+ */
+
+static int             make_certificate(cupsd_client_t *con);
+
+
+/*
+ * 'cupsdEndTLS()' - Shutdown a secure session with the client.
+ */
+
+int                                    /* O - 1 on success, 0 on error */
+cupsdEndTLS(cupsd_client_t *con)       /* I - Client connection */
+{
+  int          error;                  /* Error code */
+  gnutls_certificate_server_credentials *credentials;
+                                       /* TLS credentials */
+
+
+  credentials = (gnutls_certificate_server_credentials *)
+                    (con->http.tls_credentials);
+
+  error = gnutls_bye(con->http.tls, GNUTLS_SHUT_WR);
+  switch (error)
+  {
+    case GNUTLS_E_SUCCESS:
+      cupsdLogMessage(CUPSD_LOG_DEBUG,
+                     "SSL shutdown successful!");
+      break;
+    default:
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                     "SSL shutdown failed: %s", gnutls_strerror(error));
+      break;
+  }
+
+  gnutls_deinit(con->http.tls);
+  con->http.tls = NULL;
+
+  gnutls_certificate_free_credentials(*credentials);
+  free(credentials);
+
+  return (1);
+}
+
+
+/*
+ * 'cupsdStartTLS()' - Start a secure session with the client.
+ */
+
+int                                    /* O - 1 on success, 0 on error */
+cupsdStartTLS(cupsd_client_t *con)     /* I - Client connection */
+{
+  int          status;                 /* Error code */
+  gnutls_certificate_server_credentials *credentials;
+                                       /* TLS credentials */
+
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.",
+                  con->http.fd);
+
+ /*
+  * Verify that we have a certificate...
+  */
+
+  if (access(ServerKey, 0) || access(ServerCertificate, 0))
+  {
+   /*
+    * Nope, make a self-signed certificate...
+    */
+
+    if (!make_certificate(con))
+      return (0);
+  }
+
+ /*
+  * Create the SSL object and perform the SSL handshake...
+  */
+
+  credentials = (gnutls_certificate_server_credentials *)
+                    malloc(sizeof(gnutls_certificate_server_credentials));
+  if (credentials == NULL)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Unable to encrypt connection from %s - %s",
+                    con->http.hostname, strerror(errno));
+
+    return (0);
+  }
+
+  gnutls_certificate_allocate_credentials(credentials);
+  gnutls_certificate_set_x509_key_file(*credentials, ServerCertificate,
+                                      ServerKey, GNUTLS_X509_FMT_PEM);
+
+  gnutls_init(&con->http.tls, GNUTLS_SERVER);
+  gnutls_set_default_priority(con->http.tls);
+
+  gnutls_credentials_set(con->http.tls, GNUTLS_CRD_CERTIFICATE, *credentials);
+  gnutls_transport_set_ptr(con->http.tls, (gnutls_transport_ptr)HTTP(con));
+  gnutls_transport_set_pull_function(con->http.tls, _httpReadGNUTLS);
+  gnutls_transport_set_push_function(con->http.tls, _httpWriteGNUTLS);
+
+  while ((status = gnutls_handshake(con->http.tls)) != GNUTLS_E_SUCCESS)
+  {
+    if (gnutls_error_is_fatal(status))
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                      "Unable to encrypt connection from %s - %s",
+                      con->http.hostname, gnutls_strerror(status));
+
+      gnutls_deinit(con->http.tls);
+      gnutls_certificate_free_credentials(*credentials);
+      con->http.tls = NULL;
+      free(credentials);
+      return (0);
+    }
+  }
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
+                  con->http.hostname);
+
+  con->http.tls_credentials = credentials;
+  return (1);
+}
+
+
+/*
+ * 'make_certificate()' - Make a self-signed SSL/TLS certificate.
+ */
+
+static int                             /* O - 1 on success, 0 on failure */
+make_certificate(cupsd_client_t *con)  /* I - Client connection */
+{
+  gnutls_x509_crt      crt;            /* Self-signed certificate */
+  gnutls_x509_privkey  key;            /* Encryption key */
+  cups_lang_t          *language;      /* Default language info */
+  cups_file_t          *fp;            /* Key/cert file */
+  unsigned char                buffer[8192];   /* Buffer for x509 data */
+  size_t               bytes;          /* Number of bytes of data */
+  unsigned char                serial[4];      /* Serial number buffer */
+  time_t               curtime;        /* Current time */
+  int                  result;         /* Result of GNU TLS calls */
+
+
+ /*
+  * Create the encryption key...
+  */
+
+  cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key...");
+
+  gnutls_x509_privkey_init(&key);
+  gnutls_x509_privkey_generate(key, GNUTLS_PK_RSA, 2048, 0);
+
+ /*
+  * Save it...
+  */
+
+  bytes = sizeof(buffer);
+
+  if ((result = gnutls_x509_privkey_export(key, GNUTLS_X509_FMT_PEM,
+                                           buffer, &bytes)) < 0)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to export SSL server key - %s",
+                    gnutls_strerror(result));
+    gnutls_x509_privkey_deinit(key);
+    return (0);
+  }
+  else if ((fp = cupsFileOpen(ServerKey, "w")) != NULL)
+  {
+    cupsFileWrite(fp, (char *)buffer, bytes);
+    cupsFileClose(fp);
+
+    cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...",
+                   ServerKey);
+  }
+  else
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Unable to create SSL server key file \"%s\" - %s",
+                   ServerKey, strerror(errno));
+    gnutls_x509_privkey_deinit(key);
+    return (0);
+  }
+
+ /*
+  * Create the self-signed certificate...
+  */
+
+  cupsdLogMessage(CUPSD_LOG_INFO, "Generating self-signed SSL certificate...");
+
+  language  = cupsLangDefault();
+  curtime   = time(NULL);
+  serial[0] = curtime >> 24;
+  serial[1] = curtime >> 16;
+  serial[2] = curtime >> 8;
+  serial[3] = curtime;
+
+  gnutls_x509_crt_init(&crt);
+  if (strlen(language->language) == 5)
+    gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
+                                  language->language + 3, 2);
+  else
+    gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COUNTRY_NAME, 0,
+                                  "US", 2);
+  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_COMMON_NAME, 0,
+                                ServerName, strlen(ServerName));
+  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATION_NAME, 0,
+                                ServerName, strlen(ServerName));
+  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_ORGANIZATIONAL_UNIT_NAME,
+                                0, "Unknown", 7);
+  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_STATE_OR_PROVINCE_NAME, 0,
+                                "Unknown", 7);
+  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_X520_LOCALITY_NAME, 0,
+                                "Unknown", 7);
+  gnutls_x509_crt_set_dn_by_oid(crt, GNUTLS_OID_PKCS9_EMAIL, 0,
+                                ServerAdmin, strlen(ServerAdmin));
+  gnutls_x509_crt_set_key(crt, key);
+  gnutls_x509_crt_set_serial(crt, serial, sizeof(serial));
+  gnutls_x509_crt_set_activation_time(crt, curtime);
+  gnutls_x509_crt_set_expiration_time(crt, curtime + 10 * 365 * 86400);
+  gnutls_x509_crt_set_ca_status(crt, 0);
+  gnutls_x509_crt_set_subject_alternative_name(crt, GNUTLS_SAN_DNSNAME,
+                                               ServerName);
+  gnutls_x509_crt_set_key_purpose_oid(crt, GNUTLS_KP_TLS_WWW_SERVER, 0);
+  gnutls_x509_crt_set_key_usage(crt, GNUTLS_KEY_KEY_ENCIPHERMENT);
+  gnutls_x509_crt_set_version(crt, 3);
+
+  bytes = sizeof(buffer);
+  if (gnutls_x509_crt_get_key_id(crt, 0, buffer, &bytes) >= 0)
+    gnutls_x509_crt_set_subject_key_id(crt, buffer, bytes);
+
+  gnutls_x509_crt_sign(crt, crt, key);
+
+ /*
+  * Save it...
+  */
+
+  bytes = sizeof(buffer);
+  if ((result = gnutls_x509_crt_export(crt, GNUTLS_X509_FMT_PEM,
+                                       buffer, &bytes)) < 0)
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Unable to export SSL server certificate - %s",
+                   gnutls_strerror(result));
+  else if ((fp = cupsFileOpen(ServerCertificate, "w")) != NULL)
+  {
+    cupsFileWrite(fp, (char *)buffer, bytes);
+    cupsFileClose(fp);
+
+    cupsdLogMessage(CUPSD_LOG_INFO,
+                    "Created SSL server certificate file \"%s\"...",
+                   ServerCertificate);
+  }
+  else
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Unable to create SSL server certificate file \"%s\" - %s",
+                   ServerCertificate, strerror(errno));
+
+ /*
+  * Cleanup...
+  */
+
+  gnutls_x509_crt_deinit(crt);
+  gnutls_x509_privkey_deinit(key);
+
+  return (1);
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/tls-openssl.c b/scheduler/tls-openssl.c
new file mode 100644 (file)
index 0000000..94c9e71
--- /dev/null
@@ -0,0 +1,353 @@
+/*
+ * "$Id$"
+ *
+ *   TLS support code for the CUPS scheduler using OpenSSL.
+ *
+ *   Copyright 2007-2012 by Apple Inc.
+ *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
+ *
+ *   These coded instructions, statements, and computer programs are the
+ *   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/".
+ *
+ * Contents:
+ *
+ *   cupsdEndTLS()     - Shutdown a secure session with the client.
+ *   cupsdStartTLS()   - Start a secure session with the client.
+ *   make_certificate() - Make a self-signed SSL/TLS certificate.
+ */
+
+
+/*
+ * Local functions...
+ */
+
+static int             make_certificate(cupsd_client_t *con);
+
+
+/*
+ * 'cupsdEndTLS()' - Shutdown a secure session with the client.
+ */
+
+int                                    /* O - 1 on success, 0 on error */
+cupsdEndTLS(cupsd_client_t *con)       /* I - Client connection */
+{
+  SSL_CTX      *context;               /* Context for encryption */
+  unsigned long        error;                  /* Error code */
+  int          status;                 /* Return status */
+
+
+  context = SSL_get_SSL_CTX(con->http.tls);
+
+  switch (SSL_shutdown(con->http.tls))
+  {
+    case 1 :
+       cupsdLogMessage(CUPSD_LOG_DEBUG,
+                       "SSL shutdown successful!");
+       status = 1;
+       break;
+
+    case -1 :
+       cupsdLogMessage(CUPSD_LOG_ERROR,
+                       "Fatal error during SSL shutdown!");
+
+    default :
+       while ((error = ERR_get_error()) != 0)
+         cupsdLogMessage(CUPSD_LOG_ERROR, "SSL shutdown failed: %s",
+                         ERR_error_string(error, NULL));
+       status = 0;
+       break;
+  }
+
+  SSL_CTX_free(context);
+  SSL_free(con->http.tls);
+  con->http.tls = NULL;
+
+  return (status);
+}
+
+
+/*
+ * 'cupsdStartTLS()' - Start a secure session with the client.
+ */
+
+int                                    /* O - 1 on success, 0 on error */
+cupsdStartTLS(cupsd_client_t *con)     /* I - Client connection */
+{
+  SSL_CTX      *context;               /* Context for encryption */
+  BIO          *bio;                   /* BIO data */
+  unsigned long        error;                  /* Error code */
+
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "[Client %d] Encrypting connection.",
+                  con->http.fd);
+
+ /*
+  * Verify that we have a certificate...
+  */
+
+  if (access(ServerKey, 0) || access(ServerCertificate, 0))
+  {
+   /*
+    * Nope, make a self-signed certificate...
+    */
+
+    if (!make_certificate(con))
+      return (0);
+  }
+
+ /*
+  * Create the SSL context and accept the connection...
+  */
+
+  context = SSL_CTX_new(SSLv23_server_method());
+
+  SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
+  if (SSLOptions & CUPSD_SSL_NOEMPTY)
+    SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
+  SSL_CTX_use_PrivateKey_file(context, ServerKey, SSL_FILETYPE_PEM);
+  SSL_CTX_use_certificate_chain_file(context, ServerCertificate);
+
+  bio = BIO_new(_httpBIOMethods());
+  BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)HTTP(con));
+
+  con->http.tls = SSL_new(context);
+  SSL_set_bio(con->http.tls, bio, bio);
+
+  if (SSL_accept(con->http.tls) != 1)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to encrypt connection from %s.",
+                    con->http.hostname);
+
+    while ((error = ERR_get_error()) != 0)
+      cupsdLogMessage(CUPSD_LOG_ERROR, "%s", ERR_error_string(error, NULL));
+
+    SSL_CTX_free(context);
+    SSL_free(con->http.tls);
+    con->http.tls = NULL;
+    return (0);
+  }
+
+  cupsdLogMessage(CUPSD_LOG_DEBUG, "Connection from %s now encrypted.",
+                  con->http.hostname);
+
+  return (1);
+}
+
+
+/*
+ * 'make_certificate()' - Make a self-signed SSL/TLS certificate.
+ */
+
+static int                             /* O - 1 on success, 0 on failure */
+make_certificate(cupsd_client_t *con)  /* I - Client connection */
+{
+#ifdef HAVE_WAITPID
+  int          pid,                    /* Process ID of command */
+               status;                 /* Status of command */
+  char         command[1024],          /* Command */
+               *argv[12],              /* Command-line arguments */
+               *envp[MAX_ENV + 1],     /* Environment variables */
+               infofile[1024],         /* Type-in information for cert */
+               seedfile[1024];         /* Random number seed file */
+  int          envc,                   /* Number of environment variables */
+               bytes;                  /* Bytes written */
+  cups_file_t  *fp;                    /* Seed/info file */
+  int          infofd;                 /* Info file descriptor */
+
+
+ /*
+  * Run the "openssl" command to seed the random number generator and
+  * generate a self-signed certificate that is good for 10 years:
+  *
+  *     openssl rand -rand seedfile 1
+  *
+  *     openssl req -new -x509 -keyout ServerKey \
+  *             -out ServerCertificate -days 3650 -nodes
+  *
+  * The seeding step is crucial in ensuring that the openssl command
+  * does not block on systems without sufficient entropy...
+  */
+
+  if (!cupsFileFind("openssl", getenv("PATH"), 1, command, sizeof(command)))
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "No SSL certificate and openssl command not found!");
+    return (0);
+  }
+
+  if (access("/dev/urandom", 0))
+  {
+   /*
+    * If the system doesn't provide /dev/urandom, then any random source
+    * will probably be blocking-style, so generate some random data to
+    * use as a seed for the certificate.  Note that we have already
+    * seeded the random number generator in cupsdInitCerts()...
+    */
+
+    cupsdLogMessage(CUPSD_LOG_INFO,
+                    "Seeding the random number generator...");
+
+   /*
+    * Write the seed file...
+    */
+
+    if ((fp = cupsTempFile2(seedfile, sizeof(seedfile))) == NULL)
+    {
+      cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create seed file %s - %s",
+                      seedfile, strerror(errno));
+      return (0);
+    }
+
+    for (bytes = 0; bytes < 262144; bytes ++)
+      cupsFilePutChar(fp, CUPS_RAND());
+
+    cupsFileClose(fp);
+
+   /*
+    * Run the openssl command to seed its random number generator...
+    */
+
+    argv[0] = "openssl";
+    argv[1] = "rand";
+    argv[2] = "-rand";
+    argv[3] = seedfile;
+    argv[4] = "1";
+    argv[5] = NULL;
+
+    envc = cupsdLoadEnv(envp, MAX_ENV);
+    envp[envc] = NULL;
+
+    if (!cupsdStartProcess(command, argv, envp, -1, -1, -1, -1, -1, 1, NULL,
+                           NULL, &pid))
+    {
+      unlink(seedfile);
+      return (0);
+    }
+
+    while (waitpid(pid, &status, 0) < 0)
+      if (errno != EINTR)
+      {
+       status = 1;
+       break;
+      }
+
+    cupsdFinishProcess(pid, command, sizeof(command), NULL);
+
+   /*
+    * Remove the seed file, as it is no longer needed...
+    */
+
+    unlink(seedfile);
+
+    if (status)
+    {
+      if (WIFEXITED(status))
+       cupsdLogMessage(CUPSD_LOG_ERROR,
+                       "Unable to seed random number generator - "
+                       "the openssl command stopped with status %d!",
+                       WEXITSTATUS(status));
+      else
+       cupsdLogMessage(CUPSD_LOG_ERROR,
+                       "Unable to seed random number generator - "
+                       "the openssl command crashed on signal %d!",
+                       WTERMSIG(status));
+
+      return (0);
+    }
+  }
+
+ /*
+  * Create a file with the certificate information fields...
+  *
+  * Note: This assumes that the default questions are asked by the openssl
+  * command...
+  */
+
+  if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL)
+  {
+    cupsdLogMessage(CUPSD_LOG_ERROR,
+                    "Unable to create certificate information file %s - %s",
+                    infofile, strerror(errno));
+    return (0);
+  }
+
+  cupsFilePrintf(fp, ".\n.\n.\n%s\n.\n%s\n%s\n",
+                 ServerName, ServerName, ServerAdmin);
+  cupsFileClose(fp);
+
+  cupsdLogMessage(CUPSD_LOG_INFO,
+                  "Generating SSL server key and certificate...");
+
+  argv[0]  = "openssl";
+  argv[1]  = "req";
+  argv[2]  = "-new";
+  argv[3]  = "-x509";
+  argv[4]  = "-keyout";
+  argv[5]  = ServerKey;
+  argv[6]  = "-out";
+  argv[7]  = ServerCertificate;
+  argv[8]  = "-days";
+  argv[9]  = "3650";
+  argv[10] = "-nodes";
+  argv[11] = NULL;
+
+  cupsdLoadEnv(envp, MAX_ENV);
+
+  infofd = open(infofile, O_RDONLY);
+
+  if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL,
+                         NULL, &pid))
+  {
+    close(infofd);
+    unlink(infofile);
+    return (0);
+  }
+
+  close(infofd);
+  unlink(infofile);
+
+  while (waitpid(pid, &status, 0) < 0)
+    if (errno != EINTR)
+    {
+      status = 1;
+      break;
+    }
+
+  cupsdFinishProcess(pid, command, sizeof(command), NULL);
+
+  if (status)
+  {
+    if (WIFEXITED(status))
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                      "Unable to create SSL server key and certificate - "
+                     "the openssl command stopped with status %d!",
+                     WEXITSTATUS(status));
+    else
+      cupsdLogMessage(CUPSD_LOG_ERROR,
+                      "Unable to create SSL server key and certificate - "
+                     "the openssl command crashed on signal %d!",
+                     WTERMSIG(status));
+  }
+  else
+  {
+    cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server key file \"%s\"...",
+                   ServerKey);
+    cupsdLogMessage(CUPSD_LOG_INFO,
+                    "Created SSL server certificate file \"%s\"...",
+                   ServerCertificate);
+  }
+
+  return (!status);
+
+#else
+  return (0);
+#endif /* HAVE_WAITPID */
+}
+
+
+/*
+ * End of "$Id$".
+ */
diff --git a/scheduler/tls.c b/scheduler/tls.c
new file mode 100644 (file)
index 0000000..40d939a
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * "$Id$"
+ *
+ *   TLS support code for the CUPS scheduler.
+ *
+ *   Copyright 2012 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/".
+ */
+
+#include "cupsd.h"
+
+#ifdef HAVE_SSL
+#  ifdef HAVE_CDSASSL
+#    include "tls-darwin.c"
+#  elif defined(HAVE_GNUTLS)
+#    include "tls-gnutls.c"
+#  elif defined(HAVE_LIBSSL)
+#    include "tls-openssl.c"
+#  endif /* HAVE_CDSASSL */
+#endif /* HAVE_SSL */
+
+
+/*
+ * End of "$Id$".
+ */
index d08189a584c9ffcd8d9239c71cbe61f166466eaf..b96f97cabb9ec243dcfd2a67292bc798513acf08 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   PPD test program for CUPS.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -147,6 +147,7 @@ main(int  argc,                             /* I - Number of command-line args */
   int          len;                    /* Length of option name */
   char         *opt;                   /* Option character */
   const char   *ptr;                   /* Pointer into string */
+  cups_file_t  *fp;                    /* PPD file */
   int          files;                  /* Number of files */
   int          verbose;                /* Want verbose output? */
   int          warn;                   /* Which errors to just warn about */
@@ -303,7 +304,7 @@ main(int  argc,                             /* I - Number of command-line args */
         * Read from stdin...
        */
 
-        ppd = ppdOpen(stdin);
+        ppd = _ppdOpen(cupsFileStdin(), _PPD_LOCALIZATION_ALL);
 
         if (verbose >= 0)
           printf("%s:", (ppd && ppd->pcfilename) ? ppd->pcfilename : "(stdin)");
@@ -317,7 +318,24 @@ main(int  argc,                            /* I - Number of command-line args */
         if (verbose >= 0)
           printf("%s:", argv[i]);
 
-        ppd = ppdOpenFile(argv[i]);
+        if ((fp = cupsFileOpen(argv[i], "r")) != NULL)
+        {
+          ppd = _ppdOpen(fp, _PPD_LOCALIZATION_ALL);
+          cupsFileClose(fp);
+        }
+        else
+        {
+         status = ERROR_FILE_OPEN;
+
+         if (verbose >= 0)
+          {
+            _cupsLangPuts(stdout, _(" FAIL"));
+            _cupsLangPrintf(stdout,
+                           _("      **FAIL**  Unable to open PPD file - %s"),
+                           strerror(errno));
+           continue;
+          }
+        }
       }
 
       if (ppd == NULL)
@@ -1067,7 +1085,7 @@ main(int  argc,                           /* I - Number of command-line args */
          * Check for PaperDimension...
          */
 
-          if (size->width == 0.0 && size->length == 0.0)
+          if (size->width <= 0.0 && size->length <= 0.0)
          {
            if (verbose >= 0)
            {
@@ -3120,8 +3138,9 @@ check_sizes(ppd_file_t *ppd,              /* I - PPD file */
 
       continue;
     }
-    else if (warn != 2 && size->name[0] == 'w' &&
-             sscanf(size->name, "w%dh%d", &width, &length) == 2)
+
+    if (warn != 2 && size->name[0] == 'w' &&
+        sscanf(size->name, "w%dh%d", &width, &length) == 2)
     {
      /*
       * Validate device-specific size wNNNhNNN should have proper width and
@@ -3262,7 +3281,8 @@ check_sizes(ppd_file_t *ppd,              /* I - PPD file */
          * Check for EnvSizeName as well...
          */
 
-         snprintf(buf, sizeof(buf), "Env%s", pwg_media->ppd);
+          if (strncmp(pwg_media->ppd, "Env", 3))
+            snprintf(buf, sizeof(buf), "Env%s", pwg_media->ppd);
 
          if (strcmp(size->name, buf))
            is_ok = 0;
index c76eb9c5eba5b0c68f7a1bc25926845929dd07bc..ee6b5af9daeb6fd6896a29d26270c11b07c477e8 100644 (file)
 <INPUT TYPE="CHECKBOX" NAME="REMOTE_ADMIN" {?remote_admin}> Allow remote administration<BR>
 {have_gssapi?<INPUT TYPE="CHECKBOX" NAME="KERBEROS" {?kerberos}> Use Kerberos authentication (<A HREF="/help/kerberos.html?TOPIC=Getting+Started">FAQ</A>)<BR>:}
 <INPUT TYPE="CHECKBOX" NAME="USER_CANCEL_ANY" {?user_cancel_any}> Allow users to cancel any job (not just their own)<BR>
-<INPUT TYPE="CHECKBOX" NAME="PRESERVE_JOB_HISTORY" {?preserve_job_history}> Preserve job history<BR>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Number of jobs\:
+<INPUT TYPE="CHECKBOX" NAME="PRESERVE_JOBS" {?preserve_jobs}> Preserve job history<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Maximum jobs (0 for no limit)\:
 <INPUT TYPE="TEXT" NAME="MAX_JOBS" VALUE="{?max_jobs}" SIZE="6"><BR>
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<INPUT TYPE="CHECKBOX" NAME="PRESERVE_JOB_FILES" {?preserve_job_files}> Preserve job print files<BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Retain Metadata\:
+<INPUT TYPE="TEXT" NAME="PRESERVE_JOB_HISTORY" VALUE="{?preserve_job_history}" SIZE="6"><BR>
+&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Retain Documents\:
+<INPUT TYPE="TEXT" NAME="PRESERVE_JOB_FILES" VALUE="{?preserve_job_files}" SIZE="6"><BR>
 <INPUT TYPE="CHECKBOX" NAME="DEBUG_LOGGING" {?debug_logging}> Save debugging information for troubleshooting<BR>
 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Max log file size\:
 <INPUT TYPE="TEXT" NAME="MAX_LOG_SIZE" VALUE="{?max_log_size}" SIZE="6"></P>
index 17afce7388d3602e191897cd9087dba84403b8da..09741b54f496b6bc7093676eb856da4a666c669d 100644 (file)
@@ -43,7 +43,7 @@ online help information.</P>
 <P>If you are new to CUPS, read the "<a
 href="/help/overview.html">Overview of CUPS</a>" page. Veteran users
 should read the "<a href="/help/whatsnew.html">What's New in CUPS
-1.4</a>" page.</P>
+1.6</a>" page.</P>
 
 <P>The <A HREF="http://www.cups.org/">CUPS home page</A> also
 provides many resources including user discussion forums, answers
index 625059f621cb2faba38a5e123fdf5ad98e840e06..142fbb243fe762157c177e7bc80d7e856913d4e1 100644 (file)
@@ -6,7 +6,7 @@
 <TBODY>
 {[job_id]
 <TR VALIGN="TOP">
-<TD><A HREF="{job_printer_uri}">{job_printer_name}</A>-{job_id}&nbsp;</TD>
+<TD><A HREF="{job_printer_uri}">{job_printer_name}</A>-{job_id}{?phone? ({phone})}&nbsp;</TD>
 <TD>{?job_name=?Unknown:{job_name}}&nbsp;</TD>
 <TD>{?job_originating_user_name=?Withheld:{job_originating_user_name}}&nbsp;</TD>
 <TD>{job_k_octets}k&nbsp;</TD>
index 100d9f7adc0fc786b0a3b3a0c3d3926848bd49e9..123a19722bdd525a700d9dcc69b7bf862a7447d2 100644 (file)
@@ -1,7 +1,7 @@
 </TD></TR>
 <TR><TD>&nbsp;</TD></TR>
 <TR><TD CLASS="trailer">CUPS and the CUPS logo are trademarks of
-<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007-2011 Apple
+<A HREF="http://www.apple.com">Apple Inc.</A> CUPS is copyright 2007-2012 Apple
 Inc. All rights reserved.</TD></TR>
 </TABLE>
 </BODY>
index abe03863004bbd0781a36c3424dfdd17ecd80d57..cd6f5f2d5436395a4bad30907c29901fe47e9f32 100644 (file)
@@ -20,20 +20,13 @@ include ../Makedefs
 # Sample test files.
 #
 
-TESTFILES      =       \
+DATAFILES      =       \
                        color.jpg \
-                       create-printer-subscription.test \
                        document-a4.pdf \
                        document-a4.ps \
                        document-letter.pdf \
                        document-letter.ps \
-                       get-completed-jobs.test \
-                       get-jobs.test \
                        gray.jpg \
-                       ipp-1.1.test \
-                       ipp-2.0.test \
-                       ipp-2.1.test \
-                       ipp-2.2.test \
                        onepage-a4.pdf \
                        onepage-a4.ps \
                        onepage-letter.pdf \
@@ -42,6 +35,15 @@ TESTFILES    =       \
                        testfile.pdf \
                        testfile.ps \
                        testfile.txt
+TESTFILES      =       \
+                       create-printer-subscription.test \
+                       get-completed-jobs.test \
+                       get-jobs.test \
+                       get-printer-attributes.test \
+                       ipp-1.1.test \
+                       ipp-2.0.test \
+                       ipp-2.1.test \
+                       ipp-2.2.test
 OBJS           =       \
                        ippserver.o \
                        ipptool.o \
@@ -103,6 +105,9 @@ install:    all install-data install-headers install-libs install-exec
 install-data:
        echo Installing sample ipptool files in $(DATADIR)/ipptool...
        $(INSTALL_DIR) -m 755 $(DATADIR)/ipptool
+       for file in $(DATAFILES); do \
+               $(INSTALL_COMPDATA) $$file $(DATADIR)/ipptool; \
+       done
        for file in $(TESTFILES); do \
                $(INSTALL_DATA) $$file $(DATADIR)/ipptool; \
        done
@@ -141,6 +146,14 @@ install-libs:
 #
 
 uninstall:
+       echo Uninstalling sample ipptool files from $(DATADIR)/ipptool...
+       for file in $(DATAFILES); do \
+               $(RM) $(DATADIR)/ipptool/$$file; \
+       done
+       for file in $(TESTFILES); do \
+               $(RM) $(DATADIR)/ipptool/$$file; \
+       done
+       -$(RMDIR) $(DATADIR)/ipptool
 
 
 #
index 95ff1f5a6a9f30ba74c8cbcdbfa7c33b184f5c97..11abf0aa0f3326a4e83980be40188359b4c17a51 100644 (file)
@@ -95,7 +95,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        ATTR uri printer-uri $uri
 
        STATUS successful-ok
-       EXPECT printer-uri-supported OF-TYPE uri WITH-VALUE "$IPP_URI_SCHEME"
+       EXPECT printer-uri-supported OF-TYPE uri WITH-ALL-VALUES "$IPP_URI_SCHEME"
 }
 
 
@@ -325,7 +325,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
        EXPECT printer-state OF-TYPE enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5
        EXPECT printer-state-reasons OF-TYPE keyword IN-GROUP printer-attributes-tag
        EXPECT printer-up-time OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE >0
-       EXPECT printer-uri-supported OF-TYPE uri IN-GROUP printer-attributes-tag SAME-COUNT-AS uri-security-supported WITH-VALUE "$IPP_URI_SCHEME"
+       EXPECT printer-uri-supported OF-TYPE uri IN-GROUP printer-attributes-tag SAME-COUNT-AS uri-security-supported WITH-ALL-VALUES "$IPP_URI_SCHEME"
        EXPECT queued-job-count OF-TYPE integer IN-GROUP printer-attributes-tag COUNT 1
        EXPECT uri-authentication-supported OF-TYPE keyword IN-GROUP printer-attributes-tag
        EXPECT uri-security-supported OF-TYPE keyword IN-GROUP printer-attributes-tag SAME-COUNT-AS uri-authentication-supported
@@ -348,7 +348,7 @@ DEFINE IPP_URI_SCHEME "/^ipps?://.+$$/"
 
        STATUS successful-ok
 
-       EXPECT printer-uri-supported OF-TYPE uri IN-GROUP printer-attributes-tag WITH-VALUE "$IPP_URI_SCHEME"
+       EXPECT printer-uri-supported OF-TYPE uri IN-GROUP printer-attributes-tag WITH-ALL-VALUES "$IPP_URI_SCHEME"
        EXPECT !printer-name
 }
 
index 3800d52d396074a9e5d45de058d5413da90988be..0ee0e94e3e9f24af2534154af06ffc8f8cfef2b3 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   IPP/2.0 test suite.
 #
-#   Copyright 2007-2011 by Apple Inc.
+#   Copyright 2007-2012 by Apple Inc.
 #   Copyright 2001-2006 by Easy Software Products. All rights reserved.
 #
 #   These coded instructions, statements, and computer programs are the
@@ -24,7 +24,7 @@ INCLUDE "ipp-1.1.test"
 
 
 # Regular expression for PWG media size names (eek!)
-DEFINE MEDIA_REGEX "/^((custom|na|asme|roc|oe)_[a-z0-9][-a-z0-9]*_([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])x([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])in|(custom|iso|jis|jpn|prc|om)_[a-z0-9][-a-z0-9]*_([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])x([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])mm)$$/"
+DEFINE MEDIA_REGEX "/^(choice(_((custom|na|asme|roc|oe|roll)_[a-z0-9][-a-z0-9]*_([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])x([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])in|(custom|iso|jis|jpn|prc|om|roll)_[a-z0-9][-a-z0-9]*_([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])x([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])mm)){2,}|(custom|na|asme|roc|oe|roll)_[a-z0-9][-a-z0-9]*_([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])x([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])in|(custom|iso|jis|jpn|prc|om|roll)_[a-z0-9][-a-z0-9]*_([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])x([1-9][0-9]*(\.[0-9]*[1-9])?|0\.[0-9]*[1-9])mm)$$/"
 
 
 # Test required printer description attribute support.
@@ -51,8 +51,8 @@ DEFINE MEDIA_REGEX "/^((custom|na|asme|roc|oe)_[a-z0-9][-a-z0-9]*_([1-9][0-9]*(\
        EXPECT finishings-default OF-TYPE enum IN-GROUP printer-attributes-tag
        EXPECT finishings-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3
        EXPECT media-default OF-TYPE no-value|keyword|name IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "$MEDIA_REGEX"
-       EXPECT ?media-ready OF-TYPE keyword|name IN-GROUP printer-attributes-tag WITH-VALUE "$MEDIA_REGEX"
-       EXPECT media-supported OF-TYPE keyword|name IN-GROUP printer-attributes-tag WITH-VALUE "$MEDIA_REGEX"
+       EXPECT ?media-ready OF-TYPE keyword|name IN-GROUP printer-attributes-tag WITH-ALL-VALUES "$MEDIA_REGEX"
+       EXPECT media-supported OF-TYPE keyword|name IN-GROUP printer-attributes-tag WITH-ALL-VALUES "$MEDIA_REGEX"
        EXPECT orientation-requested-default OF-TYPE no-value|enum IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE 3,4,5,6
        EXPECT orientation-requested-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3,4,5,6
        EXPECT output-bin-default OF-TYPE keyword|name IN-GROUP printer-attributes-tag COUNT 1
@@ -61,8 +61,8 @@ DEFINE MEDIA_REGEX "/^((custom|na|asme|roc|oe)_[a-z0-9][-a-z0-9]*_([1-9][0-9]*(\
        EXPECT print-quality-supported OF-TYPE enum IN-GROUP printer-attributes-tag WITH-VALUE 3,4,5
        EXPECT printer-resolution-default OF-TYPE resolution IN-GROUP printer-attributes-tag COUNT 1
        EXPECT printer-resolution-supported OF-TYPE resolution IN-GROUP printer-attributes-tag
-       EXPECT sides-default OF-TYPE keyword IN-GROUP printer-attributes-tag COUNT 1 WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
-       EXPECT sides-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-VALUE "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+       EXPECT sides-default OF-TYPE keyword IN-GROUP printer-attributes-tag COUNT 1 WITH-ALL-VALUES "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
+       EXPECT sides-supported OF-TYPE keyword IN-GROUP printer-attributes-tag WITH-ALL-VALUES "/^(one-sided|two-sided-long-edge|two-sided-short-edge)$$/"
 
        # Optional media-col support
        EXPECT ?media-col-default OF-TYPE collection IN-GROUP printer-attributes-tag COUNT 1
index d1cdea4429e256e08a159b89e4ff2b03dd153632..5c1dd26f2b1dfef548e2e6ad893c4ed843aff0d2 100644 (file)
@@ -81,6 +81,13 @@ typedef enum _cups_output_e          /**** Output mode ****/
   _CUPS_OUTPUT_CSV                     /* Comma-separated values output */
 } _cups_output_t;
 
+typedef enum _cups_with_e              /**** WITH flags ****/
+{
+  _CUPS_WITH_LITERAL = 0,              /* Match string is a literal value */
+  _CUPS_WITH_ALL = 1,                  /* Must match all values */
+  _CUPS_WITH_REGEX = 2                 /* Match string is a regular expression */
+} _cups_with_t;
+
 typedef struct _cups_expect_s          /**** Expected attribute info ****/
 {
   int          optional,               /* Optional attribute? */
@@ -96,7 +103,7 @@ typedef struct _cups_expect_s                /**** Expected attribute info ****/
                *define_value;          /* Variable to define with value */
   int          repeat_match,           /* Repeat test on match */
                repeat_no_match,        /* Repeat test on no match */
-               with_regex,             /* WITH-VALUE is a regular expression */
+               with_flags,             /* WITH flags  */
                count;                  /* Expected count if > 0 */
   ipp_tag_t    in_group;               /* IN-GROUP value */
 } _cups_expect_t;
@@ -205,7 +212,7 @@ static void sigterm_handler(int sig);
 static int     timeout_cb(http_t *http, void *user_data);
 static void    usage(void) __attribute__((noreturn));
 static int     validate_attr(cups_array_t *errors, ipp_attribute_t *attr);
-static int      with_value(cups_array_t *errors, char *value, int regex,
+static int      with_value(cups_array_t *errors, char *value, int flags,
                           ipp_attribute_t *attr, char *matchbuf,
                           size_t matchlen);
 
@@ -1164,6 +1171,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
           _cups_strcasecmp(token, "REPEAT-MATCH") &&
           _cups_strcasecmp(token, "REPEAT-NO-MATCH") &&
           _cups_strcasecmp(token, "SAME-COUNT-AS") &&
+          _cups_strcasecmp(token, "WITH-ALL-VALUES") &&
           _cups_strcasecmp(token, "WITH-VALUE"))
         last_expect = NULL;
 
@@ -2049,11 +2057,15 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
          goto test_exit;
        }
       }
-      else if (!_cups_strcasecmp(token, "WITH-VALUE"))
+      else if (!_cups_strcasecmp(token, "WITH-ALL-VALUES") ||
+               !_cups_strcasecmp(token, "WITH-VALUE"))
       {
+       if (!_cups_strcasecmp(token, "WITH-ALL-VALUES") && last_expect)
+         last_expect->with_flags = _CUPS_WITH_ALL;
+
        if (!get_token(fp, temp, sizeof(temp), &linenum))
        {
-         print_fatal_error("Missing WITH-VALUE value on line %d.", linenum);
+         print_fatal_error("Missing %s value on line %d.", token, linenum);
          pass = 0;
          goto test_exit;
        }
@@ -2075,7 +2087,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
            */
 
            last_expect->with_value = calloc(1, tokenptr - token);
-           last_expect->with_regex = 1;
+           last_expect->with_flags |= _CUPS_WITH_REGEX;
 
            if (last_expect->with_value)
              memcpy(last_expect->with_value, token + 1, tokenptr - token - 1);
@@ -2087,11 +2099,12 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
            */
 
            last_expect->with_value = strdup(token);
+           last_expect->with_flags |= _CUPS_WITH_LITERAL;
          }
        }
        else
        {
-         print_fatal_error("WITH-VALUE without a preceding EXPECT on line %d.",
+         print_fatal_error("%s without a preceding EXPECT on line %d.", token,
                            linenum);
          pass = 0;
          goto test_exit;
@@ -2660,21 +2673,27 @@ do_tests(_cups_vars_t *vars,            /* I - Variables */
            ippAttributeString(found, buffer, sizeof(buffer));
 
          if (found &&
-             !with_value(NULL, expect->with_value, expect->with_regex, found,
+             !with_value(NULL, expect->with_value, expect->with_flags, found,
                          buffer, sizeof(buffer)))
          {
            if (expect->define_no_match)
              set_variable(vars, expect->define_no_match, "1");
            else if (!expect->define_match && !expect->define_value)
            {
-             if (expect->with_regex)
-               add_stringf(errors, "EXPECTED: %s WITH-VALUE /%s/",
-                           expect->name, expect->with_value);
+             if (expect->with_flags & _CUPS_WITH_REGEX)
+               add_stringf(errors, "EXPECTED: %s %s /%s/",
+                           expect->name,
+                           (expect->with_flags & _CUPS_WITH_ALL) ?
+                               "WITH-ALL-VALUES" : "WITH-VALUE",
+                           expect->with_value);
              else
-               add_stringf(errors, "EXPECTED: %s WITH-VALUE \"%s\"",
-                           expect->name, expect->with_value);
+               add_stringf(errors, "EXPECTED: %s %s \"%s\"",
+                           expect->name,
+                           (expect->with_flags & _CUPS_WITH_ALL) ?
+                               "WITH-ALL-VALUES" : "WITH-VALUE",
+                           expect->with_value);
 
-             with_value(errors, expect->with_value, expect->with_regex, found,
+             with_value(errors, expect->with_value, expect->with_flags, found,
                         buffer, sizeof(buffer));
            }
 
@@ -5018,16 +5037,18 @@ validate_attr(cups_array_t    *errors,  /* I - Errors array */
 static int                             /* O - 1 on match, 0 on non-match */
 with_value(cups_array_t    *errors,    /* I - Errors array */
            char            *value,     /* I - Value string */
-           int             regex,      /* I - Value is a regular expression */
+           int             flags,      /* I - Flags for match */
            ipp_attribute_t *attr,      /* I - Attribute to compare */
           char            *matchbuf,   /* I - Buffer to hold matching value */
           size_t          matchlen)    /* I - Length of match buffer */
 {
-  int  i;                              /* Looping var */
+  int  i,                              /* Looping var */
+       match;                          /* Match? */
   char *valptr;                        /* Pointer into value */
 
 
   *matchbuf = '\0';
+  match     = (flags & _CUPS_WITH_ALL) ? 1 : 0;
 
  /*
   * NULL matches everything.
@@ -5048,8 +5069,8 @@ with_value(cups_array_t    *errors,       /* I - Errors array */
         {
          char  op,                     /* Comparison operator */
                *nextptr;               /* Next pointer */
-         int   intvalue;               /* Integer value */
-
+         int   intvalue,               /* Integer value */
+               valmatch = 0;           /* Does the current value match? */
 
           valptr = value;
 
@@ -5073,34 +5094,35 @@ with_value(cups_array_t    *errors,     /* I - Errors array */
              break;
            valptr = nextptr;
 
-           switch (op)
+            if ((op == '=' && attr->values[i].integer == intvalue) ||
+                (op == '<' && attr->values[i].integer < intvalue) ||
+                (op == '>' && attr->values[i].integer > intvalue))
            {
-             case '=' :
-                 if (attr->values[i].integer == intvalue)
-                 {
-                   snprintf(matchbuf, matchlen, "%d", attr->values[i].integer);
-                   return (1);
-                 }
-                 break;
-             case '<' :
-                 if (attr->values[i].integer < intvalue)
-                 {
-                   snprintf(matchbuf, matchlen, "%d", attr->values[i].integer);
-                   return (1);
-                 }
-                 break;
-             case '>' :
-                 if (attr->values[i].integer > intvalue)
-                 {
-                   snprintf(matchbuf, matchlen, "%d", attr->values[i].integer);
-                   return (1);
-                 }
-                 break;
+             if (!matchbuf[0])
+               snprintf(matchbuf, matchlen, "%d",
+                        attr->values[i].integer);
+
+             valmatch = 1;
+             break;
            }
          }
+
+          if (flags & _CUPS_WITH_ALL)
+          {
+            if (!valmatch)
+            {
+              match = 0;
+              break;
+            }
+          }
+          else if (valmatch)
+          {
+            match = 1;
+            break;
+          }
         }
 
-       if (errors)
+        if (!match && errors)
        {
          for (i = 0; i < attr->num_values; i ++)
            add_stringf(errors, "GOT: %s=%d", attr->name,
@@ -5113,8 +5135,8 @@ with_value(cups_array_t    *errors,       /* I - Errors array */
         {
          char  op,                     /* Comparison operator */
                *nextptr;               /* Next pointer */
-         int   intvalue;               /* Integer value */
-
+         int   intvalue,               /* Integer value */
+               valmatch = 0;           /* Does the current value match? */
 
           valptr = value;
 
@@ -5138,41 +5160,37 @@ with_value(cups_array_t    *errors,     /* I - Errors array */
              break;
            valptr = nextptr;
 
-           switch (op)
+            if ((op == '=' && (attr->values[i].range.lower == intvalue ||
+                              attr->values[i].range.upper == intvalue)) ||
+               (op == '<' && attr->values[i].range.upper < intvalue) ||
+               (op == '>' && attr->values[i].range.upper > intvalue))
            {
-             case '=' :
-                 if (attr->values[i].range.lower == intvalue ||
-                     attr->values[i].range.upper == intvalue)
-                 {
-                   snprintf(matchbuf, matchlen, "%d-%d",
-                            attr->values[i].range.lower,
-                            attr->values[i].range.upper);
-                   return (1);
-                 }
-                 break;
-             case '<' :
-                 if (attr->values[i].range.upper < intvalue)
-                 {
-                   snprintf(matchbuf, matchlen, "%d-%d",
-                            attr->values[i].range.lower,
-                            attr->values[i].range.upper);
-                   return (1);
-                 }
-                 break;
-             case '>' :
-                 if (attr->values[i].range.upper > intvalue)
-                 {
-                   snprintf(matchbuf, matchlen, "%d-%d",
-                            attr->values[i].range.lower,
-                            attr->values[i].range.upper);
-                   return (1);
-                 }
-                 break;
+             if (!matchbuf[0])
+               snprintf(matchbuf, matchlen, "%d-%d",
+                        attr->values[0].range.lower,
+                        attr->values[0].range.upper);
+
+             valmatch = 1;
+             break;
            }
          }
+
+          if (flags & _CUPS_WITH_ALL)
+          {
+            if (!valmatch)
+            {
+              match = 0;
+              break;
+            }
+          }
+          else if (valmatch)
+          {
+            match = 1;
+            break;
+          }
         }
 
-       if (errors)
+        if (!match && errors)
        {
          for (i = 0; i < attr->num_values; i ++)
            add_stringf(errors, "GOT: %s=%d-%d", attr->name,
@@ -5186,12 +5204,23 @@ with_value(cups_array_t    *errors,     /* I - Errors array */
        {
           if (!strcmp(value, "true") == attr->values[i].boolean)
           {
-            strlcpy(matchbuf, value, matchlen);
-           return (1);
+            if (!matchbuf[0])
+             strlcpy(matchbuf, value, matchlen);
+
+           if (!(flags & _CUPS_WITH_ALL))
+           {
+             match = 1;
+             break;
+           }
+         }
+         else if (flags & _CUPS_WITH_ALL)
+         {
+           match = 0;
+           break;
          }
        }
 
-       if (errors)
+       if (!match && errors)
        {
          for (i = 0; i < attr->num_values; i ++)
            add_stringf(errors, "GOT: %s=%s", attr->name,
@@ -5213,7 +5242,7 @@ with_value(cups_array_t    *errors,       /* I - Errors array */
     case IPP_TAG_TEXTLANG :
     case IPP_TAG_URI :
     case IPP_TAG_URISCHEME :
-        if (regex)
+        if (flags & _CUPS_WITH_REGEX)
        {
         /*
          * Value is an extended, case-sensitive POSIX regular expression...
@@ -5238,53 +5267,66 @@ with_value(cups_array_t    *errors,     /* I - Errors array */
 
          for (i = 0; i < attr->num_values; i ++)
          {
-           if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
+           if (!regexec(&re, attr->values[i].string.text, 0, NULL, 0))
            {
-             if (errors)
-               add_stringf(errors, "GOT: %s=\"%s\"", attr->name,
-                                attr->values[i].string.text);
-             else
+             if (!matchbuf[0])
+               strlcpy(matchbuf, attr->values[i].string.text, matchlen);
+
+             if (!(flags & _CUPS_WITH_ALL))
+             {
+               match = 1;
                break;
+             }
+           }
+           else if (flags & _CUPS_WITH_ALL)
+           {
+             match = 0;
+             break;
            }
          }
 
          regfree(&re);
-
-          if (i == attr->num_values)
-            strlcpy(matchbuf, attr->values[0].string.text, matchlen);
-
-          return (i == attr->num_values);
        }
        else
        {
         /*
-         * Value is a literal string, see if at least one value matches the
-         * literal string...
+         * Value is a literal string, see if the value(s) match...
          */
 
          for (i = 0; i < attr->num_values; i ++)
          {
            if (!strcmp(value, attr->values[i].string.text))
            {
-             strlcpy(matchbuf, attr->values[i].string.text, matchlen);
-             return (1);
-           }
-         }
+             if (!matchbuf[0])
+               strlcpy(matchbuf, attr->values[i].string.text, matchlen);
 
-         if (errors)
-         {
-           for (i = 0; i < attr->num_values; i ++)
-             add_stringf(errors, "GOT: %s=\"%s\"", attr->name,
-                              attr->values[i].string.text);
+             if (!(flags & _CUPS_WITH_ALL))
+             {
+               match = 1;
+               break;
+             }
+           }
+           else if (flags & _CUPS_WITH_ALL)
+           {
+             match = 0;
+             break;
+           }
          }
        }
+
+        if (!match && errors)
+        {
+         for (i = 0; i < attr->num_values; i ++)
+           add_stringf(errors, "GOT: %s=\"%s\"", attr->name,
+                            attr->values[i].string.text);
+        }
        break;
 
     default :
         break;
   }
 
-  return (0);
+  return (match);
 }
 
 
index 147650d39805ff62e1d247e346ad09372aea1e2a..b980c64eed42a2a14138e193ee8517deeab715bd 100755 (executable)
@@ -457,9 +457,9 @@ fi
 echo "Setting up environment variables for test..."
 
 if test "x$LD_LIBRARY_PATH" = x; then
-       LD_LIBRARY_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/driver:$root/ppdc"
+       LD_LIBRARY_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/ppdc"
 else
-       LD_LIBRARY_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/driver:$root/ppdc:$LD_LIBRARY_PATH"
+       LD_LIBRARY_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/ppdc:$LD_LIBRARY_PATH"
 fi
 
 export LD_LIBRARY_PATH
@@ -471,17 +471,17 @@ fi
 export LD_PRELOAD
 
 if test "x$DYLD_LIBRARY_PATH" = x; then
-       DYLD_LIBRARY_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/driver:$root/ppdc"
+       DYLD_LIBRARY_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/ppdc"
 else
-       DYLD_LIBRARY_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/driver:$root/ppdc:$DYLD_LIBRARY_PATH"
+       DYLD_LIBRARY_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/ppdc:$DYLD_LIBRARY_PATH"
 fi
 
 export DYLD_LIBRARY_PATH
 
 if test "x$SHLIB_PATH" = x; then
-       SHLIB_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/driver:$root/ppdc"
+       SHLIB_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/ppdc"
 else
-       SHLIB_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/driver:$root/ppdc:$SHLIB_PATH"
+       SHLIB_PATH="$root/cups:$root/filter:$root/cgi-bin:$root/scheduler:$root/ppdc:$SHLIB_PATH"
 fi
 
 export SHLIB_PATH
index 61ee8865d947405cef297920d27aa6b7b8bdc745..bbaf2c29aa99f1ded5c7b7777bf47df2cda2b358 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   Configuration file for CUPS on Windows.
  *
- *   Copyright 2007-2011 by Apple Inc.
+ *   Copyright 2007-2012 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -86,8 +86,8 @@
  * Version of software...
  */
 
-#define CUPS_SVERSION "CUPS v1.5.0"
-#define CUPS_MINIMAL "CUPS/1.5.0"
+#define CUPS_SVERSION "CUPS v1.6.0"
+#define CUPS_MINIMAL "CUPS/1.6.0"
 
 
 /*
index a49280538508a75b6135e9246f7d2ee4a210ba8e..5fede836a1700286dbee640b3b42555b2440d640 100644 (file)
@@ -36,6 +36,8 @@ Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "ipptool-installer", "ipptoo
 EndProject\r
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "regex", "regex.vcproj", "{18950A1B-D37A-40C7-B2DF-C12986C0526E}"\r
 EndProject\r
+Project("{54435603-DBB4-11D2-8724-00A0C9A8B90C}") = "ipptool-installer", "libcups2-installer.vdproj", "{03CF67C2-3FF5-44EA-B3AF-FB62D3BED961}"\r
+EndProject\r
 Global\r
        GlobalSection(SolutionConfigurationPlatforms) = preSolution\r
                Debug|Win32 = Debug|Win32\r
@@ -106,6 +108,14 @@ Global
                {18950A1B-D37A-40C7-B2DF-C12986C0526E}.Release|Win32.ActiveCfg = Release|Win32\r
                {18950A1B-D37A-40C7-B2DF-C12986C0526E}.Release|Win32.Build.0 = Release|Win32\r
                {18950A1B-D37A-40C7-B2DF-C12986C0526E}.Release|x64.ActiveCfg = Release|Win32\r
+               {03CF67C2-3FF5-44EA-B3AF-FB62D3BED961}.Debug|Win32.ActiveCfg = Debug\r
+               {03CF67C2-3FF5-44EA-B3AF-FB62D3BED961}.Debug|Win32.Build.0 = Debug\r
+               {03CF67C2-3FF5-44EA-B3AF-FB62D3BED961}.Debug|x64.ActiveCfg = Debug\r
+               {03CF67C2-3FF5-44EA-B3AF-FB62D3BED961}.Debug|x64.Build.0 = Debug\r
+               {03CF67C2-3FF5-44EA-B3AF-FB62D3BED961}.Release|Win32.ActiveCfg = Release\r
+               {03CF67C2-3FF5-44EA-B3AF-FB62D3BED961}.Release|Win32.Build.0 = Release\r
+               {03CF67C2-3FF5-44EA-B3AF-FB62D3BED961}.Release|x64.ActiveCfg = Release\r
+               {03CF67C2-3FF5-44EA-B3AF-FB62D3BED961}.Release|x64.Build.0 = Release\r
        EndGlobalSection\r
        GlobalSection(SolutionProperties) = preSolution\r
                HideSolutionNode = FALSE\r
diff --git a/vcnet/libcups2-installer.vdproj b/vcnet/libcups2-installer.vdproj
new file mode 100644 (file)
index 0000000..75d6dd8
--- /dev/null
@@ -0,0 +1,2194 @@
+"DeployProject"\r
+{\r
+"VSVersion" = "3:800"\r
+"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}"\r
+"IsWebType" = "8:FALSE"\r
+"ProjectName" = "8:libcups2-installer"\r
+"LanguageId" = "3:1033"\r
+"CodePage" = "3:1252"\r
+"UILanguageId" = "3:1033"\r
+"SccProjectName" = "8:"\r
+"SccLocalPath" = "8:"\r
+"SccAuxPath" = "8:"\r
+"SccProvider" = "8:"\r
+    "Hierarchy"\r
+    {\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_00BDFF08E6DA434981F5C1F879B3EF6C"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_0299839A2CCC4F908C5D3A8F465F3FFE"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_06B57E1C99D0410EB9C8DC4D66C73FC5"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_0DDD4CA1EEBE4AB69CC694DDF483D146"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_16A59C6F3F9940288A7D26B6CA80608F"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_1AF767BD52F94DC08C2CBE11DA41E95A"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_1DFD9AECD1AD4B2291DD52028E866569"\r
+        "OwnerKey" = "8:_62CA00B1E5E4460CA93EE7E2B8FE878B"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_1ED4FB1CE10D4805981844ABC56602F6"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_22CD325A4F5141D6B5FACD713F5FD4F9"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_24E7DBA1F5964574A8251258BCDC935D"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_260594D75E4B4764BBAFE25C15E4F273"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_262BA608F9ED4BB5870E3F6C6EEA0820"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_285F62B042274099A6FD88C531DAA341"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_340E6094BE6F4BCF8350280DC8B37900"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_364DCCAFF25145BCBE75FFEEDCC75B3A"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_3697A58F04D14955AA428E89771E7BA3"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_380124B8E57C4956A73E042735724DB7"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_3CFC5A9B09ED4916A350B88FEF4662CC"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_4879AF80C19D4ED9A3758DCC412190FB"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_574EE5A852D3434987B58E3B8118C1C2"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_5ED87BAE980C4992A4C74AEAEC4A57CF"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_62CA00B1E5E4460CA93EE7E2B8FE878B"\r
+        "OwnerKey" = "8:_0299839A2CCC4F908C5D3A8F465F3FFE"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_62CA00B1E5E4460CA93EE7E2B8FE878B"\r
+        "OwnerKey" = "8:_B20638175CCB42398417E0683A12469C"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_62CA00B1E5E4460CA93EE7E2B8FE878B"\r
+        "OwnerKey" = "8:_364DCCAFF25145BCBE75FFEEDCC75B3A"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_62CA00B1E5E4460CA93EE7E2B8FE878B"\r
+        "OwnerKey" = "8:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_62CA00B1E5E4460CA93EE7E2B8FE878B"\r
+        "OwnerKey" = "8:_D02EB13951314EFD9C539150EF8E53B8"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_65560B58BEBF468C9D06493456A17DEC"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_6BD69E32EE9A4D2B9ECC40558A68FCD8"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_6E847FCD9C014B7E81FB859A0D2D2590"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_72A7EBE64092496AA67AB2DD00C0804B"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_747C33B5F41F498ABCAE119B532F6485"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_7FC58520B0F44E3E95A207905CABFED4"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_860678A628E34D219950C2E2B1BE6A89"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_8CCA95F5402D439B9B9CAC6F0FC1A443"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_9967519E7058965D4C7DEF47EB39CC50"\r
+        "OwnerKey" = "8:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_9D69B0FC2413407BA24D88B73EF456AA"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_9FBF78D7B89EEA843380D5F10E1954D7"\r
+        "OwnerKey" = "8:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_A271CCE042C14DDF8F0F1A1B16584F17"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_A513FBE6CC6247C19AF06829E5470D01"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_A833908023464B61A160E0323C8E9606"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_B20638175CCB42398417E0683A12469C"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_C1FCE2FAE4714A719B7B430E2BE93CBB"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_C494B5675E2F4B1E9301627B19CF8A52"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_C6AA56CC25F14D6582803347599840BB"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_CD0CFE42ED2D4416A01253E12A0082A8"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_CDBB327B06484A60AD16B999D88A10F5"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_D02EB13951314EFD9C539150EF8E53B8"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_D3B3B266E0FC45DD9B7EEBCC3AC52965"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_D4EC471BF98C4F8FA7A927B95CB69013"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_DA4E31E0503E4EAFA1E4BAEE05144618"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_E3C6C5A7FDD94965B68960844461D5EA"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_E47BCB853AC74A81BC61E878BFCEF5DC"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_EA287095645D4A7BA58A530186317895"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_EB7A2E97695F4964B4AF0560A258A14A"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_F77CB9E0AE78446481BD8BFD680F548E"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+        "Entry"\r
+        {\r
+        "MsmKey" = "8:_FA604C5C4FDD4D7B8110AFC6B603FBAF"\r
+        "OwnerKey" = "8:_UNDEFINED"\r
+        "MsmSig" = "8:_UNDEFINED"\r
+        }\r
+    }\r
+    "Configurations"\r
+    {\r
+        "Debug"\r
+        {\r
+        "DisplayName" = "8:Debug"\r
+        "IsDebugOnly" = "11:TRUE"\r
+        "IsReleaseOnly" = "11:FALSE"\r
+        "OutputFilename" = "8:libcups2-windows.msi"\r
+        "PackageFilesAs" = "3:2"\r
+        "PackageFileSize" = "3:-2147483648"\r
+        "CabType" = "3:1"\r
+        "Compression" = "3:3"\r
+        "SignOutput" = "11:FALSE"\r
+        "CertificateFile" = "8:"\r
+        "PrivateKeyFile" = "8:"\r
+        "TimeStampServer" = "8:"\r
+        "InstallerBootstrapper" = "3:2"\r
+            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"\r
+            {\r
+            "Enabled" = "11:TRUE"\r
+            "PromptEnabled" = "11:TRUE"\r
+            "PrerequisitesLocation" = "2:1"\r
+            "Url" = "8:"\r
+            "ComponentsUrl" = "8:"\r
+                "Items"\r
+                {\r
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Net.Framework.3.5.SP1"\r
+                    {\r
+                    "Name" = "8:.NET Framework 3.5 SP1"\r
+                    "ProductCode" = "8:Microsoft.Net.Framework.3.5.SP1"\r
+                    }\r
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Windows.Installer.3.1"\r
+                    {\r
+                    "Name" = "8:Windows Installer 3.1"\r
+                    "ProductCode" = "8:Microsoft.Windows.Installer.3.1"\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        "Release"\r
+        {\r
+        "DisplayName" = "8:Release"\r
+        "IsDebugOnly" = "11:FALSE"\r
+        "IsReleaseOnly" = "11:TRUE"\r
+        "OutputFilename" = "8:libcups2-windows.msi"\r
+        "PackageFilesAs" = "3:2"\r
+        "PackageFileSize" = "3:-2147483648"\r
+        "CabType" = "3:1"\r
+        "Compression" = "3:3"\r
+        "SignOutput" = "11:FALSE"\r
+        "CertificateFile" = "8:"\r
+        "PrivateKeyFile" = "8:"\r
+        "TimeStampServer" = "8:"\r
+        "InstallerBootstrapper" = "3:2"\r
+            "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}"\r
+            {\r
+            "Enabled" = "11:TRUE"\r
+            "PromptEnabled" = "11:TRUE"\r
+            "PrerequisitesLocation" = "2:1"\r
+            "Url" = "8:"\r
+            "ComponentsUrl" = "8:"\r
+                "Items"\r
+                {\r
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Net.Framework.3.5.SP1"\r
+                    {\r
+                    "Name" = "8:.NET Framework 3.5 SP1"\r
+                    "ProductCode" = "8:Microsoft.Net.Framework.3.5.SP1"\r
+                    }\r
+                    "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Windows.Installer.3.1"\r
+                    {\r
+                    "Name" = "8:Windows Installer 3.1"\r
+                    "ProductCode" = "8:Microsoft.Windows.Installer.3.1"\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+    "Deployable"\r
+    {\r
+        "CustomAction"\r
+        {\r
+        }\r
+        "DefaultFeature"\r
+        {\r
+        "Name" = "8:DefaultFeature"\r
+        "Title" = "8:"\r
+        "Description" = "8:"\r
+        }\r
+        "ExternalPersistence"\r
+        {\r
+            "LaunchCondition"\r
+            {\r
+            }\r
+        }\r
+        "File"\r
+        {\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_00BDFF08E6DA434981F5C1F879B3EF6C"\r
+            {\r
+            "SourcePath" = "8:..\\test\\document-a4.ps"\r
+            "TargetName" = "8:document-a4.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_06B57E1C99D0410EB9C8DC4D66C73FC5"\r
+            {\r
+            "SourcePath" = "8:..\\test\\create-printer-subscription.test"\r
+            "TargetName" = "8:create-printer-subscription.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0DDD4CA1EEBE4AB69CC694DDF483D146"\r
+            {\r
+            "SourcePath" = "8:..\\test\\get-completed-jobs.test"\r
+            "TargetName" = "8:get-completed-jobs.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_16A59C6F3F9940288A7D26B6CA80608F"\r
+            {\r
+            "SourcePath" = "8:..\\test\\onepage-a4.ps"\r
+            "TargetName" = "8:onepage-a4.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1AF767BD52F94DC08C2CBE11DA41E95A"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\images\\raster.png"\r
+            "TargetName" = "8:raster.png"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_A4CDED7951A44EF794E1E1EE9F73F240"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1ED4FB1CE10D4805981844ABC56602F6"\r
+            {\r
+            "SourcePath" = "8:..\\test\\testfile.jpg"\r
+            "TargetName" = "8:testfile.jpg"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_22CD325A4F5141D6B5FACD713F5FD4F9"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\adminutil.h"\r
+            "TargetName" = "8:adminutil.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_24E7DBA1F5964574A8251258BCDC935D"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\http.h"\r
+            "TargetName" = "8:http.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_260594D75E4B4764BBAFE25C15E4F273"\r
+            {\r
+            "SourcePath" = "8:..\\test\\print-job.test"\r
+            "TargetName" = "8:print-job.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_262BA608F9ED4BB5870E3F6C6EEA0820"\r
+            {\r
+            "SourcePath" = "8:..\\test\\ipp-1.1.test"\r
+            "TargetName" = "8:ipp-1.1.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_285F62B042274099A6FD88C531DAA341"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\ipp.h"\r
+            "TargetName" = "8:ipp.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_340E6094BE6F4BCF8350280DC8B37900"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\help\\api-httpipp.html"\r
+            "TargetName" = "8:api-httpipp.html"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_24DE31CE70694FD2977B5FB38F24D77F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3697A58F04D14955AA428E89771E7BA3"\r
+            {\r
+            "SourcePath" = "8:..\\test\\ipp-2.0.test"\r
+            "TargetName" = "8:ipp-2.0.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_380124B8E57C4956A73E042735724DB7"\r
+            {\r
+            "SourcePath" = "8:Win32\\Release\\libcups2.lib"\r
+            "TargetName" = "8:libcups2.lib"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_2927DAE23F604CF9B8B4D1EC01A6F158"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3CFC5A9B09ED4916A350B88FEF4662CC"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\transcode.h"\r
+            "TargetName" = "8:transcode.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4879AF80C19D4ED9A3758DCC412190FB"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\raster.h"\r
+            "TargetName" = "8:raster.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_574EE5A852D3434987B58E3B8118C1C2"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\array.h"\r
+            "TargetName" = "8:array.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5ED87BAE980C4992A4C74AEAEC4A57CF"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\ppd.h"\r
+            "TargetName" = "8:ppd.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_65560B58BEBF468C9D06493456A17DEC"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\language.h"\r
+            "TargetName" = "8:language.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6BD69E32EE9A4D2B9ECC40558A68FCD8"\r
+            {\r
+            "SourcePath" = "8:Win32\\Release\\libcupsimage2.lib"\r
+            "TargetName" = "8:libcupsimage2.lib"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_2927DAE23F604CF9B8B4D1EC01A6F158"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6E847FCD9C014B7E81FB859A0D2D2590"\r
+            {\r
+            "SourcePath" = "8:..\\test\\ipp-2.2.test"\r
+            "TargetName" = "8:ipp-2.2.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_72A7EBE64092496AA67AB2DD00C0804B"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\versioning.h"\r
+            "TargetName" = "8:versioning.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_747C33B5F41F498ABCAE119B532F6485"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\dir.h"\r
+            "TargetName" = "8:dir.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7FC58520B0F44E3E95A207905CABFED4"\r
+            {\r
+            "SourcePath" = "8:..\\test\\gray.jpg"\r
+            "TargetName" = "8:gray.jpg"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_860678A628E34D219950C2E2B1BE6A89"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\help\\api-raster.html"\r
+            "TargetName" = "8:api-raster.html"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_24DE31CE70694FD2977B5FB38F24D77F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8CCA95F5402D439B9B9CAC6F0FC1A443"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\help\\api-array.html"\r
+            "TargetName" = "8:api-array.html"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_24DE31CE70694FD2977B5FB38F24D77F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9967519E7058965D4C7DEF47EB39CC50"\r
+            {\r
+            "SourcePath" = "8:CRYPT32.dll"\r
+            "TargetName" = "8:CRYPT32.dll"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:TRUE"\r
+            "IsDependency" = "11:TRUE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9D69B0FC2413407BA24D88B73EF456AA"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\images\\sample-image.png"\r
+            "TargetName" = "8:sample-image.png"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_A4CDED7951A44EF794E1E1EE9F73F240"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9FBF78D7B89EEA843380D5F10E1954D7"\r
+            {\r
+            "SourcePath" = "8:Secur32.dll"\r
+            "TargetName" = "8:Secur32.dll"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:TRUE"\r
+            "IsDependency" = "11:TRUE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A271CCE042C14DDF8F0F1A1B16584F17"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\help\\api-filedir.html"\r
+            "TargetName" = "8:api-filedir.html"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_24DE31CE70694FD2977B5FB38F24D77F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A513FBE6CC6247C19AF06829E5470D01"\r
+            {\r
+            "SourcePath" = "8:..\\test\\document-a4.pdf"\r
+            "TargetName" = "8:document-a4.pdf"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A833908023464B61A160E0323C8E9606"\r
+            {\r
+            "SourcePath" = "8:..\\test\\document-letter.pdf"\r
+            "TargetName" = "8:document-letter.pdf"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C1FCE2FAE4714A719B7B430E2BE93CBB"\r
+            {\r
+            "SourcePath" = "8:..\\test\\testfile.ps"\r
+            "TargetName" = "8:testfile.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C494B5675E2F4B1E9301627B19CF8A52"\r
+            {\r
+            "SourcePath" = "8:..\\test\\document-letter.ps"\r
+            "TargetName" = "8:document-letter.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C6AA56CC25F14D6582803347599840BB"\r
+            {\r
+            "SourcePath" = "8:..\\test\\color.jpg"\r
+            "TargetName" = "8:color.jpg"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CD0CFE42ED2D4416A01253E12A0082A8"\r
+            {\r
+            "SourcePath" = "8:..\\test\\testfile.pdf"\r
+            "TargetName" = "8:testfile.pdf"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CDBB327B06484A60AD16B999D88A10F5"\r
+            {\r
+            "SourcePath" = "8:..\\test\\ipp-2.1.test"\r
+            "TargetName" = "8:ipp-2.1.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D3B3B266E0FC45DD9B7EEBCC3AC52965"\r
+            {\r
+            "SourcePath" = "8:..\\test\\get-printer-attributes.test"\r
+            "TargetName" = "8:get-printer-attributes.test"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D4EC471BF98C4F8FA7A927B95CB69013"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\help\\api-overview.html"\r
+            "TargetName" = "8:api-overview.html"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_24DE31CE70694FD2977B5FB38F24D77F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DA4E31E0503E4EAFA1E4BAEE05144618"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\help\\api-cups.html"\r
+            "TargetName" = "8:api-cups.html"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_24DE31CE70694FD2977B5FB38F24D77F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E3C6C5A7FDD94965B68960844461D5EA"\r
+            {\r
+            "SourcePath" = "8:..\\LICENSE.txt"\r
+            "TargetName" = "8:LICENSE.txt"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E47BCB853AC74A81BC61E878BFCEF5DC"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\cups.h"\r
+            "TargetName" = "8:cups.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EA287095645D4A7BA58A530186317895"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\images\\raster-organization.png"\r
+            "TargetName" = "8:raster-organization.png"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_A4CDED7951A44EF794E1E1EE9F73F240"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EB7A2E97695F4964B4AF0560A258A14A"\r
+            {\r
+            "SourcePath" = "8:..\\cups\\file.h"\r
+            "TargetName" = "8:file.h"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_121A70CA434045EDB010E7480AFCEF18"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F77CB9E0AE78446481BD8BFD680F548E"\r
+            {\r
+            "SourcePath" = "8:..\\doc\\help\\api-ppd.html"\r
+            "TargetName" = "8:api-ppd.html"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_24DE31CE70694FD2977B5FB38F24D77F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FA604C5C4FDD4D7B8110AFC6B603FBAF"\r
+            {\r
+            "SourcePath" = "8:..\\test\\onepage-letter.ps"\r
+            "TargetName" = "8:onepage-letter.ps"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_9DFBB4777E594B0F8884792467931241"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            }\r
+        }\r
+        "FileType"\r
+        {\r
+        }\r
+        "Folder"\r
+        {\r
+            "{1525181F-901A-416C-8A58-119130FE478E}:_BEC0EAE20C954C78B294B83E6696156E"\r
+            {\r
+            "Name" = "8:#1919"\r
+            "AlwaysCreate" = "11:FALSE"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Property" = "8:ProgramMenuFolder"\r
+                "Folders"\r
+                {\r
+                }\r
+            }\r
+            "{1525181F-901A-416C-8A58-119130FE478E}:_C8D931ADC425446B916E9711B929659F"\r
+            {\r
+            "Name" = "8:#1914"\r
+            "AlwaysCreate" = "11:FALSE"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Property" = "8:SystemFolder"\r
+                "Folders"\r
+                {\r
+                }\r
+            }\r
+            "{1525181F-901A-416C-8A58-119130FE478E}:_D02CDADE99F344CF92CA1A8D0278861F"\r
+            {\r
+            "Name" = "8:#1916"\r
+            "AlwaysCreate" = "11:FALSE"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Property" = "8:DesktopFolder"\r
+                "Folders"\r
+                {\r
+                }\r
+            }\r
+            "{3C67513D-01DD-4637-8A68-80971EB9504F}:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            {\r
+            "DefaultLocation" = "8:[ProgramFilesFolder]\\ipptool"\r
+            "Name" = "8:#1925"\r
+            "AlwaysCreate" = "11:FALSE"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Property" = "8:TARGETDIR"\r
+                "Folders"\r
+                {\r
+                    "{9EF0B969-E518-4E46-987F-47570745A589}:_121A70CA434045EDB010E7480AFCEF18"\r
+                    {\r
+                    "Name" = "8:include"\r
+                    "AlwaysCreate" = "11:FALSE"\r
+                    "Condition" = "8:"\r
+                    "Transitive" = "11:FALSE"\r
+                    "Property" = "8:_23D8BBBA9DEE4C8E88C9D1624DEAFB81"\r
+                        "Folders"\r
+                        {\r
+                        }\r
+                    }\r
+                    "{9EF0B969-E518-4E46-987F-47570745A589}:_24DE31CE70694FD2977B5FB38F24D77F"\r
+                    {\r
+                    "Name" = "8:doc"\r
+                    "AlwaysCreate" = "11:FALSE"\r
+                    "Condition" = "8:"\r
+                    "Transitive" = "11:FALSE"\r
+                    "Property" = "8:_4C3C248E2B3E4CB0AE8A9DF8D97AB433"\r
+                        "Folders"\r
+                        {\r
+                            "{9EF0B969-E518-4E46-987F-47570745A589}:_A4CDED7951A44EF794E1E1EE9F73F240"\r
+                            {\r
+                            "Name" = "8:images"\r
+                            "AlwaysCreate" = "11:FALSE"\r
+                            "Condition" = "8:"\r
+                            "Transitive" = "11:FALSE"\r
+                            "Property" = "8:_7ECE25C7A13C410AA18E0529C8998EB7"\r
+                                "Folders"\r
+                                {\r
+                                }\r
+                            }\r
+                        }\r
+                    }\r
+                    "{9EF0B969-E518-4E46-987F-47570745A589}:_2927DAE23F604CF9B8B4D1EC01A6F158"\r
+                    {\r
+                    "Name" = "8:lib"\r
+                    "AlwaysCreate" = "11:FALSE"\r
+                    "Condition" = "8:"\r
+                    "Transitive" = "11:FALSE"\r
+                    "Property" = "8:_927C9760A02446EBB2AEDE6BCCFDE29F"\r
+                        "Folders"\r
+                        {\r
+                        }\r
+                    }\r
+                    "{9EF0B969-E518-4E46-987F-47570745A589}:_9DFBB4777E594B0F8884792467931241"\r
+                    {\r
+                    "Name" = "8:ipptool"\r
+                    "AlwaysCreate" = "11:FALSE"\r
+                    "Condition" = "8:"\r
+                    "Transitive" = "11:FALSE"\r
+                    "Property" = "8:_77AF2E5323304714AF58A3F662F6051B"\r
+                        "Folders"\r
+                        {\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        "LaunchCondition"\r
+        {\r
+        }\r
+        "Locator"\r
+        {\r
+        }\r
+        "MsiBootstrapper"\r
+        {\r
+        "LangId" = "3:1033"\r
+        "RequiresElevation" = "11:FALSE"\r
+        }\r
+        "Product"\r
+        {\r
+        "Name" = "8:Microsoft Visual Studio"\r
+        "ProductName" = "8:CUPS SDK for Windows"\r
+        "ProductCode" = "8:{4E0D1662-B032-4CAD-8DBD-5302ADCE1C6F}"\r
+        "PackageCode" = "8:{00298F12-01DD-4785-9402-7A1E694F9577}"\r
+        "UpgradeCode" = "8:{BAB6EBBB-515D-4155-9FEF-D98DA76814CA}"\r
+        "RestartWWWService" = "11:FALSE"\r
+        "RemovePreviousVersions" = "11:TRUE"\r
+        "DetectNewerInstalledVersion" = "11:TRUE"\r
+        "InstallAllUsers" = "11:TRUE"\r
+        "ProductVersion" = "8:12.03.2600"\r
+        "Manufacturer" = "8:Apple Inc."\r
+        "ARPHELPTELEPHONE" = "8:"\r
+        "ARPHELPLINK" = "8:http://www.cups.org/str.php"\r
+        "Title" = "8:CUPS"\r
+        "Subject" = "8:"\r
+        "ARPCONTACT" = "8:Apple Inc."\r
+        "Keywords" = "8:IPP, Internet Printing Protocol"\r
+        "ARPCOMMENTS" = "8:CUPS SDK for Windows"\r
+        "ARPURLINFOABOUT" = "8:http://www.cups.org/"\r
+        "ARPPRODUCTICON" = "8:"\r
+        "ARPIconIndex" = "3:0"\r
+        "SearchPath" = "8:"\r
+        "UseSystemSearchPath" = "11:TRUE"\r
+        "TargetPlatform" = "3:0"\r
+        "PreBuildEvent" = "8:"\r
+        "PostBuildEvent" = "8:"\r
+        "RunPostBuildEvent" = "3:0"\r
+        }\r
+        "Registry"\r
+        {\r
+            "HKLM"\r
+            {\r
+                "Keys"\r
+                {\r
+                    "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_BC4E66686BCA4F9A8B24B6CF2728DACD"\r
+                    {\r
+                    "Name" = "8:Software"\r
+                    "Condition" = "8:"\r
+                    "AlwaysCreate" = "11:FALSE"\r
+                    "DeleteAtUninstall" = "11:FALSE"\r
+                    "Transitive" = "11:FALSE"\r
+                        "Keys"\r
+                        {\r
+                            "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_F9AB9B310C7545D993D690F529048AA2"\r
+                            {\r
+                            "Name" = "8:cups.org"\r
+                            "Condition" = "8:"\r
+                            "AlwaysCreate" = "11:FALSE"\r
+                            "DeleteAtUninstall" = "11:FALSE"\r
+                            "Transitive" = "11:FALSE"\r
+                                "Keys"\r
+                                {\r
+                                }\r
+                                "Values"\r
+                                {\r
+                                    "{ADCFDA98-8FDD-45E4-90BC-E3D20B029870}:_4E5BAC705A1D44E78C90C6D2A4A7BE20"\r
+                                    {\r
+                                    "Name" = "8:installdir"\r
+                                    "Condition" = "8:"\r
+                                    "Transitive" = "11:FALSE"\r
+                                    "ValueTypes" = "3:2"\r
+                                    "Value" = "8:[TARGETDIR]"\r
+                                    }\r
+                                }\r
+                            }\r
+                        }\r
+                        "Values"\r
+                        {\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "HKCU"\r
+            {\r
+                "Keys"\r
+                {\r
+                    "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_A4C9879F42874B6B92960A55F2D98922"\r
+                    {\r
+                    "Name" = "8:Software"\r
+                    "Condition" = "8:"\r
+                    "AlwaysCreate" = "11:FALSE"\r
+                    "DeleteAtUninstall" = "11:FALSE"\r
+                    "Transitive" = "11:FALSE"\r
+                        "Keys"\r
+                        {\r
+                            "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_1ACB03C307FB4B85BB27C9913FB58B09"\r
+                            {\r
+                            "Name" = "8:[Manufacturer]"\r
+                            "Condition" = "8:"\r
+                            "AlwaysCreate" = "11:FALSE"\r
+                            "DeleteAtUninstall" = "11:FALSE"\r
+                            "Transitive" = "11:FALSE"\r
+                                "Keys"\r
+                                {\r
+                                }\r
+                                "Values"\r
+                                {\r
+                                }\r
+                            }\r
+                        }\r
+                        "Values"\r
+                        {\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "HKCR"\r
+            {\r
+                "Keys"\r
+                {\r
+                }\r
+            }\r
+            "HKU"\r
+            {\r
+                "Keys"\r
+                {\r
+                }\r
+            }\r
+            "HKPU"\r
+            {\r
+                "Keys"\r
+                {\r
+                }\r
+            }\r
+        }\r
+        "Sequences"\r
+        {\r
+        }\r
+        "Shortcut"\r
+        {\r
+        }\r
+        "UserInterface"\r
+        {\r
+            "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_045DF90B1FF941A9BA7A742CFC0A6C00"\r
+            {\r
+            "UseDynamicProperties" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "SourcePath" = "8:<VsdDialogDir>\\VsdUserInterface.wim"\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_345BD86390E841A98B74ED3E07945F8C"\r
+            {\r
+            "Name" = "8:#1900"\r
+            "Sequence" = "3:2"\r
+            "Attributes" = "3:1"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_067C143A8731427180B1568AF8C07375"\r
+                    {\r
+                    "Sequence" = "3:200"\r
+                    "DisplayName" = "8:Installation Folder"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFolderDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_A2F2CC6EB9D7453599E7598D4D0629A5"\r
+                    {\r
+                    "Sequence" = "3:300"\r
+                    "DisplayName" = "8:Confirm Installation"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminConfirmDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_C2B41369B7334F419318792EBA031412"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Welcome"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminWelcomeDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "CopyrightWarning"\r
+                            {\r
+                            "Name" = "8:CopyrightWarning"\r
+                            "DisplayName" = "8:#1002"\r
+                            "Description" = "8:#1102"\r
+                            "Type" = "3:3"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:2"\r
+                            "Value" = "8:This computer program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2."\r
+                            "DefaultValue" = "8:#1202"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "Welcome"\r
+                            {\r
+                            "Name" = "8:Welcome"\r
+                            "DisplayName" = "8:#1003"\r
+                            "Description" = "8:#1103"\r
+                            "Type" = "3:3"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:1"\r
+                            "Value" = "8:#1203"\r
+                            "DefaultValue" = "8:#1203"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_6B654A06090344BA9AA443E0D0296737"\r
+            {\r
+            "Name" = "8:#1902"\r
+            "Sequence" = "3:1"\r
+            "Attributes" = "3:3"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_FB4E7BBC3DA242309FFB58F9A6194A93"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Finished"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdFinishedDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "UpdateText"\r
+                            {\r
+                            "Name" = "8:UpdateText"\r
+                            "DisplayName" = "8:#1058"\r
+                            "Description" = "8:#1158"\r
+                            "Type" = "3:15"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:1"\r
+                            "Value" = "8:#1258"\r
+                            "DefaultValue" = "8:#1258"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_712819C7C4F042ABB708949BD4426628"\r
+            {\r
+            "Name" = "8:#1900"\r
+            "Sequence" = "3:1"\r
+            "Attributes" = "3:1"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_2F49D4FACB954AF2B786D2AD9206D053"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Welcome"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdWelcomeDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "CopyrightWarning"\r
+                            {\r
+                            "Name" = "8:CopyrightWarning"\r
+                            "DisplayName" = "8:#1002"\r
+                            "Description" = "8:#1102"\r
+                            "Type" = "3:3"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:2"\r
+                            "Value" = "8:This computer program is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2."\r
+                            "DefaultValue" = "8:#1202"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "Welcome"\r
+                            {\r
+                            "Name" = "8:Welcome"\r
+                            "DisplayName" = "8:#1003"\r
+                            "Description" = "8:#1103"\r
+                            "Type" = "3:3"\r
+                            "ContextData" = "8:"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:1"\r
+                            "Value" = "8:#1203"\r
+                            "DefaultValue" = "8:#1203"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_770E25BC453A464EA8CD51381FDDDD9F"\r
+                    {\r
+                    "Sequence" = "3:300"\r
+                    "DisplayName" = "8:Confirm Installation"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdConfirmDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_9534A64B629F4F868D6D7A384C76DCB2"\r
+                    {\r
+                    "Sequence" = "3:200"\r
+                    "DisplayName" = "8:Installation Folder"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdFolderDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "InstallAllUsersVisible"\r
+                            {\r
+                            "Name" = "8:InstallAllUsersVisible"\r
+                            "DisplayName" = "8:#1059"\r
+                            "Description" = "8:#1159"\r
+                            "Type" = "3:5"\r
+                            "ContextData" = "8:1;True=1;False=0"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:0"\r
+                            "Value" = "3:1"\r
+                            "DefaultValue" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_770CCEFF81BD46A182A6E816A41A0E81"\r
+            {\r
+            "Name" = "8:#1901"\r
+            "Sequence" = "3:2"\r
+            "Attributes" = "3:2"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_75E0C1FD245D493DA0D7E3E0BC0C365F"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Progress"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminProgressDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "ShowProgress"\r
+                            {\r
+                            "Name" = "8:ShowProgress"\r
+                            "DisplayName" = "8:#1009"\r
+                            "Description" = "8:#1109"\r
+                            "Type" = "3:5"\r
+                            "ContextData" = "8:1;True=1;False=0"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:0"\r
+                            "Value" = "3:1"\r
+                            "DefaultValue" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_933B15E9A383418F8ADF3B13F68458F3"\r
+            {\r
+            "UseDynamicProperties" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "SourcePath" = "8:<VsdDialogDir>\\VsdBasicDialogs.wim"\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_E310DA8CED734E00950A3C5D630CE987"\r
+            {\r
+            "Name" = "8:#1902"\r
+            "Sequence" = "3:2"\r
+            "Attributes" = "3:3"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_CB172E69F9C74901BE1040336CFD4F72"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Finished"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdAdminFinishedDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+            "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_F44F9BE9B54940848289669635E4A5A2"\r
+            {\r
+            "Name" = "8:#1901"\r
+            "Sequence" = "3:1"\r
+            "Attributes" = "3:2"\r
+                "Dialogs"\r
+                {\r
+                    "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_14751F327A634B989283C8F28CFB6DFC"\r
+                    {\r
+                    "Sequence" = "3:100"\r
+                    "DisplayName" = "8:Progress"\r
+                    "UseDynamicProperties" = "11:TRUE"\r
+                    "IsDependency" = "11:FALSE"\r
+                    "SourcePath" = "8:<VsdDialogDir>\\VsdProgressDlg.wid"\r
+                        "Properties"\r
+                        {\r
+                            "BannerBitmap"\r
+                            {\r
+                            "Name" = "8:BannerBitmap"\r
+                            "DisplayName" = "8:#1001"\r
+                            "Description" = "8:#1101"\r
+                            "Type" = "3:8"\r
+                            "ContextData" = "8:Bitmap"\r
+                            "Attributes" = "3:4"\r
+                            "Setting" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                            "ShowProgress"\r
+                            {\r
+                            "Name" = "8:ShowProgress"\r
+                            "DisplayName" = "8:#1009"\r
+                            "Description" = "8:#1109"\r
+                            "Type" = "3:5"\r
+                            "ContextData" = "8:1;True=1;False=0"\r
+                            "Attributes" = "3:0"\r
+                            "Setting" = "3:0"\r
+                            "Value" = "3:1"\r
+                            "DefaultValue" = "3:1"\r
+                            "UsePlugInResources" = "11:TRUE"\r
+                            }\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+        "MergeModule"\r
+        {\r
+            "{CEE29DC0-9FBA-4B99-8D47-5BC643D9B626}:_1DFD9AECD1AD4B2291DD52028E866569"\r
+            {\r
+            "UseDynamicProperties" = "11:TRUE"\r
+            "IsDependency" = "11:TRUE"\r
+            "SourcePath" = "8:microsoft_vc90_crt_x86.msm"\r
+                "Properties"\r
+                {\r
+                }\r
+            "LanguageId" = "3:0"\r
+            "Exclude" = "11:FALSE"\r
+            "Folder" = "8:"\r
+            "Feature" = "8:"\r
+            "IsolateTo" = "8:"\r
+            }\r
+            "{CEE29DC0-9FBA-4B99-8D47-5BC643D9B626}:_62CA00B1E5E4460CA93EE7E2B8FE878B"\r
+            {\r
+            "UseDynamicProperties" = "11:TRUE"\r
+            "IsDependency" = "11:TRUE"\r
+            "SourcePath" = "8:policy_9_0_Microsoft_VC90_CRT_x86.msm"\r
+                "Properties"\r
+                {\r
+                }\r
+            "LanguageId" = "3:0"\r
+            "Exclude" = "11:FALSE"\r
+            "Folder" = "8:"\r
+            "Feature" = "8:"\r
+            "IsolateTo" = "8:"\r
+            }\r
+        }\r
+        "ProjectOutput"\r
+        {\r
+            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_0299839A2CCC4F908C5D3A8F465F3FFE"\r
+            {\r
+            "SourcePath" = "8:Win32\\Release\\libcupsimage2.dll"\r
+            "TargetName" = "8:"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_C8D931ADC425446B916E9711B929659F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            "ProjectOutputGroupRegister" = "3:1"\r
+            "OutputConfiguration" = "8:"\r
+            "OutputGroupCanonicalName" = "8:Built"\r
+            "OutputProjectGuid" = "8:{CB4AA6F2-3E84-45BE-B505-95CD375E1234}"\r
+            "ShowKeyOutput" = "11:TRUE"\r
+                "ExcludeFilters"\r
+                {\r
+                }\r
+            }\r
+            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_364DCCAFF25145BCBE75FFEEDCC75B3A"\r
+            {\r
+            "SourcePath" = "8:Win32\\Release\\cupstestppd.exe"\r
+            "TargetName" = "8:"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            "ProjectOutputGroupRegister" = "3:1"\r
+            "OutputConfiguration" = "8:"\r
+            "OutputGroupCanonicalName" = "8:Built"\r
+            "OutputProjectGuid" = "8:{6BE0CDD3-4ED7-409C-A80F-19DF73664B1F}"\r
+            "ShowKeyOutput" = "11:TRUE"\r
+                "ExcludeFilters"\r
+                {\r
+                }\r
+            }\r
+            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_B20638175CCB42398417E0683A12469C"\r
+            {\r
+            "SourcePath" = "8:Win32\\Release\\ipptool.exe"\r
+            "TargetName" = "8:"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_FFAEDEA1D38D4088A03FDD6F17E2CA5D"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            "ProjectOutputGroupRegister" = "3:1"\r
+            "OutputConfiguration" = "8:"\r
+            "OutputGroupCanonicalName" = "8:Built"\r
+            "OutputProjectGuid" = "8:{B246D91E-61F2-4433-BFD2-6C2A96FBD4D4}"\r
+            "ShowKeyOutput" = "11:TRUE"\r
+                "ExcludeFilters"\r
+                {\r
+                }\r
+            }\r
+            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_D02EB13951314EFD9C539150EF8E53B8"\r
+            {\r
+            "SourcePath" = "8:Win32\\Release\\regex.dll"\r
+            "TargetName" = "8:"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_C8D931ADC425446B916E9711B929659F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            "ProjectOutputGroupRegister" = "3:1"\r
+            "OutputConfiguration" = "8:"\r
+            "OutputGroupCanonicalName" = "8:Built"\r
+            "OutputProjectGuid" = "8:{18950A1B-D37A-40C7-B2DF-C12986C0526E}"\r
+            "ShowKeyOutput" = "11:TRUE"\r
+                "ExcludeFilters"\r
+                {\r
+                }\r
+            }\r
+            "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_EA282F32A10B4ED1A81AA6133B997C6A"\r
+            {\r
+            "SourcePath" = "8:Win32\\Release\\libcups2.dll"\r
+            "TargetName" = "8:"\r
+            "Tag" = "8:"\r
+            "Folder" = "8:_C8D931ADC425446B916E9711B929659F"\r
+            "Condition" = "8:"\r
+            "Transitive" = "11:FALSE"\r
+            "Vital" = "11:TRUE"\r
+            "ReadOnly" = "11:FALSE"\r
+            "Hidden" = "11:FALSE"\r
+            "System" = "11:FALSE"\r
+            "Permanent" = "11:FALSE"\r
+            "SharedLegacy" = "11:FALSE"\r
+            "PackageAs" = "3:1"\r
+            "Register" = "3:1"\r
+            "Exclude" = "11:FALSE"\r
+            "IsDependency" = "11:FALSE"\r
+            "IsolateTo" = "8:"\r
+            "ProjectOutputGroupRegister" = "3:1"\r
+            "OutputConfiguration" = "8:"\r
+            "OutputGroupCanonicalName" = "8:Built"\r
+            "OutputProjectGuid" = "8:{CB4AA6F2-3E84-45BE-B505-95CD375E8BE3}"\r
+            "ShowKeyOutput" = "11:TRUE"\r
+                "ExcludeFilters"\r
+                {\r
+                }\r
+            }\r
+        }\r
+    }\r
+}\r