diff options
71 files changed, 1820 insertions, 721 deletions
diff --git a/CHANGES-1.4.txt b/CHANGES-1.4.txt index b58c52908..5dac60fbc 100644 --- a/CHANGES-1.4.txt +++ b/CHANGES-1.4.txt @@ -3,15 +3,46 @@ CHANGES-1.4.txt CHANGES IN CUPS V1.4.5 + - Documentation fixes (STR #3542) + - Fixed the Solaris SMF configuration file for cups-lpd (STR #3611) + - The scheduler did not set the notify-subscribed-event attribute when + delivering printer-added or printer-modified events (STR #3608) + - The mailto notifier could get into an infinite loop (STR #3609) + - Date/time information was not shown in banner pages. + - Relational operators were broken in #if/#elif/#else/#endif expressions + for the PPD compiler. + - Moving a job via the web interface failed without asking for + authentication (STR #3559) + - The scheduler now clears the printer-state-reasons when the driver is + changed (STR #3570) + - The web interface did not allow a user to change the driver + (STR #3537, STR #3601) + - The scheduler was not setting the PATH_INFO environment variable when + needed (STR #3600) + - The scheduler incorrectly set the CUPSD_AUTH_TYPE environment + variable instead of AUTH_TYPE (STR #3599) + - Fixed a buffer overrun in the PPD compiler (STR #3594) + - Fixed some additional IPP job template attribute mapping issues in the + scheduler. CHANGES IN CUPS V1.4.4 - Documentation updates (STR #3453, STR #3527, STR #3528, STR #3529) + - Security: The fix for CVE-2009-3553 was incomplete (STR #3490) + - Security: The texttops filter did not check the results of allocations + (STR #3516) + - Security: The web admin interface could disclose the contents of + memory (STR #3577) + - Security: CUPS could overwrite files as root in directories owned or + writable by non-root users (STR #3510) + - The cups-config utility did not return the correct linker options on + AIX (STR #3587) - Fixed some IPP conformance issues with the scheduler's ippget-event-life, operations-supported, output-bin, and sides attributes (STR #3554) - - The GNU TLS and OpenSSL interfaces have been made thread-safe + - The OpenSSL interfaces have been made thread-safe and the GNU TLS + interface is explicitly forbidden when threading is enabled (STR #3461) - Fixed an IPP conformance issue with the scheduler's Send-Document implementation (STR #3514) diff --git a/CHANGES.txt b/CHANGES.txt index 8c072e6ed..067dc958e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,11 @@ -CHANGES.txt - 2010-05-10 +CHANGES.txt - 2010-06-16 ------------------------ CHANGES IN CUPS V1.5b1 + - Added several new color spaces to the CUPS raster format (STR #3419) + - The Validate-Job operation now uses the same policy as Print-Job by + default. - CUPS now uses iconv to implement all of its character encoding support (STR #3097) - The scheduler now implements the Cancel-Jobs, Cancel-My-Jobs, and diff --git a/backend/ipp.c b/backend/ipp.c index 3ec92d227..0a41ab367 100644 --- a/backend/ipp.c +++ b/backend/ipp.c @@ -472,6 +472,8 @@ main(int argc, /* I - Number of command-line args */ if ((http = httpConnectEncrypt(hostname, port, cupsEncryption())) == NULL) { + int error = errno; /* Connection error */ + if (job_canceled) break; @@ -497,19 +499,40 @@ main(int argc, /* I - Number of command-line args */ return (CUPS_BACKEND_FAILED); } + fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno)); + if (errno == ECONNREFUSED || errno == EHOSTDOWN || errno == EHOSTUNREACH) { if (contimeout && (time(NULL) - start_time) > contimeout) { - _cupsLangPuts(stderr, _("ERROR: Printer not responding\n")); + _cupsLangPuts(stderr, _("ERROR: The printer is not responding.\n")); return (CUPS_BACKEND_FAILED); } - _cupsLangPrintf(stderr, - _("WARNING: Network host \'%s\' is busy; " - "will retry in %d seconds...\n"), - hostname, delay); + switch (error) + { + case EHOSTDOWN : + _cupsLangPrintf(stderr, + _("WARNING: Network printer \'%s\' may not exist " + "or is unavailable at this time.\n"), + hostname); + break; + + case EHOSTUNREACH : + _cupsLangPrintf(stderr, + _("WARNING: Network printer \'%s\' is " + "unreachable at this time.\n"), + hostname); + break; + + case ECONNREFUSED : + default : + _cupsLangPrintf(stderr, + _("WARNING: Network printer \'%s\' is busy.\n"), + hostname); + break; + } sleep(delay); @@ -518,16 +541,15 @@ main(int argc, /* I - Number of command-line args */ } else if (h_errno) { - _cupsLangPrintf(stderr, _("ERROR: Unable to locate printer \'%s\'\n"), + _cupsLangPrintf(stderr, + _("ERROR: Unable to locate network printer \'%s\'.\n"), hostname); return (CUPS_BACKEND_STOP); } else { - fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno)); - _cupsLangPuts(stderr, - _("ERROR: Unable to connect to printer; will retry in 30 " - "seconds...\n")); + _cupsLangPrintf(stderr, _("ERROR: Network printer \'%s\' is not " + "responding.\n"), hostname); sleep(30); } @@ -616,8 +638,11 @@ main(int argc, /* I - Number of command-line args */ if (http->version < HTTP_1_1) { + fprintf(stderr, "DEBUG: Printer responded with HTTP version %d.%d.\n", + http->version / 100, http->version % 100); + _cupsLangPuts(stderr, - _("ERROR: Unable to print - printer does not conform to " + _("ERROR: Unable to print: the printer does not conform to " "the IPP standard.\n")); exit(CUPS_BACKEND_STOP); } @@ -634,7 +659,7 @@ main(int argc, /* I - Number of command-line args */ { if (contimeout && (time(NULL) - start_time) > contimeout) { - _cupsLangPuts(stderr, _("ERROR: Printer not responding\n")); + _cupsLangPuts(stderr, _("ERROR: The printer is not responding.\n")); return (CUPS_BACKEND_FAILED); } @@ -675,7 +700,7 @@ main(int argc, /* I - Number of command-line args */ } else if (ipp_status == IPP_NOT_FOUND) { - _cupsLangPuts(stderr, _("ERROR: Destination printer does not exist\n")); + _cupsLangPuts(stderr, _("ERROR: The printer URI is incorrect or no longer exists.\n")); if (supported) ippDelete(supported); diff --git a/backend/lpd.c b/backend/lpd.c index 2b03c1667..4210ff0c4 100644 --- a/backend/lpd.c +++ b/backend/lpd.c @@ -3,7 +3,7 @@ * * Line Printer Daemon backend for the Common UNIX Printing System (CUPS). * - * Copyright 2007-2009 by Apple Inc. + * Copyright 2007-2010 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -34,6 +34,7 @@ #include <stdarg.h> #include <sys/types.h> #include <sys/stat.h> +#include <stdio.h> #ifdef WIN32 # include <winsock.h> @@ -441,7 +442,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ if ((fd = cupsTempFd(tmpfilename, sizeof(tmpfilename))) < 0) { - _cupsLangPrintError(_("ERROR: Unable to create temporary file")); + perror("DEBUG: Unable to create temporary file"); return (CUPS_BACKEND_FAILED); } @@ -587,7 +588,7 @@ lpd_command(int fd, /* I - Socket connection to LPD host */ if (lpd_write(fd, buf, bytes) < bytes) { - _cupsLangPrintError(_("ERROR: Unable to send LPD command")); + perror("DEBUG: Unable to send LPD command"); return (-1); } @@ -754,7 +755,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */ if ((fd = socket(addr->addr.addr.sa_family, SOCK_STREAM, 0)) < 0) { - _cupsLangPrintError(_("ERROR: Unable to create socket")); + perror("DEBUG: Unable to create socket"); sleep(1); continue; @@ -771,7 +772,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */ if ((fd = rresvport_af(&lport, addr->addr.addr.sa_family)) < 0) { - _cupsLangPrintError(_("ERROR: Unable to reserve port")); + perror("DEBUG: Unable to reserve port"); sleep(1); continue; @@ -824,18 +825,40 @@ lpd_queue(const char *hostname, /* I - Host to connect to */ return (CUPS_BACKEND_FAILED); } + fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error)); + if (error == ECONNREFUSED || error == EHOSTDOWN || error == EHOSTUNREACH) { if (contimeout && (time(NULL) - start_time) > contimeout) { - _cupsLangPuts(stderr, _("ERROR: Printer not responding\n")); + _cupsLangPuts(stderr, _("ERROR: The printer is not responding.\n")); return (CUPS_BACKEND_FAILED); } - _cupsLangPrintf(stderr, - _("WARNING: Network host \'%s\' is busy; will retry in " - "%d seconds...\n"), hostname, delay); + switch (error) + { + case EHOSTDOWN : + _cupsLangPrintf(stderr, + _("WARNING: Network printer \'%s\' may not exist " + "or is unavailable at this time.\n"), + hostname); + break; + + case EHOSTUNREACH : + _cupsLangPrintf(stderr, + _("WARNING: Network printer \'%s\' is " + "unreachable at this time.\n"), + hostname); + break; + + case ECONNREFUSED : + default : + _cupsLangPrintf(stderr, + _("WARNING: Network printer \'%s\' is busy.\n"), + hostname); + break; + } sleep(delay); @@ -852,10 +875,8 @@ lpd_queue(const char *hostname, /* I - Host to connect to */ } else { - fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(errno)); - _cupsLangPuts(stderr, - _("ERROR: Unable to connect to printer; will retry in 30 " - "seconds...\n")); + _cupsLangPrintf(stderr, _("ERROR: Network printer \'%s\' is not " + "responding.\n"), hostname); sleep(30); } } @@ -905,7 +926,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */ httpAddrFreeList(addrlist); close(fd); - _cupsLangPrintError(_("ERROR: unable to stat print file")); + perror("DEBUG: unable to stat print file"); return (CUPS_BACKEND_FAILED); } @@ -998,7 +1019,8 @@ lpd_queue(const char *hostname, /* I - Host to connect to */ if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1)) { status = errno; - _cupsLangPrintError(_("ERROR: Unable to write control file")); + perror("DEBUG: Unable to write control file"); + } else { @@ -1068,7 +1090,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */ if (lpd_write(fd, buffer, nbytes) < nbytes) { - _cupsLangPrintError(_("ERROR: Unable to send print file to printer")); + perror("DEBUG: Unable to send print file to printer"); break; } else @@ -1082,7 +1104,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */ status = errno; else if (lpd_write(fd, "", 1) < 1) { - _cupsLangPrintError(_("ERROR: Unable to send trailing nul to printer")); + perror("DEBUG: Unable to send trailing nul to printer"); status = errno; } else @@ -1145,7 +1167,7 @@ lpd_queue(const char *hostname, /* I - Host to connect to */ if (lpd_write(fd, control, strlen(control) + 1) < (strlen(control) + 1)) { status = errno; - _cupsLangPrintError(_("ERROR: Unable to write control file")); + perror("DEBUG: Unable to write control file"); } else { diff --git a/backend/pap.c b/backend/pap.c index 3c8d8571d..b57698fd2 100644 --- a/backend/pap.c +++ b/backend/pap.c @@ -299,7 +299,7 @@ static int listDevices(void) if (zip_getmyzone(ZIP_DEF_INTERFACE, &at_zone)) { - _cupsLangPrintError(_("ERROR: Unable to get default AppleTalk zone")); + perror("DEBUG: Unable to get default AppleTalk zone."); return -2; } @@ -319,7 +319,7 @@ static int listDevices(void) if ((numberFound = nbp_lookup(&entity, buf, MAX_PRINTERS, &retry)) < 0) { - _cupsLangPrintError(_("ERROR: Unable to lookup AppleTalk printers")); + perror("DEBUG: Unable to lookup AppleTalk printers."); return numberFound; } @@ -448,7 +448,7 @@ static int printFile(char* name, char* type, char* zone, int fdin, int fdout, in /* try to find our printer */ if ((err = nbp_make_entity(&entity, name, type, zone)) != noErr) { - _cupsLangPrintError(_("ERROR: Unable to make AppleTalk address")); + perror("DEBUG: Unable to make AppleTalk address."); goto Exit; } @@ -568,7 +568,7 @@ static int printFile(char* name, char* type, char* zone, int fdin, int fdout, in /* Start the tickle packets and set a timeout alarm */ if ((err = papSendRequest(gSockfd, &gSessionAddr, gConnID, AT_PAP_TYPE_TICKLE, 0, false, false)) < 0) { - _cupsLangPrintError(_("ERROR: Unable to send PAP tickle request")); + perror("DEBUG: Unable to send PAP tickle request."); goto Exit; } signal(SIGALRM, signalHandler); @@ -577,7 +577,7 @@ static int printFile(char* name, char* type, char* zone, int fdin, int fdout, in /* Prime the pump with an initial send-data packet */ if ((err = papSendRequest(gSockfd, &gSessionAddr, gConnID, AT_PAP_TYPE_SEND_DATA, 0xFF, true, true)) < 0) { - _cupsLangPrintError(_("ERROR: Unable to send initial PAP send data request")); + perror("DEBUG: Unable to send initial PAP send data request."); goto Exit; } @@ -626,7 +626,7 @@ static int printFile(char* name, char* type, char* zone, int fdin, int fdout, in /* Wait here for something interesting to happen */ if ((err = select(maxfdp1, &readSet, 0, 0, timeoutPtr)) < 0) { - _cupsLangPrintError(_("ERROR: select() failed")); + perror("DEBUG: select() failed."); break; } @@ -634,7 +634,7 @@ static int printFile(char* name, char* type, char* zone, int fdin, int fdout, in { /* Time to send a status request */ if ((err = papSendRequest(gSockfd, &tuple.enu_addr, 0, AT_PAP_TYPE_SEND_STATUS, 0x01, false, false)) < 0) - _cupsLangPrintError(_("WARNING: Unable to send PAP status request")); + _cupsLangPrintError(_("WARNING: Unable to send PAP status request")); if (gStatusInterval) nextStatusTime = time(NULL) + gStatusInterval; @@ -685,7 +685,7 @@ static int printFile(char* name, char* type, char* zone, int fdin, int fdout, in { if ((rc = atp_look(gSockfd)) < 0) { - _cupsLangPrintError(_("ERROR: Unable to look for PAP response")); + perror("DEBUG: Unable to look for PAP response."); break; } @@ -698,7 +698,7 @@ static int printFile(char* name, char* type, char* zone, int fdin, int fdout, in if ((err = atp_getresp(gSockfd, &tid, &resp)) < 0) { - _cupsLangPrintError(_("ERROR: Unable to get PAP response")); + perror("DEBUG: Unable to get PAP response."); break; } userdata = resp.userdata[0]; @@ -709,7 +709,7 @@ static int printFile(char* name, char* type, char* zone, int fdin, int fdout, in reqlen = sizeof(atpReqBuf); if ((err = atp_getreq(gSockfd, &src, atpReqBuf, &reqlen, &userdata, &xo, &tid, &bitmap, 0)) < 0) { - _cupsLangPrintError(_("ERROR: Unable to get PAP request")); + perror("DEBUG: Unable to get PAP response."); break; } } diff --git a/backend/runloop.c b/backend/runloop.c index 3c914ecf4..13f9c23da 100644 --- a/backend/runloop.c +++ b/backend/runloop.c @@ -355,7 +355,7 @@ backendRunLoop( if (paperout != 1 && update_state) { fputs("STATE: +media-empty-warning\n", stderr); - _cupsLangPuts(stderr, _("ERROR: Out of paper\n")); + _cupsLangPuts(stderr, _("DEBUG: Out of paper\n")); paperout = 1; } } diff --git a/backend/serial.c b/backend/serial.c index a77b76cba..4eb3700ff 100644 --- a/backend/serial.c +++ b/backend/serial.c @@ -3,7 +3,7 @@ * * Serial port backend for the Common UNIX Printing System (CUPS). * - * Copyright 2007-2009 by Apple Inc. + * Copyright 2007-2010 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -26,6 +26,7 @@ */ #include "backend-private.h" +#include <stdio.h> #ifdef __hpux # include <sys/modem.h> @@ -614,7 +615,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ if (errno != EAGAIN || errno != EINTR) { - _cupsLangPrintError(_("ERROR: Unable to read print data")); + perror("DEBUG: Unable to read print data"); tcsetattr(device_fd, TCSADRAIN, &origopts); @@ -690,7 +691,7 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ if (errno != EAGAIN && errno != EINTR && errno != ENOTTY) { - _cupsLangPrintError(_("ERROR: Unable to write print data")); + perror("DEBUG: Unable to write print data"); tcsetattr(device_fd, TCSADRAIN, &origopts); diff --git a/backend/socket.c b/backend/socket.c index 53f8dc0b5..84e5fe5f6 100644 --- a/backend/socket.c +++ b/backend/socket.c @@ -302,18 +302,40 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ return (CUPS_BACKEND_FAILED); } + fprintf(stderr, "DEBUG: Connection error: %s\n", strerror(error)); + if (error == ECONNREFUSED || error == EHOSTDOWN || error == EHOSTUNREACH) { if (contimeout && (time(NULL) - start_time) > contimeout) { - _cupsLangPuts(stderr, _("ERROR: Printer not responding\n")); + _cupsLangPuts(stderr, _("ERROR: The printer is not responding.\n")); return (CUPS_BACKEND_FAILED); } - _cupsLangPrintf(stderr, - _("WARNING: Network host \'%s\' is busy; will retry in " - "%d seconds...\n"), hostname, delay); + switch (error) + { + case EHOSTDOWN : + _cupsLangPrintf(stderr, + _("WARNING: Network printer \'%s\' may not exist " + "or is unavailable at this time.\n"), + hostname); + break; + + case EHOSTUNREACH : + _cupsLangPrintf(stderr, + _("WARNING: Network printer \'%s\' is " + "unreachable at this time.\n"), + hostname); + break; + + case ECONNREFUSED : + default : + _cupsLangPrintf(stderr, + _("WARNING: Network printer \'%s\' is busy.\n"), + hostname); + break; + } sleep(delay); @@ -322,11 +344,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ } else { - _cupsLangPrintf(stderr, "DEBUG: Connection error: %s\n", - strerror(errno)); - _cupsLangPuts(stderr, - _("ERROR: Unable to connect to printer; will retry in 30 " - "seconds...\n")); + _cupsLangPrintf(stderr, _("ERROR: Network printer \'%s\' is not " + "responding.\n"), hostname); sleep(30); } } diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index 43fd770da..f94059984 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -112,12 +112,6 @@ extern char **environ; #define DEBUG_WRITES 0 -/* - * WAIT_EOF_DELAY is number of seconds we'll wait for responses from - * the printer after we've finished sending all the data - */ -#define WAIT_EOF_DELAY 7 -#define WAIT_SIDE_DELAY 3 #define DEFAULT_TIMEOUT 5000L #define USB_INTERFACE_KIND CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID190) @@ -247,11 +241,6 @@ typedef struct globals_s Boolean wait_eof; int drain_output; /* Drain all pending output */ int bidi_flag; /* 0=unidirectional, 1=bidirectional */ - - pthread_mutex_t sidechannel_thread_mutex; - pthread_cond_t sidechannel_thread_cond; - int sidechannel_thread_stop; - int sidechannel_thread_done; } globals_t; @@ -344,7 +333,6 @@ print_device(const char *uri, /* I - Device URI */ UInt32 bytes; /* Bytes written */ struct timeval *timeout, /* Timeout pointer */ stimeout; /* Timeout for select() */ - struct timespec cond_timeout; /* pthread condition timeout */ /* @@ -373,7 +361,8 @@ print_device(const char *uri, /* I - Device URI */ if (!g.make || !g.model) { - _cupsLangPuts(stderr, _("ERROR: Fatal USB error\n")); + fprintf(stderr, "DEBUG: Fatal USB error.\n"); + _cupsLangPuts(stderr, _("ERROR: There was an unrecoverable USB error.\n")); if (!g.make) fputs("DEBUG: USB make string is NULL\n", stderr); @@ -431,7 +420,7 @@ print_device(const char *uri, /* I - Device URI */ strlcpy(print_buffer, "USB class driver", sizeof(print_buffer)); fputs("STATE: +apple-missing-usbclassdriver-error\n", stderr); - _cupsLangPuts(stderr, _("ERROR: Fatal USB error\n")); + _cupsLangPuts(stderr, _("ERROR: There was an unrecoverable USB error.\n")); fprintf(stderr, "DEBUG: Could not load %s\n", print_buffer); if (driverBundlePath) @@ -488,15 +477,10 @@ print_device(const char *uri, /* I - Device URI */ if (have_sidechannel) { - g.sidechannel_thread_stop = 0; - g.sidechannel_thread_done = 0; - - pthread_cond_init(&g.sidechannel_thread_cond, NULL); - pthread_mutex_init(&g.sidechannel_thread_mutex, NULL); - if (pthread_create(&sidechannel_thread_id, NULL, sidechannel_thread, NULL)) { - _cupsLangPuts(stderr, _("ERROR: Fatal USB error\n")); + fprintf(stderr, "DEBUG: Fatal USB error.\n"); + _cupsLangPuts(stderr, _("ERROR: There was an unrecoverable USB error.\n")); fputs("DEBUG: Couldn't create side-channel thread\n", stderr); registry_close(); return (CUPS_BACKEND_STOP); @@ -515,7 +499,8 @@ print_device(const char *uri, /* I - Device URI */ if (pthread_create(&read_thread_id, NULL, read_thread, NULL)) { - _cupsLangPuts(stderr, _("ERROR: Fatal USB error\n")); + fprintf(stderr, "DEBUG: Fatal USB error.\n"); + _cupsLangPuts(stderr, _("ERROR: There was an unrecoverable USB error.\n")); fputs("DEBUG: Couldn't create read thread\n", stderr); registry_close(); return (CUPS_BACKEND_STOP); @@ -601,7 +586,7 @@ print_device(const char *uri, /* I - Device URI */ } else if (errno != EAGAIN && errno != EINTR) { - _cupsLangPuts(stderr, _("ERROR: Unable to read print data\n")); + _cupsLangPuts(stderr, _("ERROR: Unable to read print data.\n")); perror("DEBUG: select"); registry_close(); return (CUPS_BACKEND_FAILED); @@ -644,7 +629,7 @@ print_device(const char *uri, /* I - Device URI */ if (errno != EAGAIN && errno != EINTR) { - _cupsLangPuts(stderr, _("ERROR: Unable to read print data\n")); + _cupsLangPuts(stderr, _("ERROR: Unable to read print data.\n")); perror("DEBUG: read"); registry_close(); return (CUPS_BACKEND_FAILED); @@ -720,8 +705,7 @@ print_device(const char *uri, /* I - Device URI */ /* * Write error - bail if we don't see an error we can retry... */ - - _cupsLangPuts(stderr, _("ERROR: Unable to send print data\n")); + _cupsLangPuts(stderr, _("ERROR: Unable to send print data to printer.\n")); fprintf(stderr, "DEBUG: USB class driver WritePipe returned %x\n", iostatus); @@ -751,86 +735,6 @@ print_device(const char *uri, /* I - Device URI */ fprintf(stderr, "DEBUG: Sent %lld bytes...\n", (off_t)total_bytes); /* - * Wait for the side channel thread to exit... - */ - - if (have_sidechannel) - { - close(CUPS_SC_FD); - pthread_mutex_lock(&g.readwrite_lock_mutex); - g.readwrite_lock = 0; - pthread_cond_signal(&g.readwrite_lock_cond); - pthread_mutex_unlock(&g.readwrite_lock_mutex); - - g.sidechannel_thread_stop = 1; - pthread_mutex_lock(&g.sidechannel_thread_mutex); - if (!g.sidechannel_thread_done) - { - /* - * Wait for the side-channel thread to exit... - */ - - cond_timeout.tv_sec = time(NULL) + WAIT_SIDE_DELAY; - cond_timeout.tv_nsec = 0; - if (pthread_cond_timedwait(&g.sidechannel_thread_cond, - &g.sidechannel_thread_mutex, - &cond_timeout) != 0) - { - /* - * Force the side-channel thread to exit... - */ - - pthread_kill(sidechannel_thread_id, SIGTERM); - } - } - pthread_mutex_unlock(&g.sidechannel_thread_mutex); - - pthread_join(sidechannel_thread_id, NULL); - - pthread_cond_destroy(&g.sidechannel_thread_cond); - pthread_mutex_destroy(&g.sidechannel_thread_mutex); - } - - pthread_cond_destroy(&g.readwrite_lock_cond); - pthread_mutex_destroy(&g.readwrite_lock_mutex); - - /* - * Signal the read thread to stop... - */ - - g.read_thread_stop = 1; - - /* - * Give the read thread WAIT_EOF_DELAY seconds to complete all the data. If - * we are not signaled in that time then force the thread to exit. - */ - - pthread_mutex_lock(&g.read_thread_mutex); - - if (!g.read_thread_done) - { - cond_timeout.tv_sec = time(NULL) + WAIT_EOF_DELAY; - cond_timeout.tv_nsec = 0; - - if (pthread_cond_timedwait(&g.read_thread_cond, &g.read_thread_mutex, - &cond_timeout) != 0) - { - /* - * Force the read thread to exit... - */ - - g.wait_eof = 0; - pthread_kill(read_thread_id, SIGTERM); - } - } - pthread_mutex_unlock(&g.read_thread_mutex); - - pthread_join(read_thread_id, NULL); /* wait for the read thread to return */ - - pthread_cond_destroy(&g.read_thread_cond); - pthread_mutex_destroy(&g.read_thread_mutex); - - /* * Close the connection and input file and general clean up... */ @@ -1038,12 +942,7 @@ sidechannel_thread(void *reference) break; } } - while (!g.sidechannel_thread_stop); - - pthread_mutex_lock(&g.sidechannel_thread_mutex); - g.sidechannel_thread_done = 1; - pthread_cond_signal(&g.sidechannel_thread_cond); - pthread_mutex_unlock(&g.sidechannel_thread_mutex); + while (1); return NULL; } diff --git a/backend/usb.c b/backend/usb.c index b33f731b9..74cd6e580 100644 --- a/backend/usb.c +++ b/backend/usb.c @@ -197,8 +197,8 @@ main(int argc, /* I - Number of command-line arguments (6 or 7) */ resource, sizeof(resource)) < HTTP_URI_OK) { _cupsLangPuts(stderr, - _("ERROR: No device URI found in argv[0] or in DEVICE_URI " - "environment variable\n")); + _("ERROR: No device URI found in argv[0] or in DEVICE_URI " + "environment variable\n")); return (1); } diff --git a/cgi-bin/admin.c b/cgi-bin/admin.c index d8527cdb8..b890c8b99 100644 --- a/cgi-bin/admin.c +++ b/cgi-bin/admin.c @@ -951,8 +951,6 @@ do_am_printer(http_t *http, /* I - HTTP connection */ if (!cgiGetVariable("CURRENT_MAKE")) cgiSetVariable("CURRENT_MAKE", make); - cgiSetVariable("PPD_MAKE", make); - if (!cgiGetVariable("CURRENT_MAKE_AND_MODEL")) cgiSetVariable("CURRENT_MAKE_AND_MODEL", uriptr); @@ -1218,8 +1216,8 @@ do_am_printer(http_t *http, /* I - HTTP connection */ ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, "ipp://localhost/printers/"); - if ((var = cgiGetVariable("CURRENT_MAKE")) == NULL) - var = cgiGetVariable("PPD_MAKE"); + if ((var = cgiGetVariable("PPD_MAKE")) == NULL) + var = cgiGetVariable("CURRENT_MAKE"); if (var && !cgiGetVariable("SELECT_MAKE")) { const char *make_model; /* Make and model */ diff --git a/cgi-bin/ipp-var.c b/cgi-bin/ipp-var.c index 4c1eb3b95..fe9bc52db 100644 --- a/cgi-bin/ipp-var.c +++ b/cgi-bin/ipp-var.c @@ -285,10 +285,14 @@ cgiMoveJobs(http_t *http, /* I - Connection to server */ /* - * See who is logged in... + * Make sure we have a username... */ - user = getenv("REMOTE_USER"); + if ((user = getenv("REMOTE_USER")) == NULL) + { + puts("Status: 401\n"); + exit(0); + } /* * See if the user has already selected a new destination... diff --git a/cgi-bin/var.c b/cgi-bin/var.c index 0ec9800cb..9a37b35e7 100644 --- a/cgi-bin/var.c +++ b/cgi-bin/var.c @@ -1111,6 +1111,9 @@ cgi_initialize_string(const char *data) /* I - Form data string */ * Read the hex code... */ + if (!isxdigit(data[1] & 255) || !isxdigit(data[2] & 255)) + return (0); + if (s < (value + sizeof(value) - 1)) { data ++; @@ -1232,7 +1235,7 @@ cgi_set_sid(void) _cupsMD5Append(&md5, (unsigned char *)buffer, (int)strlen(buffer)); _cupsMD5Finish(&md5, sum); - cgiSetCookie(CUPS_SID, httpMD5String(sum, sid), "/", server_name, 0, 0); + cgiSetCookie(CUPS_SID, httpMD5String(sum, sid), "/", NULL, 0, 0); return (cupsGetOption(CUPS_SID, num_cookies, cookies)); } diff --git a/conf/cupsd.conf.in b/conf/cupsd.conf.in index e51c430c1..a7143b7dc 100644 --- a/conf/cupsd.conf.in +++ b/conf/cupsd.conf.in @@ -46,6 +46,10 @@ DefaultAuthType Basic # Set the default printer/job policies... <Policy default> # Job-related operations must be done by the owner or an administrator... + <Limit Create-Job Print-Job Print-URI Validate-Job> + Order deny,allow + </Limit> + <Limit Send-Document Send-URI Hold-Job Release-Job Restart-Job Purge-Jobs Set-Job-Attributes Create-Job-Subscription Renew-Subscription Cancel-Subscription Get-Notifications Reprocess-Job Cancel-Current-Job Suspend-Current-Job Resume-Job Cancel-My-Jobs Close-Job CUPS-Move-Job CUPS-Get-Document> Require user @OWNER @SYSTEM Order deny,allow @@ -79,7 +83,7 @@ DefaultAuthType Basic # Set the authenticated printer/job policies... <Policy authenticated> # Job-related operations must be done by the owner or an administrator... - <Limit Create-Job Print-Job Print-URI> + <Limit Create-Job Print-Job Print-URI Validate-Job> AuthType Default Order deny,allow </Limit> diff --git a/config-scripts/cups-common.m4 b/config-scripts/cups-common.m4 index c73aa3b48..db0c6c0c9 100644 --- a/config-scripts/cups-common.m4 +++ b/config-scripts/cups-common.m4 @@ -183,6 +183,14 @@ AC_TRY_COMPILE([#include <time.h>],[struct tm t; AC_DEFINE(HAVE_TM_GMTOFF), AC_MSG_RESULT(no)) +dnl See if the stat structure has the st_gen member... +AC_MSG_CHECKING(for st_gen member in stat structure) +AC_TRY_COMPILE([#include <sys/stat.h>],[struct stat t; + int o = t.st_gen;], + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_ST_GEN), + AC_MSG_RESULT(no)) + dnl See if we have the removefile(3) function for securely removing files AC_CHECK_FUNCS(removefile) diff --git a/config-scripts/cups-sharedlibs.m4 b/config-scripts/cups-sharedlibs.m4 index 4363bfce2..2e255b763 100644 --- a/config-scripts/cups-sharedlibs.m4 +++ b/config-scripts/cups-sharedlibs.m4 @@ -165,16 +165,31 @@ AC_SUBST(LIBCUPSSTATIC) if test x$enable_shared = xno; then LINKCUPS="../cups/lib$cupsbase.a" LINKCUPSIMAGE="../filter/libcupsimage.a" + + EXTLINKCUPS="-lcups" + EXTLINKCUPSDRIVER="-lcupsdriver" + EXTLINKCUPSIMAGE="-lcupsimage" else if test $uname = AIX; then LINKCUPS="-l${cupsbase}_s" LINKCUPSIMAGE="-lcupsimage_s" + + EXTLINKCUPS="-lcups_s" + EXTLINKCUPSDRIVER="-lcupsdriver_s" + EXTLINKCUPSIMAGE="-lcupsimage_s" else LINKCUPS="-l${cupsbase}" LINKCUPSIMAGE="-lcupsimage" + + EXTLINKCUPS="-lcups" + EXTLINKCUPSDRIVER="-lcupsdriver" + EXTLINKCUPSIMAGE="-lcupsimage" fi fi +AC_SUBST(EXTLINKCUPS) +AC_SUBST(EXTLINKCUPSDRIVER) +AC_SUBST(EXTLINKCUPSIMAGE) AC_SUBST(LINKCUPS) AC_SUBST(LINKCUPSIMAGE) diff --git a/config-scripts/cups-ssl.m4 b/config-scripts/cups-ssl.m4 index f8c869755..c605121c0 100644 --- a/config-scripts/cups-ssl.m4 +++ b/config-scripts/cups-ssl.m4 @@ -38,6 +38,8 @@ if test x$enable_ssl != xno; then AC_DEFINE(HAVE_CDSASSL) dnl Check for the various security headers... + AC_CHECK_HEADER(Security/SecItemPriv.h, + AC_DEFINE(HAVE_SECITEMPRIV_H)) AC_CHECK_HEADER(Security/SecPolicy.h, AC_DEFINE(HAVE_SECPOLICY_H)) AC_CHECK_HEADER(Security/SecPolicyPriv.h, @@ -54,6 +56,15 @@ if test x$enable_ssl != xno; then AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) + fi + + dnl Check for SecPolicyCreateSSL... + AC_MSG_CHECKING(for SecPolicyCreateSSL) + if test $uversion -ge 100; then + AC_DEFINE(HAVE_SECPOLICYCREATESSL) + AC_MSG_RESULT(yes) + else + AC_MSG_RESULT(no) fi]) fi fi @@ -63,24 +74,32 @@ if test x$enable_ssl != xno; then AC_PATH_PROG(LIBGNUTLSCONFIG,libgnutls-config) AC_PATH_PROG(LIBGCRYPTCONFIG,libgcrypt-config) if $PKGCONFIG --exists gnutls; then - have_ssl=1 - SSLLIBS=`$PKGCONFIG --libs gnutls` - SSLFLAGS=`$PKGCONFIG --cflags gnutls` - AC_DEFINE(HAVE_SSL) - AC_DEFINE(HAVE_GNUTLS) - elif "x$LIBGNUTLSCONFIG" != x; then - have_ssl=1 - SSLLIBS=`$LIBGNUTLSCONFIG --libs` - SSLFLAGS=`$LIBGNUTLSCONFIG --cflags` - AC_DEFINE(HAVE_SSL) - AC_DEFINE(HAVE_GNUTLS) + if test "x$have_pthread" = xyes; then + AC_MSG_WARN([The current version of GNU TLS cannot be made thread-safe.]) + else + have_ssl=1 + SSLLIBS=`$PKGCONFIG --libs gnutls` + SSLFLAGS=`$PKGCONFIG --cflags gnutls` + AC_DEFINE(HAVE_SSL) + AC_DEFINE(HAVE_GNUTLS) + fi + elif test "x$LIBGNUTLSCONFIG" != x; then + if test "x$have_pthread" = xyes; then + AC_MSG_WARN([The current version of GNU TLS cannot be made thread-safe.]) + else + have_ssl=1 + SSLLIBS=`$LIBGNUTLSCONFIG --libs` + SSLFLAGS=`$LIBGNUTLSCONFIG --cflags` + AC_DEFINE(HAVE_SSL) + AC_DEFINE(HAVE_GNUTLS) + fi fi if test $have_ssl = 1; then if $PKGCONFIG --exists gcrypt; then SSLLIBS="$SSLLIBS `$PKGCONFIG --libs gcrypt`" SSLFLAGS="$SSLFLAGS `$PKGCONFIG --cflags gcrypt`" - elif "x$LIBGCRYPTCONFIG" != x; then + elif test "x$LIBGCRYPTCONFIG" != x; then SSLLIBS="$SSLLIBS `$LIBGCRYPTCONFIG --libs`" SSLFLAGS="$SSLFLAGS `$LIBGCRYPTCONFIG --cflags`" fi diff --git a/config.h.in b/config.h.in index 5c986e3cf..af0813dc6 100644 --- a/config.h.in +++ b/config.h.in @@ -289,6 +289,7 @@ */ #undef HAVE_AUTHORIZATION_H +#undef HAVE_SECITEMPRIV_H #undef HAVE_SECPOLICY_H #undef HAVE_SECPOLICYPRIV_H #undef HAVE_SECBASEPRIV_H @@ -303,6 +304,13 @@ /* + * Do we have the SecPolicyCreateSSL function? + */ + +#undef HAVE_SECPOLICYCREATESSL + + +/* * Do we have the SLP library? */ @@ -343,6 +351,13 @@ /* + * Does the "stat" structure contain the "st_gen" member? + */ + +#undef HAVE_ST_GEN + + +/* * Does the "tm" structure contain the "tm_gmtoff" member? */ diff --git a/configure.in b/configure.in index 34198e412..11b3e49cc 100644 --- a/configure.in +++ b/configure.in @@ -31,9 +31,9 @@ sinclude(config-scripts/cups-poll.m4) sinclude(config-scripts/cups-slp.m4) sinclude(config-scripts/cups-gssapi.m4) sinclude(config-scripts/cups-ldap.m4) +sinclude(config-scripts/cups-threads.m4) sinclude(config-scripts/cups-ssl.m4) sinclude(config-scripts/cups-pam.m4) -sinclude(config-scripts/cups-threads.m4) sinclude(config-scripts/cups-largefile.m4) sinclude(config-scripts/cups-dnssd.m4) sinclude(config-scripts/cups-launchd.m4) @@ -80,7 +80,6 @@ AC_OUTPUT(Makedefs man/cupsaddsmb.man man/cupsd.conf.man man/cupsd.man - man/drv.man man/lpoptions.man scheduler/cups-lpd.xinetd scheduler/cups.sh diff --git a/cups-config.in b/cups-config.in index 8a3db3375..f59abe0bb 100755 --- a/cups-config.in +++ b/cups-config.in @@ -4,7 +4,7 @@ # # CUPS configuration utility. # -# Copyright 2007-2008 by Apple Inc. +# Copyright 2007-2010 by Apple Inc. # Copyright 2001-2006 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -15,7 +15,7 @@ # VERSION="@CUPS_VERSION@" -APIVERSION="1.4" +APIVERSION="1.5" BUILD="@CUPS_BUILD@" prefix=@prefix@ @@ -113,12 +113,12 @@ while test $# -gt 0; do ;; --libs) if test $static = no; then - libs="-lcups $LIBS"; + libs="@EXTLINKCUPS@ $LIBS"; if test $image = yes; then - libs="-lcupsimage $libs" + libs="@EXTLINKCUPSIMAGE@ $libs" fi if test $driver = yes; then - libs="-lcupsdriver $libs" + libs="@EXTLINKCUPSDRIVER@ $libs" fi else libs="$libdir/libcups.a $LIBS"; diff --git a/cups/dest.c b/cups/dest.c index 191ec7b84..98cba04d3 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -1211,7 +1211,8 @@ appleSetDefault(const char *name) /* I - Default printer/class name */ CFArrayRemoveValueAtIndex(newlocations, locindex); } else - newlocations = CFArrayCreateMutable(kCFAllocatorDefault, 0, NULL); + newlocations = CFArrayCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeArrayCallBacks); newlocation = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, diff --git a/cups/file.c b/cups/file.c index 0259716db..68fb11892 100644 --- a/cups/file.c +++ b/cups/file.c @@ -59,6 +59,8 @@ */ #include "file-private.h" +#include <sys/stat.h> +#include <sys/types.h> /* @@ -69,6 +71,7 @@ static ssize_t cups_compress(cups_file_t *fp, const char *buf, size_t bytes); #endif /* HAVE_LIBZ */ static ssize_t cups_fill(cups_file_t *fp); +static int cups_open(const char *filename, int mode); static ssize_t cups_read(cups_file_t *fp, char *buf, size_t bytes); static ssize_t cups_write(cups_file_t *fp, const char *buf, size_t bytes); @@ -827,7 +830,8 @@ cupsFileOpen(const char *filename, /* I - Name of file */ switch (*mode) { case 'a' : /* Append file */ - fd = open(filename, O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY, 0666); + fd = cups_open(filename, + O_RDWR | O_CREAT | O_APPEND | O_LARGEFILE | O_BINARY); break; case 'r' : /* Read file */ @@ -835,7 +839,21 @@ cupsFileOpen(const char *filename, /* I - Name of file */ break; case 'w' : /* Write file */ - fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT | O_LARGEFILE | O_BINARY, 0666); + fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY); + if (fd < 0 && errno == ENOENT) + { + fd = cups_open(filename, + O_WRONLY | O_CREAT | O_EXCL | O_LARGEFILE | O_BINARY); + if (fd < 0 && errno == EEXIST) + fd = cups_open(filename, O_WRONLY | O_LARGEFILE | O_BINARY); + } + + if (fd >= 0) +#ifdef WIN32 + _chsize(fd, 0); +#else + ftruncate(fd, 0); +#endif /* WIN32 */ break; case 's' : /* Read/write socket */ @@ -2209,6 +2227,94 @@ cups_fill(cups_file_t *fp) /* I - CUPS file */ /* + * 'cups_open()' - Safely open a file for writing. + * + * We don't allow appending to directories or files that are hard-linked or + * symlinked. + */ + +static int /* O - File descriptor or -1 otherwise */ +cups_open(const char *filename, /* I - Filename */ + int mode) /* I - Open mode */ +{ + int fd; /* File descriptor */ + struct stat fileinfo; /* File information */ +#ifndef WIN32 + struct stat linkinfo; /* Link information */ +#endif /* !WIN32 */ + + + /* + * Open the file... + */ + + if ((fd = open(filename, mode, 0666)) < 0) + return (-1); + + /* + * Then verify that the file descriptor doesn't point to a directory or hard- + * linked file. + */ + + if (fstat(fd, &fileinfo)) + { + close(fd); + return (-1); + } + + if (fileinfo.st_nlink != 1) + { + close(fd); + errno = EPERM; + return (-1); + } + +#ifdef WIN32 + if (fileinfo.st_mode & _S_IFDIR) +#else + if (S_ISDIR(fileinfo.st_mode)) +#endif /* WIN32 */ + { + close(fd); + errno = EISDIR; + return (-1); + } + +#ifndef WIN32 + /* + * Then use lstat to determine whether the filename is a symlink... + */ + + if (lstat(filename, &linkinfo)) + { + close(fd); + return (-1); + } + + if (S_ISLNK(linkinfo.st_mode) || + fileinfo.st_dev != linkinfo.st_dev || + fileinfo.st_ino != linkinfo.st_ino || +#ifdef HAVE_ST_GEN + fileinfo.st_gen != linkinfo.st_gen || +#endif /* HAVE_ST_GEN */ + fileinfo.st_nlink != linkinfo.st_nlink || + fileinfo.st_mode != linkinfo.st_mode) + { + /* + * Yes, don't allow! + */ + + close(fd); + errno = EPERM; + return (-1); + } +#endif /* !WIN32 */ + + return (fd); +} + + +/* * 'cups_read()' - Read from a file descriptor. */ diff --git a/cups/globals.c b/cups/globals.c index 04afcab2c..3d678d427 100644 --- a/cups/globals.c +++ b/cups/globals.c @@ -320,7 +320,9 @@ cups_globals_free(_cups_globals_t *cg) /* I - Pointer to global data */ cupsFileClose(cg->stdio_files[1]); cupsFileClose(cg->stdio_files[2]); +# ifndef CUPS_LITE cupsFreeOptions(cg->cupsd_num_settings, cg->cupsd_settings); +# endif /* !CUPS_LITE */ free(cg); } diff --git a/cups/http-support.c b/cups/http-support.c index f1e4893d3..5c1dce5d8 100644 --- a/cups/http-support.c +++ b/cups/http-support.c @@ -1353,6 +1353,9 @@ _httpResolveURI( if (strstr(hostname, "._tcp")) { #ifdef HAVE_DNSSD +# ifdef WIN32 +# pragma comment(lib, "dnssd.lib") +# endif /* WIN32 */ DNSServiceRef ref, /* DNS-SD master service reference */ domainref, /* DNS-SD service reference for domain */ localref; /* DNS-SD service reference for .local */ diff --git a/cups/http.c b/cups/http.c index a83fc20cc..6df51abc6 100644 --- a/cups/http.c +++ b/cups/http.c @@ -1240,7 +1240,7 @@ httpInitialize(void) } #ifdef WIN32 - WSAStartup(MAKEWORD(1,1), &winsockdata); + WSAStartup(MAKEWORD(2,2), &winsockdata); #elif !defined(SO_NOSIGPIPE) /* diff --git a/cups/http.h b/cups/http.h index 08067c456..85a2c8b43 100644 --- a/cups/http.h +++ b/cups/http.h @@ -250,7 +250,7 @@ typedef enum http_status_e /**** HTTP status codes ****/ HTTP_GATEWAY_TIMEOUT, /* Gateway connection timed out */ HTTP_NOT_SUPPORTED, /* HTTP version not supported */ - HTTP_AUTHORIZATION_CANCELED = 1000 /* User cancelled authorization */ + HTTP_AUTHORIZATION_CANCELED = 1000 /* User canceled authorization */ } http_status_t; diff --git a/cups/ipp.h b/cups/ipp.h index 12126e260..4f3dd5eec 100644 --- a/cups/ipp.h +++ b/cups/ipp.h @@ -414,8 +414,8 @@ struct ipp_s /**** IPP Request/Response/Notification ****/ /**** New in CUPS 1.2 ****/ ipp_attribute_t *prev; /* Previous attribute (for read) @since CUPS 1.2/Mac OS X 10.5@ */ -/**** New in CUPS 1.5 ****/ - int use; /* Use count */ +/**** New in CUPS 1.4.4 ****/ + int use; /* Use count @since CUPS 1.4.4/Mac OS X 10.6.?@ */ }; diff --git a/cups/language.c b/cups/language.c index 8ce4bc7d1..38f8e5ae0 100644 --- a/cups/language.c +++ b/cups/language.c @@ -262,9 +262,17 @@ _cupsEncodingName( { if (encoding < 0 || encoding >= (sizeof(lang_encodings) / sizeof(const char *))) + { + DEBUG_printf(("1_cupsEncodingName(encoding=%d) = out of range (\"%s\")", + encoding, lang_encodings[0])); return (lang_encodings[0]); + } else + { + DEBUG_printf(("1_cupsEncodingName(encoding=%d) = \"%s\"", + encoding, lang_encodings[encoding])); return (lang_encodings[encoding]); + } } diff --git a/cups/mark.c b/cups/mark.c index e75544b72..648e8f28b 100644 --- a/cups/mark.c +++ b/cups/mark.c @@ -72,7 +72,7 @@ cupsMarkOptions( int num_options, /* I - Number of options */ cups_option_t *options) /* I - Options */ { - int i, j, k; /* Looping vars */ + int i, j; /* Looping vars */ char *ptr, /* Pointer into string */ s[255]; /* Temporary string */ const char *val, /* Pointer into value */ @@ -80,33 +80,7 @@ cupsMarkOptions( *page_size, /* PageSize option */ *ppd_keyword; /* PPD keyword */ cups_option_t *optptr; /* Current option */ - ppd_option_t *option; /* PPD option */ ppd_attr_t *attr; /* PPD attribute */ - static const char * const duplex_options[] = - { /* Duplex option names */ - "Duplex", /* Adobe */ - "EFDuplex", /* EFI */ - "EFDuplexing", /* EFI */ - "KD03Duplex", /* Kodak */ - "JCLDuplex" /* Samsung */ - }; - static const char * const duplex_one[] = - { /* one-sided names */ - "None", - "False" - }; - static const char * const duplex_two_long[] = - { /* two-sided-long-edge names */ - "DuplexNoTumble", /* Adobe */ - "LongEdge", /* EFI */ - "Top" /* EFI */ - }; - static const char * const duplex_two_short[] = - { /* two-sided-long-edge names */ - "DuplexTumble", /* Adobe */ - "ShortEdge", /* EFI */ - "Bottom" /* EFI */ - }; /* @@ -185,98 +159,11 @@ cupsMarkOptions( */ for (i = num_options, optptr = options; i > 0; i --, optptr ++) - if (!strcasecmp(optptr->name, "media")) + if (!strcasecmp(optptr->name, "media") || + !strcasecmp(optptr->name, "output-bin") || + !strcasecmp(optptr->name, "output-mode") || + !strcasecmp(optptr->name, "sides")) continue; - else if (!strcasecmp(optptr->name, "sides")) - { - for (j = 0; - j < (int)(sizeof(duplex_options) / sizeof(duplex_options[0])); - j ++) - if (cupsGetOption(duplex_options[j], num_options, options)) - break; - - if (j < (int)(sizeof(duplex_options) / sizeof(duplex_options[0]))) - { - /* - * Don't override the PPD option with the IPP attribute... - */ - - continue; - } - - if (!strcasecmp(optptr->value, "one-sided")) - { - /* - * Mark the appropriate duplex option for one-sided output... - */ - - for (j = 0; - j < (int)(sizeof(duplex_options) / sizeof(duplex_options[0])); - j ++) - if ((option = ppdFindOption(ppd, duplex_options[j])) != NULL) - break; - - if (j < (int)(sizeof(duplex_options) / sizeof(duplex_options[0]))) - { - for (k = 0; - k < (int)(sizeof(duplex_one) / sizeof(duplex_one[0])); - k ++) - if (ppdFindChoice(option, duplex_one[k])) - { - ppd_mark_option(ppd, duplex_options[j], duplex_one[k]); - break; - } - } - } - else if (!strcasecmp(optptr->value, "two-sided-long-edge")) - { - /* - * Mark the appropriate duplex option for two-sided-long-edge output... - */ - - for (j = 0; - j < (int)(sizeof(duplex_options) / sizeof(duplex_options[0])); - j ++) - if ((option = ppdFindOption(ppd, duplex_options[j])) != NULL) - break; - - if (j < (int)(sizeof(duplex_options) / sizeof(duplex_options[0]))) - { - for (k = 0; - k < (int)(sizeof(duplex_two_long) / sizeof(duplex_two_long[0])); - k ++) - if (ppdFindChoice(option, duplex_two_long[k])) - { - ppd_mark_option(ppd, duplex_options[j], duplex_two_long[k]); - break; - } - } - } - else if (!strcasecmp(optptr->value, "two-sided-short-edge")) - { - /* - * Mark the appropriate duplex option for two-sided-short-edge output... - */ - - for (j = 0; - j < (int)(sizeof(duplex_options) / sizeof(duplex_options[0])); - j ++) - if ((option = ppdFindOption(ppd, duplex_options[j])) != NULL) - break; - - if (j < (int)(sizeof(duplex_options) / sizeof(duplex_options[0]))) - { - for (k = 0; - k < (int)(sizeof(duplex_two_short) / sizeof(duplex_two_short[0])); - k ++) - if (ppdFindChoice(option, duplex_two_short[k])) - { - ppd_mark_option(ppd, duplex_options[j], duplex_two_short[k]); - break; - } - } - } - } else if (!strcasecmp(optptr->name, "resolution") || !strcasecmp(optptr->name, "printer-resolution")) { @@ -288,13 +175,6 @@ cupsMarkOptions( ppd_mark_option(ppd, "CNRes_PGP", optptr->value); /* Canon */ } - else if (!strcasecmp(optptr->name, "output-bin")) - { - if (!cupsGetOption("OutputBin", num_options, options) && - (ppd_keyword = _pwgGetOutputBin((_pwg_t *)ppd->pwg, - optptr->value)) != NULL) - ppd_mark_option(ppd, "OutputBin", ppd_keyword); - } else if (!strcasecmp(optptr->name, "multiple-document-handling")) { if (!cupsGetOption("Collate", num_options, options) && @@ -668,6 +548,7 @@ ppdNextOption(ppd_file_t *ppd) /* I - PPD file */ * This function looks for strings of the form: * * *option choice ... *optionN choiceN + * property value ... propertyN valueN * * It stops when it finds a string that doesn't match this format. */ @@ -676,10 +557,11 @@ int /* O - Number of options */ _ppdParseOptions( const char *s, /* I - String to parse */ int num_options, /* I - Number of options */ - cups_option_t **options) /* IO - Options */ + cups_option_t **options, /* IO - Options */ + _ppd_parse_t which) /* I - What to parse */ { - char option[PPD_MAX_NAME], /* Current option */ - choice[PPD_MAX_NAME], /* Current choice */ + char option[PPD_MAX_NAME + 1], /* Current option/property */ + choice[PPD_MAX_NAME], /* Current choice/value */ *ptr; /* Pointer into option or choice */ @@ -687,8 +569,8 @@ _ppdParseOptions( return (num_options); /* - * Read all of the "*Option Choice" pairs from the string, marking PPD - * options as we go... + * Read all of the "*Option Choice" and "property value" pairs from the + * string, add them to an options array as we go... */ while (*s) @@ -700,19 +582,15 @@ _ppdParseOptions( while (isspace(*s & 255)) s ++; - if (*s != '*') - break; - /* - * Get the option name... + * Get the option/property name... */ - s ++; ptr = option; while (*s && !isspace(*s & 255) && ptr < (option + sizeof(option) - 1)) *ptr++ = *s++; - if (ptr == s) + if (ptr == s || !isspace(*s & 255)) break; *ptr = '\0'; @@ -731,13 +609,19 @@ _ppdParseOptions( while (*s && !isspace(*s & 255) && ptr < (choice + sizeof(choice) - 1)) *ptr++ = *s++; + if (!isspace(*s & 255) && *s) + break; + *ptr = '\0'; /* * Add it to the options array... */ - num_options = cupsAddOption(option, choice, num_options, options); + if (option[0] == '*' && which != _PPD_PARSE_PROPERTIES) + num_options = cupsAddOption(option + 1, choice, num_options, options); + else if (option[0] != '*' && which != _PPD_PARSE_OPTIONS) + num_options = cupsAddOption(option, choice, num_options, options); } return (num_options); @@ -806,7 +690,7 @@ ppd_mark_choices(ppd_file_t *ppd, /* I - PPD file */ return; options = NULL; - num_options = _ppdParseOptions(s, 0, &options); + num_options = _ppdParseOptions(s, 0, &options, 0); for (i = num_options, option = options; i > 0; i --, option ++) ppd_mark_option(ppd, option->name, option->value); diff --git a/cups/ppd-private.h b/cups/ppd-private.h index 2867fc83e..3b2d3aa1a 100644 --- a/cups/ppd-private.h +++ b/cups/ppd-private.h @@ -31,6 +31,7 @@ * Include necessary headers... */ +# include <cups/cups.h> # include <cups/ppd.h> # include "pwg-private.h" @@ -45,9 +46,16 @@ extern "C" { /* - * Structures... + * Types and structures... */ +typedef enum _ppd_parse_e /**** Selector for _ppdParseOptions ****/ +{ + _PPD_PARSE_OPTIONS, /* Parse only the options */ + _PPD_PARSE_PROPERTIES, /* Parse only the properties */ + _PPD_PARSE_ALL /* Parse everything */ +} _ppd_parse_t; + typedef struct _ppd_cups_uiconst_s /**** Constraint from cupsUIConstraints ****/ { ppd_option_t *option; /* Constrained option */ @@ -63,6 +71,49 @@ typedef struct _ppd_cups_uiconsts_s /**** cupsUIConstraints ****/ _ppd_cups_uiconst_t *constraints; /* Constraints */ } _ppd_cups_uiconsts_t; +typedef enum _pwg_output_mode_e /**** PWG output-mode indices ****/ +{ + _PWG_OUTPUT_MODE_MONOCHROME = 0, /* output-mode=monochrome */ + _PWG_OUTPUT_MODE_COLOR, /* output-mode=color */ + _PWG_OUTPUT_MODE_MAX +} _pwg_output_mode_t; + +typedef enum _pwg_print_quality_e /**** PWG print-quality indices ****/ +{ + _PWG_PRINT_QUALITY_DRAFT = 0, /* print-quality=3 */ + _PWG_PRINT_QUALITY_NORMAL, /* print-quality=4 */ + _PWG_PRINT_QUALITY_HIGH, /* print-quality=5 */ + _PWG_PRINT_QUALITY_MAX +} _pwg_print_quality_t; + +typedef struct _pwg_s /**** PWG-PPD conversion data ****/ +{ + int num_bins; /* Number of output bins */ + _pwg_map_t *bins; /* Output bins */ + int num_sizes; /* Number of media sizes */ + _pwg_size_t *sizes; /* Media sizes */ + int custom_max_width, /* Maximum custom width in 2540ths */ + custom_max_length, /* Maximum custom length in 2540ths */ + custom_min_width, /* Minimum custom width in 2540ths */ + custom_min_length; /* Minimum custom length in 2540ths */ + char *custom_max_keyword, /* Maximum custom size PWG keyword */ + *custom_min_keyword, /* Minimum custom size PWG keyword */ + custom_ppd_size[41]; /* Custom PPD size name */ + _pwg_size_t custom_size; /* Custom size record */ + int num_sources; /* Number of media sources */ + _pwg_map_t *sources; /* Media sources */ + int num_types; /* Number of media types */ + _pwg_map_t *types; /* Media types */ + int num_presets[_PWG_OUTPUT_MODE_MAX][_PWG_PRINT_QUALITY_MAX]; + /* Number of output-mode/print-quality options */ + cups_option_t *presets[_PWG_OUTPUT_MODE_MAX][_PWG_PRINT_QUALITY_MAX]; + /* output-mode/print-quality options */ + char *sides_option, /* PPD option for sides */ + *sides_1sided, /* Choice for one-sided */ + *sides_2sided_long, /* Choice for two-sided-long-edge */ + *sides_2sided_short; /* Choice for two-sided-short-edge */ +} _pwg_t; + /* * Prototypes... @@ -78,8 +129,11 @@ extern char *_ppdNormalizeMakeAndModel(const char *make_and_model, char *buffer, size_t bufsize); extern int _ppdParseOptions(const char *s, int num_options, - cups_option_t **options); + cups_option_t **options, + _ppd_parse_t which); +extern _pwg_t *_pwgCreateWithFile(const char *filename); extern _pwg_t *_pwgCreateWithPPD(ppd_file_t *ppd); +extern void _pwgDestroy(_pwg_t *pwg); extern const char *_pwgGetBin(_pwg_t *pwg, const char *output_bin); extern const char *_pwgGetInputSlot(_pwg_t *pwg, ipp_t *job, const char *keyword); @@ -98,6 +152,7 @@ extern const char *_pwgMediaTypeForType(const char *media_type, char *name, size_t namesize); extern const char *_pwgPageSizeForMedia(_pwg_media_t *media, char *name, size_t namesize); +extern int _pwgWriteFile(_pwg_t *pwg, const char *filename); /* diff --git a/cups/ppd.h b/cups/ppd.h index a84bcadcc..42c08df33 100644 --- a/cups/ppd.h +++ b/cups/ppd.h @@ -336,7 +336,7 @@ typedef struct ppd_file_s /**** PPD File ****/ cups_array_t *cups_uiconstraints; /* cupsUIConstraints @since CUPS 1.4/Mac OS X 10.6@ @private@ */ /**** New in CUPS 1.5 ****/ - void *pwg; /* PWG to/from PPD mappings */ + void *pwg; /* PWG to/from PPD mappings @since CUPS 1.5@ @private@ */ } ppd_file_t; diff --git a/cups/pwg-file.c b/cups/pwg-file.c index 8e4a4835e..6ebd4aaeb 100644 --- a/cups/pwg-file.c +++ b/cups/pwg-file.c @@ -46,11 +46,14 @@ _pwgCreateWithFile(const char *filename)/* I - File to read */ num_sizes, /* Number of sizes in file */ num_sources, /* Number of sources in file */ num_types; /* Number of types in file */ - char line[512], /* Current line */ + char line[2048], /* Current line */ *value, /* Pointer to value in line */ + *valueptr, /* Pointer into value */ pwg_keyword[128], /* PWG keyword */ ppd_keyword[PPD_MAX_NAME]; /* PPD keyword */ + _pwg_output_mode_t output_mode; /* Output mode for preset */ + _pwg_print_quality_t print_quality; /* Print quality for preset */ DEBUG_printf(("_pwgCreateWithFile(filename=\"%s\")", filename)); @@ -331,6 +334,38 @@ _pwgCreateWithFile(const char *filename)/* I - File to read */ pwg->num_types ++; } + else if (!strcasecmp(line, "Preset")) + { + /* + * Preset output-mode print-quality name=value ... + */ + + output_mode = (_pwg_output_mode_t)strtol(value, &valueptr, 10); + print_quality = (_pwg_print_quality_t)strtol(valueptr, &valueptr, 10); + + if (output_mode < _PWG_OUTPUT_MODE_MONOCHROME || + output_mode >= _PWG_OUTPUT_MODE_MAX || + print_quality < _PWG_PRINT_QUALITY_DRAFT || + print_quality >= _PWG_PRINT_QUALITY_MAX || + valueptr == value || !*valueptr) + { + DEBUG_printf(("_pwgCreateWithFile: Bad Preset on line %d.", linenum)); + _cupsSetError(IPP_INTERNAL_ERROR, _("Bad PWG mapping file."), 1); + goto create_error; + } + + pwg->num_presets[output_mode][print_quality] = + cupsParseOptions(valueptr, 0, + pwg->presets[output_mode] + print_quality); + } + else if (!strcasecmp(line, "SidesOption")) + pwg->sides_option = _cupsStrAlloc(value); + else if (!strcasecmp(line, "Sides1Sided")) + pwg->sides_1sided = _cupsStrAlloc(value); + else if (!strcasecmp(line, "Sides2SidedLong")) + pwg->sides_2sided_long = _cupsStrAlloc(value); + else if (!strcasecmp(line, "Sides2SidedShort")) + pwg->sides_2sided_short = _cupsStrAlloc(value); else { DEBUG_printf(("_pwgCreateWithFile: Unknown %s on line %d.", line, @@ -466,10 +501,11 @@ int /* O - 1 on success, 0 on failure */ _pwgWriteFile(_pwg_t *pwg, /* I - PWG mapping data */ const char *filename) /* I - File to write */ { - int i; /* Looping var */ + int i, j, k; /* Looping vars */ cups_file_t *fp; /* Output file */ _pwg_size_t *size; /* Current size */ _pwg_map_t *map; /* Current map */ + cups_option_t *option; /* Current option */ /* @@ -548,6 +584,38 @@ _pwgWriteFile(_pwg_t *pwg, /* I - PWG mapping data */ } /* + * Presets... + */ + + for (i = _PWG_OUTPUT_MODE_MONOCHROME; i < _PWG_OUTPUT_MODE_MAX; i ++) + for (j = _PWG_PRINT_QUALITY_DRAFT; i < _PWG_PRINT_QUALITY_MAX; i ++) + if (pwg->num_presets[i][j]) + { + cupsFilePrintf(fp, "Preset %d %d", i, j); + for (k = pwg->num_presets[i][j], option = pwg->presets[i][j]; + k > 0; + k --, option ++) + cupsFilePrintf(fp, " %s=%s", option->name, option->value); + cupsFilePutChar(fp, '\n'); + } + + /* + * Duplex/sides... + */ + + if (pwg->sides_option) + cupsFilePrintf(fp, "SidesOption %s\n", pwg->sides_option); + + if (pwg->sides_1sided) + cupsFilePrintf(fp, "Sides1Sided %s\n", pwg->sides_1sided); + + if (pwg->sides_2sided_long) + cupsFilePrintf(fp, "Sides2SidedLong %s\n", pwg->sides_2sided_long); + + if (pwg->sides_2sided_short) + cupsFilePrintf(fp, "Sides2SidedShort %s\n", pwg->sides_2sided_short); + + /* * Close and return... */ diff --git a/cups/pwg-ppd.c b/cups/pwg-ppd.c index 714304483..86c7715ec 100644 --- a/cups/pwg-ppd.c +++ b/cups/pwg-ppd.c @@ -62,20 +62,29 @@ static void pwg_unppdize_name(const char *ppd, char *name, size_t namesize); _pwg_t * /* O - PWG mapping data */ _pwgCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ { - int i, j; /* Looping vars */ - _pwg_t *pwg; /* PWG mapping data */ - ppd_option_t *input_slot, /* InputSlot option */ - *media_type, /* MediaType option */ - *output_bin; /* OutputBin option */ - ppd_choice_t *choice; /* Current InputSlot/MediaType */ - _pwg_map_t *map; /* Current source/type map */ - ppd_size_t *ppd_size; /* Current PPD size */ - _pwg_size_t *pwg_size; /* Current PWG size */ - char pwg_keyword[3 + PPD_MAX_NAME + 1 + 12 + 1 + 12 + 3], + int i, j; /* Looping vars */ + _pwg_t *pwg; /* PWG mapping data */ + ppd_option_t *input_slot, /* InputSlot option */ + *media_type, /* MediaType option */ + *output_bin, /* OutputBin option */ + *color_model, /* ColorModel option */ + *duplex; /* Duplex option */ + ppd_choice_t *choice; /* Current InputSlot/MediaType */ + _pwg_map_t *map; /* Current source/type map */ + ppd_attr_t *ppd_attr; /* Current PPD preset attribute */ + int num_options; /* Number of preset options and props */ + cups_option_t *options; /* Preset options and properties */ + ppd_size_t *ppd_size; /* Current PPD size */ + _pwg_size_t *pwg_size; /* Current PWG size */ + char pwg_keyword[3 + PPD_MAX_NAME + 1 + 12 + 1 + 12 + 3], /* PWG keyword string */ - ppd_name[PPD_MAX_NAME]; /* Normalized PPD name */ - const char *pwg_name; /* Standard PWG media name */ - _pwg_media_t *pwg_media; /* PWG media data */ + ppd_name[PPD_MAX_NAME]; + /* Normalized PPD name */ + const char *pwg_name; /* Standard PWG media name */ + _pwg_media_t *pwg_media; /* PWG media data */ + _pwg_output_mode_t pwg_output_mode;/* output-mode index */ + _pwg_print_quality_t pwg_print_quality; + /* print-quality index */ DEBUG_printf(("_pwgCreateWithPPD(ppd=%p)", ppd)); @@ -361,6 +370,171 @@ _pwgCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */ } } + if ((ppd_attr = ppdFindAttr(ppd, "APPrinterPreset", NULL)) != NULL) + { + /* + * Copy and convert APPrinterPreset (output-mode + print-quality) data... + */ + + const char *quality, /* com.apple.print.preset.quality value */ + *output_mode, /* com.apple.print.preset.output-mode value */ + *color_model_val; /* ColorModel choice */ + + + do + { + num_options = _ppdParseOptions(ppd_attr->value, 0, &options, + _PPD_PARSE_ALL); + + if ((quality = cupsGetOption("com.apple.print.preset.quality", + num_options, options)) != NULL) + { + /* + * Get the print-quality for this preset... + */ + + if (!strcmp(quality, "low")) + pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT; + else if (!strcmp(quality, "high")) + pwg_print_quality = _PWG_PRINT_QUALITY_HIGH; + else + pwg_print_quality = _PWG_PRINT_QUALITY_NORMAL; + + /* + * Get the output mode for this preset... + */ + + output_mode = cupsGetOption("com.apple.print.preset.output-mode", + num_options, options); + color_model_val = cupsGetOption("ColorModel", num_options, options); + + if (output_mode) + { + if (!strcmp(output_mode, "monochrome")) + pwg_output_mode = _PWG_OUTPUT_MODE_MONOCHROME; + else + pwg_output_mode = _PWG_OUTPUT_MODE_COLOR; + } + else if (color_model_val) + { + if (!strcasecmp(color_model_val, "Gray")) + pwg_output_mode = _PWG_OUTPUT_MODE_MONOCHROME; + else + pwg_output_mode = _PWG_OUTPUT_MODE_COLOR; + } + else + pwg_output_mode = _PWG_OUTPUT_MODE_COLOR; + + /* + * Save the options for this combination as needed... + */ + + if (!pwg->num_presets[pwg_output_mode][pwg_print_quality]) + pwg->num_presets[pwg_output_mode][pwg_print_quality] = + _ppdParseOptions(ppd_attr->value, 0, + pwg->presets[pwg_output_mode] + + pwg_print_quality, _PPD_PARSE_OPTIONS); + } + + cupsFreeOptions(num_options, options); + } + while ((ppd_attr = ppdFindNextAttr(ppd, "APPrinterPreset", NULL)) != NULL); + } + + if (!pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][_PWG_PRINT_QUALITY_DRAFT] && + !pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][_PWG_PRINT_QUALITY_NORMAL] && + !pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][_PWG_PRINT_QUALITY_HIGH] && + (color_model = ppdFindOption(ppd, "ColorModel")) != NULL && + ppdFindChoice(color_model, "Gray")) + { + /* + * Copy and convert ColorModel (output-mode) data... + */ + + cups_option_t *coption, /* Color option */ + *moption; /* Monochrome option */ + + for (pwg_print_quality = _PWG_PRINT_QUALITY_DRAFT; + pwg_print_quality < _PWG_PRINT_QUALITY_MAX; + pwg_print_quality ++) + { + if (pwg->num_presets[_PWG_OUTPUT_MODE_COLOR][pwg_print_quality]) + { + /* + * Copy the color options... + */ + + num_options = pwg->num_presets[_PWG_OUTPUT_MODE_COLOR] + [pwg_print_quality]; + options = calloc(sizeof(cups_option_t), num_options); + + if (options) + { + for (i = num_options, moption = options, + coption = pwg->presets[_PWG_OUTPUT_MODE_COLOR] + [pwg_print_quality]; + i > 0; + i --, moption ++, coption ++) + { + moption->name = _cupsStrRetain(coption->name); + moption->value = _cupsStrRetain(coption->value); + } + + pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][pwg_print_quality] = + num_options; + pwg->presets[_PWG_OUTPUT_MODE_MONOCHROME][pwg_print_quality] = + options; + } + } + else if (pwg_print_quality != _PWG_PRINT_QUALITY_NORMAL) + continue; + + /* + * Add ColorModel=Gray to the preset... + */ + + pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME][pwg_print_quality] = + cupsAddOption("ColorModel", "Gray", + pwg->num_presets[_PWG_OUTPUT_MODE_MONOCHROME] + [pwg_print_quality], + pwg->presets[_PWG_OUTPUT_MODE_MONOCHROME] + + pwg_print_quality); + } + } + + /* + * Copy and convert Duplex (sides) data... + */ + + if ((duplex = ppdFindOption(ppd, "Duplex")) == NULL) + if ((duplex = ppdFindOption(ppd, "JCLDuplex")) == NULL) + if ((duplex = ppdFindOption(ppd, "EFDuplex")) == NULL) + if ((duplex = ppdFindOption(ppd, "EFDuplexing")) == NULL) + duplex = ppdFindOption(ppd, "KD03Duplex"); + + if (duplex) + { + pwg->sides_option = _cupsStrAlloc(duplex->keyword); + + for (i = duplex->num_choices, choice = duplex->choices; + i > 0; + i --, choice ++) + { + if ((!strcasecmp(choice->choice, "None") || + !strcasecmp(choice->choice, "False")) && !pwg->sides_1sided) + pwg->sides_1sided = _cupsStrAlloc(choice->choice); + else if ((!strcasecmp(choice->choice, "DuplexNoTumble") || + !strcasecmp(choice->choice, "LongEdge") || + !strcasecmp(choice->choice, "Top")) && !pwg->sides_2sided_long) + pwg->sides_2sided_long = _cupsStrAlloc(choice->choice); + else if ((!strcasecmp(choice->choice, "DuplexTumble") || + !strcasecmp(choice->choice, "ShortEdge") || + !strcasecmp(choice->choice, "Bottom")) && + !pwg->sides_2sided_short) + pwg->sides_2sided_short = _cupsStrAlloc(choice->choice); + } + } + return (pwg); /* diff --git a/cups/pwg-private.h b/cups/pwg-private.h index 623fc5801..33a0790af 100644 --- a/cups/pwg-private.h +++ b/cups/pwg-private.h @@ -48,9 +48,11 @@ extern "C" { * Types and structures... */ -# ifndef _CUPS_PPD_H_ -typedef struct ppd_file_s ppd_file_t; -# endif /* _CUPS_PPD_H_ */ +typedef struct _pwg_map_s /**** Map element - PPD to/from PWG */ +{ + char *pwg, /* PWG media keyword */ + *ppd; /* PPD option keyword */ +} _pwg_map_t; typedef struct _pwg_media_s /**** Common media size data ****/ { @@ -61,12 +63,6 @@ typedef struct _pwg_media_s /**** Common media size data ****/ length; /* Length in 2540ths */ } _pwg_media_t; -typedef struct _pwg_map_s /**** Map element - PPD to/from PWG */ -{ - char *pwg, /* PWG media keyword */ - *ppd; /* PPD option keyword */ -} _pwg_map_t; - typedef struct _pwg_size_s /**** Size element - PPD to/from PWG */ { _pwg_map_t map; /* Map element */ @@ -78,43 +74,20 @@ typedef struct _pwg_size_s /**** Size element - PPD to/from PWG */ top; /* Top margin in 2540ths */ } _pwg_size_t; -typedef struct _pwg_s /**** PWG-PPD conversion data ****/ -{ - int num_bins; /* Number of output bins */ - _pwg_map_t *bins; /* Output bins */ - int num_sizes; /* Number of media sizes */ - _pwg_size_t *sizes; /* Media sizes */ - int custom_max_width, /* Maximum custom width in 2540ths */ - custom_max_length, /* Maximum custom length in 2540ths */ - custom_min_width, /* Minimum custom width in 2540ths */ - custom_min_length; /* Minimum custom length in 2540ths */ - char *custom_max_keyword, /* Maximum custom size PWG keyword */ - *custom_min_keyword, /* Minimum custom size PWG keyword */ - custom_ppd_size[41]; /* Custom PPD size name */ - _pwg_size_t custom_size; /* Custom size record */ - int num_sources; /* Number of media sources */ - _pwg_map_t *sources; /* Media sources */ - int num_types; /* Number of media types */ - _pwg_map_t *types; /* Media types */ -} _pwg_t; - /* * Functions... */ -extern _pwg_t *_pwgCreateWithFile(const char *filename); -extern void _pwgDestroy(_pwg_t *pwg); extern void _pwgGenerateSize(char *keyword, size_t keysize, const char *prefix, - const char *ppdname, + const char *name, int width, int length); extern int _pwgInitSize(_pwg_size_t *size, ipp_t *job, int *margins_set); extern _pwg_media_t *_pwgMediaForLegacy(const char *legacy); extern _pwg_media_t *_pwgMediaForPWG(const char *pwg); extern _pwg_media_t *_pwgMediaForSize(int width, int length); -extern int _pwgWriteFile(_pwg_t *pwg, const char *filename); # ifdef __cplusplus diff --git a/cups/raster.h b/cups/raster.h index 4848dacc2..dbb7e30b8 100644 --- a/cups/raster.h +++ b/cups/raster.h @@ -1,9 +1,9 @@ /* * "$Id$" * - * Raster file definitions for the Common UNIX Printing System (CUPS). + * Raster file definitions for CUPS. * - * Copyright 2007-2008 by Apple Inc. + * Copyright 2007-2010 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * This file is part of the CUPS Imaging library. @@ -86,26 +86,28 @@ typedef enum cups_bool_e /**** Boolean type ****/ typedef enum cups_cspace_e /**** cupsColorSpace attribute values ****/ { - CUPS_CSPACE_W = 0, /* Luminance */ - CUPS_CSPACE_RGB = 1, /* Red, green, blue */ - CUPS_CSPACE_RGBA = 2, /* Red, green, blue, alpha */ - CUPS_CSPACE_K = 3, /* Black */ - CUPS_CSPACE_CMY = 4, /* Cyan, magenta, yellow */ - CUPS_CSPACE_YMC = 5, /* Yellow, magenta, cyan */ - CUPS_CSPACE_CMYK = 6, /* Cyan, magenta, yellow, black */ - CUPS_CSPACE_YMCK = 7, /* Yellow, magenta, cyan, black */ - CUPS_CSPACE_KCMY = 8, /* Black, cyan, magenta, yellow */ - CUPS_CSPACE_KCMYcm = 9, /* Black, cyan, magenta, yellow, * - * light-cyan, light-magenta */ - CUPS_CSPACE_GMCK = 10, /* Gold, magenta, yellow, black */ - CUPS_CSPACE_GMCS = 11, /* Gold, magenta, yellow, silver */ - CUPS_CSPACE_WHITE = 12, /* White ink (as black) */ - CUPS_CSPACE_GOLD = 13, /* Gold foil */ - CUPS_CSPACE_SILVER = 14, /* Silver foil */ + CUPS_CSPACE_W = 0, /* Luminance (DeviceGray, gamma 2.2 by default) */ + CUPS_CSPACE_RGB = 1, /* Red, green, blue (DeviceRGB, sRGB by default) */ + CUPS_CSPACE_RGBA = 2, /* Red, green, blue, alpha (DeviceRGB, sRGB by default) */ + CUPS_CSPACE_K = 3, /* Black (DeviceK) */ + CUPS_CSPACE_CMY = 4, /* Cyan, magenta, yellow (DeviceCMY) */ + CUPS_CSPACE_YMC = 5, /* Yellow, magenta, cyan @deprecated@ */ + CUPS_CSPACE_CMYK = 6, /* Cyan, magenta, yellow, black (DeviceCMYK) */ + CUPS_CSPACE_YMCK = 7, /* Yellow, magenta, cyan, black @deprecated@ */ + CUPS_CSPACE_KCMY = 8, /* Black, cyan, magenta, yellow @deprecated@ */ + CUPS_CSPACE_KCMYcm = 9, /* Black, cyan, magenta, yellow, light-cyan, light-magenta @deprecated@ */ + CUPS_CSPACE_GMCK = 10, /* Gold, magenta, yellow, black @deprecated@ */ + CUPS_CSPACE_GMCS = 11, /* Gold, magenta, yellow, silver @deprecated@ */ + CUPS_CSPACE_WHITE = 12, /* White ink (as black) @deprecated@ */ + CUPS_CSPACE_GOLD = 13, /* Gold foil @deprecated@ */ + CUPS_CSPACE_SILVER = 14, /* Silver foil @deprecated@ */ CUPS_CSPACE_CIEXYZ = 15, /* CIE XYZ @since CUPS 1.1.19/Mac OS X 10.3@ */ CUPS_CSPACE_CIELab = 16, /* CIE Lab @since CUPS 1.1.19/Mac OS X 10.3@ */ - CUPS_CSPACE_RGBW = 17, /* Red, green, blue, white @since CUPS 1.2/Mac OS X 10.5@ */ + CUPS_CSPACE_RGBW = 17, /* Red, green, blue, white (DeviceRGB, sRGB by default) @since CUPS 1.2/Mac OS X 10.5@ */ + CUPS_CSPACE_SW = 18, /* Luminance (gamma 2.2) @since CUPS 1.4.5@ */ + CUPS_CSPACE_SRGB = 19, /* Red, green, blue (sRGB) @since CUPS 1.4.5@ */ + CUPS_CSPACE_ADOBERGB = 20, /* Red, green, blue (Adobe RGB) @since CUPS 1.4.5@ */ CUPS_CSPACE_ICC1 = 32, /* ICC-based, 1 color @since CUPS 1.1.19/Mac OS X 10.3@ */ CUPS_CSPACE_ICC2 = 33, /* ICC-based, 2 colors @since CUPS 1.1.19/Mac OS X 10.3@ */ @@ -121,7 +123,23 @@ typedef enum cups_cspace_e /**** cupsColorSpace attribute values ****/ CUPS_CSPACE_ICCC = 43, /* ICC-based, 12 colors @since CUPS 1.1.19/Mac OS X 10.3@ */ CUPS_CSPACE_ICCD = 44, /* ICC-based, 13 colors @since CUPS 1.1.19/Mac OS X 10.3@ */ CUPS_CSPACE_ICCE = 45, /* ICC-based, 14 colors @since CUPS 1.1.19/Mac OS X 10.3@ */ - CUPS_CSPACE_ICCF = 46 /* ICC-based, 15 colors @since CUPS 1.1.19/Mac OS X 10.3@ */ + CUPS_CSPACE_ICCF = 46, /* ICC-based, 15 colors @since CUPS 1.1.19/Mac OS X 10.3@ */ + + CUPS_CSPACE_DEVICE1 = 48, /* DeviceN, 1 color @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICE2 = 49, /* DeviceN, 2 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICE3 = 50, /* DeviceN, 3 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICE4 = 51, /* DeviceN, 4 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICE5 = 52, /* DeviceN, 5 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICE6 = 53, /* DeviceN, 6 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICE7 = 54, /* DeviceN, 7 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICE8 = 55, /* DeviceN, 8 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICE9 = 56, /* DeviceN, 9 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICEA = 57, /* DeviceN, 10 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICEB = 58, /* DeviceN, 11 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICEC = 59, /* DeviceN, 12 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICED = 60, /* DeviceN, 13 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICEE = 61, /* DeviceN, 14 colors @since CUPS 1.4.5@ */ + CUPS_CSPACE_DEVICEF = 62 /* DeviceN, 15 colors @since CUPS 1.4.5@ */ } cups_cspace_t; typedef enum cups_cut_e /**** CutMedia attribute values ****/ diff --git a/cups/testfile.c b/cups/testfile.c index 1363dfacf..74da14b64 100644 --- a/cups/testfile.c +++ b/cups/testfile.c @@ -130,12 +130,12 @@ main(int argc, /* I - Number of command-line arguments */ #endif /* !WIN32 */ /* - * Count lines in euc-jp.txt, rewind, then count again. + * Count lines in psglyphs, rewind, then count again. */ - fputs("\ncupsFileOpen(\"../data/euc-jp.txt\", \"r\"): ", stdout); + fputs("\ncupsFileOpen(\"../data/psglyphs\", \"r\"): ", stdout); - if ((fp = cupsFileOpen("../data/euc-jp.txt", "r")) == NULL) + if ((fp = cupsFileOpen("../data/psglyphs", "r")) == NULL) { puts("FAIL"); status ++; @@ -145,9 +145,9 @@ main(int argc, /* I - Number of command-line arguments */ puts("PASS"); fputs("cupsFileGets: ", stdout); - if ((count = count_lines(fp)) != 15184) + if ((count = count_lines(fp)) != 1051) { - printf("FAIL (got %d lines, expected 15184)\n", count); + printf("FAIL (got %d lines, expected 1051)\n", count); status ++; } else @@ -165,9 +165,9 @@ main(int argc, /* I - Number of command-line arguments */ puts("PASS"); fputs("cupsFileGets: ", stdout); - if ((count = count_lines(fp)) != 15184) + if ((count = count_lines(fp)) != 1051) { - printf("FAIL (got %d lines, expected 15184)\n", count); + printf("FAIL (got %d lines, expected 1051)\n", count); status ++; } else diff --git a/cups/thread-private.h b/cups/thread-private.h new file mode 100644 index 000000000..859e6c1a8 --- /dev/null +++ b/cups/thread-private.h @@ -0,0 +1,86 @@ +/* + * "$Id$" + * + * Private threading definitions for CUPS. + * + * Copyright 2009-2010 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/". + */ + +#ifndef _CUPS_THREAD_PRIVATE_H_ +# define _CUPS_THREAD_PRIVATE_H_ + +/* + * Include necessary headers... + */ + +# include "config.h" + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +# ifdef HAVE_PTHREAD_H +# include <pthread.h> +typedef void *(*_cups_thread_func_t)(void *arg); +typedef pthread_mutex_t _cups_mutex_t; +typedef pthread_key_t _cups_threadkey_t; +# define _CUPS_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER +# define _CUPS_THREADKEY_INITIALIZER -1 +# define _cupsThreadGetData(k) pthread_getspecific(k) +# define _cupsThreadSetData(k,p) pthread_setspecific(k,p) + +# elif defined(WIN32) +# include <winsock2.h> +# include <windows.h> +typedef void *(__stdcall *_cups_thread_func_t)(void *arg); +typedef struct _cups_mutex_s +{ + int m_init; /* Flag for on-demand initialization */ + CRITICAL_SECTION m_criticalSection; + /* Win32 Critical Section */ +} _cups_mutex_t; +typedef DWORD _cups_threadkey_t; +# define _CUPS_MUTEX_INITIALIZER { 0, 0 } +# define _CUPS_THREADKEY_INITIALIZER 0 +# define _cupsThreadGetData(k) TlsGetValue(k) +# define _cupsThreadSetData(k,p) TlsSetValue(k,p) + +# else +typedef char _cups_mutex_t; +typedef void *_cups_threadkey_t; +# define _CUPS_MUTEX_INITIALIZER 0 +# define _CUPS_THREADKEY_INITIALIZER (void *)0 +# define _cupsThreadGetData(k) k +# define _cupsThreadSetData(k,p) k=p +# endif /* HAVE_PTHREAD_H */ + + +/* + * Functions... + */ + +extern void _cupsMutexLock(_cups_mutex_t *mutex); +extern void _cupsMutexUnlock(_cups_mutex_t *mutex); +extern int _cupsThreadCreate(_cups_thread_func_t func, void *arg); + + +# ifdef __cplusplus +} +# endif /* __cplusplus */ +#endif /* !_CUPS_THREAD_PRIVATE_H_ */ + +/* + * End of "$Id$". + */ diff --git a/cups/thread.c b/cups/thread.c new file mode 100644 index 000000000..deb3a8ebc --- /dev/null +++ b/cups/thread.c @@ -0,0 +1,144 @@ +/* + * "$Id$" + * + * Threading primitives for CUPS. + * + * Copyright 2009-2010 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/". + * + * Contents: + * + * _cupsMutexLock() - Lock a mutex. + * _cupsMutexUnlock() - Unlock a mutex. + * _cupsThreadCreate() - Create a thread. + */ + +/* + * Include necessary headers... + */ + +#include "cups-private.h" +#include "thread-private.h" + + +#if defined(HAVE_PTHREAD_H) +/* + * '_cupsMutexLock()' - Lock a mutex. + */ + +void +_cupsMutexLock(_cups_mutex_t *mutex) /* I - Mutex */ +{ + pthread_mutex_lock(mutex); +} + + +/* + * '_cupsMutexUnlock()' - Unlock a mutex. + */ + +void +_cupsMutexUnlock(_cups_mutex_t *mutex) /* I - Mutex */ +{ + pthread_mutex_unlock(mutex); +} + + +/* + * '_cupsThreadCreate()' - Create a thread. + */ + +int /* O - 0 on failure, 1 on success */ +_cupsThreadCreate( + _cups_thread_func_t func, /* I - Entry point */ + void *arg) /* I - Entry point context */ +{ + pthread_t thread; + + return (pthread_create(&thread, NULL, (void *(*)(void *))func, arg) == 0); +} + + +#elif defined(WIN32) +# include <process.h> + + +/* + * '_cupsMutexLock()' - Lock a mutex. + */ + +void +_cupsMutexLock(_cups_mutex_t *mutex) /* I - Mutex */ +{ + if (!mutex->m_init) + { + _cupsGlobalLock(); + + if (!mutex->m_init) + { + InitializeCriticalSection(&mutex->m_criticalSection); + mutex->m_init = 1; + } + + _cupsGlobalUnlock(); + } + + EnterCriticalSection(&mutex->m_criticalSection); +} + + +/* + * '_cupsMutexUnlock()' - Unlock a mutex. + */ + +void +_cupsMutexUnlock(_cups_mutex_t *mutex) /* I - Mutex */ +{ + LeaveCriticalSection(&mutex->m_criticalSection); +} + + +/* + * '_cupsThreadCreate()' - Create a thread. + */ + +int /* O - 0 on failure, 1 on success */ +_cupsThreadCreate( + _cups_thread_func_t func, /* I - Entry point */ + void *arg) /* I - Entry point context */ +{ + return (_beginthreadex(NULL, 0, (LPTHREAD_START_ROUTINE) func, arg, 0, NULL) + != 0); +} + + +#else +/* + * '_cupsMutexLock()' - Lock a mutex. + */ + +void +_cupsMutexLock(_cups_mutex_t *mutex) /* I - Mutex */ +{ +} + + +/* + * '_cupsMutexUnlock()' - Unlock a mutex. + */ + +void +_cupsMutexUnlock(_cups_mutex_t *mutex) /* I - Mutex */ +{ +} +#endif /* HAVE_PTHREAD_H */ + + +/* + * End of "$Id$". + */ diff --git a/cups/versioning.h b/cups/versioning.h index 7d506f893..323fea5a8 100644 --- a/cups/versioning.h +++ b/cups/versioning.h @@ -49,6 +49,7 @@ # define _CUPS_API_1_2 AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER # define _CUPS_API_1_3 AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER # define _CUPS_API_1_4 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER +# define _CUPS_API_1_5 # else # define _CUPS_API_1_1_19 # define _CUPS_API_1_1_20 @@ -56,6 +57,7 @@ # define _CUPS_API_1_2 # define _CUPS_API_1_3 # define _CUPS_API_1_4 +# define _CUPS_API_1_5 # endif /* __APPLE__ && !_CUPS_SOURCE */ /* diff --git a/doc/Makefile b/doc/Makefile index bab8f31e6..07350e3fc 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -69,7 +69,6 @@ HELPFILES = \ help/man-cupsenable.html \ help/man-cupstestdsc.html \ help/man-cupstestppd.html \ - help/man-drv.html \ help/man-filter.html \ help/man-ipptool.html \ help/man-ipptoolfile.html \ diff --git a/doc/help/spec-ppd.html b/doc/help/spec-ppd.html index 2ac011e77..3c81a763c 100644 --- a/doc/help/spec-ppd.html +++ b/doc/help/spec-ppd.html @@ -10,9 +10,9 @@ <!-- "$Id: spec-ppd.html 7937 2008-09-11 16:16:41Z mike $" - CUPS PPD extensions specification for the Common UNIX Printing System (CUPS). + CUPS PPD extensions specification for CUPS. - Copyright 2007-2009 by Apple Inc. + Copyright 2007-2010 by Apple Inc. Copyright 1997-2007 by Easy Software Products. These coded instructions, statements, and computer programs are the @@ -1566,6 +1566,31 @@ before the filter that accepts the given MIME type.</p> *cupsPreFilter: "image/png 0 mypngprefilter" </pre> + +<h3><span class='info'>CUPS 1.5</span><a name='cupsPrintQuality'>cupsPrintQuality</a></h3> + +<p class='summary'>*cupsPrintQuality keyword/text: "code"</p> + +<p>This UI keyword defines standard print qualities that directly map from the IPP "print-quality" job template attribute. Standard keyword values are "Draft", "Normal", and "High" which are mapped from the IPP "print-quality" values 3, 4, and 5 respectively. Each <code>cupsPrintQuality</code> option typically sets output mode and resolution parameters in the page device dictionary, eliminating the need for separate (and sometimes confusing) output mode and resolution options.</p> + +<blockquote><b>Note:</b> + +<p>Unlike all of the other keywords defined in this document, <code>cupsPrintQuality</code> is a UI keyword that MUST be enclosed inside the PPD <code>OpenUI</code> and <code>CloseUI</code> keywords.</p> + +</blockquote> + +<p>Examples:</p> + +<pre class='command'> +*OpenUI *cupsPrintQuality/Print Quality: PickOne +*OrderDependency: 10 AnySetup *cupsPrintQuality +*DefaultcupsPrintQuality: Normal +*cupsPrintQuality Draft/Draft: "code" +*cupsPrintQuality Normal/Normal: "code" +*cupsPrintQuality High/Photo: "code" +*CloseUI: *cupsPrintQuality +</pre> + <h3><span class='info'>CUPS 1.4/Mac OS X 10.6</span><a name='cupsSNMPSupplies'>cupsSNMPSupplies</a></h3> <p class='summary'>*cupsSNMPSupplies: boolean</p> @@ -1775,39 +1800,51 @@ Technical Note TN2144</a> for more information.</p> in the print dialog of applications (such as iPhoto) that set the job style hint to <tt>NSPrintPhotoJobStyleHint</tt>. Each preset maps to one or more pairs of PPD options and choices as well as providing key/value data for -the application. The following preset names are currently defined:</p> +the application. The following standard preset names are currently defined:</p> <ul> - <li><code>Photo_with_Paper_Auto-Detect</code>; Photo printing - with paper auto-detect</li> + <li><code>General_with_Paper_Auto-Detect</code>; Normal quality general printing with auto-detected media.</li> + + <li><code>General_with_Paper_Auto-Detect_-_Draft</code>; Draft quality general printing with auto-detected media.</li> + + <li><code>General_on_Plain_Paper</code>; Normal quality general printing on plain paper.</li> + + <li><code>General_on_Plain_Paper_-_Draft</code>; Draft quality general printing on plain paper.</li> - <li><code>Photo_with_Paper_Auto-Detect_-_Fine</code>; Photo printing - with paper auto-detect - fine</li> + <li><code>Photo_with_Paper_Auto-Detect</code>; Normal quality photo printing with auto-detected media.</li> - <li><code>Photo_on_Plain_Paper</code>; Photo printing on plain paper</li> + <li><code>Photo_with_Paper_Auto-Detect_-_Fine</code>; High quality photo printing with auto-detected media.</li> - <li><code>Photo_on_Plain_Paper_-_Fine</code>; Photo printing on plain - paper - fine</li> + <li><code>Photo_on_Plain_Paper</code>; Normal quality photo printing on plain paper.</li> - <li><code>Photo_on_Photo_Paper</code>; Photo printing on photo paper</li> + <li><code>Photo_on_Plain_Paper_-_Fine</code>; High quality photo printing on plain paper.</li> - <li><code>Photo_on_Photo_Paper_-_Fine</code>; Photo printing on photo - paper - fine</li> + <li><code>Photo_on_Photo_Paper</code>; Normal quality photo printing on glossy photo paper.</li> - <li><code>Photo_on_Matte_Paper</code>; Photo printing on matte paper</li> + <li><code>Photo_on_Photo_Paper_-_Fine</code>; High quality photo printing on glossy photo paper.</li> - <li><code>Photo_on_Matte_Paper_-_Fine</code>; Photo printing on matte - paper - fine</li> + <li><code>Photo_on_Matte_Paper</code>; Normal quality photo printing on matte paper.</li> + + <li><code>Photo_on_Matte_Paper_-_Fine</code>; High quality photo printing on matte paper.</li> </ul> <p>The value string consists of pairs of keywords, either an option name and choice (*MainKeyword OptionKeyword) or a preset identifier and value -(com.apple.print.preset.foo value). Preset identifiers and their supported -values are documented in "<a -href='http://developer.apple.com/documentation/Printing/Conceptual/PresetDraft/presets_intro/chapter_1_section_2.html' ->Creating Printing Presets for iPhoto: Printing Presets File Format</a>".</p> +(com.apple.print.preset.foo value). The following preset identifiers are currently used:</p> + +<ul> + + <li><code>com.apple.print.preset.graphicsType</code>; specifies the type of printing used for this printing - "General" for general purpose printing and "Photo" for photo printing.</li> + + <li><code>com.apple.print.preset.media-front-coating</code>; specifies the media type selected by this preset - "none" (plain paper), "glossy", "high-gloss", "semi-gloss", "satin", "matte", and "autodetect".</li> + + <li><code>com.apple.print.preset.output-mode</code>; specifies the output mode for this preset - "color" (default for color printers) or "monochrome" (grayscale, default for B&W printers).</li> + + <li><code>com.apple.print.preset.quality</code>; specifies the overall print quality selected by this preset - "low" (draft), "mid" (normal), or "high".</li> + +</ul> <p>Presets, like options, can also be localized in multiple languages.</p> @@ -1871,6 +1908,17 @@ the device.</p> <h2 class='title'><a name='HISTORY'>Change History</a></h2> +<h3>Changes in CUPS 1.4.5</h3> + +<ul> + + <li>Added <a href='#cupsPrintQuality'><tt>cupsPrintQuality</tt></a> UI keyword.</li> + + <li>Added new properties and values for the <a href='#APPrinterPreset'><tt>APPrinterPreset</tt></a> keyword.</li> + +</ul> + + <h3>Changes in CUPS 1.4</h3> <ul> diff --git a/driver/rastertoescpx.c b/driver/rastertoescpx.c index 38ef623bc..d6e3b6b62 100644 --- a/driver/rastertoescpx.c +++ b/driver/rastertoescpx.c @@ -1787,7 +1787,15 @@ main(int argc, /* I - Number of command-line arguments */ if (!ppd) { - _cupsLangPuts(stderr, _("ERROR: Unable to open PPD file\n")); + ppd_status_t status; /* PPD error */ + int linenum; /* Line number */ + + _cupsLangPrintf(stderr, _("ERROR: The PPD file could not be opened.\n")); + + status = ppdLastError(&linenum); + + fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum); + return (1); } @@ -1902,7 +1910,7 @@ main(int argc, /* I - Number of command-line arguments */ if (page == 0) { - _cupsLangPuts(stderr, _("ERROR: No pages found\n")); + _cupsLangPuts(stderr, _("ERROR: No pages were found.\n")); return (1); } else diff --git a/driver/rastertopclx.c b/driver/rastertopclx.c index f522ac6fb..ce934c822 100644 --- a/driver/rastertopclx.c +++ b/driver/rastertopclx.c @@ -1812,7 +1812,15 @@ main(int argc, /* I - Number of command-line arguments */ if (!ppd) { - _cupsLangPuts(stderr, _("ERROR: Unable to open PPD file\n")); + ppd_status_t status; /* PPD error */ + int linenum; /* Line number */ + + _cupsLangPrintf(stderr, _("ERROR: The PPD file could not be opened.\n")); + + status = ppdLastError(&linenum); + + fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum); + return (1); } @@ -1927,7 +1935,7 @@ main(int argc, /* I - Number of command-line arguments */ if (Page == 0) { - _cupsLangPuts(stderr, _("ERROR: No pages found\n")); + _cupsLangPuts(stderr, _("ERROR: No pages were found.\n")); return (1); } else diff --git a/filter/imagetoraster.c b/filter/imagetoraster.c index a367b28f4..a54080c2d 100644 --- a/filter/imagetoraster.c +++ b/filter/imagetoraster.c @@ -455,7 +455,7 @@ main(int argc, /* I - Number of command-line arguments */ if (cupsRasterInterpretPPD(&header, ppd, num_options, options, raster_cb)) { - _cupsLangPuts(stderr, _("ERROR: Bad page setup\n")); + _cupsLangPuts(stderr, _("ERROR: The page setup information was not valid.\n")); fprintf(stderr, "DEBUG: %s\n", cupsRasterErrorString()); return (1); } @@ -481,6 +481,7 @@ main(int argc, /* I - Number of command-line arguments */ switch (header.cupsColorSpace) { case CUPS_CSPACE_W : + case CUPS_CSPACE_SW : if (header.cupsBitsPerColor >= 8) { primary = CUPS_IMAGE_WHITE; @@ -493,10 +494,11 @@ main(int argc, /* I - Number of command-line arguments */ } break; - default : case CUPS_CSPACE_RGB : case CUPS_CSPACE_RGBA : case CUPS_CSPACE_RGBW : + case CUPS_CSPACE_SRGB : + case CUPS_CSPACE_ADOBERGB : if (header.cupsBitsPerColor >= 8) { primary = CUPS_IMAGE_RGB; @@ -540,6 +542,42 @@ main(int argc, /* I - Number of command-line arguments */ primary = CUPS_IMAGE_CMY; secondary = CUPS_IMAGE_CMY; break; + + case CUPS_CSPACE_CIEXYZ : + case CUPS_CSPACE_CIELab : + case CUPS_CSPACE_ICC1 : + case CUPS_CSPACE_ICC2 : + case CUPS_CSPACE_ICC3 : + case CUPS_CSPACE_ICC4 : + case CUPS_CSPACE_ICC5 : + case CUPS_CSPACE_ICC6 : + case CUPS_CSPACE_ICC7 : + case CUPS_CSPACE_ICC8 : + case CUPS_CSPACE_ICC9 : + case CUPS_CSPACE_ICCA : + case CUPS_CSPACE_ICCB : + case CUPS_CSPACE_ICCC : + case CUPS_CSPACE_ICCD : + case CUPS_CSPACE_ICCE : + case CUPS_CSPACE_ICCF : + case CUPS_CSPACE_DEVICE1 : + case CUPS_CSPACE_DEVICE2 : + case CUPS_CSPACE_DEVICE3 : + case CUPS_CSPACE_DEVICE4 : + case CUPS_CSPACE_DEVICE5 : + case CUPS_CSPACE_DEVICE6 : + case CUPS_CSPACE_DEVICE7 : + case CUPS_CSPACE_DEVICE8 : + case CUPS_CSPACE_DEVICE9 : + case CUPS_CSPACE_DEVICEA : + case CUPS_CSPACE_DEVICEB : + case CUPS_CSPACE_DEVICEC : + case CUPS_CSPACE_DEVICED : + case CUPS_CSPACE_DEVICEE : + case CUPS_CSPACE_DEVICEF : + fprintf(stderr, "ERROR: Colorspace %d not supported.\n", + header.cupsColorSpace); + exit(1); break; } @@ -632,7 +670,7 @@ main(int argc, /* I - Number of command-line arguments */ if (img == NULL) { - _cupsLangPuts(stderr, _("ERROR: Unable to open image file for printing\n")); + _cupsLangPuts(stderr, _("ERROR: The image file to print could not be opened.\n")); ppdClose(ppd); return (1); } @@ -1195,8 +1233,8 @@ main(int argc, /* I - Number of command-line arguments */ header.cupsBytesPerLine) { _cupsLangPuts(stderr, - _("ERROR: Unable to write raster data to " - "driver\n")); + _("ERROR: The raster data could not be written " + "to the driver.\n")); cupsImageClose(img); exit(1); } @@ -1291,8 +1329,9 @@ main(int argc, /* I - Number of command-line arguments */ if (cupsRasterWritePixels(ras, row, header.cupsBytesPerLine) < header.cupsBytesPerLine) { - _cupsLangPuts(stderr, - _("ERROR: Unable to write raster data to driver\n")); + _cupsLangPuts(stderr, + _("ERROR: The raster data could not be written to " + "the driver.\n")); cupsImageClose(img); exit(1); } @@ -1332,8 +1371,8 @@ main(int argc, /* I - Number of command-line arguments */ header.cupsBytesPerLine) { _cupsLangPuts(stderr, - _("ERROR: Unable to write raster data to " - "driver\n")); + _("ERROR: The raster data could not be written " + "to the driver.\n")); cupsImageClose(img); exit(1); } diff --git a/filter/pdftops.c b/filter/pdftops.c index 67f0e9dc4..0868e6296 100644 --- a/filter/pdftops.c +++ b/filter/pdftops.c @@ -133,7 +133,7 @@ main(int argc, /* I - Number of command-line args */ if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0) { - _cupsLangPrintError(_("ERROR: Unable to copy PDF file")); + perror("DEBUG: Unable to copy PDF file"); return (1); } @@ -409,7 +409,7 @@ main(int argc, /* I - Number of command-line args */ if (pipe(pstops_pipe)) { - _cupsLangPrintError(_("ERROR: Unable to create pipe")); + perror("DEBUG: Unable to create pipe"); exit_status = 1; goto error; @@ -427,10 +427,10 @@ main(int argc, /* I - Number of command-line args */ #ifdef HAVE_PDFTOPS execv(CUPS_PDFTOPS, pdf_argv); - _cupsLangPrintError(_("ERROR: Unable to execute pdftops program")); + perror("DEBUG: Unable to execute pdftops program"); #else execv(CUPS_GHOSTSCRIPT, pdf_argv); - _cupsLangPrintError(_("ERROR: Unable to execute gs program")); + perror("DEBUG: Unable to execute gs program"); #endif /* HAVE_PDFTOPS */ exit(1); @@ -442,9 +442,9 @@ main(int argc, /* I - Number of command-line args */ */ #ifdef HAVE_PDFTOPS - _cupsLangPrintError(_("ERROR: Unable to execute pdftops program")); + perror("DEBUG: Unable to execute pdftops program"); #else - _cupsLangPrintError(_("ERROR: Unable to execute gs program")); + perror("DEBUG: Unable to execute gs program"); #endif /* HAVE_PDFTOPS */ exit_status = 1; @@ -464,7 +464,7 @@ main(int argc, /* I - Number of command-line args */ close(pstops_pipe[1]); execv(pstops_path, pstops_argv); - _cupsLangPrintError(_("ERROR: Unable to execute pstops program")); + perror("DEBUG: Unable to execute pstops program"); exit(1); } @@ -474,7 +474,7 @@ main(int argc, /* I - Number of command-line args */ * Unable to fork! */ - _cupsLangPrintError(_("ERROR: Unable to execute pstops program")); + perror("DEBUG: Unable to execute pstops program"); exit_status = 1; goto error; diff --git a/filter/pstops.c b/filter/pstops.c index 6ed7bd044..96e1e66cb 100644 --- a/filter/pstops.c +++ b/filter/pstops.c @@ -308,7 +308,7 @@ main(int argc, /* I - Number of command-line args */ if ((len = cupsFileGetLine(fp, line, sizeof(line))) == 0) { - _cupsLangPuts(stderr, _("ERROR: Empty print file\n")); + fputs("DEBUG: The print file is empty.\n", stderr); return (1); } @@ -651,9 +651,8 @@ copy_comments(cups_file_t *fp, /* I - File to read from */ { int pages; /* Number of pages */ - - if (saw_pages) - _cupsLangPuts(stderr, _("ERROR: Duplicate %%Pages: comment seen\n")); + if (saw_pages) + fputs("DEBUG: A duplicate %%Pages: comment was seen.\n", stderr); saw_pages = 1; @@ -699,9 +698,8 @@ copy_comments(cups_file_t *fp, /* I - File to read from */ } else if (!strncmp(line, "%%BoundingBox:", 14)) { - if (saw_bounding_box) - _cupsLangPuts(stderr, - _("ERROR: Duplicate %%BoundingBox: comment seen\n")); + if (saw_bounding_box) + fputs("DEBUG: A duplicate %%BoundingBox: comment was seen.\n", stderr); else if (strstr(line + 14, "(atend)")) { /* @@ -712,7 +710,7 @@ copy_comments(cups_file_t *fp, /* I - File to read from */ doc->bounding_box + 1, doc->bounding_box + 2, doc->bounding_box + 3) != 4) { - _cupsLangPuts(stderr, _("ERROR: Bad %%BoundingBox: comment seen\n")); + fputs("DEBUG: A bad %%BoundingBox: comment was seen.\n", stderr); doc->bounding_box[0] = (int)PageLeft; doc->bounding_box[1] = (int)PageBottom; @@ -763,11 +761,12 @@ copy_comments(cups_file_t *fp, /* I - File to read from */ break; } - if (!saw_bounding_box) - _cupsLangPuts(stderr, _("ERROR: No %%BoundingBox: comment in header\n")); + if (!saw_bounding_box) + fputs("DEBUG: There wasn't a %%BoundingBox: comment in the header.\n", + stderr); - if (!saw_pages) - _cupsLangPuts(stderr, _("ERROR: No %%Pages: comment in header\n")); + if (!saw_pages) + fputs("DEBUG: There wasn't a %%Pages: comment in the header.\n", stderr); if (!saw_for) WriteTextComment("For", doc->user); @@ -1100,10 +1099,8 @@ copy_non_dsc(cups_file_t *fp, /* I - File to read from */ * that may not print correctly... */ - _cupsLangPuts(stderr, - _("WARNING: This document does not conform to the Adobe " - "Document Structuring Conventions and may not print " - "correctly\n")); + fputs("DEBUG: This document does not conform to the Adobe Document " + "Structuring Conventions and may not print correctly.\n", stderr); /* * Then write a standard DSC comment section... @@ -1291,13 +1288,13 @@ copy_page(cups_file_t *fp, /* I - File to read from */ if (!parse_text(line + 7, &ptr, label, sizeof(label))) { - _cupsLangPuts(stderr, _("ERROR: Bad %%Page: comment in file\n")); + fputs("DEBUG: There was a bad %%Page: comment in the file.\n", stderr); label[0] = '\0'; number = doc->page; } else if (strtol(ptr, &ptr, 10) == LONG_MAX || !isspace(*ptr & 255)) { - _cupsLangPuts(stderr, _("ERROR: Bad %%Page: comment in file\n")); + fputs("DEBUG: There was a bad %%Page: comment in the file.\n", stderr); number = doc->page; } @@ -1391,8 +1388,7 @@ copy_page(cups_file_t *fp, /* I - File to read from */ bounding_box + 1, bounding_box + 2, bounding_box + 3) != 4) { - _cupsLangPuts(stderr, - _("ERROR: Bad %%PageBoundingBox: comment in file\n")); + fputs("DEBUG: There was a bad %%PageBoundingBox: comment in the file.\n", stderr); memcpy(bounding_box, doc->bounding_box, sizeof(bounding_box)); } @@ -1799,8 +1795,8 @@ copy_prolog(cups_file_t *fp, /* I - File to read from */ if (!strncmp(line, "%%EndProlog", 11)) linelen = cupsFileGetLine(fp, line, linesize); - else - _cupsLangPuts(stderr, _("ERROR: Missing %%EndProlog\n")); + else + fputs("DEBUG: The %%EndProlog comment is missing.\n", stderr); } doc_puts(doc, "%%EndProlog\n"); @@ -1870,8 +1866,8 @@ copy_setup(cups_file_t *fp, /* I - File to read from */ if (!strncmp(line, "%%EndSetup", 10)) linelen = cupsFileGetLine(fp, line, linesize); - else - _cupsLangPuts(stderr, _("ERROR: Missing %%EndSetup\n")); + else + fputs("DEBUG: The %%EndSetup comment is missing.\n", stderr); } if (num_options > 0) @@ -2249,7 +2245,7 @@ include_feature( if (sscanf(line + 17, "%254s%254s", name, value) != 2) { - _cupsLangPuts(stderr, _("ERROR: Bad %%IncludeFeature: comment\n")); + fputs("DEBUG: The %%IncludeFeature: comment is not valid.\n", stderr); return (num_options); } @@ -2755,7 +2751,7 @@ set_pstops_options( if ((doc->temp = cupsTempFile2(doc->tempfile, sizeof(doc->tempfile))) == NULL) { - _cupsLangPrintError(_("ERROR: Unable to create temporary file")); + perror("DEBUG: Unable to create temporary file"); exit(1); } } diff --git a/filter/raster.c b/filter/raster.c index dedc30325..c6d2fec3b 100644 --- a/filter/raster.c +++ b/filter/raster.c @@ -1,9 +1,9 @@ /* * "$Id: raster.c 7720 2008-07-11 22:46:21Z mike $" * - * Raster file routines for the Common UNIX Printing System (CUPS). + * Raster file routines for CUPS. * - * Copyright 2007-2008 by Apple Inc. + * Copyright 2007-2010 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * This file is part of the CUPS Imaging library. @@ -915,6 +915,7 @@ cups_raster_update(cups_raster_t *r) /* I - Raster stream */ case CUPS_CSPACE_WHITE : case CUPS_CSPACE_GOLD : case CUPS_CSPACE_SILVER : + case CUPS_CSPACE_SW : r->header.cupsNumColors = 1; break; @@ -923,6 +924,8 @@ cups_raster_update(cups_raster_t *r) /* I - Raster stream */ case CUPS_CSPACE_YMC : case CUPS_CSPACE_CIEXYZ : case CUPS_CSPACE_CIELab : + case CUPS_CSPACE_SRGB : + case CUPS_CSPACE_ADOBERGB : case CUPS_CSPACE_ICC1 : case CUPS_CSPACE_ICC2 : case CUPS_CSPACE_ICC3 : @@ -957,6 +960,25 @@ cups_raster_update(cups_raster_t *r) /* I - Raster stream */ else r->header.cupsNumColors = 4; break; + + case CUPS_CSPACE_DEVICE1 : + case CUPS_CSPACE_DEVICE2 : + case CUPS_CSPACE_DEVICE3 : + case CUPS_CSPACE_DEVICE4 : + case CUPS_CSPACE_DEVICE5 : + case CUPS_CSPACE_DEVICE6 : + case CUPS_CSPACE_DEVICE7 : + case CUPS_CSPACE_DEVICE8 : + case CUPS_CSPACE_DEVICE9 : + case CUPS_CSPACE_DEVICEA : + case CUPS_CSPACE_DEVICEB : + case CUPS_CSPACE_DEVICEC : + case CUPS_CSPACE_DEVICED : + case CUPS_CSPACE_DEVICEE : + case CUPS_CSPACE_DEVICEF : + r->header.cupsNumColors = r->header.cupsColorSpace - + CUPS_CSPACE_DEVICE1 + 1; + break; } } diff --git a/filter/rastertoepson.c b/filter/rastertoepson.c index e1d08ac30..f93b9bb33 100644 --- a/filter/rastertoepson.c +++ b/filter/rastertoepson.c @@ -1030,8 +1030,21 @@ main(int argc, /* I - Number of command-line arguments */ */ ppd = ppdOpenFile(getenv("PPD")); - if (ppd) - Model = ppd->model_number; + if (!ppd) + { + ppd_status_t status; /* PPD error */ + int linenum; /* Line number */ + + _cupsLangPrintf(stderr, _("ERROR: The PPD file could not be opened.\n")); + + status = ppdLastError(&linenum); + + fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum); + + return (1); + } + + Model = ppd->model_number; Setup(); @@ -1123,7 +1136,7 @@ main(int argc, /* I - Number of command-line arguments */ if (page == 0) { - _cupsLangPuts(stderr, _("ERROR: No pages found\n")); + _cupsLangPuts(stderr, _("ERROR: No pages were found.\n")); return (1); } else diff --git a/filter/rastertohp.c b/filter/rastertohp.c index 059a2e010..e39194f62 100644 --- a/filter/rastertohp.c +++ b/filter/rastertohp.c @@ -756,6 +756,19 @@ main(int argc, /* I - Number of command-line arguments */ */ ppd = ppdOpenFile(getenv("PPD")); + if (!ppd) + { + ppd_status_t status; /* PPD error */ + int linenum; /* Line number */ + + _cupsLangPrintf(stderr, _("ERROR: The PPD file could not be opened.\n")); + + status = ppdLastError(&linenum); + + fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum); + + return (1); + } Setup(); @@ -852,7 +865,7 @@ main(int argc, /* I - Number of command-line arguments */ if (Page == 0) { - _cupsLangPuts(stderr, _("ERROR: No pages found\n")); + _cupsLangPuts(stderr, _("ERROR: No pages were found.\n")); return (1); } else diff --git a/filter/rastertolabel.c b/filter/rastertolabel.c index e69008917..917c0e381 100644 --- a/filter/rastertolabel.c +++ b/filter/rastertolabel.c @@ -1180,12 +1180,24 @@ main(int argc, /* I - Number of command-line arguments */ num_options = cupsParseOptions(argv[5], 0, &options); - if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL) + ppd = ppdOpenFile(getenv("PPD")); + if (!ppd) { - ppdMarkDefaults(ppd); - cupsMarkOptions(ppd, num_options, options); + ppd_status_t status; /* PPD error */ + int linenum; /* Line number */ + + _cupsLangPrintf(stderr, _("ERROR: The PPD file could not be opened.\n")); + + status = ppdLastError(&linenum); + + fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum); + + return (1); } + ppdMarkDefaults(ppd); + cupsMarkOptions(ppd, num_options, options); + /* * Initialize the print device... */ @@ -1279,7 +1291,7 @@ main(int argc, /* I - Number of command-line arguments */ if (Page == 0) { - _cupsLangPuts(stderr, _("ERROR: No pages found\n")); + _cupsLangPuts(stderr, _("ERROR: No pages were found.\n")); return (1); } else diff --git a/filter/texttops.c b/filter/texttops.c index 62117ad5e..bc3a9871e 100644 --- a/filter/texttops.c +++ b/filter/texttops.c @@ -176,13 +176,25 @@ WriteProlog(const char *title, /* I - Title of job */ if (SizeColumns <= 0 || SizeColumns > 32767 || SizeLines <= 0 || SizeLines > 32767) { - _cupsLangPrintf(stderr, _("ERROR: Unable to print %dx%d text page\n"), + _cupsLangPrintf(stderr, _("ERROR: Unable to print %dx%d text page.\n"), + SizeColumns, SizeLines); + exit(1); + } + + if ((Page = calloc(sizeof(lchar_t *), SizeLines)) == NULL) + { + _cupsLangPrintf(stderr, _("ERROR: Unable to print %dx%d text page.\n"), + SizeColumns, SizeLines); + exit(1); + } + + if ((Page[0] = calloc(sizeof(lchar_t), SizeColumns * SizeLines)) == NULL) + { + _cupsLangPrintf(stderr, _("ERROR: Unable to print %dx%d text page.\n"), SizeColumns, SizeLines); exit(1); } - Page = calloc(sizeof(lchar_t *), SizeLines); - Page[0] = calloc(sizeof(lchar_t), SizeColumns * SizeLines); for (i = 1; i < SizeLines; i ++) Page[i] = Page[0] + i * SizeColumns; diff --git a/man/Makefile b/man/Makefile index 12dd67510..0d3c2edff 100644 --- a/man/Makefile +++ b/man/Makefile @@ -49,7 +49,6 @@ MAN5 = classes.conf.$(MAN5EXT) \ printers.conf.$(MAN5EXT) \ subscriptions.conf.$(MAN5EXT) MAN7 = backend.$(MAN7EXT) \ - drv.$(MAN7EXT) \ filter.$(MAN7EXT) \ notifier.$(MAN7EXT) MAN8 = cupsaccept.$(MAN8EXT) \ diff --git a/man/drv.man.in b/man/drv.man.in deleted file mode 100644 index d28a58877..000000000 --- a/man/drv.man.in +++ /dev/null @@ -1,40 +0,0 @@ -.\" -.\" "$Id$" -.\" -.\" drv man page for the Common UNIX Printing System. -.\" -.\" Copyright 2008-2009 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/". -.\" -.TH drv 1 "CUPS" "9 March 2009" "Apple Inc." -.SH NAME -drv \- cups driver interface for ppd compiler files -.SH SYNOPSIS -.B drv list -.br -.B drv cat -.I drv:///filename.drv/pcfilename -.SH DESCRIPTION -\fIdrv\fR lists and compiles PPDC source files installed in the -@CUPS_DATADIR@/drv and (on Mac OS X) /Library/Printers/PPDs/Contents/Resources -directories on behalf of the scheduler, \fIcupsd(8)\fR. -.PP -The first form of the command lists all of the PPD files that can be produced -by the driver information files in the two directories. -.PP -The second form of the command compiles the requested PPD and sends it to the -standard output. -.SH SEE ALSO -ppdc(1), ppdhtml(1), ppdi(1), ppdmerge(1), ppdpo(1), ppdcfile(5) -.br -http://localhost:631/help -.SH COPYRIGHT -Copyright 2008-2009 by Apple Inc. -.\" -.\" End of "$Id$". -.\" diff --git a/notifier/mailto.c b/notifier/mailto.c index 0c9b8a6fd..8a2d2d386 100644 --- a/notifier/mailto.c +++ b/notifier/mailto.c @@ -368,8 +368,10 @@ email_message(const char *to, /* I - Recipient of message */ fputs("DEBUG: QUIT\n", stderr); if (!cupsFileGets(fp, response, sizeof(response)) || atoi(response) >= 500) - goto smtp_error; - fprintf(stderr, "DEBUG: <<< %s\n", response); + fprintf(stderr, "ERROR: Got \"%s\" trying to QUIT connection.\n", + response); + else + fprintf(stderr, "DEBUG: <<< %s\n", response); cupsFileClose(fp); diff --git a/packaging/cups.list.in b/packaging/cups.list.in index 6abdfe4b3..79b996edf 100644 --- a/packaging/cups.list.in +++ b/packaging/cups.list.in @@ -718,8 +718,6 @@ f 0444 root sys $MANDIR/man5/mime.convs.$MAN5EXT man/mime.convs.$MAN5EXT f 0444 root sys $MANDIR/man5/mime.types.$MAN5EXT man/mime.types.$MAN5EXT f 0444 root sys $MANDIR/man5/printers.conf.$MAN5EXT man/printers.conf.$MAN5EXT -f 0444 root sys $MANDIR/man7/drv.$MAN7EXT man/drv.$MAN7EXT - l 0644 root sys $AMANDIR/man$MAN8DIR/accept.$MAN8EXT cupsaccept.$MAN8EXT f 0444 root sys $AMANDIR/man$MAN8DIR/cupsaccept.$MAN8EXT man/cupsaccept.$MAN8EXT l 0644 root sys $AMANDIR/man$MAN8DIR/cupsreject.$MAN8EXT cupsaccept.$MAN8EXT diff --git a/ppdc/ppdc-source.cxx b/ppdc/ppdc-source.cxx index 3530fed96..f68d1db9e 100644 --- a/ppdc/ppdc-source.cxx +++ b/ppdc/ppdc-source.cxx @@ -1363,17 +1363,17 @@ ppdcSource::get_integer(const char *v) // I - Value string while (isspace(*newv & 255)) newv ++; - if (strncmp(newv, "==", 2)) + if (!strncmp(newv, "==", 2)) { compop = PPDC_EQ; newv += 2; } - else if (strncmp(newv, "!=", 2)) + else if (!strncmp(newv, "!=", 2)) { compop = PPDC_NE; newv += 2; } - else if (strncmp(newv, "<=", 2)) + else if (!strncmp(newv, "<=", 2)) { compop = PPDC_LE; newv += 2; @@ -1383,7 +1383,7 @@ ppdcSource::get_integer(const char *v) // I - Value string compop = PPDC_LT; newv ++; } - else if (strncmp(newv, ">=", 2)) + else if (!strncmp(newv, ">=", 2)) { compop = PPDC_GE; newv += 2; @@ -1404,7 +1404,7 @@ ppdcSource::get_integer(const char *v) // I - Value string if (*newv == ')' || !*newv) return (-1); - if (isdigit(*v & 255) || *v == '-' || *v == '+') + if (isdigit(*newv & 255) || *newv == '-' || *newv == '+') { // Get the second number... temp2 = strtol(newv, &newv, 0); @@ -2045,8 +2045,8 @@ ppdcSource::get_token(ppdcFile *fp, // I - File to read var = find_variable(name); if (var) { - strncpy(bufptr, var->value->value, bufend - bufptr); - bufptr += strlen(var->value->value); + strlcpy(bufptr, var->value->value, bufend - bufptr + 1); + bufptr += strlen(bufptr); } else { @@ -2056,7 +2056,7 @@ ppdcSource::get_token(ppdcFile *fp, // I - File to read "%s.\n"), name, fp->line, fp->filename); snprintf(bufptr, bufend - bufptr + 1, "$%s", name); - bufptr += strlen(name) + 1; + bufptr += strlen(bufptr); } } } diff --git a/scheduler/auth.c b/scheduler/auth.c index 246130197..73a0c98c4 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -962,6 +962,67 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ con->type = CUPSD_AUTH_DIGEST; } #ifdef HAVE_GSSAPI +# ifdef HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID + else if (con->http.hostaddr->addr.sa_family == AF_LOCAL && + !strncmp(authorization, "Negotiate", 9)) + { + /* + * Pull the credentials directly from the user... + */ + + krb5_error_code error; /* Kerberos error code */ + cupsd_ucred_t peercred; /* Peer credentials */ + socklen_t peersize; /* Size of peer credentials */ + krb5_ccache peerccache; /* Peer Kerberos credentials */ + const char *peername; /* Peer username */ + + peersize = sizeof(peercred); + +# ifdef __APPLE__ + if (getsockopt(con->http.fd, 0, LOCAL_PEERCRED, &peercred, &peersize)) +# else + if (getsockopt(con->http.fd, SOL_SOCKET, SO_PEERCRED, &peercred, &peersize)) +# endif /* __APPLE__ */ + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to get peer credentials - %s", + strerror(errno)); + return; + } + + cupsdLogMessage(CUPSD_LOG_DEBUG, + "cupsdAuthorize: Copying credentials for UID %d...", + CUPSD_UCRED_UID(peercred)); + + krb5_ipc_client_set_target_uid(CUPSD_UCRED_UID(peercred)); + + if ((error = krb5_cc_default(KerberosContext, &peerccache)) != 0) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to get credentials cache for UID %d (%d/%s)", + (int)CUPSD_UCRED_UID(peercred), error, strerror(errno)); + return; + } + + if ((peername = krb5_cc_get_name(KerberosContext, peerccache)) != NULL) + { + strlcpy(username, peername, sizeof(username)); + + con->have_gss = 1; + con->type = CUPSD_AUTH_NEGOTIATE; + + cupsdLogMessage(CUPSD_LOG_DEBUG, + "cupsdAuthorize: Authorized as %s using Negotiate", + username); + } + else + cupsdLogMessage(CUPSD_LOG_ERROR, + "Unable to get Kerberos name for UID %d", + (int)CUPSD_UCRED_UID(peercred)); + + krb5_cc_close(KerberosContext, peerccache); + krb5_ipc_client_clear_target(); + } +# endif /* HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID */ else if (!strncmp(authorization, "Negotiate", 9)) { int len; /* Length of authorization string */ @@ -1003,7 +1064,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (!*authorization) { cupsdLogMessage(CUPSD_LOG_DEBUG2, - "cupsdAuthorize: No authentication data specified."); + "cupsdAuthorize: No authentication data specified."); return; } @@ -1014,7 +1075,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ len = strlen(authorization); input_token.value = malloc(len); input_token.value = httpDecode64_2(input_token.value, &len, - authorization); + authorization); input_token.length = len; /* @@ -1038,7 +1099,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (GSS_ERROR(major_status)) { cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, - "cupsdAuthorize: Error accepting GSSAPI security " + "cupsdAuthorize: Error accepting GSSAPI security " "context"); if (context != GSS_C_NO_CONTEXT) @@ -1054,7 +1115,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (!con->gss_creds) cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdAuthorize: No delegated credentials!"); + "cupsdAuthorize: No delegated credentials!"); if (major_status == GSS_S_CONTINUE_NEEDED) cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, @@ -1067,7 +1128,7 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ if (GSS_ERROR(major_status)) { cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, - "cupsdAuthorize: Error getting username"); + "cupsdAuthorize: Error getting username"); gss_release_cred(&minor_status, &con->gss_creds); gss_release_name(&minor_status, &client_name); gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER); diff --git a/scheduler/client.c b/scheduler/client.c index 2400b57fe..631bc9eee 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -54,19 +54,25 @@ #ifdef HAVE_CDSASSL # include <Security/Security.h> +# include <Security/SecItem.h> +# ifdef HAVE_SECITEMPRIV_H +# include <Security/SecItemPriv.h> +# else /* Declare constant from that header... */ +extern const CFTypeRef kSecClassIdentity; +# endif /* HAVE_SECITEMPRIV_H */ # ifdef HAVE_SECIDENTITYSEARCHPRIV_H # include <Security/SecIdentitySearchPriv.h> # else /* Declare prototype for function in that header... */ -extern OSStatus SecIdentitySearchCreateWithPolicy(SecPolicyRef policy, - CFStringRef idString, CSSM_KEYUSE keyUsage, - CFTypeRef keychainOrArray, - Boolean returnOnlyValidIdentities, +extern OSStatus SecIdentitySearchCreateWithPolicy(SecPolicyRef policy, + CFStringRef idString, CSSM_KEYUSE keyUsage, + CFTypeRef keychainOrArray, + Boolean returnOnlyValidIdentities, SecIdentitySearchRef* searchRef); # endif /* HAVE_SECIDENTITYSEARCHPRIV_H */ # ifdef HAVE_SECPOLICYPRIV_H # include <Security/SecPolicyPriv.h> # else /* Declare prototype for function in that header... */ -extern OSStatus SecPolicySetValue(SecPolicyRef policyRef, +extern OSStatus SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value); # endif /* HAVE_SECPOLICYPRIV_H */ # ifdef HAVE_SECBASEPRIV_H @@ -3353,49 +3359,125 @@ get_cdsa_certificate( cupsd_client_t *con) /* I - Client connection */ { OSStatus err; /* Error info */ - SecKeychainRef keychain; /* Keychain reference */ - SecIdentitySearchRef search; /* Search reference */ - SecIdentityRef identity; /* Identity */ + SecKeychainRef keychain = NULL;/* Keychain reference */ + SecIdentitySearchRef search = NULL; /* Search reference */ + SecIdentityRef identity = NULL;/* Identity */ CFArrayRef certificates = NULL; /* Certificate array */ +# if HAVE_SECPOLICYCREATESSL + SecPolicyRef policy = NULL; /* Policy ref */ + CFStringRef servername = NULL; + /* Server name */ + CFMutableDictionaryRef query = NULL; /* Query qualifiers */ + char localname[1024];/* Local hostname */ +# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) + SecPolicyRef policy = NULL; /* Policy ref */ + SecPolicySearchRef policy_search = NULL; + /* Policy search ref */ + CSSM_DATA options; /* Policy options */ + CSSM_APPLE_TP_SSL_OPTIONS + ssl_options; /* SSL Option for hostname */ + char localname[1024];/* Local hostname */ +# endif /* HAVE_SECPOLICYCREATESSL */ + + cupsdLogMessage(CUPSD_LOG_DEBUG, + "get_cdsa_certificate: Looking for certs for \"%s\"...", + con->servername); if ((err = SecKeychainOpen(ServerCertificate, &keychain))) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot open keychain \"%s\" - %s (%d)", ServerCertificate, cssmErrorString(err), (int)err); - return (NULL); + goto cleanup; + } + +# if HAVE_SECPOLICYCREATESSL + servername = CFStringCreateWithCString(kCFAllocatorDefault, con->servername, + kCFStringEncodingUTF8); + + if ((policy = SecPolicyCreateSSL(1, servername)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); + goto cleanup; + } + + if (servername) + CFRelease(servername); + + if (!(query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, + &kCFTypeDictionaryKeyCallBacks, + &kCFTypeDictionaryValueCallBacks))) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create query dictionary"); + goto cleanup; + } + + CFDictionaryAddValue(query, kSecClass, kSecClassIdentity); + CFDictionaryAddValue(query, kSecMatchPolicy, policy); + CFDictionaryAddValue(query, kSecReturnRef, kCFBooleanTrue); + CFDictionaryAddValue(query, kSecMatchLimit, kSecMatchLimitOne); + + err = SecItemCopyMatching(query, (CFTypeRef *)&identity); + + if (err && DNSSDHostName) + { + /* + * Search for the connection server name failed; try the DNS-SD .local + * hostname instead... + */ + + snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); + + cupsdLogMessage(CUPSD_LOG_DEBUG, + "get_cdsa_certificate: Looking for certs for \"%s\"...", + localname); + + servername = CFStringCreateWithCString(kCFAllocatorDefault, localname, + kCFStringEncodingUTF8); + + CFRelease(policy); + + if ((policy = SecPolicyCreateSSL(1, servername)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create ssl policy reference"); + goto cleanup; + } + + if (servername) + CFRelease(servername); + + CFDictionarySetValue(query, kSecMatchPolicy, policy); + + err = SecItemCopyMatching(query, (CFTypeRef *)&identity); } -# if HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY + if (err) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Cannot find signing key in keychain \"%s\": %s (%d)", + ServerCertificate, cssmErrorString(err), (int)err); + goto cleanup; + } + +# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) /* * Use a policy to search for valid certificates who's common name matches the * servername... */ - SecPolicySearchRef policy_search; /* Policy search ref */ - SecPolicyRef policy; /* Policy ref */ - CSSM_DATA options; /* Policy options */ - CSSM_APPLE_TP_SSL_OPTIONS - ssl_options; /* SSL Option for hostname */ - char localname[1024];/* Local hostname */ - - - if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL, + if (SecPolicySearchCreate(CSSM_CERT_X_509v3, &CSSMOID_APPLE_TP_SSL, NULL, &policy_search)) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create a policy search reference"); - CFRelease(keychain); - return (NULL); + goto cleanup; } if (SecPolicySearchCopyNext(policy_search, &policy)) { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot find a policy to use for searching"); - CFRelease(keychain); - CFRelease(policy_search); - return (NULL); + goto cleanup; } memset(&ssl_options, 0, sizeof(ssl_options)); @@ -3403,10 +3485,6 @@ get_cdsa_certificate( ssl_options.ServerName = con->servername; ssl_options.ServerNameLen = strlen(con->servername); - cupsdLogMessage(CUPSD_LOG_DEBUG, - "get_cdsa_certificate: Looking for certs for \"%s\"...", - con->servername); - options.Data = (uint8 *)&ssl_options; options.Length = sizeof(ssl_options); @@ -3414,13 +3492,20 @@ get_cdsa_certificate( { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot set policy value to use for searching"); - CFRelease(keychain); - CFRelease(policy_search); - return (NULL); + goto cleanup; } - err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN, - keychain, FALSE, &search); + if ((err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN, + keychain, FALSE, &search))) + { + cupsdLogMessage(CUPSD_LOG_ERROR, + "Cannot create identity search reference: %s (%d)", + cssmErrorString(err), (int)err); + goto cleanup; + } + + err = SecIdentitySearchCopyNext(search, &identity); + if (err && DNSSDHostName) { /* @@ -3441,13 +3526,18 @@ get_cdsa_certificate( { cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot set policy value to use for searching"); - CFRelease(keychain); - CFRelease(policy_search); - return (NULL); + goto cleanup; } - err = SecIdentitySearchCreateWithPolicy(policy, NULL, CSSM_KEYUSE_SIGN, - keychain, FALSE, &search); + err = SecIdentitySearchCopyNext(search, &identity); + } + + if (err) + { + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Cannot find signing key in keychain \"%s\": %s (%d)", + ServerCertificate, cssmErrorString(err), (int)err); + goto cleanup; } # else @@ -3455,43 +3545,56 @@ get_cdsa_certificate( * Assume there is exactly one SecIdentity in the keychain... */ - err = SecIdentitySearchCreate(keychain, CSSM_KEYUSE_SIGN, &search); -# endif /* HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY */ - - if (err) + if ((err = SecIdentitySearchCreate(keychain, CSSM_KEYUSE_SIGN, &search))) + { cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot create keychain search reference: %s (%d)", - cssmErrorString(err), (int)err); - else + "Cannot create identity search reference (%d)", (int)err); + goto cleanup; + } + + if ((err = SecIdentitySearchCopyNext(search, &identity))) { - if ((err = SecIdentitySearchCopyNext(search, &identity))) - { - cupsdLogMessage(CUPSD_LOG_DEBUG, - "Cannot find signing key in keychain \"%s\": %s (%d)", - ServerCertificate, cssmErrorString(err), (int)err); - } - else - { - if (CFGetTypeID(identity) != SecIdentityGetTypeID()) - cupsdLogMessage(CUPSD_LOG_ERROR, - "SecIdentitySearchCopyNext CFTypeID failure!"); - else - { - if ((certificates = CFArrayCreate(NULL, (const void **)&identity, - 1, &kCFTypeArrayCallBacks)) == NULL) - cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array"); - } + cupsdLogMessage(CUPSD_LOG_DEBUG, + "Cannot find signing key in keychain \"%s\": %s (%d)", + ServerCertificate, cssmErrorString(err), (int)err); + goto cleanup; + } +# endif /* HAVE_SECPOLICYCREATESSL */ - CFRelease(identity); - } + if (CFGetTypeID(identity) != SecIdentityGetTypeID()) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "SecIdentity CFTypeID failure!"); + goto cleanup; + } - CFRelease(search); + if ((certificates = CFArrayCreate(NULL, (const void **)&identity, + 1, &kCFTypeArrayCallBacks)) == NULL) + { + cupsdLogMessage(CUPSD_LOG_ERROR, "Cannot create certificate array"); + goto cleanup; } -# if HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY - CFRelease(policy); - CFRelease(policy_search); -# endif /* HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY */ + cleanup : + + if (keychain) + CFRelease(keychain); + if (search) + CFRelease(search); + if (identity) + CFRelease(identity); + +# if HAVE_SECPOLICYCREATESSL + if (policy) + CFRelease(policy); + if (query) + CFRelease(query); + +# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) + if (policy) + CFRelease(policy); + if (policy_search) + CFRelease(policy_search); +# endif /* HAVE_SECPOLICYCREATESSL */ return (certificates); } @@ -4504,7 +4607,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ char argbuf[10240], /* Argument buffer */ *argv[100], /* Argument strings */ *envp[MAX_ENV + 20]; /* Environment variables */ - char auth_type[256], /* CUPSD_AUTH_TYPE environment variable */ + char auth_type[256], /* AUTH_TYPE environment variable */ content_length[1024], /* CONTENT_LENGTH environment variable */ content_type[1024], /* CONTENT_TYPE environment variable */ http_cookie[32768], /* HTTP_COOKIE environment variable */ @@ -4550,7 +4653,12 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ argv[0] = command; if (options) - strlcpy(argbuf, options, sizeof(argbuf)); + { + commptr = options; + if (*commptr == ' ') + commptr ++; + strlcpy(argbuf, commptr, sizeof(argbuf)); + } else argbuf[0] = '\0'; @@ -4649,7 +4757,7 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ if (con->username[0]) { - snprintf(auth_type, sizeof(auth_type), "CUPSD_AUTH_TYPE=%s", + snprintf(auth_type, sizeof(auth_type), "AUTH_TYPE=%s", httpGetField(HTTP(con), HTTP_FIELD_AUTHORIZATION)); if ((uriptr = strchr(auth_type + 10, ' ')) != NULL) diff --git a/scheduler/conf.c b/scheduler/conf.c index a69e224d4..a10f1cdb3 100644 --- a/scheduler/conf.c +++ b/scheduler/conf.c @@ -1167,6 +1167,19 @@ cupsdReadConfiguration(void) cupsdLogMessage(CUPSD_LOG_INFO, "<Policy default>"); cupsdLogMessage(CUPSD_LOG_INFO, + "<Limit Create-Job Print-Job Print-URI Validate-Job>"); + cupsdLogMessage(CUPSD_LOG_INFO, "Order Deny,Allow"); + + po = cupsdAddPolicyOp(p, NULL, IPP_CREATE_JOB); + po->order_type = CUPSD_AUTH_ALLOW; + + cupsdAddPolicyOp(p, po, IPP_PRINT_JOB); + cupsdAddPolicyOp(p, po, IPP_PRINT_URI); + cupsdAddPolicyOp(p, po, IPP_VALIDATE_JOB); + + cupsdLogMessage(CUPSD_LOG_INFO, "</Limit>"); + + cupsdLogMessage(CUPSD_LOG_INFO, "<Limit Send-Document Send-URI Cancel-Job Hold-Job " "Release-Job Restart-Job Purge-Jobs " "Set-Job-Attributes Create-Job-Subscription " @@ -3682,11 +3695,30 @@ read_policy(cups_file_t *fp, /* I - Configuration file */ linenum); /* - * Verify that we have an explicit policy for Cancel-Jobs, Cancel-My-Jobs, - * Close-Job, and CUPS-Get-Document (ensures that upgrades do not - * introduce new security issues...) + * Verify that we have an explicit policy for Validate-Job, Cancel-Jobs, + * Cancel-My-Jobs, Close-Job, and CUPS-Get-Document, which ensures that + * upgrades do not introduce new security issues... */ + if ((op = cupsdFindPolicyOp(pol, IPP_VALIDATE_JOB)) == NULL || + op->op == IPP_ANY_OPERATION) + { + if ((op = cupsdFindPolicyOp(pol, IPP_PRINT_JOB)) != NULL && + op->op != IPP_ANY_OPERATION) + { + /* + * Add a new limit for Validate-Job using the Print-Job limit as a + * template... + */ + + cupsdLogMessage(CUPSD_LOG_WARN, + "No limit for Validate-Job defined in policy %s " + "- using Print-Job's policy", pol->name); + + cupsdAddPolicyOp(pol, op, IPP_VALIDATE_JOB); + } + } + if ((op = cupsdFindPolicyOp(pol, IPP_CANCEL_JOBS)) == NULL || op->op == IPP_ANY_OPERATION) { diff --git a/scheduler/cups.xml.in b/scheduler/cups.xml.in index 81aa0b3ba..211c086b7 100644 --- a/scheduler/cups.xml.in +++ b/scheduler/cups.xml.in @@ -116,6 +116,10 @@ type='service' version='1'> + <restarter> + <service_fmri value='svc:/network/inetd:default' /> + </restarter> + <dependency name='filesystem_minimal' grouping='require_all' @@ -155,10 +159,6 @@ timeout_seconds='60' /> <instance name='default' enabled='false' > - <restarter> - <service_fmri value='svc:/network/inetd:default' /> - </restarter> - <dependency name='cupsd' grouping='require_all' diff --git a/scheduler/ipp.c b/scheduler/ipp.c index 3fcabd681..9cc8fbc84 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -1257,7 +1257,7 @@ add_class(cupsd_client_t *con, /* I - Client connection */ if (modify) { - cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED | CUPSD_EVENT_PRINTER_CONFIG, + cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, pclass, NULL, "Class \"%s\" modified by \"%s\".", pclass->name, get_username(con)); @@ -1268,7 +1268,7 @@ add_class(cupsd_client_t *con, /* I - Client connection */ { cupsdAddPrinterHistory(pclass); - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED | CUPSD_EVENT_PRINTER_CONFIG, + cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, pclass, NULL, "New class \"%s\" added by \"%s\".", pclass->name, get_username(con)); @@ -1536,22 +1536,10 @@ add_job(cupsd_client_t *con, /* I - Client connection */ * Do media selection as needed... */ - if (!ippFindAttribute(con->request, "InputSlot", IPP_TAG_ZERO) && - (ppd = _pwgGetInputSlot(printer->pwg, con->request, NULL)) != NULL) - ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "InputSlot", NULL, - ppd); - - if (!ippFindAttribute(con->request, "MediaType", IPP_TAG_ZERO) && - (ppd = _pwgGetMediaType(printer->pwg, con->request, NULL)) != NULL) - ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "MediaType", NULL, - ppd); - - if (!ippFindAttribute(con->request, "PageSize", IPP_TAG_ZERO) && + if (!ippFindAttribute(con->request, "PageRegion", IPP_TAG_ZERO) && + !ippFindAttribute(con->request, "PageSize", IPP_TAG_ZERO) && (ppd = _pwgGetPageSize(printer->pwg, con->request, NULL, &exact)) != NULL) { - ippAddString(con->request, IPP_TAG_JOB, IPP_TAG_NAME, "PageSize", NULL, - ppd); - if (!exact && (media_col = ippFindAttribute(con->request, "media-col", IPP_TAG_BEGIN_COLLECTION)) != NULL) @@ -2951,7 +2939,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ { /* * If we changed the PPD/interface script, then remove the printer's cache - * file... + * file and clear the printer-state-reasons... */ char cache_name[1024]; /* Cache filename for printer attrs */ @@ -2964,6 +2952,8 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ printer->name); unlink(cache_name); + cupsdSetPrinterReasons(printer, "none"); + #ifdef __APPLE__ /* * (Re)register color profiles... @@ -3040,7 +3030,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ if (modify) { - cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED | CUPSD_EVENT_PRINTER_CONFIG, + cupsdAddEvent(CUPSD_EVENT_PRINTER_MODIFIED, printer, NULL, "Printer \"%s\" modified by \"%s\".", printer->name, get_username(con)); @@ -3051,7 +3041,7 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ { cupsdAddPrinterHistory(printer); - cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED | CUPSD_EVENT_PRINTER_CONFIG, + cupsdAddEvent(CUPSD_EVENT_PRINTER_ADDED, printer, NULL, "New printer \"%s\" added by \"%s\".", printer->name, get_username(con)); @@ -9022,7 +9012,7 @@ print_job(cupsd_client_t *con, /* I - Client connection */ type) != 2) { send_ipp_status(con, IPP_BAD_REQUEST, - _("Could not scan type \"%s\""), + _("Bad document-format \"%s\""), format->values[0].string.text); return; } @@ -9038,7 +9028,7 @@ print_job(cupsd_client_t *con, /* I - Client connection */ if (sscanf(default_format, "%15[^/]/%31[^;]", super, type) != 2) { send_ipp_status(con, IPP_BAD_REQUEST, - _("Could not scan type \"%s\""), + _("Bad document-format \"%s\""), default_format); return; } @@ -9103,7 +9093,9 @@ print_job(cupsd_client_t *con, /* I - Client connection */ else if (!filetype) { send_ipp_status(con, IPP_DOCUMENT_FORMAT, - _("Unsupported format \'%s/%s\'"), super, type); + _("Unsupported document-format \"%s\""), + format ? format->values[0].string.text : + "application/octet-stream"); cupsdLogMessage(CUPSD_LOG_INFO, "Hint: Do you have the raw file printing rules enabled?"); @@ -11696,7 +11688,8 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ ipp_attribute_t *uri) /* I - Printer URI */ { http_status_t status; /* Policy status */ - ipp_attribute_t *attr; /* Current attribute */ + ipp_attribute_t *attr, /* Current attribute */ + *auth_info; /* auth-info attribute */ ipp_attribute_t *format; /* Document-format attribute */ cups_ptype_t dtype; /* Destination type (printer/class) */ char super[MIME_MAX_SUPER], @@ -11715,15 +11708,21 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ */ if ((attr = ippFindAttribute(con->request, "compression", - IPP_TAG_KEYWORD)) != NULL && - !strcmp(attr->values[0].string.text, "none")) + IPP_TAG_KEYWORD)) != NULL) { - send_ipp_status(con, IPP_ATTRIBUTES, - _("Unsupported compression attribute %s"), - attr->values[0].string.text); - ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD, - "compression", NULL, attr->values[0].string.text); - return; + if (strcmp(attr->values[0].string.text, "none") +#ifdef HAVE_LIBZ + && strcmp(attr->values[0].string.text, "gzip") +#endif /* HAVE_LIBZ */ + ) + { + send_ipp_status(con, IPP_ATTRIBUTES, + _("Unsupported compression \"%s\""), + attr->values[0].string.text); + ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_KEYWORD, + "compression", NULL, attr->values[0].string.text); + return; + } } /* @@ -11747,7 +11746,7 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ cupsdLogMessage(CUPSD_LOG_INFO, "Hint: Do you have the raw file printing rules enabled?"); send_ipp_status(con, IPP_DOCUMENT_FORMAT, - _("Unsupported format \"%s\""), + _("Unsupported document-format \"%s\""), format->values[0].string.text); ippAddString(con->response, IPP_TAG_UNSUPPORTED_GROUP, IPP_TAG_MIMETYPE, "document-format", NULL, format->values[0].string.text); @@ -11774,11 +11773,32 @@ validate_job(cupsd_client_t *con, /* I - Client connection */ * Check policy... */ + auth_info = ippFindAttribute(con->request, "auth-info", IPP_TAG_TEXT); + if ((status = cupsdCheckPolicy(printer->op_policy_ptr, con, NULL)) != HTTP_OK) { send_http_error(con, status, printer); return; } + else if (printer->num_auth_info_required == 1 && + !strcmp(printer->auth_info_required[0], "negotiate") && + !con->username[0]) + { + send_http_error(con, HTTP_UNAUTHORIZED, printer); + return; + } +#ifdef HAVE_SSL + else if (auth_info && !con->http.tls && + !httpAddrLocalhost(con->http.hostaddr)) + { + /* + * Require encryption of auth-info over non-local connections... + */ + + send_http_error(con, HTTP_UPGRADE_REQUIRED, printer); + return; + } +#endif /* HAVE_SSL */ /* * Everything was ok, so return OK status... diff --git a/scheduler/job.c b/scheduler/job.c index d5a47756f..9822ac581 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -173,7 +173,7 @@ static void free_job_history(cupsd_job_t *job); static char *get_options(cupsd_job_t *job, int banner_page, char *copies, size_t copies_size, char *title, size_t title_size); -static int ipp_length(ipp_t *ipp); +static size_t ipp_length(ipp_t *ipp); static void load_job_cache(const char *filename); static void load_next_job_id(const char *filename); static void load_request_root(void); @@ -3020,39 +3020,159 @@ get_options(cupsd_job_t *job, /* I - Job */ size_t title_size) /* I - Size of title buffer */ { int i; /* Looping var */ + size_t newlength; /* New option buffer length */ char *optptr, /* Pointer to options */ *valptr; /* Pointer in value string */ ipp_attribute_t *attr; /* Current attribute */ + _pwg_t *pwg; /* PWG->PPD mapping data */ + int num_pwgppds; /* Number of PWG->PPD options */ + cups_option_t *pwgppds, /* PWG->PPD options */ + *pwgppd, /* Current PWG->PPD option */ + *preset; /* Current preset option */ + int output_mode, /* Output mode (if any) */ + print_quality; /* Print quality (if any) */ + const char *ppd; /* PPD option choice */ + int exact; /* Did we get an exact match? */ static char *options = NULL;/* Full list of options */ - static int optlength = 0; /* Length of option buffer */ + static size_t optlength = 0; /* Length of option buffer */ /* - * Building the options string is harder than it needs to be, but - * for the moment we need to pass strings for command-line args and - * not IPP attribute pointers... :) + * Building the options string is harder than it needs to be, but for the + * moment we need to pass strings for command-line args and not IPP attribute + * pointers... :) * - * First allocate/reallocate the option buffer as needed... + * First build an options array for any PWG->PPD mapped option/choice pairs. */ - i = ipp_length(job->attrs); + pwg = job->printer->pwg; + num_pwgppds = 0; + pwgppds = NULL; - if (i > optlength || !options) + if (pwg) + { + if ((attr = ippFindAttribute(job->attrs, "output-mode", + IPP_TAG_KEYWORD)) != NULL && + !strcmp(attr->values[0].string.text, "monochrome")) + output_mode = _PWG_OUTPUT_MODE_MONOCHROME; + else + output_mode = _PWG_OUTPUT_MODE_COLOR; + + if ((attr = ippFindAttribute(job->attrs, "print-quality", + IPP_TAG_INTEGER)) != NULL && + attr->values[0].integer >= IPP_QUALITY_DRAFT && + attr->values[0].integer <= IPP_QUALITY_HIGH) + print_quality = attr->values[0].integer - IPP_QUALITY_DRAFT; + else + print_quality = IPP_QUALITY_NORMAL; + + if (pwg->num_presets[output_mode][print_quality] == 0) + { + /* + * Try to find a preset that works so that we maximize the chances of us + * getting a good print using IPP attributes. + */ + + if (pwg->num_presets[output_mode][_PWG_PRINT_QUALITY_NORMAL] > 0) + print_quality = _PWG_PRINT_QUALITY_NORMAL; + else if (pwg->num_presets[_PWG_OUTPUT_MODE_COLOR][print_quality] > 0) + output_mode = _PWG_OUTPUT_MODE_COLOR; + else + { + print_quality = _PWG_PRINT_QUALITY_NORMAL; + output_mode = _PWG_OUTPUT_MODE_COLOR; + } + } + + if (pwg->num_presets[output_mode][print_quality] > 0) + { + /* + * Copy the preset options as long as the corresponding names are not + * already defined in the IPP request... + */ + + for (i = pwg->num_presets[output_mode][print_quality], + preset = pwg->presets[output_mode][print_quality]; + i > 0; + i --, preset ++) + { + if (!ippFindAttribute(job->attrs, preset->name, IPP_TAG_ZERO)) + num_pwgppds = cupsAddOption(preset->name, preset->value, num_pwgppds, + &pwgppds); + } + } + + if (pwg->sides_option && + !ippFindAttribute(job->attrs, pwg->sides_option, IPP_TAG_ZERO) && + (attr = ippFindAttribute(job->attrs, "sides", IPP_TAG_KEYWORD)) != NULL) + { + /* + * Add a duplex option... + */ + + if (!strcmp(attr->values[0].string.text, "one-sided")) + num_pwgppds = cupsAddOption(pwg->sides_option, pwg->sides_1sided, + num_pwgppds, &pwgppds); + else if (!strcmp(attr->values[0].string.text, "two-sided-long-edge")) + num_pwgppds = cupsAddOption(pwg->sides_option, pwg->sides_2sided_long, + num_pwgppds, &pwgppds); + else if (!strcmp(attr->values[0].string.text, "two-sided-short-edge")) + num_pwgppds = cupsAddOption(pwg->sides_option, pwg->sides_2sided_short, + num_pwgppds, &pwgppds); + } + } + + if (!ippFindAttribute(job->attrs, "InputSlot", IPP_TAG_ZERO) && + (ppd = _pwgGetInputSlot(job->printer->pwg, job->attrs, NULL)) != NULL) + num_pwgppds = cupsAddOption("InputSlot", ppd, num_pwgppds, &pwgppds); + + if (!ippFindAttribute(job->attrs, "MediaType", IPP_TAG_ZERO) && + (ppd = _pwgGetMediaType(job->printer->pwg, job->attrs, NULL)) != NULL) + num_pwgppds = cupsAddOption("MediaType", ppd, num_pwgppds, &pwgppds); + + if (!ippFindAttribute(job->attrs, "PageRegion", IPP_TAG_ZERO) && + !ippFindAttribute(job->attrs, "PageSize", IPP_TAG_ZERO) && + (ppd = _pwgGetPageSize(job->printer->pwg, job->attrs, NULL, + &exact)) != NULL) + num_pwgppds = cupsAddOption("PageSize", ppd, num_pwgppds, &pwgppds); + + if (!ippFindAttribute(job->attrs, "OutputBin", IPP_TAG_ZERO) && + (attr = ippFindAttribute(job->attrs, "output-bin", + IPP_TAG_ZERO)) != NULL && + (attr->value_tag == IPP_TAG_KEYWORD || attr->value_tag == IPP_TAG_NAME) && + (ppd = _pwgGetOutputBin(pwg, attr->values[0].string.text)) != NULL) + num_pwgppds = cupsAddOption("OutputBin", ppd, num_pwgppds, &pwgppds); + + /* + * Figure out how much room we need... + */ + + newlength = ipp_length(job->attrs); + + for (i = num_pwgppds, pwgppd = pwgppds; i > 0; i --, pwgppd ++) + newlength += 1 + strlen(pwgppd->name) + 1 + strlen(pwgppd->value); + + /* + * Then allocate/reallocate the option buffer as needed... + */ + + if (newlength > optlength || !options) { if (!options) - optptr = malloc(i); + optptr = malloc(newlength); else - optptr = realloc(options, i); + optptr = realloc(options, newlength); if (!optptr) { cupsdLogJob(job, CUPSD_LOG_CRIT, - "Unable to allocate %d bytes for option buffer!", i); + "Unable to allocate " CUPS_LLFMT " bytes for option buffer!", + CUPS_LLCAST newlength); return (NULL); } options = optptr; - optlength = i; + optlength = newlength; } /* @@ -3088,7 +3208,8 @@ get_options(cupsd_job_t *job, /* I - Job */ * Filter out other unwanted attributes... */ - if (attr->value_tag == IPP_TAG_MIMETYPE || + if (attr->value_tag == IPP_TAG_NOVALUE || + attr->value_tag == IPP_TAG_MIMETYPE || attr->value_tag == IPP_TAG_NAMELANG || attr->value_tag == IPP_TAG_TEXTLANG || (attr->value_tag == IPP_TAG_URI && strcmp(attr->name, "job-uuid")) || @@ -3096,8 +3217,7 @@ get_options(cupsd_job_t *job, /* I - Job */ attr->value_tag == IPP_TAG_BEGIN_COLLECTION) /* Not yet supported */ continue; - if (!strncmp(attr->name, "time-", 5) || - !strcmp(attr->name, "job-hold-until")) + if (!strcmp(attr->name, "job-hold-until")) continue; if (!strncmp(attr->name, "job-", 4) && @@ -3155,11 +3275,6 @@ get_options(cupsd_job_t *job, /* I - Job */ if (!attr->values[i].boolean) strlcat(optptr, "no", optlength - (optptr - options)); - case IPP_TAG_NOVALUE : - strlcat(optptr, attr->name, - optlength - (optptr - options)); - break; - case IPP_TAG_RANGE : if (attr->values[i].range.lower == attr->values[i].range.upper) snprintf(optptr, optlength - (optptr - options) - 1, @@ -3204,6 +3319,25 @@ get_options(cupsd_job_t *job, /* I - Job */ } } + /* + * Finally loop through the PWG->PPD mapped options and add them... + */ + + for (i = num_pwgppds, pwgppd = pwgppds; i > 0; i --, pwgppd ++) + { + *optptr++ = ' '; + strcpy(optptr, pwgppd->name); + optptr += strlen(optptr); + *optptr++ = '='; + strcpy(optptr, pwgppd->value); + optptr += strlen(optptr); + } + + cupsFreeOptions(num_pwgppds, pwgppds); + + /* + * Return the options string... + */ return (options); } @@ -3214,10 +3348,10 @@ get_options(cupsd_job_t *job, /* I - Job */ * the textual IPP attributes. */ -static int /* O - Size of attribute buffer */ +static size_t /* O - Size of attribute buffer */ ipp_length(ipp_t *ipp) /* I - IPP request */ { - int bytes; /* Number of bytes */ + size_t bytes; /* Number of bytes */ int i; /* Looping var */ ipp_attribute_t *attr; /* Current attribute */ @@ -3234,16 +3368,14 @@ ipp_length(ipp_t *ipp) /* I - IPP request */ * Skip attributes that won't be sent to filters... */ - if (attr->value_tag == IPP_TAG_MIMETYPE || + if (attr->value_tag == IPP_TAG_NOVALUE || + attr->value_tag == IPP_TAG_MIMETYPE || attr->value_tag == IPP_TAG_NAMELANG || attr->value_tag == IPP_TAG_TEXTLANG || attr->value_tag == IPP_TAG_URI || attr->value_tag == IPP_TAG_URISCHEME) continue; - if (strncmp(attr->name, "time-", 5) == 0) - continue; - /* * Add space for a leading space and commas between each value. * For the first attribute, the leading space isn't used, so the diff --git a/scheduler/main.c b/scheduler/main.c index 6b2283c4b..8248c526c 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -770,8 +770,7 @@ main(int argc, /* I - Number of command-line args */ !cupsArrayCount(ActiveJobs) && (!Browsing || (!BrowseRemoteProtocols && - (!NumBrowsers || !BrowseLocalProtocols || - cupsArrayCount(Printers) == 0)))) + (!BrowseLocalProtocols || !cupsArrayCount(Printers))))) { timeout = LaunchdTimeout; launchd_idle_exit = 1; @@ -1621,10 +1620,10 @@ launchd_checkout(void) * shared printers to advertise... */ - if ((cupsArrayCount(ActiveJobs) || NumPolled || - (Browsing && - (BrowseRemoteProtocols || - (BrowseLocalProtocols && NumBrowsers && cupsArrayCount(Printers)))))) + if (cupsArrayCount(ActiveJobs) || NumPolled || + (Browsing && + (BrowseRemoteProtocols || + (BrowseLocalProtocols && cupsArrayCount(Printers))))) { cupsdLogMessage(CUPSD_LOG_DEBUG, "Creating launchd keepalive file \"" CUPS_KEEPALIVE diff --git a/scheduler/printers.c b/scheduler/printers.c index f11d9e758..76eb86028 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -2683,8 +2683,8 @@ cupsdSetPrinterAttrs(cupsd_printer_t *p)/* I - Printer to setup */ int /* O - 1 if something changed, 0 otherwise */ cupsdSetPrinterReasons( - cupsd_printer_t *p, /* I - Printer */ - const char *s) /* I - Reasons strings */ + cupsd_printer_t *p, /* I - Printer */ + const char *s) /* I - Reasons strings */ { int i, /* Looping var */ changed = 0; /* Did something change? */ diff --git a/scheduler/select.c b/scheduler/select.c index cc553754f..03e47437a 100644 --- a/scheduler/select.c +++ b/scheduler/select.c @@ -3,7 +3,7 @@ * * Select abstraction functions for the Common UNIX Printing System (CUPS). * - * Copyright 2007-2009 by Apple Inc. + * Copyright 2007-2010 by Apple Inc. * Copyright 2006-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -241,11 +241,11 @@ static fd_set cupsd_global_input, static int compare_fds(_cupsd_fd_t *a, _cupsd_fd_t *b); static _cupsd_fd_t *find_fd(int fd); -#define release_fd(f) { \ +#define release_fd(f) { \ (f)->use --; \ if (!(f)->use) free((f));\ } -#define retain_fd(f) (f)->use++ +#define retain_fd(f) (f)->use++ /* @@ -454,7 +454,8 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ if (fdptr->read_cb && event->filter == EVFILT_READ) (*(fdptr->read_cb))(fdptr->data); - if (fdptr->use > 1 && fdptr->write_cb && event->filter == EVFILT_WRITE) + if (fdptr->use > 1 && fdptr->write_cb && event->filter == EVFILT_WRITE && + !cupsArrayFind(cupsd_inactive_fds, fdptr)) (*(fdptr->write_cb))(fdptr->data); release_fd(fdptr); @@ -500,7 +501,8 @@ cupsdDoSelect(long timeout) /* I - Timeout in seconds */ (*(fdptr->read_cb))(fdptr->data); if (fdptr->use > 1 && fdptr->write_cb && - (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP))) + (event->events & (EPOLLOUT | EPOLLERR | EPOLLHUP)) && + !cupsArrayFind(cupsd_inactive_fds, fdptr)) (*(fdptr->write_cb))(fdptr->data); release_fd(fdptr); diff --git a/templates/admin.tmpl b/templates/admin.tmpl index da89d54e2..477da139e 100644 --- a/templates/admin.tmpl +++ b/templates/admin.tmpl @@ -105,6 +105,6 @@ <THEAD><TR><TH>Name</TH><TH>Events</TH><TH>Queue Name</TH></TR></THEAD> <TBODY>{[notify_subscription_id] <TR><TD><A HREF="{notify_recipient_uri}">{notify_recipient_name}</A><BR> -<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Cancel RSS Subscription"></FORM> </TD><TD>{notify_events}</TD><TD NOWRAP> {notify_printer_name?{notify_printer_name}:All Queues}</TD></TR>} +<FORM ACTION="/admin/" METHOD="POST"><INPUT TYPE="HIDDEN" NAME="org.cups.sid" VALUE="{$org.cups.sid}"><INPUT TYPE="HIDDEN" NAME="OP" VALUE="cancel-subscription"><INPUT TYPE="HIDDEN" NAME="notify_subscription_id" VALUE="{notify_subscription_id}"><INPUT TYPE="SUBMIT" VALUE="Cancel RSS Subscription"></FORM> </TD><TD>{notify_events}</TD><TD NOWRAP> {notify_printer_name?{notify_printer_name}:All Queues}</TD></TR>} </TBODY> </TABLE>:} diff --git a/test/ipp-1.1.test b/test/ipp-1.1.test index a92a09dc4..fb1caf849 100644 --- a/test/ipp-1.1.test +++ b/test/ipp-1.1.test @@ -567,7 +567,7 @@ ATTR uri printer-uri $uri ATTR name requesting-user-name $user ATTR keyword which-jobs completed - DELAY 10 + DELAY 20 STATUS successful-ok EXPECT job-id OF-TYPE integer IN-GROUP job-attributes-tag COUNT 1 WITH-VALUE >0 diff --git a/test/print-job-hold.test b/test/print-job-hold.test index a46827928..d70e523e7 100644 --- a/test/print-job-hold.test +++ b/test/print-job-hold.test @@ -1,16 +1,13 @@ # Test print-job and job-hold-until attribute { # The name of the test... - NAME "Print with print-job + job-hold-until" - - # The resource to use for the POST - # RESOURCE /admin + NAME "Print-Job w/job-hold-until=indefinite" # The operation to use - OPERATION print-job + OPERATION Print-Job # Attributes, starting in the operation group... - GROUP operation + GROUP operation-attributes-tag ATTR charset attributes-charset utf-8 ATTR language attributes-natural-language en ATTR uri printer-uri $uri @@ -21,10 +18,24 @@ FILE $filename # What statuses are OK? - STATUS ok - STATUS ok-subst + STATUS successful-ok + STATUS successful-ok-ignored-or-substituted-attributes # What attributes do we expect? EXPECT job-id EXPECT job-uri } +{ + NAME "Release-Job" + OPERATION Release-Job + + GROUP operation-attributes-tag + ATTR charset attributes-charset utf-8 + ATTR language attributes-natural-language en + ATTR uri printer-uri $uri + ATTR integer job-id $job-id + ATTR name requesting-user-name $user + + # What statuses are OK? + STATUS successful-ok +} diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh index 11a011608..013e4283b 100755 --- a/test/run-stp-tests.sh +++ b/test/run-stp-tests.sh @@ -803,7 +803,7 @@ if grep -iq 'testfile.pdf na_letter_8.5x11in' /tmp/cups-$user/log/page_log; then echo "<P>PASS: page_log formatted correctly.</P>" >>$strfile else echo "FAIL: page_log formatted incorrectly." - echo "<P>FAIL: page_log formatted incorrectly.</P>" >>$strfile + echo "<P>FAIL: page_log formatted incorrectly - no page size information.</P>" >>$strfile fail=`expr $fail + 1` fi diff --git a/tools/makeipptoolpkg b/tools/makeipptoolpkg index 62cd199f2..1fe318380 100644 --- a/tools/makeipptoolpkg +++ b/tools/makeipptoolpkg @@ -28,7 +28,7 @@ if test $# = 0; then svn up rev=`svnversion . | sed -e '1,$s/[a-zA-Z]//g'` fileversion="1.5svn-r$rev" - version=snapshot + version=snapshots else fileversion=$1 version=$1 diff --git a/vcnet/libcups2.vcproj b/vcnet/libcups2.vcproj index 13fa19872..17f8d67aa 100644 --- a/vcnet/libcups2.vcproj +++ b/vcnet/libcups2.vcproj @@ -1302,6 +1302,10 @@ </FileConfiguration>
</File>
<File
+ RelativePath="..\cups\sspi.c"
+ >
+ </File>
+ <File
RelativePath="..\cups\string.c"
>
<FileConfiguration
@@ -1374,6 +1378,10 @@ </FileConfiguration>
</File>
<File
+ RelativePath="..\cups\thread.c"
+ >
+ </File>
+ <File
RelativePath="..\cups\transcode.c"
>
<FileConfiguration
@@ -1572,10 +1580,18 @@ >
</File>
<File
+ RelativePath="..\cups\sspi-private.h"
+ >
+ </File>
+ <File
RelativePath="..\cups\string.h"
>
</File>
<File
+ RelativePath="..\cups\thread-private.h"
+ >
+ </File>
+ <File
RelativePath="..\cups\transcode.h"
>
</File>
|