diff options
author | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2009-03-07 16:36:03 +0000 |
---|---|---|
committer | msweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be> | 2009-03-07 16:36:03 +0000 |
commit | 1340db2dab0b5ac933dec4796637ca3baa10bb4b (patch) | |
tree | d6c9ec39af99e162ee755e6369b5c222d6349cd6 | |
parent | b9faaae17cfc7cd8dfd6e82cf607c05b2f4def68 (diff) |
Merge changes from CUPS 1.4svn-r8414.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@1277 a1ca3aef-8c08-0410-bb20-df032aa958be
-rw-r--r-- | CHANGES-1.3.txt | 5 | ||||
-rw-r--r-- | CHANGES.txt | 6 | ||||
-rw-r--r-- | backend/Makefile | 8 | ||||
-rw-r--r-- | backend/dnssd.c | 2 | ||||
-rw-r--r-- | backend/lpd.c | 2 | ||||
-rw-r--r-- | backend/socket.c | 2 | ||||
-rw-r--r-- | backend/testbackend.c | 10 | ||||
-rw-r--r-- | berkeley/lpq.c | 15 | ||||
-rw-r--r-- | cups/Makefile | 2 | ||||
-rw-r--r-- | cups/conflicts.c | 95 | ||||
-rw-r--r-- | cups/file.h | 1 | ||||
-rw-r--r-- | cups/test.ppd | 8 | ||||
-rw-r--r-- | cups/test2.ppd | 19 | ||||
-rw-r--r-- | cups/testppd.c | 19 | ||||
-rw-r--r-- | doc/help/spec-ppd.html | 49 | ||||
-rw-r--r-- | driver/Dependencies | 6 | ||||
-rw-r--r-- | man/cupsfilter.man | 8 | ||||
-rw-r--r-- | man/cupstestppd.man | 6 | ||||
-rw-r--r-- | scheduler/cupsd.h | 4 | ||||
-rw-r--r-- | scheduler/cupsfilter.c | 40 | ||||
-rw-r--r-- | scheduler/ipp.c | 6 | ||||
-rw-r--r-- | scheduler/job.c | 61 | ||||
-rw-r--r-- | scheduler/main.c | 22 | ||||
-rw-r--r-- | scheduler/printers.c | 10 | ||||
-rw-r--r-- | scheduler/process.c | 2 | ||||
-rw-r--r-- | systemv/Dependencies | 4 | ||||
-rw-r--r-- | systemv/cupstestppd.c | 588 |
27 files changed, 847 insertions, 153 deletions
diff --git a/CHANGES-1.3.txt b/CHANGES-1.3.txt index 8f4621f57..4a4147c1a 100644 --- a/CHANGES-1.3.txt +++ b/CHANGES-1.3.txt @@ -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) diff --git a/CHANGES.txt b/CHANGES.txt index c1cedc32f..ef8e6ff69 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -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. diff --git a/backend/Makefile b/backend/Makefile index 6ea05fdb2..807b4c4e6 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -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 # diff --git a/backend/dnssd.c b/backend/dnssd.c index 97c0d6071..f5687f3c3 100644 --- a/backend/dnssd.c +++ b/backend/dnssd.c @@ -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. diff --git a/backend/lpd.c b/backend/lpd.c index b39394c61..67a856a02 100644 --- a/backend/lpd.c +++ b/backend/lpd.c @@ -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"), diff --git a/backend/socket.c b/backend/socket.c index 09137f958..f3d20b9b4 100644 --- a/backend/socket.c +++ b/backend/socket.c @@ -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"), diff --git a/backend/testbackend.c b/backend/testbackend.c index e0f573ccd..74a0f1e5a 100644 --- a/backend/testbackend.c +++ b/backend/testbackend.c @@ -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); } diff --git a/berkeley/lpq.c b/berkeley/lpq.c index db089867e..50d240e12 100644 --- a/berkeley/lpq.c +++ b/berkeley/lpq.c @@ -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) { diff --git a/cups/Makefile b/cups/Makefile index bec16188f..31be2be31 100644 --- a/cups/Makefile +++ b/cups/Makefile @@ -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) diff --git a/cups/conflicts.c b/cups/conflicts.c index 4c90f169e..138a0c119 100644 --- a/cups/conflicts.c +++ b/cups/conflicts.c @@ -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"))) diff --git a/cups/file.h b/cups/file.h index c5eb357fa..c8a2b4667 100644 --- a/cups/file.h +++ b/cups/file.h @@ -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; diff --git a/cups/test.ppd b/cups/test.ppd index 35743b0a2..45473fdac 100644 --- a/cups/test.ppd +++ b/cups/test.ppd @@ -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 diff --git a/cups/test2.ppd b/cups/test2.ppd index fb32e4830..bd07c867b 100644 --- a/cups/test2.ppd +++ b/cups/test2.ppd @@ -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 @@ -40,25 +40,22 @@ *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 diff --git a/cups/testppd.c b/cups/testppd.c index 29565dec4..3a6bb8517 100644 --- a/cups/testppd.c +++ b/cups/testppd.c @@ -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; diff --git a/doc/help/spec-ppd.html b/doc/help/spec-ppd.html index 11ff4a4cf..fe4b0cfd8 100644 --- a/doc/help/spec-ppd.html +++ b/doc/help/spec-ppd.html @@ -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" diff --git a/driver/Dependencies b/driver/Dependencies index a89ca293f..2111f79f0 100644 --- a/driver/Dependencies +++ b/driver/Dependencies @@ -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 diff --git a/man/cupsfilter.man b/man/cupsfilter.man index 337c57e0d..9bd428d9f 100644 --- a/man/cupsfilter.man +++ b/man/cupsfilter.man @@ -11,14 +11,14 @@ .\" 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 diff --git a/man/cupstestppd.man b/man/cupstestppd.man index 4757c5d72..fd2b878b5 100644 --- a/man/cupstestppd.man +++ b/man/cupstestppd.man @@ -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. diff --git a/scheduler/cupsd.h b/scheduler/cupsd.h index e9d8df1f0..8da2d9616 100644 --- a/scheduler/cupsd.h +++ b/scheduler/cupsd.h @@ -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 */ diff --git a/scheduler/cupsfilter.c b/scheduler/cupsfilter.c index d3c30210a..17f6f89ea 100644 --- a/scheduler/cupsfilter.c +++ b/scheduler/cupsfilter.c @@ -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" diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 3fc1f33b0..c0160e2e9 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -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 diff --git a/scheduler/job.c b/scheduler/job.c index 25ddffd9f..cd185c473 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -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... diff --git a/scheduler/main.c b/scheduler/main.c index 437f0f5ba..ccc395211 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -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; } } diff --git a/scheduler/printers.c b/scheduler/printers.c index c826120f1..47142db2b 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -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 ++; diff --git a/scheduler/process.c b/scheduler/process.c index bd548ff06..45d3bcfb6 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -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... diff --git a/systemv/Dependencies b/systemv/Dependencies index 79765c4b9..f0b180813 100644 --- a/systemv/Dependencies +++ b/systemv/Dependencies @@ -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 diff --git a/systemv/cupstestppd.c b/systemv/cupstestppd.c index 855c17fbf..4a619ebca 100644 --- a/systemv/cupstestppd.c +++ b/systemv/cupstestppd.c @@ -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 @@ -21,17 +21,19 @@ * 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. */ @@ -41,12 +43,13 @@ #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 }; @@ -94,6 +98,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) @@ -1859,6 +2008,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... @@ -2476,6 +2757,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" @@ -2945,6 +3378,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. */ |