From: msweet Date: Mon, 11 Apr 2011 18:53:27 +0000 (+0000) Subject: Merge changes from CUPS 1.5svn-r9675. X-Git-Tag: release-1.6.3~49 X-Git-Url: http://git.ipfire.org/?p=thirdparty%2Fcups.git;a=commitdiff_plain;h=07ed0e9a4385437b52e7195b681e600c2f1c5623 Merge changes from CUPS 1.5svn-r9675. git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@3122 a1ca3aef-8c08-0410-bb20-df032aa958be --- diff --git a/CHANGES.txt b/CHANGES.txt index 9bfca9891..8fcf44780 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,8 +1,9 @@ -CHANGES.txt - 2011-03-18 +CHANGES.txt - 2011-03-31 ------------------------ CHANGES IN CUPS V1.5b1 + - Added new PWG Raster filter for IPP Everywhere printer support. - Added printer-uuid attribute. - Added support for the cupsSingleFile PPD keyword. - Dropped support for the printer-state-history attribute (STR #3654) diff --git a/backend/ipp.c b/backend/ipp.c index 95263a85e..d54bd3def 100644 --- a/backend/ipp.c +++ b/backend/ipp.c @@ -95,6 +95,16 @@ static const char * const pattrs[] = /* Printer attributes we want */ "printer-state-message", "printer-state-reasons", }; +static const char * const remote_job_states[] = +{ /* Remote job state keywords */ + "cups-remote-pending", + "cups-remote-pending-held", + "cups-remote-processing", + "cups-remote-stopped", + "cups-remote-canceled", + "cups-remote-aborted", + "cups-remote-completed" +}; static char tmpfilename[1024] = ""; /* Temporary spool file name */ @@ -512,6 +522,16 @@ main(int argc, /* I - Number of command-line args */ password = getenv("AUTH_PASSWORD"); } +#ifdef HAVE_GSSAPI + /* + * For Kerberos, become the printing user (if we can) to get the credentials + * that way. + */ + + if (!getuid() && (value = getenv("AUTH_UID")) != NULL) + seteuid(atoi(value)); +#endif /* HAVE_GSSAPI */ + /* * Try finding the remote server... */ @@ -1421,6 +1441,23 @@ main(int argc, /* I - Number of command-line args */ if ((job_state = ippFindAttribute(response, "job-state", IPP_TAG_ENUM)) != NULL) { + /* + * Reflect the remote job state in the local queue... + */ + + fputs("STATE: -cups-remote-pending," + "cups-remote-pending-held," + "cups-remote-processing," + "cups-remote-stopped," + "cups-remote-canceled," + "cups-remote-aborted," + "cups-remote-completed\n", stderr); + if (job_state->values[0].integer >= IPP_JOB_PENDING && + job_state->values[0].integer <= IPP_JOB_COMPLETED) + fprintf(stderr, "STATE: +%s\n", + remote_job_states[job_state->values[0].integer - + IPP_JOB_PENDING]); + /* * Stop polling if the job is finished or pending-held... */ diff --git a/backend/snmp-supplies.c b/backend/snmp-supplies.c index d6d8ae1b9..86854b120 100644 --- a/backend/snmp-supplies.c +++ b/backend/snmp-supplies.c @@ -233,7 +233,10 @@ backendSNMPSupplies( for (i = 0, ptr = value; i < num_supplies; i ++, ptr += strlen(ptr)) { - percent = 100 * supplies[i].level / supplies[i].max_capacity; + if (supplies[i].max_capacity > 0) + percent = 100 * supplies[i].level / supplies[i].max_capacity; + else + percent = 50; if (percent <= 10) { diff --git a/backend/usb-darwin.c b/backend/usb-darwin.c index a41dfbf38..0733891b1 100644 --- a/backend/usb-darwin.c +++ b/backend/usb-darwin.c @@ -1,7 +1,7 @@ /* * "$Id: usb-darwin.c 7953 2008-09-17 01:43:19Z mike $" * -* Copyright 2005-2010 Apple Inc. All rights reserved. +* Copyright 2005-2011 Apple Inc. All rights reserved. * * IMPORTANT: This Apple software is supplied to you by Apple Computer, * Inc. ("Apple") in consideration of your agreement to the following @@ -1435,9 +1435,15 @@ static kern_return_t load_classdriver(CFStringRef driverPath, "permissions (0%o/uid=%d/gid=%d).\n", bundlestr, bundleinfo.st_mode, (int)bundleinfo.st_uid, (int)bundleinfo.st_gid); - fputs("STATE: +cups-insecure-filter-warning\n", stderr); - - if (bundleinfo.st_uid || (bundleinfo.st_mode & S_IWOTH)) + if (bundleinfo.st_uid || + (bundleinfo.st_gid && bundleinfo.st_gid != 80 && + (bundleinfo.st_mode & S_IWGRP)) || + (bundleinfo.st_mode & (S_ISUID | S_IWOTH))) + fputs("STATE: +cups-insecure-filter-warning\n", stderr); + + if (bundleinfo.st_uid || + (bundleinfo.st_gid && bundleinfo.st_gid != 80 && + (bundleinfo.st_mode & S_IWOTH))) { if (driverPath) return (load_classdriver(NULL, intf, printerDriver)); diff --git a/conf/mime.convs.in b/conf/mime.convs.in index 9e6796ad4..804546c9e 100644 --- a/conf/mime.convs.in +++ b/conf/mime.convs.in @@ -5,9 +5,9 @@ # VERSIONS OF CUPS. Instead, create a "local.convs" file that # reflects your local configuration changes. # -# MIME converts file for the Common UNIX Printing System (CUPS). +# Base MIME conversions file for CUPS. # -# Copyright 2007-2010 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2007 by Easy Software Products. # # These coded instructions, statements, and computer programs are the @@ -88,6 +88,9 @@ image/x-sun-raster application/vnd.cups-raster 100 imagetoraster # pstoraster is part of GPL Ghostscript... application/vnd.cups-postscript application/vnd.cups-raster 100 pstoraster +# PWG Raster filter for IPP Everywhere... +application/vnd.cups-raster image/pwg-raster 100 rastertopwg + ######################################################################## # # Raw filter... diff --git a/conf/mime.types b/conf/mime.types index dd28daaf6..77944f4bb 100644 --- a/conf/mime.types +++ b/conf/mime.types @@ -1,13 +1,13 @@ # # "$Id: mime.types 7670 2008-06-17 22:42:08Z mike $" # -# MIME types file for the Common UNIX Printing System (CUPS). +# Base MIME types file for CUPS. # # DO NOT EDIT THIS FILE, AS IT IS OVERWRITTEN WHEN YOU INSTALL NEW # VERSIONS OF CUPS. Instead, create a "local.types" file that # reflects your local configuration changes. # -# Copyright 2007-2010 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2007 by Easy Software Products. # # These coded instructions, statements, and computer programs are the @@ -92,6 +92,7 @@ image/jpeg jpeg jpg jpe string(0,) +\ char(3,0xe4) char(3,0xe5) char(3,0xe6) char(3,0xe7)\ char(3,0xe8) char(3,0xe9) char(3,0xea) char(3,0xeb)\ char(3,0xec) char(3,0xed) char(3,0xee) char(3,0xef)) +image/pwg-raster string(0,"RaS2") + string(356,<0000000000000000>) priority(100) image/tiff tiff tif string(0,MM<002A>) string(0,II<2A00>) image/x-photocd pcd string(2048,PCD_IPI) image/x-portable-anymap pnm diff --git a/cups/auth.c b/cups/auth.c index f9054d222..abc22eb90 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -260,8 +260,8 @@ _cupsSetNegotiateAuthString( OM_uint32 minor_status, /* Minor status code */ major_status; /* Major status code */ gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; - /* Output token */ - char *gss_service_name; /* GSS service name */ + /* Output token */ + _cups_globals_t *cg = _cupsGlobals(); /* Thread globals */ # ifdef __APPLE__ @@ -280,13 +280,10 @@ _cupsSetNegotiateAuthString( if (http->gssname == GSS_C_NO_NAME) { - if ((gss_service_name = getenv("CUPS_GSSSERVICENAME")) == NULL) - gss_service_name = CUPS_DEFAULT_GSSSERVICENAME; - else - DEBUG_puts("2_cupsSetNegotiateAuthString: GSS service name set via " - "environment variable"); + if (!cg->gss_service_name[0]) + _cupsSetDefaults(); - http->gssname = cups_get_gssname(http, gss_service_name); + http->gssname = cups_get_gssname(http, cg->gss_service_name); } if (http->gssctx != GSS_C_NO_CONTEXT) @@ -298,9 +295,6 @@ _cupsSetNegotiateAuthString( major_status = gss_init_sec_context(&minor_status, GSS_C_NO_CREDENTIAL, &http->gssctx, http->gssname, http->gssmech, -#ifdef GSS_C_DELEG_POLICY_FLAG - GSS_C_DELEG_POLICY_FLAG | -#endif /* GSS_C_DELEG_POLICY_FLAG */ GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, @@ -628,7 +622,7 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ DEBUG_printf(("9cups_local_auth: Unable to open file %s: %s", filename, strerror(errno))); -#ifdef HAVE_GSSAPI +# ifdef HAVE_GSSAPI if (!strncmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9)) { /* @@ -637,8 +631,19 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ return (1); } -#endif /* HAVE_GSSAPI */ +# endif /* HAVE_GSSAPI */ +# ifdef HAVE_AUTHORIZATION_H + if (httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", + auth_key, sizeof(auth_key))) + { + /* + * Don't use the root certificate as a replacement for an authkey... + */ + + return (1); + } +# endif /* HAVE_AUTHORIZATION_H */ if (!httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "trc", trc, sizeof(trc))) { diff --git a/cups/backend.c b/cups/backend.c index 83613ea20..818455f45 100644 --- a/cups/backend.c +++ b/cups/backend.c @@ -63,7 +63,7 @@ cupsBackendDeviceURI(char **argv) /* I - Command-line arguments */ } return (_httpResolveURI(device_uri, cg->resolved_uri, - sizeof(cg->resolved_uri), 1)); + sizeof(cg->resolved_uri), 1, NULL, NULL)); } diff --git a/cups/conflicts.c b/cups/conflicts.c index 56f800c1d..543b6aece 100644 --- a/cups/conflicts.c +++ b/cups/conflicts.c @@ -94,6 +94,7 @@ cupsGetConflicts( cups_array_t *active; /* Active conflicts */ _ppd_cups_uiconsts_t *c; /* Current constraints */ _ppd_cups_uiconst_t *cptr; /* Current constraint */ + ppd_choice_t *marked; /* Marked choice */ /* @@ -125,8 +126,16 @@ cupsGetConflicts( i > 0; i --, cptr ++) if (strcasecmp(cptr->option->keyword, option)) - num_options = cupsAddOption(cptr->option->keyword, cptr->choice->choice, - num_options, options); + { + if (cptr->choice) + num_options = cupsAddOption(cptr->option->keyword, + cptr->choice->choice, num_options, + options); + else if ((marked = ppdFindMarkedChoice(ppd, + cptr->option->keyword)) != NULL) + num_options = cupsAddOption(cptr->option->keyword, marked->choice, + num_options, options); + } } cupsArrayDelete(active); diff --git a/cups/cups-private.h b/cups/cups-private.h index 6e1677f88..0de2a37e6 100644 --- a/cups/cups-private.h +++ b/cups/cups-private.h @@ -68,6 +68,12 @@ typedef struct _cups_globals_s /**** CUPS global state data ****/ /* Number of server settings */ cups_option_t *cupsd_settings;/* Server settings */ + /* auth.c */ +# ifdef HAVE_GSSAPI + char gss_service_name[32]; + /* Kerberos service name */ +# endif /* HAVE_GSSAPI */ + /* backend.c */ char resolved_uri[1024]; /* Buffer for cupsBackendDeviceURI */ diff --git a/cups/http-private.h b/cups/http-private.h index 6b8d031a5..79ff84d6e 100644 --- a/cups/http-private.h +++ b/cups/http-private.h @@ -3,7 +3,7 @@ * * Private HTTP definitions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -79,6 +79,67 @@ typedef int socklen_t; # include "md5-private.h" # include "ipp-private.h" +# if defined HAVE_LIBSSL +# include +# include +# include +# elif defined HAVE_GNUTLS +# include +# include +# include +# elif defined(HAVE_CDSASSL) +# include +# include +# include +# ifdef HAVE_SECITEM_H +# include +# endif /* HAVE_SECITEM_H */ +# ifdef HAVE_SECBASEPRIV_H +# include +# endif /* HAVE_SECBASEPRIV_H */ +# ifdef HAVE_SECCERTIFICATE_H +# include +# include +# endif /* HAVE_SECCERTIFICATE_H */ +# ifdef HAVE_SECITEMPRIV_H +# include +# endif /* HAVE_SECITEMPRIV_H */ +# ifdef HAVE_SECIDENTITYSEARCHPRIV_H +# include +# endif /* HAVE_SECIDENTITYSEARCHPRIV_H */ +# ifdef HAVE_SECPOLICYPRIV_H +# include +# endif /* HAVE_SECPOLICYPRIV_H */ +# elif defined(HAVE_SSPISSL) +# include "sspi-private.h" +# endif /* HAVE_LIBSSL */ + +# ifndef WIN32 +# include +# ifdef HAVE_GETIFADDRS +# include +# else +# include +# ifdef HAVE_SYS_SOCKIO_H +# include +# endif /* HAVE_SYS_SOCKIO_H */ +# endif /* HAVE_GETIFADDRS */ +# endif /* !WIN32 */ + + +/* + * C++ magic... + */ + +# ifdef __cplusplus +extern "C" { +# endif /* __cplusplus */ + + +/* + * Types and functions for SSL support... + */ + # if defined HAVE_LIBSSL /* * The OpenSSL library provides its own SSL/TLS context structure for its @@ -86,10 +147,6 @@ typedef int socklen_t; * (basic IO) implementation to do timeouts... */ -# include -# include -# include - typedef SSL *http_tls_t; typedef void *http_tls_credentials_t; @@ -99,9 +156,6 @@ extern BIO_METHOD *_httpBIOMethods(void); /* * The GNU TLS library is more of a "bare metal" SSL/TLS library... */ -# include -# include -# include typedef gnutls_session http_tls_t; typedef void *http_tls_credentials_t; @@ -117,42 +171,24 @@ extern ssize_t _httpWriteGNUTLS(gnutls_transport_ptr ptr, const void *data, * for its IO and protocol management... */ -# include -# include -# include -# ifdef HAVE_SECITEM_H -# include -# endif /* HAVE_SECITEM_H */ -# ifdef HAVE_SECBASEPRIV_H -# include -# elif defined(HAVE_CSSMERRORSTRING) /* Declare prototype for function in that header... */ +# if !defined(HAVE_SECBASEPRIV_H) && defined(HAVE_CSSMERRORSTRING) /* Declare prototype for function in that header... */ extern const char *cssmErrorString(int error); -# endif /* HAVE_SECBASEPRIV_H */ -# ifdef HAVE_SECCERTIFICATE_H -# include -# include -# endif /* HAVE_SECCERTIFICATE_H */ -# ifdef HAVE_SECITEMPRIV_H -# include -# else /* Declare constants from that header... */ +# endif /* !HAVE_SECBASEPRIV_H && HAVE_CSSMERRORSTRING */ +# ifndef HAVE_SECITEMPRIV_H /* Declare constants from that header... */ extern const CFTypeRef kSecClassCertificate; extern const CFTypeRef kSecClassIdentity; -# endif /* HAVE_SECITEMPRIV_H */ -# ifdef HAVE_SECIDENTITYSEARCHPRIV_H -# include -# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) /* Declare prototype for function in that header... */ +# endif /* !HAVE_SECITEMPRIV_H */ +# if !defined(HAVE_SECIDENTITYSEARCHPRIV_H) && defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) /* Declare prototype for function in that header... */ 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 -# elif defined(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY) /* Declare prototype for function in that header... */ +# endif /* !HAVE_SECIDENTITYSEARCHPRIV_H && HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY */ +# if !defined(HAVE_SECPOLICYPRIV_H) && defined(HAVE_SECPOLICYSETVALUE) /* Declare prototype for function in that header... */ extern OSStatus SecPolicySetValue(SecPolicyRef policyRef, const CSSM_DATA *value); -# endif /* HAVE_SECPOLICYPRIV_H */ +# endif /* !HAVE_SECPOLICYPRIV_H && HAVE_SECPOLICYSETVALUE */ typedef SSLContextRef http_tls_t; typedef CFArrayRef http_tls_credentials_t; @@ -163,11 +199,20 @@ extern OSStatus _httpWriteCDSA(SSLConnectionRef connection, const void *data, size_t *dataLength); # elif defined(HAVE_SSPISSL) -# include "sspi-private.h" +/* + * Windows' SSPI library gets a CUPS wrapper... + */ + typedef _sspi_struct_t * http_tls_t; typedef void *http_tls_credentials_t; + # else +/* + * Otherwise define stub types since we have no SSL support... + */ + typedef void *http_tls_t; +typedef void *http_tls_credentials_t; # endif /* HAVE_LIBSSL */ @@ -258,22 +303,13 @@ extern const char *hstrerror(int error); * Some OS's don't have getifaddrs() and freeifaddrs()... */ -# ifndef WIN32 -# include -# ifdef HAVE_GETIFADDRS -# include -# else -# include -# ifdef HAVE_SYS_SOCKIO_H -# include -# endif /* HAVE_SYS_SOCKIO_H */ - -# ifdef ifa_dstaddr -# undef ifa_dstaddr -# endif /* ifa_dstaddr */ -# ifndef ifr_netmask -# define ifr_netmask ifr_addr -# endif /* !ifr_netmask */ +# if !defined(WIN32) && !defined(HAVE_GETIFADDRS) +# ifdef ifa_dstaddr +# undef ifa_dstaddr +# endif /* ifa_dstaddr */ +# ifndef ifr_netmask +# define ifr_netmask ifr_addr +# endif /* !ifr_netmask */ struct ifaddrs /**** Interface Structure ****/ { @@ -291,25 +327,28 @@ struct ifaddrs /**** Interface Structure ****/ void *ifa_data; /* Interface statistics */ }; -# ifndef ifa_broadaddr -# define ifa_broadaddr ifa_ifu.ifu_broadaddr -# endif /* !ifa_broadaddr */ -# ifndef ifa_dstaddr -# define ifa_dstaddr ifa_ifu.ifu_dstaddr -# endif /* !ifa_dstaddr */ +# ifndef ifa_broadaddr +# define ifa_broadaddr ifa_ifu.ifu_broadaddr +# endif /* !ifa_broadaddr */ +# ifndef ifa_dstaddr +# define ifa_dstaddr ifa_ifu.ifu_dstaddr +# endif /* !ifa_dstaddr */ extern int _cups_getifaddrs(struct ifaddrs **addrs); -# define getifaddrs _cups_getifaddrs +# define getifaddrs _cups_getifaddrs extern void _cups_freeifaddrs(struct ifaddrs *addrs); -# define freeifaddrs _cups_freeifaddrs -# endif /* HAVE_GETIFADDRS */ -# endif /* !WIN32 */ +# define freeifaddrs _cups_freeifaddrs +# endif /* !WIN32 && !HAVE_GETIFADDRS */ + /* * Prototypes... */ extern int _httpAddrPort(http_addr_t *addr); +extern char *_httpAssembleUUID(const char *server, int port, + const char *name, int number, + char *buffer, size_t bufsize); extern http_tls_credentials_t _httpConvertCredentials(cups_array_t *credentials); extern http_t *_httpCreate(const char *host, int port, @@ -324,13 +363,23 @@ extern char *_httpEncodeURI(char *dst, const char *src, extern void _httpFreeCredentials(http_tls_credentials_t credentials); extern ssize_t _httpPeek(http_t *http, char *buffer, size_t length); extern const char *_httpResolveURI(const char *uri, char *resolved_uri, - size_t resolved_size, int log); + size_t resolved_size, int log, + int (*cb)(void *context), + void *context); extern void _httpSetTimeout(http_t *http, double timeout, _http_timeout_cb_t cb, void *user_data); extern int _httpUpdate(http_t *http, http_status_t *status); extern int _httpWait(http_t *http, int msec, int usessl); +/* + * C++ magic... + */ + +# ifdef __cplusplus +} +# endif /* __cplusplus */ + #endif /* !_CUPS_HTTP_PRIVATE_H_ */ /* diff --git a/cups/http-support.c b/cups/http-support.c index 1d73f7d48..f598bfbb5 100644 --- a/cups/http-support.c +++ b/cups/http-support.c @@ -20,6 +20,7 @@ * components. * httpAssembleURIf() - Assemble a uniform resource identifier from its * components with a formatted resource. + * _httpAssembleUUID() - Make a UUID URI conforming to RFC 4122. * httpDecode64() - Base64-decode a string. * httpDecode64_2() - Base64-decode a string. * httpEncode64() - Base64-encode a string. @@ -436,6 +437,56 @@ httpAssembleURIf( } +/* + * '_httpAssembleUUID()' - Make a UUID URI conforming to RFC 4122. + * + * The buffer needs to be at least 46 bytes in size. + */ + +char * /* I - UUID string */ +_httpAssembleUUID(const char *server, /* I - Server name */ + int port, /* I - Port number */ + const char *name, /* I - Object name or NULL */ + int number, /* I - Object number or 0 */ + char *buffer, /* I - String buffer */ + size_t bufsize) /* I - Size of buffer */ +{ + char data[1024]; /* Source string for MD5 */ + _cups_md5_state_t md5state; /* MD5 state */ + unsigned char md5sum[16]; /* MD5 digest/sum */ + + + /* + * Build a version 3 UUID conforming to RFC 4122. + * + * Start with the MD5 sum of the server, port, object name and + * number, and some random data on the end. + */ + + snprintf(data, sizeof(data), "%s:%d:%s:%d:%04x:%04x", server, + port, name ? name : server, number, + CUPS_RAND() & 0xffff, CUPS_RAND() & 0xffff); + + _cupsMD5Init(&md5state); + _cupsMD5Append(&md5state, (unsigned char *)data, strlen(data)); + _cupsMD5Finish(&md5state, md5sum); + + /* + * Generate the UUID from the MD5... + */ + + snprintf(buffer, bufsize, + "urn:uuid:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" + "%02x%02x%02x%02x%02x%02x", + md5sum[0], md5sum[1], md5sum[2], md5sum[3], md5sum[4], md5sum[5], + (md5sum[6] & 15) | 0x30, md5sum[7], (md5sum[8] & 0x3f) | 0x40, + md5sum[9], md5sum[10], md5sum[11], md5sum[12], md5sum[13], + md5sum[14], md5sum[15]); + + return (buffer); +} + + /* * 'httpDecode64()' - Base64-decode a string. * @@ -1331,7 +1382,9 @@ _httpResolveURI( const char *uri, /* I - DNS-SD URI */ char *resolved_uri, /* I - Buffer for resolved URI */ size_t resolved_size, /* I - Size of URI buffer */ - int logit) /* I - Log progress to stderr? */ + int logit, /* I - Log progress to stderr? */ + int (*cb)(void *context), /* I - Continue callback function */ + void *context) /* I - Context pointer for callback */ { char scheme[32], /* URI components... */ userpass[256], @@ -1463,12 +1516,18 @@ _httpResolveURI( if (logit) _cupsLangPrintFilter(stderr, "INFO", _("Looking for printer.")); + if (cb && !(*cb)(context)) + { + DEBUG_puts("5_httpResolveURI: callback returned 0 (stop)"); + break; + } + /* - * For the first minute, wakeup every 2 seconds to emit a - * "looking for printer" message... + * For the first minute (or forever if we have a callback), wakeup + * every 2 seconds to emit a "looking for printer" message... */ - timeout = (time(NULL) < (start_time + 60)) ? 2000 : -1; + timeout = (time(NULL) < (start_time + 60) || cb) ? 2000 : -1; #ifdef HAVE_POLL polldata.fd = DNSServiceRefSockFD(ref); diff --git a/cups/libcups2.def b/cups/libcups2.def index 6e9581823..13009f340 100644 --- a/cups/libcups2.def +++ b/cups/libcups2.def @@ -29,6 +29,7 @@ _cups_strcpy _cups_strlcat _cups_strlcpy _httpAddrPort +_httpAssembleUUID _httpCreate _httpEncodeURI _httpPeek diff --git a/cups/libcups_s.exp b/cups/libcups_s.exp index 80b347a75..c36b87810 100644 --- a/cups/libcups_s.exp +++ b/cups/libcups_s.exp @@ -41,6 +41,7 @@ _cups_strcpy _cups_strlcat _cups_strlcpy _httpAddrPort +_httpAssembleUUID _httpBIOMethods _httpCreate _httpEncodeURI diff --git a/cups/raster.h b/cups/raster.h index eabd190be..4437accb5 100644 --- a/cups/raster.h +++ b/cups/raster.h @@ -3,7 +3,7 @@ * * Raster file definitions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * This file is part of the CUPS Imaging library. @@ -66,6 +66,19 @@ extern "C" { # define CUPS_RASTER_HAVE_COLORIMETRIC 1 +/* + * The following definition can be used to determine if the + * device colorspaces (DEVICEn) are defined... + */ + +# define CUPS_RASTER_HAVE_DEVICE 1 + +/* + * The following definition can be used to determine if PWG Raster is supported. + */ + +# define CUPS_RASTER_HAVE_PWGRASTER 1 + /* * Types... diff --git a/cups/testhttp.c b/cups/testhttp.c index ccb7c19dd..f711e9ab9 100644 --- a/cups/testhttp.c +++ b/cups/testhttp.c @@ -3,7 +3,7 @@ * * HTTP test program for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -468,7 +468,7 @@ main(int argc, /* I - Number of command-line arguments */ printf("_httpResolveURI(%s): ", argv[1]); fflush(stdout); - if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), 1)) + if (!_httpResolveURI(argv[1], resolved, sizeof(resolved), 1, NULL, NULL)) { puts("FAIL"); return (1); diff --git a/cups/usersys.c b/cups/usersys.c index 20a38db2d..3b46d4cc8 100644 --- a/cups/usersys.c +++ b/cups/usersys.c @@ -3,7 +3,7 @@ * * User, system, and password routines for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -57,6 +57,9 @@ static void cups_read_client_conf(cups_file_t *fp, _cups_globals_t *cg, const char *cups_encryption, const char *cups_server, +#ifdef HAVE_GSSAPI + const char *cups_gssservicename, +#endif /* HAVE_GSSAPI */ const char *cups_anyroot, const char *cups_expiredroot, const char *cups_expiredcerts); @@ -519,6 +522,9 @@ _cupsSetDefaults(void) const char *home, /* Home directory of user */ *cups_encryption, /* CUPS_ENCRYPTION env var */ *cups_server, /* CUPS_SERVER env var */ +#ifdef HAVE_GSSAPI + *cups_gssservicename, /* CUPS_GSSSERVICENAME env var */ +#endif /* HAVE_GSSAPI */ *cups_anyroot, /* CUPS_ANYROOT env var */ *cups_expiredroot, /* CUPS_EXPIREDROOT env var */ *cups_expiredcerts; /* CUPS_EXPIREDCERTS env var */ @@ -532,11 +538,14 @@ _cupsSetDefaults(void) * First collect environment variables... */ - cups_encryption = getenv("CUPS_ENCRYPTION"); - cups_server = getenv("CUPS_SERVER"); - cups_anyroot = getenv("CUPS_ANYROOT"); - cups_expiredroot = getenv("CUPS_EXPIREDROOT"); - cups_expiredcerts = getenv("CUPS_EXPIREDCERTS"); + cups_encryption = getenv("CUPS_ENCRYPTION"); + cups_server = getenv("CUPS_SERVER"); +#ifdef HAVE_GSSAPI + cups_gssservicename = getenv("CUPS_GSSSERVICENAME"); +#endif /* HAVE_GSSAPI */ + cups_anyroot = getenv("CUPS_ANYROOT"); + cups_expiredroot = getenv("CUPS_EXPIREDROOT"); + cups_expiredcerts = getenv("CUPS_EXPIREDCERTS"); /* * Then, if needed, read the ~/.cups/client.conf or /etc/cups/client.conf @@ -575,6 +584,9 @@ _cupsSetDefaults(void) */ cups_read_client_conf(fp, cg, cups_encryption, cups_server, +#ifdef HAVE_GSSAPI + cups_gssservicename, +#endif /* HAVE_GSSAPI */ cups_anyroot, cups_expiredroot, cups_expiredcerts); cupsFileClose(fp); @@ -592,6 +604,10 @@ cups_read_client_conf( _cups_globals_t *cg, /* I - Global data */ const char *cups_encryption, /* I - CUPS_ENCRYPTION env var */ const char *cups_server, /* I - CUPS_SERVER env var */ +#ifdef HAVE_GSSAPI + const char *cups_gssservicename, + /* I - CUPS_GSSSERVICENAME env var */ +#endif /* HAVE_GSSAPI */ const char *cups_anyroot, /* I - CUPS_ANYROOT env var */ const char *cups_expiredroot, /* I - CUPS_EXPIREDROOT env var */ const char *cups_expiredcerts) /* I - CUPS_EXPIREDCERTS env var */ @@ -604,6 +620,9 @@ cups_read_client_conf( any_root[1024], /* AllowAnyRoot value */ expired_root[1024], /* AllowExpiredRoot value */ expired_certs[1024]; /* AllowExpiredCerts value */ +#ifdef HAVE_GSSAPI + char gss_service_name[32]; /* GSSServiceName value */ +#endif /* HAVE_GSSAPI */ /* @@ -642,6 +661,14 @@ cups_read_client_conf( strlcpy(expired_certs, value, sizeof(expired_certs)); cups_expiredcerts = expired_certs; } +#ifdef HAVE_GSSAPI + else if (!cups_gssservicename && !strcasecmp(line, "GSSServiceName") && + value) + { + strlcpy(gss_service_name, value, sizeof(gss_service_name)); + cups_gssservicename = gss_service_name; + } +#endif /* HAVE_GSSAPI */ } /* @@ -730,6 +757,14 @@ cups_read_client_conf( cg->ipp_port = ntohs(service->s_port); } +#ifdef HAVE_GSSAPI + if (!cups_gssservicename) + cups_gssservicename = CUPS_DEFAULT_GSSSERVICENAME; + + strlcpy(cg->gss_service_name, cups_gssservicename, + sizeof(cg->gss_service_name)); +#endif /* HAVE_GSSAPI */ + if (cups_anyroot) cg->any_root = !strcasecmp(cups_anyroot, "yes") || !strcasecmp(cups_anyroot, "on") || diff --git a/cups/util.c b/cups/util.c index 80f36d153..4e5c74035 100644 --- a/cups/util.c +++ b/cups/util.c @@ -1762,7 +1762,7 @@ cups_get_printer_uri( { httpSeparateURI(HTTP_URI_CODING_ALL, _httpResolveURI(attr->values[0].string.text, uri, - sizeof(uri), 0), + sizeof(uri), 0, NULL, NULL), scheme, sizeof(scheme), username, sizeof(username), host, hostsize, port, resource, resourcesize); ippDelete(response); diff --git a/data/media.defs b/data/media.defs index 8d5d278e7..98148729e 100644 --- a/data/media.defs +++ b/data/media.defs @@ -3,7 +3,7 @@ * * Adobe standard media size definitions for the CUPS PPD file compiler. * - * Copyright 2007 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2005 by Easy Software Products. * * These codedinstructions, statements, and computer programs are the @@ -165,7 +165,7 @@ #media "LetterPlus/US Letter Oversize" 612 914 #media "LetterRotated/US Letter" 792 612 #media "LetterSmall/US Letter Small" 612 792 -#media "Monarch/Monarch" 279 540 +#media "Monarch/Envelope Monarch" 279 540 #media "Note/Note" 612 792 #media "Postcard/Postcard" 284 419 #media "PostcardRotated/Postcard" 419 284 diff --git a/data/testprint.in b/data/testprint.in index 5eff73140..8cee3ab4f 100644 --- a/data/testprint.in +++ b/data/testprint.in @@ -2,7 +2,6 @@ Show printer-name printer-info printer-location printer-make-and-model printer-driver-name printer-driver-version paper-size imageable-area Header Printer Test Page Footer Printer Test Page -Notice This test page was produced by CUPS @CUPS_VERSION@. +Notice CUPS @CUPS_VERSION@. Image images/cups.png Image images/color-wheel.png - diff --git a/filter/Makefile b/filter/Makefile index a4d08770a..104d4cda6 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -1,9 +1,9 @@ # # "$Id: Makefile 7871 2008-08-27 21:12:43Z mike $" # -# Filter makefile for the Common UNIX Printing System (CUPS). +# Filter makefile for CUPS. # -# Copyright 2007-2010 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2006 by Easy Software Products. # # These coded instructions, statements, and computer programs are the @@ -26,9 +26,10 @@ FILTERS = \ pstops \ $(IMGFILTERS) \ $(PDFTOPS) \ - rastertolabel \ rastertoepson \ - rastertohp + rastertohp \ + rastertolabel \ + rastertopwg LIBTARGETS = \ $(LIBCUPSIMAGE) \ libcupsimage.a \ @@ -52,7 +53,7 @@ OBJS = $(IMAGEOBJS) \ bannertops.o commandtops.o gziptoany.o imagetops.o \ imagetoraster.o common.o pdftops.o pstext.o pstops.o \ rasterbench.o rastertoepson.o rastertohp.o rastertolabel.o \ - testimage.o testraster.o textcommon.o texttops.o + rastertopwg.o testimage.o testraster.o textcommon.o texttops.o # @@ -446,15 +447,6 @@ pdftops: pdftops.o common.o ../cups/$(LIBCUPS) $(CC) $(LDFLAGS) -o $@ pdftops.o common.o $(LIBS) -# -# rastertolabel -# - -rastertolabel: rastertolabel.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) - echo Linking $@... - $(CC) $(LDFLAGS) -o $@ rastertolabel.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS) - - # # rastertoepson # @@ -473,6 +465,24 @@ rastertohp: rastertohp.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) $(CC) $(LDFLAGS) -o $@ rastertohp.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS) +# +# rastertolabel +# + +rastertolabel: rastertolabel.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ rastertolabel.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS) + + +# +# rastertopwg +# + +rastertopwg: rastertopwg.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) + echo Linking $@... + $(CC) $(LDFLAGS) -o $@ rastertopwg.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS) + + # # testraster # @@ -508,7 +518,7 @@ texttops: texttops.o textcommon.o common.o \ # # Dependencies... # - + include Dependencies diff --git a/filter/raster.c b/filter/raster.c index a57dd1874..7e54b0ec3 100644 --- a/filter/raster.c +++ b/filter/raster.c @@ -1043,7 +1043,6 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */ unsigned char *bufptr; /* Temporary buffer pointer */ - remaining -= count; for (bufptr = r->bufptr; count > 0; count --, total ++) @@ -1241,7 +1240,7 @@ cups_raster_write( *wptr++ = r->count - 1; /* - * Write using a modified TIFF "packbits" compression... + * Write using a modified PackBits compression... */ for (ptr = pixels; ptr < pend;) @@ -1279,7 +1278,7 @@ cups_raster_write( * Encode a sequence of non-repeating pixels... */ - for (count = 1; count < 127 && ptr < plast; count ++, ptr += bpp) + for (count = 1; count < 128 && ptr < plast; count ++, ptr += bpp) if (!memcmp(ptr, ptr + bpp, bpp)) break; diff --git a/filter/rastertopwg.c b/filter/rastertopwg.c new file mode 100644 index 000000000..6f6497c09 --- /dev/null +++ b/filter/rastertopwg.c @@ -0,0 +1,218 @@ +/* + * "$Id$" + * + * CUPS raster to PWG raster format filter for CUPS. + * + * Copyright 2011 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/". + * + * This file is subject to the Apple OS-Developed Software exception. + * + * Contents: + * + * main() - Main entry for filter. + */ + +/* + * Include necessary headers... + */ + +#include +#include +#include +#include +#include +#include + + +/* + * 'main()' - Main entry for filter. + */ + +int /* O - Exit status */ +main(int argc, /* I - Number of command-line args */ + char *argv[]) /* I - Command-line arguments */ +{ + int fd; /* Raster file */ + cups_raster_t *inras, /* Input raster stream */ + *outras; /* Output raster stream */ + cups_page_header2_t inheader, /* Input raster page header */ + outheader; /* Output raster page header */ + int y; /* Current line */ + unsigned char *line; /* Line buffer */ + int page = 0, /* Current page */ + page_width, /* Actual page width */ + page_height, /* Actual page height */ + page_top, /* Top margin */ + page_bottom, /* Bottom margin */ + page_left, /* Left margin */ + linesize, /* Bytes per line */ + lineoffset; /* Offset into line */ + unsigned char white; /* White pixel */ + + + if (argc < 6 || argc > 7) + { + puts("Usage: rastertopwg job user title copies options [filename]"); + return (1); + } + else if (argc == 7) + { + if ((fd = open(argv[6], O_RDONLY)) < 0) + { + perror("ERROR: Unable to open print file"); + return (1); + } + } + else + fd = 0; + + inras = cupsRasterOpen(fd, CUPS_RASTER_READ); + outras = cupsRasterOpen(1, CUPS_RASTER_WRITE_PWG); + + while (cupsRasterReadHeader2(inras, &inheader)) + { + /* + * Compute the real raster size... + */ + + page ++; + + fprintf(stderr, "PAGE: %d %d\n", page, inheader.NumCopies); + + page_width = (int)(inheader.cupsPageSize[0] * inheader.HWResolution[0] / + 72.0); + page_height = (int)(inheader.cupsPageSize[1] * inheader.HWResolution[1] / + 72.0); + page_left = (int)(inheader.cupsImagingBBox[0] * + inheader.HWResolution[0] / 72.0); + page_bottom = (int)(inheader.cupsImagingBBox[1] * + inheader.HWResolution[1] / 72.0); + page_top = page_height - page_bottom - inheader.cupsHeight; + linesize = (page_width * inheader.cupsBitsPerPixel + 7) / 8; + lineoffset = page_left * inheader.cupsBitsPerPixel / 8; /* Round down */ + + switch (inheader.cupsColorSpace) + { + case CUPS_CSPACE_W : + case CUPS_CSPACE_RGB : + case CUPS_CSPACE_SW : + case CUPS_CSPACE_SRGB : + case CUPS_CSPACE_ADOBERGB : + white = 255; + break; + + case CUPS_CSPACE_K : + case CUPS_CSPACE_CMYK : + 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 : + white = 0; + break; + default : + _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data.")); + fprintf(stderr, "DEBUG: Unsupported cupsColorSpace %d on page %d.\n", + inheader.cupsColorSpace, page); + return (1); + } + + if (inheader.cupsColorOrder != CUPS_ORDER_CHUNKED) + { + _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data.")); + fprintf(stderr, "DEBUG: Unsupported cupsColorOrder %d on page %d.\n", + inheader.cupsColorOrder, page); + return (1); + } + + if (inheader.cupsBitsPerPixel != 1 && + inheader.cupsBitsPerColor != 8 && inheader.cupsBitsPerColor != 16) + { + _cupsLangPrintFilter(stderr, "ERROR", _("Unsupported raster data.")); + fprintf(stderr, "DEBUG: Unsupported cupsBitsPerColor %d on page %d.\n", + inheader.cupsBitsPerColor, page); + return (1); + } + + memcpy(&outheader, &inheader, sizeof(outheader)); + outheader.cupsWidth = page_width; + outheader.cupsHeight = page_height; + outheader.cupsBytesPerLine = linesize; + + if (!cupsRasterWriteHeader2(outras, &outheader)) + { + _cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data.")); + fprintf(stderr, "DEBUG: Unable to write header for page %d.\n", page); + return (1); + } + + /* + * Copy raster data... + */ + + line = malloc(linesize); + + memset(line, white, linesize); + for (y = page_top; y > 0; y --) + if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine)) + { + _cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data.")); + fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n", + page_top - y + 1, page); + return (1); + } + + for (y = inheader.cupsHeight; y > 0; y --) + { + cupsRasterReadPixels(inras, line + lineoffset, inheader.cupsBytesPerLine); + if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine)) + { + _cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data.")); + fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n", + inheader.cupsHeight - y + page_top + 1, page); + return (1); + } + } + + memset(line, white, linesize); + for (y = page_top; y > 0; y --) + if (!cupsRasterWritePixels(outras, line, outheader.cupsBytesPerLine)) + { + _cupsLangPrintFilter(stderr, "ERROR", _("Error sending raster data.")); + fprintf(stderr, "DEBUG: Unable to write line %d for page %d.\n", + page_bottom - y + page_top + inheader.cupsHeight + 1, page); + return (1); + } + + free(line); + } + + cupsRasterClose(inras); + if (fd) + close(fd); + + cupsRasterClose(outras); + + return (0); +} + + +/* + * End of "$Id$". + */ diff --git a/man/client.conf.man.in b/man/client.conf.man.in index 366236a12..0f85f305f 100644 --- a/man/client.conf.man.in +++ b/man/client.conf.man.in @@ -1,9 +1,9 @@ .\" .\" "$Id: client.conf.man.in 6649 2007-07-11 21:46:42Z mike $" .\" -.\" client.conf man page for the Common UNIX Printing System (CUPS). +.\" client.conf man page for CUPS. .\" -.\" Copyright 2007-2009 by Apple Inc. +.\" Copyright 2007-2011 by Apple Inc. .\" Copyright 2006 by Easy Software Products. .\" .\" These coded instructions, statements, and computer programs are the @@ -12,7 +12,7 @@ .\" which should have been included with this file. If this file is .\" file is missing or damaged, see the license at "http://www.cups.org/". .\" -.TH client.conf 5 "CUPS" "25 February 2006" "Apple Inc." +.TH client.conf 5 "CUPS" "28 March 2011" "Apple Inc." .SH NAME client.conf \- client configuration file for cups .SH DESCRIPTION @@ -34,16 +34,22 @@ Encryption Required Specifies the level of encryption that is required for a particular location. .TP 5 +GSSServiceName name +Specifies the Kerberos service name that is used for authentication, typically +"host", "http", or "ipp". CUPS adds the remote hostname +("name@server.example.com") for you. The default name is +"@CUPS_DEFAULT_GSSSERVICENAME@". +.TP 5 ServerName hostname-or-ip-address[:port] .TP 5 ServerName /domain/socket .br -Specifies the address and optionally the port to use when -connecting to the server +Specifies the address and optionally the port to use when connecting to the +server. .SH SEE ALSO http://localhost:631/help .SH COPYRIGHT -Copyright 2007-2009 by Apple Inc. +Copyright 2007-2011 by Apple Inc. .\" .\" End of "$Id: client.conf.man.in 6649 2007-07-11 21:46:42Z mike $". .\" diff --git a/man/lp.man b/man/lp.man index 5b183556c..c313b52df 100644 --- a/man/lp.man +++ b/man/lp.man @@ -1,9 +1,9 @@ .\" .\" "$Id: lp.man 7889 2008-08-29 22:03:35Z mike $" .\" -.\" lp man page for the Common UNIX Printing System (CUPS). +.\" lp man page for CUPS. .\" -.\" Copyright 2007-2010 by Apple Inc. +.\" Copyright 2007-2011 by Apple Inc. .\" Copyright 1997-2006 by Easy Software Products. .\" .\" These coded instructions, statements, and computer programs are the @@ -12,7 +12,7 @@ .\" which should have been included with this file. If this file is .\" file is missing or damaged, see the license at "http://www.cups.org/". .\" -.TH lp 1 "CUPS" "31 August 2010" "Apple Inc." +.TH lp 1 "CUPS" "31 March 2011" "Apple Inc." .SH NAME lp - print files .SH SYNOPSIS @@ -142,11 +142,10 @@ Submits jobs as \fIusername\fR. .TP 5 -H resume .br -Specifies when the job should be printed. A value of -\fIimmediate\fR will print the file immediately, a value of -\fIhold\fR will hold the job indefinitely, and a time value -(HH:MM) will hold the job until the specified time. Use a value -of \fIresume\fR with the \fI-i\fR option to resume a held job. +Specifies when the job should be printed. A value of \fIimmediate\fR will print +the file immediately, a value of \fIhold\fR will hold the job indefinitely, and +a UTC time value (HH:MM) will hold the job until the specified UTC (not local) +time. Use a value of \fIresume\fR with the \fI-i\fR option to resume a held job. Use a value of \fIrestart\fR with the \fI-i\fR option to restart a completed job. .TP 5 @@ -257,7 +256,7 @@ is highest priority). .br http://localhost:631/help .SH COPYRIGHT -Copyright 2007-2010 by Apple Inc. +Copyright 2007-2011 by Apple Inc. .\" .\" End of "$Id: lp.man 7889 2008-08-29 22:03:35Z mike $". .\" diff --git a/packaging/cups.list.in b/packaging/cups.list.in index 79b996edf..ee2d64a49 100644 --- a/packaging/cups.list.in +++ b/packaging/cups.list.in @@ -3,7 +3,7 @@ # # ESP Package Manager (EPM) file list for CUPS. # -# Copyright 2007-2010 by Apple Inc. +# Copyright 2007-2011 by Apple Inc. # Copyright 1997-2007 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the @@ -15,7 +15,7 @@ # Product information %product CUPS -%copyright 2007-2010 by Apple Inc. +%copyright 2007-2011 by Apple Inc. %vendor Apple Inc. #%license LICENSE.txt %readme LICENSE.txt @@ -309,6 +309,7 @@ l 0755 root sys $SERVERBIN/filter/rastertodymo rastertolabel f 0555 root sys $SERVERBIN/filter/rastertoepson filter/rastertoepson f 0555 root sys $SERVERBIN/filter/rastertohp filter/rastertohp f 0555 root sys $SERVERBIN/filter/rastertopclx driver/rastertopclx +f 0555 root sys $SERVERBIN/filter/rastertopwg filter/rastertopwg f 0555 root sys $SERVERBIN/filter/texttops filter/texttops d 0755 root sys $SERVERBIN/notifier - f 0555 root sys $SERVERBIN/notifier/mailto notifier/mailto diff --git a/scheduler/auth.c b/scheduler/auth.c index d2e1b1374..4d99f2653 100644 --- a/scheduler/auth.c +++ b/scheduler/auth.c @@ -27,7 +27,6 @@ * access a location. * cupsdCheckAuth() - Check authorization masks. * cupsdCheckGroup() - Check for a user's group membership. - * cupsdCopyKrb5Creds() - Get a copy of the Kerberos credentials. * cupsdCopyLocation() - Make a copy of a location... * cupsdDeleteAllLocations() - Free all memory used for location * authorization. @@ -382,6 +381,10 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ username[0] = '\0'; password[0] = '\0'; +#ifdef HAVE_GSSAPI + con->gss_uid = 0; +#endif /* HAVE_GSSAPI */ + #ifdef HAVE_AUTHORIZATION_H if (con->authref) { @@ -991,102 +994,6 @@ 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 */ - krb5_principal peerprncpl; /* Peer's default principal */ - 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)); - - if (!KerberosInitialized) - { - /* - * Setup a Kerberos context for the scheduler to use... - */ - - KerberosInitialized = 1; - - if (krb5_init_context(&KerberosContext)) - { - KerberosContext = NULL; - - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to initialize Kerberos context"); - return; - } - } - - 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)); - krb5_ipc_client_clear_target(); - return; - } - - if (krb5_cc_get_principal(KerberosContext, peerccache, &peerprncpl)) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to get Kerberos principal for UID %d", - (int)CUPSD_UCRED_UID(peercred)); - krb5_cc_close(KerberosContext, peerccache); - krb5_ipc_client_clear_target(); - return; - } - - if (krb5_unparse_name(KerberosContext, peerprncpl, &peername)) - { - 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(); - return; - } - - strlcpy(username, peername, sizeof(username)); - - con->have_gss = 1; - con->type = CUPSD_AUTH_NEGOTIATE; - - free(peername); - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdAuthorize: Authorized as %s using Negotiate", - username); - - 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 */ @@ -1115,8 +1022,6 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ } # endif /* __APPLE__ */ - con->gss_output_token.length = 0; - /* * Find the start of the Kerberos input token... */ @@ -1155,10 +1060,13 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ GSS_C_NO_CHANNEL_BINDINGS, &client_name, NULL, - &con->gss_output_token, - &con->gss_flags, + &output_token, NULL, - &con->gss_creds); + NULL, + NULL); + + if (output_token.length > 0) + gss_release_buffer(&minor_status, &output_token); if (GSS_ERROR(major_status)) { @@ -1177,10 +1085,6 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ * Get the username associated with the client's credentials... */ - if (!con->gss_creds) - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdAuthorize: No delegated credentials!"); - if (major_status == GSS_S_CONTINUE_NEEDED) cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, "cupsdAuthorize: Credentials not complete"); @@ -1193,7 +1097,6 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ { cupsdLogGSSMessage(CUPSD_LOG_DEBUG, major_status, minor_status, "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); return; @@ -1210,10 +1113,41 @@ cupsdAuthorize(cupsd_client_t *con) /* I - Client connection */ con->type = CUPSD_AUTH_NEGOTIATE; } - else - gss_release_cred(&minor_status, &con->gss_creds); gss_delete_sec_context(&minor_status, &context, GSS_C_NO_BUFFER); + +# if defined(SO_PEERCRED) && defined(AF_LOCAL) + /* + * Get the client's UID if we are printing locally - that allows a backend + * to run as the correct user to get Kerberos credentials of its own. + */ + + if (con->http.hostaddr->addr.sa_family == AF_LOCAL) + { + cupsd_ucred_t peercred; /* Peer credentials */ + socklen_t peersize; /* Size of peer credentials */ + + 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)); + } + else + { + cupsdLogMessage(CUPSD_LOG_DEBUG, + "cupsdAuthorize: Using credentials for UID %d...", + CUPSD_UCRED_UID(peercred)); + con->gss_uid = CUPSD_UCRED_UID(peercred); + } + } +# endif /* SO_PEERCRED && AF_LOCAL */ } #endif /* HAVE_GSSAPI */ else @@ -1597,178 +1531,6 @@ cupsdCheckGroup( } -#ifdef HAVE_GSSAPI -/* - * 'cupsdCopyKrb5Creds()' - Get a copy of the Kerberos credentials. - */ - -krb5_ccache /* O - Credentials or NULL */ -cupsdCopyKrb5Creds(cupsd_client_t *con) /* I - Client connection */ -{ -# if !defined(HAVE_KRB5_CC_NEW_UNIQUE) && !defined(HAVE_HEIMDAL) - cupsdLogMessage(CUPSD_LOG_INFO, - "Sorry, your version of Kerberos does not support delegated " - "credentials!"); - return (NULL); - -# else - krb5_ccache ccache = NULL; /* Credentials */ - krb5_error_code error; /* Kerberos error code */ - OM_uint32 major_status, /* Major status code */ - minor_status; /* Minor status code */ - krb5_principal principal; /* Kerberos principal */ - - -# ifdef __APPLE__ - /* - * If the weak-linked GSSAPI/Kerberos library is not present, don't try - * to use it... - */ - - if (krb5_init_context == NULL) - return (NULL); -# endif /* __APPLE__ */ - - if (!KerberosInitialized) - { - /* - * Setup a Kerberos context for the scheduler to use... - */ - - KerberosInitialized = 1; - - if (krb5_init_context(&KerberosContext)) - { - KerberosContext = NULL; - - cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to initialize Kerberos context"); - return (NULL); - } - } - - /* - * We MUST create a file-based cache because memory-based caches are - * only valid for the current process/address space. - * - * Due to various bugs/features in different versions of Kerberos, we - * need either the krb5_cc_new_unique() function or Heimdal's version - * of krb5_cc_gen_new() to create a new FILE: credential cache that - * can be passed to the backend. These functions create a temporary - * file (typically in /tmp) containing the cached credentials, which - * are removed when we have successfully printed a job. - */ - -# ifdef HAVE_KRB5_CC_NEW_UNIQUE - if ((error = krb5_cc_new_unique(KerberosContext, "FILE", NULL, &ccache)) != 0) -# else /* HAVE_HEIMDAL */ - if ((error = krb5_cc_gen_new(KerberosContext, &krb5_fcc_ops, &ccache)) != 0) -# endif /* HAVE_KRB5_CC_NEW_UNIQUE */ - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to create new credentials cache (%d/%s)", - error, strerror(errno)); - return (NULL); - } - - if ((error = krb5_parse_name(KerberosContext, con->username, &principal)) != 0) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to parse kerberos username (%d/%s)", error, - strerror(errno)); - krb5_cc_destroy(KerberosContext, ccache); - return (NULL); - } - - if ((error = krb5_cc_initialize(KerberosContext, ccache, principal))) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to initialize credentials cache (%d/%s)", error, - strerror(errno)); - krb5_cc_destroy(KerberosContext, ccache); - krb5_free_principal(KerberosContext, principal); - return (NULL); - } - - krb5_free_principal(KerberosContext, principal); - - /* - * Copy the user's credentials to the new cache file... - */ - -# ifdef HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID - if (con->http.hostaddr->addr.sa_family == AF_LOCAL && - !(con->gss_flags & GSS_C_DELEG_FLAG)) - { - /* - * Pull the credentials directly from the user... - */ - - cupsd_ucred_t peercred; /* Peer credentials */ - socklen_t peersize; /* Size of peer credentials */ - krb5_ccache peerccache; /* Peer Kerberos credentials */ - - 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)); - krb5_cc_destroy(KerberosContext, ccache); - return (NULL); - } - - cupsdLogMessage(CUPSD_LOG_DEBUG, - "cupsdCopyKrb5Creds: 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)); - krb5_cc_destroy(KerberosContext, ccache); - return (NULL); - } - - error = krb5_cc_copy_creds(KerberosContext, peerccache, ccache); - krb5_cc_close(KerberosContext, peerccache); - krb5_ipc_client_clear_target(); - - if (error) - { - cupsdLogMessage(CUPSD_LOG_ERROR, - "Unable to copy credentials cache for UID %d (%d/%s)", - (int)CUPSD_UCRED_UID(peercred), error, strerror(errno)); - krb5_cc_destroy(KerberosContext, ccache); - return (NULL); - } - } - else -# endif /* HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID */ - { - major_status = gss_krb5_copy_ccache(&minor_status, con->gss_creds, ccache); - - if (GSS_ERROR(major_status)) - { - cupsdLogGSSMessage(CUPSD_LOG_ERROR, major_status, minor_status, - "Unable to copy client credentials cache"); - krb5_cc_destroy(KerberosContext, ccache); - return (NULL); - } - } - - return (ccache); -# endif /* !HAVE_KRB5_CC_NEW_UNIQUE && !HAVE_HEIMDAL */ -} -#endif /* HAVE_GSSAPI */ - - /* * 'cupsdCopyLocation()' - Make a copy of a location... */ diff --git a/scheduler/auth.h b/scheduler/auth.h index 5e7525cbc..e836f418c 100644 --- a/scheduler/auth.h +++ b/scheduler/auth.h @@ -3,7 +3,7 @@ * * Authorization definitions for the CUPS scheduler. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2006 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -138,9 +138,6 @@ extern int cupsdCheckAuth(unsigned ip[4], char *name, int namelen, extern int cupsdCheckGroup(const char *username, struct passwd *user, const char *groupname); -#ifdef HAVE_GSSAPI -extern krb5_ccache cupsdCopyKrb5Creds(cupsd_client_t *con); -#endif /* HAVE_GSSAPI */ extern cupsd_location_t *cupsdCopyLocation(cupsd_location_t *loc); extern void cupsdDeleteAllLocations(void); extern cupsd_location_t *cupsdFindBest(const char *path, http_state_t state); diff --git a/scheduler/client.c b/scheduler/client.c index f1f219e0c..5db08bd39 100644 --- a/scheduler/client.c +++ b/scheduler/client.c @@ -859,12 +859,7 @@ cupsdReadClient(cupsd_client_t *con) /* I - Client to read from */ #ifdef HAVE_GSSAPI con->have_gss = 0; - - if (con->gss_creds) - { - OM_uint32 minor_status; - gss_release_cred(&minor_status, &con->gss_creds); - } + con->gss_uid = 0; #endif /* HAVE_GSSAPI */ /* @@ -2548,7 +2543,7 @@ cupsdSendHeader( int auth_type) /* I - Type of authentication */ { char auth_str[1024]; /* Authorization string */ -#ifdef HAVE_GSSAPI +#if 0 /* def HAVE_GSSAPI */ static char *gss_buf = NULL; /* Kerberos auth data buffer */ static int gss_bufsize = 0; /* Size of Kerberos auth data buffer */ #endif /* HAVE_GSSAPI */ @@ -2619,7 +2614,7 @@ cupsdSendHeader( snprintf(auth_str, sizeof(auth_str), "Digest realm=\"CUPS\", nonce=\"%s\"", con->http.hostname); #ifdef HAVE_GSSAPI - else if (auth_type == CUPSD_AUTH_NEGOTIATE && con->gss_output_token.length == 0) + else if (auth_type == CUPSD_AUTH_NEGOTIATE /* && con->gss_output_token.length == 0 */) strlcpy(auth_str, "Negotiate", sizeof(auth_str)); #endif /* HAVE_GSSAPI */ @@ -2660,7 +2655,7 @@ cupsdSendHeader( #ifdef HAVE_AUTHORIZATION_H if (SystemGroupAuthKey) snprintf(auth_key, auth_size, - ", authkey=\"%s\", trc=\"y\"", + ", authkey=\"%s\"", SystemGroupAuthKey); else #else @@ -2682,7 +2677,7 @@ cupsdSendHeader( } } -#ifdef HAVE_GSSAPI +#if 0 /* def HAVE_GSSAPI */ /* * WWW-Authenticate: Negotiate can be included even for * non-401 replies... @@ -4966,15 +4961,6 @@ pipe_command(cupsd_client_t *con, /* I - Client connection */ snprintf(remote_user, sizeof(remote_user), "REMOTE_USER=%s", con->username); envp[envc ++] = remote_user; - - /* - * Save Kerberos credentials, if any... - */ - -#ifdef HAVE_GSSAPI - if (con->gss_creds) - ccache = cupsdCopyKrb5Creds(con); -#endif /* HAVE_GSSAPI */ } if (con->http.version == HTTP_1_1) diff --git a/scheduler/client.h b/scheduler/client.h index a88f9dcef..ded57bd75 100644 --- a/scheduler/client.h +++ b/scheduler/client.h @@ -3,7 +3,7 @@ * * Client definitions for the CUPS scheduler. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -56,10 +56,7 @@ struct cupsd_client_s int serverport; /* Server port for connection */ #ifdef HAVE_GSSAPI int have_gss; /* Have GSS credentials? */ - gss_cred_id_t gss_creds; /* Delegated credentials from client */ - unsigned gss_flags; /* Credential flags */ - gss_buffer_desc gss_output_token; - /* Output token for Negotiate header */ + uid_t gss_uid; /* User ID for local prints */ #endif /* HAVE_GSSAPI */ #ifdef HAVE_AUTHORIZATION_H AuthorizationRef authref; /* Authorization ref */ diff --git a/scheduler/cups-driverd.cxx b/scheduler/cups-driverd.cxx index 5ddf5b3cf..8f78df3b8 100644 --- a/scheduler/cups-driverd.cxx +++ b/scheduler/cups-driverd.cxx @@ -30,9 +30,9 @@ * dump_ppds_dat() - Dump the contents of the ppds.dat file. * free_array() - Free an array of strings. * list_ppds() - List PPD files. - * load_ppds() - Load PPD files recursively. * load_drv() - Load the PPDs from a driver information file. * load_drivers() - Load driver-generated PPD files. + * load_ppds() - Load PPD files recursively. * load_ppds_dat() - Load the ppds.dat file. * regex_device_id() - Compile a regular expression based on the 1284 device * ID. @@ -922,11 +922,14 @@ list_ppds(int request_id, /* I - Request ID */ if (ChangedPPD) { - if ((fp = cupsFileOpen(filename, "w")) != NULL) + char newname[1024]; /* New filename */ + + snprintf(newname, sizeof(newname), "%s.%d", filename, (int)getpid()); + + if ((fp = cupsFileOpen(newname, "w")) != NULL) { unsigned ppdsync = PPD_SYNC; /* Sync word */ - cupsFileWrite(fp, (char *)&ppdsync, sizeof(ppdsync)); for (ppd = (ppd_info_t *)cupsArrayFirst(PPDsByName); @@ -936,8 +939,12 @@ list_ppds(int request_id, /* I - Request ID */ cupsFileClose(fp); - fprintf(stderr, "INFO: [cups-driverd] Wrote \"%s\", %d PPDs...\n", - filename, cupsArrayCount(PPDsByName)); + if (rename(newname, filename)) + fprintf(stderr, "ERROR: [cups-driverd] Unable to rename \"%s\" - %s\n", + newname, strerror(errno)); + else + fprintf(stderr, "INFO: [cups-driverd] Wrote \"%s\", %d PPDs...\n", + filename, cupsArrayCount(PPDsByName)); } else fprintf(stderr, "ERROR: [cups-driverd] Unable to write \"%s\" - %s\n", @@ -1337,931 +1344,931 @@ list_ppds(int request_id, /* I - Request ID */ /* - * 'load_ppds()' - Load PPD files recursively. + * 'load_drv()' - Load the PPDs from a driver information file. */ static int /* O - 1 on success, 0 on failure */ -load_ppds(const char *d, /* I - Actual directory */ - const char *p, /* I - Virtual path in name */ - int descend) /* I - Descend into directories? */ +load_drv(const char *filename, /* I - Actual filename */ + const char *name, /* I - Name to the rest of the world */ + cups_file_t *fp, /* I - File to read from */ + time_t mtime, /* I - Mod time of driver info file */ + off_t size) /* I - Size of driver info file */ { - struct stat dinfo, /* Directory information */ - *dinfoptr; /* Pointer to match */ - int i; /* Looping var */ - cups_file_t *fp; /* Pointer to file */ - cups_dir_t *dir; /* Directory pointer */ - cups_dentry_t *dent; /* Directory entry */ - char filename[1024], /* Name of PPD or directory */ - line[256], /* Line from backend */ - *ptr, /* Pointer into name */ - name[128], /* Name of PPD file */ - lang_version[64], /* PPD LanguageVersion */ - lang_encoding[64], /* PPD LanguageEncoding */ - country[64], /* Country code */ - manufacturer[256], /* Manufacturer */ - make_model[256], /* Make and Model */ - model_name[256], /* ModelName */ - nick_name[256], /* NickName */ - device_id[256], /* 1284DeviceID */ - product[256], /* Product */ - psversion[256], /* PSVersion */ - temp[512]; /* Temporary make and model */ - int model_number, /* cupsModelNumber */ - type; /* ppd-type */ - cups_array_t *products, /* Product array */ - *psversions, /* PSVersion array */ - *cups_languages; /* cupsLanguages array */ - ppd_info_t *ppd, /* New PPD file */ - key; /* Search key */ - int new_ppd; /* Is this a new PPD? */ - struct /* LanguageVersion translation table */ - { - const char *version, /* LanguageVersion string */ - *language; /* Language code */ - } languages[] = - { - { "chinese", "zh" }, - { "czech", "cs" }, - { "danish", "da" }, - { "dutch", "nl" }, - { "english", "en" }, - { "finnish", "fi" }, - { "french", "fr" }, - { "german", "de" }, - { "greek", "el" }, - { "hungarian", "hu" }, - { "italian", "it" }, - { "japanese", "ja" }, - { "korean", "ko" }, - { "norwegian", "no" }, - { "polish", "pl" }, - { "portuguese", "pt" }, - { "russian", "ru" }, - { "simplified chinese", "zh_CN" }, - { "slovak", "sk" }, - { "spanish", "es" }, - { "swedish", "sv" }, - { "traditional chinese", "zh_TW" }, - { "turkish", "tr" } - }; + ppdcSource *src; // Driver information file + ppdcDriver *d; // Current driver + ppdcAttr *device_id, // 1284DeviceID attribute + *product, // Current product value + *ps_version, // PSVersion attribute + *cups_fax, // cupsFax attribute + *nick_name; // NickName attribute + ppdcFilter *filter; // Current filter + ppd_info_t *ppd; // Current PPD + int products_found; // Number of products found + char uri[1024], // Driver URI + make_model[1024]; // Make and model + int type; // Driver type /* - * See if we've loaded this directory before... + * Load the driver info file... */ - if (stat(d, &dinfo)) - { - if (errno != ENOENT) - fprintf(stderr, "ERROR: [cups-driverd] Unable to stat \"%s\": %s\n", d, - strerror(errno)); + src = new ppdcSource(filename, fp); - return (0); - } - else if (cupsArrayFind(Inodes, &dinfo)) + if (src->drivers->count == 0) { - fprintf(stderr, "ERROR: [cups-driverd] Skipping \"%s\": loop detected!\n", - d); + fprintf(stderr, + "ERROR: [cups-driverd] Bad driver information file \"%s\"!\n", + filename); + src->release(); return (0); } /* - * Nope, add it to the Inodes array and continue... + * Add a dummy entry for the file... */ - dinfoptr = (struct stat *)malloc(sizeof(struct stat)); - memcpy(dinfoptr, &dinfo, sizeof(struct stat)); - cupsArrayAdd(Inodes, dinfoptr); - - if ((dir = cupsDirOpen(d)) == NULL) - { - if (errno != ENOENT) - fprintf(stderr, - "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n", - d, strerror(errno)); - - return (0); - } + add_ppd(name, name, "", "", "", "", "", "", mtime, size, 0, + PPD_TYPE_DRV, "drv"); + ChangedPPD = 1; - fprintf(stderr, "DEBUG: [cups-driverd] Loading \"%s\"...\n", d); + /* + * Then the drivers in the file... + */ - while ((dent = cupsDirRead(dir)) != NULL) + for (d = (ppdcDriver *)src->drivers->first(); + d; + d = (ppdcDriver *)src->drivers->next()) { - /* - * Skip files/directories starting with "."... - */ - - if (dent->filename[0] == '.') - continue; - - /* - * See if this is a file... - */ + httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "drv", "", "", 0, + "/%s/%s", name, + d->file_name ? d->file_name->value : + d->pc_file_name->value); - snprintf(filename, sizeof(filename), "%s/%s", d, dent->filename); + device_id = d->find_attr("1284DeviceID", NULL); + ps_version = d->find_attr("PSVersion", NULL); + nick_name = d->find_attr("NickName", NULL); - if (p[0]) - snprintf(name, sizeof(name), "%s/%s", p, dent->filename); + if (nick_name) + strlcpy(make_model, nick_name->value->value, sizeof(make_model)); + else if (strncasecmp(d->model_name->value, d->manufacturer->value, + strlen(d->manufacturer->value))) + snprintf(make_model, sizeof(make_model), "%s %s, %s", + d->manufacturer->value, d->model_name->value, + d->version->value); else - strlcpy(name, dent->filename, sizeof(name)); - - if (S_ISDIR(dent->fileinfo.st_mode)) - { - /* - * Do subdirectory... - */ - - if (descend) - if (!load_ppds(filename, name, 1)) - { - cupsDirClose(dir); - return (1); - } + snprintf(make_model, sizeof(make_model), "%s, %s", d->model_name->value, + d->version->value); - continue; - } - else if ((ptr = filename + strlen(filename) - 6) > filename && - !strcmp(ptr, ".plist")) + if ((cups_fax = d->find_attr("cupsFax", NULL)) != NULL && + !strcasecmp(cups_fax->value->value, "true")) + type = PPD_TYPE_FAX; + else if (d->type == PPDC_DRIVER_PS) + type = PPD_TYPE_POSTSCRIPT; + else if (d->type != PPDC_DRIVER_CUSTOM) + type = PPD_TYPE_RASTER; + else { - /* - * Skip plist files in the PPDs directory... - */ - - continue; + for (filter = (ppdcFilter *)d->filters->first(), + type = PPD_TYPE_POSTSCRIPT; + filter; + filter = (ppdcFilter *)d->filters->next()) + if (strcasecmp(filter->mime_type->value, "application/vnd.cups-raster")) + type = PPD_TYPE_RASTER; + else if (strcasecmp(filter->mime_type->value, + "application/vnd.cups-pdf")) + type = PPD_TYPE_PDF; } - /* - * See if this file has been scanned before... - */ + for (product = (ppdcAttr *)d->attrs->first(), products_found = 0, + ppd = NULL; + product; + product = (ppdcAttr *)d->attrs->next()) + if (!strcmp(product->name->value, "Product")) + { + if (!products_found) + ppd = add_ppd(name, uri, "en", d->manufacturer->value, make_model, + device_id ? device_id->value->value : "", + product->value->value, + ps_version ? ps_version->value->value : "(3010) 0", + mtime, size, d->model_number, type, "drv"); + else if (products_found < PPD_MAX_PROD) + strlcpy(ppd->record.products[products_found], product->value->value, + sizeof(ppd->record.products[0])); + else + break; - strcpy(key.record.filename, name); - strcpy(key.record.name, name); + products_found ++; + } - ppd = (ppd_info_t *)cupsArrayFind(PPDsByName, &key); + if (!products_found) + add_ppd(name, uri, "en", d->manufacturer->value, make_model, + device_id ? device_id->value->value : "", + d->model_name->value, + ps_version ? ps_version->value->value : "(3010) 0", + mtime, size, d->model_number, type, "drv"); + } - if (ppd && - ppd->record.size == dent->fileinfo.st_size && - ppd->record.mtime == dent->fileinfo.st_mtime) - { - /* - * Rewind to the first entry for this file... - */ + src->release(); - while ((ppd = (ppd_info_t *)cupsArrayPrev(PPDsByName)) != NULL && - !strcmp(ppd->record.filename, name)); + return (1); +} - /* - * Then mark all of the matches for this file as found... - */ - while ((ppd = (ppd_info_t *)cupsArrayNext(PPDsByName)) != NULL && - !strcmp(ppd->record.filename, name)) - ppd->found = 1; +/* + * 'load_drivers()' - Load driver-generated PPD files. + */ - continue; - } +static int /* O - 1 on success, 0 on failure */ +load_drivers(cups_array_t *include, /* I - Drivers to include */ + cups_array_t *exclude) /* I - Drivers to exclude */ +{ + int i; /* Looping var */ + char *start, /* Start of value */ + *ptr; /* Pointer into string */ + const char *server_bin, /* CUPS_SERVERBIN env variable */ + *scheme, /* Scheme for this driver */ + *scheme_end; /* Pointer to end of scheme */ + char drivers[1024]; /* Location of driver programs */ + int pid; /* Process ID for driver program */ + cups_file_t *fp; /* Pipe to driver program */ + cups_dir_t *dir; /* Directory pointer */ + cups_dentry_t *dent; /* Directory entry */ + char *argv[3], /* Arguments for command */ + filename[1024], /* Name of driver */ + line[2048], /* Line from driver */ + name[512], /* ppd-name */ + make[128], /* ppd-make */ + make_and_model[128], /* ppd-make-and-model */ + device_id[128], /* ppd-device-id */ + languages[128], /* ppd-natural-language */ + product[128], /* ppd-product */ + psversion[128], /* ppd-psversion */ + type_str[128]; /* ppd-type */ + int type; /* PPD type */ + ppd_info_t *ppd; /* Newly added PPD */ + + + /* + * Try opening the driver directory... + */ + + if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL) + server_bin = CUPS_SERVERBIN; + + snprintf(drivers, sizeof(drivers), "%s/driver", server_bin); + + if ((dir = cupsDirOpen(drivers)) == NULL) + { + fprintf(stderr, "ERROR: [cups-driverd] Unable to open driver directory " + "\"%s\": %s\n", + drivers, strerror(errno)); + return (0); + } + + /* + * Loop through all of the device drivers... + */ + + argv[1] = (char *)"list"; + argv[2] = NULL; + while ((dent = cupsDirRead(dir)) != NULL) + { /* - * No, file is new/changed, so re-scan it... + * Only look at executable files... */ - if ((fp = cupsFileOpen(filename, "r")) == NULL) + if (!(dent->fileinfo.st_mode & 0111) || !S_ISREG(dent->fileinfo.st_mode)) continue; /* - * Now see if this is a PPD file... + * Include/exclude specific drivers... */ - line[0] = '\0'; - cupsFileGets(fp, line, sizeof(line)); + if (exclude) + { + /* + * Look for "scheme" or "scheme*" (prefix match), and skip any matches. + */ - if (strncmp(line, "*PPD-Adobe:", 11)) + for (scheme = (char *)cupsArrayFirst(exclude); + scheme; + scheme = (char *)cupsArrayNext(exclude)) + { + fprintf(stderr, "DEBUG: [cups-driverd] Exclude \"%s\" with \"%s\"?\n", + dent->filename, scheme); + scheme_end = scheme + strlen(scheme) - 1; + + if ((scheme_end > scheme && *scheme_end == '*' && + !strncmp(scheme, dent->filename, scheme_end - scheme)) || + !strcmp(scheme, dent->filename)) + { + fputs("DEBUG: [cups-driverd] Yes, exclude!\n", stderr); + break; + } + } + + if (scheme) + continue; + } + + if (include) { /* - * Nope, treat it as a driver information file... + * Look for "scheme" or "scheme*" (prefix match), and skip any non-matches. */ - load_drv(filename, name, fp, dent->fileinfo.st_mtime, - dent->fileinfo.st_size); - continue; + for (scheme = (char *)cupsArrayFirst(include); + scheme; + scheme = (char *)cupsArrayNext(include)) + { + fprintf(stderr, "DEBUG: [cups-driverd] Include \"%s\" with \"%s\"?\n", + dent->filename, scheme); + scheme_end = scheme + strlen(scheme) - 1; + + if ((scheme_end > scheme && *scheme_end == '*' && + !strncmp(scheme, dent->filename, scheme_end - scheme)) || + !strcmp(scheme, dent->filename)) + { + fputs("DEBUG: [cups-driverd] Yes, include!\n", stderr); + break; + } + } + + if (!scheme) + continue; } + else + scheme = dent->filename; /* - * Now read until we get the NickName field... + * Run the driver with no arguments and collect the output... */ - cups_languages = cupsArrayNew(NULL, NULL); - products = cupsArrayNew(NULL, NULL); - psversions = cupsArrayNew(NULL, NULL); - - model_name[0] = '\0'; - nick_name[0] = '\0'; - manufacturer[0] = '\0'; - device_id[0] = '\0'; - lang_encoding[0] = '\0'; - strcpy(lang_version, "en"); - model_number = 0; - type = PPD_TYPE_POSTSCRIPT; + argv[0] = dent->filename; + snprintf(filename, sizeof(filename), "%s/%s", drivers, dent->filename); - while (cupsFileGets(fp, line, sizeof(line)) != NULL) + if ((fp = cupsdPipeCommand(&pid, filename, argv, 0)) != NULL) { - if (!strncmp(line, "*Manufacturer:", 14)) - sscanf(line, "%*[^\"]\"%255[^\"]", manufacturer); - else if (!strncmp(line, "*ModelName:", 11)) - sscanf(line, "%*[^\"]\"%127[^\"]", model_name); - else if (!strncmp(line, "*LanguageEncoding:", 18)) - sscanf(line, "%*[^:]:%63s", lang_encoding); - else if (!strncmp(line, "*LanguageVersion:", 17)) - sscanf(line, "%*[^:]:%63s", lang_version); - else if (!strncmp(line, "*NickName:", 10)) - sscanf(line, "%*[^\"]\"%255[^\"]", nick_name); - else if (!strncasecmp(line, "*1284DeviceID:", 14)) + while (cupsFileGets(fp, line, sizeof(line))) { - sscanf(line, "%*[^\"]\"%255[^\"]", device_id); + /* + * Each line is of the form: + * + * "ppd-name" ppd-natural-language "ppd-make" "ppd-make-and-model" \ + * "ppd-device-id" "ppd-product" "ppd-psversion" + */ - // Make sure device ID ends with a semicolon... - if (device_id[0] && device_id[strlen(device_id) - 1] != ';') - strlcat(device_id, ";", sizeof(device_id)); - } - else if (!strncmp(line, "*Product:", 9)) - { - if (sscanf(line, "%*[^\"]\"(%255[^\"]", product) == 1) + device_id[0] = '\0'; + product[0] = '\0'; + psversion[0] = '\0'; + strcpy(type_str, "postscript"); + + if (sscanf(line, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\"" + "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"" + "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"" + "%*[ \t]\"%127[^\"]\"", + name, languages, make, make_and_model, + device_id, product, psversion, type_str) < 4) + { + /* + * Bad format; strip trailing newline and write an error message. + */ + + if (line[strlen(line) - 1] == '\n') + line[strlen(line) - 1] = '\0'; + + fprintf(stderr, "ERROR: [cups-driverd] Bad line from \"%s\": %s\n", + dent->filename, line); + break; + } + else { /* - * Make sure the value ends with a right parenthesis - can't stop at - * the first right paren since the product name may contain escaped - * parenthesis... + * Add the device to the array of available devices... */ - ptr = product + strlen(product) - 1; - if (ptr > product && *ptr == ')') - { - /* - * Yes, ends with a parenthesis, so remove it from the end and - * add the product to the list... - */ + if ((start = strchr(languages, ',')) != NULL) + *start++ = '\0'; - *ptr = '\0'; - cupsArrayAdd(products, strdup(product)); - } - } - } - else if (!strncmp(line, "*PSVersion:", 11)) - { - sscanf(line, "%*[^\"]\"%255[^\"]", psversion); - cupsArrayAdd(psversions, strdup(psversion)); - } - else if (!strncmp(line, "*cupsLanguages:", 15)) - { - char *start; /* Start of language */ + for (type = 0; + type < (int)(sizeof(ppd_types) / sizeof(ppd_types[0])); + type ++) + if (!strcmp(type_str, ppd_types[type])) + break; + if (type >= (int)(sizeof(ppd_types) / sizeof(ppd_types[0]))) + { + fprintf(stderr, + "ERROR: [cups-driverd] Bad ppd-type \"%s\" ignored!\n", + type_str); + type = PPD_TYPE_UNKNOWN; + } - for (start = line + 15; *start && isspace(*start & 255); start ++); + ppd = add_ppd(filename, name, languages, make, make_and_model, + device_id, product, psversion, 0, 0, 0, type, scheme); - if (*start++ == '\"') - { - while (*start) + if (!ppd) { - for (ptr = start + 1; - *ptr && *ptr != '\"' && !isspace(*ptr & 255); - ptr ++); + cupsDirClose(dir); + cupsFileClose(fp); + return (0); + } - if (*ptr) + if (start && *start) + { + for (i = 1; i < PPD_MAX_LANG && *start; i ++) { - *ptr++ = '\0'; - - while (isspace(*ptr & 255)) + if ((ptr = strchr(start, ',')) != NULL) *ptr++ = '\0'; - } + else + ptr = start + strlen(start); - cupsArrayAdd(cups_languages, strdup(start)); - start = ptr; - } - } - } - else if (!strncmp(line, "*cupsFax:", 9)) - { - for (ptr = line + 9; isspace(*ptr & 255); ptr ++); + strlcpy(ppd->record.languages[i], start, + sizeof(ppd->record.languages[0])); - if (!strncasecmp(ptr, "true", 4)) - type = PPD_TYPE_FAX; - } - else if (!strncmp(line, "*cupsFilter:", 12) && type == PPD_TYPE_POSTSCRIPT) - { - if (strstr(line + 12, "application/vnd.cups-raster")) - type = PPD_TYPE_RASTER; - else if (strstr(line + 12, "application/vnd.cups-pdf")) - type = PPD_TYPE_PDF; - } - else if (!strncmp(line, "*cupsModelNumber:", 17)) - sscanf(line, "*cupsModelNumber:%d", &model_number); - else if (!strncmp(line, "*OpenUI", 7)) - { - /* - * Stop early if we have a NickName or ModelName attributes - * before the first OpenUI... - */ + start = ptr; + } + } - if ((model_name[0] || nick_name[0]) && cupsArrayCount(products) > 0 && - cupsArrayCount(psversions) > 0) - break; + fprintf(stderr, "DEBUG2: [cups-driverd] Added dynamic PPD \"%s\"...\n", + name); + } } + + cupsFileClose(fp); } + else + fprintf(stderr, "WARNING: [cups-driverd] Unable to execute \"%s\": %s\n", + filename, strerror(errno)); + } - /* - * Close the file... - */ + cupsDirClose(dir); - cupsFileClose(fp); + return (1); +} - /* - * See if we got all of the required info... - */ - if (nick_name[0]) - cupsCharsetToUTF8((cups_utf8_t *)make_model, nick_name, - sizeof(make_model), _ppdGetEncoding(lang_encoding)); - else - strcpy(make_model, model_name); +/* + * 'load_ppds()' - Load PPD files recursively. + */ - while (isspace(make_model[0] & 255)) - _cups_strcpy(make_model, make_model + 1); +static int /* O - 1 on success, 0 on failure */ +load_ppds(const char *d, /* I - Actual directory */ + const char *p, /* I - Virtual path in name */ + int descend) /* I - Descend into directories? */ +{ + struct stat dinfo, /* Directory information */ + *dinfoptr; /* Pointer to match */ + int i; /* Looping var */ + cups_file_t *fp; /* Pointer to file */ + cups_dir_t *dir; /* Directory pointer */ + cups_dentry_t *dent; /* Directory entry */ + char filename[1024], /* Name of PPD or directory */ + line[256], /* Line from backend */ + *ptr, /* Pointer into name */ + name[128], /* Name of PPD file */ + lang_version[64], /* PPD LanguageVersion */ + lang_encoding[64], /* PPD LanguageEncoding */ + country[64], /* Country code */ + manufacturer[256], /* Manufacturer */ + make_model[256], /* Make and Model */ + model_name[256], /* ModelName */ + nick_name[256], /* NickName */ + device_id[256], /* 1284DeviceID */ + product[256], /* Product */ + psversion[256], /* PSVersion */ + temp[512]; /* Temporary make and model */ + int model_number, /* cupsModelNumber */ + type; /* ppd-type */ + cups_array_t *products, /* Product array */ + *psversions, /* PSVersion array */ + *cups_languages; /* cupsLanguages array */ + ppd_info_t *ppd, /* New PPD file */ + key; /* Search key */ + int new_ppd; /* Is this a new PPD? */ + struct /* LanguageVersion translation table */ + { + const char *version, /* LanguageVersion string */ + *language; /* Language code */ + } languages[] = + { + { "chinese", "zh" }, + { "czech", "cs" }, + { "danish", "da" }, + { "dutch", "nl" }, + { "english", "en" }, + { "finnish", "fi" }, + { "french", "fr" }, + { "german", "de" }, + { "greek", "el" }, + { "hungarian", "hu" }, + { "italian", "it" }, + { "japanese", "ja" }, + { "korean", "ko" }, + { "norwegian", "no" }, + { "polish", "pl" }, + { "portuguese", "pt" }, + { "russian", "ru" }, + { "simplified chinese", "zh_CN" }, + { "slovak", "sk" }, + { "spanish", "es" }, + { "swedish", "sv" }, + { "traditional chinese", "zh_TW" }, + { "turkish", "tr" } + }; - if (!make_model[0] || cupsArrayCount(products) == 0 || - cupsArrayCount(psversions) == 0) - { - /* - * We don't have all the info needed, so skip this file... - */ - if (!make_model[0]) - fprintf(stderr, "WARNING: Missing NickName and ModelName in %s!\n", - filename); + /* + * See if we've loaded this directory before... + */ - if (cupsArrayCount(products) == 0) - fprintf(stderr, "WARNING: Missing Product in %s!\n", filename); + if (stat(d, &dinfo)) + { + if (errno != ENOENT) + fprintf(stderr, "ERROR: [cups-driverd] Unable to stat \"%s\": %s\n", d, + strerror(errno)); - if (cupsArrayCount(psversions) == 0) - fprintf(stderr, "WARNING: Missing PSVersion in %s!\n", filename); + return (0); + } + else if (cupsArrayFind(Inodes, &dinfo)) + { + fprintf(stderr, "ERROR: [cups-driverd] Skipping \"%s\": loop detected!\n", + d); + return (0); + } - free_array(products); - free_array(psversions); - free_array(cups_languages); + /* + * Nope, add it to the Inodes array and continue... + */ - continue; - } + dinfoptr = (struct stat *)malloc(sizeof(struct stat)); + memcpy(dinfoptr, &dinfo, sizeof(struct stat)); + cupsArrayAdd(Inodes, dinfoptr); - if (model_name[0]) - cupsArrayAdd(products, strdup(model_name)); + if ((dir = cupsDirOpen(d)) == NULL) + { + if (errno != ENOENT) + fprintf(stderr, + "ERROR: [cups-driverd] Unable to open PPD directory \"%s\": %s\n", + d, strerror(errno)); - /* - * Normalize the make and model string... - */ + return (0); + } - while (isspace(manufacturer[0] & 255)) - _cups_strcpy(manufacturer, manufacturer + 1); + fprintf(stderr, "DEBUG: [cups-driverd] Loading \"%s\"...\n", d); - if (!strncasecmp(make_model, manufacturer, strlen(manufacturer))) - strlcpy(temp, make_model, sizeof(temp)); - else - snprintf(temp, sizeof(temp), "%s %s", manufacturer, make_model); + while ((dent = cupsDirRead(dir)) != NULL) + { + /* + * Skip files/directories starting with "."... + */ - _ppdNormalizeMakeAndModel(temp, make_model, sizeof(make_model)); + if (dent->filename[0] == '.') + continue; /* - * See if we got a manufacturer... + * See if this is a file... */ - if (!manufacturer[0] || !strcmp(manufacturer, "ESP")) + snprintf(filename, sizeof(filename), "%s/%s", d, dent->filename); + + if (p[0]) + snprintf(name, sizeof(name), "%s/%s", p, dent->filename); + else + strlcpy(name, dent->filename, sizeof(name)); + + if (S_ISDIR(dent->fileinfo.st_mode)) { /* - * Nope, copy the first part of the make and model then... + * Do subdirectory... */ - strlcpy(manufacturer, make_model, sizeof(manufacturer)); + if (descend) + if (!load_ppds(filename, name, 1)) + { + cupsDirClose(dir); + return (1); + } + continue; + } + else if ((ptr = filename + strlen(filename) - 6) > filename && + !strcmp(ptr, ".plist")) + { /* - * Truncate at the first space, dash, or slash, or make the - * manufacturer "Other"... + * Skip plist files in the PPDs directory... */ - for (ptr = manufacturer; *ptr; ptr ++) - if (*ptr == ' ' || *ptr == '-' || *ptr == '/') - break; - - if (*ptr && ptr > manufacturer) - *ptr = '\0'; - else - strcpy(manufacturer, "Other"); + continue; } - else if (!strncasecmp(manufacturer, "LHAG", 4) || - !strncasecmp(manufacturer, "linotype", 8)) - strcpy(manufacturer, "LHAG"); - else if (!strncasecmp(manufacturer, "Hewlett", 7)) - strcpy(manufacturer, "HP"); /* - * Fix the lang_version as needed... + * See if this file has been scanned before... */ - if ((ptr = strchr(lang_version, '-')) != NULL) - *ptr++ = '\0'; - else if ((ptr = strchr(lang_version, '_')) != NULL) - *ptr++ = '\0'; + strcpy(key.record.filename, name); + strcpy(key.record.name, name); - if (ptr) + ppd = (ppd_info_t *)cupsArrayFind(PPDsByName, &key); + + if (ppd && + ppd->record.size == dent->fileinfo.st_size && + ppd->record.mtime == dent->fileinfo.st_mtime) { /* - * Setup the country suffix... + * Rewind to the first entry for this file... */ - country[0] = '_'; - _cups_strcpy(country + 1, ptr); - } - else - { + while ((ppd = (ppd_info_t *)cupsArrayPrev(PPDsByName)) != NULL && + !strcmp(ppd->record.filename, name)); + /* - * No country suffix... + * Then mark all of the matches for this file as found... */ - country[0] = '\0'; - } - - for (i = 0; i < (int)(sizeof(languages) / sizeof(languages[0])); i ++) - if (!strcasecmp(languages[i].version, lang_version)) - break; - - if (i < (int)(sizeof(languages) / sizeof(languages[0]))) - { - /* - * Found a known language... - */ - - snprintf(lang_version, sizeof(lang_version), "%s%s", - languages[i].language, country); - } - else - { - /* - * Unknown language; use "xx"... - */ + while ((ppd = (ppd_info_t *)cupsArrayNext(PPDsByName)) != NULL && + !strcmp(ppd->record.filename, name)) + ppd->found = 1; - strcpy(lang_version, "xx"); + continue; } /* - * Record the PPD file... + * No, file is new/changed, so re-scan it... */ - new_ppd = !ppd; - - if (new_ppd) - { - /* - * Add new PPD file... - */ + if ((fp = cupsFileOpen(filename, "r")) == NULL) + continue; - fprintf(stderr, "DEBUG2: [cups-driverd] Adding ppd \"%s\"...\n", name); + /* + * Now see if this is a PPD file... + */ - ppd = add_ppd(name, name, lang_version, manufacturer, make_model, - device_id, (char *)cupsArrayFirst(products), - (char *)cupsArrayFirst(psversions), - dent->fileinfo.st_mtime, dent->fileinfo.st_size, - model_number, type, "file"); + line[0] = '\0'; + cupsFileGets(fp, line, sizeof(line)); - if (!ppd) - { - cupsDirClose(dir); - return (0); - } - } - else + if (strncmp(line, "*PPD-Adobe:", 11)) { /* - * Update existing record... + * Nope, treat it as a driver information file... */ - fprintf(stderr, "DEBUG2: [cups-driverd] Updating ppd \"%s\"...\n", name); - - memset(ppd, 0, sizeof(ppd_info_t)); - - ppd->found = 1; - ppd->record.mtime = dent->fileinfo.st_mtime; - ppd->record.size = dent->fileinfo.st_size; - ppd->record.model_number = model_number; - ppd->record.type = type; - - strlcpy(ppd->record.name, name, sizeof(ppd->record.name)); - strlcpy(ppd->record.make, manufacturer, sizeof(ppd->record.make)); - strlcpy(ppd->record.make_and_model, make_model, - sizeof(ppd->record.make_and_model)); - strlcpy(ppd->record.languages[0], lang_version, - sizeof(ppd->record.languages[0])); - strlcpy(ppd->record.products[0], (char *)cupsArrayFirst(products), - sizeof(ppd->record.products[0])); - strlcpy(ppd->record.psversions[0], (char *)cupsArrayFirst(psversions), - sizeof(ppd->record.psversions[0])); - strlcpy(ppd->record.device_id, device_id, sizeof(ppd->record.device_id)); + load_drv(filename, name, fp, dent->fileinfo.st_mtime, + dent->fileinfo.st_size); + continue; } /* - * Add remaining products, versions, and languages... - */ - - for (i = 1; - i < PPD_MAX_PROD && (ptr = (char *)cupsArrayNext(products)) != NULL; - i ++) - strlcpy(ppd->record.products[i], ptr, - sizeof(ppd->record.products[0])); - - for (i = 1; - i < PPD_MAX_VERS && (ptr = (char *)cupsArrayNext(psversions)) != NULL; - i ++) - strlcpy(ppd->record.psversions[i], ptr, - sizeof(ppd->record.psversions[0])); - - for (i = 1, ptr = (char *)cupsArrayFirst(cups_languages); - i < PPD_MAX_LANG && ptr; - i ++, ptr = (char *)cupsArrayNext(cups_languages)) - strlcpy(ppd->record.languages[i], ptr, - sizeof(ppd->record.languages[0])); - - /* - * Free products, versions, and languages... + * Now read until we get the NickName field... */ - free_array(cups_languages); - free_array(products); - free_array(psversions); - - ChangedPPD = 1; - } - - cupsDirClose(dir); - - return (1); -} - - -/* - * 'load_drv()' - Load the PPDs from a driver information file. - */ + cups_languages = cupsArrayNew(NULL, NULL); + products = cupsArrayNew(NULL, NULL); + psversions = cupsArrayNew(NULL, NULL); -static int /* O - 1 on success, 0 on failure */ -load_drv(const char *filename, /* I - Actual filename */ - const char *name, /* I - Name to the rest of the world */ - cups_file_t *fp, /* I - File to read from */ - time_t mtime, /* I - Mod time of driver info file */ - off_t size) /* I - Size of driver info file */ -{ - ppdcSource *src; // Driver information file - ppdcDriver *d; // Current driver - ppdcAttr *device_id, // 1284DeviceID attribute - *product, // Current product value - *ps_version, // PSVersion attribute - *cups_fax, // cupsFax attribute - *nick_name; // NickName attribute - ppdcFilter *filter; // Current filter - ppd_info_t *ppd; // Current PPD - int products_found; // Number of products found - char uri[1024], // Driver URI - make_model[1024]; // Make and model - int type; // Driver type + model_name[0] = '\0'; + nick_name[0] = '\0'; + manufacturer[0] = '\0'; + device_id[0] = '\0'; + lang_encoding[0] = '\0'; + strcpy(lang_version, "en"); + model_number = 0; + type = PPD_TYPE_POSTSCRIPT; + while (cupsFileGets(fp, line, sizeof(line)) != NULL) + { + if (!strncmp(line, "*Manufacturer:", 14)) + sscanf(line, "%*[^\"]\"%255[^\"]", manufacturer); + else if (!strncmp(line, "*ModelName:", 11)) + sscanf(line, "%*[^\"]\"%127[^\"]", model_name); + else if (!strncmp(line, "*LanguageEncoding:", 18)) + sscanf(line, "%*[^:]:%63s", lang_encoding); + else if (!strncmp(line, "*LanguageVersion:", 17)) + sscanf(line, "%*[^:]:%63s", lang_version); + else if (!strncmp(line, "*NickName:", 10)) + sscanf(line, "%*[^\"]\"%255[^\"]", nick_name); + else if (!strncasecmp(line, "*1284DeviceID:", 14)) + { + sscanf(line, "%*[^\"]\"%255[^\"]", device_id); - /* - * Load the driver info file... - */ + // Make sure device ID ends with a semicolon... + if (device_id[0] && device_id[strlen(device_id) - 1] != ';') + strlcat(device_id, ";", sizeof(device_id)); + } + else if (!strncmp(line, "*Product:", 9)) + { + if (sscanf(line, "%*[^\"]\"(%255[^\"]", product) == 1) + { + /* + * Make sure the value ends with a right parenthesis - can't stop at + * the first right paren since the product name may contain escaped + * parenthesis... + */ - src = new ppdcSource(filename, fp); + ptr = product + strlen(product) - 1; + if (ptr > product && *ptr == ')') + { + /* + * Yes, ends with a parenthesis, so remove it from the end and + * add the product to the list... + */ - if (src->drivers->count == 0) - { - fprintf(stderr, - "ERROR: [cups-driverd] Bad driver information file \"%s\"!\n", - filename); - src->release(); - return (0); - } + *ptr = '\0'; + cupsArrayAdd(products, strdup(product)); + } + } + } + else if (!strncmp(line, "*PSVersion:", 11)) + { + sscanf(line, "%*[^\"]\"%255[^\"]", psversion); + cupsArrayAdd(psversions, strdup(psversion)); + } + else if (!strncmp(line, "*cupsLanguages:", 15)) + { + char *start; /* Start of language */ - /* - * Add a dummy entry for the file... - */ - add_ppd(name, name, "", "", "", "", "", "", mtime, size, 0, - PPD_TYPE_DRV, "drv"); - ChangedPPD = 1; + for (start = line + 15; *start && isspace(*start & 255); start ++); - /* - * Then the drivers in the file... - */ + if (*start++ == '\"') + { + while (*start) + { + for (ptr = start + 1; + *ptr && *ptr != '\"' && !isspace(*ptr & 255); + ptr ++); - for (d = (ppdcDriver *)src->drivers->first(); - d; - d = (ppdcDriver *)src->drivers->next()) - { - httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "drv", "", "", 0, - "/%s/%s", name, - d->file_name ? d->file_name->value : - d->pc_file_name->value); + if (*ptr) + { + *ptr++ = '\0'; - device_id = d->find_attr("1284DeviceID", NULL); - ps_version = d->find_attr("PSVersion", NULL); - nick_name = d->find_attr("NickName", NULL); + while (isspace(*ptr & 255)) + *ptr++ = '\0'; + } - if (nick_name) - strlcpy(make_model, nick_name->value->value, sizeof(make_model)); - else if (strncasecmp(d->model_name->value, d->manufacturer->value, - strlen(d->manufacturer->value))) - snprintf(make_model, sizeof(make_model), "%s %s, %s", - d->manufacturer->value, d->model_name->value, - d->version->value); - else - snprintf(make_model, sizeof(make_model), "%s, %s", d->model_name->value, - d->version->value); + cupsArrayAdd(cups_languages, strdup(start)); + start = ptr; + } + } + } + else if (!strncmp(line, "*cupsFax:", 9)) + { + for (ptr = line + 9; isspace(*ptr & 255); ptr ++); - if ((cups_fax = d->find_attr("cupsFax", NULL)) != NULL && - !strcasecmp(cups_fax->value->value, "true")) - type = PPD_TYPE_FAX; - else if (d->type == PPDC_DRIVER_PS) - type = PPD_TYPE_POSTSCRIPT; - else if (d->type != PPDC_DRIVER_CUSTOM) - type = PPD_TYPE_RASTER; - else - { - for (filter = (ppdcFilter *)d->filters->first(), - type = PPD_TYPE_POSTSCRIPT; - filter; - filter = (ppdcFilter *)d->filters->next()) - if (strcasecmp(filter->mime_type->value, "application/vnd.cups-raster")) + if (!strncasecmp(ptr, "true", 4)) + type = PPD_TYPE_FAX; + } + else if (!strncmp(line, "*cupsFilter:", 12) && type == PPD_TYPE_POSTSCRIPT) + { + if (strstr(line + 12, "application/vnd.cups-raster")) type = PPD_TYPE_RASTER; - else if (strcasecmp(filter->mime_type->value, - "application/vnd.cups-pdf")) + else if (strstr(line + 12, "application/vnd.cups-pdf")) type = PPD_TYPE_PDF; - } - - for (product = (ppdcAttr *)d->attrs->first(), products_found = 0, - ppd = NULL; - product; - product = (ppdcAttr *)d->attrs->next()) - if (!strcmp(product->name->value, "Product")) + } + else if (!strncmp(line, "*cupsModelNumber:", 17)) + sscanf(line, "*cupsModelNumber:%d", &model_number); + else if (!strncmp(line, "*OpenUI", 7)) { - if (!products_found) - ppd = add_ppd(name, uri, "en", d->manufacturer->value, make_model, - device_id ? device_id->value->value : "", - product->value->value, - ps_version ? ps_version->value->value : "(3010) 0", - mtime, size, d->model_number, type, "drv"); - else if (products_found < PPD_MAX_PROD) - strlcpy(ppd->record.products[products_found], product->value->value, - sizeof(ppd->record.products[0])); - else - break; + /* + * Stop early if we have a NickName or ModelName attributes + * before the first OpenUI... + */ - products_found ++; + if ((model_name[0] || nick_name[0]) && cupsArrayCount(products) > 0 && + cupsArrayCount(psversions) > 0) + break; } + } - if (!products_found) - add_ppd(name, uri, "en", d->manufacturer->value, make_model, - device_id ? device_id->value->value : "", - d->model_name->value, - ps_version ? ps_version->value->value : "(3010) 0", - mtime, size, d->model_number, type, "drv"); - } - - src->release(); + /* + * Close the file... + */ - return (1); -} + cupsFileClose(fp); + /* + * See if we got all of the required info... + */ -/* - * 'load_drivers()' - Load driver-generated PPD files. - */ + if (nick_name[0]) + cupsCharsetToUTF8((cups_utf8_t *)make_model, nick_name, + sizeof(make_model), _ppdGetEncoding(lang_encoding)); + else + strcpy(make_model, model_name); -static int /* O - 1 on success, 0 on failure */ -load_drivers(cups_array_t *include, /* I - Drivers to include */ - cups_array_t *exclude) /* I - Drivers to exclude */ -{ - int i; /* Looping var */ - char *start, /* Start of value */ - *ptr; /* Pointer into string */ - const char *server_bin, /* CUPS_SERVERBIN env variable */ - *scheme, /* Scheme for this driver */ - *scheme_end; /* Pointer to end of scheme */ - char drivers[1024]; /* Location of driver programs */ - int pid; /* Process ID for driver program */ - cups_file_t *fp; /* Pipe to driver program */ - cups_dir_t *dir; /* Directory pointer */ - cups_dentry_t *dent; /* Directory entry */ - char *argv[3], /* Arguments for command */ - filename[1024], /* Name of driver */ - line[2048], /* Line from driver */ - name[512], /* ppd-name */ - make[128], /* ppd-make */ - make_and_model[128], /* ppd-make-and-model */ - device_id[128], /* ppd-device-id */ - languages[128], /* ppd-natural-language */ - product[128], /* ppd-product */ - psversion[128], /* ppd-psversion */ - type_str[128]; /* ppd-type */ - int type; /* PPD type */ - ppd_info_t *ppd; /* Newly added PPD */ + while (isspace(make_model[0] & 255)) + _cups_strcpy(make_model, make_model + 1); + if (!make_model[0] || cupsArrayCount(products) == 0 || + cupsArrayCount(psversions) == 0) + { + /* + * We don't have all the info needed, so skip this file... + */ - /* - * Try opening the driver directory... - */ + if (!make_model[0]) + fprintf(stderr, "WARNING: Missing NickName and ModelName in %s!\n", + filename); - if ((server_bin = getenv("CUPS_SERVERBIN")) == NULL) - server_bin = CUPS_SERVERBIN; + if (cupsArrayCount(products) == 0) + fprintf(stderr, "WARNING: Missing Product in %s!\n", filename); - snprintf(drivers, sizeof(drivers), "%s/driver", server_bin); + if (cupsArrayCount(psversions) == 0) + fprintf(stderr, "WARNING: Missing PSVersion in %s!\n", filename); - if ((dir = cupsDirOpen(drivers)) == NULL) - { - fprintf(stderr, "ERROR: [cups-driverd] Unable to open driver directory " - "\"%s\": %s\n", - drivers, strerror(errno)); - return (0); - } + free_array(products); + free_array(psversions); + free_array(cups_languages); - /* - * Loop through all of the device drivers... - */ + continue; + } - argv[1] = (char *)"list"; - argv[2] = NULL; + if (model_name[0]) + cupsArrayAdd(products, strdup(model_name)); - while ((dent = cupsDirRead(dir)) != NULL) - { /* - * Only look at executable files... + * Normalize the make and model string... */ - if (!(dent->fileinfo.st_mode & 0111) || !S_ISREG(dent->fileinfo.st_mode)) - continue; + while (isspace(manufacturer[0] & 255)) + _cups_strcpy(manufacturer, manufacturer + 1); + + if (!strncasecmp(make_model, manufacturer, strlen(manufacturer))) + strlcpy(temp, make_model, sizeof(temp)); + else + snprintf(temp, sizeof(temp), "%s %s", manufacturer, make_model); + + _ppdNormalizeMakeAndModel(temp, make_model, sizeof(make_model)); /* - * Include/exclude specific drivers... + * See if we got a manufacturer... */ - if (exclude) + if (!manufacturer[0] || !strcmp(manufacturer, "ESP")) { /* - * Look for "scheme" or "scheme*" (prefix match), and skip any matches. + * Nope, copy the first part of the make and model then... */ - for (scheme = (char *)cupsArrayFirst(exclude); - scheme; - scheme = (char *)cupsArrayNext(exclude)) - { - fprintf(stderr, "DEBUG: [cups-driverd] Exclude \"%s\" with \"%s\"?\n", - dent->filename, scheme); - scheme_end = scheme + strlen(scheme) - 1; + strlcpy(manufacturer, make_model, sizeof(manufacturer)); - if ((scheme_end > scheme && *scheme_end == '*' && - !strncmp(scheme, dent->filename, scheme_end - scheme)) || - !strcmp(scheme, dent->filename)) - { - fputs("DEBUG: [cups-driverd] Yes, exclude!\n", stderr); + /* + * Truncate at the first space, dash, or slash, or make the + * manufacturer "Other"... + */ + + for (ptr = manufacturer; *ptr; ptr ++) + if (*ptr == ' ' || *ptr == '-' || *ptr == '/') break; - } - } - if (scheme) - continue; + if (*ptr && ptr > manufacturer) + *ptr = '\0'; + else + strcpy(manufacturer, "Other"); } + else if (!strncasecmp(manufacturer, "LHAG", 4) || + !strncasecmp(manufacturer, "linotype", 8)) + strcpy(manufacturer, "LHAG"); + else if (!strncasecmp(manufacturer, "Hewlett", 7)) + strcpy(manufacturer, "HP"); - if (include) + /* + * Fix the lang_version as needed... + */ + + if ((ptr = strchr(lang_version, '-')) != NULL) + *ptr++ = '\0'; + else if ((ptr = strchr(lang_version, '_')) != NULL) + *ptr++ = '\0'; + + if (ptr) { /* - * Look for "scheme" or "scheme*" (prefix match), and skip any non-matches. + * Setup the country suffix... */ - for (scheme = (char *)cupsArrayFirst(include); - scheme; - scheme = (char *)cupsArrayNext(include)) - { - fprintf(stderr, "DEBUG: [cups-driverd] Include \"%s\" with \"%s\"?\n", - dent->filename, scheme); - scheme_end = scheme + strlen(scheme) - 1; + country[0] = '_'; + _cups_strcpy(country + 1, ptr); + } + else + { + /* + * No country suffix... + */ - if ((scheme_end > scheme && *scheme_end == '*' && - !strncmp(scheme, dent->filename, scheme_end - scheme)) || - !strcmp(scheme, dent->filename)) - { - fputs("DEBUG: [cups-driverd] Yes, include!\n", stderr); - break; - } - } + country[0] = '\0'; + } - if (!scheme) - continue; + for (i = 0; i < (int)(sizeof(languages) / sizeof(languages[0])); i ++) + if (!strcasecmp(languages[i].version, lang_version)) + break; + + if (i < (int)(sizeof(languages) / sizeof(languages[0]))) + { + /* + * Found a known language... + */ + + snprintf(lang_version, sizeof(lang_version), "%s%s", + languages[i].language, country); } else - scheme = dent->filename; + { + /* + * Unknown language; use "xx"... + */ + + strcpy(lang_version, "xx"); + } /* - * Run the driver with no arguments and collect the output... + * Record the PPD file... */ - argv[0] = dent->filename; - snprintf(filename, sizeof(filename), "%s/%s", drivers, dent->filename); + new_ppd = !ppd; - if ((fp = cupsdPipeCommand(&pid, filename, argv, 0)) != NULL) + if (new_ppd) { - while (cupsFileGets(fp, line, sizeof(line))) - { - /* - * Each line is of the form: - * - * "ppd-name" ppd-natural-language "ppd-make" "ppd-make-and-model" \ - * "ppd-device-id" "ppd-product" "ppd-psversion" - */ + /* + * Add new PPD file... + */ - device_id[0] = '\0'; - product[0] = '\0'; - psversion[0] = '\0'; - strcpy(type_str, "postscript"); + fprintf(stderr, "DEBUG2: [cups-driverd] Adding ppd \"%s\"...\n", name); - if (sscanf(line, "\"%511[^\"]\"%127s%*[ \t]\"%127[^\"]\"" - "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"" - "%*[ \t]\"%127[^\"]\"%*[ \t]\"%127[^\"]\"" - "%*[ \t]\"%127[^\"]\"", - name, languages, make, make_and_model, - device_id, product, psversion, type_str) < 4) - { - /* - * Bad format; strip trailing newline and write an error message. - */ + ppd = add_ppd(name, name, lang_version, manufacturer, make_model, + device_id, (char *)cupsArrayFirst(products), + (char *)cupsArrayFirst(psversions), + dent->fileinfo.st_mtime, dent->fileinfo.st_size, + model_number, type, "file"); - if (line[strlen(line) - 1] == '\n') - line[strlen(line) - 1] = '\0'; + if (!ppd) + { + cupsDirClose(dir); + return (0); + } + } + else + { + /* + * Update existing record... + */ - fprintf(stderr, "ERROR: [cups-driverd] Bad line from \"%s\": %s\n", - dent->filename, line); - break; - } - else - { - /* - * Add the device to the array of available devices... - */ + fprintf(stderr, "DEBUG2: [cups-driverd] Updating ppd \"%s\"...\n", name); - if ((start = strchr(languages, ',')) != NULL) - *start++ = '\0'; + memset(ppd, 0, sizeof(ppd_info_t)); - for (type = 0; - type < (int)(sizeof(ppd_types) / sizeof(ppd_types[0])); - type ++) - if (!strcmp(type_str, ppd_types[type])) - break; + ppd->found = 1; + ppd->record.mtime = dent->fileinfo.st_mtime; + ppd->record.size = dent->fileinfo.st_size; + ppd->record.model_number = model_number; + ppd->record.type = type; - if (type >= (int)(sizeof(ppd_types) / sizeof(ppd_types[0]))) - { - fprintf(stderr, - "ERROR: [cups-driverd] Bad ppd-type \"%s\" ignored!\n", - type_str); - type = PPD_TYPE_UNKNOWN; - } + strlcpy(ppd->record.name, name, sizeof(ppd->record.name)); + strlcpy(ppd->record.make, manufacturer, sizeof(ppd->record.make)); + strlcpy(ppd->record.make_and_model, make_model, + sizeof(ppd->record.make_and_model)); + strlcpy(ppd->record.languages[0], lang_version, + sizeof(ppd->record.languages[0])); + strlcpy(ppd->record.products[0], (char *)cupsArrayFirst(products), + sizeof(ppd->record.products[0])); + strlcpy(ppd->record.psversions[0], (char *)cupsArrayFirst(psversions), + sizeof(ppd->record.psversions[0])); + strlcpy(ppd->record.device_id, device_id, sizeof(ppd->record.device_id)); + } - ppd = add_ppd(filename, name, languages, make, make_and_model, - device_id, product, psversion, 0, 0, 0, type, scheme); + /* + * Add remaining products, versions, and languages... + */ - if (!ppd) - { - cupsDirClose(dir); - cupsFileClose(fp); - return (0); - } + for (i = 1; + i < PPD_MAX_PROD && (ptr = (char *)cupsArrayNext(products)) != NULL; + i ++) + strlcpy(ppd->record.products[i], ptr, + sizeof(ppd->record.products[0])); - if (start && *start) - { - for (i = 1; i < PPD_MAX_LANG && *start; i ++) - { - if ((ptr = strchr(start, ',')) != NULL) - *ptr++ = '\0'; - else - ptr = start + strlen(start); + for (i = 1; + i < PPD_MAX_VERS && (ptr = (char *)cupsArrayNext(psversions)) != NULL; + i ++) + strlcpy(ppd->record.psversions[i], ptr, + sizeof(ppd->record.psversions[0])); - strlcpy(ppd->record.languages[i], start, - sizeof(ppd->record.languages[0])); + for (i = 1, ptr = (char *)cupsArrayFirst(cups_languages); + i < PPD_MAX_LANG && ptr; + i ++, ptr = (char *)cupsArrayNext(cups_languages)) + strlcpy(ppd->record.languages[i], ptr, + sizeof(ppd->record.languages[0])); - start = ptr; - } - } + /* + * Free products, versions, and languages... + */ - fprintf(stderr, "DEBUG2: [cups-driverd] Added dynamic PPD \"%s\"...\n", - name); - } - } + free_array(cups_languages); + free_array(products); + free_array(psversions); - cupsFileClose(fp); - } - else - fprintf(stderr, "WARNING: [cups-driverd] Unable to execute \"%s\": %s\n", - filename, strerror(errno)); + ChangedPPD = 1; } cupsDirClose(dir); @@ -2302,7 +2309,6 @@ load_ppds_dat(char *filename, /* I - Filename buffer */ unsigned ppdsync; /* Sync word */ int num_ppds; /* Number of PPDs */ - if (cupsFileRead(fp, (char *)&ppdsync, sizeof(ppdsync)) == sizeof(ppdsync) && ppdsync == PPD_SYNC && diff --git a/scheduler/filter.c b/scheduler/filter.c index 1234de52a..9f734da56 100644 --- a/scheduler/filter.c +++ b/scheduler/filter.c @@ -17,8 +17,10 @@ * mimeAddFilter() - Add a filter to the current MIME database. * mimeFilter() - Find the fastest way to convert from one type to * another. - * mimeFilterLookup() - Lookup a filter... - * compare_filters() - Compare two filters... + * mimeFilter2() - Find the fastest way to convert from one type to + * another, including the file size. + * mimeFilterLookup() - Lookup a filter. + * compare_filters() - Compare two filters. * find_filters() - Find the filters to convert from one type to another. */ @@ -49,8 +51,8 @@ typedef struct _mime_typelist_s /**** List of source types ****/ static int compare_filters(mime_filter_t *, mime_filter_t *); static int compare_srcs(mime_filter_t *, mime_filter_t *); static cups_array_t *find_filters(mime_t *mime, mime_type_t *src, - mime_type_t *dst, int *cost, - _mime_typelist_t *visited); + size_t srcsize, mime_type_t *dst, + int *cost, _mime_typelist_t *visited); /* @@ -137,16 +139,37 @@ mimeFilter(mime_t *mime, /* I - MIME database */ mime_type_t *dst, /* I - Destination file type */ int *cost) /* O - Cost of filters */ { - /* - * Range-check the input... - */ - DEBUG_printf(("mimeFilter(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), " - "cost=%p(%d))\n", + "cost=%p(%d))", mime, src, src ? src->super : "?", src ? src->type : "?", dst, dst ? dst->super : "?", dst ? dst->type : "?", cost, cost ? *cost : 0)); + return (mimeFilter2(mime, src, 0, dst, cost)); +} + + +/* + * 'mimeFilter2()' - Find the fastest way to convert from one type to another, + * including file size. + */ + +cups_array_t * /* O - Array of filters to run */ +mimeFilter2(mime_t *mime, /* I - MIME database */ + mime_type_t *src, /* I - Source file type */ + size_t srcsize, /* I - Size of source file */ + mime_type_t *dst, /* I - Destination file type */ + int *cost) /* O - Cost of filters */ +{ + /* + * Range-check the input... + */ + + DEBUG_printf(("mimeFilter2(mime=%p, src=%p(%s/%s), srcsize=" CUPS_LLFMT + ", dst=%p(%s/%s), cost=%p(%d))", + mime, src, src ? src->super : "?", src ? src->type : "?", + CUPS_LLCAST srcsize, dst, dst ? dst->super : "?", + dst ? dst->type : "?", cost, cost ? *cost : 0)); if (cost) *cost = 0; @@ -162,7 +185,6 @@ mimeFilter(mime_t *mime, /* I - MIME database */ { mime_filter_t *current; /* Current filter */ - mime->srcs = cupsArrayNew((cups_array_func_t)compare_srcs, NULL); for (current = mimeFirstFilter(mime); @@ -175,12 +197,12 @@ mimeFilter(mime_t *mime, /* I - MIME database */ * Find the filters... */ - return (find_filters(mime, src, dst, cost, NULL)); + return (find_filters(mime, src, srcsize, dst, cost, NULL)); } /* - * 'mimeFilterLookup()' - Lookup a filter... + * 'mimeFilterLookup()' - Lookup a filter. */ mime_filter_t * /* O - Filter for src->dst */ @@ -199,7 +221,7 @@ mimeFilterLookup(mime_t *mime, /* I - MIME database */ /* - * 'compare_filters()' - Compare two filters... + * 'compare_filters()' - Compare two filters. */ static int /* O - Comparison result */ @@ -243,6 +265,7 @@ compare_srcs(mime_filter_t *f0, /* I - First filter */ static cups_array_t * /* O - Array of filters to run */ find_filters(mime_t *mime, /* I - MIME database */ mime_type_t *src, /* I - Source file type */ + size_t srcsize, /* I - Size of source file */ mime_type_t *dst, /* I - Destination file type */ int *cost, /* O - Cost of filters */ _mime_typelist_t *list) /* I - Source types we've used */ @@ -257,21 +280,23 @@ find_filters(mime_t *mime, /* I - MIME database */ *listptr; /* Pointer in list */ - DEBUG_printf(("find_filters(mime=%p, src=%p(%s/%s), dst=%p(%s/%s), " - "cost=%p, list=%p)\n", mime, src, src->super, src->type, - dst, dst->super, dst->type, cost, list)); + DEBUG_printf(("2find_filters(mime=%p, src=%p(%s/%s), srcsize=" CUPS_LLFMT + ", dst=%p(%s/%s), cost=%p, list=%p)", mime, src, src->super, + src->type, CUPS_LLCAST srcsize, dst, dst->super, dst->type, + cost, list)); /* * See if there is a filter that can convert the files directly... */ - if ((current = mimeFilterLookup(mime, src, dst)) != NULL) + if ((current = mimeFilterLookup(mime, src, dst)) != NULL && + (current->maxsize == 0 || srcsize <= current->maxsize)) { /* * Got a direct filter! */ - DEBUG_puts("find_filters: Direct filter found!"); + DEBUG_puts("2find_filters: Direct filter found!"); if ((mintemp = cupsArrayNew(NULL, NULL)) == NULL) return (NULL); @@ -283,8 +308,8 @@ find_filters(mime_t *mime, /* I - MIME database */ if (!cost) return (mintemp); - DEBUG_puts("find_filters: Found direct filter:"); - DEBUG_printf(("find_filters: %s (cost=%d)\n", current->filter, mincost)); + DEBUG_puts("2find_filters: Found direct filter:"); + DEBUG_printf(("2find_filters: %s (cost=%d)", current->filter, mincost)); } else { @@ -319,6 +344,8 @@ find_filters(mime_t *mime, /* I - MIME database */ mime_type_t *current_dst; /* Current destination type */ + if (current->maxsize > 0 && srcsize > current->maxsize) + continue; for (listptr = list, current_dst = current->dst; listptr; @@ -337,7 +364,7 @@ find_filters(mime_t *mime, /* I - MIME database */ listnode.src = current->src; cupsArraySave(mime->srcs); - temp = find_filters(mime, current->dst, dst, &tempcost, &listnode); + temp = find_filters(mime, current->dst, srcsize, dst, &tempcost, &listnode); cupsArrayRestore(mime->srcs); if (!temp) diff --git a/scheduler/ipp.c b/scheduler/ipp.c index ef466a1c8..d0011c03a 100644 --- a/scheduler/ipp.c +++ b/scheduler/ipp.c @@ -88,7 +88,6 @@ * renew_subscription() - Renew an existing subscription... * restart_job() - Restart an old print job. * save_auth_info() - Save authentication information for a job. - * save_krb5_creds() - Save Kerberos credentials for the job. * send_document() - Send a file to a printer or class. * send_http_error() - Send a HTTP error back to the IPP client. * send_ipp_status() - Send a status back to the IPP client. @@ -224,9 +223,6 @@ static void renew_subscription(cupsd_client_t *con, int sub_id); static void restart_job(cupsd_client_t *con, ipp_attribute_t *uri); static void save_auth_info(cupsd_client_t *con, cupsd_job_t *job, ipp_attribute_t *auth_info); -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5_H) -static void save_krb5_creds(cupsd_client_t *con, cupsd_job_t *job); -#endif /* HAVE_GSSAPI && HAVE_KRB5_H */ static void send_document(cupsd_client_t *con, ipp_attribute_t *uri); static void send_http_error(cupsd_client_t *con, http_status_t status, cupsd_printer_t *printer); @@ -2341,7 +2337,8 @@ add_job_uuid(cupsd_client_t *con, /* I - Client connection */ if (!ippFindAttribute(job->attrs, "job-uuid", IPP_TAG_URI)) ippAddString(job->attrs, IPP_TAG_JOB, IPP_TAG_URI, "job-uuid", NULL, - cupsdMakeUUID(job->dest, job->id, uuid, sizeof(uuid))); + _httpAssembleUUID(ServerName, RemotePort, job->dest, job->id, + uuid, sizeof(uuid))); } @@ -2670,6 +2667,15 @@ add_printer(cupsd_client_t *con, /* I - Client connection */ if ((attr = ippFindAttribute(con->request, "printer-is-shared", IPP_TAG_BOOLEAN)) != NULL) { + if (attr->values[0].boolean && + printer->num_auth_info_required == 1 && + !strcmp(printer->auth_info_required[0], "negotiate")) + { + send_ipp_status(con, IPP_BAD_REQUEST, + _("Cannot share a remote Kerberized printer.")); + return; + } + if (printer->shared && !attr->values[0].boolean) cupsdDeregisterPrinter(printer, 1); @@ -3812,7 +3818,6 @@ apple_register_profiles( kCFPreferencesCurrentHost }; CFDictionaryRef deviceDict; /* Device dictionary */ - CFStringRef printerUUID; /* Printer UUID */ CFUUIDRef deviceUUID; /* Device UUID */ deviceDict = CFDictionaryCreate(kCFAllocatorDefault, @@ -3822,21 +3827,12 @@ apple_register_profiles( sizeof(deviceDictKeys[0]), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); - printerUUID = CFStringCreateWithCString(kCFAllocatorDefault, - p->uuid + 9, /* Skip urn:uuid: */ - kCFStringEncodingUTF8); - if (printerUUID) - { - deviceUUID = CFUUIDCreateFromString(kCFAllocatorDefault, printerUUID); - CFRelease(printerUUID); + deviceUUID = ColorSyncCreateUUIDFromUInt32(device_id); - if (!deviceDict || !deviceUUID || - !ColorSyncRegisterDevice(kColorSyncPrinterDeviceClass, deviceUUID, - deviceDict)) - error = 1001; - } - else - error = 1001; + if (!deviceDict || !deviceUUID || + !ColorSyncRegisterDevice(kColorSyncPrinterDeviceClass, deviceUUID, + deviceDict)) + error = 1001; if (deviceUUID) CFRelease(deviceUUID); @@ -3921,7 +3917,6 @@ apple_unregister_profiles( * printer. */ - CFStringRef printerUUID; /* Printer UUID */ CFUUIDRef deviceUUID; /* Device UUID */ deviceUUID = ColorSyncCreateUUIDFromUInt32(_ppdHashName(p->name)); @@ -3930,20 +3925,6 @@ apple_unregister_profiles( ColorSyncUnregisterDevice(kColorSyncPrinterDeviceClass, deviceUUID); CFRelease(deviceUUID); } - - printerUUID = CFStringCreateWithCString(kCFAllocatorDefault, p->uuid + 9, - kCFStringEncodingUTF8); - if (printerUUID) - { - deviceUUID = CFUUIDCreateFromString(kCFAllocatorDefault, printerUUID); - if (deviceUUID) - { - ColorSyncUnregisterDevice(kColorSyncPrinterDeviceClass, deviceUUID); - CFRelease(deviceUUID); - } - - CFRelease(printerUUID); - } } # else @@ -10377,6 +10358,14 @@ save_auth_info( cupsdSetStringf(&job->auth_password, "AUTH_PASSWORD=%s", con->password); } +#ifdef HAVE_GSSAPI + if (con->have_gss && con->gss_uid > 0) + { + cupsFilePrintf(fp, "%d\n", (int)con->gss_uid); + cupsdSetStringf(&job->auth_uid, "AUTH_UID=%d", (int)con->gss_uid); + } +#endif /* HAVE_GSSAPI */ + /* * Write a random number of newlines to the end of the file... */ @@ -10389,52 +10378,7 @@ save_auth_info( */ cupsFileClose(fp); - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5_H) -# ifdef HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID - if (con->have_gss && - (con->http.hostaddr->addr.sa_family == AF_LOCAL || con->gss_creds)) -# else - if (con->have_gss && con->gss_creds) -# endif /* HAVE_KRB5_IPC_CLIENT_SET_TARGET_UID */ - save_krb5_creds(con, job); - else if (job->ccname) - cupsdClearString(&(job->ccname)); -#endif /* HAVE_GSSAPI && HAVE_KRB5_H */ -} - - -#if defined(HAVE_GSSAPI) && defined(HAVE_KRB5_H) -/* - * 'save_krb5_creds()' - Save Kerberos credentials for the job. - */ - -static void -save_krb5_creds(cupsd_client_t *con, /* I - Client connection */ - cupsd_job_t *job) /* I - Job */ -{ - /* - * Get the credentials... - */ - - job->ccache = cupsdCopyKrb5Creds(con); - - /* - * Add the KRB5CCNAME environment variable to the job so that the - * backend can use the credentials when printing. - */ - - if (job->ccache) - { - cupsdSetStringf(&(job->ccname), "KRB5CCNAME=FILE:%s", - krb5_cc_get_name(KerberosContext, job->ccache)); - - cupsdLogJob(job, CUPSD_LOG_DEBUG2, "save_krb5_creds: %s", job->ccname); - } - else - cupsdClearString(&(job->ccname)); } -#endif /* HAVE_GSSAPI && HAVE_KRB5_H */ /* diff --git a/scheduler/job.c b/scheduler/job.c index 96d26e12f..3d9c9e4e4 100644 --- a/scheduler/job.c +++ b/scheduler/job.c @@ -944,11 +944,8 @@ cupsdContinueJob(cupsd_job_t *job) /* I - Job */ envp[envc ++] = job->auth_domain; if (job->auth_password) envp[envc ++] = job->auth_password; - -#ifdef HAVE_GSSAPI - if (job->ccname) - envp[envc ++] = job->ccname; -#endif /* HAVE_GSSAPI */ + if (job->auth_uid) + envp[envc ++] = job->auth_uid; envp[envc] = NULL; @@ -1257,20 +1254,7 @@ cupsdDeleteJob(cupsd_job_t *job, /* I - Job */ cupsdClearString(&job->auth_username); cupsdClearString(&job->auth_domain); cupsdClearString(&job->auth_password); - -#ifdef HAVE_GSSAPI - /* - * Destroy the credential cache and clear the KRB5CCNAME env var string. - */ - - if (job->ccache) - { - krb5_cc_destroy(KerberosContext, job->ccache); - job->ccache = NULL; - } - - cupsdClearString(&job->ccname); -#endif /* HAVE_GSSAPI */ + cupsdClearString(&job->auth_uid); if (job->num_files > 0) { @@ -1712,6 +1696,7 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ cupsdClearString(&job->auth_username); cupsdClearString(&job->auth_domain); cupsdClearString(&job->auth_password); + cupsdClearString(&job->auth_uid); if ((fp = cupsFileOpen(jobfile, "r")) != NULL) { @@ -1737,6 +1722,9 @@ cupsdLoadJob(cupsd_job_t *job) /* I - Job */ cupsdSetStringf(&job->auth_password, "AUTH_PASSWORD=%s", data); } + if (cupsFileGets(fp, line, sizeof(line)) && isdigit(line[0] & 255)) + cupsdSetStringf(&job->auth_uid, "AUTH_UID=%s", line); + cupsFileClose(fp); } } @@ -2391,20 +2379,7 @@ cupsdSetJobState( cupsdClearString(&job->auth_username); cupsdClearString(&job->auth_domain); cupsdClearString(&job->auth_password); - -#ifdef HAVE_GSSAPI - /* - * Destroy the credential cache and clear the KRB5CCNAME env var string. - */ - - if (job->ccache) - { - krb5_cc_destroy(KerberosContext, job->ccache); - job->ccache = NULL; - } - - cupsdClearString(&job->ccname); -#endif /* HAVE_GSSAPI */ + cupsdClearString(&job->auth_uid); /* * Remove the print file for good if we aren't preserving jobs or @@ -2705,10 +2680,17 @@ finalize_job(cupsd_job_t *job, /* I - Job */ /* * Clear the "connecting-to-device" reason, which is only valid when a printer - * is processing... + * is processing, along with any remote printing job state... */ - cupsdSetPrinterReasons(job->printer, "-connecting-to-device"); + cupsdSetPrinterReasons(job->printer, "-connecting-to-device," + "cups-remote-pending," + "cups-remote-pending-held," + "cups-remote-processing," + "cups-remote-stopped," + "cups-remote-canceled," + "cups-remote-aborted," + "cups-remote-completed"); /* * Similarly, clear the "offline-report" reason for non-USB devices since we @@ -3946,6 +3928,13 @@ start_job(cupsd_job_t *job, /* I - Job ID */ cupsdSetJobState(job, IPP_JOB_PROCESSING, CUPSD_JOB_DEFAULT, NULL); cupsdSetPrinterState(printer, IPP_PRINTER_PROCESSING, 0); + cupsdSetPrinterReasons(printer, "-cups-remote-pending," + "cups-remote-pending-held," + "cups-remote-processing," + "cups-remote-stopped," + "cups-remote-canceled," + "cups-remote-aborted," + "cups-remote-completed"); job->cost = 0; job->current_file = 0; diff --git a/scheduler/job.h b/scheduler/job.h index 2268886b0..03a8dff87 100644 --- a/scheduler/job.h +++ b/scheduler/job.h @@ -74,15 +74,13 @@ struct cupsd_job_s /**** Job request ****/ * if any */ *auth_domain, /* AUTH_DOMAIN environment variable, * if any */ - *auth_password; /* AUTH_PASSWORD environment variable, + *auth_password, /* AUTH_PASSWORD environment variable, + * if any */ + *auth_uid; /* AUTH_UID environment variable, * if any */ void *profile; /* Security profile */ cups_array_t *history; /* Debug log history */ int progress; /* Printing progress */ -#ifdef HAVE_GSSAPI - krb5_ccache ccache; /* Kerberos credential cache */ - char *ccname; /* KRB5CCNAME environment variable */ -#endif /* HAVE_GSSAPI */ }; typedef struct cupsd_joblog_s /**** Job log message ****/ diff --git a/scheduler/main.c b/scheduler/main.c index d043875cc..411c65210 100644 --- a/scheduler/main.c +++ b/scheduler/main.c @@ -21,7 +21,6 @@ * cupsdClosePipe() - Close a pipe as necessary. * cupsdFreeStrings() - Free an array of strings. * cupsdHoldSignals() - Hold child and termination signals. - * cupsdMakeUUID() - Make a UUID URI conforming to RFC 4122. * cupsdOpenPipe() - Create a pipe which is closed on exec. * cupsdReleaseSignals() - Release signals for delivery. * cupsdSetString() - Set a string value. @@ -947,6 +946,7 @@ main(int argc, /* I - Number of command-line args */ browse_time = current_time; } +#ifndef HAVE_AUTHORIZATION_H /* * Update the root certificate once every 5 minutes if we have client * connections... @@ -962,6 +962,7 @@ main(int argc, /* I - Number of command-line args */ cupsdDeleteCert(0); cupsdAddCert(0, "root", NULL); } +#endif /* !HAVE_AUTHORIZATION_H */ /* * Check for new data on the client sockets... @@ -1298,54 +1299,6 @@ cupsdHoldSignals(void) } -/* - * 'cupsdMakeUUID()' - Make a UUID URI conforming to RFC 4122. - * - * The buffer needs to be at least 46 bytes in size. - */ - -char * /* I - UUID string */ -cupsdMakeUUID(const char *name, /* I - Object name */ - int number, /* I - Object number */ - char *buffer, /* I - String buffer */ - size_t bufsize) /* I - Size of buffer */ -{ - char data[1024]; /* Source string for MD5 */ - _cups_md5_state_t md5state; /* MD5 state */ - unsigned char md5sum[16]; /* MD5 digest/sum */ - - - /* - * Build a version 3 UUID conforming to RFC 4122. - * - * Start with the MD5 sum of the ServerName, RemotePort, object name and - * number, and some random data on the end. - */ - - snprintf(data, sizeof(data), "%s:%d:%s:%d:%04x:%04x", ServerName, - RemotePort, name ? name : ServerName, number, - CUPS_RAND() & 0xffff, CUPS_RAND() & 0xffff); - - _cupsMD5Init(&md5state); - _cupsMD5Append(&md5state, (unsigned char *)data, strlen(data)); - _cupsMD5Finish(&md5state, md5sum); - - /* - * Generate the UUID from the MD5... - */ - - snprintf(buffer, bufsize, - "urn:uuid:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-" - "%02x%02x%02x%02x%02x%02x", - md5sum[0], md5sum[1], md5sum[2], md5sum[3], md5sum[4], md5sum[5], - (md5sum[6] & 15) | 0x30, md5sum[7], (md5sum[8] & 0x3f) | 0x40, - md5sum[9], md5sum[10], md5sum[11], md5sum[12], md5sum[13], - md5sum[14], md5sum[15]); - - return (buffer); -} - - /* * 'cupsdOpenPipe()' - Create a pipe which is closed on exec. */ diff --git a/scheduler/mime.h b/scheduler/mime.h index 630b2d763..e3f214b37 100644 --- a/scheduler/mime.h +++ b/scheduler/mime.h @@ -3,7 +3,7 @@ * * MIME type/conversion database definitions for CUPS. * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2011 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -97,6 +97,7 @@ typedef struct _mime_filter_s /**** MIME Conversion Filter Data ****/ *dst; /* Destination type */ int cost; /* Relative cost */ char filter[MIME_MAX_FILTER];/* Filter program to use */ + size_t maxsize; /* Maximum file size for this filter */ } mime_filter_t; typedef struct _mime_s /**** MIME Database ****/ @@ -135,6 +136,9 @@ extern mime_filter_t *mimeAddFilter(mime_t *mime, mime_type_t *src, extern void mimeDeleteFilter(mime_t *mime, mime_filter_t *filter); extern cups_array_t *mimeFilter(mime_t *mime, mime_type_t *src, mime_type_t *dst, int *cost); +extern cups_array_t *mimeFilter2(mime_t *mime, mime_type_t *src, + size_t srcsize, mime_type_t *dst, + int *cost); extern mime_filter_t *mimeFilterLookup(mime_t *mime, mime_type_t *src, mime_type_t *dst); extern mime_filter_t *mimeFirstFilter(mime_t *mime); diff --git a/scheduler/printers.c b/scheduler/printers.c index 5331ca7bb..de4b637de 100644 --- a/scheduler/printers.c +++ b/scheduler/printers.c @@ -135,7 +135,8 @@ cupsdAddPrinter(const char *name) /* I - Name of printer */ httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL, ServerName, RemotePort, "/printers/%s", name); cupsdSetString(&p->uri, uri); - cupsdSetString(&p->uuid, cupsdMakeUUID(name, 0, uuid, sizeof(uuid))); + cupsdSetString(&p->uuid, _httpAssembleUUID(ServerName, RemotePort, name, 0, + uuid, sizeof(uuid))); cupsdSetDeviceURI(p, "file:///dev/null"); p->state = IPP_PRINTER_STOPPED; @@ -1804,6 +1805,16 @@ cupsdSetAuthInfoRequired( p->auth_info_required[p->num_auth_info_required] = "negotiate"; p->num_auth_info_required ++; + + /* + * Don't allow sharing of queues that require Kerberos authentication. + */ + + if (p->shared) + { + cupsdDeregisterPrinter(p, 1); + p->shared = 0; + } } else if ((end - values) == 6 && !strncmp(values, "domain", 6)) { @@ -1882,6 +1893,16 @@ cupsdSetAuthInfoRequired( p->auth_info_required[p->num_auth_info_required] = "negotiate"; p->num_auth_info_required ++; + /* + * Don't allow sharing of queues that require Kerberos authentication. + */ + + if (p->shared) + { + cupsdDeregisterPrinter(p, 1); + p->shared = 0; + } + return (1); } else if (!strcmp(attr->values[i].string.text, "domain")) @@ -3539,6 +3560,7 @@ add_printer_filter( /* Destination super/type */ program[1024]; /* Program/filter name */ int cost; /* Cost of filter */ + size_t maxsize = 0; /* Maximum supported file size */ mime_type_t *temptype, /* MIME type looping var */ *desttype; /* Destination MIME type */ char filename[1024], /* Full filter filename */ @@ -3555,7 +3577,9 @@ add_printer_filter( * Parse the filter string; it should be in one of the following formats: * * source/type cost program + * source/type cost maxsize(nnnn) program * source/type dest/type cost program + * source/type dest/type cost maxsize(nnnn) program */ if (sscanf(filter, "%15[^/]/%255s%*[ \t]%15[^/]/%255s%d%*[ \t]%1023[^\n]", @@ -3588,6 +3612,26 @@ add_printer_filter( } } + if (!strncmp(program, "maxsize(", 8)) + { + char *ptr; /* Pointer into maxsize(nnnn) program */ + + maxsize = strtoll(program + 8, &ptr, 10); + + if (*ptr != ')') + { + cupsdLogMessage(CUPSD_LOG_ERROR, "%s: invalid filter string \"%s\"!", + p->name, filter); + return; + } + + ptr ++; + while (_cups_isspace(*ptr)) + ptr ++; + + _cups_strcpy(program, ptr); + } + /* * See if the filter program exists; if not, stop the printer and flag * the error! @@ -3632,6 +3676,12 @@ add_printer_filter( "(0%o/uid=%d/gid=%d).", filename, fileinfo.st_mode, (int)fileinfo.st_uid, (int)fileinfo.st_gid); +#ifdef __APPLE__ /* Don't flag filters with group write for "admin" */ + if (fileinfo.st_uid || + (fileinfo.st_gid && fileinfo.st_gid != 80 && + (fileinfo.st_mode & S_IWGRP)) || + (fileinfo.st_mode & (S_ISUID | S_IWOTH))) +#endif /* __APPLE__ */ cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning"); cupsdLogMessage(CUPSD_LOG_WARN, "%s: %s", p->name, p->state_message); diff --git a/scheduler/process.c b/scheduler/process.c index 2260249f1..80c3fcb59 100644 --- a/scheduler/process.c +++ b/scheduler/process.c @@ -435,7 +435,11 @@ cupsdStartProcess( command, commandinfo.st_mode, (int)commandinfo.st_uid, (int)commandinfo.st_gid); +#ifdef __APPLE__ /* Don't flag filters with group write for "admin" */ + if (commandinfo.st_gid != 80 && job && job->printer) +#else if (job && job->printer) +#endif /* __APPLE__ */ { if (cupsdSetPrinterReasons(job->printer, "+cups-insecure-filter-warning")) cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, job->printer, NULL, diff --git a/test/get-jobs.test b/test/get-jobs.test index b40ea15d9..8ad6c5b9f 100644 --- a/test/get-jobs.test +++ b/test/get-jobs.test @@ -31,7 +31,7 @@ ATTR language attributes-natural-language en ATTR uri printer-uri $uri ATTR keyword requested-attributes - job-id,job-state,job-name,job-originating-user-name + job-id,job-state,job-name,job-originating-user-name,job-media-sheets,job-media-sheets-completed,job-impressions,job-impressions-completed # What statuses are OK? STATUS successful-ok @@ -41,6 +41,10 @@ DISPLAY job-state DISPLAY job-name DISPLAY job-originating-user-name + DISPLAY job-impressions + DISPLAY job-impressions-completed + DISPLAY job-media-sheets + DISPLAY job-media-sheets-completed } diff --git a/xcode/CUPS.xcodeproj/project.pbxproj b/xcode/CUPS.xcodeproj/project.pbxproj index 5aa8f861d..07f865b42 100644 --- a/xcode/CUPS.xcodeproj/project.pbxproj +++ b/xcode/CUPS.xcodeproj/project.pbxproj @@ -47,6 +47,7 @@ 276683DB1337B24A000D33D0 /* PBXTargetDependency */, 276683DD1337B24A000D33D0 /* PBXTargetDependency */, 276683DF1337B24A000D33D0 /* PBXTargetDependency */, + 7258EAEF13459ADA009286F1 /* PBXTargetDependency */, 7243793F1333FD23009631B9 /* PBXTargetDependency */, 724379C31333FF7D009631B9 /* PBXTargetDependency */, ); @@ -336,6 +337,9 @@ 724379C71333FFC7009631B9 /* usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 724379C51333FFC7009631B9 /* usb.c */; }; 724379C91333FFF3009631B9 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 724379C81333FFF3009631B9 /* CoreFoundation.framework */; }; 724379CB1334000E009631B9 /* ieee1284.c in Sources */ = {isa = PBXBuildFile; fileRef = 724379CA1334000E009631B9 /* ieee1284.c */; }; + 7258EAED134594EB009286F1 /* rastertopwg.c in Sources */ = {isa = PBXBuildFile; fileRef = 7258EAEC134594EB009286F1 /* rastertopwg.c */; }; + 7258EAF413459B6D009286F1 /* libcups.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 72220EAE1333047D00FCA411 /* libcups.dylib */; }; + 7258EAF513459B6D009286F1 /* libcupsimage.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 72F75A611336F9A3004BB496 /* libcupsimage.dylib */; }; 7263EE2713330D2800BA4D44 /* libpam.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 7263EE2613330D2800BA4D44 /* libpam.dylib */; }; 7263EE2C13330D5C00BA4D44 /* Kerberos.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7263EE2913330D5C00BA4D44 /* Kerberos.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 7263EE2D13330D5C00BA4D44 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7263EE2A13330D5C00BA4D44 /* Security.framework */; }; @@ -747,6 +751,27 @@ remoteGlobalIDString = 7243795A1333FF1D009631B9; remoteInfo = usb; }; + 7258EAEE13459ADA009286F1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 72BF96371333042100B1EAD7 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 7258EAE1134594C4009286F1; + remoteInfo = rastertopwg; + }; + 7258EAF013459B67009286F1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 72BF96371333042100B1EAD7 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 72220EAD1333047D00FCA411; + remoteInfo = libcups; + }; + 7258EAF213459B67009286F1 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 72BF96371333042100B1EAD7 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 72F75A601336F9A3004BB496; + remoteInfo = libcupsimage; + }; 72F75A651336FA30004BB496 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 72BF96371333042100B1EAD7 /* Project object */; @@ -960,6 +985,15 @@ ); runOnlyForDeploymentPostprocessing = 1; }; + 7258EAE0134594C4009286F1 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + ); + runOnlyForDeploymentPostprocessing = 1; + }; 72F75A501336F950004BB496 /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; @@ -1034,6 +1068,8 @@ 276683F91337F7A9000D33D0 /* ipptool.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ipptool.c; path = ../test/ipptool.c; sourceTree = ""; }; 276684041337FA1D000D33D0 /* cupsaddsmb */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = cupsaddsmb; sourceTree = BUILT_PRODUCTS_DIR; }; 276684101337FA7C000D33D0 /* cupsaddsmb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cupsaddsmb.c; path = ../systemv/cupsaddsmb.c; sourceTree = ""; }; + 27D3037C134148CB00F022B1 /* libcups_s.exp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.exports; name = libcups_s.exp; path = ../cups/libcups_s.exp; sourceTree = ""; }; + 27D3037D134148CB00F022B1 /* libcups2.def */ = {isa = PBXFileReference; lastKnownFileType = text; name = libcups2.def; path = ../cups/libcups2.def; sourceTree = ""; }; 72220EAE1333047D00FCA411 /* libcups.dylib */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.dylib"; includeInIndex = 0; path = libcups.dylib; sourceTree = BUILT_PRODUCTS_DIR; }; 72220EB51333052D00FCA411 /* adminutil.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = adminutil.c; path = ../cups/adminutil.c; sourceTree = ""; }; 72220EB71333056300FCA411 /* adminutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = adminutil.h; path = ../cups/adminutil.h; sourceTree = ""; }; @@ -1179,6 +1215,8 @@ 724379C51333FFC7009631B9 /* usb.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = usb.c; path = ../backend/usb.c; sourceTree = ""; }; 724379C81333FFF3009631B9 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = SDKs/MacOSX10.7.sdk/System/Library/Frameworks/CoreFoundation.framework; sourceTree = DEVELOPER_DIR; }; 724379CA1334000E009631B9 /* ieee1284.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = ieee1284.c; path = ../backend/ieee1284.c; sourceTree = ""; }; + 7258EAE2134594C4009286F1 /* rastertopwg */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = rastertopwg; sourceTree = BUILT_PRODUCTS_DIR; }; + 7258EAEC134594EB009286F1 /* rastertopwg.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rastertopwg.c; path = ../filter/rastertopwg.c; sourceTree = ""; }; 7263EE2613330D2800BA4D44 /* libpam.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpam.dylib; path = SDKs/MacOSX10.6.sdk/usr/lib/libpam.dylib; sourceTree = DEVELOPER_DIR; }; 7263EE2913330D5C00BA4D44 /* Kerberos.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Kerberos.framework; path = SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Kerberos.framework; sourceTree = DEVELOPER_DIR; }; 7263EE2A13330D5C00BA4D44 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = SDKs/MacOSX10.6.sdk/System/Library/Frameworks/Security.framework; sourceTree = DEVELOPER_DIR; }; @@ -1437,6 +1475,15 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 7258EADF134594C4009286F1 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 7258EAF413459B6D009286F1 /* libcups.dylib in Frameworks */, + 7258EAF513459B6D009286F1 /* libcupsimage.dylib in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 72F75A4F1336F950004BB496 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -1556,6 +1603,7 @@ 276683A41337ACAB000D33D0 /* ppdpo */, 276683F01337F78E000D33D0 /* ipptool */, 276684041337FA1D000D33D0 /* cupsaddsmb */, + 7258EAE2134594C4009286F1 /* rastertopwg */, ); name = Products; sourceTree = ""; @@ -1563,6 +1611,8 @@ 72220EB41333050100FCA411 /* libcups */ = { isa = PBXGroup; children = ( + 27D3037C134148CB00F022B1 /* libcups_s.exp */, + 27D3037D134148CB00F022B1 /* libcups2.def */, 276683561337A8C5000D33D0 /* cups.strings */, 72220EB51333052D00FCA411 /* adminutil.c */, 72220EB81333056300FCA411 /* array.c */, @@ -1758,6 +1808,14 @@ name = backends; sourceTree = ""; }; + 7258EADC134594A8009286F1 /* filters */ = { + isa = PBXGroup; + children = ( + 7258EAEC134594EB009286F1 /* rastertopwg.c */, + ); + name = filters; + sourceTree = ""; + }; 72BF96351333042100B1EAD7 = { isa = PBXGroup; children = ( @@ -1784,6 +1842,7 @@ 274FF67313333B0A00317ECB /* commands */, 72220F5D13330A5A00FCA411 /* cupsd */, 274FF5D513332C2C00317ECB /* daemon */, + 7258EADC134594A8009286F1 /* filters */, 276683CB1337B1CC000D33D0 /* ppdc tools */, 273BF6B81333B4A90022CAAB /* tests */, 72220EAF1333047D00FCA411 /* Products */, @@ -2352,6 +2411,25 @@ productReference = 7243795B1333FF1D009631B9 /* usb */; productType = "com.apple.product-type.tool"; }; + 7258EAE1134594C4009286F1 /* rastertopwg */ = { + isa = PBXNativeTarget; + buildConfigurationList = 7258EAE9134594C4009286F1 /* Build configuration list for PBXNativeTarget "rastertopwg" */; + buildPhases = ( + 7258EADE134594C4009286F1 /* Sources */, + 7258EADF134594C4009286F1 /* Frameworks */, + 7258EAE0134594C4009286F1 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + 7258EAF113459B67009286F1 /* PBXTargetDependency */, + 7258EAF313459B67009286F1 /* PBXTargetDependency */, + ); + name = rastertopwg; + productName = rastertopwg; + productReference = 7258EAE2134594C4009286F1 /* rastertopwg */; + productType = "com.apple.product-type.tool"; + }; 72F75A511336F950004BB496 /* cupstestppd */ = { isa = PBXNativeTarget; buildConfigurationList = 72F75A581336F951004BB496 /* Build configuration list for PBXNativeTarget "cupstestppd" */; @@ -2435,6 +2513,7 @@ 276683891337AC97000D33D0 /* ppdi */, 276683961337ACA2000D33D0 /* ppdmerge */, 276683A31337ACAB000D33D0 /* ppdpo */, + 7258EAE1134594C4009286F1 /* rastertopwg */, 7243792F1333FB85009631B9 /* socket */, 273BF6BC1333B5000022CAAB /* testcups */, 7243795A1333FF1D009631B9 /* usb */, @@ -2788,6 +2867,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 7258EADE134594C4009286F1 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 7258EAED134594EB009286F1 /* rastertopwg.c in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 72F75A4E1336F950004BB496 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -3089,6 +3176,21 @@ target = 7243795A1333FF1D009631B9 /* usb */; targetProxy = 724379C21333FF7D009631B9 /* PBXContainerItemProxy */; }; + 7258EAEF13459ADA009286F1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 7258EAE1134594C4009286F1 /* rastertopwg */; + targetProxy = 7258EAEE13459ADA009286F1 /* PBXContainerItemProxy */; + }; + 7258EAF113459B67009286F1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 72220EAD1333047D00FCA411 /* libcups */; + targetProxy = 7258EAF013459B67009286F1 /* PBXContainerItemProxy */; + }; + 7258EAF313459B67009286F1 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 72F75A601336F9A3004BB496 /* libcupsimage */; + targetProxy = 7258EAF213459B67009286F1 /* PBXContainerItemProxy */; + }; 72F75A661336FA30004BB496 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 72220EAD1333047D00FCA411 /* libcups */; @@ -3123,7 +3225,6 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3141,7 +3242,6 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3177,7 +3277,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3197,7 +3296,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3234,7 +3332,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/lib; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/cups; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3256,7 +3353,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/lib; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/cups; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = /usr/include/cups; @@ -3280,7 +3376,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3299,7 +3394,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3321,7 +3415,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3340,7 +3433,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3362,7 +3454,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3381,7 +3472,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3403,7 +3493,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3422,7 +3511,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/libexec/cups/daemon; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3444,7 +3532,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/sbin; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3463,7 +3550,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/sbin; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3487,7 +3573,6 @@ GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/local/lib; MACH_O_TYPE = staticlib; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/cups; PRODUCT_NAME = libcups_static; @@ -3512,7 +3597,6 @@ GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/local/lib; MACH_O_TYPE = staticlib; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/cups; PRODUCT_NAME = libcups_static; PUBLIC_HEADERS_FOLDER_PATH = /usr/include/cups; @@ -3537,7 +3621,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/sbin; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3556,7 +3639,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/sbin; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3578,7 +3660,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3597,7 +3678,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3619,7 +3699,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3638,7 +3717,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3660,7 +3738,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3679,7 +3756,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3701,7 +3777,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3720,7 +3795,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3742,7 +3816,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3761,7 +3834,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3783,7 +3855,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3802,7 +3873,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/bin; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3824,7 +3894,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/sbin; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3843,7 +3912,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/sbin; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3866,7 +3934,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/lib; - MACOSX_DEPLOYMENT_TARGET = 10.6; ONLY_ACTIVE_ARCH = YES; PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/cups; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -3889,7 +3956,6 @@ GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; INSTALL_PATH = /usr/lib; - MACOSX_DEPLOYMENT_TARGET = 10.6; PRIVATE_HEADERS_FOLDER_PATH = /usr/local/include/cups; PRODUCT_NAME = "$(TARGET_NAME)"; PUBLIC_HEADERS_FOLDER_PATH = /usr/include/cups; @@ -3912,7 +3978,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + INSTALL_PATH = /usr/sbin; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3931,7 +3997,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + INSTALL_PATH = /usr/sbin; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -3953,7 +4019,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + INSTALL_PATH = /usr/lib; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -3973,7 +4039,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; - MACOSX_DEPLOYMENT_TARGET = 10.6; + INSTALL_PATH = /usr/lib; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -4152,6 +4218,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = /usr/libexec/cups/backend; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/../backend\"", @@ -4173,6 +4240,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = /usr/libexec/cups/backend; LIBRARY_SEARCH_PATHS = ( "$(inherited)", "\"$(SRCROOT)/../backend\"", @@ -4181,6 +4249,45 @@ }; name = Release; }; + 7258EAEA134594C4009286F1 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_STANDARD_32_64_BIT)"; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1"; + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = /usr/libexec/cups/filter; + ONLY_ACTIVE_ARCH = YES; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + 7258EAEB134594C4009286F1 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_VERSION = com.apple.compilers.llvm.clang.1_0; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = /usr/libexec/cups/filter; + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; 72BF963C1333042100B1EAD7 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -4189,6 +4296,7 @@ ., .., ); + MACOSX_DEPLOYMENT_TARGET = ""; OTHER_CFLAGS = ( "-D_CUPS_SOURCE", "-Wno-shorten-64-to-32", @@ -4205,6 +4313,7 @@ ., .., ); + MACOSX_DEPLOYMENT_TARGET = ""; OTHER_CFLAGS = ( "-D_CUPS_SOURCE", "-Wno-shorten-64-to-32", @@ -4229,6 +4338,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = /usr/bin; ONLY_ACTIVE_ARCH = YES; PRODUCT_NAME = "$(TARGET_NAME)"; }; @@ -4246,6 +4356,7 @@ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_UNUSED_VARIABLE = YES; + INSTALL_PATH = /usr/bin; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; @@ -4400,6 +4511,7 @@ 276683641337A9B6000D33D0 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 276683761337AC79000D33D0 /* Build configuration list for PBXNativeTarget "ppdc" */ = { isa = XCConfigurationList; @@ -4408,6 +4520,7 @@ 276683781337AC79000D33D0 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 276683831337AC8C000D33D0 /* Build configuration list for PBXNativeTarget "ppdhtml" */ = { isa = XCConfigurationList; @@ -4416,6 +4529,7 @@ 276683851337AC8C000D33D0 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 276683901337AC97000D33D0 /* Build configuration list for PBXNativeTarget "ppdi" */ = { isa = XCConfigurationList; @@ -4424,6 +4538,7 @@ 276683921337AC97000D33D0 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 2766839D1337ACA2000D33D0 /* Build configuration list for PBXNativeTarget "ppdmerge" */ = { isa = XCConfigurationList; @@ -4432,6 +4547,7 @@ 2766839F1337ACA2000D33D0 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 276683AA1337ACAB000D33D0 /* Build configuration list for PBXNativeTarget "ppdpo" */ = { isa = XCConfigurationList; @@ -4440,6 +4556,7 @@ 276683AC1337ACAB000D33D0 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 276683F61337F78F000D33D0 /* Build configuration list for PBXNativeTarget "ipptool" */ = { isa = XCConfigurationList; @@ -4448,6 +4565,7 @@ 276683F81337F78F000D33D0 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 2766840A1337FA1E000D33D0 /* Build configuration list for PBXNativeTarget "cupsaddsmb" */ = { isa = XCConfigurationList; @@ -4456,6 +4574,7 @@ 2766840C1337FA1E000D33D0 /* Release */, ); defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; }; 72220EB21333047D00FCA411 /* Build configuration list for PBXNativeTarget "libcups" */ = { isa = XCConfigurationList; @@ -4529,6 +4648,15 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 7258EAE9134594C4009286F1 /* Build configuration list for PBXNativeTarget "rastertopwg" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 7258EAEA134594C4009286F1 /* Debug */, + 7258EAEB134594C4009286F1 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 72BF963A1333042100B1EAD7 /* Build configuration list for PBXProject "CUPS" */ = { isa = XCConfigurationList; buildConfigurations = (