From: msweet Date: Sat, 7 Mar 2009 16:36:03 +0000 (+0000) Subject: Merge changes from CUPS 1.4svn-r8414. X-Git-Tag: release-1.6.3~113 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=1340db2dab0b5ac933dec4796637ca3baa10bb4b;p=thirdparty%2Fcups.git 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 --- 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.

CUPS 1.4 and higher define two new attributes for constraints, cupsUIConstraints and cupsUIResolver. Each cupsUIConstraints attribute points to a cupsUIResolver -attribute which corrects the conflict condition. The same -cupsUIResolver can be used by multiple cupsUIConstraints.

+attribute which specifies alternate options that resolve the conflict condition. +The same cupsUIResolver can be used by multiple +cupsUIConstraints.

+ +
Note: + +

When developing PPD files that contain constraints, it is very important + to use the cupstestppd(1) program to + verify that your constraints are accurate and cannot result in unresolvable + option selections.

+ +

CUPS 1.4cupsUIConstraints

@@ -393,9 +403,8 @@ attribute which corrects the conflict condition. The same

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.

+constraint exists. When no resolver is provided, CUPS first tries the default +choice followed by testing each option choice to resolve the conflict.

Examples:

@@ -403,6 +412,15 @@ installable options.

*% Specify that 2-sided printing cannot happen on transparencies *cupsUIConstraints transparency: "*Duplex *MediaType Transparency" +*% Specify that envelope printing cannot happen from the paper trays +*cupsUIConstraints envelope: "*PageSize Env10 *InputSlot Tray1" +*cupsUIConstraints envelope: "*PageSize Env10 *InputSlot Tray1" +*cupsUIConstraints envelope: "*PageSize EnvDL *InputSlot Tray2" +*cupsUIConstraints envelope: "*PageSize EnvDL *InputSlot Tray2" + +*% Specify an installable option constraint for the envelope feeder +*cupsUIConstraints: "*InputSlot EnvFeeder *InstalledEnvFeeder" + *% Specify that photo printing cannot happen on plain paper or transparencies at 1200dpi *cupsUIConstraints photo: "*OutputMode Photo *MediaType Plain *Resolution 1200dpi" *cupsUIConstraints photo: "*OutputMode Photo *MediaType Transparency *Resolution 1200dpi" @@ -410,18 +428,29 @@ installable options.

CUPS 1.4cupsUIResolver

-

*cupsUIResolution resolver: "*Keyword OptionKeyword ..."

+

*cupsUIResolution resolver: "*Keyword1 OptionKeyword1 *Keyword2 OptionKeyword2 ..."

-

Specifies one or more options to mark/select to resolve a constraint. The +

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 cupsUIConstraints. The same action -can be used for multiple constraints.

+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 +cupsResolveConflicts() +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.

Examples:

-*% Specify the option to change for the 2-sided transparency constraint 
-*cupsUIResolver transparency: "*Duplex None"
+*% Specify the options to change for the 2-sided transparency constraint 
+*cupsUIResolver transparency: "*Duplex None *MediaType Plain"
+
+*% 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...
+*cupsUIResolver envelope: "*InputSlot EnvFeeder *InputSlot ManualFeed *PageSize Letter"
 
 *% Specify the options to change for the photo printing constraints 
 *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 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
-#include 
+#include 
 
 
 /*
@@ -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 : "");
-      }
-
-     /*
-      * 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 : "");
-      }
-#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 : "");
+
+      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 : "");
+
+      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 : "");
+
+      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 : "");
+
+      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.
  */