From 839a51c83c61febe8d4c9ba56f6a05fce3d03710 Mon Sep 17 00:00:00 2001 From: msweet Date: Wed, 9 Apr 2008 22:42:49 +0000 Subject: [PATCH] Merge changes from CUPS 1.4svn-r7394. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@702 a1ca3aef-8c08-0410-bb20-df032aa958be --- CHANGES-1.3.txt | 26 ++ CHANGES.txt | 12 +- INSTALL.txt | 4 +- Makedefs.in | 2 +- backend/Makefile | 2 +- backend/usb-unix.c | 5 +- cgi-bin/Makefile | 1 - cgi-bin/admin.c | 26 +- cgi-bin/search.c | 4 +- conf/cupsd.conf.in | 39 ++ config-scripts/cups-common.m4 | 11 +- config-scripts/cups-compiler.m4 | 16 +- config-scripts/cups-pap.m4 | 10 +- cups/Makefile | 1 - cups/adminutil.c | 3 + cups/http-private.h | 6 + cups/http-support.c | 17 + cups/http.c | 20 +- cups/libcups.exp | 1 + cups/ppd.c | 2 +- doc/help/spec-ppd.html | 10 +- driver/Makefile | 1 - driver/pcl-common.h | 2 +- driver/rastertoescpx.c | 86 +++- driver/rastertopclx.c | 85 +++- filter/Makefile | 1 - filter/image-gif.c | 3 +- filter/image-png.c | 46 +- filter/pdftops.c | 35 +- filter/rastertoepson.c | 130 +++--- filter/rastertohp.c | 120 ++--- filter/rastertolabel.c | 85 ++-- install-sh | 18 +- man/ppdpo.man | 20 +- ppdc/Makefile | 1 - ppdc/ppdc-catalog.cxx | 775 ++++++++++++++++++++++++++------ ppdc/ppdmerge.cxx | 2 + scheduler/Makefile | 1 - scheduler/client.c | 4 +- scheduler/cups-driverd.c | 14 +- scheduler/ipp.c | 10 +- scheduler/log.c | 19 +- scripting/php/Makefile | 2 +- test/4.3-job-ops.test | 50 ++- test/5.5-lp.sh | 30 +- test/5.6-lpr.sh | 30 +- test/5.7-lprm.sh | 4 + test/5.8-cancel.sh | 4 +- test/run-stp-tests.sh | 215 +++++++-- test/str-header.html | 16 +- test/waitjobs.sh | 37 ++ tools/testosx | 2 +- 52 files changed, 1520 insertions(+), 546 deletions(-) create mode 100755 test/waitjobs.sh diff --git a/CHANGES-1.3.txt b/CHANGES-1.3.txt index 0da640d7b..e2b84293e 100644 --- a/CHANGES-1.3.txt +++ b/CHANGES-1.3.txt @@ -1,8 +1,34 @@ CHANGES-1.3.txt --------------- +CHANGES IN CUPS V1.3.8 + + - Documentation updates (STR #2785) + - The scheduler did not reject requests with an empty + Content-Length field (STR #2787) + - The web interface allowed the creation and cancellation + of RSS subscriptions without a username (STR #2774) + - The PNG image loading code would crash with large images + (STR #2790) + - The scheduler did not log the current date and time and + did not escape special characters in request URIs when + logging bad requests to the access_log file (STR #2788) + + CHANGES IN CUPS V1.3.7 + - CVE-2008-0047: cgiCompileSearch buffer overflow (STR #2729) + - CVE-2008-1373: CUPS GIF image filter overflow (STR #2765) + - Updated the "make check" tests to do a more thorough + automated test. + - cups-driverd complained about missing directories (STR + #2777) + - cupsaddsmb would leave the Samba username and password on + disk if no Windows drivers were installed (STR #2779) + - The Linux USB backend used 100% CPU when a printer was + disconnected (STR #2769) + - The sample raster drivers did not properly handle SIGTERM + (STR #2770) - The scheduler sent notify_post() messages too often on Mac OS X. - Kerberos access to the web interface did not work diff --git a/CHANGES.txt b/CHANGES.txt index 5d4c25186..7c0a2f2b2 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,18 @@ -CHANGES.txt - 2008-03-21 +CHANGES.txt - 2008-04-08 ------------------------ CHANGES IN CUPS V1.4b1 + - Added --enable-pap configure option. + - The default cupsd.conf file now includes an "authenticated" + policy which requires authentication for remote print jobs. + - Added support for Czech and Hungarian in PPD files + (STR #2735, STR #2736) + - The PPD compiler tools now support Mac OS X .strings files + for localization (STR #2737) + - ppdOpen*() now default the colorspace member to PPD_CS_N + when no DefaultColorSpace attribute is present in the PPD + file. - The build system has been updated to support separate installation of data, program, header, and library files. - All support libraries are now built as shared libraries diff --git a/INSTALL.txt b/INSTALL.txt index 6ca73c64f..ba785ed4d 100644 --- a/INSTALL.txt +++ b/INSTALL.txt @@ -1,4 +1,4 @@ -INSTALL - CUPS v1.4svn - 2008-01-22 +INSTALL - CUPS v1.4svn - 2008-04-08 ----------------------------------- This file describes how to compile and install CUPS from source @@ -33,7 +33,7 @@ BEFORE YOU BEGIN many of the features provided by CUPS. Kerberos support requires MIT Kerberos 1.6.3 or later or - or Heimdal Kerberos, along with the corresponding GSSAPI + Heimdal Kerberos, along with the corresponding GSSAPI pieces. Also, please note that CUPS no longer includes the diff --git a/Makedefs.in b/Makedefs.in index cb771a0fa..d4a8929d6 100644 --- a/Makedefs.in +++ b/Makedefs.in @@ -35,7 +35,7 @@ RM = @RM@ -f RMDIR = @RMDIR@ SED = @SED@ SHELL = /bin/sh -STRIP = @STRIP@ + # # Installation programs... diff --git a/backend/Makefile b/backend/Makefile index ff3cdcf3a..c898b3db0 100644 --- a/backend/Makefile +++ b/backend/Makefile @@ -70,7 +70,7 @@ install-data: install-exec: $(INSTALL_DIR) -m 755 $(SERVERBIN)/backend for file in $(RBACKENDS); do \ - $(LIBTOOL) $(INSTALL) -m 700 $$file $(SERVERBIN)/backend; \ + $(LIBTOOL) $(INSTALL_BIN) -m 700 $$file $(SERVERBIN)/backend; \ done for file in $(UBACKENDS); do \ $(INSTALL_BIN) $$file $(SERVERBIN)/backend; \ diff --git a/backend/usb-unix.c b/backend/usb-unix.c index 64215815e..f18061065 100644 --- a/backend/usb-unix.c +++ b/backend/usb-unix.c @@ -415,11 +415,10 @@ open_device(const char *uri, /* I - Device URI */ */ if (busy) - { _cupsLangPuts(stderr, _("INFO: Printer busy; will retry in 5 seconds...\n")); - sleep(5); - } + + sleep(5); } } #elif defined(__sun) && defined(ECPPIOC_GETDEVID) diff --git a/cgi-bin/Makefile b/cgi-bin/Makefile index 4122d37ee..9a49370f6 100644 --- a/cgi-bin/Makefile +++ b/cgi-bin/Makefile @@ -139,7 +139,6 @@ install-libs: $(INSTALLSTATIC) $(INSTALL32) $(INSTALL64) $(LN) $(LIBCUPSCGI) $(LIBDIR)/`basename $(LIBCUPSCGI) .1`; \ fi if test $(LIBCUPSCGI) = "libcupscgi.1.dylib"; then \ - $(STRIP) -x $(LIBDIR)/$(LIBCUPSCGI); \ $(RM) $(LIBDIR)/libcupscgi.dylib; \ $(LN) $(LIBCUPSCGI) $(LIBDIR)/libcupscgi.dylib; \ fi diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c index 6fa500d71..b54d27fdc 100644 --- a/cgi-bin/admin.c +++ b/cgi-bin/admin.c @@ -308,6 +308,16 @@ do_add_rss_subscription(http_t *http) /* I - HTTP connection */ return; } + /* + * Make sure we have a username... + */ + + if ((user = getenv("REMOTE_USER")) == NULL) + { + puts("Status: 401\n"); + exit(0); + } + /* * Validate the subscription name... */ @@ -352,9 +362,6 @@ do_add_rss_subscription(http_t *http) /* I - HTTP connection */ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, printer_uri); - if ((user = getenv("REMOTE_USER")) == NULL) - user = "guest"; - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user); @@ -1305,6 +1312,16 @@ do_cancel_subscription(http_t *http)/* I - HTTP connection */ return; } + /* + * Require a username... + */ + + if ((user = getenv("REMOTE_USER")) == NULL) + { + puts("Status: 401\n"); + exit(0); + } + /* * Cancel the subscription... */ @@ -1316,9 +1333,6 @@ do_cancel_subscription(http_t *http)/* I - HTTP connection */ ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_INTEGER, "notify-subscription-id", id); - if ((user = getenv("REMOTE_USER")) == NULL) - user = "guest"; - ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "requesting-user-name", NULL, user); diff --git a/cgi-bin/search.c b/cgi-bin/search.c index 4ec4de397..4dc725859 100644 --- a/cgi-bin/search.c +++ b/cgi-bin/search.c @@ -167,7 +167,9 @@ cgiCompileSearch(const char *query) /* I - Query string */ * string + RE overhead... */ - wlen = (sptr - s) + 4 * wlen + 2 * strlen(prefix) + 4; + wlen = (sptr - s) + 2 * 4 * wlen + 2 * strlen(prefix) + 11; + if (lword) + wlen += strlen(lword); if (wlen > slen) { diff --git a/conf/cupsd.conf.in b/conf/cupsd.conf.in index 787c3a07a..40917e9b3 100644 --- a/conf/cupsd.conf.in +++ b/conf/cupsd.conf.in @@ -77,6 +77,45 @@ 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 + Satisfy any + + + # All administration operations require an administrator to authenticate... + + AuthType Default + Require user @SYSTEM + Order deny,allow + + + # All printer operations require a printer operator to authenticate... + + AuthType Default + Require user @CUPS_DEFAULT_PRINTADMIN_AUTH@ + Order deny,allow + + + # Only the owner or an administrator can cancel or authenticate a job... + + Require user @OWNER @CUPS_DEFAULT_PRINTADMIN_AUTH@ + Order deny,allow + AuthType Default + Satisfy any + + + + Order deny,allow + AuthType Default + Satisfy any + + + # # End of "$Id: cupsd.conf.in 6720 2007-07-25 00:40:03Z mike $". # diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 index 7236aebc0..c643663b0 100644 --- a/config-scripts/cups-common.m4 +++ b/config-scripts/cups-common.m4 @@ -42,11 +42,6 @@ AC_PROG_AWK AC_PROG_CC AC_PROG_CPP AC_PROG_CXX -AC_PROG_INSTALL -if test "$INSTALL" = "$ac_install_sh"; then - # Use full path to install-sh script... - INSTALL="`pwd`/install-sh -c" -fi AC_PROG_RANLIB AC_PATH_PROG(AR,ar) AC_PATH_PROG(HTMLDOC,htmldoc) @@ -56,7 +51,11 @@ AC_PATH_PROG(MV,mv) AC_PATH_PROG(RM,rm) AC_PATH_PROG(RMDIR,rmdir) AC_PATH_PROG(SED,sed) -AC_PATH_PROG(STRIP,strip) + +AC_MSG_CHECKING(for install-sh script) +INSTALL="`pwd`/install-sh -c" +AC_SUBST(INSTALL) +AC_MSG_RESULT(using $INSTALL) if test "x$AR" = x; then AC_MSG_ERROR([Unable to find required library archive command.]) diff --git a/config-scripts/cups-compiler.m4 b/config-scripts/cups-compiler.m4 index 07faa0c4b..1fb08a520 100644 --- a/config-scripts/cups-compiler.m4 +++ b/config-scripts/cups-compiler.m4 @@ -21,12 +21,14 @@ AC_SUBST(INSTALL_STRIP) AC_SUBST(OPTIM) AC_ARG_WITH(optim, [ --with-optim="flags" set optimization flags ]) -AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging, default=no], - [if test x$enable_debug = xyes; then - OPTIM="-g" - else - INSTALL_STRIP="-s" - fi]) +AC_ARG_ENABLE(debug, [ --enable-debug turn on debugging, default=no]) + +dnl For debugging, keep symbols, otherwise strip them... +if test x$enable_debug = xyes; then + OPTIM="-g" +else + INSTALL_STRIP="-s" +fi dnl Setup general architecture flags... AC_ARG_WITH(archflags, [ --with-archflags="flags" @@ -48,7 +50,7 @@ if test -z "$with_ldarchflags"; then LDARCHFLAGS="$ARCHFLAGS" fi else - LDARCHFLAGS="$with_archflags" + LDARCHFLAGS="$with_ldarchflags" fi AC_SUBST(ARCHFLAGS) diff --git a/config-scripts/cups-pap.m4 b/config-scripts/cups-pap.m4 index b1fe05bc6..ec52d3c5f 100644 --- a/config-scripts/cups-pap.m4 +++ b/config-scripts/cups-pap.m4 @@ -3,7 +3,7 @@ dnl "$Id: cups-pam.m4 5466 2006-04-26 19:52:27Z mike $" dnl dnl PAP (AppleTalk) stuff for the Common UNIX Printing System (CUPS). dnl -dnl Copyright 2007 by Apple Inc. +dnl Copyright 2007-2008 by Apple Inc. dnl Copyright 2006 by Easy Software Products, all rights reserved. dnl dnl These coded instructions, statements, and computer programs are the @@ -15,14 +15,16 @@ dnl # Currently the PAP backend is only supported on MacOS X with the AppleTalk # SDK installed... +AC_ARG_ENABLE(pap, [ --enable-pap build with AppleTalk support, default=auto]) + PAP="" -if test $uname = Darwin; then +AC_SUBST(PAP) + +if test x$enable_pap != xno -a $uname = Darwin; then PAP="pap" AC_CHECK_HEADER(AppleTalk/at_proto.h) fi -AC_SUBST(PAP) - dnl dnl End of "$Id: cups-pam.m4 5466 2006-04-26 19:52:27Z mike $". dnl diff --git a/cups/Makefile b/cups/Makefile index 2c8bdbdb9..5e66a122b 100644 --- a/cups/Makefile +++ b/cups/Makefile @@ -201,7 +201,6 @@ install-libs: $(INSTALLSTATIC) $(INSTALL32) $(INSTALL64) $(LN) $(LIBCUPS) $(LIBDIR)/`basename $(LIBCUPS) .2`; \ fi if test $(LIBCUPS) = "libcups.2.dylib"; then \ - $(STRIP) -x $(LIBDIR)/$(LIBCUPS); \ $(RM) $(LIBDIR)/libcups.dylib; \ $(LN) $(LIBCUPS) $(LIBDIR)/libcups.dylib; \ fi diff --git a/cups/adminutil.c b/cups/adminutil.c index c75b0d904..70fdce425 100644 --- a/cups/adminutil.c +++ b/cups/adminutil.c @@ -808,6 +808,9 @@ cupsAdminExportSamba( if (have_drivers == 0) { _cupsSetError(IPP_NOT_FOUND, message); + + unlink(authfile); + return (0); } diff --git a/cups/http-private.h b/cups/http-private.h index 78348a4dd..ba416f666 100644 --- a/cups/http-private.h +++ b/cups/http-private.h @@ -257,6 +257,12 @@ extern void _cups_freeifaddrs(struct ifaddrs *addrs); # endif /* HAVE_GETIFADDRS */ # endif /* !WIN32 */ +/* + * Common URI encoding function... + */ + +extern char *_httpEncodeURI(char *dst, const char *src, size_t dstsize); + #endif /* !_CUPS_HTTP_PRIVATE_H_ */ /* diff --git a/cups/http-support.c b/cups/http-support.c index be6cfbe84..a8d58b0be 100644 --- a/cups/http-support.c +++ b/cups/http-support.c @@ -36,6 +36,7 @@ * httpStatus() - Return a short string describing a HTTP status code. * _cups_hstrerror() - hstrerror() emulation function for Solaris and * others... + * _httpEncodeURI() - Percent-encode a HTTP request URI. * http_copy_decode() - Copy and decode a URI. * http_copy_encode() - Copy and encode a URI. */ @@ -1203,6 +1204,20 @@ _cups_hstrerror(int error) /* I - Error number */ #endif /* !HAVE_HSTRERROR */ +/* + * '_httpEncodeURI()' - Percent-encode a HTTP request URI. + */ + +char * /* O - Encoded URI */ +_httpEncodeURI(char *dst, /* I - Destination buffer */ + const char *src, /* I - Source URI */ + size_t dstsize) /* I - Size of destination buffer */ +{ + http_copy_encode(dst, src, dst + dstsize - 1, NULL, NULL, 1); + return (dst); +} + + /* * 'http_copy_decode()' - Copy and decode a URI. */ @@ -1311,6 +1326,8 @@ http_copy_encode(char *dst, /* O - Destination buffer */ *dst++ = *src++; } + *dst = '\0'; + if (*src) return (NULL); else diff --git a/cups/http.c b/cups/http.c index 2faa1262e..e48c174c6 100644 --- a/cups/http.c +++ b/cups/http.c @@ -2527,8 +2527,7 @@ http_send(http_t *http, /* I - Connection to server */ const char *uri) /* I - URI */ { int i; /* Looping var */ - char *ptr, /* Pointer in buffer */ - buf[1024]; /* Encoded URI buffer */ + char buf[1024]; /* Encoded URI buffer */ static const char * const codes[] = { /* Request code strings */ NULL, @@ -2545,8 +2544,6 @@ http_send(http_t *http, /* I - Connection to server */ "TRACE", "CLOSE" }; - static const char hex[] = "0123456789ABCDEF"; - /* Hex digits */ DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n", @@ -2566,20 +2563,7 @@ http_send(http_t *http, /* I - Connection to server */ * Encode the URI as needed... */ - for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++) - if (*uri <= ' ' || *uri >= 127) - { - if (ptr < (buf + sizeof(buf) - 1)) - *ptr ++ = '%'; - if (ptr < (buf + sizeof(buf) - 1)) - *ptr ++ = hex[(*uri >> 4) & 15]; - if (ptr < (buf + sizeof(buf) - 1)) - *ptr ++ = hex[*uri & 15]; - } - else - *ptr ++ = *uri; - - *ptr = '\0'; + _httpEncodeURI(buf, uri, sizeof(buf)); /* * See if we had an error the last time around; if so, reconnect... diff --git a/cups/libcups.exp b/cups/libcups.exp index 35f309431..8271f59ac 100644 --- a/cups/libcups.exp +++ b/cups/libcups.exp @@ -26,6 +26,7 @@ __cupsStrFormatd __cupsStrFree __cupsStrScand __cupsStrStatistics +__httpEncodeURI __httpReadCDSA __httpWriteCDSA __ippAddAttr diff --git a/cups/ppd.c b/cups/ppd.c index a70a0cfeb..f8c714d13 100644 --- a/cups/ppd.c +++ b/cups/ppd.c @@ -590,7 +590,7 @@ ppdOpen2(cups_file_t *fp) /* I - File to read from */ ppd->language_level = 2; ppd->color_device = 0; - ppd->colorspace = PPD_CS_GRAY; + ppd->colorspace = PPD_CS_N; ppd->landscape = -90; ppd->coptions = cupsArrayNew((cups_array_func_t)ppd_compare_coptions, NULL); diff --git a/doc/help/spec-ppd.html b/doc/help/spec-ppd.html index f78693450..5aa7b357a 100644 --- a/doc/help/spec-ppd.html +++ b/doc/help/spec-ppd.html @@ -1185,7 +1185,7 @@ text:for%20all%20good%20men%20to%20come%20to%20the%20aid%20of%20their%20country. *cupsIPPReason com.vendor-error/A serious error occurred: "http://www.vendor.com/help" *% Map com.vendor-error to text and a local, Apple help book, and remote page -*APHelpBook: "file:///Library/Printers/vendor/Help/filename" +*APHelpBook: "file:///Library/Printers/vendor/Help.bundle" *cupsIPPReason com.vendor-error/A serious error occurred: "/help/com.vendor/error.html help:anchor='com.vendor-error'%20bookID=Vendor%20Help http://www.vendor.com/help" @@ -1446,9 +1446,9 @@ attribute.

APHelpBook

-

*APHelpBook: "file URL"

+

*APHelpBook: "bundle URL"

-

This string attribute specifies the Apple help book file to use when +

This string attribute specifies the Apple help book bundle to use when looking up IPP reason codes for this printer driver. The cupsIPPReason attribute maps "help" URIs to this file.

@@ -1456,7 +1456,7 @@ looking up IPP reason codes for this printer driver. The

Example:

-*APHelpBook: "file:///Library/Printers/vendor/Help/filename"
+*APHelpBook: "file:///Library/Printers/vendor/Help.bundle"
 

Mac OS X 10.3APPrinterIconPath

@@ -1634,7 +1634,7 @@ the device.

  • Added custom option values support
  • -
  • Added APBookFile attribute
  • +
  • Added APHelpBook attribute
  • Added APDuplexRequiresFlippedMargin attribute
  • diff --git a/driver/Makefile b/driver/Makefile index 30715f805..ea4240acb 100644 --- a/driver/Makefile +++ b/driver/Makefile @@ -151,7 +151,6 @@ install-libs: $(INSTALLSTATIC) $(INSTALL32) $(INSTALL64) $(LN) $(LIBCUPSDRIVER) $(LIBDIR)/`basename $(LIBCUPSDRIVER) .1`; \ fi if test $(LIBCUPSDRIVER) = "libcupsdriver.1.dylib"; then \ - $(STRIP) -x $(LIBDIR)/$(LIBCUPSDRIVER); \ $(RM) $(LIBDIR)/libcupsdriver.dylib; \ $(LN) $(LIBCUPSDRIVER) $(LIBDIR)/libcupsdriver.dylib; \ fi diff --git a/driver/pcl-common.h b/driver/pcl-common.h index 78cf70168..17819ab01 100644 --- a/driver/pcl-common.h +++ b/driver/pcl-common.h @@ -17,7 +17,7 @@ * Include necessary headers... */ -#include "string.h" +#include #include "data/pcl.h" diff --git a/driver/rastertoescpx.c b/driver/rastertoescpx.c index f9cf22a61..362086e45 100644 --- a/driver/rastertoescpx.c +++ b/driver/rastertoescpx.c @@ -3,7 +3,7 @@ * * Advanced EPSON ESC/P raster driver for CUPS. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -18,6 +18,7 @@ * StartPage() - Start a page of graphics. * EndPage() - Finish a page of graphics. * Shutdown() - Shutdown a printer. + * CancelJob() - Cancel the current job... * CompressData() - Compress a line of graphics. * OutputBand() - Output a band of graphics. * ProcessLine() - Read graphics from the page stream and output @@ -32,6 +33,7 @@ #include "driver.h" #include #include "data/escp.h" +#include /* @@ -82,6 +84,7 @@ int PrinterPlanes, /* # of color planes */ cups_lut_t *DitherLuts[7]; /* Lookup tables for dithering */ cups_dither_t *DitherStates[7]; /* Dither state tables */ int OutputFeed; /* Number of lines to skip */ +int Canceled; /* Is the job canceled? */ /* @@ -89,18 +92,19 @@ int OutputFeed; /* Number of lines to skip */ */ void Setup(ppd_file_t *); -void StartPage(ppd_file_t *, cups_page_header_t *); -void EndPage(ppd_file_t *, cups_page_header_t *); +void StartPage(ppd_file_t *, cups_page_header2_t *); +void EndPage(ppd_file_t *, cups_page_header2_t *); void Shutdown(ppd_file_t *); void AddBand(cups_weave_t *band); +void CancelJob(int sig); void CompressData(ppd_file_t *, const unsigned char *, const int, int, int, const int, const int, const int, const int); -void OutputBand(ppd_file_t *, cups_page_header_t *, +void OutputBand(ppd_file_t *, cups_page_header2_t *, cups_weave_t *band); void ProcessLine(ppd_file_t *, cups_raster_t *, - cups_page_header_t *, const int y); + cups_page_header2_t *, const int y); /* @@ -126,7 +130,7 @@ Setup(ppd_file_t *ppd) /* I - PPD file */ void StartPage(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header) /* I - Page header */ + cups_page_header2_t *header) /* I - Page header */ { int i, y; /* Looping vars */ int subrow, /* Current subrow */ @@ -1043,7 +1047,7 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */ void EndPage(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header) /* I - Page header */ + cups_page_header2_t *header) /* I - Page header */ { int i; /* Looping var */ cups_weave_t *band, /* Current band */ @@ -1264,6 +1268,19 @@ AddBand(cups_weave_t *band) /* I - Band to add */ } +/* + * 'CancelJob()' - Cancel the current job... + */ + +void +CancelJob(int sig) /* I - Signal */ +{ + (void)sig; + + Canceled = 1; +} + + /* * 'CompressData()' - Compress a line of graphics. */ @@ -1467,7 +1484,7 @@ CompressData(ppd_file_t *ppd, /* I - PPD file information */ void OutputBand(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header, /* I - Page header */ + cups_page_header2_t *header, /* I - Page header */ cups_weave_t *band) /* I - Current band */ { int xstep, /* Spacing between columns */ @@ -1529,7 +1546,7 @@ OutputBand(ppd_file_t *ppd, /* I - PPD file */ void ProcessLine(ppd_file_t *ppd, /* I - PPD file */ cups_raster_t *ras, /* I - Raster stream */ - cups_page_header_t *header, /* I - Page header */ + cups_page_header2_t *header, /* I - Page header */ const int y) /* I - Current scanline */ { int plane, /* Current color plane */ @@ -1725,12 +1742,15 @@ main(int argc, /* I - Number of command-line arguments */ { int fd; /* File descriptor */ cups_raster_t *ras; /* Raster stream for printing */ - cups_page_header_t header; /* Page header from file */ + cups_page_header2_t header; /* Page header from file */ int page; /* Current page */ int y; /* Current line */ ppd_file_t *ppd; /* PPD file */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* @@ -1783,6 +1803,25 @@ main(int argc, /* I - Number of command-line arguments */ ras = cupsRasterOpen(fd, CUPS_RASTER_READ); + /* + * Register a signal handler to eject the current page if the + * job is cancelled. + */ + + Canceled = 0; + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, CancelJob); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = CancelJob; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, CancelJob); +#endif /* HAVE_SIGSET */ + /* * Initialize the print device... */ @@ -1795,8 +1834,15 @@ main(int argc, /* I - Number of command-line arguments */ page = 0; - while (cupsRasterReadHeader(ras, &header)) + while (cupsRasterReadHeader2(ras, &header)) { + /* + * Write a status message with the page number and number of copies. + */ + + if (Canceled) + break; + page ++; fprintf(stderr, "PAGE: %d 1\n", page); @@ -1806,16 +1852,34 @@ main(int argc, /* I - Number of command-line arguments */ for (y = 0; y < header.cupsHeight; y ++) { + /* + * Let the user know how far we have progressed... + */ + + if (Canceled) + break; + if ((y & 127) == 0) fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", page, 100 * y / header.cupsHeight); + /* + * Read and write a line of graphics or whitespace... + */ + ProcessLine(ppd, ras, &header, y); } + /* + * Eject the page... + */ + fprintf(stderr, "INFO: Finished page %d...\n", page); EndPage(ppd, &header); + + if (Canceled) + break; } Shutdown(ppd); diff --git a/driver/rastertopclx.c b/driver/rastertopclx.c index 9c5097448..d021e2342 100644 --- a/driver/rastertopclx.c +++ b/driver/rastertopclx.c @@ -15,10 +15,10 @@ * * Contents: * - * Setup() - Prepare a printer for graphics output. * StartPage() - Start a page of graphics. * EndPage() - Finish a page of graphics. * Shutdown() - Shutdown a printer. + * CancelJob() - Cancel the current job... * CompressData() - Compress a line of graphics. * OutputLine() - Output the specified number of lines of graphics. * ReadLine() - Read graphics from the page stream. @@ -31,6 +31,7 @@ #include "driver.h" #include "pcl-common.h" +#include /* @@ -80,23 +81,25 @@ const int ColorOrders[7][7] = /* Order of color planes */ { 5, 0, 1, 2, 3, 4, 0 }, /* KCMYcm */ { 5, 0, 1, 2, 3, 4, 6 } /* KCMYcmk */ }; +int Canceled; /* Is the job canceled? */ /* * Prototypes... */ -void StartPage(ppd_file_t *ppd, cups_page_header_t *header, int job_id, +void StartPage(ppd_file_t *ppd, cups_page_header2_t *header, int job_id, const char *user, const char *title, int num_options, cups_option_t *options); -void EndPage(ppd_file_t *ppd, cups_page_header_t *header); +void EndPage(ppd_file_t *ppd, cups_page_header2_t *header); void Shutdown(ppd_file_t *ppd, int job_id, const char *user, const char *title, int num_options, cups_option_t *options); +void CancelJob(int sig); void CompressData(unsigned char *line, int length, int plane, int pend, int type); -void OutputLine(ppd_file_t *ppd, cups_page_header_t *header); -int ReadLine(cups_raster_t *ras, cups_page_header_t *header); +void OutputLine(ppd_file_t *ppd, cups_page_header2_t *header); +int ReadLine(cups_raster_t *ras, cups_page_header2_t *header); /* @@ -105,7 +108,7 @@ int ReadLine(cups_raster_t *ras, cups_page_header_t *header); void StartPage(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header, /* I - Page header */ + cups_page_header2_t *header, /* I - Page header */ int job_id, /* I - Job ID */ const char *user, /* I - User printing job */ const char *title, /* I - Title of job */ @@ -807,7 +810,7 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */ void EndPage(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header) /* I - Page header */ + cups_page_header2_t *header) /* I - Page header */ { int plane; /* Current plane */ @@ -916,6 +919,19 @@ Shutdown(ppd_file_t *ppd, /* I - PPD file */ } +/* + * 'CancelJob()' - Cancel the current job... + */ + +void +CancelJob(int sig) /* I - Signal */ +{ + (void)sig; + + Canceled = 1; +} + + /* * 'CompressData()' - Compress a line of graphics. */ @@ -1518,7 +1534,7 @@ CompressData(unsigned char *line, /* I - Data to compress */ void OutputLine(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header) /* I - Page header */ + cups_page_header2_t *header) /* I - Page header */ { int i, j; /* Looping vars */ int plane; /* Current plane */ @@ -1657,7 +1673,7 @@ OutputLine(ppd_file_t *ppd, /* I - PPD file */ int /* O - Number of lines (0 if blank) */ ReadLine(cups_raster_t *ras, /* I - Raster stream */ - cups_page_header_t *header) /* I - Page header */ + cups_page_header2_t *header) /* I - Page header */ { int plane, /* Current color plane */ width; /* Width of line */ @@ -1755,12 +1771,15 @@ main(int argc, /* I - Number of command-line arguments */ { int fd; /* File descriptor */ cups_raster_t *ras; /* Raster stream for printing */ - cups_page_header_t header; /* Page header from file */ + cups_page_header2_t header; /* Page header from file */ int y; /* Current line */ ppd_file_t *ppd; /* PPD file */ int job_id; /* Job ID */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* @@ -1813,6 +1832,25 @@ main(int argc, /* I - Number of command-line arguments */ ras = cupsRasterOpen(fd, CUPS_RASTER_READ); + /* + * Register a signal handler to eject the current page if the + * job is cancelled. + */ + + Canceled = 0; + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, CancelJob); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = CancelJob; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, CancelJob); +#endif /* HAVE_SIGSET */ + /* * Process pages as needed... */ @@ -1821,8 +1859,15 @@ main(int argc, /* I - Number of command-line arguments */ Page = 0; - while (cupsRasterReadHeader(ras, &header)) + while (cupsRasterReadHeader2(ras, &header)) { + /* + * Write a status message with the page number and number of copies. + */ + + if (Canceled) + break; + Page ++; fprintf(stderr, "PAGE: %d %d\n", Page, header.NumCopies); @@ -1833,19 +1878,37 @@ main(int argc, /* I - Number of command-line arguments */ for (y = 0; y < (int)header.cupsHeight; y ++) { + /* + * Let the user know how far we have progressed... + */ + + if (Canceled) + break; + if ((y & 127) == 0) fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", Page, 100 * y / header.cupsHeight); + /* + * Read and write a line of graphics or whitespace... + */ + if (ReadLine(ras, &header)) OutputLine(ppd, &header); else OutputFeed ++; } + /* + * Eject the page... + */ + fprintf(stderr, "INFO: Finished page %d...\n", Page); EndPage(ppd, &header); + + if (Canceled) + break; } Shutdown(ppd, job_id, argv[2], argv[3], num_options, options); diff --git a/filter/Makefile b/filter/Makefile index c0990f8dc..6bd1f556e 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -130,7 +130,6 @@ install-libs: $(INSTALLSTATIC) $(INSTALL32) $(INSTALL64) $(LN) $(LIBCUPSIMAGE) $(LIBDIR)/`basename $(LIBCUPSIMAGE) .2`; \ fi -if test $(LIBCUPSIMAGE) = "libcupsimage.2.dylib"; then \ - $(STRIP) -x $(LIBDIR)/$(LIBCUPSIMAGE); \ $(RM) $(LIBDIR)/libcupsimage.dylib; \ $(LN) $(LIBCUPSIMAGE) $(LIBDIR)/libcupsimage.dylib; \ fi diff --git a/filter/image-gif.c b/filter/image-gif.c index a391811fc..d78670d37 100644 --- a/filter/image-gif.c +++ b/filter/image-gif.c @@ -37,6 +37,7 @@ #define GIF_INTERLACE 0x40 #define GIF_COLORMAP 0x80 +#define GIF_MAX_BITS 12 typedef cups_ib_t gif_cmap_t[256][4]; typedef short gif_table_t[4096]; @@ -462,7 +463,7 @@ gif_read_image(FILE *fp, /* I - Input file */ pass = 0; code_size = getc(fp); - if (!pixels) + if (code_size > GIF_MAX_BITS || !pixels) return (-1); if (gif_read_lzw(fp, 1, code_size) < 0) diff --git a/filter/image-png.c b/filter/image-png.c index 1db19e2d7..332b3c39b 100644 --- a/filter/image-png.c +++ b/filter/image-png.c @@ -3,7 +3,7 @@ * * PNG image routines for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -170,16 +170,56 @@ _cupsImageReadPNG( * Interlaced images must be loaded all at once... */ + size_t bufsize; /* Size of buffer */ + + if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) - in = malloc(img->xsize * img->ysize); + { + bufsize = img->xsize * img->ysize; + + if ((bufsize / img->ysize) != img->xsize) + { + fprintf(stderr, "DEBUG: PNG image dimensions (%ux%u) too large!\n", + (unsigned)width, (unsigned)height); + fclose(fp); + return (1); + } + } else - in = malloc(img->xsize * img->ysize * 3); + { + bufsize = img->xsize * img->ysize * 3; + + if ((bufsize / (img->ysize * 3)) != img->xsize) + { + fprintf(stderr, "DEBUG: PNG image dimensions (%ux%u) too large!\n", + (unsigned)width, (unsigned)height); + fclose(fp); + return (1); + } + } + + in = malloc(bufsize); } bpp = cupsImageGetDepth(img); out = malloc(img->xsize * bpp); + if (!in || !out) + { + fputs("DEBUG: Unable to allocate memory for PNG image!\n", stderr); + + if (in) + free(in); + + if (out) + free(out); + + fclose(fp); + + return (1); + } + /* * Read the image, interlacing as needed... */ diff --git a/filter/pdftops.c b/filter/pdftops.c index 9db1e9168..f1abb52bf 100644 --- a/filter/pdftops.c +++ b/filter/pdftops.c @@ -28,6 +28,7 @@ #include #include #include +#include /* @@ -37,6 +38,13 @@ static void cancel_job(int sig); +/* + * Local globals... + */ + +static int job_canceled = 0; + + /* * 'main()' - Main entry for filter... */ @@ -57,6 +65,7 @@ main(int argc, /* I - Number of command-line args */ ppd_file_t *ppd; /* PPD file */ ppd_size_t *size; /* Current page size */ int pdfpid, /* Process ID for pdftops */ + pdfwaitpid, /* Process ID from wait() */ pdfstatus, /* Status from pdftops */ pdfargc; /* Number of args for pdftops */ char *pdfargv[100], /* Arguments for pdftops */ @@ -261,7 +270,17 @@ main(int argc, /* I - Number of command-line args */ * Parent comes here... */ - if (wait(&pdfstatus) != pdfpid) + while ((pdfwaitpid = wait(&pdfstatus)) < 0 && errno == EINTR) + { + /* + * Wait until we get a valid process ID or the job is canceled... + */ + + if (job_canceled) + break; + } + + if (pdfwaitpid != pdfpid) { kill(pdfpid, SIGTERM); pdfstatus = 1; @@ -270,18 +289,18 @@ main(int argc, /* I - Number of command-line args */ { if (WIFEXITED(pdfstatus)) { - pdfstatus = WEXITSTATUS(pdfstatus); + pdfstatus = WEXITSTATUS(pdfstatus); - _cupsLangPrintf(stderr, - _("ERROR: pdftops filter exited with status %d!\n"), + _cupsLangPrintf(stderr, + _("ERROR: pdftops filter exited with status %d!\n"), pdfstatus); } else { - pdfstatus = WTERMSIG(pdfstatus); + pdfstatus = WTERMSIG(pdfstatus); - _cupsLangPrintf(stderr, - _("ERROR: pdftops filter crashed on signal %d!\n"), + _cupsLangPrintf(stderr, + _("ERROR: pdftops filter crashed on signal %d!\n"), pdfstatus); } } @@ -306,6 +325,8 @@ static void cancel_job(int sig) /* I - Signal number (unused) */ { (void)sig; + + job_canceled = 1; } diff --git a/filter/rastertoepson.c b/filter/rastertoepson.c index f1ad6547c..62ecb347b 100644 --- a/filter/rastertoepson.c +++ b/filter/rastertoepson.c @@ -77,7 +77,8 @@ int DotBit, /* Bit in buffers */ LineCount, /* # of lines processed */ EvenOffset, /* Offset into 'even' buffers */ OddOffset, /* Offset into 'odd' buffers */ - Shingling; /* Shingle output? */ + Shingling, /* Shingle output? */ + Canceled; /* Has the current job been canceled? */ /* @@ -85,15 +86,15 @@ int DotBit, /* Bit in buffers */ */ void Setup(void); -void StartPage(const ppd_file_t *ppd, const cups_page_header_t *header); -void EndPage(const cups_page_header_t *header); +void StartPage(const ppd_file_t *ppd, const cups_page_header2_t *header); +void EndPage(const cups_page_header2_t *header); void Shutdown(void); void CancelJob(int sig); void CompressData(const unsigned char *line, int length, int plane, int type, int xstep, int ystep); -void OutputLine(const cups_page_header_t *header); -void OutputRows(const cups_page_header_t *header, int row); +void OutputLine(const cups_page_header2_t *header); +void OutputRows(const cups_page_header2_t *header, int row); /* @@ -123,31 +124,11 @@ Setup(void) void StartPage(const ppd_file_t *ppd, /* I - PPD file */ - const cups_page_header_t *header) /* I - Page header */ + const cups_page_header2_t *header) /* I - Page header */ { int n, t; /* Numbers */ int plane; /* Looping var */ -#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* Actions for POSIX signals */ -#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ - - - /* - * Register a signal handler to eject the current page if the - * job is cancelled. - */ -#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGTERM, CancelJob); -#elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - - sigemptyset(&action.sa_mask); - action.sa_handler = CancelJob; - sigaction(SIGTERM, &action, NULL); -#else - signal(SIGTERM, CancelJob); -#endif /* HAVE_SIGSET */ /* * Send a reset sequence. @@ -339,7 +320,7 @@ StartPage(const ppd_file_t *ppd, /* I - PPD file */ */ void -EndPage(const cups_page_header_t *header) /* I - Page header */ +EndPage(const cups_page_header2_t *header) /* I - Page header */ { #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) struct sigaction action; /* Actions for POSIX signals */ @@ -377,22 +358,6 @@ EndPage(const cups_page_header_t *header) /* I - Page header */ putchar(12); /* Form feed */ fflush(stdout); - /* - * Unregister the signal handler... - */ - -#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGTERM, SIG_IGN); -#elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - - sigemptyset(&action.sa_mask); - action.sa_handler = SIG_IGN; - sigaction(SIGTERM, &action, NULL); -#else - signal(SIGTERM, SIG_IGN); -#endif /* HAVE_SIGSET */ - /* * Free memory... */ @@ -429,31 +394,9 @@ Shutdown(void) void CancelJob(int sig) /* I - Signal */ { - int i; /* Looping var */ - - (void)sig; - /* - * Send out lots of NUL bytes to clear out any pending raster data... - */ - - if (DotBytes) - i = DotBytes * 360 * 8; - else - i = 720; - - for (; i > 0; i --) - putchar(0); - - /* - * End the current page and exit... - */ - - EndPage(NULL); - Shutdown(); - - exit(0); + Canceled = 1; } @@ -670,7 +613,7 @@ CompressData(const unsigned char *line, /* I - Data to compress */ */ void -OutputLine(const cups_page_header_t *header) /* I - Page header */ +OutputLine(const cups_page_header2_t *header) /* I - Page header */ { if (header->cupsRowCount) { @@ -838,7 +781,7 @@ OutputLine(const cups_page_header_t *header) /* I - Page header */ */ void -OutputRows(const cups_page_header_t *header, /* I - Page image header */ +OutputRows(const cups_page_header2_t *header, /* I - Page image header */ int row) /* I - Row number (0 or 1) */ { unsigned i, n; /* Looping vars */ @@ -1012,16 +955,19 @@ OutputRows(const cups_page_header_t *header, /* I - Page image header */ * 'main()' - Main entry and processing of driver. */ -int /* O - Exit status */ -main(int argc, /* I - Number of command-line arguments */ - char *argv[]) /* I - Command-line arguments */ +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ { - int fd; /* File descriptor */ - cups_raster_t *ras; /* Raster stream for printing */ - cups_page_header_t header; /* Page header from file */ - ppd_file_t *ppd; /* PPD file */ - int page; /* Current page */ - int y; /* Current line */ + int fd; /* File descriptor */ + cups_raster_t *ras; /* Raster stream for printing */ + cups_page_header2_t header; /* Page header from file */ + ppd_file_t *ppd; /* PPD file */ + int page; /* Current page */ + int y; /* Current line */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* @@ -1064,6 +1010,25 @@ main(int argc, /* I - Number of command-line arguments */ ras = cupsRasterOpen(fd, CUPS_RASTER_READ); + /* + * Register a signal handler to eject the current page if the + * job is cancelled. + */ + + Canceled = 0; + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, CancelJob); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = CancelJob; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, CancelJob); +#endif /* HAVE_SIGSET */ + /* * Initialize the print device... */ @@ -1080,12 +1045,15 @@ main(int argc, /* I - Number of command-line arguments */ page = 0; - while (cupsRasterReadHeader(ras, &header)) + while (cupsRasterReadHeader2(ras, &header)) { /* * Write a status message with the page number and number of copies. */ + if (Canceled) + break; + page ++; fprintf(stderr, "PAGE: %d %d\n", page, header.NumCopies); @@ -1106,6 +1074,9 @@ main(int argc, /* I - Number of command-line arguments */ * Let the user know how far we have progressed... */ + if (Canceled) + break; + if ((y & 127) == 0) fprintf(stderr, _("INFO: Printing page %d, %d%% complete...\n"), page, 100 * y / header.cupsHeight); @@ -1129,6 +1100,9 @@ main(int argc, /* I - Number of command-line arguments */ */ EndPage(&header); + + if (Canceled) + break; } /* diff --git a/filter/rastertohp.c b/filter/rastertohp.c index 04ac4017a..9f9b7bc45 100644 --- a/filter/rastertohp.c +++ b/filter/rastertohp.c @@ -52,7 +52,8 @@ int NumPlanes, /* Number of color planes */ ColorBits, /* Number of bits per color */ Feed, /* Number of lines to skip */ Duplex, /* Current duplex mode */ - Page; /* Current page number */ + Page, /* Current page number */ + Canceled; /* Has the current job been canceled? */ /* @@ -60,13 +61,13 @@ int NumPlanes, /* Number of color planes */ */ void Setup(void); -void StartPage(ppd_file_t *ppd, cups_page_header_t *header); +void StartPage(ppd_file_t *ppd, cups_page_header2_t *header); void EndPage(void); void Shutdown(void); void CancelJob(int sig); void CompressData(unsigned char *line, int length, int plane, int type); -void OutputLine(cups_page_header_t *header); +void OutputLine(cups_page_header2_t *header); /* @@ -91,31 +92,11 @@ Setup(void) void StartPage(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header) /* I - Page header */ + cups_page_header2_t *header) /* I - Page header */ { int plane; /* Looping var */ -#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* Actions for POSIX signals */ -#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ - /* - * Register a signal handler to eject the current page if the - * job is cancelled. - */ - -#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGTERM, CancelJob); -#elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - - sigemptyset(&action.sa_mask); - action.sa_handler = CancelJob; - sigaction(SIGTERM, &action, NULL); -#else - signal(SIGTERM, CancelJob); -#endif /* HAVE_SIGSET */ - /* * Show page device dictionary... */ @@ -410,11 +391,6 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */ void EndPage(void) { -#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* Actions for POSIX signals */ -#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ - - /* * Eject the current page... */ @@ -436,22 +412,6 @@ EndPage(void) fflush(stdout); - /* - * Unregister the signal handler... - */ - -#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGTERM, SIG_IGN); -#elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - - sigemptyset(&action.sa_mask); - action.sa_handler = SIG_IGN; - sigaction(SIGTERM, &action, NULL); -#else - signal(SIGTERM, SIG_IGN); -#endif /* HAVE_SIGSET */ - /* * Free memory... */ @@ -489,26 +449,9 @@ Shutdown(void) void CancelJob(int sig) /* I - Signal */ { - int i; /* Looping var */ - - (void)sig; - /* - * Send out lots of NUL bytes to clear out any pending raster data... - */ - - for (i = 0; i < 600; i ++) - putchar(0); - - /* - * End the current page and exit... - */ - - EndPage(); - Shutdown(); - - exit(0); + Canceled = 1; } @@ -648,7 +591,7 @@ CompressData(unsigned char *line, /* I - Data to compress */ */ void -OutputLine(cups_page_header_t *header) /* I - Page header */ +OutputLine(cups_page_header2_t *header) /* I - Page header */ { int plane, /* Current plane */ bytes, /* Bytes to write */ @@ -731,15 +674,18 @@ OutputLine(cups_page_header_t *header) /* I - Page header */ * 'main()' - Main entry and processing of driver. */ -int /* O - Exit status */ -main(int argc, /* I - Number of command-line arguments */ - char *argv[]) /* I - Command-line arguments */ +int /* O - Exit status */ +main(int argc, /* I - Number of command-line arguments */ + char *argv[]) /* I - Command-line arguments */ { - int fd; /* File descriptor */ - cups_raster_t *ras; /* Raster stream for printing */ - cups_page_header_t header; /* Page header from file */ - int y; /* Current line */ - ppd_file_t *ppd; /* PPD file */ + int fd; /* File descriptor */ + cups_raster_t *ras; /* Raster stream for printing */ + cups_page_header2_t header; /* Page header from file */ + int y; /* Current line */ + ppd_file_t *ppd; /* PPD file */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* @@ -782,6 +728,25 @@ main(int argc, /* I - Number of command-line arguments */ ras = cupsRasterOpen(fd, CUPS_RASTER_READ); + /* + * Register a signal handler to eject the current page if the + * job is cancelled. + */ + + Canceled = 0; + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, CancelJob); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = CancelJob; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, CancelJob); +#endif /* HAVE_SIGSET */ + /* * Initialize the print device... */ @@ -796,12 +761,15 @@ main(int argc, /* I - Number of command-line arguments */ Page = 0; - while (cupsRasterReadHeader(ras, &header)) + while (cupsRasterReadHeader2(ras, &header)) { /* * Write a status message with the page number and number of copies. */ + if (Canceled) + break; + Page ++; fprintf(stderr, "PAGE: %d %d\n", Page, header.NumCopies); @@ -822,6 +790,9 @@ main(int argc, /* I - Number of command-line arguments */ * Let the user know how far we have progressed... */ + if (Canceled) + break; + if ((y & 127) == 0) fprintf(stderr, _("INFO: Printing page %d, %d%% complete...\n"), Page, 100 * y / header.cupsHeight); @@ -849,6 +820,9 @@ main(int argc, /* I - Number of command-line arguments */ */ EndPage(); + + if (Canceled) + break; } /* diff --git a/filter/rastertolabel.c b/filter/rastertolabel.c index 05adc0397..cb62278fd 100644 --- a/filter/rastertolabel.c +++ b/filter/rastertolabel.c @@ -3,7 +3,7 @@ * * Label printer filter for the Common UNIX Printing System (CUPS). * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2008 by Apple Inc. * Copyright 2001-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -90,10 +90,10 @@ int ModelNumber, /* cupsModelNumber attribute */ */ void Setup(ppd_file_t *ppd); -void StartPage(ppd_file_t *ppd, cups_page_header_t *header); -void EndPage(ppd_file_t *ppd, cups_page_header_t *header); +void StartPage(ppd_file_t *ppd, cups_page_header2_t *header); +void EndPage(ppd_file_t *ppd, cups_page_header2_t *header); void CancelJob(int sig); -void OutputLine(ppd_file_t *ppd, cups_page_header_t *header, int y); +void OutputLine(ppd_file_t *ppd, cups_page_header2_t *header, int y); void PCLCompress(unsigned char *line, int length); void ZPLCompress(char repeat_char, int repeat_count); @@ -166,13 +166,10 @@ Setup(ppd_file_t *ppd) /* I - PPD file */ void StartPage(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header) /* I - Page header */ + cups_page_header2_t *header) /* I - Page header */ { ppd_choice_t *choice; /* Marked choice */ int length; /* Actual label length */ -#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) - struct sigaction action; /* Actions for POSIX signals */ -#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* @@ -226,23 +223,6 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */ fprintf(stderr, "DEBUG: cupsRowFeed = %d\n", header->cupsRowFeed); fprintf(stderr, "DEBUG: cupsRowStep = %d\n", header->cupsRowStep); - /* - * Register a signal handler to eject the current page if the - * job is canceled. - */ - -#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGTERM, CancelJob); -#elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - - sigemptyset(&action.sa_mask); - action.sa_handler = CancelJob; - sigaction(SIGTERM, &action, NULL); -#else - signal(SIGTERM, CancelJob); -#endif /* HAVE_SIGSET */ - switch (ModelNumber) { case DYMO_3x0 : @@ -498,7 +478,7 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */ void EndPage(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header) /* I - Page header */ + cups_page_header2_t *header) /* I - Page header */ { int val; /* Option value */ ppd_choice_t *choice; /* Marked choice */ @@ -732,22 +712,6 @@ EndPage(ppd_file_t *ppd, /* I - PPD file */ fflush(stdout); - /* - * Unregister the signal handler... - */ - -#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ - sigset(SIGTERM, SIG_IGN); -#elif defined(HAVE_SIGACTION) - memset(&action, 0, sizeof(action)); - - sigemptyset(&action.sa_mask); - action.sa_handler = SIG_IGN; - sigaction(SIGTERM, &action, NULL); -#else - signal(SIGTERM, SIG_IGN); -#endif /* HAVE_SIGSET */ - /* * Free memory... */ @@ -779,7 +743,7 @@ CancelJob(int sig) /* I - Signal */ void OutputLine(ppd_file_t *ppd, /* I - PPD file */ - cups_page_header_t *header, /* I - Page header */ + cups_page_header2_t *header, /* I - Page header */ int y) /* I - Line number */ { int i; /* Looping var */ @@ -1145,11 +1109,14 @@ main(int argc, /* I - Number of command-line arguments */ { int fd; /* File descriptor */ cups_raster_t *ras; /* Raster stream for printing */ - cups_page_header_t header; /* Page header from file */ + cups_page_header2_t header; /* Page header from file */ int y; /* Current line */ ppd_file_t *ppd; /* PPD file */ int num_options; /* Number of options */ cups_option_t *options; /* Options */ +#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) + struct sigaction action; /* Actions for POSIX signals */ +#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ /* @@ -1192,6 +1159,25 @@ main(int argc, /* I - Number of command-line arguments */ ras = cupsRasterOpen(fd, CUPS_RASTER_READ); + /* + * Register a signal handler to eject the current page if the + * job is cancelled. + */ + + Canceled = 0; + +#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ + sigset(SIGTERM, CancelJob); +#elif defined(HAVE_SIGACTION) + memset(&action, 0, sizeof(action)); + + sigemptyset(&action.sa_mask); + action.sa_handler = CancelJob; + sigaction(SIGTERM, &action, NULL); +#else + signal(SIGTERM, CancelJob); +#endif /* HAVE_SIGSET */ + /* * Open the PPD file and apply options... */ @@ -1214,15 +1200,17 @@ main(int argc, /* I - Number of command-line arguments */ * Process pages as needed... */ - Page = 0; - Canceled = 0; + Page = 0; - while (cupsRasterReadHeader(ras, &header)) + while (cupsRasterReadHeader2(ras, &header)) { /* * Write a status message with the page number and number of copies. */ + if (Canceled) + break; + Page ++; fprintf(stderr, "PAGE: %d 1\n", Page); @@ -1243,6 +1231,9 @@ main(int argc, /* I - Number of command-line arguments */ * Let the user know how far we have progressed... */ + if (Canceled) + break; + if ((y & 15) == 0) fprintf(stderr, _("INFO: Printing page %d, %d%% complete...\n"), Page, 100 * y / header.cupsHeight); diff --git a/install-sh b/install-sh index 398a88e14..2c4a67c2d 100755 --- a/install-sh +++ b/install-sh @@ -3,6 +3,7 @@ # install - install a program, script, or datafile # This comes from X11R5 (mit/util/scripts/install.sh). # +# Library stripping changes Copyright 2008 by Apple Inc. # Copyright 1991 by the Massachusetts Institute of Technology # # Permission to use, copy, modify, distribute, and sell this software and its @@ -181,7 +182,9 @@ while [ $# -ne 0 ] ; do if [ ! -d "${pathcomp}" ] ; then - $mkdirprog "${pathcomp}" + $mkdirprog "${pathcomp}" && + if [ x"$chowncmd" != x ]; then $doit $chowncmd "$pathcomp"; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd "$pathcomp"; else : ; fi else : fi @@ -196,7 +199,6 @@ then if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi else @@ -219,6 +221,16 @@ else : fi +# Check the destination file - for libraries just use the "-x" option to strip + case "$dstfile" in + *.a | *.dylib | *.sl | *.sl.* | *.so | *.so.*) + stripopt="-x" + ;; + *) + stripopt="" + ;; + esac + # Make a temp file name in the proper directory. dsttmp=$dstdir/#inst.$$# @@ -237,7 +249,7 @@ else if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && - if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $stripopt $dsttmp; else :;fi && if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && # Now rename the file to the real destination. diff --git a/man/ppdpo.man b/man/ppdpo.man index b5b43ebbe..dc84e846b 100644 --- a/man/ppdpo.man +++ b/man/ppdpo.man @@ -3,7 +3,7 @@ .\" .\" ppdpo man page for the CUPS Driver Development Kit. .\" -.\" 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 @@ -12,9 +12,9 @@ .\" 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 ppdpo 1 "CUPS Driver Development Kit" "14 February 2007" "Apple Inc." +.TH ppdpo 1 "Common UNIX Printing System" "27 March 2008" "Apple Inc." .SH NAME -ppdpo \- cups message catalog generator +ppdpo \- ppd message catalog generator .SH SYNOPSIS .B ppdpo [ \-I @@ -24,18 +24,22 @@ ppdpo \- cups message catalog generator ] .I source-file .SH DESCRIPTION -\fIppdpo\fR extracts UI strings from PPDC source files and writes them in -a GNU gettext format message catalog source file for translation. +\fIppdpo\fR extracts UI strings from PPDC source files and updates either +a GNU gettext or Mac OS X strings format message catalog source file for +translation. .PP The \fI-I\fR option specifies an alternate include directory; multiple \fI-I\fR options can be supplied to add additional directories. .PP -The \fI-o\fR option specifies the output file. +The \fI-o\fR option specifies the output file. The supported extensions are +".po" or ".po.gz" for GNU gettext format message catalogs and ".strings" for +Mac OS X strings files. .SH SEE ALSO -cupsprofile(1), ppdc(1), ppdhtml(1), ppdi(1), ppdmerge(1), ppdcfile(5), CUPS Driver Developer Kit Manual. +ppdc(1), ppdhtml(1), ppdi(1), ppdmerge(1), ppdcfile(5), +http://localhost:631/help .SH COPYRIGHT -Copyright 2007 by Apple Inc. +Copyright 2007-2008 by Apple Inc. .\" .\" End of "$Id: ppdpo.man 343 2007-07-13 19:52:48Z mike $". .\" diff --git a/ppdc/Makefile b/ppdc/Makefile index edaafeceb..d67920817 100644 --- a/ppdc/Makefile +++ b/ppdc/Makefile @@ -165,7 +165,6 @@ install-libs: $(INSTALLSTATIC) $(INSTALL32) $(INSTALL64) $(LN) $(LIBCUPSPPDC) $(LIBDIR)/`basename $(LIBCUPSPPDC) .1`; \ fi if test $(LIBCUPSPPDC) = "libcupsppdc.1.dylib"; then \ - $(STRIP) -x $(LIBDIR)/$(LIBCUPSPPDC); \ $(RM) $(LIBDIR)/libcupsppdc.dylib; \ $(LN) $(LIBCUPSPPDC) $(LIBDIR)/libcupsppdc.dylib; \ fi diff --git a/ppdc/ppdc-catalog.cxx b/ppdc/ppdc-catalog.cxx index 96cd6e3aa..29de91f67 100644 --- a/ppdc/ppdc-catalog.cxx +++ b/ppdc/ppdc-catalog.cxx @@ -30,6 +30,29 @@ #include +// +// Character encodings... +// + +typedef enum +{ + PPDC_CS_AUTO, + PPDC_CS_UTF8, + PPDC_CS_UTF16BE, + PPDC_CS_UTF16LE +} ppdc_cs_t; + + +// +// Local functions... +// + +static int get_utf8(char *&ptr); +static int get_utf16(cups_file_t *fp, ppdc_cs_t &cs); +static int put_utf8(int ch, char *&ptr, char *end); +static int put_utf16(cups_file_t *fp, int ch); + + // // 'ppdcCatalog::ppdcCatalog()' - Create a shared message catalog. // @@ -155,146 +178,260 @@ ppdcCatalog::load_messages( if ((fp = cupsFileOpen(f, "r")) == NULL) return (-1); - /* - * Read messages from the catalog file until EOF... - * - * The format is the GNU gettext .po format, which is fairly simple: - * - * msgid "some text" - * msgstr "localized text" - * - * The ID and localized text can span multiple lines using the form: - * - * msgid "" - * "some long text" - * msgstr "" - * "localized text spanning " - * "multiple lines" - */ + if ((ptr = strrchr(f, '.')) == NULL) + goto unknown_load_format; + else if (!strcmp(ptr, ".strings")) + { + /* + * Read messages in Mac OS X ".strings" format, which are UTF-16 text + * files of the format: + * + * "id" = "str"; + * + * Strings files can also contain C-style comments. + */ + + ppdc_cs_t cs = PPDC_CS_AUTO; // Character set for file + int ch; // Current character from file + char *end; // End of buffer + + + id[0] = '\0'; + str[0] = '\0'; + ptr = NULL; + end = NULL; + + while ((ch = get_utf16(fp, cs)) != 0) + { + if (ptr) + { + if (ch == '\\') + { + if ((ch = get_utf16(fp, cs)) == 0) + break; - linenum = 0; - id[0] = '\0'; - str[0] = '\0'; + if (ch == 'n') + ch = '\n'; + else if (ch == 't') + ch = '\t'; + } - while (cupsFileGets(fp, line, sizeof(line))) - { - linenum ++; + put_utf8(ch, ptr, end); + } + else if (ch == '/') + { + // Start of a comment? + if ((ch = get_utf16(fp, cs)) == 0) + break; - // Skip blank and comment lines... - if (line[0] == '#' || !line[0]) - continue; + if (ch == '*') + { + // Skip C comment... + int lastch = 0; - // Strip the trailing quote... - if ((ptr = strrchr(line, '\"')) == NULL) - { - fprintf(stderr, "load_messages: Expected quoted string on line %d of %s!\n", - linenum, f); - cupsFileClose(fp); - return (-1); - } + while ((ch = get_utf16(fp, cs)) != 0) + { + if (ch == '/' && lastch == '*') + break; - *ptr = '\0'; + lastch = ch; + } + } + else if (ch == '/') + { + // Skip C++ comment... + while ((ch = get_utf16(fp, cs)) != 0) + if (ch == '\n') + break; + } + } + else if (ch == '\"') + { + // Start or finish quoted string... + if (ptr) + { + *ptr = '\0'; + ptr = NULL; + } + else if (id[0]) + { + ptr = str; + end = str + sizeof(str) - 1; + } + else + { + ptr = id; + end = id + sizeof(id) - 1; + } + } + else if (ch == ';') + { + // Add string... + temp = new ppdcMessage(id, str); - // Find start of value... - if ((ptr = strchr(line, '\"')) == NULL) - { - fprintf(stderr, "load_messages: Expected quoted string on line %d of %s!\n", - linenum, f); - cupsFileClose(fp); - return (-1); + messages->add(temp); + } } + } + else if (!strcmp(ptr, ".po") || !strcmp(ptr, ".gz")) + { + /* + * Read messages from the catalog file until EOF... + * + * The format is the GNU gettext .po format, which is fairly simple: + * + * msgid "some text" + * msgstr "localized text" + * + * The ID and localized text can span multiple lines using the form: + * + * msgid "" + * "some long text" + * msgstr "" + * "localized text spanning " + * "multiple lines" + */ + + linenum = 0; + id[0] = '\0'; + str[0] = '\0'; + + while (cupsFileGets(fp, line, sizeof(line))) + { + linenum ++; - ptr ++; + // Skip blank and comment lines... + if (line[0] == '#' || !line[0]) + continue; - // Unquote the text... - char *sptr, *dptr; // Source/destination pointers + // Strip the trailing quote... + if ((ptr = strrchr(line, '\"')) == NULL) + { + fprintf(stderr, "ERROR: Expected quoted string on line %d of %s!\n", + linenum, f); + cupsFileClose(fp); + return (-1); + } - for (sptr = ptr, dptr = ptr; *sptr;) - { - if (*sptr == '\\') + *ptr = '\0'; + + // Find start of value... + if ((ptr = strchr(line, '\"')) == NULL) + { + fprintf(stderr, "ERROR: Expected quoted string on line %d of %s!\n", + linenum, f); + cupsFileClose(fp); + return (-1); + } + + ptr ++; + + // Unquote the text... + char *sptr, *dptr; // Source/destination pointers + + for (sptr = ptr, dptr = ptr; *sptr;) { - sptr ++; - if (isdigit(*sptr)) + if (*sptr == '\\') { - *dptr = 0; + sptr ++; + if (isdigit(*sptr)) + { + *dptr = 0; + + while (isdigit(*sptr)) + { + *dptr = *dptr * 8 + *sptr - '0'; + sptr ++; + } - while (isdigit(*sptr)) + dptr ++; + } + else { - *dptr = *dptr * 8 + *sptr - '0'; + if (*sptr == 'n') + *dptr++ = '\n'; + else if (*sptr == 'r') + *dptr++ = '\r'; + else if (*sptr == 't') + *dptr++ = '\t'; + else + *dptr++ = *sptr; + sptr ++; } - - dptr ++; } else - { - if (*sptr == 'n') - *dptr++ = '\n'; - else if (*sptr == 'r') - *dptr++ = '\r'; - else if (*sptr == 't') - *dptr++ = '\t'; - else - *dptr++ = *sptr; - - sptr ++; - } + *dptr++ = *sptr++; } - else - *dptr++ = *sptr++; - } - *dptr = '\0'; + *dptr = '\0'; - // Create or add to a message... - if (!strncmp(line, "msgid", 5)) - { - if (id[0] && str[0]) + // Create or add to a message... + if (!strncmp(line, "msgid", 5)) { - temp = new ppdcMessage(id, str); + if (id[0] && str[0]) + { + temp = new ppdcMessage(id, str); - messages->add(temp); + messages->add(temp); + } + + strlcpy(id, ptr, sizeof(id)); + str[0] = '\0'; } + else if (!strncmp(line, "msgstr", 6)) + { + if (!id[0]) + { + fprintf(stderr, "ERROR: Need a msgid line before any " + "translation strings on line %d of %s!\n", + linenum, f); + cupsFileClose(fp); + return (-1); + } - strlcpy(id, ptr, sizeof(id)); - str[0] = '\0'; - } - else if (!strncmp(line, "msgstr", 6)) - { - if (!id[0]) + strlcpy(str, ptr, sizeof(str)); + } + else if (line[0] == '\"' && str[0]) + strlcat(str, ptr, sizeof(str)); + else if (line[0] == '\"' && id[0]) + strlcat(id, ptr, sizeof(id)); + else { - fprintf(stderr, "load_messages: Need a msgid line before any " - "translation strings on line %d of %s!\n", + fprintf(stderr, "ERROR: Unexpected text on line %d of %s!\n", linenum, f); cupsFileClose(fp); return (-1); } - - strlcpy(str, ptr, sizeof(str)); } - else if (line[0] == '\"' && str[0]) - strlcat(str, ptr, sizeof(str)); - else if (line[0] == '\"' && id[0]) - strlcat(id, ptr, sizeof(id)); - else + + if (id[0] && str[0]) { - fprintf(stderr, "load_messages: Unexpected text on line %d of %s!\n", - linenum, f); - cupsFileClose(fp); - return (-1); + temp = new ppdcMessage(id, str); + + messages->add(temp); } } + else + goto unknown_load_format; - if (id[0] && str[0]) - { - temp = new ppdcMessage(id, str); - - messages->add(temp); - } + /* + * Close the file and return... + */ cupsFileClose(fp); return (0); + + /* + * Unknown format error... + */ + + unknown_load_format: + + fprintf(stderr, "ERROR: Unknown message catalog format for \"%s\"!\n", f); + cupsFileClose(fp); + return (-1); } @@ -308,55 +445,132 @@ ppdcCatalog::save_messages( { cups_file_t *fp; // Message file ppdcMessage *m; // Current message - const char *ptr; // Pointer into string + char *ptr; // Pointer into string + int utf16; // Output UTF-16 .strings file? + int ch; // Current character - if ((fp = cupsFileOpen(f, "w")) == NULL) + // Open the file... + if ((ptr = strrchr(f, '.')) == NULL) return (-1); + if (!strcmp(ptr, ".gz")) + fp = cupsFileOpen(f, "w9"); + else + fp = cupsFileOpen(f, "w"); + + if (!fp) + return (-1); + + // For .strings files, write a BOM for big-endian output... + utf16 = !strcmp(ptr, ".strings"); + + if (utf16) + put_utf16(fp, 0xfeff); + + // Loop through all of the messages... for (m = (ppdcMessage *)messages->first(); m; m = (ppdcMessage *)messages->next()) { - cupsFilePuts(fp, "msgid \""); - for (ptr = m->id->value; *ptr; ptr ++) - switch (*ptr) - { - case '\n' : - cupsFilePuts(fp, "\\n"); - break; - case '\\' : - cupsFilePuts(fp, "\\\\"); - break; - case '\"' : - cupsFilePuts(fp, "\\\""); - break; - default : - cupsFilePutChar(fp, *ptr); - break; - } - cupsFilePuts(fp, "\"\n"); + if (utf16) + { + put_utf16(fp, '\"'); - cupsFilePuts(fp, "msgstr \""); - for (ptr = m->string->value; *ptr; ptr ++) - switch (*ptr) - { - case '\n' : - cupsFilePuts(fp, "\\n"); - break; - case '\\' : - cupsFilePuts(fp, "\\\\"); - break; - case '\"' : - cupsFilePuts(fp, "\\\""); - break; - default : - cupsFilePutChar(fp, *ptr); - break; - } - cupsFilePuts(fp, "\"\n"); + ptr = m->id->value; + while ((ch = get_utf8(ptr)) != 0) + switch (ch) + { + case '\n' : + put_utf16(fp, '\\'); + put_utf16(fp, 'n'); + break; + case '\\' : + put_utf16(fp, '\\'); + put_utf16(fp, '\\'); + break; + case '\"' : + put_utf16(fp, '\\'); + put_utf16(fp, '\"'); + break; + default : + put_utf16(fp, ch); + break; + } + + put_utf16(fp, '\"'); + put_utf16(fp, ' '); + put_utf16(fp, '='); + put_utf16(fp, ' '); + put_utf16(fp, '\"'); + + ptr = m->string->value; + while ((ch = get_utf8(ptr)) != 0) + switch (ch) + { + case '\n' : + put_utf16(fp, '\\'); + put_utf16(fp, 'n'); + break; + case '\\' : + put_utf16(fp, '\\'); + put_utf16(fp, '\\'); + break; + case '\"' : + put_utf16(fp, '\\'); + put_utf16(fp, '\"'); + break; + default : + put_utf16(fp, ch); + break; + } - cupsFilePutChar(fp, '\n'); + put_utf16(fp, '\"'); + put_utf16(fp, ';'); + put_utf16(fp, '\n'); + } + else + { + cupsFilePuts(fp, "msgid \""); + for (ptr = m->id->value; *ptr; ptr ++) + switch (*ptr) + { + case '\n' : + cupsFilePuts(fp, "\\n"); + break; + case '\\' : + cupsFilePuts(fp, "\\\\"); + break; + case '\"' : + cupsFilePuts(fp, "\\\""); + break; + default : + cupsFilePutChar(fp, *ptr); + break; + } + cupsFilePuts(fp, "\"\n"); + + cupsFilePuts(fp, "msgstr \""); + for (ptr = m->string->value; *ptr; ptr ++) + switch (*ptr) + { + case '\n' : + cupsFilePuts(fp, "\\n"); + break; + case '\\' : + cupsFilePuts(fp, "\\\\"); + break; + case '\"' : + cupsFilePuts(fp, "\\\""); + break; + default : + cupsFilePutChar(fp, *ptr); + break; + } + cupsFilePuts(fp, "\"\n"); + + cupsFilePutChar(fp, '\n'); + } } cupsFileClose(fp); @@ -365,6 +579,287 @@ ppdcCatalog::save_messages( } +// +// 'get_utf8()' - Get a UTF-8 character. +// + +static int // O - Unicode character or 0 on EOF +get_utf8(char *&ptr) // IO - Pointer to character +{ + int ch; // Current character + + + if ((ch = *ptr++ & 255) < 0xc0) + return (ch); + + if ((ch & 0xe0) == 0xc0) + { + // Two-byte UTF-8... + if ((*ptr & 0xc0) != 0x80) + return (0); + + ch = ((ch & 0x1f) << 6) | (*ptr++ & 0x3f); + } + else if ((ch & 0xf0) == 0xe0) + { + // Three-byte UTF-8... + if ((*ptr & 0xc0) != 0x80) + return (0); + + ch = ((ch & 0x0f) << 6) | (*ptr++ & 0x3f); + + if ((*ptr & 0xc0) != 0x80) + return (0); + + ch = (ch << 6) | (*ptr++ & 0x3f); + } + else if ((ch & 0xf8) == 0xf0) + { + // Four-byte UTF-8... + if ((*ptr & 0xc0) != 0x80) + return (0); + + ch = ((ch & 0x07) << 6) | (*ptr++ & 0x3f); + + if ((*ptr & 0xc0) != 0x80) + return (0); + + ch = (ch << 6) | (*ptr++ & 0x3f); + + if ((*ptr & 0xc0) != 0x80) + return (0); + + ch = (ch << 6) | (*ptr++ & 0x3f); + } + + return (ch); +} + + +// +// 'get_utf16()' - Get a UTF-16 character... +// + +static int // O - Unicode character or 0 on EOF +get_utf16(cups_file_t *fp, // I - File to read from + ppdc_cs_t &cs) // IO - Character set of file +{ + int ch; // Current character + unsigned char buffer[3]; // Bytes + + + if (cs == PPDC_CS_AUTO) + { + // Get byte-order-mark, if present... + if (cupsFileRead(fp, (char *)buffer, 2) != 2) + return (0); + + if (buffer[0] == 0xfe && buffer[1] == 0xff) + { + // Big-endian UTF-16... + cs = PPDC_CS_UTF16BE; + + if (cupsFileRead(fp, (char *)buffer, 2) != 2) + return (0); + } + else if (buffer[0] == 0xff && buffer[1] == 0xfe) + { + // Little-endian UTF-16... + cs = PPDC_CS_UTF16LE; + + if (cupsFileRead(fp, (char *)buffer, 2) != 2) + return (0); + } + else if (buffer[0] == 0x00 && buffer[1] != 0x00) + { + // No BOM, assume big-endian UTF-16... + cs = PPDC_CS_UTF16BE; + } + else if (buffer[0] != 0x00 && buffer[1] == 0x00) + { + // No BOM, assume little-endian UTF-16... + cs = PPDC_CS_UTF16LE; + } + else + { + // No BOM, assume UTF-8... + cs = PPDC_CS_UTF8; + + cupsFileRewind(fp); + } + } + else if (cs != PPDC_CS_UTF8) + { + if (cupsFileRead(fp, (char *)buffer, 2) != 2) + return (0); + } + + if (cs == PPDC_CS_UTF8) + { + // UTF-8 character... + ch = cupsFileGetChar(fp); + + if ((ch & 0xe0) == 0xc0) + { + // Two-byte UTF-8... + if (cupsFileRead(fp, (char *)buffer, 1) != 1) + return (0); + + if ((buffer[0] & 0xc0) != 0x80) + return (0); + + ch = ((ch & 0x1f) << 6) | (buffer[0] & 0x3f); + } + else if ((ch & 0xf0) == 0xe0) + { + // Three-byte UTF-8... + if (cupsFileRead(fp, (char *)buffer, 2) != 2) + return (0); + + if ((buffer[0] & 0xc0) != 0x80 || + (buffer[1] & 0xc0) != 0x80) + return (0); + + ch = ((((ch & 0x0f) << 6) | (buffer[0] & 0x3f)) << 6) | + (buffer[1] & 0x3f); + } + else if ((ch & 0xf8) == 0xf0) + { + // Four-byte UTF-8... + if (cupsFileRead(fp, (char *)buffer, 3) != 3) + return (0); + + if ((buffer[0] & 0xc0) != 0x80 || + (buffer[1] & 0xc0) != 0x80 || + (buffer[2] & 0xc0) != 0x80) + return (0); + + ch = ((((((ch & 0x07) << 6) | (buffer[0] & 0x3f)) << 6) | + (buffer[1] & 0x3f)) << 6) | (buffer[2] & 0x3f); + } + } + else + { + // UTF-16 character... + if (cs == PPDC_CS_UTF16BE) + ch = (buffer[0] << 8) | buffer[1]; + else + ch = (buffer[1] << 8) | buffer[0]; + + if (ch >= 0xd800 && ch <= 0xdbff) + { + // Handle multi-word encoding... + int lch; + + if (cupsFileRead(fp, (char *)buffer, 2) != 2) + return (0); + + if (cs == PPDC_CS_UTF16BE) + lch = (buffer[0] << 8) | buffer[1]; + else + lch = (buffer[1] << 8) | buffer[0]; + + if (lch < 0xdc00 || lch >= 0xdfff) + return (0); + + ch = (((ch & 0x3ff) << 10) | (lch & 0x3ff)) + 0x10000; + } + } + + return (ch); +} + + +// +// 'put_utf8()' - Add a UTF-8 character to a string. +// + +static int // O - 0 on success, -1 on failure +put_utf8(int ch, // I - Unicode character + char *&ptr, // IO - String pointer + char *end) // I - End of buffer +{ + if (ch < 0x80) + { + // One-byte ASCII... + if (ptr >= end) + return (-1); + + *ptr++ = ch; + } + else if (ch < 0x800) + { + // Two-byte UTF-8... + if ((ptr + 1) >= end) + return (-1); + + *ptr++ = 0xc0 | (ch >> 6); + *ptr++ = 0x80 | (ch & 0x3f); + } + else if (ch < 0x10000) + { + // Three-byte UTF-8... + if ((ptr + 2) >= end) + return (-1); + + *ptr++ = 0xe0 | (ch >> 12); + *ptr++ = 0x80 | ((ch >> 6) & 0x3f); + *ptr++ = 0x80 | (ch & 0x3f); + } + else + { + // Four-byte UTF-8... + if ((ptr + 3) >= end) + return (-1); + + *ptr++ = 0xf0 | (ch >> 18); + *ptr++ = 0x80 | ((ch >> 12) & 0x3f); + *ptr++ = 0x80 | ((ch >> 6) & 0x3f); + *ptr++ = 0x80 | (ch & 0x3f); + } + + return (0); +} + + +// +// 'put_utf16()' - Write a UTF-16 character to a file. +// + +static int // O - 0 on success, -1 on failure +put_utf16(cups_file_t *fp, // I - File to write to + int ch) // I - Unicode character +{ + unsigned char buffer[4]; // Output buffer + + + if (ch < 0x10000) + { + // One-word UTF-16 big-endian... + buffer[0] = ch >> 8; + buffer[1] = ch; + + if (cupsFileWrite(fp, (char *)buffer, 2) == 2) + return (0); + } + else + { + // Two-word UTF-16 big-endian... + ch -= 0x10000; + + buffer[0] = 0xd8 | (ch >> 18); + buffer[1] = ch >> 10; + buffer[2] = 0xdc | ((ch >> 8) & 0x03); + buffer[3] = ch; + + if (cupsFileWrite(fp, (char *)buffer, 4) == 4) + return (0); + } + + return (-1); +} + + // // End of "$Id$". // diff --git a/ppdc/ppdmerge.cxx b/ppdc/ppdmerge.cxx index 598b4b8d6..1db93444f 100644 --- a/ppdc/ppdmerge.cxx +++ b/ppdc/ppdmerge.cxx @@ -297,6 +297,7 @@ ppd_locale(ppd_file_t *ppd) // I - PPD file } languages[] = { { "chinese", "zh" }, + { "czech", "cs" }, { "danish", "da" }, { "dutch", "nl" }, { "english", "en" }, @@ -304,6 +305,7 @@ ppd_locale(ppd_file_t *ppd) // I - PPD file { "french", "fr" }, { "german", "de" }, { "greek", "el" }, + { "hungarian", "hu" }, { "italian", "it" }, { "japanese", "ja" }, { "korean", "ko" }, diff --git a/scheduler/Makefile b/scheduler/Makefile index faea0b37d..e359e05cb 100644 --- a/scheduler/Makefile +++ b/scheduler/Makefile @@ -212,7 +212,6 @@ install-libs: $(INSTALLSTATIC) $(INSTALL32) $(INSTALL64) $(LN) $(LIBCUPSMIME) $(LIBDIR)/`basename $(LIBCUPSMIME) .1`; \ fi if test $(LIBCUPSMIME) = "libcupsmime.1.dylib"; then \ - $(STRIP) -x $(LIBDIR)/$(LIBCUPSMIME); \ $(RM) $(LIBDIR)/libcupsmime.dylib; \ $(LN) $(LIBCUPSMIME) $(LIBDIR)/libcupsmime.dylib; \ fi diff --git a/scheduler/client.c b/scheduler/client.c index c2d772b6a..94ddc900a 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -1450,7 +1450,9 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ break; } - else if (con->http.data_remaining < 0) + else if (con->http.data_remaining < 0 || + (!con->http.fields[HTTP_FIELD_CONTENT_LENGTH][0] && + con->http.data_encoding == HTTP_ENCODE_LENGTH)) { /* * Negative content lengths are invalid! diff --git a/scheduler/cups-driverd.c b/scheduler/cups-driverd.c index c9a82044d..9a199b015 100644 --- a/scheduler/cups-driverd.c +++ b/scheduler/cups-driverd.c @@ -1079,6 +1079,7 @@ load_ppds(const char *d, /* I - Actual directory */ } languages[] = { { "chinese", "zh" }, + { "czech", "cs" }, { "danish", "da" }, { "dutch", "nl" }, { "english", "en" }, @@ -1086,6 +1087,7 @@ load_ppds(const char *d, /* I - Actual directory */ { "french", "fr" }, { "german", "de" }, { "greek", "el" }, + { "hungarian", "hu" }, { "italian", "it" }, { "japanese", "ja" }, { "korean", "ko" }, @@ -1102,9 +1104,11 @@ load_ppds(const char *d, /* I - Actual directory */ if ((dir = cupsDirOpen(d)) == NULL) { - fprintf(stderr, - "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n", - d, strerror(errno)); + if (errno != ENOENT) + fprintf(stderr, + "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n", + d, strerror(errno)); + return (0); } @@ -1582,8 +1586,8 @@ load_drivers(void) if ((dir = cupsDirOpen(drivers)) == NULL) { fprintf(stderr, "ERROR: [cups-driverd] Unable to open driver directory " - "\"%s\": %s\n", - drivers, strerror(errno)); + "\"%s\": %s\n", + drivers, strerror(errno)); return (0); } diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 24ee885d3..9ecca1cde 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -8970,13 +8970,13 @@ save_auth_info( cupsFilePrintf(fp, "%s\n", line); if (!strcmp(dest->auth_info_required[i], "username")) - cupsdSetStringf(&job->auth_username, "CUPSD_AUTH_USERNAME=%s", + cupsdSetStringf(&job->auth_username, "AUTH_USERNAME=%s", auth_info->values[i].string.text); else if (!strcmp(dest->auth_info_required[i], "domain")) - cupsdSetStringf(&job->auth_domain, "CUPSD_AUTH_DOMAIN=%s", + cupsdSetStringf(&job->auth_domain, "AUTH_DOMAIN=%s", auth_info->values[i].string.text); else if (!strcmp(dest->auth_info_required[i], "password")) - cupsdSetStringf(&job->auth_password, "CUPSD_AUTH_PASSWORD=%s", + cupsdSetStringf(&job->auth_password, "AUTH_PASSWORD=%s", auth_info->values[i].string.text); } } @@ -8989,7 +8989,7 @@ save_auth_info( httpEncode64_2(line, sizeof(line), con->username, strlen(con->username)); cupsFilePrintf(fp, "%s\n", line); - cupsdSetStringf(&job->auth_username, "CUPSD_AUTH_USERNAME=%s", con->username); + cupsdSetStringf(&job->auth_username, "AUTH_USERNAME=%s", con->username); cupsdClearString(&job->auth_domain); /* @@ -8999,7 +8999,7 @@ save_auth_info( httpEncode64_2(line, sizeof(line), con->password, strlen(con->password)); cupsFilePrintf(fp, "%s\n", line); - cupsdSetStringf(&job->auth_password, "CUPSD_AUTH_PASSWORD=%s", con->password); + cupsdSetStringf(&job->auth_password, "AUTH_PASSWORD=%s", con->password); } /* diff --git a/scheduler/log.c b/scheduler/log.c index 77ab3e5e8..698f5eb70 100644 --- a/scheduler/log.c +++ b/scheduler/log.c @@ -65,6 +65,13 @@ cupsdGetDateTime(time_t t) /* I - Time value */ }; + /* + * Make sure we have a valid time... + */ + + if (!t) + t = time(NULL); + if (t != last_time) { last_time = t; @@ -174,7 +181,7 @@ cupsdLogMessage(int level, /* I - Log level */ 'd' }; #ifdef HAVE_VSYSLOG - static const int syslevels[] = /* SYSLOG levels... */ + static const int syslevels[] = /* SYSLOG levels... */ { 0, LOG_EMERG, @@ -188,8 +195,8 @@ cupsdLogMessage(int level, /* I - Log level */ LOG_DEBUG }; #endif /* HAVE_VSYSLOG */ - static int linesize = 0; /* Size of line for output file */ - static char *line = NULL; /* Line for output file */ + static int linesize = 0; /* Size of line for output file */ + static char *line = NULL; /* Line for output file */ /* @@ -388,6 +395,7 @@ int /* O - 1 on success, 0 on error */ cupsdLogRequest(cupsd_client_t *con, /* I - Request to log */ http_status_t code) /* I - Response code */ { + char temp[2048]; /* Temporary string for URI */ static const char * const states[] = /* HTTP client states... */ { "WAITING", @@ -417,7 +425,7 @@ cupsdLogRequest(cupsd_client_t *con, /* I - Request to log */ syslog(LOG_INFO, "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n", con->http.hostname, con->username[0] != '\0' ? con->username : "-", - states[con->operation], con->uri, + states[con->operation], _httpEncodeURI(temp, con->uri, sizeof(temp)), con->http.version / 100, con->http.version % 100, code, CUPS_LLCAST con->bytes, con->request ? @@ -443,7 +451,8 @@ cupsdLogRequest(cupsd_client_t *con, /* I - Request to log */ cupsFilePrintf(AccessFile, "%s - %s %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n", con->http.hostname, con->username[0] != '\0' ? con->username : "-", - cupsdGetDateTime(con->start), states[con->operation], con->uri, + cupsdGetDateTime(con->start), states[con->operation], + _httpEncodeURI(temp, con->uri, sizeof(temp)), con->http.version / 100, con->http.version % 100, code, CUPS_LLCAST con->bytes, con->request ? diff --git a/scripting/php/Makefile b/scripting/php/Makefile index bc07028fe..09b07fb24 100644 --- a/scripting/php/Makefile +++ b/scripting/php/Makefile @@ -82,7 +82,7 @@ install-data: install-exec: echo Installing $(PHPCUPS) in $(PHPDIR) $(INSTALL_DIR) $(PHPDIR) - $(INSTALL_BIN) $(PHPCUPS) $(PHPDIR) + $(INSTALL_LIB) $(PHPCUPS) $(PHPDIR) if test "x$(SYMROOT)" != x; then \ $(INSTALL_DIR) $(SYMROOT); \ cp $(PHPCUPS) $(SYMROOT); \ diff --git a/test/4.3-job-ops.test b/test/4.3-job-ops.test index f086ed369..0d3a42cf8 100644 --- a/test/4.3-job-ops.test +++ b/test/4.3-job-ops.test @@ -159,10 +159,10 @@ } { # The name of the test... - NAME "Print Image Job to Test1" + NAME "Hold Job on Test1" # The operation to use - OPERATION print-job + OPERATION hold-job RESOURCE /printers/Test1 # The attributes to send @@ -170,24 +170,22 @@ ATTR charset attributes-charset utf-8 ATTR language attributes-natural-language en ATTR uri printer-uri $method://$hostname:$port/printers/Test1 + ATTR integer job-id $job-id ATTR name requesting-user-name $user - FILE testfile.jpg - # What statuses are OK? STATUS successful-ok # What attributes do we expect? EXPECT attributes-charset EXPECT attributes-natural-language - EXPECT job-id } { # The name of the test... - NAME "Hold Job on Test1" + NAME "Release Job on Test1" # The operation to use - OPERATION hold-job + OPERATION release-job RESOURCE /printers/Test1 # The attributes to send @@ -207,10 +205,10 @@ } { # The name of the test... - NAME "Release Job on Test1" + NAME "Print Held Image Job to Test1" # The operation to use - OPERATION release-job + OPERATION print-job RESOURCE /printers/Test1 # The attributes to send @@ -218,8 +216,11 @@ ATTR charset attributes-charset utf-8 ATTR language attributes-natural-language en ATTR uri printer-uri $method://$hostname:$port/printers/Test1 - ATTR integer job-id $job-id ATTR name requesting-user-name $user + GROUP job + ATTR keyword job-hold-until indefinite + + FILE testfile.jpg # What statuses are OK? STATUS successful-ok @@ -227,20 +228,22 @@ # What attributes do we expect? EXPECT attributes-charset EXPECT attributes-natural-language + EXPECT job-id } { # The name of the test... - NAME "Get Job List on Test1" + NAME "Cancel Job" # The operation to use - OPERATION get-jobs - RESOURCE /printers/Test1 + OPERATION cancel-job + RESOURCE /jobs # The attributes to send GROUP operation ATTR charset attributes-charset utf-8 ATTR language attributes-natural-language en - ATTR uri printer-uri $method://$hostname:$port/printers/Test1 + ATTR uri job-uri $method://$hostname:$port/jobs/$job-id + ATTR name requesting-user-name $user # What statuses are OK? STATUS successful-ok @@ -251,17 +254,17 @@ } { # The name of the test... - NAME "Get All Jobs" + NAME "Get Job List on Test1" # The operation to use OPERATION get-jobs - RESOURCE /jobs + RESOURCE /printers/Test1 # The attributes to send GROUP operation ATTR charset attributes-charset utf-8 ATTR language attributes-natural-language en - ATTR uri job-uri $method://$hostname:$port/jobs + ATTR uri printer-uri $method://$hostname:$port/printers/Test1 # What statuses are OK? STATUS successful-ok @@ -269,24 +272,20 @@ # What attributes do we expect? EXPECT attributes-charset EXPECT attributes-natural-language - EXPECT job-uri - EXPECT job-id - EXPECT job-state } { # The name of the test... - NAME "Cancel Job" + NAME "Get All Jobs" # The operation to use - OPERATION cancel-job + OPERATION get-jobs RESOURCE /jobs # The attributes to send GROUP operation ATTR charset attributes-charset utf-8 ATTR language attributes-natural-language en - ATTR uri job-uri $method://$hostname:$port/jobs/$job-id - ATTR name requesting-user-name $user + ATTR uri job-uri $method://$hostname:$port/jobs # What statuses are OK? STATUS successful-ok @@ -294,6 +293,9 @@ # What attributes do we expect? EXPECT attributes-charset EXPECT attributes-natural-language + EXPECT job-uri + EXPECT job-id + EXPECT job-state } # diff --git a/test/5.5-lp.sh b/test/5.5-lp.sh index 8c340f5e5..d1928eb54 100644 --- a/test/5.5-lp.sh +++ b/test/5.5-lp.sh @@ -4,7 +4,7 @@ # # Test the lp command. # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2008 by Apple Inc. # Copyright 1997-2005 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -16,8 +16,8 @@ echo "LP Default Test" echo "" -echo " lp testfile.jpg" -../systemv/lp testfile.jpg 2>&1 +echo " lp testfile.pdf" +../systemv/lp testfile.pdf 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -28,8 +28,20 @@ echo "" echo "LP Destination Test" echo "" -echo " lp -d Test1 testfile.jpg" -../systemv/lp -d Test1 -o job-hold-until=indefinite testfile.jpg 2>&1 +echo " lp -d Test2 testfile.jpg" +../systemv/lp -d Test2 testfile.jpg 2>&1 +if test $? != 0; then + echo " FAILED" + exit 1 +else + echo " PASSED" +fi +echo "" + +echo "LP Options Test" +echo "" +echo " lp -d Test1 -P 1-4 -o job-sheets=classified,classified testfile.pdf" +../systemv/lp -d Test1 -P 1-4 -o job-sheets=classified,classified testfile.pdf 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -38,13 +50,15 @@ else fi echo "" -echo "LP Flood Test" +echo "LP Flood Test ($1 times in parallel)" echo "" -echo " lp -d Test1 testfile.jpg ($1 times in parallel)" +echo " lp -d Test1 testfile.jpg" +echo " lp -d Test2 testfile.jpg" i=0 while test $i -lt $1; do echo " flood copy $i..." 1>&2 ../systemv/lp -d Test1 testfile.jpg 2>&1 & + ../systemv/lp -d Test2 testfile.jpg 2>&1 & lppid=$! i=`expr $i + 1` done @@ -57,6 +71,8 @@ else fi echo "" +./waitjobs.sh + # # End of "$Id: 5.5-lp.sh 6649 2007-07-11 21:46:42Z mike $". # diff --git a/test/5.6-lpr.sh b/test/5.6-lpr.sh index 1de750fac..a1fe01d35 100644 --- a/test/5.6-lpr.sh +++ b/test/5.6-lpr.sh @@ -4,7 +4,7 @@ # # Test the lpr command. # -# Copyright 2007 by Apple Inc. +# Copyright 2007-2008 by Apple Inc. # Copyright 1997-2005 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -16,8 +16,8 @@ echo "LPR Default Test" echo "" -echo " lpr testfile.jpg" -../berkeley/lpr testfile.jpg 2>&1 +echo " lpr testfile.pdf" +../berkeley/lpr testfile.pdf 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -28,8 +28,20 @@ echo "" echo "LPR Destination Test" echo "" -echo " lpr -P Test1 testfile.jpg" -../berkeley/lpr -P Test1 testfile.jpg 2>&1 +echo " lpr -P Test2 testfile.jpg" +../berkeley/lpr -P Test2 testfile.jpg 2>&1 +if test $? != 0; then + echo " FAILED" + exit 1 +else + echo " PASSED" +fi +echo "" + +echo "LPR Options Test" +echo "" +echo " lpr -P Test1 -o number-up=4 -o job-sheets=standard,none testfile.pdf" +../berkeley/lpr -P Test1 -o number-up=4 -o job-sheets=standard,none testfile.pdf 2>&1 if test $? != 0; then echo " FAILED" exit 1 @@ -38,13 +50,15 @@ else fi echo "" -echo "LPR Flood Test" +echo "LPR Flood Test ($1 times in parallel)" echo "" -echo " lpr -P Test1 testfile.jpg ($1 times in parallel)" +echo " lpr -P Test1 testfile.jpg" +echo " lpr -P Test2 testfile.jpg" i=0 while test $i -lt $1; do echo " flood copy $i..." 1>&2 ../berkeley/lpr -P Test1 testfile.jpg 2>&1 & + ../berkeley/lpr -P Test2 testfile.jpg 2>&1 & lprpid=$! i=`expr $i + 1` done @@ -57,6 +71,8 @@ else fi echo "" +./waitjobs.sh + # # End of "$Id: 5.6-lpr.sh 6649 2007-07-11 21:46:42Z mike $". # diff --git a/test/5.7-lprm.sh b/test/5.7-lprm.sh index f2848ed84..fe323db15 100644 --- a/test/5.7-lprm.sh +++ b/test/5.7-lprm.sh @@ -16,6 +16,8 @@ echo "LPRM Current Test" echo "" +echo " lpr -o job-hold-until=indefinite testfile.jpg" +../berkeley/lpr -o job-hold-until=indefinite testfile.jpg 2>&1 echo " lprm" ../berkeley/lprm 2>&1 if test $? != 0; then @@ -28,6 +30,8 @@ echo "" echo "LPRM Destination Test" echo "" +echo " lpr -P Test1 -o job-hold-until=indefinite testfile.jpg" +../berkeley/lpr -P Test1 -o job-hold-until=indefinite testfile.jpg 2>&1 echo " lprm Test1" ../berkeley/lprm Test1 2>&1 if test $? != 0; then diff --git a/test/5.8-cancel.sh b/test/5.8-cancel.sh index 9212d4387..90a688d52 100644 --- a/test/5.8-cancel.sh +++ b/test/5.8-cancel.sh @@ -4,7 +4,7 @@ # # Test the cancel command. # -# 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 @@ -16,6 +16,8 @@ echo "Cancel Destination Test" echo "" +echo " lp -d Test1 -o job-hold-until=indefinite testfile.jpg" +../systemv/lp -d Test1 -o job-hold-until=indefinite testfile.jpg 2>&1 echo " cancel Test1" ../systemv/cancel Test1 2>&1 if test $? != 0; then diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh index ba5184cff..c9e5d28d2 100755 --- a/test/run-stp-tests.sh +++ b/test/run-stp-tests.sh @@ -5,7 +5,7 @@ # Perform the complete set of IPP compliance tests specified in the # CUPS Software Test Plan. # -# 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 @@ -97,7 +97,7 @@ case "$testtype" in echo "Running the timid tests (1)" nprinters1=0 nprinters2=0 - pjobs=0 + pjobs=10 ;; esac @@ -207,6 +207,7 @@ rm -rf /tmp/cups-$user mkdir /tmp/cups-$user mkdir /tmp/cups-$user/bin mkdir /tmp/cups-$user/bin/backend +mkdir /tmp/cups-$user/bin/driver mkdir /tmp/cups-$user/bin/filter mkdir /tmp/cups-$user/certs mkdir /tmp/cups-$user/share @@ -228,17 +229,15 @@ ln -s $root/backend/snmp /tmp/cups-$user/bin/backend ln -s $root/backend/socket /tmp/cups-$user/bin/backend ln -s $root/backend/usb /tmp/cups-$user/bin/backend ln -s $root/cgi-bin /tmp/cups-$user/bin +ln -s $root/ppdc/drv /tmp/cups-$user/bin/driver ln -s $root/monitor /tmp/cups-$user/bin ln -s $root/notifier /tmp/cups-$user/bin ln -s $root/scheduler /tmp/cups-$user/bin/daemon ln -s $root/filter/hpgltops /tmp/cups-$user/bin/filter -ln -s $root/filter/imagetops /tmp/cups-$user/bin/filter -ln -s $root/filter/imagetoraster /tmp/cups-$user/bin/filter ln -s $root/filter/pstops /tmp/cups-$user/bin/filter ln -s $root/filter/rastertoepson /tmp/cups-$user/bin/filter ln -s $root/filter/rastertohp /tmp/cups-$user/bin/filter ln -s $root/filter/texttops /tmp/cups-$user/bin/filter -ln -s $root/filter/pdftops /tmp/cups-$user/bin/filter ln -s $root/data/classified /tmp/cups-$user/share/banners ln -s $root/data/confidential /tmp/cups-$user/share/banners @@ -272,9 +271,12 @@ if test `uname` = Darwin; then ln -s /usr/libexec/cups/filter/pstopdffilter /tmp/cups-$user/bin/filter ln -s /private/etc/cups/apple.* /tmp/cups-$user +else + ln -s $root/filter/imagetops /tmp/cups-$user/bin/filter + ln -s $root/filter/imagetoraster /tmp/cups-$user/bin/filter + ln -s $root/filter/pdftops /tmp/cups-$user/bin/filter fi - # # Then create the necessary config files... # @@ -430,11 +432,6 @@ echo "" $valgrind ../scheduler/cupsd -c /tmp/cups-$user/cupsd.conf -f >/tmp/cups-$user/log/debug_log 2>&1 & cupsd=$! -#if test -x /usr/bin/strace; then -# # Trace system calls in cupsd if we have strace... -# /usr/bin/strace -tt -o /tmp/cups-$user/log/cupsd.trace -p $cupsd & -#fi - if test "x$testtype" = x0; then echo "Scheduler is PID $cupsd and is listening on port 8631." echo "" @@ -469,7 +466,7 @@ done # Create the test report source file... # -strfile=cups-str-1.4-`date +%Y-%m-%d`-$user.html +strfile=/tmp/cups-$user/cups-str-1.4-`date +%Y-%m-%d`-$user.html rm -f $strfile cat str-header.html >$strfile @@ -492,7 +489,7 @@ for file in 4*.test; do echo "Performing $file..." echo "" >>$strfile - ./ipptest ipp://localhost:$port/printers $file >>$strfile + ./ipptest ipp://localhost:$port/printers $file | tee -a $strfile status=$? if test $status != 0; then @@ -521,7 +518,7 @@ for file in 5*.sh; do echo "" >>$strfile echo "\"$file\":" >>$strfile - sh $file $pjobs >>$strfile + sh $file $pjobs | tee -a $strfile status=$? if test $status != 0; then @@ -532,20 +529,6 @@ done echo "" >>$strfile -# -# Wait for jobs to complete... -# - -while true; do - jobs=`../systemv/lpstat 2>/dev/null` - if test "x$jobs" = "x"; then - break - fi - - echo "Waiting for jobs to complete..." - sleep 10 -done - # # Stop the server... # @@ -558,28 +541,182 @@ kill $cupsd echo "

    3 - Log Files

    " >>$strfile +# +# Verify counts... +# + +echo "Test Summary" +echo "" +echo "

    Summary

    " >>$strfile + +# Pages printed on Test1 +count=`grep '^Test1 ' /tmp/cups-$user/log/page_log | awk 'BEGIN{count=0}{count=count+$7}END{print count}'` +expected=`expr $pjobs \* 2 + 35` +if test $count != $expected; then + echo "FAIL: Printer 'Test1' produced $count page(s), expected $expected." + echo "

    FAIL: Printer 'Test1' produced $count page(s), expected $expected.

    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: Printer 'Test1' correctly produced $count page(s)." + echo "

    PASS: Printer 'Test1' correctly produced $count page(s).

    " >>$strfile +fi + +# Paged printed on Test2 +count=`grep '^Test2 ' /tmp/cups-$user/log/page_log | awk 'BEGIN{count=0}{count=count+$7}END{print count}'` +expected=`expr $pjobs \* 2 + 3` +if test $count != $expected; then + echo "FAIL: Printer 'Test2' produced $count page(s), expected $expected." + echo "

    FAIL: Printer 'Test2' produced $count page(s), expected $expected.

    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: Printer 'Test2' correctly produced $count page(s)." + echo "

    PASS: Printer 'Test2' correctly produced $count page(s).

    " >>$strfile +fi + +# Requested processed +count=`wc -l /tmp/cups-$user/log/access_log | awk '{print $1}'` +echo "PASS: $count requests processed." +echo "

    PASS: $count requests processed.

    " >>$strfile + +# Emergency log messages +count=`grep '^X ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +if test $count != 0; then + echo "FAIL: $count emergency messages, expected 0." + grep '^X ' /tmp/cups-$user/log/error_log + echo "

    FAIL: $count emergency messages, expected 0.

    " >>$strfile + echo "
    " >>$strfile
    +	grep '^X ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
    +	echo "
    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: $count emergency messages." + echo "

    PASS: $count emergency messages.

    " >>$strfile +fi + +# Alert log messages +count=`grep '^A ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +if test $count != 0; then + echo "FAIL: $count alert messages, expected 0." + grep '^A ' /tmp/cups-$user/log/error_log + echo "

    FAIL: $count alert messages, expected 0.

    " >>$strfile + echo "
    " >>$strfile
    +	grep '^A ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
    +	echo "
    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: $count alert messages." + echo "

    PASS: $count alert messages.

    " >>$strfile +fi + +# Critical log messages +count=`grep '^C ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +if test $count != 0; then + echo "FAIL: $count critical messages, expected 0." + grep '^C ' /tmp/cups-$user/log/error_log + echo "

    FAIL: $count critical messages, expected 0.

    " >>$strfile + echo "
    " >>$strfile
    +	grep '^C ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
    +	echo "
    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: $count critical messages." + echo "

    PASS: $count critical messages.

    " >>$strfile +fi + +# Error log messages +count=`grep '^E ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +if test $count != 9; then + echo "FAIL: $count error messages, expected 9." + grep '^E ' /tmp/cups-$user/log/error_log + echo "

    FAIL: $count error messages, expected 9.

    " >>$strfile + echo "
    " >>$strfile
    +	grep '^E ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
    +	echo "
    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: $count error messages." + echo "

    PASS: $count error messages.

    " >>$strfile +fi + +# Warning log messages +count=`grep '^W ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +if test $count != 0; then + echo "FAIL: $count warning messages, expected 0." + grep '^W ' /tmp/cups-$user/log/error_log + echo "

    FAIL: $count warning messages, expected 0.

    " >>$strfile + echo "
    " >>$strfile
    +	grep '^W ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
    +	echo "
    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: $count warning messages." + echo "

    PASS: $count warning messages.

    " >>$strfile +fi + +# Notice log messages +count=`grep '^N ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +if test $count != 0; then + echo "FAIL: $count notice messages, expected 0." + grep '^N ' /tmp/cups-$user/log/error_log + echo "

    FAIL: $count notice messages, expected 0.

    " >>$strfile + echo "
    " >>$strfile
    +	grep '^N ' /tmp/cups-$user/log/error_log | sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
    +	echo "
    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: $count notice messages." + echo "

    PASS: $count notice messages.

    " >>$strfile +fi + +# Info log messages +count=`grep '^I ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +if test $count = 0; then + echo "FAIL: $count info messages, expected more than 0." + echo "

    FAIL: $count info messages, expected more than 0.

    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: $count info messages." + echo "

    PASS: $count info messages.

    " >>$strfile +fi + +# Debug log messages +count=`grep '^D ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +if test $count = 0; then + echo "FAIL: $count debug messages, expected more than 0." + echo "

    FAIL: $count debug messages, expected more than 0.

    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: $count debug messages." + echo "

    PASS: $count debug messages.

    " >>$strfile +fi + +# Debug2 log messages +count=`grep '^d ' /tmp/cups-$user/log/error_log | wc -l | awk '{print $1}'` +if test $count != 0; then + echo "FAIL: $count debug2 messages, expected 0." + echo "

    FAIL: $count debug2 messages, expected 0.

    " >>$strfile + fail=`expr $fail + 1` +else + echo "PASS: $count debug2 messages." + echo "

    PASS: $count debug2 messages.

    " >>$strfile +fi + +# Log files... echo "

    access_log

    " >>$strfile echo "
    " >>$strfile
    -cat /tmp/cups-$user/log/access_log >>$strfile
    +sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
     echo "
    " >>$strfile echo "

    error_log

    " >>$strfile echo "
    " >>$strfile
    -cat /tmp/cups-$user/log/error_log >>$strfile
    +sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
     echo "
    " >>$strfile echo "

    page_log

    " >>$strfile echo "
    " >>$strfile
    -cat /tmp/cups-$user/log/page_log >>$strfile
    +sed -e '1,$s/&/&/g' -e '1,$s/>$strfile
     echo "
    " >>$strfile -if test -f /tmp/cups-$user/log/cupsd.trace; then - echo "

    cupsd.trace

    " >>$strfile - echo "
    " >>$strfile
    -	cat /tmp/cups-$user/log/cupsd.trace >>$strfile
    -	echo "
    " >>$strfile -fi - # # Format the reports and tell the user where to find them... # @@ -595,7 +732,7 @@ else fi echo "Log files can be found in /tmp/cups-$user/log." -echo "A HTML report was created in test/$strfile." +echo "A HTML report was created in $strfile." echo "" if test $fail != 0; then diff --git a/test/str-header.html b/test/str-header.html index ec06860c2..a584063e8 100644 --- a/test/str-header.html +++ b/test/str-header.html @@ -1,18 +1,24 @@ - - + + - CUPS 1.3 Software Test Report + CUPS 1.4 Software Test Report + -

    CUPS 1.3 Software Test Report

    +

    CUPS 1.4 Software Test Report

    This software test report provides detailed test results that are used to evaluate the stability and compliance of the Common -UNIX Printing System ("CUPS") Version 1.3. +UNIX Printing System ("CUPS") Version 1.4.

    Document Overview

    diff --git a/test/waitjobs.sh b/test/waitjobs.sh new file mode 100755 index 000000000..d69e44080 --- /dev/null +++ b/test/waitjobs.sh @@ -0,0 +1,37 @@ +#!/bin/sh +# +# "$Id$" +# +# Script to wait for jobs to complete. +# +# Copyright 2008 by Apple Inc. +# +# These coded instructions, statements, and computer programs are the +# property of Apple Inc. and are protected by Federal copyright +# law. Distribution and use rights are outlined in the file "LICENSE.txt" +# which should have been included with this file. If this file is +# file is missing or damaged, see the license at "http://www.cups.org/". +# + +# Get timeout from command-line +if test $# = 1; then + timeout=$1 +else + timeout=60 +fi + +echo "Waiting for jobs to complete..." + +while test $timeout -gt 0; do + jobs=`../systemv/lpstat 2>/dev/null` + if test "x$jobs" = "x"; then + break + fi + + sleep 5 + timeout=`expr $timeout - 5` +done + +# +# End of "$Id$". +# diff --git a/tools/testosx b/tools/testosx index 13bf53da1..918e7a41c 100755 --- a/tools/testosx +++ b/tools/testosx @@ -105,7 +105,7 @@ done # Install CUPS into the Package directory... #make INSTALL=$topdir/install-sh BUILDROOT=$pkgdir/Package install -make BUILDROOT=$pkgdir/Package install +make BUILDROOT=$pkgdir/Package install || exit 1 # Figure out where PackageMaker is installled... if test -d /Developer/Applications/Utilities/PackageMaker.app; then -- 2.39.2