]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from CUPS 1.4svn-r8414.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Sat, 7 Mar 2009 16:36:03 +0000 (16:36 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Sat, 7 Mar 2009 16:36:03 +0000 (16:36 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@1277 a1ca3aef-8c08-0410-bb20-df032aa958be

27 files changed:
CHANGES-1.3.txt
CHANGES.txt
backend/Makefile
backend/dnssd.c
backend/lpd.c
backend/socket.c
backend/testbackend.c
berkeley/lpq.c
cups/Makefile
cups/conflicts.c
cups/file.h
cups/test.ppd
cups/test2.ppd
cups/testppd.c
doc/help/spec-ppd.html
driver/Dependencies
man/cupsfilter.man
man/cupstestppd.man
scheduler/cupsd.h
scheduler/cupsfilter.c
scheduler/ipp.c
scheduler/job.c
scheduler/main.c
scheduler/printers.c
scheduler/process.c
systemv/Dependencies
systemv/cupstestppd.c

index 8f4621f575f2a7e6f83d22e98db0c94569f4a63a..4a4147c1aa2a469fa7d540a769037833840c4ac6 100644 (file)
@@ -5,6 +5,11 @@ CHANGES IN CUPS V1.3.10
 
        - Documentation fixes (STR #2994, STR #2995, STR #3008, STR #3056,
          STR #3057)
+       - The lpq command did not work when showing all destinations (STR #3117)
+       - The scheduler used a codeset name of UTF8 which is not supported on
+         Solaris (STR #3113)
+       - cupsGetJobs() did not work with a NULL destination (STR #3107,
+         STR #)
        - Fixed a localization problem for option choices (incorrectly) named
          "Custom" (STR #3106)
        - The fallback OpenSSL random number seeding would not work (STR #3079)
index c1cedc32fc01d07ba3f766331c7046f9ddfee8d8..ef8e6ff695c9c08c2b614e7b6e2f64d037d8ce80 100644 (file)
@@ -1,9 +1,13 @@
-CHANGES.txt - 2009-02-25
+CHANGES.txt - 2009-03-04
 ------------------------
 
 CHANGES IN CUPS V1.4b3
 
        - Documentation fixes (STR #3044, STR #3057)
+       - The cupstestppd program did not validate the capitalization of
+         filenames in the PPD file.
+       - The cupstestppd program did not validate the PageSize and PageRegion
+         values.
        - The cups-deviced helper program could miss reporting some backend
          devices (STR #3108)
        - The cupsSideChannelSNMP* functions did not work.
index 6ea05fdb2de42a625ff711456c91bfa56d693784..807b4c4e6c11231e6e9f738c07f36937493a179f 100644 (file)
@@ -19,8 +19,8 @@ include ../Makedefs
 
 RBACKENDS =    ipp lpd $(DNSSD_BACKEND)
 UBACKENDS =    $(PAP) $(LEGACY_BACKENDS) serial snmp socket usb
-TARGETS        =       test1284 testbackend testsupplies \
-               libbackend.a $(RBACKENDS) $(UBACKENDS)
+UNITTESTS =    test1284 testbackend testsupplies
+TARGETS =      libbackend.a $(RBACKENDS) $(UBACKENDS)
 LIBOBJS        =       ieee1284.o network.o runloop.o snmp-supplies.o
 OBJS   =       ipp.o lpd.o dnssd.o pap.o parallel.o scsi.o serial.o snmp.o \
                socket.o test1284.o testbackend.o testsupplies.o usb.o
@@ -44,7 +44,7 @@ libs:
 # Make unit tests...
 #
 
-unittests:
+unittests:     $(UNITTESTS)
 
 
 #
@@ -52,7 +52,7 @@ unittests:
 #
 
 clean:
-       $(RM) $(OBJS) $(TARGETS) $(LIBOBJS) http mdns
+       $(RM) $(OBJS) $(TARGETS) $(UNITTESTS) $(LIBOBJS) http mdns
 
 
 #
index 97c0d60715834d88ce0f7ffab2d6e5aee1364411..f5687f3c3ddb1db206699c6cd62ed9bfe17ac2e6 100644 (file)
@@ -19,6 +19,8 @@
  *   browse_callback()       - Browse devices.
  *   browse_local_callback() - Browse local devices.
  *   compare_devices()       - Compare two devices.
+ *   exec_backend()          - Execute the backend that corresponds to the
+ *                             resolved service name.
  *   get_device()            - Create or update a device.
  *   query_callback()        - Process query data.
  *   unquote()               - Unquote a name string.
index b39394c611739e0192ea7e76243826c400854a1a..67a856a029ca6429681a701126baeea196dbe067 100644 (file)
@@ -672,6 +672,8 @@ lpd_queue(const char *hostname,             /* I - Host to connect to */
 
   sprintf(portname, "%d", port);
 
+  fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);
+
   if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
   {
     _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'!\n"),
index 09137f9580d8296b6d03c5f0389f9fba9f14ce5c..f3d20b9b448336eb3dd4597999434146fe8b026b 100644 (file)
@@ -261,6 +261,8 @@ main(int  argc,                             /* I - Number of command-line arguments (6 or 7) */
 
   sprintf(portname, "%d", port);
 
+  fprintf(stderr, "DEBUG: Looking up \"%s\"...\n", hostname);
+
   if ((addrlist = httpAddrGetList(hostname, AF_UNSPEC, portname)) == NULL)
   {
     _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'!\n"),
index e0f573ccdce48254bfa245122c4174a27306648e..74a0f1e5a776ab508d873eaf1e1d7c3a6eadc534 100644 (file)
@@ -246,7 +246,7 @@ main(int  argc,                             /* I - Number of command-line args */
 
         write(1, ps_query, strlen(ps_query));
        write(2, "DEBUG: START\n", 13);
-        while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer), 5.0)) > 0)
+        while ((bytes = cupsBackChannelRead(buffer, sizeof(buffer), 60.0)) > 0)
          write(2, buffer, bytes);
        write(2, "\nDEBUG: END\n", 12);
       }
@@ -297,7 +297,7 @@ main(int  argc,                             /* I - Number of command-line args */
     close(side_fds[1]);
 
     execv(backend, argv + first_arg);
-    fprintf(stderr, "textbackend: Unable to execute \"%s\": %s\n", backend,
+    fprintf(stderr, "testbackend: Unable to execute \"%s\": %s\n", backend,
             strerror(errno));
     return (errno);
   }
@@ -353,7 +353,7 @@ main(int  argc,                             /* I - Number of command-line args */
 
     length   = 0;
     scstatus = cupsSideChannelDoRequest(CUPS_SC_CMD_DRAIN_OUTPUT, buffer,
-                                        &length, 5.0);
+                                        &length, 60.0);
     printf("CUPS_SC_CMD_DRAIN_OUTPUT returned %s\n", statuses[scstatus]);
 
     length   = 1;
@@ -437,10 +437,12 @@ usage(void)
   puts("Options:");
   puts("  -d          Show log messages from backend.");
   puts("  -oid 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("  -ps         Send PostScript query code to backend.");
-  puts("  -s          Do SNMP tests.");
+  puts("  -s          Do side-channel + SNMP tests.");
   puts("  -t          Send spaces slowly to backend ('trickle').");
   puts("  -walk OID   Walk the specified SNMP OID.");
+  puts("              (.1.3.6.1.2.1.43 is a good one for printers)");
 
   exit(1);
 }
index db089867eb69d0804abdbc091a75689e0836390f..50d240e1258122d9f381d4d08097f4d82becd23a 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   "lpq" command for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 2007-2009 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -372,17 +372,13 @@ show_jobs(const char *command,            /* I - Command name */
 
   request = ippNewRequest(id ? IPP_GET_JOB_ATTRIBUTES : IPP_GET_JOBS);
 
-  if (dest == NULL)
+  if (id)
   {
-    if (id)
-      sprintf(resource, "ipp://localhost/jobs/%d", id);
-    else
-      strcpy(resource, "ipp://localhost/jobs");
-
+    snprintf(resource, sizeof(resource), "ipp://localhost/jobs/%d", id);
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "job-uri",
                  NULL, resource);
   }
-  else
+  else if (dest)
   {
     httpAssembleURIf(HTTP_URI_CODING_ALL, resource, sizeof(resource), "ipp",
                      NULL, "localhost", 0, "/printers/%s", dest);
@@ -390,6 +386,9 @@ show_jobs(const char *command,              /* I - Command name */
     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                  NULL, resource);
   }
+  else
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
+                 NULL, "ipp://localhost/");
 
   if (user)
   {
index bec16188f8d66a60b381c346d20d89fe52a112a2..31be2be3127f3d501ff5f32315a3ffb025173603 100644 (file)
@@ -516,7 +516,7 @@ testoptions:        testoptions.o libcups.a
 # testppd (dependency on static CUPS library is intentional)
 #
 
-testppd:       testppd.o libcups.a
+testppd:       testppd.o libcups.a test.ppd test2.ppd
        echo Linking $@...
        $(CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testppd.o libcups.a \
                $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
index 4c90f169e4106fff7bc46b987696a81dc6d9eeb3..138a0c1199bb5d5708b27d953f766ec766725613 100644 (file)
@@ -181,16 +181,21 @@ cupsResolveConflicts(
     cups_option_t **options)           /* IO - Additional selected options */
 {
   int                  i,              /* Looping var */
-                       num_newopts,    /* Number of new options */
-                       num_resopts;    /* Number of resolver options */
-  cups_option_t                *newopts,       /* New options */
-                       *resopts;       /* Resolver options */
+                       num_newopts;    /* Number of new options */
+  cups_option_t                *newopts;       /* New options */
   cups_array_t         *active,        /* Active constraints */
                        *pass,          /* Resolvers for this pass */
-                       *resolvers;     /* Resolvers we have used */
+                       *resolvers,     /* Resolvers we have used */
+                       *test;          /* Test array for conflicts */
   _ppd_cups_uiconsts_t *consts;        /* Current constraints */
   _ppd_cups_uiconst_t  *constptr;      /* Current constraint */
   ppd_attr_t           *resolver;      /* Current resolver */
+  const char           *resval;        /* Pointer into resolver value */
+  char                 resoption[PPD_MAX_NAME],
+                                       /* Current resolver option */
+                       reschoice[PPD_MAX_NAME],
+                                       /* Current resolver choice */
+                       *resptr;        /* Pointer into option/choice */
   const char           *value;         /* Selected option value */
   int                  changed;        /* Did we change anything? */
   ppd_choice_t         *marked;        /* Marked choice */
@@ -277,25 +282,74 @@ cupsResolveConflicts(
         cupsArrayAdd(pass, consts->resolver);
        cupsArrayAdd(resolvers, consts->resolver);
 
-        if (option && choice)
+        for (resval = resolver->value; *resval && !changed;)
        {
-         resopts     = NULL;
-         num_resopts = _ppdParseOptions(resolver->value, 0, &resopts);
+         while (isspace(*resval & 255))
+           resval ++;
 
-          if ((value = cupsGetOption(option, num_newopts, newopts)) != NULL &&
-             !strcasecmp(value, choice))
+         if (*resval != '*')
+           break;
+
+         for (resval ++, resptr = resoption;
+              *resval && !isspace(*resval & 255);
+              resval ++)
+            if (resptr < (resoption + sizeof(resoption) - 1))
+             *resptr++ = *resval;
+
+          *resptr = '\0';
+
+         while (isspace(*resval & 255))
+           resval ++;
+
+         for (resptr = reschoice;
+              *resval && !isspace(*resval & 255);
+              resval ++)
+            if (resptr < (reschoice + sizeof(reschoice) - 1))
+             *resptr++ = *resval;
+
+          *resptr = '\0';
+
+          if (!resoption[0] || !reschoice[0])
+           break;
+
+         /*
+         * Is this the option we are changing?
+         */
+
+         if (option &&
+             (!strcasecmp(resoption, option) ||
+              (!strcasecmp(option, "PageSize") &&
+               !strcasecmp(resoption, "PageRegion")) ||
+              (!strcasecmp(option, "PageRegion") &&
+               !strcasecmp(resoption, "PageSize"))))
+           continue;
+
+        /*
+         * Try this choice...
+         */
+
+          if ((test = ppd_test_constraints(ppd, resoption, reschoice,
+                                          num_newopts, newopts,
+                                          _PPD_ALL_CONSTRAINTS)) == NULL)
          {
-           DEBUG_printf(("cupsResolveConflicts: Resolver %s changes %s!\n",
-                         consts->resolver, option));
-           cupsFreeOptions(num_resopts, resopts);
-           goto error;
-          }
+          /*
+           * That worked...
+           */
 
-         cupsFreeOptions(num_resopts, resopts);
-       }
+            changed = 1;
+         }
+         else
+            cupsArrayDelete(test);
 
-        num_newopts = _ppdParseOptions(resolver->value, num_newopts, &newopts);
-        changed     = 1;
+        /*
+         * Add the option/choice from the resolver regardless of whether it
+         * worked; this makes sure that we can cascade several changes to
+         * make things resolve...
+         */
+
+         num_newopts = cupsAddOption(resoption, reschoice, num_newopts,
+                                     &newopts);
+        }
       }
       else
       {
@@ -306,7 +360,6 @@ cupsResolveConflicts(
 
         int            j;              /* Looping var */
        ppd_choice_t    *cptr;          /* Current choice */
-        cups_array_t   *test;          /* Test array for conflicts */
         ppd_size_t     *size;          /* Current page size */
 
 
@@ -1019,7 +1072,7 @@ ppd_test_constraints(
         key.option = constptr->option;
 
        if ((marked = (ppd_choice_t *)cupsArrayFind(ppd->marked, &key))
-               != NULL &&
+               == NULL ||
            (!strcasecmp(marked->choice, "None") ||
             !strcasecmp(marked->choice, "Off") ||
             !strcasecmp(marked->choice, "False")))
index c5eb357facecd086a83dfeaf973a0c11fa68706d..c8a2b4667c1bab5a8464b7b8650e3d1bf19cdf05 100644 (file)
@@ -91,7 +91,6 @@ extern ssize_t                cupsFilePutConf(cups_file_t *fp, const char *directive,
                                        const char *value) _CUPS_API_1_4;
 extern int             cupsFilePuts(cups_file_t *fp, const char *s) _CUPS_API_1_2;
 extern ssize_t         cupsFileRead(cups_file_t *fp, char *buf, size_t bytes) _CUPS_API_1_2;
-extern ssize_t         cupsFileReady(cups_file_t *fp) _CUPS_API_1_4;
 extern off_t           cupsFileRewind(cups_file_t *fp) _CUPS_API_1_2;
 extern off_t           cupsFileSeek(cups_file_t *fp, off_t pos) _CUPS_API_1_2;
 extern cups_file_t     *cupsFileStderr(void) _CUPS_API_1_2;
index 35743b0a22fe5ac528d71973dc2937d2ad412755..45473fdacac7d27ef5b5c18fdda001078ae97ba0 100644 (file)
@@ -5,14 +5,14 @@
 *% Test PPD file for the Common UNIX Printing System (CUPS).
 *%
 *% This file is used to test the CUPS PPD API functions and cannot be
-*% used with any known printers.  Look at the PPD files in the "ppd"
-*% subdirectory as well as the CUPS web site for working PPD files.
+*% used with any known printers.  Look on the CUPS web site for working PPD
+*% files.
 *%
 *% If you are a PPD file developer, consider using the PPD compiler (ppdc)
 *% to create your PPD files - not only will it save you time, it produces
 *% consistently high-quality files.
 *%
-*% Copyright 2007-2008 by Apple Inc.
+*% Copyright 2007-2009 by Apple Inc.
 *% Copyright 2002-2006 by Easy Software Products.
 *% 
 *% These coded instructions, statements, and computer programs are the
@@ -40,7 +40,7 @@
 *LandscapeOrientation: Plus90
 *TTRasterizer: Type42
 
-*% These constraints are used to test ppdConflicts() and ppdResolveConflicts()
+*% These constraints are used to test ppdConflicts() and cupsResolveConflicts()
 *UIConstraints: *PageSize Letter *InputSlot Envelope
 *UIConstraints: *InputSlot Envelope *PageSize Letter
 *UIConstraints: *PageRegion Letter *InputSlot Envelope
index fb32e48303bb916a22da6cd8ccd3ca4d9a154de0..bd07c867b722dfd1c590b3eecf9745417c81993a 100644 (file)
@@ -5,14 +5,14 @@
 *% Test PPD file #2 for the Common UNIX Printing System (CUPS).
 *%
 *% This file is used to test the CUPS PPD API functions and cannot be
-*% used with any known printers.  Look at the PPD files in the "ppd"
-*% subdirectory as well as the CUPS web site for working PPD files.
+*% used with any known printers.  Look on the CUPS web site for working PPD
+*% files.
 *%
 *% If you are a PPD file developer, consider using the PPD compiler (ppdc)
 *% to create your PPD files - not only will it save you time, it produces
 *% consistently high-quality files.
 *%
-*% Copyright 2007-2008 by Apple Inc.
+*% Copyright 2007-2009 by Apple Inc.
 *% Copyright 2002-2006 by Easy Software Products.
 *% 
 *% These coded instructions, statements, and computer programs are the
 *LandscapeOrientation: Plus90
 *TTRasterizer: Type42
 
-*% These constraints are used to test ppdConflicts() and ppdResolveConflicts()
+*% These constraints are used to test ppdConflicts() and cupsResolveConflicts()
 *cupsUIConstraints envelope: "*PageSize Letter *InputSlot Envelope"
-*cupsUIConstraints envelope: "*PageRegion Letter *InputSlot Envelope"
-*cupsUIResolver envelope: "*InputSlot Manual"
+*cupsUIConstraints envelope: "*PageSize A4 *InputSlot Envelope"
+*cupsUIResolver envelope: "*InputSlot Manual *PageSize Env10"
 
 *cupsUIConstraints envphoto: "*PageSize Env10 *InputSlot Envelope *Quality Photo"
-*cupsUIConstraints envphoto: "*PageRegion Env10 *InputSlot Envelope *Quality Photo"
 *cupsUIResolver envphoto: "*Quality Normal"
 
 *% This constraint is used to test ppdInstallableConflict()
 *cupsUIConstraints: "*Duplex *InstalledDuplexer False"
 
-*% These constraints are used to test the loop detection code in ppdResolveConflicts()
+*% These constraints are used to test the loop detection code in cupsResolveConflicts()
 *cupsUIConstraints loop1: "*PageSize A4 *Quality Photo"
 *cupsUIResolver loop1: "*Quality Normal"
 *cupsUIConstraints loop2: "*PageSize A4 *Quality Normal"
-*cupsUIResolver loop2: "*PageSize Letter *Quality Draft"
-*cupsUIConstraints loop3: "*PageSize Letter *Quality Draft"
-*cupsUIResolver loop3: "*PageSize A4 *Quality Photo"
+*cupsUIResolver loop2: "*Quality Photo"
 
 *% For PageSize, we have put all of the translations in-line...
 *OpenUI *PageSize/Page Size: PickOne
index 29565dec4f807d804aac00aa8322d56a5fb3235e..3a6bb8517a75833140205de816d4a1606007189d 100644 (file)
@@ -601,8 +601,8 @@ main(int  argc,                             /* I - Number of command-line arguments */
     ppdMarkOption(ppd, "InputSlot", "Envelope");
     ppdMarkOption(ppd, "Quality", "Photo");
 
-    if ((conflicts = ppdConflicts(ppd)) == 2)
-      puts("PASS (2)");
+    if ((conflicts = ppdConflicts(ppd)) == 1)
+      puts("PASS (1)");
     else
     {
       printf("FAIL (%d)\n", conflicts);
@@ -649,6 +649,7 @@ main(int  argc,                             /* I - Number of command-line arguments */
 
     fputs("cupsResolveConflicts(loop test): ", stdout);
     ppdMarkOption(ppd, "PageSize", "A4");
+    ppdMarkOption(ppd, "InputSlot", "Tray");
     ppdMarkOption(ppd, "Quality", "Photo");
     num_options = 0;
     options     = NULL;
@@ -950,13 +951,23 @@ main(int  argc,                           /* I - Number of command-line arguments */
        }
       }
 
-      puts("Constraints:");
+      puts("\nConstraints:");
 
       for (i = ppd->num_consts, c = ppd->consts; i > 0; i --, c ++)
         printf("    *UIConstraints: *%s %s *%s %s\n", c->option1, c->choice1,
               c->option2, c->choice2);
+      if (ppd->num_consts == 0)
+        puts("    NO CONSTRAINTS");
+
+      puts("\nFilters:");
+
+      for (i = 0; i < ppd->num_filters; i ++)
+        printf("    %s\n", ppd->filters[i]);
+
+      if (ppd->num_filters == 0)
+        puts("    NO FILTERS");
 
-      puts("Attributes:");
+      puts("\nAttributes:");
 
       for (attr = (ppd_attr_t *)cupsArrayFirst(ppd->sorted_attrs);
            attr;
index 11ff4a4cf9f78e2bda42b84294e5934266776cf8..fe4b0cfd8834da5b9c8dec59ef4859b976721a4d 100644 (file)
@@ -380,8 +380,18 @@ have to guess how a particular constraint is best resolved.</p>
 <p>CUPS 1.4 and higher define two new attributes for constraints,
 <tt>cupsUIConstraints</tt> and <tt>cupsUIResolver</tt>. Each
 <tt>cupsUIConstraints</tt> attribute points to a <tt>cupsUIResolver</tt>
-attribute which corrects the conflict condition. The same
-<tt>cupsUIResolver</tt> can be used by multiple <tt>cupsUIConstraints</tt>.</p>
+attribute which specifies alternate options that resolve the conflict condition.
+The same <tt>cupsUIResolver</tt> can be used by multiple
+<tt>cupsUIConstraints</tt>.</p>
+
+<blockquote><b>Note:</b>
+
+    <p>When developing PPD files that contain constraints, it is very important
+    to use the <a href="man-cupstestppd.html">cupstestppd(1)</a> program to
+    verify that your constraints are accurate and cannot result in unresolvable
+    option selections.</p>
+
+</blockquote>
 
 <h3><span class='info'>CUPS 1.4</span><a name='cupsUIConstraints'>cupsUIConstraints</a></h3>
 
@@ -393,9 +403,8 @@ attribute which corrects the conflict condition. The same
 
 <p>Lists two or more options which conflict. The "resolver" string is a
 (possibly unique) keyword which specifies which options to change when the
-constraint exists. When no resolver is provided, a "revert to defaults"
-change is assumed - this type of constraint is typically only used for
-installable options.</p>
+constraint exists. When no resolver is provided, CUPS first tries the default
+choice followed by testing each option choice to resolve the conflict.</p>
 
 <p>Examples:</p>
 
@@ -403,6 +412,15 @@ installable options.</p>
 <em>*% Specify that 2-sided printing cannot happen on transparencies</em> 
 *cupsUIConstraints transparency: "*Duplex *MediaType Transparency"
 
+<em>*% Specify that envelope printing cannot happen from the paper trays</em> 
+*cupsUIConstraints envelope: "*PageSize Env10 *InputSlot Tray1"
+*cupsUIConstraints envelope: "*PageSize Env10 *InputSlot Tray1"
+*cupsUIConstraints envelope: "*PageSize EnvDL *InputSlot Tray2"
+*cupsUIConstraints envelope: "*PageSize EnvDL *InputSlot Tray2"
+
+<em>*% Specify an installable option constraint for the envelope feeder</em>
+*cupsUIConstraints: "*InputSlot EnvFeeder *InstalledEnvFeeder"
+
 <em>*% Specify that photo printing cannot happen on plain paper or transparencies at 1200dpi</em> 
 *cupsUIConstraints photo: "*OutputMode Photo *MediaType Plain *Resolution 1200dpi"
 *cupsUIConstraints photo: "*OutputMode Photo *MediaType Transparency *Resolution 1200dpi"
@@ -410,18 +428,29 @@ installable options.</p>
 
 <h3><span class='info'>CUPS 1.4</span><a name='cupsUIResolver'>cupsUIResolver</a></h3>
 
-<p class='summary'>*cupsUIResolution resolver: "*Keyword OptionKeyword ..."</p>
+<p class='summary'>*cupsUIResolution resolver: "*Keyword1 OptionKeyword1 *Keyword2 OptionKeyword2 ..."</p>
 
-<p>Specifies one or more options to mark/select to resolve a constraint. The
+<p>Specifies two or more options to mark/select to resolve a constraint. The
 "resolver" string identifies a particular action to take for one or more
 <a href='#cupsUIConstraints'><tt>cupsUIConstraints</tt></a>. The same action
-can be used for multiple constraints.</p>
+can be used for multiple constraints. The option keyword pairs are treated as
+an ordered list of option selections to try - only the first N selections will
+be used, where N is the minimum number of selections required. Because
+<a href="api-ppd.html#cupsResolveConflicts"><code>cupsResolveConflicts()</code></a>
+will not change the most recent option selection passed to it, at least two
+options from the constraints must be listed to avoid situations where conflicts
+cannot be resolved.</p>
 
 <p>Examples:</p>
 
 <pre class='command'>
-<em>*% Specify the option to change for the 2-sided transparency constraint</em> 
-*cupsUIResolver transparency: "*Duplex None"
+<em>*% Specify the options to change for the 2-sided transparency constraint</em> 
+*cupsUIResolver transparency: "*Duplex None *MediaType Plain"
+
+<em>*% Specify the options to change for the envelope printing constraints.  Notice
+*% that we try to change the InputSlot to either the envelope feeder or the
+*% manual feed first, then we change the page size...</em>
+*cupsUIResolver envelope: "*InputSlot EnvFeeder *InputSlot ManualFeed *PageSize Letter"
 
 <em>*% Specify the options to change for the photo printing constraints</em> 
 *cupsUIResolver photo: "*OutputMode Best *Resolution 600dpi"
index a89ca293f4d327fd77c2d54740dc774930f76126..2111f79f0e0e3fb80bb6d9e28a0391df2b6afc1b 100644 (file)
@@ -11,11 +11,13 @@ commandtopclx.o: ../cups/string.h ../config.h ../data/pcl.h
 rastertoescpx.o: driver.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 rastertoescpx.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 rastertoescpx.o: ../cups/file.h ../cups/language.h ../cups/raster.h
-rastertoescpx.o: ../cups/string.h ../config.h ../data/escp.h
+rastertoescpx.o: ../cups/i18n.h ../cups/transcode.h ../cups/string.h
+rastertoescpx.o: ../config.h ../data/escp.h
 rastertopclx.o: driver.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 rastertopclx.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 rastertopclx.o: ../cups/file.h ../cups/language.h ../cups/raster.h
-rastertopclx.o: pcl-common.h ../cups/string.h ../config.h ../data/pcl.h
+rastertopclx.o: ../cups/i18n.h ../cups/transcode.h ../cups/string.h
+rastertopclx.o: ../config.h pcl-common.h ../data/pcl.h
 pcl-common.o: driver.h ../cups/cups.h ../cups/ipp.h ../cups/http.h
 pcl-common.o: ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 pcl-common.o: ../cups/file.h ../cups/language.h ../cups/raster.h pcl-common.h
index 337c57e0d608e6e17793524ac1a272cac88f2105..9bd428d9f62911224929a6248548cae063d6eca3 100644 (file)
 .\"   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 cupsfilter 8 "Common UNIX Printing System" "10 September 2008" "Apple Inc."
+.TH cupsfilter 8 "Common UNIX Printing System" "26 February 2009" "Apple Inc."
 .SH NAME
 cupsfilter \- convert a file to another format using cups filters
 .SH SYNOPSIS
 .B cupsfilter
 [ -c
 .I config-file
-] -j
+] [ -e ] -j
 .I job-id[,N]
 [ -m
 .I mime/type
@@ -42,6 +42,10 @@ through CUPS. By default, \fIcupsfilter\fR generates a PDF file.
 .br
 Uses the named cupsd.conf configuration file.
 .TP 5
+-e
+.br
+Use every filter from the PPD file.
+.TP 5
 -j job-id[,N]
 .br
 Converts document N from the specified job. If N is omitted, document 1 is
index 4757c5d72ea4c3925ed1984dd2b3e32bbd0aefca..fd2b878b5659811ae0cc793c2150ed6d516681bc 100644 (file)
@@ -12,7 +12,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 cupstestppd 1 "Common UNIX Printing System" "3 May 2007" "Apple Inc."
+.TH cupstestppd 1 "Common UNIX Printing System" "2 March 2009" "Apple Inc."
 .SH NAME
 cupstestppd \- test conformance of ppd files
 .SH SYNOPSIS
@@ -63,6 +63,10 @@ Report all filter errors as warnings.
 .br
 Report all profile errors as warnings.
 .TP 5
+-W sizes
+.br
+Report all media size errors as warnings.
+.TP 5
 -W translations
 .br
 Report all translation errors as warnings.
index e9d8df1f079e23930803ce464e02cf9a59acf971..8da2d96169b69f15c42638ac83dc1087e4c8defc 100644 (file)
@@ -152,8 +152,10 @@ typedef void (*cupsd_selfunc_t)(void *data);
  * Globals...
  */
 
-VAR int                        TestConfigFile  VALUE(0);
+VAR int                        TestConfigFile  VALUE(0),
                                        /* Test the cupsd.conf file? */
+                       UseProfiles     VALUE(1);
+                                       /* Use security profiles for child procs? */
 VAR int                        MaxFDs          VALUE(0);
                                        /* Maximum number of files */
 
index d3c30210a8d261d37f0761cc789278811adf1e04..17f6f89ea8eb924b3df9cd33fbe9292e7a948e1a 100644 (file)
@@ -86,7 +86,8 @@ static int            compare_pids(mime_filter_t *a, mime_filter_t *b);
 static char            *escape_options(int num_options, cups_option_t *options);
 static int             exec_filter(const char *filter, char **argv,
                                    char **envp, int infd, int outfd);
-static int             exec_filters(cups_array_t *filters, const char *infile,
+static int             exec_filters(mime_type_t *srctype,
+                                    cups_array_t *filters, const char *infile,
                                     const char *outfile, const char *ppdfile,
                                     const char *printer, const char *user,
                                     const char *title, int num_options,
@@ -133,7 +134,8 @@ main(int  argc,                             /* I - Number of command-line args */
   const char   *ppdfile;               /* PPD file */
   const char   *title,                 /* Title string */
                *user;                  /* Username */
-  int          removeppd,              /* Remove PPD file */
+  int          all_filters,            /* Use all filters */
+               removeppd,              /* Remove PPD file */
                removeinfile;           /* Remove input file */
   int          status;                 /* Execution status */
 
@@ -159,6 +161,7 @@ main(int  argc,                             /* I - Number of command-line args */
   ppdfile      = NULL;
   title        = NULL;
   user         = cupsUser();
+  all_filters  = 0;
   removeppd    = 0;
   removeinfile = 0;
 
@@ -213,6 +216,10 @@ main(int  argc,                            /* I - Number of command-line args */
              removeinfile = 1;
              break;
 
+          case 'e' : /* Use every filter from the PPD file */
+             all_filters = 1;
+             break;
+
           case 'f' : /* Specify input file... */
              i ++;
              if (i < argc && !infile)
@@ -380,8 +387,16 @@ main(int  argc,                            /* I - Number of command-line args */
     return (1);
   }
 
-  printer_type = add_printer_filters(command, mime, printer, ppdfile,
-                                     &prefilter_type);
+  if (all_filters)
+  {
+    printer_type = add_printer_filters(command, mime, printer, ppdfile,
+                                      &prefilter_type);
+  }
+  else
+  {
+    printer_type   = mimeType(mime, "application", "vnd.cups-postscript");
+    prefilter_type = NULL;
+  }
 
  /*
   * Get the source and destination types...
@@ -429,6 +444,8 @@ main(int  argc,                             /* I - Number of command-line args */
 
     filters = cupsArrayNew(NULL, NULL);
     cupsArrayAdd(filters, &GZIPFilter);
+    GZIPFilter.src = src;
+    GZIPFilter.dst = dst;
   }
   else if ((filters = mimeFilter(mime, src, dst, &cost)) == NULL)
   {
@@ -456,7 +473,8 @@ main(int  argc,                             /* I - Number of command-line args */
         filter;
         filter = (mime_filter_t *)cupsArrayNext(filters))
     {
-      if ((prefilter = mimeFilterLookup(mime, filter->src, prefilter_type)))
+      if ((prefilter = mimeFilterLookup(mime, filter->src,
+                                        prefilter_type)) != NULL)
        cupsArrayAdd(prefilters, prefilter);
 
       cupsArrayAdd(prefilters, filter);
@@ -470,7 +488,7 @@ main(int  argc,                             /* I - Number of command-line args */
   * Do it!
   */
 
-  status = exec_filters(filters, infile, outfile, ppdfile, printer, user,
+  status = exec_filters(src, filters, infile, outfile, ppdfile, printer, user,
                         title, num_options, options);
 
  /*
@@ -610,6 +628,8 @@ add_printer_filters(
       if (ppdattr->value)
        add_printer_filter(command, mime, *prefilter_type, ppdattr->value);
   }
+  else
+    *prefilter_type = NULL;
 
   return (printer_type);
 }
@@ -789,7 +809,8 @@ exec_filter(const char *filter,             /* I - Filter to execute */
  */
 
 static int                             /* O - 0 on success, 1 on error */
-exec_filters(cups_array_t  *filters,   /* I - Array of filters to run */
+exec_filters(mime_type_t   *srctype,   /* I - Source type */
+             cups_array_t  *filters,   /* I - Array of filters to run */
              const char    *infile,    /* I - File to filter */
             const char    *outfile,    /* I - File to create */
             const char    *ppdfile,    /* I - PPD file, if any */
@@ -833,9 +854,8 @@ exec_filters(cups_array_t  *filters,        /* I - Array of filters to run */
 
   optstr = escape_options(num_options, options);
 
-  filter = cupsArrayFirst(filters);
   snprintf(content_type, sizeof(content_type), "CONTENT_TYPE=%s/%s",
-           filter->src->super, filter->src->type);
+           srctype->super, srctype->type);
   snprintf(cups_datadir, sizeof(cups_datadir), "CUPS_DATADIR=%s", DataDir);
   snprintf(cups_fontpath, sizeof(cups_fontpath), "CUPS_FONTPATH=%s", FontPath);
   snprintf(cups_serverbin, sizeof(cups_serverbin), "CUPS_SERVERBIN=%s",
@@ -1285,6 +1305,7 @@ usage(const char *command,                /* I - Command name */
                    "Options:\n"
                    "\n"
                    "  -c cupsd.conf    Set cupsd.conf file to use\n"
+                   "  -e               Use every filter from the PPD file\n"
                    "  -j job-id[,N]    Filter file N from the specified job (default is file 1)\n"
                    "  -n copies        Set number of copies\n"
                    "  -o name=value    Set option(s)\n"
@@ -1296,6 +1317,7 @@ usage(const char *command,                /* I - Command name */
                    "\n"
                    "Options:\n"
                    "\n"
+                   "  -e                   Use every filter from the PPD file\n"
                    "  -f filename          Set file to be converted (otherwise stdin)\n"
                    "  -o filename          Set file to be generated (otherwise stdout)\n"
                    "  -i mime/type         Set input MIME type (otherwise auto-typed)\n"
index 3fc1f33b0c81f53538faeef6d2c592deb69a709d..c0160e2e9effcce3cce4168d66342df0321cef88 100644 (file)
@@ -360,7 +360,8 @@ cupsdProcessIPPRequest(
       */
 
       attr = con->request->attrs;
-      if (attr && !strcmp(attr->name, "attributes-charset") &&
+      if (attr && attr->name &&
+          !strcmp(attr->name, "attributes-charset") &&
          (attr->value_tag & IPP_TAG_MASK) == IPP_TAG_CHARSET)
        charset = attr;
       else
@@ -369,7 +370,8 @@ cupsdProcessIPPRequest(
       if (attr)
         attr = attr->next;
 
-      if (attr && !strcmp(attr->name, "attributes-natural-language") &&
+      if (attr && attr->name &&
+          !strcmp(attr->name, "attributes-natural-language") &&
          (attr->value_tag & IPP_TAG_MASK) == IPP_TAG_LANGUAGE)
        language = attr;
       else
index 25ddffd9fcf27b56139de6cc883b976d25f24c5f..cd185c4739ac641784542dab41d1c98eb3614e49 100644 (file)
@@ -22,7 +22,6 @@
  *   cupsdCleanJobs()           - Clean out old jobs.
  *   cupsdContinueJob()         - Continue printing with the next file in a job.
  *   cupsdDeleteJob()           - Free all memory used by a job.
- *   cupsdFinishJob()           - Finish a job.
  *   cupsdFreeAllJobs()         - Free all jobs from memory.
  *   cupsdFindJob()             - Find the specified job.
  *   cupsdGetPrinterJobCount()  - Get the number of pending, processing, or held
@@ -491,7 +490,7 @@ cupsdContinueJob(cupsd_job_t *job)  /* I - Job */
 
   FilterLevel -= job->cost;
 
-  filters   = NULL;
+  filters = NULL;
 
   if (job->printer->raw)
   {
@@ -827,7 +826,7 @@ cupsdContinueJob(cupsd_job_t *job)  /* I - Job */
         * Just the language code (ll)...
        */
 
-        snprintf(lang, sizeof(lang), "LANG=%s.UTF8",
+        snprintf(lang, sizeof(lang), "LANG=%s.UTF-8",
                 attr->values[0].string.text);
         break;
 
@@ -836,7 +835,7 @@ cupsdContinueJob(cupsd_job_t *job)  /* I - Job */
         * Language and country code (ll-cc)...
        */
 
-        snprintf(lang, sizeof(lang), "LANG=%c%c_%c%c.UTF8",
+        snprintf(lang, sizeof(lang), "LANG=%c%c_%c%c.UTF-8",
                 attr->values[0].string.text[0],
                 attr->values[0].string.text[1],
                 toupper(attr->values[0].string.text[3] & 255),
@@ -2481,9 +2480,40 @@ finalize_job(cupsd_job_t *job)           /* I - Job */
   * Process the exit status...
   */
 
-  printer_state = IPP_PRINTER_IDLE;
-  job_state     = IPP_JOB_COMPLETED;
-  message       = "Job completed.";
+  if (job->printer->state == IPP_PRINTER_PROCESSING)
+    printer_state = IPP_PRINTER_IDLE;
+  else
+    printer_state = job->printer->state;
+
+  switch (job_state = job->state_value)
+  {
+    case IPP_JOB_PENDING :
+        message = "Job paused.";
+       break;
+
+    case IPP_JOB_HELD :
+        message = "Job held.";
+       break;
+
+    default :
+    case IPP_JOB_PROCESSING :
+    case IPP_JOB_COMPLETED :
+       job_state     = IPP_JOB_COMPLETED;
+       message       = "Job completed.";
+        break;
+
+    case IPP_JOB_STOPPED :
+        message = "Job stopped.";
+       break;
+
+    case IPP_JOB_CANCELED :
+        message = "Job canceled.";
+       break;
+
+    case IPP_JOB_ABORTED :
+        message = "Job aborted.";
+       break;
+  }
 
   if (job->status < 0)
   {
@@ -2741,8 +2771,8 @@ get_options(cupsd_job_t *job,             /* I - Job */
   optptr  = options;
   *optptr = '\0';
 
-  snprintf(title, sizeof(title), "%s-%d", job->printer->name, job->id);
-  strcpy(copies, "1");
+  snprintf(title, title_size, "%s-%d", job->printer->name, job->id);
+  strlcpy(copies, "1", copies_size);
 
   for (attr = job->attrs->attrs; attr != NULL; attr = attr->next)
   {
@@ -2754,12 +2784,12 @@ get_options(cupsd_job_t *job,           /* I - Job */
       */
 
       if (!banner_page)
-        sprintf(copies, "%d", attr->values[0].integer);
+        snprintf(copies, copies_size, "%d", attr->values[0].integer);
     }
     else if (!strcmp(attr->name, "job-name") &&
             (attr->value_tag == IPP_TAG_NAME ||
              attr->value_tag == IPP_TAG_NAMELANG))
-      strlcpy(title, attr->values[0].string.text, sizeof(title));
+      strlcpy(title, attr->values[0].string.text, title_size);
     else if (attr->group_tag == IPP_TAG_JOB)
     {
      /*
@@ -3494,10 +3524,11 @@ start_job(cupsd_job_t     *job,         /* I - Job ID */
   cupsdSetJobState(job, IPP_JOB_PROCESSING, CUPSD_JOB_DEFAULT, NULL);
   cupsdSetPrinterState(printer, IPP_PRINTER_PROCESSING, 0);
 
-  job->cost     = 0;
-  job->progress = 0;
-  job->printer  = printer;
-  printer->job  = job;
+  job->cost         = 0;
+  job->current_file = 0;
+  job->progress     = 0;
+  job->printer      = printer;
+  printer->job      = job;
 
  /*
   * Setup the last exit status and security profiles...
index 437f0f5ba57c08725e0be02da34d05fb93c0a912..ccc3952114a278f55f456c179bb94e45a0677efe 100644 (file)
@@ -145,8 +145,9 @@ main(int  argc,                             /* I - Number of command-line args */
   struct stat          statbuf;        /* Needed for checking lpsched FIFO */
 #endif /* __sgi */
 #ifdef __APPLE__
-  int                  run_as_child = 0;
+  int                  run_as_child = 0,
                                        /* Needed for Mac OS X fork/exec */
+                       use_sysman = 1; /* Use system management functions? */
 #else
   time_t               netif_time = 0; /* Time since last network update */
 #endif /* __APPLE__ */
@@ -188,6 +189,11 @@ main(int  argc,                            /* I - Number of command-line args */
         switch (*opt)
        {
 #ifdef __APPLE__
+          case 'S' : /* Disable system management functions */
+              puts("Warning: -S (disable system management) for internal testing use only!");
+             use_sysman = 0;
+             break;
+
          case 'C' : /* Run as child with config file */
               run_as_child = 1;
              fg           = -1;
@@ -270,11 +276,16 @@ main(int  argc,                           /* I - Number of command-line args */
              break;
 
           case 'p' : /* Stop immediately for profiling */
-              puts("Warning: -p option is for internal testing use only!");
+              puts("Warning: -p (startup profiling) is for internal testing use only!");
              stop_scheduler = 1;
              fg             = 1;
              break;
 
+          case 'P' : /* Disable security profiles */
+              puts("Warning: -P (disable security profiles) is for internal testing use only!");
+             UseProfiles = 0;
+             break;
+
           case 't' : /* Test the cupsd.conf file... */
              TestConfigFile = 1;
              fg             = 1;
@@ -630,7 +641,8 @@ main(int  argc,                             /* I - Number of command-line args */
   * Start power management framework...
   */
 
-  cupsdStartSystemMonitor();
+  if (use_sysman)
+    cupsdStartSystemMonitor();
 #endif /* __APPLE__ */
 
  /*
@@ -1149,7 +1161,8 @@ main(int  argc,                           /* I - Number of command-line args */
   * Stop monitoring system event monitoring...
   */
 
-  cupsdStopSystemMonitor();
+  if (use_sysman)
+    cupsdStopSystemMonitor();
 #endif /* __APPLE__ */
 
 #ifdef HAVE_GSSAPI
@@ -1742,6 +1755,7 @@ process_children(void)
            cupsdContinueJob(job);
          }
        }
+       break;
       }
     }
 
index c826120f19b665e9aec5b1411a806e385799763b..47142db2bd4f933b621a86f4c823f876eca47250 100644 (file)
@@ -2015,7 +2015,7 @@ cupsdSetPrinterAttr(
   * Don't allow empty values...
   */
 
-  if (!*value)
+  if (!*value && strcmp(name, "marker-message"))
   {
     cupsdLogMessage(CUPSD_LOG_ERROR, "Ignoring empty \"%s\" attribute", name);
     return;
@@ -2736,10 +2736,6 @@ cupsdSetPrinterReasons(
          * Found a match, so remove it...
          */
 
-         cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                         "cupsdSetPrinterReasons: Removing \"%s\" at index %d",
-                         reason, i);
-
          p->num_reasons --;
          _cupsStrFree(p->reasons[i]);
 
@@ -2779,10 +2775,6 @@ cupsdSetPrinterReasons(
           return;
         }
 
-       cupsdLogMessage(CUPSD_LOG_DEBUG2,
-                       "cupsdSetPrinterReasons: Adding \"%s\" at index %d",
-                       reason, i);
-
         p->reasons[i] = _cupsStrAlloc(reason);
        p->num_reasons ++;
 
index bd548ff06c5383d27cd3c56b5415a392e7b2b033..45d3bcfb6ab445232076cc862cedf6db22361f79 100644 (file)
@@ -83,7 +83,7 @@ cupsdCreateProfile(int job_id)                /* I - Job ID or 0 for none */
                temp[1024];             /* Quoted TempDir */
 
 
-  if (RunUser)
+  if (!UseProfiles || RunUser)
   {
    /*
     * Only use sandbox profiles as root...
index 79765c4b9b1dd404c8ee8e8bd3bf10bce9bad4e4..f0b18081377fa47135f7f552a23c9ead5731ba16 100644 (file)
@@ -23,8 +23,8 @@ cupstestdsc.o: ../cups/file.h ../cups/i18n.h ../cups/transcode.h
 cupstestppd.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
 cupstestppd.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h
 cupstestppd.o: ../cups/array.h ../cups/file.h ../cups/language.h
-cupstestppd.o: ../cups/ppd-private.h ../cups/cups.h ../cups/i18n.h
-cupstestppd.o: ../cups/transcode.h ../cups/raster.h
+cupstestppd.o: ../cups/dir.h ../cups/ppd-private.h ../cups/cups.h
+cupstestppd.o: ../cups/i18n.h ../cups/transcode.h ../cups/raster.h
 lp.o: ../cups/string.h ../config.h ../cups/cups.h ../cups/ipp.h
 lp.o: ../cups/http.h ../cups/versioning.h ../cups/ppd.h ../cups/array.h
 lp.o: ../cups/file.h ../cups/language.h ../cups/i18n.h ../cups/transcode.h
index 855c17fbff7d9353cf871a70ffe8a1dd78e140be..4a619ebcad57a03c800dbe6dafacaf290ef8ca7c 100644 (file)
@@ -3,7 +3,7 @@
  *
  *   PPD test program for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007-2008 by Apple Inc.
+ *   Copyright 2007-2009 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
  *   main()               - Main entry for test program.
  *   check_basics()       - Check for CR LF, mixed line endings, and blank
  *                          lines.
+ *   check_constraints()  - Check UIConstraints in the PPD file.
  *   check_case()         - Check that there are no duplicate groups, options,
  *                          or choices that differ only by case.
- *   check_constraints()  - Check UIConstraints in the PPD file.
  *   check_defaults()     - Check default option keywords in the PPD file.
  *   check_duplex()       - Check duplex keywords in the PPD file.
  *   check_filters()      - Check filters in the PPD file.
  *   check_profiles()     - Check ICC color profiles in the PPD file.
+ *   check_sizes()        - Check media sizes in the PPD file.
  *   check_translations() - Check translations in the PPD file.
  *   show_conflicts()     - Show option conflicts in a PPD file.
  *   test_raster()        - Test PostScript commands for raster printers.
  *   usage()              - Show program usage...
+ *   valid_path()         - Check whether a path has the correct capitalization.
  *   valid_utf8()         - Check whether a string contains valid UTF-8 text.
  */
 
 
 #include <cups/string.h>
 #include <cups/cups.h>
+#include <cups/dir.h>
 #include <cups/ppd-private.h>
 #include <cups/i18n.h>
 #include <cups/raster.h>
 #include <errno.h>
 #include <stdlib.h>
-#include <sys/stat.h>
+#include <math.h>
 
 
 /*
@@ -62,7 +65,8 @@ enum
   WARN_PROFILES = 8,
   WARN_TRANSLATIONS = 16,
   WARN_DUPLEX = 32,
-  WARN_ALL = 63
+  WARN_SIZES = 64,
+  WARN_ALL = 127
 };
 
 
@@ -93,6 +97,168 @@ enum
 };
 
 
+/*
+ * Standard Adobe media keywords (must remain sorted)...
+ */
+
+static const char adobe_size_names[][PPD_MAX_NAME] =
+{
+  "10x11",
+  "10x13",
+  "10x14",
+  "12x11",
+  "15x11",
+  "7x9",
+  "8x10",
+  "9x11",
+  "9x12",
+  "A0",
+  "A1",
+  "A10",
+  "A2",
+  "A3",
+  "A3Extra",
+  "A3Rotated",
+  "A4",
+  "A4Extra",
+  "A4Plus",
+  "A4Rotated",
+  "A4Small",
+  "A5",
+  "A5Extra",
+  "A5Rotated",
+  "A6",
+  "A6Rotated",
+  "A7",
+  "A8",
+  "A9",
+  "ARCHA",
+  "ARCHB",
+  "ARCHC",
+  "ARCHD",
+  "ARCHE",
+  "AnsiA",
+  "AnsiB",
+  "AnsiC",
+  "AnsiD",
+  "AnsiE",
+  "B0",
+  "B1",
+  "B1",
+  "B10",
+  "B2",
+  "B3",
+  "B4",
+  "B4Rotated",
+  "B5",
+  "B5Rotated",
+  "B6",
+  "B6Rotated",
+  "B7",
+  "B8",
+  "B9",
+  "C4",
+  "C5",
+  "C6",
+  "DL",
+  "DoublePostcard",
+  "DoublePostcardRotated",
+  "Env10",
+  "Env11",
+  "Env12",
+  "Env14",
+  "Env9",
+  "EnvC0",
+  "EnvC1",
+  "EnvC2",
+  "EnvC3",
+  "EnvC4",
+  "EnvC5",
+  "EnvC6",
+  "EnvC65",
+  "EnvC7",
+  "EnvChou3",
+  "EnvChou3Rotated",
+  "EnvChou4",
+  "EnvChou4Rotated",
+  "EnvDL",
+  "EnvISOB4",
+  "EnvISOB5",
+  "EnvISOB6",
+  "EnvInvite",
+  "EnvItalian",
+  "EnvKaku2",
+  "EnvKaku2Rotated",
+  "EnvKaku3",
+  "EnvKaku3Rotated",
+  "EnvMonarch",
+  "EnvPRC1",
+  "EnvPRC10",
+  "EnvPRC10Rotated",
+  "EnvPRC1Rotated",
+  "EnvPRC2",
+  "EnvPRC2Rotated",
+  "EnvPRC3",
+  "EnvPRC3Rotated",
+  "EnvPRC4",
+  "EnvPRC4Rotated",
+  "EnvPRC5",
+  "EnvPRC5Rotated",
+  "EnvPRC6",
+  "EnvPRC6Rotated",
+  "EnvPRC7",
+  "EnvPRC7Rotated",
+  "EnvPRC8",
+  "EnvPRC8Rotated",
+  "EnvPRC9",
+  "EnvPRC9Rotated",
+  "EnvPersonal",
+  "EnvYou4",
+  "EnvYou4Rotated",
+  "Executive",
+  "FanFoldGerman",
+  "FanFoldGermanLegal",
+  "FanFoldUS",
+  "Folio",
+  "ISOB0",
+  "ISOB1",
+  "ISOB10",
+  "ISOB2",
+  "ISOB3",
+  "ISOB4",
+  "ISOB5",
+  "ISOB5Extra",
+  "ISOB6",
+  "ISOB7",
+  "ISOB8",
+  "ISOB9",
+  "Ledger",
+  "Legal",
+  "LegalExtra",
+  "Letter",
+  "LetterExtra",
+  "LetterPlus",
+  "LetterRotated",
+  "LetterSmall",
+  "Monarch",
+  "Note",
+  "PRC16K",
+  "PRC16KRotated",
+  "PRC32K",
+  "PRC32KBig",
+  "PRC32KBigRotated",
+  "PRC32KRotated",
+  "Postcard",
+  "PostcardRotated",
+  "Quarto",
+  "Statement",
+  "SuperA",
+  "SuperB",
+  "Tabloid",
+  "TabloidExtra"
+};
+
+
 /*
  * Local functions...
  */
@@ -109,11 +275,14 @@ static int        check_filters(ppd_file_t *ppd, const char *root, int errors,
                              int verbose, int warn);
 static int     check_profiles(ppd_file_t *ppd, const char *root, int errors,
                               int verbose, int warn);
-static int     check_translations(ppd_file_t *ppd, int errors, int verbose,\
+static int     check_sizes(ppd_file_t *ppd, int errors, int verbose, int warn);
+static int     check_translations(ppd_file_t *ppd, int errors, int verbose,
                                   int warn);
 static void    show_conflicts(ppd_file_t *ppd);
 static int     test_raster(ppd_file_t *ppd, int verbose);
 static void    usage(void);
+static int     valid_path(const char *keyword, const char *path, int errors,
+                          int verbose, int warn);
 static int     valid_utf8(const char *s);
 
 
@@ -203,6 +372,8 @@ main(int  argc,                             /* I - Number of command-line args */
                warn |= WARN_FILTERS;
              else if (!strcmp(argv[i], "profiles"))
                warn |= WARN_PROFILES;
+             else if (!strcmp(argv[i], "sizes"))
+               warn |= WARN_SIZES;
              else if (!strcmp(argv[i], "translations"))
                warn |= WARN_TRANSLATIONS;
              else if (!strcmp(argv[i], "all"))
@@ -1088,6 +1259,9 @@ main(int  argc,                           /* I - Number of command-line args */
       if (!(warn & WARN_PROFILES))
         errors = check_profiles(ppd, root, errors, verbose, 0);
 
+      if (!(warn & WARN_SIZES))
+       errors = check_sizes(ppd, errors, verbose, 0);
+
       if (!(warn & WARN_TRANSLATIONS))
         errors = check_translations(ppd, errors, verbose, 0);
 
@@ -1222,6 +1396,11 @@ main(int  argc,                          /* I - Number of command-line args */
        if (warn & WARN_FILTERS)
          errors = check_filters(ppd, root, errors, verbose, 1);
 
+        if (warn & WARN_SIZES)
+         errors = check_sizes(ppd, errors, verbose, 1);
+        else
+         errors = check_sizes(ppd, errors, verbose, 2);
+
        if (warn & WARN_TRANSLATIONS)
          errors = check_translations(ppd, errors, verbose, 1);
 
@@ -1384,36 +1563,6 @@ main(int  argc,                          /* I - Number of command-line args */
          }
       }
 
-#ifdef __APPLE__
-     /*
-      * APDialogExtension
-      */
-
-      for (attr = ppdFindAttr(ppd, "APDialogExtension", NULL); 
-          attr != NULL; 
-          attr = ppdFindNextAttr(ppd, "APDialogExtension", NULL))
-      {
-       if ((!attr->value || access(attr->value, 0)) && verbose >= 0)
-         _cupsLangPrintf(stdout, _("        WARN    Missing "
-                                   "APDialogExtension file \"%s\"\n"),
-                         attr->value ? attr->value : "<NULL>");
-      }
-
-     /*
-      * APPrinterIconPath
-      */
-
-      for (attr = ppdFindAttr(ppd, "APPrinterIconPath", NULL); 
-          attr != NULL; 
-          attr = ppdFindNextAttr(ppd, "APPrinterIconPath", NULL))
-      {
-       if ((!attr->value || access(attr->value, 0)) && verbose >= 0)
-         _cupsLangPrintf(stdout, _("        WARN    Missing "
-                                   "APPrinterIconPath file \"%s\"\n"),
-                         attr->value ? attr->value : "<NULL>");
-      }
-#endif /* __APPLE__ */
-
       if (verbose > 0)
       {
         if (errors)
@@ -1858,6 +2007,24 @@ check_constraints(ppd_file_t *ppd,       /* I - PPD file */
        }
       }
 
+     /*
+      * Resolvers must list at least two options...
+      */
+
+      if (num_options < 2)
+      {
+       if (!warn && !errors && !verbose)
+         _cupsLangPuts(stdout, _(" FAIL\n"));
+
+       _cupsLangPrintf(stdout,
+                       _("      %s  cupsUIResolver %s does not list at least "
+                         "two different options!\n"),
+                       prefix, constattr->spec);
+
+       if (!warn)
+         errors ++;
+      }
+
      /*
       * Test the resolver...
       */
@@ -2245,6 +2412,10 @@ check_filters(ppd_file_t *ppd,           /* I - PPD file */
 
   prefix = warn ? "  WARN  " : "**FAIL**";
 
+ /*
+  * cupsFilter
+  */
+
   for (i = 0; i < ppd->num_filters; i ++)
   {
     if (sscanf(ppd->filters[i], "%15[^/]/%255s%d%*[ \t]%1023[^\n]", super, type,
@@ -2290,9 +2461,15 @@ check_filters(ppd_file_t *ppd,           /* I - PPD file */
        if (!warn)
          errors ++;
       }
+      else
+        errors = valid_path("cupsFilter", pathprog, errors, verbose, warn);
     }
   }
 
+ /*
+  * cupsPreFilter
+  */
+
   for (attr = ppdFindAttr(ppd, "cupsPreFilter", NULL);
        attr;
        attr = ppdFindNextAttr(ppd, "cupsPreFilter", NULL))
@@ -2341,8 +2518,110 @@ check_filters(ppd_file_t *ppd,          /* I - PPD file */
         if (!warn)
          errors ++;
       }
+      else
+        errors = valid_path("cupsPreFilter", pathprog, errors, verbose, warn);
+    }
+  }
+
+#ifdef __APPLE__
+ /*
+  * APDialogExtension
+  */
+
+  for (attr = ppdFindAttr(ppd, "APDialogExtension", NULL); 
+       attr != NULL; 
+       attr = ppdFindNextAttr(ppd, "APDialogExtension", NULL))
+  {
+    if (!attr->value || access(attr->value, 0))
+    {
+      if (!warn && !errors && !verbose)
+       _cupsLangPuts(stdout, _(" FAIL\n"));
+
+      if (verbose >= 0)
+       _cupsLangPrintf(stdout, _("      %s  Missing "
+                                 "APDialogExtension file \"%s\"\n"),
+                       prefix, attr->value ? attr->value : "<NULL>");
+
+      if (!warn)
+       errors ++;
+    }
+    else
+      errors = valid_path("APDialogExtension", attr->value, errors, verbose,
+                          warn);
+  }
+
+ /*
+  * APPrinterIconPath
+  */
+
+  if ((attr = ppdFindAttr(ppd, "APPrinterIconPath", NULL)) != NULL)
+  {
+    if (!attr->value || access(attr->value, 0))
+    {
+      if (!warn && !errors && !verbose)
+       _cupsLangPuts(stdout, _(" FAIL\n"));
+
+      if (verbose >= 0)
+       _cupsLangPrintf(stdout, _("      %s  Missing "
+                                 "APPrinterIconPath file \"%s\"\n"),
+                       prefix, attr->value ? attr->value : "<NULL>");
+
+      if (!warn)
+       errors ++;
+    }
+    else
+      errors = valid_path("APPrinterIconPath", attr->value, errors, verbose,
+                          warn);
+  }
+
+ /*
+  * APPrinterLowInkTool
+  */
+
+  if ((attr = ppdFindAttr(ppd, "APPrinterLowInkTool", NULL)) != NULL)
+  {
+    if (!attr->value || access(attr->value, 0))
+    {
+      if (!warn && !errors && !verbose)
+       _cupsLangPuts(stdout, _(" FAIL\n"));
+
+      if (verbose >= 0)
+       _cupsLangPrintf(stdout, _("      %s  Missing "
+                                 "APPrinterLowInkTool file \"%s\"\n"),
+                       prefix, attr->value ? attr->value : "<NULL>");
+
+      if (!warn)
+       errors ++;
+    }
+    else
+      errors = valid_path("APPrinterLowInkTool", attr->value, errors, verbose,
+                          warn);
+  }
+
+ /*
+  * APPrinterUtilityPath
+  */
+
+  if ((attr = ppdFindAttr(ppd, "APPrinterUtilityPath", NULL)) != NULL)
+  {
+    if (!attr->value || access(attr->value, 0))
+    {
+      if (!warn && !errors && !verbose)
+       _cupsLangPuts(stdout, _(" FAIL\n"));
+
+      if (verbose >= 0)
+       _cupsLangPrintf(stdout, _("      %s  Missing "
+                                 "APPrinterUtilityPath file \"%s\"\n"),
+                       prefix, attr->value ? attr->value : "<NULL>");
+
+      if (!warn)
+       errors ++;
     }
+    else
+      errors = valid_path("APPrinterUtilityPath", attr->value, errors, verbose,
+                          warn);
   }
+#endif /* __APPLE__ */
 
   return (errors);
 }
@@ -2430,6 +2709,8 @@ check_profiles(ppd_file_t *ppd,           /* I - PPD file */
       if (!warn)
        errors ++;
     }
+    else
+      errors = valid_path("cupsICCProfile", filename, errors, verbose, warn);
 
    /*
     * Check for hash collisions...
@@ -2475,6 +2756,158 @@ check_profiles(ppd_file_t *ppd,         /* I - PPD file */
 }
 
 
+/*
+ * 'check_sizes()' - Check media sizes in the PPD file.
+ */
+
+static int                             /* O - Errors found */
+check_sizes(ppd_file_t *ppd,           /* I - PPD file */
+           int        errors,          /* I - Errors found */
+           int        verbose,         /* I - Verbosity level */
+           int        warn)            /* I - Warnings only? */
+{
+  int          i;                      /* Looping vars */
+  ppd_size_t   *size;                  /* Current size */
+  int          width,                  /* Custom width */
+               length;                 /* Custom length */
+  char         name[PPD_MAX_NAME],     /* Size name without dot suffix */
+               *nameptr;               /* Pointer into name */
+  const char   *prefix;                /* WARN/FAIL prefix */
+  ppd_option_t *page_size,             /* PageSize option */
+               *page_region;           /* PageRegion option */
+
+
+  prefix = warn ? "  WARN  " : "**FAIL**";
+
+  if ((page_size = ppdFindOption(ppd, "PageSize")) == NULL && warn != 2)
+  {
+    if (!warn && !errors && !verbose)
+      _cupsLangPuts(stdout, _(" FAIL\n"));
+
+    if (verbose >= 0)
+      _cupsLangPrintf(stdout,
+                     _("      %s  Missing REQUIRED PageSize option!\n"
+                       "                REF: Page 99, section 5.14.\n"),
+                     prefix);
+
+    if (!warn)
+      errors ++;
+  }
+
+  if ((page_region = ppdFindOption(ppd, "PageRegion")) == NULL && warn != 2)
+  {
+    if (!warn && !errors && !verbose)
+      _cupsLangPuts(stdout, _(" FAIL\n"));
+
+    if (verbose >= 0)
+      _cupsLangPrintf(stdout,
+                     _("      %s  Missing REQUIRED PageRegion option!\n"
+                       "                REF: Page 100, section 5.14.\n"),
+                     prefix);
+
+    if (!warn)
+      errors ++;
+  }
+
+  for (i = ppd->num_sizes, size = ppd->sizes; i > 0; i --, size ++)
+  {
+   /*
+    * Check that the size name is standard...
+    */
+
+    if (!strcmp(size->name, "Custom"))
+    {
+     /*
+      * Skip custom page size...
+      */
+
+      continue;
+    }
+    else 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
+      * length...
+      */
+
+      if (fabs(width - size->width) >= 1.0 ||
+          fabs(length - size->length) >= 1.0)
+      {
+       if (!warn && !errors && !verbose)
+         _cupsLangPuts(stdout, _(" FAIL\n"));
+
+       if (verbose >= 0)
+         _cupsLangPrintf(stdout,
+                         _("      %s  Size \"%s\" has unexpected dimensions "
+                           "(%gx%g)!\n"),
+                         prefix, size->name, size->width, size->length);
+
+       if (!warn)
+         errors ++;
+      }
+    }
+    else if (warn && verbose >= 0)
+    {
+     /*
+      * Lookup the size name in the standard size table...
+      */
+
+      strlcpy(name, size->name, sizeof(name));
+      if ((nameptr = strchr(name, '.')) != NULL)
+        *nameptr = '\0';
+
+      if (!bsearch(name, adobe_size_names,
+                   sizeof(adobe_size_names) /
+                      sizeof(adobe_size_names[0]),
+                  sizeof(adobe_size_names[0]),
+                  (int (*)(const void *, const void *))strcmp))
+      {
+       _cupsLangPrintf(stdout,
+                       _("      %s  Non-standard size name \"%s\"!\n"
+                         "                REF: Page 187, section B.2.\n"),
+                       prefix, size->name);
+      }
+    }
+
+   /*
+    * Verify that the size is defined for both PageSize and PageRegion...
+    */
+
+    if (warn != 2 && !ppdFindChoice(page_size, size->name))
+    {
+      if (!warn && !errors && !verbose)
+       _cupsLangPuts(stdout, _(" FAIL\n"));
+
+      if (verbose >= 0)
+       _cupsLangPrintf(stdout,
+                       _("      %s  Size \"%s\" defined for %s but not for "
+                         "%s!\n"),
+                       prefix, size->name, "PageRegion", "PageSize");
+
+      if (!warn)
+       errors ++;
+    }
+    else if (warn != 2 && !ppdFindChoice(page_region, size->name))
+    {
+      if (!warn && !errors && !verbose)
+       _cupsLangPuts(stdout, _(" FAIL\n"));
+
+      if (verbose >= 0)
+       _cupsLangPrintf(stdout,
+                       _("      %s  Size \"%s\" defined for %s but not for "
+                         "%s!\n"),
+                       prefix, size->name, "PageSize", "PageRegion");
+
+      if (!warn)
+       errors ++;
+    }
+  }
+
+  return (errors);
+}
+
+
 /*
  * 'check_translations()' - Check translations in the PPD file.
  */
@@ -2933,7 +3366,7 @@ usage(void)
                  "\n"
                  "    -R root-directory    Set alternate root\n"
                  "    -W {all,none,constraints,defaults,duplex,filters,"
-                 "translations}\n"
+                 "profiles,sizes,translations}\n"
                  "                         Issue warnings instead of errors\n"
                  "    -q                   Run silently\n"
                  "    -r                   Use 'relaxed' open mode\n"
@@ -2944,6 +3377,89 @@ usage(void)
 }
 
 
+/*
+ * 'valid_path()' - Check whether a path has the correct capitalization.
+ */
+
+static int                             /* O - Errors found */
+valid_path(const char *keyword,                /* I - Keyword using path */
+           const char *path,           /* I - Path to check */
+          int        errors,           /* I - Errors found */
+          int        verbose,          /* I - Verbosity level */
+          int        warn)             /* I - Warnings only? */
+{
+  cups_dir_t   *dir;                   /* Current directory */
+  cups_dentry_t        *dentry;                /* Current directory entry */
+  char         temp[1024],             /* Temporary path */
+               *ptr;                   /* Pointer into temporary path */
+  const char   *prefix;                /* WARN/FAIL prefix */
+
+
+  prefix = warn ? "  WARN  " : "**FAIL**";
+
+ /*
+  * Loop over the components of the path, checking that the entry exists with
+  * the same capitalization...
+  */
+
+  strlcpy(temp, path, sizeof(temp));
+
+  while ((ptr = strrchr(temp, '/')) != NULL)
+  {
+   /*
+    * Chop off the trailing component so temp == dirname and ptr == basename.
+    */
+
+    *ptr++ = '\0';
+
+   /*
+    * Try opening the directory containing the base name...
+    */
+
+    if (temp[0])
+      dir = cupsDirOpen(temp);
+    else
+      dir = cupsDirOpen("/");
+
+    if (!dir)
+      dentry = NULL;
+    else
+    {
+      while ((dentry = cupsDirRead(dir)) != NULL)
+      {
+        if (!strcmp(dentry->filename, ptr))
+         break;
+      }
+
+      cupsDirClose(dir);
+    }
+
+   /*
+    * Display an error if the filename doesn't exist with the same
+    * capitalization...
+    */
+
+    if (!dentry)
+    {
+      if (!warn && !errors && !verbose)
+       _cupsLangPuts(stdout, _(" FAIL\n"));
+
+      if (verbose >= 0)
+       _cupsLangPrintf(stdout,
+                       _("      %s  %s file \"%s\" has the wrong "
+                         "capitalization!\n"), prefix, keyword, path);
+
+      if (!warn)
+       errors ++;
+
+      break;
+    }
+  }
+
+  return (errors);
+}
+
+
 /*
  * 'valid_utf8()' - Check whether a string contains valid UTF-8 text.
  */