From dd1abb6b5f145c5e5f279d8848b5f3ec161fd227 Mon Sep 17 00:00:00 2001 From: msweet Date: Wed, 18 Jun 2008 16:44:53 +0000 Subject: [PATCH] Merge changes from CUPS 1.4svn-r7670. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@810 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES-1.3.txt | 26 +++- CHANGES.txt | 9 +- CREDITS.txt | 3 +- backend/runloop.c | 10 +- backend/serial.c | 11 +- conf/Makefile | 12 +- conf/cupsd.conf.in | 4 +- conf/mime.types | 4 +- config-scripts/cups-compiler.m4 | 6 + config-scripts/cups-defaults.m4 | 2 +- config-scripts/cups-sharedlibs.m4 | 13 +- cups/debug.c | 5 +- cups/http.c | 4 + cups/localize.c | 7 - cups/testppd.c | 15 +- cups/util.c | 14 +- desktop/cups.desktop | 3 +- doc/help/ref-cupsd-conf.html.in | 2 +- doc/help/spec-ppd.html | 5 +- filter/pstops.c | 95 ++++++------- man/cups-config.man | 8 +- man/cups-deviced.man.in | 8 +- man/cups-driverd.man.in | 18 +-- man/cupsd.conf.man.in | 6 +- man/lpq.man | 4 +- man/mantohtml.c | 2 +- man/mime.types.man | 11 +- packaging/cups.list.in | 7 +- packaging/cups.spec.in | 5 +- ppdc/ppdmerge.cxx | 44 +++--- scheduler/auth.c | 2 +- scheduler/conf.c | 11 +- scheduler/cups-driverd.c | 44 +++--- scheduler/cupsfilter.c | 5 + scheduler/ipp.c | 48 ++++++- scheduler/job.c | 13 ++ scheduler/mime.h | 3 +- scheduler/printers.c | 17 +-- scheduler/testmime.c | 2 +- scheduler/testspeed.c | 222 ++++++++++++++++++++---------- scheduler/type.c | 20 ++- systemv/cupstestppd.c | 4 +- systemv/lpoptions.c | 99 ++++++++++--- test/run-stp-tests.sh | 11 +- 44 files changed, 595 insertions(+), 269 deletions(-) diff --git a/CHANGES-1.3.txt b/CHANGES-1.3.txt index 90b02ac20..aa85f31d2 100644 --- a/CHANGES-1.3.txt +++ b/CHANGES-1.3.txt @@ -3,7 +3,31 @@ CHANGES-1.3.txt CHANGES IN CUPS V1.3.8 - - Documentation updates (STR #2785) + - Documentation updates (STR #2785, STR #2861, STR #2862) + - The ppdLocalize functions incorrectly mapped all generic + locales to country-specific locales. + - The cups-driverd program did not support Simplified Chinese + or Traditional Chinese language version strings (STR #2851) + - Added an Indonesian translation (STR #2792) + - Fixed a timing issue in the backends that could cause data + corruption with the CUPS_SC_CMD_DRAIN_OUTPUT side-channel + command (STR #2858) + - The scheduler did not support "HostNameLookups" with all of + the boolean names (STR #2861) + - Fixed a compile problem with glibc 2.8 (STR #2860) + - The scheduler incorrectly filtered out queues with ACLs and + authentication. + - The PostScript filter did not support %%IncludeFeature lines + in the page setup section of each page (STR #2831) + - The scheduler did not generate printer-state events when the + default printer was changed (STR #2764) + - cupstestppd incorrectly reported a warning about the PPD format + version in some locales (STR #2854) + - cupsGetPPD() and friends incorrectly returned a PPD file for + a class with no printers. + - The member-uris values for local printers in a class returned + by the scheduler did not reflect the connected hostname or + port. - The CUPS PHP extension was not thread-safe (STR #2828) - The scheduler incorrectly added the document-format-default attribute to the list of "common" printer attributes, which diff --git a/CHANGES.txt b/CHANGES.txt index 4f447198b..5ada0f3be 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,15 @@ -CHANGES.txt - 2008-05-20 +CHANGES.txt - 2008-06-17 ------------------------ CHANGES IN CUPS V1.4b1 + - MIME types now support a priority() attribute (STR #2719) + - The standard MIME types are now installed in + DataDir/mime (STR #2719) + - The lpoptions command now describes custom options and + the necessary parameters (STR #2660) + - The ppdmerge program did not support Simplified Chinese + or Traditional Chinese language version strings (STR #2851) - The PPD compiler now supports localizable attributes (STR #2738) - The ppdpo utility now includes cupsIPPReasons values in diff --git a/CREDITS.txt b/CREDITS.txt index ffaa9f3aa..7c08ee4d8 100644 --- a/CREDITS.txt +++ b/CREDITS.txt @@ -1,4 +1,4 @@ -CREDITS.txt - 2007-09-10 +CREDITS.txt - 2008-06-16 ------------------------ Few projects are completed by one person, and CUPS is no exception. We'd @@ -30,6 +30,7 @@ like to thank the following individuals for their contributions: Daniel Nylander - Swedish localization. Giulio Orsero - Bug fixes and testing. Michal Osowiecki - Polish localization. + Citra Paska - Indonesian localization. Kurt Pfeifle - Bug fixes, beta testing, evangelism. Vincenzo Reale - Italian localization. Petter Reinholdtsen - HP-UX compiler stuff. diff --git a/backend/runloop.c b/backend/runloop.c index 53c6ac7f1..fbb14fdab 100644 --- a/backend/runloop.c +++ b/backend/runloop.c @@ -219,7 +219,7 @@ backendRunLoop( FD_SET(print_fd, &input); if (use_bc) FD_SET(device_fd, &input); - if (side_cb) + if (!print_bytes && side_cb) FD_SET(CUPS_SC_FD, &input); FD_ZERO(&output); @@ -260,7 +260,15 @@ backendRunLoop( */ if (side_cb && FD_ISSET(CUPS_SC_FD, &input)) + { + /* + * Do the side-channel request, then start back over in the select + * loop since it may have read from print_fd... + */ + (*side_cb)(print_fd, device_fd, snmp_fd, addr, use_bc); + continue; + } /* * Check if we have back-channel data ready... diff --git a/backend/serial.c b/backend/serial.c index 7a775259d..3ac7ff659 100644 --- a/backend/serial.c +++ b/backend/serial.c @@ -558,7 +558,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ if (!print_bytes) FD_SET(print_fd, &input); FD_SET(device_fd, &input); - FD_SET(CUPS_SC_FD, &input); + if (!print_bytes) + FD_SET(CUPS_SC_FD, &input); FD_ZERO(&output); if (print_bytes) @@ -572,7 +573,15 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ */ if (FD_ISSET(CUPS_SC_FD, &input)) + { + /* + * Do the side-channel request, then start back over in the select + * loop since it may have read from print_fd... + */ + side_cb(print_fd, device_fd, 1); + continue; + } /* * Check if we have back-channel data ready... diff --git a/conf/Makefile b/conf/Makefile index 90ab0cd54..4bb31c9ed 100644 --- a/conf/Makefile +++ b/conf/Makefile @@ -75,11 +75,15 @@ install-data: done $(INSTALL_CONFIG) cupsd.conf $(SERVERROOT)/cupsd.conf.default -chgrp $(CUPS_GROUP) $(SERVERROOT)/cupsd.conf.default + $(INSTALL_DIR) -m 755 $(DATADIR)/mime for file in $(REPLACE); do \ + if test -r $(DATADIR)/mime/$$file ; then \ + $(MV) $(DATADIR)/mime/$$file $(DATADIR)/mime/$$file.O ; \ + fi ; \ if test -r $(SERVERROOT)/$$file ; then \ - $(MV) $(SERVERROOT)/$$file $(SERVERROOT)/$$file.O ; \ + $(MV) $(SERVERROOT)/$$file $(DATADIR)/mime/$$file.O ; \ fi ; \ - $(INSTALL_DATA) $$file $(SERVERROOT) ; \ + $(INSTALL_DATA) $$file $(DATADIR)/mime ; \ done -if test x$(PAMDIR) != x; then \ $(INSTALL_DIR) -m 755 $(BUILDROOT)$(PAMDIR); \ @@ -121,6 +125,10 @@ uninstall: $(RM) $(SERVERROOT)/$$file; \ done -$(RMDIR) $(SERVERROOT) + for file in $(REPLACE); do \ + $(RM) $(DATADIR)/mime/$$file; \ + done + -$(RMDIR) $(DATADIR)/mime -if test x$(PAMDIR) != x; then \ $(RM) $(BUILDROOT)$(PAMDIR)/cups; \ $(RMDIR) $(BUILDROOT)$(PAMDIR); \ diff --git a/conf/cupsd.conf.in b/conf/cupsd.conf.in index 3561a805e..8939b8a4b 100644 --- a/conf/cupsd.conf.in +++ b/conf/cupsd.conf.in @@ -48,7 +48,7 @@ DefaultAuthType Basic # Set the default printer/job policies... # Job-related operations must be done by the owner or an administrator... - + Require user @OWNER @SYSTEM Order deny,allow @@ -81,7 +81,7 @@ DefaultAuthType Basic # Set the authenticated printer/job policies... # Job-related operations must be done by the owner or an administrator... - + Require user @OWNER @SYSTEM Order deny,allow AuthType Default diff --git a/conf/mime.types b/conf/mime.types index bda116265..1852d460c 100644 --- a/conf/mime.types +++ b/conf/mime.types @@ -7,7 +7,7 @@ # VERSIONS OF CUPS. Instead, create a "local.types" file that # reflects your local configuration changes. # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2008 by Apple Inc. # Copyright 1997-2007 by Easy Software Products. # # These coded instructions, statements, and computer programs are the @@ -33,6 +33,8 @@ # extension Pattern match on "*.extension" # ascii(offset,length) True if bytes are valid printable ASCII # (CR, NL, TAB, BS, 32-126) +# priority(number) Sets priority of type (0=lowest, +# 100=default, 200=highest) # printable(offset,length) True if bytes are printable 8-bit chars # (CR, NL, TAB, BS, 32-126, 128-254) # string(offset,"string") True if bytes are identical to string diff --git a/config-scripts/cups-compiler.m4 b/config-scripts/cups-compiler.m4 index 004a0990c..51a5daa6f 100644 --- a/config-scripts/cups-compiler.m4 +++ b/config-scripts/cups-compiler.m4 @@ -529,6 +529,12 @@ case $uname in OPTIM="$OPTIM -D_HPUX_SOURCE" ;; + Linux*) + # glibc 2.8 and higher breaks peer credentials unless you + # define _GNU_SOURCE... + OPTIM="$OPTIM -D_GNU_SOURCE" + ;; + OSF*) # Tru64 UNIX aka Digital UNIX aka OSF/1 need to be told # to be POSIX-compliant... diff --git a/config-scripts/cups-defaults.m4 b/config-scripts/cups-defaults.m4 index b72631f4c..f2cff3c2e 100644 --- a/config-scripts/cups-defaults.m4 +++ b/config-scripts/cups-defaults.m4 @@ -15,7 +15,7 @@ dnl file is missing or damaged, see the license at "http://www.cups.org/". dnl dnl Default languages... -LANGUAGES="`ls -1 locale/*.po | sed -e '1,$s/locale\/cups_//' -e '1,$s/\.po//' | tr '\n' ' '`" +LANGUAGES="`ls -1 locale/cups_*.po | sed -e '1,$s/locale\/cups_//' -e '1,$s/\.po//' | tr '\n' ' '`" AC_ARG_WITH(languages, [ --with-languages set installed languages, default=all ],[ case "$withval" in diff --git a/config-scripts/cups-sharedlibs.m4 b/config-scripts/cups-sharedlibs.m4 index 41897d62e..f3962ab85 100644 --- a/config-scripts/cups-sharedlibs.m4 +++ b/config-scripts/cups-sharedlibs.m4 @@ -20,7 +20,18 @@ AC_ARG_ENABLE(shared, [ --enable-shared turn on shared libraries, defau if test x$enable_shared != xno; then case "$uname" in - SunOS* | UNIX_S*) + SunOS*) + LIBCUPS="libcups.so.2" + LIBCUPSCGI="libcupscgi.so.1" + LIBCUPSDRIVER="libcupsdriver.so.1" + LIBCUPSIMAGE="libcupsimage.so.2" + LIBCUPSMIME="libcupsmime.so.1" + LIBCUPSPPDC="libcupsppdc.so.1" + DSO="\$(CC)" + DSOXX="\$(CXX)" + DSOFLAGS="$DSOFLAGS -Wl,-h\`basename \$@\` -G \$(OPTIM)" + ;; + UNIX_S*) LIBCUPS="libcups.so.2" LIBCUPSCGI="libcupscgi.so.1" LIBCUPSDRIVER="libcupsdriver.so.1" diff --git a/cups/debug.c b/cups/debug.c index fcaa11e2a..965947976 100644 --- a/cups/debug.c +++ b/cups/debug.c @@ -393,7 +393,10 @@ _cups_debug_printf(const char *format, /* I - Printf-style format string */ else if (!strcmp(cups_debug_log, "-")) cg->debug_fd = 2; else - cg->debug_fd = open(cups_debug_log, O_WRONLY | O_APPEND | O_CREAT, 0644); + { + snprintf(buffer, sizeof(buffer), cups_debug_log, getpid()); + cg->debug_fd = open(buffer, O_WRONLY | O_APPEND | O_CREAT, 0644); + } } if (cg->debug_fd < 0) diff --git a/cups/http.c b/cups/http.c index dabf218ce..b70139108 100644 --- a/cups/http.c +++ b/cups/http.c @@ -2439,8 +2439,12 @@ http_debug_hex(const char *prefix, /* I - Prefix for line */ char line[255], /* Line buffer */ *start, /* Start of line after prefix */ *ptr; /* Pointer into line */ + _cups_globals_t *cg = _cupsGlobals(); /* Global data */ + if (cg->debug_init && cg->debug_fd < 0) + return; + DEBUG_printf(("%s: %d bytes:\n", prefix, bytes)); snprintf(line, sizeof(line), "%s: ", prefix); diff --git a/cups/localize.c b/cups/localize.c index 6e28bb8d5..551dde98e 100644 --- a/cups/localize.c +++ b/cups/localize.c @@ -658,13 +658,6 @@ ppd_ll_CC(char *ll_CC, /* O - Country-specific locale name */ strlcpy(ll_CC, "sv_SE", ll_CC_size); else if (!strcmp(ll_CC, "zh")) /* Simplified Chinese */ strlcpy(ll_CC, "zh_CN", ll_CC_size); - else if (ll_CC_size >= 6) - { - ll_CC[2] = '_'; - ll_CC[3] = toupper(ll_CC[0] & 255); - ll_CC[4] = toupper(ll_CC[1] & 255); - ll_CC[5] = '\0'; - } } DEBUG_printf(("ppd_ll_CC: lang->language=\"%s\", ll_CC=\"%s\"...\n", diff --git a/cups/testppd.c b/cups/testppd.c index 46e070c62..6772970b8 100644 --- a/cups/testppd.c +++ b/cups/testppd.c @@ -28,7 +28,7 @@ #include #include #include -#include "ppd.h" +#include "cups.h" #ifdef WIN32 # include #else @@ -313,7 +313,15 @@ main(int argc, /* I - Number of command-line arguments */ } else { - if ((ppd = ppdOpenFile(argv[1])) == NULL) + const char *filename; /* PPD filename */ + + + if (!strncmp(argv[1], "-d", 2)) + filename = cupsGetPPD(argv[1] + 2); + else + filename = argv[1]; + + if ((ppd = ppdOpenFile(filename)) == NULL) { ppd_status_t err; /* Last error in file */ int line; /* Line number in file */ @@ -436,6 +444,9 @@ main(int argc, /* I - Number of command-line arguments */ printf(" *%s %s/%s: \"%s\"\n", attr->name, attr->spec, attr->text, attr->value ? attr->value : ""); } + + if (!strncmp(argv[1], "-d", 2)) + unlink(filename); } #ifdef __APPLE__ diff --git a/cups/util.c b/cups/util.c index ba9c62ee9..a07276786 100644 --- a/cups/util.c +++ b/cups/util.c @@ -949,7 +949,7 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL resource, sizeof(resource), 0)) return (HTTP_NOT_FOUND); - DEBUG_printf(("Printer hostname=\"%s\", port=%d\n", hostname, port)); + DEBUG_printf(("cupsGetPPD3: Printer hostname=\"%s\", port=%d\n", hostname, port)); /* * Remap local hostname to localhost... @@ -1775,6 +1775,16 @@ cups_get_printer_uri( host, hostsize, port, resource, resourcesize); ippDelete(response); + if (!strncmp(resource, "/classes/", 9)) + { + _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found for class!")); + + *host = '\0'; + *resource = '\0'; + + return (0); + } + return (1); } @@ -1782,7 +1792,7 @@ cups_get_printer_uri( } if (cupsLastError() != IPP_NOT_FOUND) - _cupsSetError(IPP_INTERNAL_ERROR, "No printer-uri found!"); + _cupsSetError(IPP_INTERNAL_ERROR, _("No printer-uri found!")); *host = '\0'; *resource = '\0'; diff --git a/desktop/cups.desktop b/desktop/cups.desktop index ced9b0cb4..1a9b33a76 100644 --- a/desktop/cups.desktop +++ b/desktop/cups.desktop @@ -33,4 +33,5 @@ Name[zh_TW]=印表管理 Comment[zh_TW]=CUPS 網頁介面 Name[de]=Druckerverwaltung Comment[de]=CUPS Webinterface - +Name[id]=Manajemen Pencetakan +Comment[id]=Antarmuka Web CUPS diff --git a/doc/help/ref-cupsd-conf.html.in b/doc/help/ref-cupsd-conf.html.in index 46ad1027b..b61ef0b66 100644 --- a/doc/help/ref-cupsd-conf.html.in +++ b/doc/help/ref-cupsd-conf.html.in @@ -988,7 +988,7 @@ printers are shared (published) by default. The default is

Description

The Deny directive specifies a hostname, IP -address, or network that is allowed access to the server. +address, or network that is denied access to the server. Deny directives are cummulative, so multiple Deny directives can be used to allow access for multiple hosts or networks. The /mm notation diff --git a/doc/help/spec-ppd.html b/doc/help/spec-ppd.html index 435393a9f..402b3bcdd 100644 --- a/doc/help/spec-ppd.html +++ b/doc/help/spec-ppd.html @@ -44,8 +44,9 @@ file:

 PPD-FILE = HEADER +(DATA / COMMENT / LINE-END)
 
-HEADER   = "*" 0x50.50.44.2D.41.64.6F.62.65 ":"   ; *PPD-Adobe:
-           *WSP DQUOTE "4.3" DQUOTE LINE-END
+HEADER   = "*PPD-Adobe:" *WSP DQUOTE VERSION DQUOTE LINE-END
+
+VERSION  = "4.0" / "4.1" / "4.2" / "4.3"
 
 COMMENT  = "*%" *TCHAR LINE-END
 
diff --git a/filter/pstops.c b/filter/pstops.c
index f8ab6b00a..77bc2df96 100644
--- a/filter/pstops.c
+++ b/filter/pstops.c
@@ -1506,11 +1506,56 @@ copy_page(cups_file_t  *fp,		/* I - File to read from */
   */
 
   if (first_page)
+    doc_puts(doc, "%%BeginPageSetup\n");
+
+  if (!strncmp(line, "%%BeginPageSetup", 16))
   {
-    char	*page_setup;		/* PageSetup commands to send */
+    int	feature = 0;			/* In a Begin/EndFeature block? */
+
+    while ((linelen = cupsFileGetLine(fp, line, linesize)) > 0)
+    {
+      if (!strncmp(line, "%%EndPageSetup", 14))
+	break;
+      else if (!strncmp(line, "%%BeginFeature:", 15))
+      {
+	feature = 1;
 
+	if (doc->number_up > 1 || doc->fitplot)
+	  continue;
+      }
+      else if (!strncmp(line, "%%EndFeature", 12))
+      {
+	feature = 0;
+
+	if (doc->number_up > 1 || doc->fitplot)
+	  continue;
+      }
+      else if (!strncmp(line, "%%IncludeFeature:", 17))
+      {
+	pageinfo->num_options = include_feature(ppd, line,
+						pageinfo->num_options,
+						&(pageinfo->options));
+	continue;
+      }
+      else if (!strncmp(line, "%%Include", 9))
+	continue;
+
+      if (!feature || (doc->number_up == 1 && !doc->fitplot))
+	doc_write(doc, line, linelen);
+    }
+
+   /*
+    * Skip %%EndPageSetup...
+    */
+
+    if (linelen > 0)
+      linelen = cupsFileGetLine(fp, line, linesize);
+  }
+
+  if (first_page)
+  {
+    char	*page_setup;		/* PageSetup commands to send */
 
-    doc_puts(doc, "%%BeginPageSetup\n");
 
     if (pageinfo->num_options > 0)
     {
@@ -1580,48 +1625,6 @@ copy_page(cups_file_t  *fp,		/* I - File to read from */
 
   start_nup(doc, number, 1, bounding_box);
 
- /*
-  * Copy page setup commands as needed...
-  */
-
-  if (!strncmp(line, "%%BeginPageSetup", 16))
-  {
-    int	feature = 0;			/* In a Begin/EndFeature block? */
-
-
-    while ((linelen = cupsFileGetLine(fp, line, linesize)) > 0)
-    {
-      if (!strncmp(line, "%%EndPageSetup", 14))
-        break;
-      else if (!strncmp(line, "%%BeginFeature:", 15))
-      {
-        feature = 1;
-
-	if (doc->number_up > 1 || doc->fitplot)
-	  continue;
-      }
-      else if (!strncmp(line, "%%EndFeature", 12))
-      {
-        feature = 0;
-
-	if (doc->number_up > 1 || doc->fitplot)
-	  continue;
-      }
-      else if (!strncmp(line, "%%Include", 9))
-        continue;
-
-      if (!feature || (doc->number_up == 1 && !doc->fitplot))
-	doc_write(doc, line, linelen);
-    }
-
-   /*
-    * Skip %%EndPageSetup...
-    */
-
-    if (linelen > 0)
-      linelen = cupsFileGetLine(fp, line, linesize);
-  }
-
  /*
   * Finish the PageSetup section as needed...
   */
@@ -1789,8 +1792,6 @@ copy_setup(cups_file_t  *fp,		/* I - File to read from */
 
   doc_puts(doc, "%%BeginSetup\n");
   
-  do_setup(doc, ppd);
-
   if (!strncmp(line, "%%BeginSetup", 12))
   {
     while (strncmp(line, "%%EndSetup", 10))
@@ -1820,6 +1821,8 @@ copy_setup(cups_file_t  *fp,		/* I - File to read from */
       fputs(_("ERROR: Missing %%EndSetup!\n"), stderr);
   }
 
+  do_setup(doc, ppd);
+
   doc_puts(doc, "%%EndSetup\n");
 
   return (linelen);
diff --git a/man/cups-config.man b/man/cups-config.man
index 4f31a6227..6e6e014ea 100644
--- a/man/cups-config.man
+++ b/man/cups-config.man
@@ -3,7 +3,7 @@
 .\"
 .\"   cups-config man page for the Common UNIX Printing System (CUPS).
 .\"
-.\"   Copyright 2007 by Apple Inc.
+.\"   Copyright 2007-2008 by Apple Inc.
 .\"   Copyright 1997-2006 by Easy Software Products.
 .\"
 .\"   These coded instructions, statements, and computer programs are the
@@ -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 cups-config 1 "Common UNIX Printing System" "11 February 2006" "Apple Inc."
+.TH cups-config 1 "Common UNIX Printing System" "16 June 2008" "Apple Inc."
 .SH NAME
 cups-config \- get cups api, compiler, directory, and link information.
 .SH SYNOPSIS
@@ -73,7 +73,7 @@ Displays the program usage message.
 --image
 .br
 When used with \fI--libs\fR, adds the CUPS imaging library to the
-list or displayed libraries.
+list of displayed libraries.
 .TP 5
 --ldflags
 .br
@@ -104,7 +104,7 @@ Displays the full version number of the CUPS installation
 .SH SEE ALSO
 http://localhost:631/help
 .SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
 .\"
 .\" End of "$Id: cups-config.man 6649 2007-07-11 21:46:42Z mike $".
 .\"
diff --git a/man/cups-deviced.man.in b/man/cups-deviced.man.in
index 6d4c10fa7..9db1f07c6 100644
--- a/man/cups-deviced.man.in
+++ b/man/cups-deviced.man.in
@@ -3,7 +3,7 @@
 .\"
 .\"   cups-deviced man page for the Common UNIX Printing System (CUPS).
 .\"
-.\"   Copyright 2007 by Apple Inc.
+.\"   Copyright 2007-2008 by Apple Inc.
 .\"   Copyright 1997-2006 by Easy Software Products.
 .\"
 .\"   These coded instructions, statements, and computer programs are the
@@ -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 cups-deviced 8 "Common UNIX Printing System" "12 February 2006" "Apple Inc."
+.TH cups-deviced 8 "Common UNIX Printing System" "16 June 2008" "Apple Inc."
 .SH NAME
 cups-deviced \- cups device daemon
 .SH SYNOPSIS
@@ -24,7 +24,7 @@ cups-deviced \- cups device daemon
 It is run by \fIcupsd(8)\fR in response to a
 \fICUPS-Get-Devices\fR request. The output format is an IPP
 response message. The \fIrequest-id\fR argument is the request ID
-from the original IPP request, typically 1. The \Ilimit\fR
+from the original IPP request, typically 1. The \fIlimit\fR
 argument is the limit value from the original IPP request - 0
 means no limit. The \fIuser-id\fR argument is the
 requesting-user-name value from the original IPP request.
@@ -38,7 +38,7 @@ backend(7), cupsd(8), cupsd.conf(5),
 .br
 http://localhost:631/help
 .SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
 .\"
 .\" End of "$Id: cups-deviced.man.in 6649 2007-07-11 21:46:42Z mike $".
 .\"
diff --git a/man/cups-driverd.man.in b/man/cups-driverd.man.in
index 4f67a7832..b84a78fe7 100644
--- a/man/cups-driverd.man.in
+++ b/man/cups-driverd.man.in
@@ -3,7 +3,7 @@
 .\"
 .\"   cups-driverd man page for the Common UNIX Printing System (CUPS).
 .\"
-.\"   Copyright 2007 by Apple Inc.
+.\"   Copyright 2007-2008 by Apple Inc.
 .\"   Copyright 1997-2006 by Easy Software Products.
 .\"
 .\"   These coded instructions, statements, and computer programs are the
@@ -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 cups-driverd 8 "Common UNIX Printing System" "12 February 2006" "Apple Inc."
+.TH cups-driverd 8 "Common UNIX Printing System" "16 June 2008" "Apple Inc."
 .SH NAME
 cups-driverd \- cups driver daemon
 .SH SYNOPSIS
@@ -33,10 +33,10 @@ The second form lists the available manufacturers or PPD files to
 stdout as indicated by the \fIoptions\fR argument. The output
 format is an IPP response message. The \fIrequest_id\fR argument
 is the request ID from the original IPP request, typically 1. The
-\Ilimit\fR argument is the limit value from the original IPP
+\fIlimit\fR argument is the limit value from the original IPP
 request - 0 means no limit. Finally, the \fIoptions\fR argument
 is a space-delimited list of attributes ("name=value name=value
-\...") that were passed in with the request. Currently
+\&...") that were passed in with the request. Currently
 \fIcups-driverd\fR looks for the \fIppd-make\fR and
 \fIrequested-attributes\fR attributes and tailors the output
 accordingly.
@@ -48,7 +48,7 @@ conform to the Adobe PPD File Format Specification version 4.3
 and may be compressed using the \fIgzip(1)\fR program. Driver
 programs must implement the command-line interface shown in the
 next section.
-.Sh DRIVER PROGRAMS
+.SS DRIVER PROGRAMS
 Driver programs provide an interface to dynamically-generated PPD
 files. The following arguments are currently defined:
 .TP 5
@@ -59,7 +59,7 @@ Lists the supported PPD files to stdout.
 drivername cat ppdname
 .br
 Writes the named PPD file to stdout.
-.Sh LISTING FILES (drivername list)
+.SS LISTING FILES (drivername list)
 When run with the single argument "list", the program must list
 the available PPD files it can generate to stdout using the
 following format:
@@ -74,12 +74,12 @@ typically "en". \fIMake\fR is the Manufacturer name from the PPD
 file. \fIMake and model\fR is the NickName name from the PPD
 file. \fI1284 device id\fR is the 1284DeviceId from the PPD file,
 if any.
-.Sh WRITING FILES (drivername cat ppdname)
+.SS WRITING FILES (drivername cat ppdname)
 When the driver program is run with the "cat ppdname" arguments,
 it must write the named PPD file to stdout, uncompressed. If the
 named PPD file does not exist, the driver program must not write
 any output to stdout and report the error to stderr instead.
-.Sh DRIVER ERROR MESSAGES
+.SS DRIVER ERROR MESSAGES
 Error messages can be relayed back to \fIcupsd\fR by writing them
 to stderr. The following prefixes are recognized:
 .TP 5
@@ -99,7 +99,7 @@ cupsd(8), cupsd.conf(5), cupstestppd(1),
 .br
 http://localhost:631/help
 .SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
 .\"
 .\" End of "$Id: cups-driverd.man.in 6649 2007-07-11 21:46:42Z mike $".
 .\"
diff --git a/man/cupsd.conf.man.in b/man/cupsd.conf.man.in
index 19d747fb1..875a087c8 100644
--- a/man/cupsd.conf.man.in
+++ b/man/cupsd.conf.man.in
@@ -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 cupsd.conf 5 "Common UNIX Printing System" "15 May 2008" "Apple Inc."
+.TH cupsd.conf 5 "Common UNIX Printing System" "16 June 2008" "Apple Inc."
 .SH NAME
 cupsd.conf \- server configuration file for cups
 .SH DESCRIPTION
@@ -306,9 +306,9 @@ HideImplicitMembers No
 .br
 Specifies whether to hide members of implicit classes.
 .TP 5
-HostNameLookups Yes
+HostNameLookups On
 .TP 5
-HostNameLookups No
+HostNameLookups Off
 .TP 5
 HostNameLookups Double
 .br
diff --git a/man/lpq.man b/man/lpq.man
index 3be52e9f4..5745011d4 100644
--- a/man/lpq.man
+++ b/man/lpq.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 lpq 1 "Common UNIX Printing System" "2 January 2008" "Apple Inc."
+.TH lpq 1 "Common UNIX Printing System" "16 June 2008" "Apple Inc."
 .SH NAME
 lpq \- show printer queue status
 .SH SYNOPSIS
@@ -33,7 +33,7 @@ no printer or class is specified on the command-line.
 .LP
 The \fI+interval\fR option allows you to continuously report the
 jobs in the queue until the queue is empty; the list of jobs is
-show once every \fIinterval\fR seconds.
+shown once every \fIinterval\fR seconds.
 .SH OPTIONS
 \fIlpq\fR supports the following options:
 .TP 5
diff --git a/man/mantohtml.c b/man/mantohtml.c
index affd6fcba..9ae8de71d 100644
--- a/man/mantohtml.c
+++ b/man/mantohtml.c
@@ -158,7 +158,7 @@ main(int  argc,				/* I - Number of command-line args */
       }
       else if (section < 0)
         continue;
-      else if (!strncmp(line, ".SH ", 4) || !strncmp(line, ".Sh ", 4))
+      else if (!strncmp(line, ".SH ", 4) || !strncmp(line, ".SS ", 4))
       {
        /*
         * Grab heading...
diff --git a/man/mime.types.man b/man/mime.types.man
index 2f902e43c..24659a991 100644
--- a/man/mime.types.man
+++ b/man/mime.types.man
@@ -3,7 +3,7 @@
 .\"
 .\"   mime.types man page for the Common UNIX Printing System (CUPS).
 .\"
-.\"   Copyright 2007 by Apple Inc.
+.\"   Copyright 2007-2008 by Apple Inc.
 .\"   Copyright 1997-2006 by Easy Software Products.
 .\"
 .\"   These coded instructions, statements, and computer programs are the
@@ -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 mime.types 5 "Common UNIX Printing System" "12 February 2006" "Apple Inc."
+.TH mime.types 5 "Common UNIX Printing System" "17 June 2008" "Apple Inc."
 .SH NAME
 mime.types \- mime type description file for cups
 .SH DESCRIPTION
@@ -51,6 +51,11 @@ printable(offset,length)
 .br
 True if bytes are printable 8-bit chars (CR, NL, TAB, BS, 32-126, 128-254)
 .TP 5
+priority(number)
+.br
+Specifies the relative priority of this MIME type. The default priority is 100.
+Larger values have higher priority while smaller values have lower priority.
+.TP 5
 string(offset,"string")
 .br
 True if bytes are identical to string
@@ -88,7 +93,7 @@ strings.
 .br
 http://localhost:631/help
 .SH COPYRIGHT
-Copyright 2007 by Apple Inc.
+Copyright 2007-2008 by Apple Inc.
 .\"
 .\" End of "$Id: mime.types.man 6649 2007-07-11 21:46:42Z mike $".
 .\"
diff --git a/packaging/cups.list.in b/packaging/cups.list.in
index ac535a2c7..48324fd8a 100644
--- a/packaging/cups.list.in
+++ b/packaging/cups.list.in
@@ -467,6 +467,10 @@ d 0755 root sys $DATADIR/fonts -
 f 0644 root sys $DATADIR/fonts fonts/Courier*
 f 0644 root sys $DATADIR/fonts/Symbol fonts/Symbol
 
+d 0755 root sys $DATADIR/mime -
+f 0644 root sys $DATADIR/mime/mime.convs conf/mime.convs
+f 0644 root sys $DATADIR/mime/mime.types conf/mime.types
+
 d 0755 root sys $DATADIR/model -
 
 d 0755 root sys $DATADIR/ppdc -
@@ -514,8 +518,6 @@ d 0755 root $CUPS_GROUP $SERVERROOT/ppd -
 d 0700 root $CUPS_GROUP $SERVERROOT/ssl -
 c $CUPS_PERM root $CUPS_GROUP $SERVERROOT conf/*.conf
 f $CUPS_PERM root $CUPS_GROUP $SERVERROOT/cupsd.conf.default conf/cupsd.conf
-f 0644 root $CUPS_GROUP $SERVERROOT/mime.convs conf/mime.convs
-f 0644 root $CUPS_GROUP $SERVERROOT/mime.types conf/mime.types
 
 %if PAMDIR
 d 0755 root sys $PAMDIR -
@@ -643,6 +645,7 @@ f 0644 root sys $MANDIR/man5/printers.conf.$MAN5EXT man/printers.conf.$MAN5EXT
 f 0644 root sys $MANDIR/man7/backend.$MAN7EXT man/backend.$MAN7EXT
 f 0644 root sys $MANDIR/man7/commandtoescpx.$MAN7EXT man/commandtoescpx.$MAN7EXT
 f 0644 root sys $MANDIR/man7/commandtopclx.$MAN7EXT man/commandtopclx.$MAN7EXT
+f 0644 root sys $MANDIR/man7/drv.$MAN7EXT man/drv.$MAN7EXT
 f 0644 root sys $MANDIR/man7/filter.$MAN7EXT man/filter.$MAN7EXT
 f 0644 root sys $MANDIR/man7/rastertoescpx.$MAN7EXT man/rastertoescpx.$MAN7EXT
 f 0644 root sys $MANDIR/man7/rastertopclx.$MAN7EXT man/rastertopclx.$MAN7EXT
diff --git a/packaging/cups.spec.in b/packaging/cups.spec.in
index 8deff15b5..4e564c176 100644
--- a/packaging/cups.spec.in
+++ b/packaging/cups.spec.in
@@ -157,8 +157,6 @@ rm -rf $RPM_BUILD_ROOT
 %config(noreplace) /etc/cups/*.conf
 /etc/cups/cupsd.conf.default
 %dir /etc/cups/interfaces
-/etc/cups/mime.types
-/etc/cups/mime.convs
 %dir /etc/cups/ppd
 %attr(0700,root,root) %dir /etc/cups/ssl
 
@@ -237,6 +235,8 @@ rm -rf $RPM_BUILD_ROOT
 /usr/share/cups/drv/*
 %dir /usr/share/cups/fonts
 /usr/share/cups/fonts/*
+%dir /usr/share/cups/mime
+/usr/share/cups/mime/*
 %dir /usr/share/cups/model
 %dir /usr/share/cups/ppdc
 /usr/share/cups/ppdc/*
@@ -280,6 +280,7 @@ rm -rf $RPM_BUILD_ROOT
 /usr/share/man/man5/mime.*.5.gz
 %dir /usr/share/man/man7
 /usr/share/man/man7/commandto*
+/usr/share/man/man7/drv*
 /usr/share/man/man7/rasterto*
 %dir /usr/share/man/man8
 /usr/share/man/man8/accept.8.gz
diff --git a/ppdc/ppdmerge.cxx b/ppdc/ppdmerge.cxx
index 1db93444f..fec8b3b69 100644
--- a/ppdc/ppdmerge.cxx
+++ b/ppdc/ppdmerge.cxx
@@ -296,27 +296,29 @@ ppd_locale(ppd_file_t *ppd)		// I - PPD file
 		*language;		// Language code */
   }		languages[] =
   {
-    { "chinese",	"zh" },
-    { "czech",		"cs" },
-    { "danish",		"da" },
-    { "dutch",		"nl" },
-    { "english",	"en" },
-    { "finnish",	"fi" },
-    { "french",		"fr" },
-    { "german",		"de" },
-    { "greek",		"el" },
-    { "hungarian",	"hu" },
-    { "italian",	"it" },
-    { "japanese",	"ja" },
-    { "korean",		"ko" },
-    { "norwegian",	"no" },
-    { "polish",		"pl" },
-    { "portuguese",	"pt" },
-    { "russian",	"ru" },
-    { "slovak",		"sk" },
-    { "spanish",	"es" },
-    { "swedish",	"sv" },
-    { "turkish",	"tr" }
+    { "chinese",		"zh" },
+    { "czech",			"cs" },
+    { "danish",			"da" },
+    { "dutch",			"nl" },
+    { "english",		"en" },
+    { "finnish",		"fi" },
+    { "french",			"fr" },
+    { "german",			"de" },
+    { "greek",			"el" },
+    { "hungarian",		"hu" },
+    { "italian",		"it" },
+    { "japanese",		"ja" },
+    { "korean",			"ko" },
+    { "norwegian",		"no" },
+    { "polish",			"pl" },
+    { "portuguese",		"pt" },
+    { "russian",		"ru" },
+    { "simplified chinese",	"zh_CN" },
+    { "slovak",			"sk" },
+    { "spanish",		"es" },
+    { "swedish",		"sv" },
+    { "traditional chinese",	"zh_TW" },
+    { "turkish",		"tr" }
   };
 
 
diff --git a/scheduler/auth.c b/scheduler/auth.c
index 4447ba1b0..f065a1f51 100644
--- a/scheduler/auth.c
+++ b/scheduler/auth.c
@@ -1404,7 +1404,7 @@ cupsdCheckGroup(
   * Check group membership through MacOS X membership API...
   */
 
-  if (!mbr_uid_to_uuid(user->pw_uid, useruuid))
+  if (user && !mbr_uid_to_uuid(user->pw_uid, useruuid))
   {
     if (group)
     {
diff --git a/scheduler/conf.c b/scheduler/conf.c
index 20a5edd66..c9eb950fa 100644
--- a/scheduler/conf.c
+++ b/scheduler/conf.c
@@ -346,6 +346,7 @@ cupsdReadConfiguration(void)
   cups_file_t	*fp;			/* Configuration file */
   int		status;			/* Return status */
   char		temp[1024],		/* Temporary buffer */
+		mimedir[1024],		/* MIME directory */
 		*slash;			/* Directory separator */
   cups_lang_t	*language;		/* Language */
   struct passwd	*user;			/* Default user */
@@ -1113,6 +1114,7 @@ cupsdReadConfiguration(void)
     */
 
     snprintf(temp, sizeof(temp), "%s/filter", ServerBin);
+    snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir);
 
     MimeDatabase = mimeLoad(ServerRoot, temp);
 
@@ -1123,6 +1125,9 @@ cupsdReadConfiguration(void)
       exit(errno);
     }
 
+    if (!access(mimedir, 0))
+      MimeDatabase = mimeMerge(MimeDatabase, mimedir, temp);
+
     cupsdLogMessage(CUPSD_LOG_INFO,
                     "Loaded MIME database from \'%s\': %d types, %d filters...",
                     ServerRoot, mimeNumTypes(MimeDatabase),
@@ -2868,9 +2873,11 @@ read_configuration(cups_file_t *fp)	/* I - File to read from */
       * Do hostname lookups?
       */
 
-      if (!strcasecmp(value, "off"))
+      if (!strcasecmp(value, "off") || !strcasecmp(value, "no") ||
+          !strcasecmp(value, "false"))
         HostNameLookups = 0;
-      else if (!strcasecmp(value, "on"))
+      else if (!strcasecmp(value, "on") || !strcasecmp(value, "yes") ||
+          !strcasecmp(value, "true"))
         HostNameLookups = 1;
       else if (!strcasecmp(value, "double"))
         HostNameLookups = 2;
diff --git a/scheduler/cups-driverd.c b/scheduler/cups-driverd.c
index 7325f6073..013f1de89 100644
--- a/scheduler/cups-driverd.c
+++ b/scheduler/cups-driverd.c
@@ -1079,27 +1079,29 @@ load_ppds(const char *d,		/* I - Actual directory */
 		*language;		/* Language code */
   }		languages[] =
   {
-    { "chinese",	"zh" },
-    { "czech",		"cs" },
-    { "danish",		"da" },
-    { "dutch",		"nl" },
-    { "english",	"en" },
-    { "finnish",	"fi" },
-    { "french",		"fr" },
-    { "german",		"de" },
-    { "greek",		"el" },
-    { "hungarian",	"hu" },
-    { "italian",	"it" },
-    { "japanese",	"ja" },
-    { "korean",		"ko" },
-    { "norwegian",	"no" },
-    { "polish",		"pl" },
-    { "portuguese",	"pt" },
-    { "russian",	"ru" },
-    { "slovak",		"sk" },
-    { "spanish",	"es" },
-    { "swedish",	"sv" },
-    { "turkish",	"tr" }
+    { "chinese",		"zh" },
+    { "czech",			"cs" },
+    { "danish",			"da" },
+    { "dutch",			"nl" },
+    { "english",		"en" },
+    { "finnish",		"fi" },
+    { "french",			"fr" },
+    { "german",			"de" },
+    { "greek",			"el" },
+    { "hungarian",		"hu" },
+    { "italian",		"it" },
+    { "japanese",		"ja" },
+    { "korean",			"ko" },
+    { "norwegian",		"no" },
+    { "polish",			"pl" },
+    { "portuguese",		"pt" },
+    { "russian",		"ru" },
+    { "simplified chinese",	"zh_CN" },
+    { "slovak",			"sk" },
+    { "spanish",		"es" },
+    { "swedish",		"sv" },
+    { "traditional chinese",	"zh_TW" },
+    { "turkish",		"tr" }
   };
 
 
diff --git a/scheduler/cupsfilter.c b/scheduler/cupsfilter.c
index abe1092d5..3ece2f4b2 100644
--- a/scheduler/cupsfilter.c
+++ b/scheduler/cupsfilter.c
@@ -110,6 +110,7 @@ main(int  argc,				/* I - Number of command-line args */
   int		compression;		/* Compression of file */
   int		cost;			/* Cost of filters */
   mime_t	*mime;			/* MIME database */
+  char		mimedir[1024];		/* MIME directory */
   char		*infile,		/* File to filter */
 		*outfile;		/* File to create */
   char		cupsdconf[1024];	/* cupsd.conf file */
@@ -360,6 +361,10 @@ main(int  argc,				/* I - Number of command-line args */
     return (1);
   }
 
+  snprintf(mimedir, sizeof(mimedir), "%s/mime", DataDir);
+  if (!access(mimedir, 0))
+    mime = mimeMerge(mime, mimedir, Path);
+
  /*
   * Get the source and destination types...
   */
diff --git a/scheduler/ipp.c b/scheduler/ipp.c
index 58e27f2f2..ac80acb7f 100644
--- a/scheduler/ipp.c
+++ b/scheduler/ipp.c
@@ -5387,6 +5387,40 @@ copy_printer_attrs(
     ippAddInteger(con->response, IPP_TAG_PRINTER, IPP_TAG_INTEGER,
                   "marker-change-time", printer->marker_time);
 
+  if (printer->num_printers > 0 &&
+      (!ra || cupsArrayFind(ra, "member-uris")))
+  {
+    ipp_attribute_t	*member_uris;	/* member-uris attribute */
+    cupsd_printer_t	*p2;		/* Printer in class */
+    ipp_attribute_t	*p2_uri;	/* printer-uri-supported for class printer */
+
+
+    if ((member_uris = ippAddStrings(con->response, IPP_TAG_PRINTER,
+                                     IPP_TAG_URI, "member-uris",
+				     printer->num_printers, NULL,
+				     NULL)) != NULL)
+    {
+      for (i = 0; i < printer->num_printers; i ++)
+      {
+        p2 = printer->printers[i];
+
+        if ((p2_uri = ippFindAttribute(p2->attrs, "printer-uri-supported",
+	                               IPP_TAG_URI)) != NULL)
+          member_uris->values[i].string.text =
+	      _cupsStrAlloc(p2_uri->values[0].string.text);
+        else
+	{
+	  httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri,
+	                   sizeof(printer_uri), "ipp", NULL, con->servername,
+			   con->serverport,
+			   (p2->type & CUPS_PRINTER_CLASS) ?
+			       "/classes/%s" : "/printers/%s", p2->name);
+	  member_uris->values[i].string.text = _cupsStrAlloc(printer_uri);
+        }
+      }
+    }
+  }
+
   if (printer->alert && (!ra || cupsArrayFind(ra, "printer-alert")))
     ippAddString(con->response, IPP_TAG_PRINTER, IPP_TAG_STRING,
                  "printer-alert", NULL, printer->alert);
@@ -7522,7 +7556,8 @@ get_printers(cupsd_client_t *con,	/* I - Client connection */
       * access...
       */
 
-      if (printer->num_users && username && !user_allowed(printer, username))
+      if (!(printer->type & CUPS_PRINTER_AUTHENTICATED) &&
+          printer->num_users && username && !user_allowed(printer, username))
         continue;
 
      /*
@@ -9862,7 +9897,8 @@ set_default(cupsd_client_t  *con,	/* I - Client connection */
 {
   http_status_t		status;		/* Policy status */
   cups_ptype_t		dtype;		/* Destination type (printer/class) */
-  cupsd_printer_t	*printer;	/* Printer */
+  cupsd_printer_t	*printer,	/* Printer */
+			*oldprinter;	/* Old default printer */
 
 
   cupsdLogMessage(CUPSD_LOG_DEBUG2, "set_default(%p[%d], %s)", con,
@@ -9897,8 +9933,16 @@ set_default(cupsd_client_t  *con,	/* I - Client connection */
   * Set it as the default...
   */
 
+  oldprinter     = DefaultPrinter;
   DefaultPrinter = printer;
 
+  if (oldprinter)
+    cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, oldprinter, NULL,
+                  "%s is no longer the default printer.", oldprinter->name);
+
+  cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, printer, NULL,
+		"%s is now the default printer.", printer->name);
+
   cupsdMarkDirty(CUPSD_DIRTY_PRINTERS | CUPSD_DIRTY_CLASSES |
                  CUPSD_DIRTY_REMOTE | CUPSD_DIRTY_PRINTCAP);
 
diff --git a/scheduler/job.c b/scheduler/job.c
index a9c7bc293..68c68651f 100644
--- a/scheduler/job.c
+++ b/scheduler/job.c
@@ -3646,6 +3646,9 @@ update_job(cupsd_job_t *job)		/* I - Job to check */
       * job sheet count...
       */
 
+      if (LogLevel >= CUPSD_LOG_DEBUG)
+        cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] PAGE: %s", job->id, message);
+
       if (job->sheets)
       {
         if (!strncasecmp(message, "total ", 6))
@@ -3697,6 +3700,10 @@ update_job(cupsd_job_t *job)		/* I - Job to check */
     }
     else if (loglevel == CUPSD_LOG_STATE)
     {
+      if (LogLevel >= CUPSD_LOG_DEBUG)
+        cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] STATE: %s", job->id,
+	                message);
+
       if (!strcmp(message, "paused"))
       {
         cupsdStopPrinter(job->printer, 1);
@@ -3722,6 +3729,9 @@ update_job(cupsd_job_t *job)		/* I - Job to check */
       const char	*attr;		/* Attribute */
 
 
+      if (LogLevel >= CUPSD_LOG_DEBUG)
+        cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] ATTR: %s", job->id, message);
+
       num_attrs = cupsParseOptions(message, 0, &attrs);
 
       if ((attr = cupsGetOption("auth-info-required", num_attrs,
@@ -3789,6 +3799,9 @@ update_job(cupsd_job_t *job)		/* I - Job to check */
       cups_option_t	*keywords;	/* Keywords */
 
 
+      if (LogLevel >= CUPSD_LOG_DEBUG)
+        cupsdLogMessage(CUPSD_LOG_DEBUG, "[Job %d] PPD: %s", job->id, message);
+
       num_keywords = cupsParseOptions(message, 0, &keywords);
 
       if (cupsdUpdatePrinterPPD(job->printer, num_keywords, keywords))
diff --git a/scheduler/mime.h b/scheduler/mime.h
index 87e2fa625..975ab79f4 100644
--- a/scheduler/mime.h
+++ b/scheduler/mime.h
@@ -3,7 +3,7 @@
  *
  *   MIME type/conversion database definitions for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2007 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -86,6 +86,7 @@ typedef struct _mime_magic_s		/**** MIME Magic Data ****/
 typedef struct _mime_type_s		/**** MIME Type Data ****/
 {
   mime_magic_t	*rules;			/* Rules used to detect this type */
+  int		priority;		/* Priority of this type */
   char		super[MIME_MAX_SUPER],	/* Super-type name ("image", "application", etc.) */
 		type[MIME_MAX_TYPE];	/* Type name ("png", "postscript", etc.) */
 } mime_type_t;
diff --git a/scheduler/printers.c b/scheduler/printers.c
index 409120564..c2ae13f2c 100644
--- a/scheduler/printers.c
+++ b/scheduler/printers.c
@@ -2156,29 +2156,20 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */
       if (p->num_printers > 0)
       {
        /*
-	* Add a list of member URIs and names...
+	* Add a list of member names; URIs are added in copy_printer_attrs...
 	*/
 
-	attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_URI,
-                             "member-uris", p->num_printers, NULL, NULL);
+	attr    = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
+                                "member-names", p->num_printers, NULL, NULL);
         p->type |= CUPS_PRINTER_OPTIONS;
 
 	for (i = 0; i < p->num_printers; i ++)
 	{
           if (attr != NULL)
-            attr->values[i].string.text = _cupsStrAlloc(p->printers[i]->uri);
+            attr->values[i].string.text = _cupsStrAlloc(p->printers[i]->name);
 
 	  p->type &= ~CUPS_PRINTER_OPTIONS | p->printers[i]->type;
         }
-
-	attr = ippAddStrings(p->attrs, IPP_TAG_PRINTER, IPP_TAG_NAME,
-                             "member-names", p->num_printers, NULL, NULL);
-
-	if (attr != NULL)
-	{
-	  for (i = 0; i < p->num_printers; i ++)
-            attr->values[i].string.text = _cupsStrAlloc(p->printers[i]->name);
-        }
       }
     }
     else
diff --git a/scheduler/testmime.c b/scheduler/testmime.c
index 59288a197..130aaaaa2 100644
--- a/scheduler/testmime.c
+++ b/scheduler/testmime.c
@@ -3,7 +3,7 @@
  *
  *   MIME test program for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
diff --git a/scheduler/testspeed.c b/scheduler/testspeed.c
index 65a0f9ff0..4b740675e 100644
--- a/scheduler/testspeed.c
+++ b/scheduler/testspeed.c
@@ -3,7 +3,7 @@
  *
  *   Scheduler speed test for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2005 by Easy Software Products.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -40,8 +40,9 @@
  * Local functions...
  */
 
-static int	do_test(const char *server, http_encryption_t encryption,
-			int requests, int verbose);
+static int	do_test(const char *server, int port,
+		        http_encryption_t encryption, int requests,
+			int verbose);
 static void	usage(void);
 
 
@@ -55,10 +56,13 @@ main(int  argc,				/* I - Number of command-line arguments */
      char *argv[])			/* I - Command-line arguments */
 {
   int		i;			/* Looping var */
-  const char	*server;		/* Server to use */
+  char		*server,		/* Server to use */
+		*ptr;			/* Pointer to port in server */
+  int		port;			/* Port to use */
   http_encryption_t encryption;		/* Encryption to use */
   int		requests;		/* Number of requests to send */
   int		children;		/* Number of children to fork */
+  int		good_children;		/* Number of children that exited normally */
   int		pid;			/* Child PID */
   int		status;			/* Child status */
   time_t	start,			/* Start time */
@@ -73,81 +77,135 @@ main(int  argc,				/* I - Number of command-line arguments */
 
   requests   = 100;
   children   = 5;
-  server     = cupsServer();
+  server     = (char *)cupsServer();
+  port       = ippPort();
   encryption = HTTP_ENCRYPT_IF_REQUESTED;
   verbose    = 0;
 
   for (i = 1; i < argc; i ++)
-    if (!strcmp(argv[i], "-c"))
+    if (argv[i][0] == '-')
     {
-      i ++;
-      if (i >= argc)
-        usage();
-
-      children = atoi(argv[i]);
+      for (ptr = argv[i] + 1; *ptr; ptr ++)
+        switch (*ptr)
+	{
+	  case 'c' : /* Number of children */
+	      i ++;
+	      if (i >= argc)
+		usage();
+
+	      children = atoi(argv[i]);
+	      break;
+
+          case 'r' : /* Number of requests */
+	      i ++;
+	      if (i >= argc)
+		usage();
+
+	      requests = atoi(argv[i]);
+	      break;
+
+	  case 'E' : /* Enable encryption */
+	      encryption = HTTP_ENCRYPT_REQUIRED;
+	      break;
+
+          case 'v' : /* Verbose logging */
+              verbose ++;
+	      break;
+
+          default :
+              usage();
+	      break;
+        }
     }
-    else if (!strcmp(argv[i], "-r"))
+    else
     {
-      i ++;
-      if (i >= argc)
-        usage();
+      server = argv[i];
 
-      requests = atoi(argv[i]);
+      if (server[0] != '/' && (ptr = strrchr(server, ':')) != NULL)
+      {
+        *ptr++ = '\0';
+	port   = atoi(ptr);
+      }
     }
-    else if (!strcmp(argv[i], "-E"))
-      encryption = HTTP_ENCRYPT_REQUIRED;
-    else if (!strcmp(argv[i], "-v"))
-      verbose ++;
-    else if (argv[i][0] == '-')
-      usage();
-    else
-      server = argv[i];
 
  /*
   * Then create child processes to act as clients...
   */
 
-  printf("testspeed: Simulating %d clients with %d requests to %s with %s encryption...\n",
-         children, requests, server,
-	 encryption == HTTP_ENCRYPT_IF_REQUESTED ? "no" : "");
+  if (children > 0)
+  {
+    printf("testspeed: Simulating %d clients with %d requests to %s with "
+           "%sencryption...\n", children, requests, server,
+	   encryption == HTTP_ENCRYPT_IF_REQUESTED ? "no " : "");
+  }
 
   start = time(NULL);
 
-  if (children == 1)
-  {
-    do_test(server, encryption, requests, verbose);
-  }
+  if (children < 1)
+    return (do_test(server, port, encryption, requests, verbose));
+  else if (children == 1)
+    good_children = do_test(server, port, encryption, requests, verbose) ? 0 : 1;
   else
   {
+    char	options[255],		/* Command-line options for child */
+		reqstr[255],		/* Requests string for child */
+		serverstr[255];		/* Server:port string for child */
+
+
+    snprintf(reqstr, sizeof(reqstr), "%d", requests);
+
+    if (port == 631 || server[0] == '/')
+      strlcpy(serverstr, server, sizeof(serverstr));
+    else
+      snprintf(serverstr, sizeof(serverstr), "%s:%d", server, port);
+
+    strlcpy(options, "-cr", sizeof(options));
+
+    if (encryption == HTTP_ENCRYPT_REQUIRED)
+      strlcat(options, "E", sizeof(options));
+
+    if (verbose)
+      strlcat(options, "v", sizeof(options));
+
     for (i = 0; i < children; i ++)
+    {
+      fflush(stdout);
+
       if ((pid = fork()) == 0)
       {
        /*
 	* Child goes here...
 	*/
 
-	exit(do_test(server, encryption, requests, verbose));
+        execlp(argv[0], argv[0], options, "0", reqstr, serverstr, (char *)NULL);
+	exit(errno);
       }
       else if (pid < 0)
       {
-	perror("fork failed");
+	printf("testspeed: Fork failed: %s\n", strerror(errno));
 	break;
       }
       else
-	printf("testspeed(%d): Started...\n", pid);
+	printf("testspeed: Started child %d...\n", pid);
+    }
 
    /*
     * Wait for children to finish...
     */
 
-    for (;;)
+    puts("testspeed: Waiting for children to finish...");
+
+    for (good_children = 0;;)
     {
       pid = wait(&status);
 
       if (pid < 0 && errno != EINTR)
 	break;
 
-      printf("testspeed(%d): Ended (%d)...\n", pid, status);
+      printf("testspeed: Ended child %d (%d)...\n", pid, status / 256);
+
+      if (!status)
+        good_children ++;
     }
   }
 
@@ -155,12 +213,15 @@ main(int  argc,				/* I - Number of command-line arguments */
   * Compute the total run time...
   */
 
-  end     = time(NULL);
-  elapsed = end - start;
-  i       = children * requests;
+  if (good_children > 0)
+  {
+    end     = time(NULL);
+    elapsed = end - start;
+    i       = good_children * requests;
 
-  printf("testspeed: %dx%d=%d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
-         children, requests, i, elapsed, elapsed / i, i / elapsed);
+    printf("testspeed: %dx%d=%d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
+	   good_children, requests, i, elapsed, elapsed / i, i / elapsed);
+  }
 
  /*
   * Exit with no errors...
@@ -176,18 +237,19 @@ main(int  argc,				/* I - Number of command-line arguments */
 
 static int				/* O - Exit status */
 do_test(const char        *server,	/* I - Server to use */
+        int               port,		/* I - Port number to use */
         http_encryption_t encryption,	/* I - Encryption to use */
 	int               requests,	/* I - Number of requests to send */
 	int               verbose)	/* I - Verbose output? */
 {
   int		i;			/* Looping var */
   http_t	*http;			/* Connection to server */
-  ipp_t		*request,		/* IPP Request */
-		*response;		/* IPP Response */
-  cups_lang_t	*language;		/* Default language */
+  ipp_t		*request;		/* IPP Request */
   struct timeval start,			/* Start time */
 		end;			/* End time */
-  double	elapsed;		/* Elapsed time */
+  double	reqtime,		/* Time for this request */
+		elapsed;		/* Elapsed time */
+  int		op;			/* Current operation */
   static ipp_op_t ops[4] =		/* Operations to test... */
 		{
 		  IPP_PRINT_JOB,
@@ -201,26 +263,19 @@ do_test(const char        *server,	/* I - Server to use */
   * Connect to the server...
   */
 
-  http = httpConnectEncrypt(server, ippPort(), encryption);
-
-  if (http == NULL)
+  if ((http = httpConnectEncrypt(server, port, encryption)) == NULL)
   {
-    perror("testspeed: unable to connect to server");
+    printf("testspeed(%d): unable to connect to server - %s\n", (int)getpid(),
+           strerror(errno));
     return (1);
   }
 
-  language = cupsLangDefault();
-
  /*
   * Do multiple requests...
   */
 
   for (elapsed = 0.0, i = 0; i < requests; i ++)
   {
-    if (verbose && (i % 10) == 0)
-      printf("testspeed(%d): %d%% complete...\n", (int)getpid(),
-             i * 100 / requests);
-
    /*
     * Build a request which requires the following attributes:
     *
@@ -230,47 +285,63 @@ do_test(const char        *server,	/* I - Server to use */
     * In addition, IPP_GET_JOBS needs a printer-uri attribute.
     */
 
-    request = ippNew();
-
-    request->request.op.operation_id = ops[i & 3];
-    request->request.op.request_id   = 1;
-
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
-        	 "attributes-charset", NULL, cupsLangEncoding(language));
-
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
-        	 "attributes-natural-language", NULL, language->language);
+    op      = ops[i & 3];
+    request = ippNewRequest(op);
 
     gettimeofday(&start, NULL);
 
-    switch (request->request.op.operation_id)
+    if (verbose)
+      printf("testspeed(%d): %.6f %s ", (int)getpid(), elapsed,
+	     ippOpString(op));
+
+    switch (op)
     {
       case IPP_GET_JOBS :
 	  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                        NULL, "ipp://localhost/printers/");
 
       default :
-	  response = cupsDoRequest(http, request, "/");
+	  ippDelete(cupsDoRequest(http, request, "/"));
           break;
 
       case IPP_PRINT_JOB :
 	  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                        NULL, "ipp://localhost/printers/test");
-	  response = cupsDoFileRequest(http, request, "/printers/test",
-	                               "../data/testprint.ps");
+          ippAddString(request, IPP_TAG_JOB, IPP_TAG_KEYWORD, "job-hold-until",
+	               NULL, "indefinite");
+	  ippDelete(cupsDoFileRequest(http, request, "/printers/test",
+	                              "../data/testprint.ps"));
           break;
     }
 
     gettimeofday(&end, NULL);
 
-    if (response != NULL)
-      ippDelete(response);
+    reqtime = (end.tv_sec - start.tv_sec) +
+              0.000001 * (end.tv_usec - start.tv_usec);
+    elapsed += reqtime;
+
+    switch (cupsLastError())
+    {
+      case IPP_OK :
+      case IPP_NOT_FOUND :
+          if (verbose)
+	  {
+	    printf("succeeded: %s (%.6f)\n", cupsLastErrorString(), reqtime);
+	    fflush(stdout);
+	  }
+          break;
 
-    elapsed += (end.tv_sec - start.tv_sec) +
-               0.000001 * (end.tv_usec - start.tv_usec);
+      default :
+          if (!verbose)
+	    printf("testspeed(%d): %s ", (int)getpid(),
+	           ippOpString(ops[i & 3]));
+
+	  printf("failed: %s\n", cupsLastErrorString());
+          httpClose(http);
+	  return (1);
+    }
   }
 
-  cupsLangFree(language);
   httpClose(http);
 
   printf("testspeed(%d): %d requests in %.1fs (%.3fs/r, %.1fr/s)\n",
@@ -287,7 +358,8 @@ do_test(const char        *server,	/* I - Server to use */
 static void
 usage(void)
 {
-  puts("Usage: testspeed [-c children] [-h] [-r requests] [-v] [-E] hostname");
+  puts("Usage: testspeed [-c children] [-h] [-r requests] [-v] [-E] "
+       "hostname[:port]");
   exit(0);
 }
 
diff --git a/scheduler/type.c b/scheduler/type.c
index e56bf02d4..f40d10b2b 100644
--- a/scheduler/type.c
+++ b/scheduler/type.c
@@ -3,7 +3,7 @@
  *
  *   MIME typing routines for the Common UNIX Printing System (CUPS).
  *
- *   Copyright 2007 by Apple Inc.
+ *   Copyright 2007-2008 by Apple Inc.
  *   Copyright 1997-2006 by Easy Software Products, all rights reserved.
  *
  *   These coded instructions, statements, and computer programs are the
@@ -102,6 +102,7 @@ mimeAddType(mime_t     *mime,		/* I - MIME database */
 
   strlcpy(temp->super, super, sizeof(temp->super));
   strcpy(temp->type, type);		/* Safe: temp->type is allocated */
+  temp->priority = 100;
 
   cupsArrayAdd(mime->types, temp);
 
@@ -396,6 +397,11 @@ mimeAddTypeRule(mime_type_t *mt,	/* I - Type to add to */
 	  op = MIME_MAGIC_LOCALE;
 	else if (!strcmp(name, "contains"))
 	  op = MIME_MAGIC_CONTAINS;
+	else if (!strcmp(name, "priority") && num_values == 1)
+	{
+	  mt->priority = atoi(value[0]);
+	  continue;
+	}
 	else
 	  return (-1);
       }
@@ -532,7 +538,8 @@ mimeFileType(mime_t     *mime,		/* I - MIME database */
 {
   _mime_filebuf_t	fb;		/* File buffer */
   const char		*base;		/* Base filename of file */
-  mime_type_t		*type;		/* File type */
+  mime_type_t		*type,		/* File type */
+			*best;		/* Best match */
 
 
   DEBUG_printf(("mimeFileType(mime=%p, pathname=\"%s\", filename=\"%s\", "
@@ -578,11 +585,14 @@ mimeFileType(mime_t     *mime,		/* I - MIME database */
   * Then check it against all known types...
   */
 
-  for (type = (mime_type_t *)cupsArrayFirst(mime->types);
+  for (type = (mime_type_t *)cupsArrayFirst(mime->types), best = NULL;
        type;
        type = (mime_type_t *)cupsArrayNext(mime->types))
     if (checkrules(base, &fb, type->rules))
-      break;
+    {
+      if (!best || type->priority > best->priority)
+        best = type;
+    }
 
  /*
   * Finally, close the file and return a match (if any)...
@@ -593,7 +603,7 @@ mimeFileType(mime_t     *mime,		/* I - MIME database */
 
   cupsFileClose(fb.fp);
 
-  return (type);
+  return (best);
 }
 
 
diff --git a/systemv/cupstestppd.c b/systemv/cupstestppd.c
index 3e9b87416..e11f6dc46 100644
--- a/systemv/cupstestppd.c
+++ b/systemv/cupstestppd.c
@@ -141,12 +141,14 @@ main(int  argc,				/* I - Number of command-line args */
   ppd_group_t	*group2;		/* UI group */
   ppd_option_t	*option2;		/* Standard UI option */
   ppd_choice_t	*choice;		/* Standard UI option choice */
+  struct lconv	*loc;			/* Locale data */
   static char	*uis[] = { "BOOLEAN", "PICKONE", "PICKMANY" };
   static char	*sections[] = { "ANY", "DOCUMENT", "EXIT",
                                 "JCL", "PAGE", "PROLOG" };
 
 
   _cupsSetLocale(argv);
+  loc = localeconv();
 
  /*
   * Display PPD files for each file listed on the command-line...
@@ -370,7 +372,7 @@ main(int  argc,				/* I - Number of command-line args */
 
       if ((attr = ppdFindAttr(ppd, "FormatVersion", NULL)) != NULL &&
           attr->value)
-        ppdversion = (int)(10 * atof(attr->value) + 0.5);
+        ppdversion = (int)(10 * _cupsStrScand(attr->value, NULL, loc) + 0.5);
 
       for (j = 0; j < ppd->num_filters; j ++)
         if (strstr(ppd->filters[j], "application/vnd.cups-raster"))
diff --git a/systemv/lpoptions.c b/systemv/lpoptions.c
index c9094c709..132523be6 100644
--- a/systemv/lpoptions.c
+++ b/systemv/lpoptions.c
@@ -35,9 +35,9 @@
  * Local functions...
  */
 
-void	list_group(ppd_group_t *group);
-void	list_options(cups_dest_t *dest);
-void	usage(void);
+static void	list_group(ppd_file_t *ppd, ppd_group_t *group);
+static void	list_options(cups_dest_t *dest);
+static void	usage(void);
 
 
 /*
@@ -400,21 +400,80 @@ main(int  argc,				/* I - Number of command-line arguments */
  * 'list_group()' - List printer-specific options from the PPD group.
  */
 
-void
-list_group(ppd_group_t *group)	/* I - Group to show */
+static void
+list_group(ppd_file_t  *ppd,		/* I - PPD file */
+           ppd_group_t *group)		/* I - Group to show */
 {
-  int		i, j;		/* Looping vars */
-  ppd_option_t	*option;	/* Current option */
-  ppd_choice_t	*choice;	/* Current choice */
-  ppd_group_t	*subgroup;	/* Current subgroup */
+  int		i, j;			/* Looping vars */
+  ppd_option_t	*option;		/* Current option */
+  ppd_choice_t	*choice;		/* Current choice */
+  ppd_group_t	*subgroup;		/* Current subgroup */
 
 
   for (i = group->num_options, option = group->options; i > 0; i --, option ++)
   {
+    if (!strcasecmp(option->keyword, "PageRegion"))
+      continue;
+
     _cupsLangPrintf(stdout, "%s/%s:", option->keyword, option->text);
 
-    for (j = option->num_choices, choice = option->choices; j > 0; j --, choice ++)
-      if (choice->marked)
+    for (j = option->num_choices, choice = option->choices;
+         j > 0;
+	 j --, choice ++)
+      if (!strcasecmp(choice->choice, "Custom"))
+      {
+        ppd_coption_t	*coption;	/* Custom option */
+        ppd_cparam_t	*cparam;	/* Custom parameter */
+	static const char * const types[] =
+	{				/* Parameter types */
+	  "CURVE",
+	  "INTEGER",
+	  "INVCURVE",
+	  "PASSCODE",
+	  "PASSWORD",
+	  "POINTS",
+	  "REAL",
+	  "STRING"
+	};
+
+
+        if ((coption = ppdFindCustomOption(ppd, option->keyword)) == NULL ||
+	    cupsArrayCount(coption->params) == 0)
+	  _cupsLangPrintf(stdout, " %sCustom", choice->marked ? "*" : "");
+        else if (!strcasecmp(option->keyword, "PageSize") ||
+	        !strcasecmp(option->keyword, "PageRegion"))
+	  _cupsLangPrintf(stdout, " %sCustom.WIDTHxHEIGHT",
+	                  choice->marked ? "*" : "");
+        else
+	{
+	  cparam = (ppd_cparam_t *)cupsArrayFirst(coption->params);
+
+	  if (cupsArrayCount(coption->params) == 1)
+	    _cupsLangPrintf(stdout, " %sCustom.%s", choice->marked ? "*" : "",
+	                    types[cparam->type]);
+	  else
+	  {
+	    const char	*prefix;	/* Prefix string */
+
+
+            if (choice->marked)
+	      prefix = " *{";
+	    else
+	      prefix = " {";
+
+	    while (cparam)
+	    {
+	      _cupsLangPrintf(stdout, "%s%s=%s", choice->marked ? "*" : "",
+			      cparam->name, types[cparam->type]);
+	      cparam = (ppd_cparam_t *)cupsArrayNext(coption->params);
+	      prefix = " ";
+	    }
+
+	    _cupsLangPuts(stdout, "}");
+	  }
+	}
+      }
+      else if (choice->marked)
         _cupsLangPrintf(stdout, " *%s", choice->choice);
       else
         _cupsLangPrintf(stdout, " %s", choice->choice);
@@ -423,7 +482,7 @@ list_group(ppd_group_t *group)	/* I - Group to show */
   }
 
   for (i = group->num_subgroups, subgroup = group->subgroups; i > 0; i --, subgroup ++)
-    list_group(subgroup);
+    list_group(ppd, subgroup);
 }
 
 
@@ -431,13 +490,13 @@ list_group(ppd_group_t *group)	/* I - Group to show */
  * 'list_options()' - List printer-specific options from the PPD file.
  */
 
-void
-list_options(cups_dest_t *dest)	/* I - Destination to list */
+static void
+list_options(cups_dest_t *dest)		/* I - Destination to list */
 {
-  int		i;		/* Looping var */
-  const char	*filename;	/* PPD filename */
-  ppd_file_t	*ppd;		/* PPD data */
-  ppd_group_t	*group;		/* Current group */
+  int		i;			/* Looping var */
+  const char	*filename;		/* PPD filename */
+  ppd_file_t	*ppd;			/* PPD data */
+  ppd_group_t	*group;			/* Current group */
 
 
   if ((filename = cupsGetPPD(dest->name)) == NULL)
@@ -461,7 +520,7 @@ list_options(cups_dest_t *dest)	/* I - Destination to list */
   cupsMarkOptions(ppd, dest->num_options, dest->options);
 
   for (i = ppd->num_groups, group = ppd->groups; i > 0; i --, group ++)
-    list_group(group);
+    list_group(ppd, group);
 
   ppdClose(ppd);
   unlink(filename);
@@ -472,7 +531,7 @@ list_options(cups_dest_t *dest)	/* I - Destination to list */
  * 'usage()' - Show program usage and exit.
  */
 
-void
+static void
 usage(void)
 {
   _cupsLangPuts(stdout,
diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh
index 364e31b80..89fb1d800 100755
--- a/test/run-stp-tests.sh
+++ b/test/run-stp-tests.sh
@@ -472,7 +472,8 @@ done
 # Create the test report source file...
 #
 
-strfile=/tmp/cups-$user/cups-str-1.4-`date +%Y-%m-%d`-$user.html
+date=`date "+%Y-%m-%d"`
+strfile=/tmp/cups-$user/cups-str-1.4-$date-$user.html
 
 rm -f $strfile
 cat str-header.html >$strfile
@@ -516,7 +517,7 @@ echo "Running command tests..."
 echo "

2 - Command Tests

" >>$strfile echo "

This section provides the results to the command tests" >>$strfile echo "outlined in the CUPS Software Test Plan. These tests were run on" >>$strfile -echo `date "+%Y-%m-%d"` by $user on `hostname`. >>$strfile +echo $date by $user on `hostname`. >>$strfile echo "

" >>$strfile
 
 for file in 5*.sh; do
@@ -734,6 +735,8 @@ echo ""
 
 if test $fail != 0; then
 	echo "$fail tests failed."
+	cp /tmp/cups-$user/log/error_log error_log-$date-$user
+	cp $strfile .
 else
 	echo "All tests were successful."
 fi
@@ -743,6 +746,10 @@ echo "A HTML report was created in $strfile."
 echo ""
 
 if test $fail != 0; then
+	echo "Copies of the error_log and `basename $strfile` files are in"
+	echo "`pwd`."
+	echo ""
+
 	exit 1
 fi
 
-- 
2.39.2