diff options
69 files changed, 2630 insertions, 1486 deletions
@@ -17,8 +17,8 @@ #ifndef _CUPS_CONFIG_H_ #define _CUPS_CONFIG_H_ -#define CUPS_SVERSION "CUPS v2.2.6" -#define CUPS_MINIMAL "CUPS/2.2.6" +#define CUPS_SVERSION "CUPS v2.2.9" +#define CUPS_MINIMAL "CUPS/2.2.9" #define CUPS_DEFAULT_PRINTOPERATOR_AUTH "@SYSTEM" #define CUPS_DEFAULT_LOG_LEVEL "warn" #define CUPS_DEFAULT_BROWSE_LOCAL_PROTOCOLS "dnssd" diff --git a/cups/Makefile b/cups/Makefile index 9a220c85..f83c937c 100644 --- a/cups/Makefile +++ b/cups/Makefile @@ -1,8 +1,8 @@ # # Library Makefile for CUPS. # -# Copyright 2007-2017 by Apple Inc. -# Copyright 1997-2006 by Easy Software Products, all rights reserved. +# Copyright © 2007-2018 by Apple Inc. +# Copyright © 1997-2006 by Easy Software Products, all rights reserved. # # These coded instructions, statements, and computer programs are the # property of Apple Inc. and are protected by Federal copyright @@ -312,8 +312,9 @@ uninstall: libcups.so.2: $(LIBOBJS) echo Linking $@... - $(DSO) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS) $(LIBGSSAPI) \ + $(DSO) $(ARCHFLAGS) $(LDFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS) $(LIBGSSAPI) \ $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ $(RM) `basename $@ .2` $(LN) $@ `basename $@ .2` @@ -329,13 +330,14 @@ libcups.2.dylib: $(LIBOBJS) $(LIBCUPSORDER) grep -v -E -e '^(_cupsConnect|_cupsCharset|_cupsEncodingName|_cupsSetDefaults|_cupsSetHTTPError|_cupsUserDefault)$$' | \ sort >t.exp echo Linking $@... - $(DSO) $(ARCHFLAGS) $(DSOFLAGS) -o $@ \ + $(DSO) $(ARCHFLAGS) $(LDFLAGS) $(DSOFLAGS) -o $@ \ -install_name $(libdir)/$@ \ - -current_version 2.12.0 \ + -current_version 2.13.0 \ -compatibility_version 2.0.0 \ -exported_symbols_list t.exp \ $(LIBOBJS) $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) \ $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ $(RM) libcups.dylib t.exp $(LN) $@ libcups.dylib @@ -346,8 +348,8 @@ libcups.2.dylib: $(LIBOBJS) $(LIBCUPSORDER) libcups.la: $(LIBOBJS) echo Linking $@... - $(LD_CC) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS:.o=.lo) \ - -rpath $(LIBDIR) -version-info 2:12 $(LIBGSSAPI) $(SSLLIBS) \ + $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) $(DSOFLAGS) -o $@ $(LIBOBJS:.o=.lo) \ + -rpath $(LIBDIR) -version-info 2:13 $(LIBGSSAPI) $(SSLLIBS) \ $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) @@ -369,12 +371,12 @@ libcups.a: $(LIBOBJS) libcups2.def: $(LIBOBJS) Makefile echo Generating $@... echo "LIBRARY libcups2" >libcups2.def - echo "VERSION 2.12" >>libcups2.def + echo "VERSION 2.13" >>libcups2.def echo "EXPORTS" >>libcups2.def (nm $(LIBOBJS) 2>/dev/null | grep "T _" | awk '{print $$3}'; \ echo __cups_strcpy; echo __cups_strlcat; echo __cups_strlcpy) | \ grep -v -E \ - -e 'cups_debug|Apple|BackChannel|Backend|FileCheck|Filter|GSSService|SetNegotiate|SideChannel' \ + -e 'cups_debug|Apple|BackChannel|Backend|FileCheck|Filter|GSSService|SetNegotiate|SideChannel|SNMP' \ -e 'Block$$' | \ sed -e '1,$$s/^_//' | sort >>libcups2.def @@ -387,6 +389,7 @@ testadmin: testadmin.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ testadmin.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -397,6 +400,7 @@ testarray: testarray.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testarray.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Running array API tests... ./testarray @@ -409,6 +413,7 @@ testcache: testcache.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ testcache.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -419,6 +424,7 @@ testconflicts: testconflicts.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ testconflicts.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -429,6 +435,7 @@ testcreds: testcreds.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testcreds.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -439,6 +446,7 @@ testcups: testcups.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ testcups.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -449,6 +457,7 @@ testdest: testdest.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ testdest.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -459,6 +468,7 @@ testfile: testfile.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testfile.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Running file API tests... ./testfile @@ -471,6 +481,7 @@ testgetdests: testgetdests.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ testgetdests.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -481,6 +492,7 @@ testhttp: testhttp.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testhttp.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Running HTTP API tests... ./testhttp @@ -493,6 +505,7 @@ testipp: testipp.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testipp.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Running IPP API tests... ./testipp @@ -505,6 +518,7 @@ testi18n: testi18n.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testi18n.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Running internationalization API tests... ./testi18n @@ -517,6 +531,7 @@ testlang: testlang.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testlang.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Creating locale directory structure... $(RM) -r locale $(MKDIR) locale/en @@ -541,6 +556,7 @@ testoptions: testoptions.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testoptions.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Running option API tests... ./testoptions @@ -553,6 +569,7 @@ testppd: testppd.o $(LIBCUPSSTATIC) test.ppd test2.ppd echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testppd.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Running PPD API tests... ./testppd @@ -565,6 +582,7 @@ testpwg: testpwg.o $(LIBCUPSSTATIC) test.ppd echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testpwg.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Running PWG API tests... ./testpwg test.ppd @@ -577,6 +595,7 @@ testsnmp: testsnmp.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ testsnmp.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -587,6 +606,7 @@ tlscheck: tlscheck.o $(LIBCUPSSTATIC) echo Linking $@... $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ tlscheck.o $(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # diff --git a/cups/adminutil.c b/cups/adminutil.c index adb1f7ae..375b9054 100644 --- a/cups/adminutil.c +++ b/cups/adminutil.c @@ -22,11 +22,11 @@ #include "adminutil.h" #include <fcntl.h> #include <sys/stat.h> -#ifdef WIN32 +#ifdef _WIN32 #else # include <unistd.h> # include <sys/wait.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ /* @@ -2087,7 +2087,7 @@ do_samba_command(const char *command, /* I - Command to run */ const char *authfile, /* I - Samba authentication file */ FILE *logfile) /* I - Optional log file */ { -#ifdef WIN32 +#ifdef _WIN32 return (1); /* Always fail on Windows... */ #else @@ -2154,7 +2154,7 @@ do_samba_command(const char *command, /* I - Command to run */ return (WEXITSTATUS(status)); else return (-WTERMSIG(status)); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -2172,9 +2172,9 @@ get_cupsd_conf( int *remote) /* O - Remote file? */ { int fd; /* Temporary file descriptor */ -#ifndef WIN32 +#ifndef _WIN32 struct stat info; /* cupsd.conf file information */ -#endif /* WIN32 */ +#endif /* _WIN32 */ http_status_t status; /* Status of getting cupsd.conf */ char host[HTTP_MAX_HOST]; /* Hostname for connection */ @@ -2191,7 +2191,7 @@ get_cupsd_conf( snprintf(name, namesize, "%s/cupsd.conf", cg->cups_serverroot); *remote = 0; -#ifndef WIN32 +#ifndef _WIN32 if (!_cups_strcasecmp(host, "localhost") && !access(name, R_OK)) { /* @@ -2218,7 +2218,7 @@ get_cupsd_conf( status = HTTP_STATUS_OK; } else -#endif /* !WIN32 */ +#endif /* !_WIN32 */ { /* * Read cupsd.conf via a HTTP GET request... diff --git a/cups/api-ppd.shtml b/cups/api-ppd.shtml index 50c48500..49409462 100644 --- a/cups/api-ppd.shtml +++ b/cups/api-ppd.shtml @@ -1,7 +1,7 @@ <!-- PPD API introduction for CUPS. - Copyright 2007-2012 by Apple Inc. + Copyright 2007-2018 by Apple Inc. Copyright 1997-2006 by Easy Software Products, all rights reserved. These coded instructions, statements, and computer programs are the @@ -13,7 +13,7 @@ <h2 class='title'><a name='OVERVIEW'>Overview</a></h2> -<blockquote>The PPD API is deprecated starting in CUPS 1.6/macOS 10.8. Please use the new Job Ticket APIs in the <a href="api-cups.html">CUPS API</a> documentation. These functions will be removed in a future release of CUPS.</blockquote> +<blockquote>The PPD API is deprecated starting in CUPS 1.6/macOS 10.8. Please use the new Job Ticket APIs in the <a href="cupspm.html">CUPS API</a> documentation. These functions will be removed in a future release of CUPS.</blockquote> <p>The CUPS PPD API provides read-only access the data in PostScript Printer Description ("PPD") files which are used for all printers with a driver. With diff --git a/cups/auth.c b/cups/auth.c index c051c86b..a1f50423 100644 --- a/cups/auth.c +++ b/cups/auth.c @@ -1,8 +1,8 @@ /* * Authentication functions for CUPS. * - * Copyright 2007-2016 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products. * * This file contains Kerberos support code, copyright 2006 by * Jelmer Vernooij. @@ -23,11 +23,11 @@ #include "cups-private.h" #include <fcntl.h> #include <sys/stat.h> -#if defined(WIN32) || defined(__EMX__) +#if defined(_WIN32) || defined(__EMX__) # include <io.h> #else # include <unistd.h> -#endif /* WIN32 || __EMX__ */ +#endif /* _WIN32 || __EMX__ */ #if HAVE_AUTHORIZATION_H # include <Security/Authorization.h> @@ -47,6 +47,10 @@ extern const char *cssmErrorString(int error); * Local functions... */ +static const char *cups_auth_find(const char *www_authenticate, const char *scheme); +static const char *cups_auth_param(const char *scheme, const char *name, char *value, size_t valsize); +static const char *cups_auth_scheme(const char *www_authenticate, char *scheme, size_t schemesize); + #ifdef HAVE_GSSAPI # ifdef HAVE_GSS_ACQUIRE_CRED_EX_F # ifdef HAVE_GSS_GSSAPI_SPI_H @@ -112,10 +116,10 @@ cupsDoAuthentication( const char *resource) /* I - Resource path */ { const char *password, /* Password string */ - *www_auth; /* WWW-Authenticate header */ - char prompt[1024], /* Prompt for user */ - realm[HTTP_MAX_VALUE], /* realm="xyz" string */ - nonce[HTTP_MAX_VALUE]; /* nonce="xyz" string */ + *www_auth, /* WWW-Authenticate header */ + *schemedata; /* Scheme-specific data */ + char scheme[256], /* Scheme name */ + prompt[1024]; /* Prompt for user */ int localauth; /* Local authentication result */ _cups_globals_t *cg; /* Global data */ @@ -163,122 +167,129 @@ cupsDoAuthentication( } /* - * Nope, see if we should retry the current username:password... + * Nope, loop through the authentication schemes to find the first we support. */ - www_auth = http->fields[HTTP_FIELD_WWW_AUTHENTICATE]; + www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE); - if ((http->digest_tries > 1 || !http->userpass[0]) && - (!_cups_strncasecmp(www_auth, "Basic", 5) || - !_cups_strncasecmp(www_auth, "Digest", 6))) + for (schemedata = cups_auth_scheme(www_auth, scheme, sizeof(scheme)); schemedata; schemedata = cups_auth_scheme(schemedata + strlen(scheme), scheme, sizeof(scheme))) { /* - * Nope - get a new password from the user... + * Check the scheme name... */ - char default_username[HTTP_MAX_VALUE]; - /* Default username */ +#ifdef HAVE_GSSAPI + if (!_cups_strcasecmp(scheme, "Negotiate")) + { + /* + * Kerberos authentication... + */ - cg = _cupsGlobals(); + if (_cupsSetNegotiateAuthString(http, method, resource)) + { + http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; + return (-1); + } - if (!cg->lang_default) - cg->lang_default = cupsLangDefault(); + break; + } + else +#endif /* HAVE_GSSAPI */ + if (_cups_strcasecmp(scheme, "Basic") && _cups_strcasecmp(scheme, "Digest")) + continue; /* Not supported (yet) */ - if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username", - default_username)) - cupsSetUser(default_username); + /* + * See if we should retry the current username:password... + */ - snprintf(prompt, sizeof(prompt), - _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), - cupsUser(), - http->hostname[0] == '/' ? "localhost" : http->hostname); + if ((http->digest_tries > 1 || !http->userpass[0]) && (!_cups_strcasecmp(scheme, "Basic") || (!_cups_strcasecmp(scheme, "Digest")))) + { + /* + * Nope - get a new password from the user... + */ - http->digest_tries = _cups_strncasecmp(www_auth, "Digest", 6) != 0; - http->userpass[0] = '\0'; + char default_username[HTTP_MAX_VALUE]; + /* Default username */ - if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL) - { - http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; - return (-1); - } + cg = _cupsGlobals(); - snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(), - password); - } - else if (http->status == HTTP_STATUS_UNAUTHORIZED) - http->digest_tries ++; + if (!cg->lang_default) + cg->lang_default = cupsLangDefault(); - if (http->status == HTTP_STATUS_UNAUTHORIZED && http->digest_tries >= 3) - { - DEBUG_printf(("1cupsDoAuthentication: Too many authentication tries (%d)", - http->digest_tries)); + if (cups_auth_param(schemedata, "username", default_username, sizeof(default_username))) + cupsSetUser(default_username); - http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; - return (-1); - } + snprintf(prompt, sizeof(prompt), _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), cupsUser(), http->hostname[0] == '/' ? "localhost" : http->hostname); - /* - * Got a password; encode it for the server... - */ + http->digest_tries = _cups_strncasecmp(scheme, "Digest", 6) != 0; + http->userpass[0] = '\0'; -#ifdef HAVE_GSSAPI - if (!_cups_strncasecmp(www_auth, "Negotiate", 9)) - { - /* - * Kerberos authentication... - */ + if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL) + { + http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; + return (-1); + } - if (_cupsSetNegotiateAuthString(http, method, resource)) + snprintf(http->userpass, sizeof(http->userpass), "%s:%s", cupsUser(), password); + } + else if (http->status == HTTP_STATUS_UNAUTHORIZED) + http->digest_tries ++; + + if (http->status == HTTP_STATUS_UNAUTHORIZED && http->digest_tries >= 3) { + DEBUG_printf(("1cupsDoAuthentication: Too many authentication tries (%d)", http->digest_tries)); + http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; return (-1); } - } - else -#endif /* HAVE_GSSAPI */ - if (!_cups_strncasecmp(www_auth, "Basic", 5)) - { + /* - * Basic authentication... + * Got a password; encode it for the server... */ - char encode[256]; /* Base64 buffer */ + if (!_cups_strcasecmp(scheme, "Basic")) + { + /* + * Basic authentication... + */ + char encode[256]; /* Base64 buffer */ - httpEncode64_2(encode, sizeof(encode), http->userpass, - (int)strlen(http->userpass)); - httpSetAuthString(http, "Basic", encode); - } - else if (!_cups_strncasecmp(www_auth, "Digest", 6)) - { - /* - * Digest authentication... - */ + httpEncode64_2(encode, sizeof(encode), http->userpass, (int)strlen(http->userpass)); + httpSetAuthString(http, "Basic", encode); + break; + } + else if (!_cups_strcasecmp(scheme, "Digest")) + { + /* + * Digest authentication... + */ - char encode[33], /* MD5 buffer */ - digest[1024]; /* Digest auth data */ + char nonce[HTTP_MAX_VALUE]; /* nonce="xyz" string */ - httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm); - httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce); + cups_auth_param(schemedata, "algorithm", http->algorithm, sizeof(http->algorithm)); + cups_auth_param(schemedata, "opaque", http->opaque, sizeof(http->opaque)); + cups_auth_param(schemedata, "nonce", nonce, sizeof(nonce)); + cups_auth_param(schemedata, "realm", http->realm, sizeof(http->realm)); - httpMD5(cupsUser(), realm, strchr(http->userpass, ':') + 1, encode); - httpMD5Final(nonce, method, resource, encode); - snprintf(digest, sizeof(digest), - "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", " - "response=\"%s\"", cupsUser(), realm, nonce, resource, encode); - httpSetAuthString(http, "Digest", digest); + if (_httpSetDigestAuthString(http, nonce, method, resource)) + break; + } + } + + if (http->authstring) + { + DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring)); + + return (0); } else { - DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"", - www_auth)); + DEBUG_printf(("1cupsDoAuthentication: Unknown auth type: \"%s\"", www_auth)); http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; + return (-1); } - - DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring)); - - return (0); } @@ -336,7 +347,7 @@ _cupsSetNegotiateAuthString( GSS_C_NO_BUFFER, &http->gssmech, &output_token, NULL, NULL); -#ifdef HAVE_GSS_ACQUIRE_CRED_EX_F +# ifdef HAVE_GSS_ACQUIRE_CRED_EX_F if (major_status == GSS_S_NO_CRED) { /* @@ -412,7 +423,7 @@ _cupsSetNegotiateAuthString( } } } -#endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */ +# endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */ if (GSS_ERROR(major_status)) { @@ -422,11 +433,11 @@ _cupsSetNegotiateAuthString( return (-1); } -#ifdef DEBUG +# ifdef DEBUG else if (major_status == GSS_S_CONTINUE_NEEDED) cups_gss_printf(major_status, minor_status, "_cupsSetNegotiateAuthString: Continuation needed!"); -#endif /* DEBUG */ +# endif /* DEBUG */ if (output_token.length > 0 && output_token.length <= 65536) { @@ -464,8 +475,259 @@ _cupsSetNegotiateAuthString( return (0); } +#endif /* HAVE_GSSAPI */ + + +/* + * 'cups_auth_find()' - Find the named WWW-Authenticate scheme. + * + * The "www_authenticate" parameter points to the current position in the header. + * + * Returns @code NULL@ if the auth scheme is not present. + */ + +static const char * /* O - Start of matching scheme or @code NULL@ if not found */ +cups_auth_find(const char *www_authenticate, /* I - Pointer into WWW-Authenticate header */ + const char *scheme) /* I - Authentication scheme */ +{ + size_t schemelen = strlen(scheme); /* Length of scheme */ + + + DEBUG_printf(("8cups_auth_find(www_authenticate=\"%s\", scheme=\"%s\"(%d))", www_authenticate, scheme, (int)schemelen)); + + while (*www_authenticate) + { + /* + * Skip leading whitespace and commas... + */ + + DEBUG_printf(("9cups_auth_find: Before whitespace: \"%s\"", www_authenticate)); + while (isspace(*www_authenticate & 255) || *www_authenticate == ',') + www_authenticate ++; + DEBUG_printf(("9cups_auth_find: After whitespace: \"%s\"", www_authenticate)); + + /* + * See if this is "Scheme" followed by whitespace or the end of the string. + */ + + if (!strncmp(www_authenticate, scheme, schemelen) && (isspace(www_authenticate[schemelen] & 255) || www_authenticate[schemelen] == ',' || !www_authenticate[schemelen])) + { + /* + * Yes, this is the start of the scheme-specific information... + */ + + DEBUG_printf(("9cups_auth_find: Returning \"%s\".", www_authenticate)); + + return (www_authenticate); + } + + /* + * Skip the scheme name or param="value" string... + */ + + while (!isspace(*www_authenticate & 255) && *www_authenticate) + { + if (*www_authenticate == '\"') + { + /* + * Skip quoted value... + */ + + www_authenticate ++; + while (*www_authenticate && *www_authenticate != '\"') + www_authenticate ++; + + DEBUG_printf(("9cups_auth_find: After quoted: \"%s\"", www_authenticate)); + } + + www_authenticate ++; + } + + DEBUG_printf(("9cups_auth_find: After skip: \"%s\"", www_authenticate)); + } + + DEBUG_puts("9cups_auth_find: Returning NULL."); + + return (NULL); +} +/* + * 'cups_auth_param()' - Copy the value for the named authentication parameter, + * if present. + */ + +static const char * /* O - Parameter value or @code NULL@ if not present */ +cups_auth_param(const char *scheme, /* I - Pointer to auth data */ + const char *name, /* I - Name of parameter */ + char *value, /* I - Value buffer */ + size_t valsize) /* I - Size of value buffer */ +{ + char *valptr = value, /* Pointer into value buffer */ + *valend = value + valsize - 1; /* Pointer to end of buffer */ + size_t namelen = strlen(name); /* Name length */ + int param; /* Is this a parameter? */ + + + DEBUG_printf(("8cups_auth_param(scheme=\"%s\", name=\"%s\", value=%p, valsize=%d)", scheme, name, (void *)value, (int)valsize)); + + while (!isspace(*scheme & 255) && *scheme) + scheme ++; + + while (*scheme) + { + while (isspace(*scheme & 255) || *scheme == ',') + scheme ++; + + if (!strncmp(scheme, name, namelen) && scheme[namelen] == '=') + { + /* + * Found the parameter, copy the value... + */ + + scheme += namelen + 1; + if (*scheme == '\"') + { + scheme ++; + + while (*scheme && *scheme != '\"') + { + if (valptr < valend) + *valptr++ = *scheme; + + scheme ++; + } + } + else + { + while (*scheme && strchr("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~+/=", *scheme)) + { + if (valptr < valend) + *valptr++ = *scheme; + + scheme ++; + } + } + + *valptr = '\0'; + + DEBUG_printf(("9cups_auth_param: Returning \"%s\".", value)); + + return (value); + } + + /* + * Skip the param=value string... + */ + + param = 0; + + while (!isspace(*scheme & 255) && *scheme) + { + if (*scheme == '=') + param = 1; + else if (*scheme == '\"') + { + /* + * Skip quoted value... + */ + + scheme ++; + while (*scheme && *scheme != '\"') + scheme ++; + } + + scheme ++; + } + + /* + * If this wasn't a parameter, we are at the end of this scheme's + * parameters... + */ + + if (!param) + break; + } + + *value = '\0'; + + DEBUG_puts("9cups_auth_param: Returning NULL."); + + return (NULL); +} + + +/* + * 'cups_auth_scheme()' - Get the (next) WWW-Authenticate scheme. + * + * The "www_authenticate" parameter points to the current position in the header. + * + * Returns @code NULL@ if there are no (more) auth schemes present. + */ + +static const char * /* O - Start of scheme or @code NULL@ if not found */ +cups_auth_scheme(const char *www_authenticate, /* I - Pointer into WWW-Authenticate header */ + char *scheme, /* I - Scheme name buffer */ + size_t schemesize) /* I - Size of buffer */ +{ + const char *start; /* Start of scheme data */ + char *sptr = scheme, /* Pointer into scheme buffer */ + *send = scheme + schemesize - 1;/* End of scheme buffer */ + int param; /* Is this a parameter? */ + + + DEBUG_printf(("8cups_auth_scheme(www_authenticate=\"%s\", scheme=%p, schemesize=%d)", www_authenticate, (void *)scheme, (int)schemesize)); + + while (*www_authenticate) + { + /* + * Skip leading whitespace and commas... + */ + + while (isspace(*www_authenticate & 255) || *www_authenticate == ',') + www_authenticate ++; + + /* + * Parse the scheme name or param="value" string... + */ + + for (sptr = scheme, start = www_authenticate, param = 0; *www_authenticate && *www_authenticate != ',' && !isspace(*www_authenticate & 255); www_authenticate ++) + { + if (*www_authenticate == '=') + param = 1; + else if (!param && sptr < send) + *sptr++ = *www_authenticate; + else if (*www_authenticate == '\"') + { + /* + * Skip quoted value... + */ + + www_authenticate ++; + while (*www_authenticate && *www_authenticate != '\"') + www_authenticate ++; + } + } + + if (sptr > scheme && !param) + { + *sptr = '\0'; + + DEBUG_printf(("9cups_auth_scheme: Returning \"%s\".", start)); + + return (start); + } + } + + *scheme = '\0'; + + DEBUG_puts("9cups_auth_scheme: Returning NULL."); + + return (NULL); +} + + +#ifdef HAVE_GSSAPI # ifdef HAVE_GSS_ACQUIRE_CRED_EX_F /* * 'cups_gss_acquire()' - Kerberos credentials callback. @@ -639,9 +901,9 @@ static int /* O - 0 if available */ /* -1 error */ cups_local_auth(http_t *http) /* I - HTTP connection to server */ { -#if defined(WIN32) || defined(__EMX__) +#if defined(_WIN32) || defined(__EMX__) /* - * Currently WIN32 and OS-2 do not support the CUPS server... + * Currently _WIN32 and OS-2 do not support the CUPS server... */ return (1); @@ -650,6 +912,8 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ FILE *fp; /* Certificate file */ char trc[16], /* Try Root Certificate parameter */ filename[1024]; /* Certificate filename */ + const char *www_auth, /* WWW-Authenticate header */ + *schemedata; /* Data for the named auth scheme */ _cups_globals_t *cg = _cupsGlobals(); /* Global data */ # if defined(HAVE_AUTHORIZATION_H) OSStatus status; /* Status */ @@ -668,13 +932,14 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ * See if we are accessing localhost... */ - if (!httpAddrLocalhost(http->hostaddr) && - _cups_strcasecmp(http->hostname, "localhost") != 0) + if (!httpAddrLocalhost(http->hostaddr) && _cups_strcasecmp(http->hostname, "localhost") != 0) { DEBUG_puts("8cups_local_auth: Not a local connection!"); return (1); } + www_auth = httpGetField(http, HTTP_FIELD_WWW_AUTHENTICATE); + # if defined(HAVE_AUTHORIZATION_H) /* * Delete any previous authorization reference... @@ -686,12 +951,9 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ http->auth_ref = NULL; } - if (!getenv("GATEWAY_INTERFACE") && - httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", - auth_key, sizeof(auth_key))) + if (!getenv("GATEWAY_INTERFACE") && (schemedata = cups_auth_find(www_auth, "AuthRef")) != NULL && cups_auth_param(schemedata, "key", auth_key, sizeof(auth_key))) { - status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, - kAuthorizationFlagDefaults, &http->auth_ref); + status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &http->auth_ref); if (status != errAuthorizationSuccess) { DEBUG_printf(("8cups_local_auth: AuthorizationCreate() returned %d (%s)", @@ -745,6 +1007,11 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ } # endif /* HAVE_AUTHORIZATION_H */ +# ifdef HAVE_GSSAPI + if (cups_auth_find(www_auth, "Negotiate")) + return (1); +# endif /* HAVE_GSSAPI */ + # if defined(SO_PEERCRED) && defined(AF_LOCAL) /* * See if we can authenticate using the peer credentials provided over a @@ -752,16 +1019,9 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ * information... */ - if ( -# ifdef HAVE_GSSAPI - _cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9) && -# endif /* HAVE_GSSAPI */ -# ifdef HAVE_AUTHORIZATION_H - !httpGetSubField2(http, HTTP_FIELD_WWW_AUTHENTICATE, "authkey", - auth_key, sizeof(auth_key)) && -# endif /* HAVE_AUTHORIZATION_H */ - http->hostaddr->addr.sa_family == AF_LOCAL && - !getenv("GATEWAY_INTERFACE")) /* Not via CGI programs... */ + if (http->hostaddr->addr.sa_family == AF_LOCAL && + !getenv("GATEWAY_INTERFACE") && /* Not via CGI programs... */ + cups_auth_find(www_auth, "PeerCred")) { /* * Verify that the current cupsUser() matches the current UID... @@ -784,6 +1044,9 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ } # endif /* SO_PEERCRED && AF_LOCAL */ + if ((schemedata = cups_auth_find(www_auth, "Local")) == NULL) + return (1); + /* * Try opening a certificate file for this PID. If that fails, * try the root certificate... @@ -797,33 +1060,9 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ * No certificate for this PID; see if we can get the root certificate... */ - DEBUG_printf(("9cups_local_auth: Unable to open file %s: %s", - filename, strerror(errno))); + DEBUG_printf(("9cups_local_auth: Unable to open file \"%s\": %s", filename, strerror(errno))); -# ifdef HAVE_GSSAPI - if (!_cups_strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE], "Negotiate", 9)) - { - /* - * Kerberos required, don't try the root certificate... - */ - - return (1); - } -# 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))) + if (!cups_auth_param(schemedata, "trc", trc, sizeof(trc))) { /* * Scheduler doesn't want us to use the root certificate... @@ -833,7 +1072,8 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ } snprintf(filename, sizeof(filename), "%s/certs/0", cg->cups_statedir); - fp = fopen(filename, "r"); + if ((fp = fopen(filename, "r")) == NULL) + DEBUG_printf(("9cups_local_auth: Unable to open file \"%s\": %s", filename, strerror(errno))); } if (fp) @@ -864,5 +1104,5 @@ cups_local_auth(http_t *http) /* I - HTTP connection to server */ } return (1); -#endif /* WIN32 || __EMX__ */ +#endif /* _WIN32 || __EMX__ */ } diff --git a/cups/backchannel.c b/cups/backchannel.c index e804d45b..bca04dc3 100644 --- a/cups/backchannel.c +++ b/cups/backchannel.c @@ -19,12 +19,12 @@ #include "cups.h" #include <errno.h> -#ifdef WIN32 +#ifdef _WIN32 # include <io.h> # include <fcntl.h> #else # include <sys/time.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ /* @@ -77,11 +77,11 @@ cupsBackChannelRead(char *buffer, /* I - Buffer to read into */ * Read bytes from the pipe... */ -#ifdef WIN32 +#ifdef _WIN32 return ((ssize_t)_read(3, buffer, (unsigned)bytes)); #else return (read(3, buffer, bytes)); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -139,11 +139,11 @@ cupsBackChannelWrite( * Write bytes to the pipe... */ -#ifdef WIN32 +#ifdef _WIN32 count = (ssize_t)_write(3, buffer, (unsigned)(bytes - total)); #else count = write(3, buffer, bytes - total); -#endif /* WIN32 */ +#endif /* _WIN32 */ if (count < 0) { diff --git a/cups/cups.h b/cups/cups.h index 8f5c818f..cf3be127 100644 --- a/cups/cups.h +++ b/cups/cups.h @@ -1,7 +1,7 @@ /* * API definitions for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -21,12 +21,12 @@ */ # include <sys/types.h> -# if defined(WIN32) && !defined(__CUPS_SSIZE_T_DEFINED) +# if defined(_WIN32) && !defined(__CUPS_SSIZE_T_DEFINED) # define __CUPS_SSIZE_T_DEFINED # include <stddef.h> /* Windows does not support the ssize_t type, so map it to long... */ typedef long ssize_t; /* @private@ */ -# endif /* WIN32 && !__CUPS_SSIZE_T_DEFINED */ +# endif /* _WIN32 && !__CUPS_SSIZE_T_DEFINED */ # include "file.h" # include "ipp.h" @@ -47,10 +47,10 @@ extern "C" { * Constants... */ -# define CUPS_VERSION 2.0206 +# define CUPS_VERSION 2.0209 # define CUPS_VERSION_MAJOR 2 # define CUPS_VERSION_MINOR 2 -# define CUPS_VERSION_PATCH 6 +# define CUPS_VERSION_PATCH 9 # define CUPS_BC_FD 3 /* Back-channel file descriptor for @@ -606,6 +606,9 @@ extern ssize_t cupsHashData(const char *algorithm, const void *data, size_t dat extern int cupsAddIntegerOption(const char *name, int value, int num_options, cups_option_t **options) _CUPS_API_2_2_4; extern int cupsGetIntegerOption(const char *name, int num_options, cups_option_t *options) _CUPS_API_2_2_4; +/* New in CUPS 2.2.7 */ +extern const char *cupsHashString(const unsigned char *hash, size_t hashsize, char *buffer, size_t bufsize) _CUPS_API_2_2_7; + # ifdef __cplusplus } # endif /* __cplusplus */ diff --git a/cups/debug-private.h b/cups/debug-private.h index 23a0ae17..dc9fe4eb 100644 --- a/cups/debug-private.h +++ b/cups/debug-private.h @@ -1,7 +1,7 @@ /* * Private debugging macros for CUPS. * - * Copyright 2007-2012 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -67,20 +67,10 @@ extern "C" { */ # ifdef DEBUG -# ifdef WIN32 -# ifdef LIBCUPS2_EXPORTS -# define DLLExport __declspec(dllexport) -# else -# define DLLExport -# endif /* LIBCUPS2_EXPORTS */ -# else -# define DLLExport -# endif /* WIN32 */ # define DEBUG_puts(x) _cups_debug_puts(x) # define DEBUG_printf(x) _cups_debug_printf x # define DEBUG_set(logfile,level,filter) _cups_debug_set(logfile,level,filter,1) # else -# define DLLExport # define DEBUG_puts(x) # define DEBUG_printf(x) # define DEBUG_set(logfile,level,filter) @@ -93,16 +83,13 @@ extern "C" { extern int _cups_debug_fd; extern int _cups_debug_level; -extern void DLLExport _cups_debug_printf(const char *format, ...) - __attribute__ ((__format__ (__printf__, 1, 2))); -extern void DLLExport _cups_debug_puts(const char *s); -extern void DLLExport _cups_debug_set(const char *logfile, - const char *level, const char *filter, - int force); -# ifdef WIN32 -extern int _cups_gettimeofday(struct timeval *tv, void *tz); +extern void _cups_debug_printf(const char *format, ...) _CUPS_FORMAT(1, 2); +extern void _cups_debug_puts(const char *s); +extern void _cups_debug_set(const char *logfile, const char *level, const char *filter, int force) _CUPS_PRIVATE; +# ifdef _WIN32 +extern int _cups_gettimeofday(struct timeval *tv, void *tz) _CUPS_PRIVATE; # define gettimeofday(a,b) _cups_gettimeofday(a, b) -# endif /* WIN32 */ +# endif /* _WIN32 */ # ifdef __cplusplus } diff --git a/cups/debug.c b/cups/debug.c index bd244fe7..b68f5edb 100644 --- a/cups/debug.c +++ b/cups/debug.c @@ -18,7 +18,7 @@ #include "cups-private.h" #include "thread-private.h" -#ifdef WIN32 +#ifdef _WIN32 # include <sys/timeb.h> # include <time.h> # include <io.h> @@ -36,7 +36,7 @@ _cups_gettimeofday(struct timeval *tv, /* I - Timeval struct */ #else # include <sys/time.h> # include <unistd.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ #include <regex.h> #include <fcntl.h> @@ -83,7 +83,7 @@ debug_thread_id(void) * '_cups_debug_printf()' - Write a formatted line to the log. */ -void DLLExport +void _cups_debug_printf(const char *format, /* I - Printf-style format string */ ...) /* I - Additional arguments as needed */ { @@ -168,7 +168,7 @@ _cups_debug_printf(const char *format, /* I - Printf-style format string */ * '_cups_debug_puts()' - Write a single line to the log. */ -void DLLExport +void _cups_debug_puts(const char *s) /* I - String to output */ { struct timeval curtime; /* Current time */ @@ -248,7 +248,7 @@ _cups_debug_puts(const char *s) /* I - String to output */ * '_cups_debug_set()' - Enable or disable debug logging. */ -void DLLExport +void _cups_debug_set(const char *logfile, /* I - Log file or NULL */ const char *level, /* I - Log level or NULL */ const char *filter, /* I - Filter string or NULL */ diff --git a/cups/dest.c b/cups/dest.c index 57a8dc95..7ef85a1b 100644 --- a/cups/dest.c +++ b/cups/dest.c @@ -2090,9 +2090,9 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ cups_option_t *option; /* Current option */ _ipp_option_t *match; /* Matching attribute for option */ FILE *fp; /* File pointer */ -#ifndef WIN32 +#ifndef _WIN32 const char *home; /* HOME environment variable */ -#endif /* WIN32 */ +#endif /* _WIN32 */ char filename[1024]; /* lpoptions file */ int num_temps; /* Number of temporary destinations */ cups_dest_t *temps = NULL, /* Temporary destinations */ @@ -2126,7 +2126,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot); -#ifndef WIN32 +#ifndef _WIN32 if (getuid()) { /* @@ -2152,7 +2152,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home); } } -#endif /* !WIN32 */ +#endif /* !_WIN32 */ /* * Try to open the file... @@ -2164,7 +2164,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ return (-1); } -#ifndef WIN32 +#ifndef _WIN32 /* * Set the permissions to 0644 when saving to the /etc/cups/lpoptions * file... @@ -2172,7 +2172,7 @@ cupsSetDests2(http_t *http, /* I - Connection to server or @code CUPS_HTTP_ if (!getuid()) fchmod(fileno(fp), 0644); -#endif /* !WIN32 */ +#endif /* !_WIN32 */ /* * Write each printer; each line looks like: @@ -26,7 +26,7 @@ * Windows implementation... */ -#ifdef WIN32 +#ifdef _WIN32 # include <windows.h> /* @@ -145,7 +145,7 @@ cupsDirOpen(const char *directory) /* I - Directory name */ cups_dentry_t * /* O - Directory entry or @code NULL@ if there are no more */ cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */ { - WIN32_FIND_DATA entry; /* Directory entry data */ + WIN32_FIND_DATAA entry; /* Directory entry data */ /* @@ -165,11 +165,11 @@ cupsDirRead(cups_dir_t *dp) /* I - Directory pointer */ * No, find the first file... */ - dp->dir = FindFirstFile(dp->directory, &entry); + dp->dir = FindFirstFileA(dp->directory, &entry); if (dp->dir == INVALID_HANDLE_VALUE) return (NULL); } - else if (!FindNextFile(dp->dir, &entry)) + else if (!FindNextFileA(dp->dir, &entry)) return (NULL); /* @@ -422,4 +422,4 @@ cupsDirRewind(cups_dir_t *dp) /* I - Directory pointer */ rewinddir(dp->dir); } -#endif /* WIN32 */ +#endif /* _WIN32 */ diff --git a/cups/file-private.h b/cups/file-private.h index 1f4db798..6789283e 100644 --- a/cups/file-private.h +++ b/cups/file-private.h @@ -6,7 +6,7 @@ * our own file functions allows us to provide transparent support of * different line endings, gzip'd print files, PPD files, etc. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -31,13 +31,10 @@ # include <stdarg.h> # include <fcntl.h> -# ifdef HAVE_LIBZ -# include <zlib.h> -# endif /* HAVE_LIBZ */ -# ifdef WIN32 +# ifdef _WIN32 # include <io.h> # include <sys/locking.h> -# endif /* WIN32 */ +# endif /* _WIN32 */ /* @@ -88,30 +85,6 @@ typedef enum /**** _cupsFileCheck file type values ****/ typedef void (*_cups_fc_func_t)(void *context, _cups_fc_result_t result, const char *message); -struct _cups_file_s /**** CUPS file structure... ****/ - -{ - int fd; /* File descriptor */ - char mode, /* Mode ('r' or 'w') */ - compressed, /* Compression used? */ - is_stdio, /* stdin/out/err? */ - eof, /* End of file? */ - buf[4096], /* Buffer */ - *ptr, /* Pointer into buffer */ - *end; /* End of buffer data */ - off_t pos, /* Position in file */ - bufpos; /* File position for start of buffer */ - -#ifdef HAVE_LIBZ - z_stream stream; /* (De)compression stream */ - Bytef cbuf[4096]; /* (De)compression buffer */ - uLong crc; /* (De)compression CRC */ -#endif /* HAVE_LIBZ */ - - char *printf_buffer; /* cupsFilePrintf buffer */ - size_t printf_size; /* Size of cupsFilePrintf buffer */ -}; - /* * Prototypes... @@ -125,6 +98,7 @@ extern _cups_fc_result_t _cupsFileCheck(const char *filename, extern void _cupsFileCheckFilter(void *context, _cups_fc_result_t result, const char *message); +extern int _cupsFilePeekAhead(cups_file_t *fp, int ch); # ifdef __cplusplus } diff --git a/cups/file.c b/cups/file.c index 5d150540..5c9ddf8f 100644 --- a/cups/file.c +++ b/cups/file.c @@ -6,7 +6,7 @@ * our own file functions allows us to provide transparent support of * different line endings, gzip'd print files, PPD files, etc. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -26,6 +26,39 @@ #include <sys/stat.h> #include <sys/types.h> +# ifdef HAVE_LIBZ +# include <zlib.h> +# endif /* HAVE_LIBZ */ + + +/* + * Internal structures... + */ + +struct _cups_file_s /**** CUPS file structure... ****/ + +{ + int fd; /* File descriptor */ + char mode, /* Mode ('r' or 'w') */ + compressed, /* Compression used? */ + is_stdio, /* stdin/out/err? */ + eof, /* End of file? */ + buf[4096], /* Buffer */ + *ptr, /* Pointer into buffer */ + *end; /* End of buffer data */ + off_t pos, /* Position in file */ + bufpos; /* File position for start of buffer */ + +#ifdef HAVE_LIBZ + z_stream stream; /* (De)compression stream */ + Bytef cbuf[4096]; /* (De)compression buffer */ + uLong crc; /* (De)compression CRC */ +#endif /* HAVE_LIBZ */ + + char *printf_buffer; /* cupsFilePrintf buffer */ + size_t printf_size; /* Size of cupsFilePrintf buffer */ +}; + /* * Local functions... @@ -40,7 +73,7 @@ static ssize_t cups_read(cups_file_t *fp, char *buf, size_t bytes); static ssize_t cups_write(cups_file_t *fp, const char *buf, size_t bytes); -#ifndef WIN32 +#ifndef _WIN32 /* * '_cupsFileCheck()' - Check the permissions of the given filename. */ @@ -306,7 +339,7 @@ _cupsFileCheckFilter( fprintf(stderr, "%s: %s\n", prefix, message); } -#endif /* !WIN32 */ +#endif /* !_WIN32 */ /* @@ -526,22 +559,22 @@ cupsFileFind(const char *filename, /* I - File to find */ while (*path) { -#ifdef WIN32 +#ifdef _WIN32 if (*path == ';' || (*path == ':' && ((bufptr - buffer) > 1 || !isalpha(buffer[0] & 255)))) #else if (*path == ';' || *path == ':') -#endif /* WIN32 */ +#endif /* _WIN32 */ { if (bufptr > buffer && bufptr[-1] != '/' && bufptr < bufend) *bufptr++ = '/'; strlcpy(bufptr, filename, (size_t)(bufend - bufptr)); -#ifdef WIN32 +#ifdef _WIN32 if (!access(buffer, 0)) #else if (!access(buffer, executable ? X_OK : 0)) -#endif /* WIN32 */ +#endif /* _WIN32 */ { DEBUG_printf(("1cupsFileFind: Returning \"%s\"", buffer)); return (buffer); @@ -992,11 +1025,11 @@ cupsFileLock(cups_file_t *fp, /* I - CUPS file */ * Try the lock... */ -#ifdef WIN32 +#ifdef _WIN32 return (_locking(fp->fd, block ? _LK_LOCK : _LK_NBLCK, 0)); #else return (lockf(fp->fd, block ? F_LOCK : F_TLOCK, 0)); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -1084,11 +1117,11 @@ cupsFileOpen(const char *filename, /* I - Name of file */ } if (fd >= 0) -#ifdef WIN32 +#ifdef _WIN32 _chsize(fd, 0); #else ftruncate(fd, 0); -#endif /* WIN32 */ +#endif /* _WIN32 */ break; case 's' : /* Read/write socket */ @@ -1255,15 +1288,27 @@ cupsFileOpenFd(int fd, /* I - File descriptor */ * Don't pass this file to child processes... */ -#ifndef WIN32 +#ifndef _WIN32 fcntl(fp->fd, F_SETFD, fcntl(fp->fd, F_GETFD) | FD_CLOEXEC); -#endif /* !WIN32 */ +#endif /* !_WIN32 */ return (fp); } /* + * '_cupsFilePeekAhead()' - See if the requested character is buffered up. + */ + +int /* O - 1 if present, 0 otherwise */ +_cupsFilePeekAhead(cups_file_t *fp, /* I - CUPS file */ + int ch) /* I - Character */ +{ + return (fp && fp->ptr && memchr(fp->ptr, ch, (size_t)(fp->end - fp->ptr))); +} + + +/* * 'cupsFilePeekChar()' - Peek at the next character from a file. * * @since CUPS 1.2/macOS 10.5@ @@ -2019,11 +2064,11 @@ cupsFileUnlock(cups_file_t *fp) /* I - CUPS file */ * Unlock... */ -#ifdef WIN32 +#ifdef _WIN32 return (_locking(fp->fd, _LK_UNLCK, 0)); #else return (lockf(fp->fd, F_ULOCK, 0)); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -2553,9 +2598,9 @@ cups_open(const char *filename, /* I - Filename */ { int fd; /* File descriptor */ struct stat fileinfo; /* File information */ -#ifndef WIN32 +#ifndef _WIN32 struct stat linkinfo; /* Link information */ -#endif /* !WIN32 */ +#endif /* !_WIN32 */ /* @@ -2583,18 +2628,18 @@ cups_open(const char *filename, /* I - Filename */ return (-1); } -#ifdef WIN32 +#ifdef _WIN32 if (fileinfo.st_mode & _S_IFDIR) #else if (S_ISDIR(fileinfo.st_mode)) -#endif /* WIN32 */ +#endif /* _WIN32 */ { close(fd); errno = EISDIR; return (-1); } -#ifndef WIN32 +#ifndef _WIN32 /* * Then use lstat to determine whether the filename is a symlink... */ @@ -2622,7 +2667,7 @@ cups_open(const char *filename, /* I - Filename */ errno = EPERM; return (-1); } -#endif /* !WIN32 */ +#endif /* !_WIN32 */ return (fd); } @@ -2648,7 +2693,7 @@ cups_read(cups_file_t *fp, /* I - CUPS file */ for (;;) { -#ifdef WIN32 +#ifdef _WIN32 if (fp->mode == 's') total = (ssize_t)recv(fp->fd, buf, (unsigned)bytes, 0); else @@ -2658,7 +2703,7 @@ cups_read(cups_file_t *fp, /* I - CUPS file */ total = recv(fp->fd, buf, bytes, 0); else total = read(fp->fd, buf, bytes); -#endif /* WIN32 */ +#endif /* _WIN32 */ DEBUG_printf(("9cups_read: total=" CUPS_LLFMT, CUPS_LLCAST total)); @@ -2705,7 +2750,7 @@ cups_write(cups_file_t *fp, /* I - CUPS file */ total = 0; while (bytes > 0) { -#ifdef WIN32 +#ifdef _WIN32 if (fp->mode == 's') count = (ssize_t)send(fp->fd, buf, (unsigned)bytes, 0); else @@ -2715,7 +2760,7 @@ cups_write(cups_file_t *fp, /* I - CUPS file */ count = send(fp->fd, buf, bytes, 0); else count = write(fp->fd, buf, bytes); -#endif /* WIN32 */ +#endif /* _WIN32 */ DEBUG_printf(("9cups_write: count=" CUPS_LLFMT, CUPS_LLCAST count)); diff --git a/cups/file.h b/cups/file.h index 42abe208..0d3a2e5d 100644 --- a/cups/file.h +++ b/cups/file.h @@ -6,7 +6,7 @@ * our own file functions allows us to provide transparent support of * different line endings, gzip'd print files, PPD files, etc. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -29,11 +29,11 @@ # include "versioning.h" # include <stddef.h> # include <sys/types.h> -# if defined(WIN32) && !defined(__CUPS_SSIZE_T_DEFINED) +# if defined(_WIN32) && !defined(__CUPS_SSIZE_T_DEFINED) # define __CUPS_SSIZE_T_DEFINED /* Windows does not support the ssize_t type, so map it to off_t... */ typedef off_t ssize_t; /* @private@ */ -# endif /* WIN32 && !__CUPS_SSIZE_T_DEFINED */ +# endif /* _WIN32 && !__CUPS_SSIZE_T_DEFINED */ /* @@ -85,9 +85,7 @@ extern cups_file_t *cupsFileOpen(const char *filename, const char *mode) _CUPS_API_1_2; extern cups_file_t *cupsFileOpenFd(int fd, const char *mode) _CUPS_API_1_2; extern int cupsFilePeekChar(cups_file_t *fp) _CUPS_API_1_2; -extern int cupsFilePrintf(cups_file_t *fp, const char *format, ...) - __attribute__((__format__ (__printf__, 2, 3))) - _CUPS_API_1_2; +extern int cupsFilePrintf(cups_file_t *fp, const char *format, ...) _CUPS_FORMAT(2, 3) _CUPS_API_1_2; extern int cupsFilePutChar(cups_file_t *fp, int c) _CUPS_API_1_2; extern ssize_t cupsFilePutConf(cups_file_t *fp, const char *directive, const char *value) _CUPS_API_1_4; diff --git a/cups/getputfile.c b/cups/getputfile.c index ae33bc59..7749ae0a 100644 --- a/cups/getputfile.c +++ b/cups/getputfile.c @@ -1,7 +1,7 @@ /* * Get/put file functions for CUPS. * - * Copyright 2007-2014 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -20,11 +20,11 @@ #include "cups-private.h" #include <fcntl.h> #include <sys/stat.h> -#if defined(WIN32) || defined(__EMX__) +#if defined(_WIN32) || defined(__EMX__) # include <io.h> #else # include <unistd.h> -#endif /* WIN32 || __EMX__ */ +#endif /* _WIN32 || __EMX__ */ /* @@ -45,6 +45,8 @@ cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFA http_status_t status; /* HTTP status from server */ char if_modified_since[HTTP_MAX_VALUE]; /* If-Modified-Since header */ + int new_auth = 0; /* Using new auth information? */ + int digest; /* Are we using Digest authentication? */ /* @@ -85,9 +87,33 @@ cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFA } httpClearFields(http); - httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since); + digest = http->authstring && !strncmp(http->authstring, "Digest ", 7); + + if (digest && !new_auth) + { + /* + * Update the Digest authentication string... + */ + + _httpSetDigestAuthString(http, http->nextnonce, "GET", resource); + } + +#ifdef HAVE_GSSAPI + if (http->authstring && !strncmp(http->authstring, "Negotiate", 9) && !new_auth) + { + /* + * Do not use cached Kerberos credentials since they will look like a + * "replay" attack... + */ + + _cupsSetNegotiateAuthString(http, "GET", resource); + } +#endif /* HAVE_GSSAPI */ + + httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); + if (httpGet(http, resource)) { if (httpReconnect2(http, 30000, NULL)) @@ -102,6 +128,8 @@ cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFA } } + new_auth = 0; + while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); if (status == HTTP_STATUS_UNAUTHORIZED) @@ -116,6 +144,8 @@ cupsGetFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFA * See if we can do authentication... */ + new_auth = 1; + if (cupsDoAuthentication(http, "GET", resource)) { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; @@ -267,6 +297,8 @@ cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFA int retries; /* Number of retries */ char buffer[8192]; /* Buffer for file */ http_status_t status; /* HTTP status from server */ + int new_auth = 0; /* Using new auth information? */ + int digest; /* Are we using Digest authentication? */ /* @@ -309,10 +341,34 @@ cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFA http->authstring)); httpClearFields(http); - httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked"); httpSetExpect(http, HTTP_STATUS_CONTINUE); + digest = http->authstring && !strncmp(http->authstring, "Digest ", 7); + + if (digest && !new_auth) + { + /* + * Update the Digest authentication string... + */ + + _httpSetDigestAuthString(http, http->nextnonce, "PUT", resource); + } + +#ifdef HAVE_GSSAPI + if (http->authstring && !strncmp(http->authstring, "Negotiate", 9) && !new_auth) + { + /* + * Do not use cached Kerberos credentials since they will look like a + * "replay" attack... + */ + + _cupsSetNegotiateAuthString(http, "PUT", resource); + } +#endif /* HAVE_GSSAPI */ + + httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring); + if (httpPut(http, resource)) { if (httpReconnect2(http, 30000, NULL)) @@ -383,6 +439,8 @@ cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFA DEBUG_printf(("2cupsPutFd: status=%d", status)); + new_auth = 0; + if (status == HTTP_STATUS_UNAUTHORIZED) { /* @@ -395,6 +453,8 @@ cupsPutFd(http_t *http, /* I - Connection to server or @code CUPS_HTTP_DEFA * See if we can do authentication... */ + new_auth = 1; + if (cupsDoAuthentication(http, "PUT", resource)) { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; diff --git a/cups/globals.c b/cups/globals.c index 8a05c3eb..28c993be 100644 --- a/cups/globals.c +++ b/cups/globals.c @@ -34,23 +34,23 @@ static _cups_threadkey_t cups_globals_key = _CUPS_THREADKEY_INITIALIZER; static pthread_once_t cups_globals_key_once = PTHREAD_ONCE_INIT; /* One-time initialization object */ #endif /* HAVE_PTHREAD_H */ -#if defined(HAVE_PTHREAD_H) || defined(WIN32) +#if defined(HAVE_PTHREAD_H) || defined(_WIN32) static _cups_mutex_t cups_global_mutex = _CUPS_MUTEX_INITIALIZER; /* Global critical section */ -#endif /* HAVE_PTHREAD_H || WIN32 */ +#endif /* HAVE_PTHREAD_H || _WIN32 */ /* * Local functions... */ -#ifdef WIN32 +#ifdef _WIN32 static void cups_fix_path(char *path); -#endif /* WIN32 */ +#endif /* _WIN32 */ static _cups_globals_t *cups_globals_alloc(void); -#if defined(HAVE_PTHREAD_H) || defined(WIN32) +#if defined(HAVE_PTHREAD_H) || defined(_WIN32) static void cups_globals_free(_cups_globals_t *g); -#endif /* HAVE_PTHREAD_H || WIN32 */ +#endif /* HAVE_PTHREAD_H || _WIN32 */ #ifdef HAVE_PTHREAD_H static void cups_globals_init(void); #endif /* HAVE_PTHREAD_H */ @@ -65,7 +65,7 @@ _cupsGlobalLock(void) { #ifdef HAVE_PTHREAD_H pthread_mutex_lock(&cups_global_mutex); -#elif defined(WIN32) +#elif defined(_WIN32) EnterCriticalSection(&cups_global_mutex.m_criticalSection); #endif /* HAVE_PTHREAD_H */ } @@ -120,13 +120,13 @@ _cupsGlobalUnlock(void) { #ifdef HAVE_PTHREAD_H pthread_mutex_unlock(&cups_global_mutex); -#elif defined(WIN32) +#elif defined(_WIN32) LeaveCriticalSection(&cups_global_mutex.m_criticalSection); #endif /* HAVE_PTHREAD_H */ } -#ifdef WIN32 +#ifdef _WIN32 /* * 'DllMain()' - Main entry for library. */ @@ -170,7 +170,7 @@ DllMain(HINSTANCE hinst, /* I - DLL module handle */ return (TRUE); } -#endif /* WIN32 */ +#endif /* _WIN32 */ /* @@ -182,13 +182,13 @@ cups_globals_alloc(void) { _cups_globals_t *cg = malloc(sizeof(_cups_globals_t)); /* Pointer to global data */ -#ifdef WIN32 +#ifdef _WIN32 HKEY key; /* Registry key */ DWORD size; /* Size of string */ static char installdir[1024] = "", /* Install directory */ confdir[1024] = "", /* Server root directory */ localedir[1024] = ""; /* Locale directory */ -#endif /* WIN32 */ +#endif /* _WIN32 */ if (!cg) @@ -219,7 +219,7 @@ cups_globals_alloc(void) * Then set directories as appropriate... */ -#ifdef WIN32 +#ifdef _WIN32 if (!installdir[0]) { /* @@ -315,7 +315,7 @@ cups_globals_alloc(void) if ((cg->localedir = getenv("LOCALEDIR")) == NULL) cg->localedir = CUPS_LOCALEDIR; } -#endif /* WIN32 */ +#endif /* _WIN32 */ return (cg); } @@ -325,7 +325,7 @@ cups_globals_alloc(void) * 'cups_globals_free()' - Free global data. */ -#if defined(HAVE_PTHREAD_H) || defined(WIN32) +#if defined(HAVE_PTHREAD_H) || defined(_WIN32) static void cups_globals_free(_cups_globals_t *cg) /* I - Pointer to global data */ { @@ -360,7 +360,7 @@ cups_globals_free(_cups_globals_t *cg) /* I - Pointer to global data */ free(cg); } -#endif /* HAVE_PTHREAD_H || WIN32 */ +#endif /* HAVE_PTHREAD_H || _WIN32 */ #ifdef HAVE_PTHREAD_H diff --git a/cups/hash.c b/cups/hash.c index ede54616..50dc5fb3 100644 --- a/cups/hash.c +++ b/cups/hash.c @@ -1,7 +1,7 @@ /* * Hashing function for CUPS. * - * Copyright 2015-2016 by Apple Inc. + * Copyright © 2015-2018 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -21,6 +21,8 @@ # include <CommonCrypto/CommonDigest.h> #elif defined(HAVE_GNUTLS) # include <gnutls/crypto.h> +#else +# include "md5-private.h" #endif /* __APPLE__ */ @@ -53,7 +55,24 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ } #ifdef __APPLE__ - if (!strcmp(algorithm, "sha")) + if (!strcmp(algorithm, "md5")) + { + /* + * MD5 (deprecated but widely used...) + */ + + CC_MD5_CTX ctx; /* MD5 context */ + + if (hashsize < CC_MD5_DIGEST_LENGTH) + goto too_small; + + CC_MD5_Init(&ctx); + CC_MD5_Update(&ctx, data, (CC_LONG)datalen); + CC_MD5_Final(hash, &ctx); + + return (CC_MD5_DIGEST_LENGTH); + } + else if (!strcmp(algorithm, "sha")) { /* * SHA-1... @@ -171,7 +190,9 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ unsigned char temp[64]; /* Temporary hash buffer */ size_t tempsize = 0; /* Truncate to this size? */ - if (!strcmp(algorithm, "sha")) + if (!strcmp(algorithm, "md5")) + alg = GNUTLS_DIG_MD5; + else if (!strcmp(algorithm, "sha")) alg = GNUTLS_DIG_SHA1; else if (!strcmp(algorithm, "sha2-224")) alg = GNUTLS_DIG_SHA224; @@ -219,10 +240,20 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ #else /* - * No hash support without CommonCrypto or GNU TLS... + * No hash support beyond MD5 without CommonCrypto or GNU TLS... */ - if (hashsize < 64) + if (!strcmp(algorithm, "md5")) + { + _cups_md5_state_t state; /* MD5 state info */ + + _cupsMD5Init(&state); + _cupsMD5Append(&state, data, datalen); + _cupsMD5Finish(&state, hash); + + return (16); + } + else if (hashsize < 64) goto too_small; #endif /* __APPLE__ */ @@ -243,3 +274,53 @@ cupsHashData(const char *algorithm, /* I - Algorithm name */ _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Hash buffer too small."), 1); return (-1); } + + +/* + * 'cupsHashString()' - Format a hash value as a hexadecimal string. + * + * The passed buffer must be at least 2 * hashsize + 1 characters in length. + * + * @since CUPS 2.2.7@ + */ + +const char * /* O - Formatted string */ +cupsHashString( + const unsigned char *hash, /* I - Hash */ + size_t hashsize, /* I - Size of hash */ + char *buffer, /* I - String buffer */ + size_t bufsize) /* I - Size of string buffer */ +{ + char *bufptr = buffer; /* Pointer into buffer */ + static const char *hex = "0123456789abcdef"; + /* Hex characters (lowercase!) */ + + + /* + * Range check input... + */ + + if (!hash || hashsize < 1 || !buffer || bufsize < (2 * hashsize + 1)) + { + if (buffer) + *buffer = '\0'; + return (NULL); + } + + /* + * Loop until we've converted the whole hash... + */ + + while (hashsize > 0) + { + *bufptr++ = hex[*hash >> 4]; + *bufptr++ = hex[*hash & 15]; + + hash ++; + hashsize --; + } + + *bufptr = '\0'; + + return (buffer); +} diff --git a/cups/http-addr.c b/cups/http-addr.c index 61c86384..f8b8131c 100644 --- a/cups/http-addr.c +++ b/cups/http-addr.c @@ -69,11 +69,11 @@ int /* O - 0 on success, -1 on failure */ httpAddrClose(http_addr_t *addr, /* I - Listen address or @code NULL@ */ int fd) /* I - Socket file descriptor */ { -#ifdef WIN32 +#ifdef _WIN32 if (closesocket(fd)) #else if (close(fd)) -#endif /* WIN32 */ +#endif /* _WIN32 */ return (-1); #ifdef AF_LOCAL @@ -258,9 +258,9 @@ httpAddrListen(http_addr_t *addr, /* I - Address to bind to */ * Close on exec... */ -#ifndef WIN32 +#ifndef _WIN32 fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC); -#endif /* !WIN32 */ +#endif /* !_WIN32 */ #ifdef SO_NOSIGPIPE /* diff --git a/cups/http-addrlist.c b/cups/http-addrlist.c index e5fc940e..d9a96c4e 100644 --- a/cups/http-addrlist.c +++ b/cups/http-addrlist.c @@ -1,7 +1,7 @@ /* * HTTP address list routines for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -24,9 +24,9 @@ #ifdef HAVE_POLL # include <poll.h> #endif /* HAVE_POLL */ -#ifndef WIN32 +#ifndef _WIN32 # include <fcntl.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ /* @@ -61,14 +61,14 @@ httpAddrConnect2( int *cancel) /* I - Pointer to "cancel" variable */ { int val; /* Socket option value */ -#ifndef WIN32 - int flags; /* Socket flags */ -#endif /* !WIN32 */ - int remaining; /* Remaining timeout */ +#ifndef _WIN32 int i, j, /* Looping vars */ - nfds, /* Number of file descriptors */ - fds[100], /* Socket file descriptors */ + flags, /* Socket flags */ result; /* Result from select() or poll() */ +#endif /* !_WIN32 */ + int remaining; /* Remaining timeout */ + int nfds, /* Number of file descriptors */ + fds[100]; /* Socket file descriptors */ http_addrlist_t *addrs[100]; /* Addresses */ #ifndef HAVE_POLL int max_fd = -1; /* Highest file descriptor */ @@ -84,8 +84,10 @@ httpAddrConnect2( # endif /* HAVE_POLL */ #endif /* O_NONBLOCK */ #ifdef DEBUG +# ifndef _WIN32 socklen_t len; /* Length of value */ http_addr_t peer; /* Peer address */ +# endif /* !_WIN32 */ char temp[256]; /* Temporary address string */ #endif /* DEBUG */ @@ -213,11 +215,11 @@ httpAddrConnect2( return (addrlist); } -#ifdef WIN32 +#ifdef _WIN32 if (WSAGetLastError() != WSAEINPROGRESS && WSAGetLastError() != WSAEWOULDBLOCK) #else if (errno != EINPROGRESS && errno != EWOULDBLOCK) -#endif /* WIN32 */ +#endif /* _WIN32 */ { DEBUG_printf(("1httpAddrConnect2: Unable to connect to %s:%d: %s", httpAddrString(&(addrlist->addr), temp, sizeof(temp)), httpAddrPort(&(addrlist->addr)), strerror(errno))); httpAddrClose(NULL, fds[nfds]); @@ -225,9 +227,9 @@ httpAddrConnect2( continue; } -#ifndef WIN32 +#ifndef _WIN32 fcntl(fds[nfds], F_SETFL, flags); -#endif /* !WIN32 */ +#endif /* !_WIN32 */ #ifndef HAVE_POLL if (fds[nfds] > max_fd) @@ -296,11 +298,11 @@ httpAddrConnect2( DEBUG_printf(("1httpAddrConnect2: select() returned %d (%d)", result, errno)); # endif /* HAVE_POLL */ } -# ifdef WIN32 +# ifdef _WIN32 while (result < 0 && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)); # else while (result < 0 && (errno == EINTR || errno == EAGAIN)); -# endif /* WIN32 */ +# endif /* _WIN32 */ if (result > 0) { @@ -377,11 +379,11 @@ httpAddrConnect2( httpAddrClose(NULL, fds[nfds]); } -#ifdef WIN32 +#ifdef _WIN32 _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, "Connection failed", 0); #else _cupsSetError(IPP_STATUS_ERROR_SERVICE_UNAVAILABLE, strerror(errno), 0); -#endif /* WIN32 */ +#endif /* _WIN32 */ return (NULL); } @@ -618,6 +620,7 @@ httpAddrGetList(const char *hostname, /* I - Hostname, IP address, or NULL for p if (!temp) { httpAddrFreeList(first); + freeaddrinfo(results); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); return (NULL); } @@ -848,11 +851,11 @@ httpAddrGetList(const char *hostname, /* I - Hostname, IP address, or NULL for p temp->addr.ipv6.sin6_family = AF_INET6; temp->addr.ipv6.sin6_port = htons(portnum); -# ifdef WIN32 +# ifdef _WIN32 temp->addr.ipv6.sin6_addr.u.Byte[15] = 1; # else temp->addr.ipv6.sin6_addr.s6_addr32[3] = htonl(1); -# endif /* WIN32 */ +# endif /* _WIN32 */ if (!first) first = temp; diff --git a/cups/http-private.h b/cups/http-private.h index f71e564b..32cb9ea5 100644 --- a/cups/http-private.h +++ b/cups/http-private.h @@ -1,7 +1,7 @@ /* * Private HTTP definitions for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -30,7 +30,7 @@ # endif /* __sun */ # include <limits.h> -# ifdef WIN32 +# ifdef _WIN32 # include <io.h> # include <winsock2.h> # define CUPS_SOCAST (const char *) @@ -39,7 +39,7 @@ # include <fcntl.h> # include <sys/socket.h> # define CUPS_SOCAST -# endif /* WIN32 */ +# endif /* _WIN32 */ # ifdef HAVE_GSSAPI # ifdef HAVE_GSS_GSSAPI_H @@ -68,7 +68,6 @@ typedef int socklen_t; # endif /* __APPLE__ && !_SOCKLEN_T */ # include <cups/http.h> -# include "md5-private.h" # include "ipp-private.h" # ifdef HAVE_GNUTLS @@ -141,7 +140,7 @@ extern SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator, SecCertificate # include <sspi.h> # endif /* HAVE_GNUTLS */ -# ifndef WIN32 +# ifndef _WIN32 # include <net/if.h> # include <resolv.h> # ifdef HAVE_GETIFADDRS @@ -152,11 +151,7 @@ extern SecIdentityRef SecIdentityCreate(CFAllocatorRef allocator, SecCertificate # include <sys/sockio.h> # endif /* HAVE_SYS_SOCKIO_H */ # endif /* HAVE_GETIFADDRS */ -# endif /* !WIN32 */ - -# ifdef HAVE_LIBZ -# include <zlib.h> -# endif /* HAVE_LIBZ */ +# endif /* !_WIN32 */ /* @@ -180,13 +175,17 @@ extern "C" { # define _HTTP_TLS_NONE 0 /* No TLS options */ # define _HTTP_TLS_ALLOW_RC4 1 /* Allow RC4 cipher suites */ -# define _HTTP_TLS_ALLOW_SSL3 2 /* Allow SSL 3.0 */ -# define _HTTP_TLS_ALLOW_DH 4 /* Allow DH/DHE key negotiation */ -# define _HTTP_TLS_DENY_TLS10 16 /* Deny TLS 1.0 */ -# define _HTTP_TLS_DENY_CBC 32 /* Deny CBC cipher suites */ -# define _HTTP_TLS_ONLY_TLS10 64 /* Only use TLS 1.0 */ +# define _HTTP_TLS_ALLOW_DH 2 /* Allow DH/DHE key negotiation */ +# define _HTTP_TLS_DENY_CBC 4 /* Deny CBC cipher suites */ # define _HTTP_TLS_SET_DEFAULT 128 /* Setting the default TLS options */ +# define _HTTP_TLS_SSL3 0 /* Min/max version is SSL/3.0 */ +# define _HTTP_TLS_1_0 1 /* Min/max version is TLS/1.0 */ +# define _HTTP_TLS_1_1 2 /* Min/max version is TLS/1.1 */ +# define _HTTP_TLS_1_2 3 /* Min/max version is TLS/1.2 */ +# define _HTTP_TLS_1_3 4 /* Min/max version is TLS/1.3 */ +# define _HTTP_TLS_MAX 5 /* Highest known TLS version */ + /* * Types and functions for SSL support... @@ -297,10 +296,10 @@ struct _http_s /**** HTTP connection structure ****/ char buffer[HTTP_MAX_BUFFER]; /* Buffer for incoming data */ int _auth_type; /* Authentication in use (deprecated) */ - _cups_md5_state_t md5_state; /* MD5 state */ + unsigned char _md5_state[88]; /* MD5 state (deprecated) */ char nonce[HTTP_MAX_VALUE]; /* Nonce value */ - int nonce_count; /* Nonce count */ + unsigned nonce_count; /* Nonce count */ http_tls_t tls; /* TLS state information */ http_encryption_t encryption; /* Encryption requirements */ @@ -361,9 +360,20 @@ struct _http_s /**** HTTP connection structure ****/ /* Default field values */ # ifdef HAVE_LIBZ _http_coding_t coding; /* _HTTP_CODING_xxx */ - z_stream stream; /* (De)compression stream */ - Bytef *sbuffer; /* (De)compression buffer */ + void *stream; /* (De)compression stream */ + unsigned char *sbuffer; /* (De)compression buffer */ # endif /* HAVE_LIBZ */ + + /**** New in CUPS 2.2.9 ****/ + char *authentication_info, + /* Authentication-Info header */ + algorithm[65], /* Algorithm from WWW-Authenticate */ + nextnonce[HTTP_MAX_VALUE], + /* Next nonce value from Authentication-Info */ + opaque[HTTP_MAX_VALUE], + /* Opaque value from WWW-Authenticate */ + realm[HTTP_MAX_VALUE]; + /* Realm from WWW-Authenticate */ }; # endif /* !_HTTP_NO_PRIVATE */ @@ -382,7 +392,7 @@ extern const char *_cups_hstrerror(int error); * Some OS's don't have getifaddrs() and freeifaddrs()... */ -# if !defined(WIN32) && !defined(HAVE_GETIFADDRS) +# if !defined(_WIN32) && !defined(HAVE_GETIFADDRS) # ifdef ifa_dstaddr # undef ifa_dstaddr # endif /* ifa_dstaddr */ @@ -417,7 +427,7 @@ extern int _cups_getifaddrs(struct ifaddrs **addrs); # define getifaddrs _cups_getifaddrs extern void _cups_freeifaddrs(struct ifaddrs *addrs); # define freeifaddrs _cups_freeifaddrs -# endif /* !WIN32 && !HAVE_GETIFADDRS */ +# endif /* !_WIN32 && !HAVE_GETIFADDRS */ /* @@ -437,12 +447,13 @@ extern const char *_httpResolveURI(const char *uri, char *resolved_uri, size_t resolved_size, int options, int (*cb)(void *context), void *context); +extern int _httpSetDigestAuthString(http_t *http, const char *nonce, const char *method, const char *resource); extern const char *_httpStatus(cups_lang_t *lang, http_status_t status); extern void _httpTLSInitialize(void); extern size_t _httpTLSPending(http_t *http); extern int _httpTLSRead(http_t *http, char *buf, int len); extern int _httpTLSSetCredentials(http_t *http); -extern void _httpTLSSetOptions(int options); +extern void _httpTLSSetOptions(int options, int min_version, int max_version); extern int _httpTLSStart(http_t *http); extern void _httpTLSStop(http_t *http); extern int _httpTLSWrite(http_t *http, const char *buf, int len); diff --git a/cups/http-support.c b/cups/http-support.c index 76dbb7db..767fbf68 100644 --- a/cups/http-support.c +++ b/cups/http-support.c @@ -1,7 +1,7 @@ /* * HTTP support routines for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -20,13 +20,13 @@ #include "cups-private.h" #ifdef HAVE_DNSSD # include <dns_sd.h> -# ifdef WIN32 +# ifdef _WIN32 # include <io.h> # elif defined(HAVE_POLL) # include <poll.h> # else # include <sys/select.h> -# endif /* WIN32 */ +# endif /* _WIN32 */ #elif defined(HAVE_AVAHI) # include <avahi-client/client.h> # include <avahi-client/lookup.h> @@ -502,7 +502,6 @@ httpAssembleUUID(const char *server, /* I - Server name */ 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 */ @@ -517,9 +516,7 @@ httpAssembleUUID(const char *server, /* I - Server name */ port, name ? name : server, number, (unsigned)CUPS_RAND() & 0xffff, (unsigned)CUPS_RAND() & 0xffff); - _cupsMD5Init(&md5state); - _cupsMD5Append(&md5state, (unsigned char *)data, (int)strlen(data)); - _cupsMD5Finish(&md5state, md5sum); + cupsHashData("md5", (unsigned char *)data, strlen(data), md5sum, sizeof(md5sum)); /* * Generate the UUID from the MD5... @@ -1035,7 +1032,7 @@ httpSeparateURI( *ptr = '\0'; - if (*uri != ':') + if (*uri != ':' || *scheme == '.' || !*scheme) { *scheme = '\0'; return (HTTP_URI_STATUS_BAD_SCHEME); @@ -1306,6 +1303,152 @@ httpSeparateURI( /* + * '_httpSetDigestAuthString()' - Calculate a Digest authentication response + * using the appropriate RFC 2068/2617/7616 + * algorithm. + */ + +int /* O - 1 on success, 0 on failure */ +_httpSetDigestAuthString( + http_t *http, /* I - HTTP connection */ + const char *nonce, /* I - Nonce value */ + const char *method, /* I - HTTP method */ + const char *resource) /* I - HTTP resource path */ +{ + char kd[65], /* Final MD5/SHA-256 digest */ + ha1[65], /* Hash of username:realm:password */ + ha2[65], /* Hash of method:request-uri */ + username[HTTP_MAX_VALUE], + /* username:password */ + *password, /* Pointer to password */ + temp[1024], /* Temporary string */ + digest[1024]; /* Digest auth data */ + unsigned char hash[32]; /* Hash buffer */ + size_t hashsize; /* Size of hash */ + + + DEBUG_printf(("2_httpSetDigestAuthString(http=%p, nonce=\"%s\", method=\"%s\", resource=\"%s\")", http, nonce, method, resource)); + + if (nonce && *nonce && strcmp(nonce, http->nonce)) + { + strlcpy(http->nonce, nonce, sizeof(http->nonce)); + + if (nonce == http->nextnonce) + http->nextnonce[0] = '\0'; + + http->nonce_count = 1; + } + else + http->nonce_count ++; + + strlcpy(username, http->userpass, sizeof(username)); + if ((password = strchr(username, ':')) != NULL) + *password++ = '\0'; + else + return (0); + + if (http->algorithm[0]) + { + /* + * Follow RFC 2617/7616... + */ + + int i; /* Looping var */ + char cnonce[65]; /* cnonce value */ + const char *hashalg; /* Hashing algorithm */ + + for (i = 0; i < 64; i ++) + cnonce[i] = "0123456789ABCDEF"[CUPS_RAND() & 15]; + cnonce[64] = '\0'; + + if (!_cups_strcasecmp(http->algorithm, "MD5")) + { + /* + * RFC 2617 Digest with MD5 + */ + + hashalg = "md5"; + } + else if (!_cups_strcasecmp(http->algorithm, "SHA-256")) + { + /* + * RFC 7616 Digest with SHA-256 + */ + + hashalg = "sha2-256"; + } + else + { + /* + * Some other algorithm we don't support, skip this one... + */ + + return (0); + } + + /* + * Calculate digest value... + */ + + /* H(A1) = H(username:realm:password) */ + snprintf(temp, sizeof(temp), "%s:%s:%s", username, http->realm, password); + hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash)); + cupsHashString(hash, hashsize, ha1, sizeof(ha1)); + + /* H(A2) = H(method:uri) */ + snprintf(temp, sizeof(temp), "%s:%s", method, resource); + hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash)); + cupsHashString(hash, hashsize, ha2, sizeof(ha2)); + + /* KD = H(H(A1):nonce:nc:cnonce:qop:H(A2)) */ + snprintf(temp, sizeof(temp), "%s:%s:%08x:%s:%s:%s", ha1, http->nonce, http->nonce_count, cnonce, "auth", ha2); + hashsize = (size_t)cupsHashData(hashalg, (unsigned char *)temp, strlen(temp), hash, sizeof(hash)); + cupsHashString(hash, hashsize, kd, sizeof(kd)); + + /* + * Pass the RFC 2617/7616 WWW-Authenticate header... + */ + + if (http->opaque[0]) + snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", algorithm=%s, qop=auth, opaque=\"%s\", cnonce=\"%s\", nc=%08x, uri=\"%s\", response=\"%s\"", cupsUser(), http->realm, http->nonce, http->algorithm, http->opaque, cnonce, http->nonce_count, resource, kd); + else + snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", algorithm=%s, qop=auth, cnonce=\"%s\", nc=%08x, uri=\"%s\", response=\"%s\"", username, http->realm, http->nonce, http->algorithm, cnonce, http->nonce_count, resource, kd); + } + else + { + /* + * Use old RFC 2069 Digest method... + */ + + /* H(A1) = H(username:realm:password) */ + snprintf(temp, sizeof(temp), "%s:%s:%s", username, http->realm, password); + hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash)); + cupsHashString(hash, hashsize, ha1, sizeof(ha1)); + + /* H(A2) = H(method:uri) */ + snprintf(temp, sizeof(temp), "%s:%s", method, resource); + hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash)); + cupsHashString(hash, hashsize, ha2, sizeof(ha2)); + + /* KD = H(H(A1):nonce:H(A2)) */ + snprintf(temp, sizeof(temp), "%s:%s:%s", ha1, http->nonce, ha2); + hashsize = (size_t)cupsHashData("md5", (unsigned char *)temp, strlen(temp), hash, sizeof(hash)); + cupsHashString(hash, hashsize, kd, sizeof(kd)); + + /* + * Pass the old RFC 2069 WWW-Authenticate header... + */ + + snprintf(digest, sizeof(digest), "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"", username, http->realm, http->nonce, resource, kd); + } + + httpSetAuthString(http, "Digest", digest); + + return (1); +} + + +/* * 'httpStateString()' - Return the string describing a HTTP state value. * * @since CUPS 2.0/OS 10.10@ @@ -1360,6 +1503,9 @@ _httpStatus(cups_lang_t *lang, /* I - Language */ case HTTP_STATUS_MOVED_PERMANENTLY : s = _("Moved Permanently"); break; + case HTTP_STATUS_FOUND : + s = _("Found"); + break; case HTTP_STATUS_SEE_OTHER : s = _("See Other"); break; @@ -1622,9 +1768,6 @@ _httpResolveURI( _http_uribuf_t uribuf; /* URI buffer */ int offline = 0; /* offline-report state set? */ # ifdef HAVE_DNSSD -# ifdef WIN32 -# pragma comment(lib, "dnssd.lib") -# endif /* WIN32 */ DNSServiceRef ref, /* DNS-SD master service reference */ domainref = NULL,/* DNS-SD service reference for domain */ ippref = NULL, /* DNS-SD service reference for network IPP */ @@ -1753,11 +1896,11 @@ _httpResolveURI( FD_ZERO(&input_set); FD_SET(DNSServiceRefSockFD(ref), &input_set); -# ifdef WIN32 +# ifdef _WIN32 stimeout.tv_sec = (long)timeout; # else stimeout.tv_sec = timeout; -# endif /* WIN32 */ +# endif /* _WIN32 */ stimeout.tv_usec = 0; fds = select(DNSServiceRefSockFD(ref)+1, &input_set, NULL, NULL, diff --git a/cups/http.c b/cups/http.c index 61b88c9d..5c14ef68 100644 --- a/cups/http.c +++ b/cups/http.c @@ -1,7 +1,7 @@ /* * HTTP routines for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * This file contains Kerberos support code, copyright 2006 by @@ -23,22 +23,26 @@ #include "cups-private.h" #include <fcntl.h> #include <math.h> -#ifdef WIN32 +#ifdef _WIN32 # include <tchar.h> #else # include <signal.h> # include <sys/time.h> # include <sys/resource.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ #ifdef HAVE_POLL # include <poll.h> #endif /* HAVE_POLL */ +# ifdef HAVE_LIBZ +# include <zlib.h> +# endif /* HAVE_LIBZ */ /* * Local functions... */ +static void http_add_field(http_t *http, http_field_t field, const char *value, int append); #ifdef HAVE_LIBZ static void http_content_coding_finish(http_t *http); static void http_content_coding_start(http_t *http, @@ -105,7 +109,8 @@ static const char * const http_fields[] = "WWW-Authenticate", "Accept-Encoding", "Allow", - "Server" + "Server", + "Authentication-Info" }; @@ -325,6 +330,12 @@ httpClearFields(http_t *http) /* I - HTTP connection */ http->server = NULL; } + if (http->authentication_info) + { + _cupsStrFree(http->authentication_info); + http->authentication_info = NULL; + } + http->expect = (http_status_t)0; } } @@ -969,11 +980,14 @@ httpGetField(http_t *http, /* I - HTTP connection */ case HTTP_FIELD_SERVER : return (http->server); + case HTTP_FIELD_AUTHENTICATION_INFO : + return (http->authentication_info); + case HTTP_FIELD_AUTHORIZATION : if (http->field_authorization) { /* - * Special case for WWW-Authenticate: as its contents can be + * Special case for Authorization: as its contents can be * longer than HTTP_MAX_VALUE... */ @@ -1183,11 +1197,11 @@ httpGets(char *line, /* I - Line to read into */ * Pre-load the buffer as needed... */ -#ifdef WIN32 +#ifdef _WIN32 WSASetLastError(0); #else errno = 0; -#endif /* WIN32 */ +#endif /* _WIN32 */ while (http->used == 0) { @@ -1201,11 +1215,11 @@ httpGets(char *line, /* I - Line to read into */ continue; DEBUG_puts("3httpGets: Timed out!"); -#ifdef WIN32 +#ifdef _WIN32 http->error = WSAETIMEDOUT; #else http->error = ETIMEDOUT; -#endif /* WIN32 */ +#endif /* _WIN32 */ return (NULL); } @@ -1219,7 +1233,7 @@ httpGets(char *line, /* I - Line to read into */ * Nope, can't get a line this time... */ -#ifdef WIN32 +#ifdef _WIN32 DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError())); if (WSAGetLastError() == WSAEINTR) @@ -1256,7 +1270,7 @@ httpGets(char *line, /* I - Line to read into */ http->error = errno; continue; } -#endif /* WIN32 */ +#endif /* _WIN32 */ return (NULL); } @@ -1523,9 +1537,9 @@ void httpInitialize(void) { static int initialized = 0; /* Have we been called before? */ -#ifdef WIN32 +#ifdef _WIN32 WSADATA winsockdata; /* WinSock data */ -#endif /* WIN32 */ +#endif /* _WIN32 */ _cupsGlobalLock(); @@ -1535,7 +1549,7 @@ httpInitialize(void) return; } -#ifdef WIN32 +#ifdef _WIN32 WSAStartup(MAKEWORD(2,2), &winsockdata); #elif !defined(SO_NOSIGPIPE) @@ -1557,7 +1571,7 @@ httpInitialize(void) # else signal(SIGPIPE, SIG_IGN); # endif /* !SO_NOSIGPIPE */ -#endif /* WIN32 */ +#endif /* _WIN32 */ # ifdef HAVE_SSL _httpTLSInitialize(); @@ -1713,7 +1727,7 @@ httpPeek(http_t *http, /* I - HTTP connection */ #ifdef HAVE_LIBZ if (http->used == 0 && (http->coding == _HTTP_CODING_IDENTITY || - (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in == 0))) + (http->coding >= _HTTP_CODING_GUNZIP && ((z_stream *)http->stream)->avail_in == 0))) #else if (http->used == 0) #endif /* HAVE_LIBZ */ @@ -1762,16 +1776,16 @@ httpPeek(http_t *http, /* I - HTTP connection */ int zerr; /* Decompressor error */ z_stream stream; /* Copy of decompressor stream */ - if (http->used > 0 && http->stream.avail_in < HTTP_MAX_BUFFER) + if (http->used > 0 && ((z_stream *)http->stream)->avail_in < HTTP_MAX_BUFFER) { - size_t buflen = buflen = HTTP_MAX_BUFFER - http->stream.avail_in; + size_t buflen = buflen = HTTP_MAX_BUFFER - ((z_stream *)http->stream)->avail_in; /* Number of bytes to copy */ - if (http->stream.avail_in > 0 && - http->stream.next_in > http->sbuffer) - memmove(http->sbuffer, http->stream.next_in, http->stream.avail_in); + if (((z_stream *)http->stream)->avail_in > 0 && + ((z_stream *)http->stream)->next_in > http->sbuffer) + memmove(http->sbuffer, ((z_stream *)http->stream)->next_in, ((z_stream *)http->stream)->avail_in); - http->stream.next_in = http->sbuffer; + ((z_stream *)http->stream)->next_in = http->sbuffer; if (buflen > (size_t)http->data_remaining) buflen = (size_t)http->data_remaining; @@ -1782,8 +1796,8 @@ httpPeek(http_t *http, /* I - HTTP connection */ DEBUG_printf(("1httpPeek: Copying %d more bytes of data into " "decompression buffer.", (int)buflen)); - memcpy(http->sbuffer + http->stream.avail_in, http->buffer, buflen); - http->stream.avail_in += buflen; + memcpy(http->sbuffer + ((z_stream *)http->stream)->avail_in, http->buffer, buflen); + ((z_stream *)http->stream)->avail_in += buflen; http->used -= (int)buflen; http->data_remaining -= (off_t)buflen; @@ -1792,9 +1806,9 @@ httpPeek(http_t *http, /* I - HTTP connection */ } DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length, - (int)http->stream.avail_in)); + (int)((z_stream *)http->stream)->avail_in)); - if (inflateCopy(&stream, &(http->stream)) != Z_OK) + if (inflateCopy(&stream, (z_stream *)http->stream) != Z_OK) { DEBUG_puts("2httpPeek: Unable to copy decompressor stream."); http->error = ENOMEM; @@ -1811,14 +1825,14 @@ httpPeek(http_t *http, /* I - HTTP connection */ { DEBUG_printf(("2httpPeek: zerr=%d", zerr)); #ifdef DEBUG - http_debug_hex("2httpPeek", (char *)http->sbuffer, (int)http->stream.avail_in); + http_debug_hex("2httpPeek", (char *)http->sbuffer, (int)((z_stream *)http->stream)->avail_in); #endif /* DEBUG */ http->error = EIO; return (-1); } - bytes = (ssize_t)(length - http->stream.avail_out); + bytes = (ssize_t)(length - ((z_stream *)http->stream)->avail_out); # else DEBUG_puts("2httpPeek: No inflateCopy on this platform, httpPeek does not " @@ -1845,7 +1859,7 @@ httpPeek(http_t *http, /* I - HTTP connection */ if (bytes < 0) { -#ifdef WIN32 +#ifdef _WIN32 if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK) bytes = 0; else @@ -1855,7 +1869,7 @@ httpPeek(http_t *http, /* I - HTTP connection */ bytes = 0; else http->error = errno; -#endif /* WIN32 */ +#endif /* _WIN32 */ } else if (bytes == 0) { @@ -1985,31 +1999,31 @@ httpRead2(http_t *http, /* I - HTTP connection */ { do { - if (http->stream.avail_in > 0) + if (((z_stream *)http->stream)->avail_in > 0) { int zerr; /* Decompressor error */ DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d", - (int)http->stream.avail_in, (int)length)); + (int)((z_stream *)http->stream)->avail_in, (int)length)); - http->stream.next_out = (Bytef *)buffer; - http->stream.avail_out = (uInt)length; + ((z_stream *)http->stream)->next_out = (Bytef *)buffer; + ((z_stream *)http->stream)->avail_out = (uInt)length; - if ((zerr = inflate(&(http->stream), Z_SYNC_FLUSH)) < Z_OK) + if ((zerr = inflate((z_stream *)http->stream, Z_SYNC_FLUSH)) < Z_OK) { DEBUG_printf(("2httpRead2: zerr=%d", zerr)); #ifdef DEBUG - http_debug_hex("2httpRead2", (char *)http->sbuffer, (int)http->stream.avail_in); + http_debug_hex("2httpRead2", (char *)http->sbuffer, (int)((z_stream *)http->stream)->avail_in); #endif /* DEBUG */ http->error = EIO; return (-1); } - bytes = (ssize_t)(length - http->stream.avail_out); + bytes = (ssize_t)(length - ((z_stream *)http->stream)->avail_out); DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d", - http->stream.avail_in, http->stream.avail_out, + ((z_stream *)http->stream)->avail_in, ((z_stream *)http->stream)->avail_out, (int)bytes)); } else @@ -2017,16 +2031,16 @@ httpRead2(http_t *http, /* I - HTTP connection */ if (bytes == 0) { - ssize_t buflen = HTTP_MAX_BUFFER - (ssize_t)http->stream.avail_in; + ssize_t buflen = HTTP_MAX_BUFFER - (ssize_t)((z_stream *)http->stream)->avail_in; /* Additional bytes for buffer */ if (buflen > 0) { - if (http->stream.avail_in > 0 && - http->stream.next_in > http->sbuffer) - memmove(http->sbuffer, http->stream.next_in, http->stream.avail_in); + if (((z_stream *)http->stream)->avail_in > 0 && + ((z_stream *)http->stream)->next_in > http->sbuffer) + memmove(http->sbuffer, ((z_stream *)http->stream)->next_in, ((z_stream *)http->stream)->avail_in); - http->stream.next_in = http->sbuffer; + ((z_stream *)http->stream)->next_in = http->sbuffer; DEBUG_printf(("1httpRead2: Reading up to %d more bytes of data into " "decompression buffer.", (int)buflen)); @@ -2036,10 +2050,10 @@ httpRead2(http_t *http, /* I - HTTP connection */ if (buflen > http->data_remaining) buflen = (ssize_t)http->data_remaining; - bytes = http_read_buffered(http, (char *)http->sbuffer + http->stream.avail_in, (size_t)buflen); + bytes = http_read_buffered(http, (char *)http->sbuffer + ((z_stream *)http->stream)->avail_in, (size_t)buflen); } else if (http->data_encoding == HTTP_ENCODING_CHUNKED) - bytes = http_read_chunk(http, (char *)http->sbuffer + http->stream.avail_in, (size_t)buflen); + bytes = http_read_chunk(http, (char *)http->sbuffer + ((z_stream *)http->stream)->avail_in, (size_t)buflen); else bytes = 0; @@ -2052,7 +2066,7 @@ httpRead2(http_t *http, /* I - HTTP connection */ "decompression buffer.", CUPS_LLCAST bytes)); http->data_remaining -= bytes; - http->stream.avail_in += (uInt)bytes; + ((z_stream *)http->stream)->avail_in += (uInt)bytes; if (http->data_remaining <= 0 && http->data_encoding == HTTP_ENCODING_CHUNKED) @@ -2131,7 +2145,7 @@ httpRead2(http_t *http, /* I - HTTP connection */ if ( #ifdef HAVE_LIBZ (http->coding == _HTTP_CODING_IDENTITY || - (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in == 0)) && + (http->coding >= _HTTP_CODING_GUNZIP && ((z_stream *)http->stream)->avail_in == 0)) && #endif /* HAVE_LIBZ */ ((http->data_remaining <= 0 && http->data_encoding == HTTP_ENCODING_LENGTH) || @@ -2416,11 +2430,11 @@ httpReconnect2(http_t *http, /* I - HTTP connection */ * Unable to connect... */ -#ifdef WIN32 +#ifdef _WIN32 http->error = WSAGetLastError(); #else http->error = errno; -#endif /* WIN32 */ +#endif /* _WIN32 */ http->status = HTTP_STATUS_ERROR; DEBUG_printf(("1httpReconnect2: httpAddrConnect failed: %s", @@ -2659,105 +2673,7 @@ httpSetField(http_t *http, /* I - HTTP connection */ value == NULL) return; - switch (field) - { - case HTTP_FIELD_ACCEPT_ENCODING : - if (http->accept_encoding) - _cupsStrFree(http->accept_encoding); - - http->accept_encoding = _cupsStrAlloc(value); - break; - - case HTTP_FIELD_ALLOW : - if (http->allow) - _cupsStrFree(http->allow); - - http->allow = _cupsStrAlloc(value); - break; - - case HTTP_FIELD_SERVER : - if (http->server) - _cupsStrFree(http->server); - - http->server = _cupsStrAlloc(value); - break; - - case HTTP_FIELD_WWW_AUTHENTICATE : - /* CUPS STR #4503 - don't override WWW-Authenticate for unknown auth schemes */ - if (http->fields[HTTP_FIELD_WWW_AUTHENTICATE][0] && - _cups_strncasecmp(value, "Basic ", 6) && - _cups_strncasecmp(value, "Digest ", 7) && - _cups_strncasecmp(value, "Negotiate ", 10)) - { - DEBUG_printf(("1httpSetField: Ignoring unknown auth scheme in \"%s\".", value)); - return; - } - - /* Fall through to copy */ - - default : - strlcpy(http->fields[field], value, HTTP_MAX_VALUE); - break; - } - - if (field == HTTP_FIELD_AUTHORIZATION) - { - /* - * Special case for Authorization: as its contents can be - * longer than HTTP_MAX_VALUE - */ - - if (http->field_authorization) - free(http->field_authorization); - - http->field_authorization = strdup(value); - } - else if (field == HTTP_FIELD_HOST) - { - /* - * Special-case for Host: as we don't want a trailing "." on the hostname and - * need to bracket IPv6 numeric addresses. - */ - - char *ptr = strchr(value, ':'); - - if (value[0] != '[' && ptr && strchr(ptr + 1, ':')) - { - /* - * Bracket IPv6 numeric addresses... - * - * This is slightly inefficient (basically copying twice), but is an edge - * case and not worth optimizing... - */ - - snprintf(http->fields[HTTP_FIELD_HOST], - sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value); - } - else - { - /* - * Check for a trailing dot on the hostname... - */ - - ptr = http->fields[HTTP_FIELD_HOST]; - - if (*ptr) - { - ptr += strlen(ptr) - 1; - - if (*ptr == '.') - *ptr = '\0'; - } - } - } -#ifdef HAVE_LIBZ - else if (field == HTTP_FIELD_CONTENT_ENCODING && - http->data_encoding != HTTP_ENCODING_FIELDS) - { - DEBUG_puts("1httpSetField: Calling http_content_coding_start."); - http_content_coding_start(http, value); - } -#endif /* HAVE_LIBZ */ + http_add_field(http, field, value, 0); } @@ -2855,11 +2771,11 @@ httpShutdown(http_t *http) /* I - HTTP connection */ _httpTLSStop(http); #endif /* HAVE_SSL */ -#ifdef WIN32 +#ifdef _WIN32 shutdown(http->fd, SD_RECEIVE); /* Microsoft-ism... */ #else shutdown(http->fd, SHUT_RD); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -3035,7 +2951,12 @@ _httpUpdate(http_t *http, /* I - HTTP connection */ httpSetCookie(http, value); } else if ((field = httpFieldValue(line)) != HTTP_FIELD_UNKNOWN) - httpSetField(http, field, value); + { + http_add_field(http, field, value, 1); + + if (field == HTTP_FIELD_AUTHENTICATION_INFO) + httpGetSubField2(http, HTTP_FIELD_AUTHENTICATION_INFO, "nextnonce", http->nextnonce, (int)sizeof(http->nextnonce)); + } #ifdef DEBUG else DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line)); @@ -3188,12 +3109,12 @@ _httpWait(http_t *http, /* I - HTTP connection */ DEBUG_printf(("6_httpWait: select() returned %d...", nfds)); } -# ifdef WIN32 +# ifdef _WIN32 while (nfds < 0 && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)); # else while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); -# endif /* WIN32 */ +# endif /* _WIN32 */ #endif /* HAVE_POLL */ DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds, @@ -3229,7 +3150,7 @@ httpWait(http_t *http, /* I - HTTP connection */ } #ifdef HAVE_LIBZ - if (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in > 0) + if (http->coding >= _HTTP_CODING_GUNZIP && ((z_stream *)http->stream)->avail_in > 0) { DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready."); return (1); @@ -3325,17 +3246,17 @@ httpWrite2(http_t *http, /* I - HTTP connection */ size_t slen; /* Bytes to write */ ssize_t sret; /* Bytes written */ - http->stream.next_in = (Bytef *)buffer; - http->stream.avail_in = (uInt)length; + ((z_stream *)http->stream)->next_in = (Bytef *)buffer; + ((z_stream *)http->stream)->avail_in = (uInt)length; - while (deflate(&(http->stream), Z_NO_FLUSH) == Z_OK) + while (deflate((z_stream *)http->stream, Z_NO_FLUSH) == Z_OK) { - DEBUG_printf(("1httpWrite2: avail_out=%d", http->stream.avail_out)); + DEBUG_printf(("1httpWrite2: avail_out=%d", ((z_stream *)http->stream)->avail_out)); - if (http->stream.avail_out > 0) + if (((z_stream *)http->stream)->avail_out > 0) continue; - slen = _HTTP_MAX_SBUFFER - http->stream.avail_out; + slen = _HTTP_MAX_SBUFFER - ((z_stream *)http->stream)->avail_out; DEBUG_printf(("1httpWrite2: Writing intermediate chunk, len=%d", (int)slen)); @@ -3352,8 +3273,8 @@ httpWrite2(http_t *http, /* I - HTTP connection */ return (-1); } - http->stream.next_out = (Bytef *)http->sbuffer; - http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER; + ((z_stream *)http->stream)->next_out = (Bytef *)http->sbuffer; + ((z_stream *)http->stream)->avail_out = (uInt)_HTTP_MAX_SBUFFER; } bytes = (ssize_t)length; @@ -3689,6 +3610,125 @@ httpWriteResponse(http_t *http, /* I - HTTP connection */ } +/* + * 'http_add_field()' - Add a value for a HTTP field, appending if needed. + */ + +static void +http_add_field(http_t *http, /* I - HTTP connection */ + http_field_t field, /* I - HTTP field */ + const char *value, /* I - Value string */ + int append) /* I - Append value? */ +{ + char newvalue[1024]; /* New value string */ + const char *oldvalue; /* Old field value */ + + + + /* + * Optionally append the new value to the existing one... + */ + + if (append && field != HTTP_FIELD_ACCEPT_ENCODING && field != HTTP_FIELD_ACCEPT_LANGUAGE && field != HTTP_FIELD_ACCEPT_RANGES && field != HTTP_FIELD_ALLOW && field != HTTP_FIELD_LINK && field != HTTP_FIELD_TRANSFER_ENCODING && field != HTTP_FIELD_UPGRADE && field != HTTP_FIELD_WWW_AUTHENTICATE) + append = 0; + + if (field == HTTP_FIELD_HOST) + { + /* + * Special-case for Host: as we don't want a trailing "." on the hostname and + * need to bracket IPv6 numeric addresses. + */ + + char *ptr = strchr(value, ':'); + + if (value[0] != '[' && ptr && strchr(ptr + 1, ':')) + { + /* + * Bracket IPv6 numeric addresses... + */ + + snprintf(newvalue, sizeof(newvalue), "[%s]", value); + value = newvalue; + } + else if (*value && value[strlen(value) - 1] == '.') + { + /* + * Strip the trailing dot on the hostname... + */ + + strlcpy(newvalue, value, sizeof(newvalue)); + newvalue[strlen(newvalue) - 1] = '\0'; + value = newvalue; + } + } + else if (append && *value && (oldvalue = httpGetField(http, field)) != NULL && *oldvalue) + { + snprintf(newvalue, sizeof(newvalue), "%s, %s", oldvalue, value); + value = newvalue; + } + + /* + * Save the new value... + */ + + switch (field) + { + case HTTP_FIELD_ACCEPT_ENCODING : + if (http->accept_encoding) + _cupsStrFree(http->accept_encoding); + + http->accept_encoding = _cupsStrAlloc(value); + break; + + case HTTP_FIELD_ALLOW : + if (http->allow) + _cupsStrFree(http->allow); + + http->allow = _cupsStrAlloc(value); + break; + + case HTTP_FIELD_SERVER : + if (http->server) + _cupsStrFree(http->server); + + http->server = _cupsStrAlloc(value); + break; + + case HTTP_FIELD_AUTHENTICATION_INFO : + if (http->authentication_info) + _cupsStrFree(http->authentication_info); + + http->authentication_info = _cupsStrAlloc(value); + break; + + default : + strlcpy(http->fields[field], value, HTTP_MAX_VALUE); + break; + } + + if (field == HTTP_FIELD_AUTHORIZATION) + { + /* + * Special case for Authorization: as its contents can be + * longer than HTTP_MAX_VALUE + */ + + if (http->field_authorization) + free(http->field_authorization); + + http->field_authorization = strdup(value); + } +#ifdef HAVE_LIBZ + else if (field == HTTP_FIELD_CONTENT_ENCODING && + http->data_encoding != HTTP_ENCODING_FIELDS) + { + DEBUG_puts("1http_add_field: Calling http_content_coding_start."); + http_content_coding_start(http, value); + } +#endif /* HAVE_LIBZ */ +} + + #ifdef HAVE_LIBZ /* * 'http_content_coding_finish()' - Finish doing any content encoding. @@ -3710,13 +3750,13 @@ http_content_coding_finish( { case _HTTP_CODING_DEFLATE : case _HTTP_CODING_GZIP : - http->stream.next_in = dummy; - http->stream.avail_in = 0; + ((z_stream *)http->stream)->next_in = dummy; + ((z_stream *)http->stream)->avail_in = 0; do { - zerr = deflate(&(http->stream), Z_FINISH); - bytes = _HTTP_MAX_SBUFFER - http->stream.avail_out; + zerr = deflate((z_stream *)http->stream, Z_FINISH); + bytes = _HTTP_MAX_SBUFFER - ((z_stream *)http->stream)->avail_out; if (bytes > 0) { @@ -3728,15 +3768,18 @@ http_content_coding_finish( http_write(http, (char *)http->sbuffer, bytes); } - http->stream.next_out = (Bytef *)http->sbuffer; - http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER; + ((z_stream *)http->stream)->next_out = (Bytef *)http->sbuffer; + ((z_stream *)http->stream)->avail_out = (uInt)_HTTP_MAX_SBUFFER; } while (zerr == Z_OK); - deflateEnd(&(http->stream)); + deflateEnd((z_stream *)http->stream); free(http->sbuffer); + free(http->stream); + http->sbuffer = NULL; + http->stream = NULL; if (http->wused) httpFlushWrite(http); @@ -3744,9 +3787,13 @@ http_content_coding_finish( case _HTTP_CODING_INFLATE : case _HTTP_CODING_GUNZIP : - inflateEnd(&(http->stream)); + inflateEnd((z_stream *)http->stream); + free(http->sbuffer); + free(http->stream); + http->sbuffer = NULL; + http->stream = NULL; break; default : @@ -3816,8 +3863,6 @@ http_content_coding_start( return; } - memset(&(http->stream), 0, sizeof(http->stream)); - switch (coding) { case _HTTP_CODING_DEFLATE : @@ -3838,18 +3883,30 @@ http_content_coding_start( * documentation. */ - if ((zerr = deflateInit2(&(http->stream), Z_DEFAULT_COMPRESSION, - Z_DEFLATED, - coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7, - Z_DEFAULT_STRATEGY)) < Z_OK) + if ((http->stream = calloc(1, sizeof(z_stream))) == NULL) + { + free(http->sbuffer); + + http->sbuffer = NULL; + http->status = HTTP_STATUS_ERROR; + http->error = errno; + return; + } + + if ((zerr = deflateInit2((z_stream *)http->stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7, Z_DEFAULT_STRATEGY)) < Z_OK) { - http->status = HTTP_STATUS_ERROR; - http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL; + free(http->sbuffer); + free(http->stream); + + http->sbuffer = NULL; + http->stream = NULL; + http->status = HTTP_STATUS_ERROR; + http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL; return; } - http->stream.next_out = (Bytef *)http->sbuffer; - http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER; + ((z_stream *)http->stream)->next_out = (Bytef *)http->sbuffer; + ((z_stream *)http->stream)->avail_out = (uInt)_HTTP_MAX_SBUFFER; break; case _HTTP_CODING_INFLATE : @@ -3866,19 +3923,30 @@ http_content_coding_start( * -15 is raw inflate, 31 is gunzip, per ZLIB documentation. */ - if ((zerr = inflateInit2(&(http->stream), - coding == _HTTP_CODING_INFLATE ? -15 : 31)) - < Z_OK) + if ((http->stream = calloc(1, sizeof(z_stream))) == NULL) + { + free(http->sbuffer); + + http->sbuffer = NULL; + http->status = HTTP_STATUS_ERROR; + http->error = errno; + return; + } + + if ((zerr = inflateInit2((z_stream *)http->stream, coding == _HTTP_CODING_INFLATE ? -15 : 31)) < Z_OK) { free(http->sbuffer); + free(http->stream); + http->sbuffer = NULL; + http->stream = NULL; http->status = HTTP_STATUS_ERROR; http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL; return; } - http->stream.avail_in = 0; - http->stream.next_in = http->sbuffer; + ((z_stream *)http->stream)->avail_in = 0; + ((z_stream *)http->stream)->next_in = http->sbuffer; break; default : @@ -3944,7 +4012,7 @@ http_create( if ((http = calloc(sizeof(http_t), 1)) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); - httpAddrFreeList(addrlist); + httpAddrFreeList(myaddrlist); return (NULL); } @@ -4056,7 +4124,7 @@ http_read(http_t *http, /* I - HTTP connection */ DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length)); - if (!http->blocking) + if (!http->blocking || http->timeout_value > 0.0) { while (!httpWait(http, http->wait_value)) { @@ -4081,7 +4149,7 @@ http_read(http_t *http, /* I - HTTP connection */ if (bytes < 0) { -#ifdef WIN32 +#ifdef _WIN32 if (WSAGetLastError() != WSAEINTR) { http->error = WSAGetLastError(); @@ -4117,7 +4185,7 @@ http_read(http_t *http, /* I - HTTP connection */ http->error = errno; return (-1); } -#endif /* WIN32 */ +#endif /* _WIN32 */ } } while (bytes < 0); @@ -4131,7 +4199,7 @@ http_read(http_t *http, /* I - HTTP connection */ if (bytes < 0) { -#ifdef WIN32 +#ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) bytes = 0; else @@ -4141,7 +4209,7 @@ http_read(http_t *http, /* I - HTTP connection */ bytes = 0; else http->error = errno; -#endif /* WIN32 */ +#endif /* _WIN32 */ } else if (bytes == 0) { @@ -4505,7 +4573,7 @@ static void http_set_timeout(int fd, /* I - File descriptor */ double timeout) /* I - Timeout in seconds */ { -#ifdef WIN32 +#ifdef _WIN32 DWORD tv = (DWORD)(timeout * 1000); /* Timeout in milliseconds */ @@ -4520,7 +4588,7 @@ http_set_timeout(int fd, /* I - File descriptor */ setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv)); setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv)); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -4651,7 +4719,7 @@ http_write(http_t *http, /* I - HTTP connection */ { DEBUG_printf(("3http_write: About to write %d bytes.", (int)length)); - if (http->timeout_cb) + if (http->timeout_value > 0.0) { #ifdef HAVE_POLL struct pollfd pfd; /* Polled file descriptor */ @@ -4682,12 +4750,12 @@ http_write(http_t *http, /* I - HTTP connection */ nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout); } -# ifdef WIN32 +# ifdef _WIN32 while (nfds < 0 && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)); # else while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); -# endif /* WIN32 */ +# endif /* _WIN32 */ #endif /* HAVE_POLL */ if (nfds < 0) @@ -4695,13 +4763,13 @@ http_write(http_t *http, /* I - HTTP connection */ http->error = errno; return (-1); } - else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data)) + else if (nfds == 0 && (!http->timeout_cb || !(*http->timeout_cb)(http, http->timeout_data))) { -#ifdef WIN32 +#ifdef _WIN32 http->error = WSAEWOULDBLOCK; #else http->error = EWOULDBLOCK; -#endif /* WIN32 */ +#endif /* _WIN32 */ return (-1); } } @@ -4720,7 +4788,7 @@ http_write(http_t *http, /* I - HTTP connection */ if (bytes < 0) { -#ifdef WIN32 +#ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) continue; else if (WSAGetLastError() == WSAEWOULDBLOCK) @@ -4754,7 +4822,7 @@ http_write(http_t *http, /* I - HTTP connection */ http->error = errno; continue; } -#endif /* WIN32 */ +#endif /* _WIN32 */ DEBUG_printf(("3http_write: error writing data (%s).", strerror(http->error))); diff --git a/cups/http.h b/cups/http.h index c61a79ee..e94adae3 100644 --- a/cups/http.h +++ b/cups/http.h @@ -1,7 +1,7 @@ /* * Hyper-Text Transport Protocol definitions for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -25,7 +25,7 @@ # include <string.h> # include <time.h> # include <sys/types.h> -# ifdef WIN32 +# ifdef _WIN32 # ifndef __CUPS_SSIZE_T_DEFINED # define __CUPS_SSIZE_T_DEFINED /* Windows does not support the ssize_t type, so map it to off_t... */ @@ -54,7 +54,7 @@ typedef off_t ssize_t; /* @private@ */ # if defined(LOCAL_PEERCRED) && !defined(SO_PEERCRED) # define SO_PEERCRED LOCAL_PEERCRED # endif /* LOCAL_PEERCRED && !SO_PEERCRED */ -# endif /* WIN32 */ +# endif /* _WIN32 */ /* @@ -85,7 +85,7 @@ extern "C" { # define s6_addr32 _S6_un._S6_u32 # elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__APPLE__)|| defined(__DragonFly__) # define s6_addr32 __u6_addr.__u6_addr32 -# elif defined(WIN32) +# elif defined(_WIN32) /* * Windows only defines byte and 16-bit word members of the union and * requires special casing of all raw address code... @@ -181,6 +181,7 @@ typedef enum http_field_e /**** HTTP field names ****/ HTTP_FIELD_ACCEPT_ENCODING, /* Accepting-Encoding field @since CUPS 1.7/macOS 10.9@ */ HTTP_FIELD_ALLOW, /* Allow field @since CUPS 1.7/macOS 10.9@ */ HTTP_FIELD_SERVER, /* Server field @since CUPS 1.7/macOS 10.9@ */ + HTTP_FIELD_AUTHENTICATION_INFO, /* Authentication-Info field (@since CUPS 2.2.9) */ HTTP_FIELD_MAX /* Maximum field index */ } http_field_t; @@ -248,10 +249,11 @@ typedef enum http_status_e /**** HTTP status codes ****/ HTTP_STATUS_MULTIPLE_CHOICES = 300, /* Multiple files match request */ HTTP_STATUS_MOVED_PERMANENTLY, /* Document has moved permanently */ - HTTP_STATUS_MOVED_TEMPORARILY, /* Document has moved temporarily */ - HTTP_STATUS_SEE_OTHER, /* See this other link... */ + HTTP_STATUS_FOUND, /* Document was found at a different URI */ + HTTP_STATUS_SEE_OTHER, /* See this other link */ HTTP_STATUS_NOT_MODIFIED, /* File not modified */ HTTP_STATUS_USE_PROXY, /* Must use a proxy to access this URI */ + HTTP_STATUS_TEMPORARY_REDIRECT = 307, /* Temporary redirection */ HTTP_STATUS_BAD_REQUEST = 400, /* Bad request */ HTTP_STATUS_UNAUTHORIZED, /* Unauthorized to access host */ @@ -285,6 +287,8 @@ typedef enum http_status_e /**** HTTP status codes ****/ HTTP_STATUS_CUPS_PKI_ERROR, /* Error negotiating a secure connection @since CUPS 1.5/macOS 10.7@ */ HTTP_STATUS_CUPS_WEBIF_DISABLED /* Web interface is disabled @private@ */ +# define HTTP_STATUS_MOVED_TEMPORARILY HTTP_STATUS_FOUND /* Renamed in RFC 7231 */ + # ifndef _CUPS_NO_DEPRECATED /* Old names for this enumeration */ # define HTTP_ERROR HTTP_STATUS_ERROR @@ -476,8 +480,7 @@ extern int httpHead(http_t *http, const char *uri); extern void httpInitialize(void); extern int httpOptions(http_t *http, const char *uri); extern int httpPost(http_t *http, const char *uri); -extern int httpPrintf(http_t *http, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); +extern int httpPrintf(http_t *http, const char *format, ...) _CUPS_FORMAT(2, 3); extern int httpPut(http_t *http, const char *uri); extern int httpRead(http_t *http, char *buffer, int length) _CUPS_DEPRECATED_MSG("Use httpRead2 instead."); extern int httpReconnect(http_t *http) _CUPS_DEPRECATED_1_6_MSG("Use httpReconnect2 instead."); diff --git a/cups/ipp-support.c b/cups/ipp-support.c index 675e5f38..d1ad65c8 100644 --- a/cups/ipp-support.c +++ b/cups/ipp-support.c @@ -1,8 +1,8 @@ /* * Internet Printing Protocol support functions for CUPS. * - * Copyright 2007-2017 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -960,9 +960,12 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */ "feed-orientation-supported", "finishings", "finishings-col", + "finishings-col-database", "finishings-col-default", + "finishings-col-ready", "finishings-col-supported", "finishings-default", + "finishings-ready", "finishings-supported", "font-name-requested", "font-name-requested-default", @@ -1001,6 +1004,7 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */ "media-bottom-margin-supported", "media-col", "media-col-default", + "media-col-ready", "media-col-supported", "media-color-supported", "media-default", @@ -1015,6 +1019,7 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */ "media-left-margin-supported", "media-order-count-supported", "media-pre-printed-supported", + "media-ready", "media-recycled-supported", "media-right-margin-supported", "media-size-supported", @@ -1277,9 +1282,12 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */ "feed-orientation-supported", "finishings", "finishings-col", + "finishings-col-database", "finishings-col-default", + "finishings-col-ready", "finishings-col-supported", "finishings-default", + "finishings-ready", "finishings-supported", "font-name-requested", "font-name-requested-default", @@ -1383,6 +1391,7 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */ "media-bottom-margin-supported", "media-col", "media-col-default", + "media-col-ready", "media-col-supported", "media-color-supported", "media-default", @@ -1397,6 +1406,7 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */ "media-left-margin-supported", "media-order-count-supported", "media-pre-printed-supported", + "media-ready", "media-recycled-supported", "media-right-margin-supported", "media-size-supported", @@ -1582,10 +1592,12 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */ "job-page-limit", /* CUPS extension */ "job-password-encryption-supported", "job-password-supported", + "job-presets-supported", /* IPP Presets */ "job-quota-period", /* CUPS extension */ "job-resolvers-supported", "job-settable-attributes-supported", "job-spooling-supported", + "job-triggers-supported", /* IPP Presets */ "jpeg-k-octets-supported", /* CUPS extension */ "jpeg-x-dimension-supported", /* CUPS extension */ "jpeg-y-dimension-supported", /* CUPS extension */ @@ -1599,8 +1611,6 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */ "marker-message", /* CUPS extension */ "marker-names", /* CUPS extension */ "marker-types", /* CUPS extension */ - "media-col-ready", - "media-ready", "member-names", /* CUPS extension */ "member-uris", /* CUPS extension */ "multiple-destination-uris-supported",/* IPP FaxOut */ @@ -1623,6 +1633,8 @@ ippCreateRequestedArray(ipp_t *request) /* I - IPP request */ "printer-charge-info", "printer-charge-info-uri", "printer-commands", /* CUPS extension */ + "printer-config-change-date-time", + "printer-config-change-time", "printer-current-time", "printer-detailed-status-messages", "printer-device-id", @@ -1,8 +1,8 @@ /* * Internet Printing Protocol functions for CUPS. * - * Copyright 2007-2017 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -19,9 +19,9 @@ #include "cups-private.h" #include <regex.h> -#ifdef WIN32 +#ifdef _WIN32 # include <io.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ /* @@ -33,12 +33,8 @@ static ipp_attribute_t *ipp_add_attr(ipp_t *ipp, const char *name, int num_values); static void ipp_free_values(ipp_attribute_t *attr, int element, int count); -static char *ipp_get_code(const char *locale, char *buffer, - size_t bufsize) - __attribute__((nonnull(1,2))); -static char *ipp_lang_code(const char *locale, char *buffer, - size_t bufsize) - __attribute__((nonnull(1,2))); +static char *ipp_get_code(const char *locale, char *buffer, size_t bufsize) _CUPS_NONNULL((1, 2)); +static char *ipp_lang_code(const char *locale, char *buffer, size_t bufsize) _CUPS_NONNULL((1, 2)); static size_t ipp_length(ipp_t *ipp, int collection); static ssize_t ipp_read_http(http_t *http, ipp_uchar_t *buffer, size_t length); @@ -1483,6 +1479,7 @@ ippCopyAttribute( int quickcopy) /* I - 1 for a referenced copy, 0 for normal */ { int i; /* Looping var */ + ipp_tag_t srctag; /* Source value tag */ ipp_attribute_t *dstattr; /* Destination attribute */ _ipp_value_t *srcval, /* Source value */ *dstval; /* Destination value */ @@ -1501,9 +1498,10 @@ ippCopyAttribute( * Copy it... */ - quickcopy = quickcopy ? IPP_TAG_CUPS_CONST : 0; + quickcopy = (quickcopy && (srcattr->value_tag & IPP_TAG_CUPS_CONST)) ? IPP_TAG_CUPS_CONST : 0; + srctag = srcattr->value_tag & IPP_TAG_CUPS_MASK; - switch (srcattr->value_tag & ~IPP_TAG_CUPS_CONST) + switch (srctag) { case IPP_TAG_ZERO : dstattr = ippAddSeparator(dst); @@ -1516,139 +1514,70 @@ ippCopyAttribute( case IPP_TAG_NOTSETTABLE : case IPP_TAG_DELETEATTR : case IPP_TAG_ADMINDEFINE : - dstattr = ippAddOutOfBand(dst, srcattr->group_tag, srcattr->value_tag & ~IPP_TAG_CUPS_CONST, srcattr->name); + dstattr = ippAddOutOfBand(dst, srcattr->group_tag, srctag, srcattr->name); break; case IPP_TAG_INTEGER : case IPP_TAG_ENUM : - dstattr = ippAddIntegers(dst, srcattr->group_tag, srcattr->value_tag, - srcattr->name, srcattr->num_values, NULL); - if (!dstattr) - break; - - for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) - dstval->integer = srcval->integer; - break; - case IPP_TAG_BOOLEAN : - dstattr = ippAddBooleans(dst, srcattr->group_tag, srcattr->name, - srcattr->num_values, NULL); - if (!dstattr) - break; - - for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) - dstval->boolean = srcval->boolean; + case IPP_TAG_DATE : + case IPP_TAG_RESOLUTION : + case IPP_TAG_RANGE : + if ((dstattr = ipp_add_attr(dst, srcattr->name, srcattr->group_tag, srctag, srcattr->num_values)) != NULL) + memcpy(dstattr->values, srcattr->values, (size_t)srcattr->num_values * sizeof(_ipp_value_t)); break; case IPP_TAG_TEXT : case IPP_TAG_NAME : + case IPP_TAG_RESERVED_STRING : case IPP_TAG_KEYWORD : case IPP_TAG_URI : case IPP_TAG_URISCHEME : case IPP_TAG_CHARSET : case IPP_TAG_LANGUAGE : case IPP_TAG_MIMETYPE : - dstattr = ippAddStrings(dst, srcattr->group_tag, - (ipp_tag_t)(srcattr->value_tag | quickcopy), - srcattr->name, srcattr->num_values, NULL, NULL); - if (!dstattr) + if ((dstattr = ippAddStrings(dst, srcattr->group_tag, (ipp_tag_t)(srctag | quickcopy), srcattr->name, srcattr->num_values, NULL, NULL)) == NULL) break; if (quickcopy) { - for (i = srcattr->num_values, srcval = srcattr->values, - dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) - dstval->string.text = srcval->string.text; + /* + * Can safely quick-copy these string values... + */ + + memcpy(dstattr->values, srcattr->values, (size_t)srcattr->num_values * sizeof(_ipp_value_t)); } - else if (srcattr->value_tag & IPP_TAG_CUPS_CONST) - { - for (i = srcattr->num_values, srcval = srcattr->values, - dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) - dstval->string.text = _cupsStrAlloc(srcval->string.text); - } else { - for (i = srcattr->num_values, srcval = srcattr->values, - dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) - dstval->string.text = _cupsStrRetain(srcval->string.text); - } - break; - - case IPP_TAG_DATE : - if (srcattr->num_values != 1) - return (NULL); - - dstattr = ippAddDate(dst, srcattr->group_tag, srcattr->name, - srcattr->values[0].date); - break; - - case IPP_TAG_RESOLUTION : - dstattr = ippAddResolutions(dst, srcattr->group_tag, srcattr->name, - srcattr->num_values, IPP_RES_PER_INCH, - NULL, NULL); - if (!dstattr) - break; - - for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) - { - dstval->resolution.xres = srcval->resolution.xres; - dstval->resolution.yres = srcval->resolution.yres; - dstval->resolution.units = srcval->resolution.units; - } - break; - - case IPP_TAG_RANGE : - dstattr = ippAddRanges(dst, srcattr->group_tag, srcattr->name, - srcattr->num_values, NULL, NULL); - if (!dstattr) - break; + /* + * Otherwise do a normal reference counted copy... + */ - for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) - { - dstval->range.lower = srcval->range.lower; - dstval->range.upper = srcval->range.upper; + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++) + dstval->string.text = _cupsStrAlloc(srcval->string.text); } break; case IPP_TAG_TEXTLANG : case IPP_TAG_NAMELANG : - dstattr = ippAddStrings(dst, srcattr->group_tag, - (ipp_tag_t)(srcattr->value_tag | quickcopy), - srcattr->name, srcattr->num_values, NULL, NULL); - if (!dstattr) + if ((dstattr = ippAddStrings(dst, srcattr->group_tag, (ipp_tag_t)(srctag | quickcopy), srcattr->name, srcattr->num_values, NULL, NULL)) == NULL) break; if (quickcopy) { - for (i = srcattr->num_values, srcval = srcattr->values, - dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) - { - dstval->string.language = srcval->string.language; - dstval->string.text = srcval->string.text; - } + /* + * Can safely quick-copy these string values... + */ + + memcpy(dstattr->values, srcattr->values, (size_t)srcattr->num_values * sizeof(_ipp_value_t)); } else if (srcattr->value_tag & IPP_TAG_CUPS_CONST) { - for (i = srcattr->num_values, srcval = srcattr->values, - dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) + /* + * Otherwise do a normal reference counted copy... + */ + + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++) { if (srcval == srcattr->values) dstval->string.language = _cupsStrAlloc(srcval->string.language); @@ -1658,32 +1587,13 @@ ippCopyAttribute( dstval->string.text = _cupsStrAlloc(srcval->string.text); } } - else - { - for (i = srcattr->num_values, srcval = srcattr->values, - dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) - { - if (srcval == srcattr->values) - dstval->string.language = _cupsStrRetain(srcval->string.language); - else - dstval->string.language = dstattr->values[0].string.language; - - dstval->string.text = _cupsStrRetain(srcval->string.text); - } - } break; case IPP_TAG_BEGIN_COLLECTION : - dstattr = ippAddCollections(dst, srcattr->group_tag, srcattr->name, - srcattr->num_values, NULL); - if (!dstattr) + if ((dstattr = ippAddCollections(dst, srcattr->group_tag, srcattr->name, srcattr->num_values, NULL)) == NULL) break; - for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++) { dstval->collection = srcval->collection; srcval->collection->use ++; @@ -1692,15 +1602,10 @@ ippCopyAttribute( case IPP_TAG_STRING : default : - /* TODO: Implement quick copy for unknown/octetString values */ - dstattr = ippAddIntegers(dst, srcattr->group_tag, srcattr->value_tag, - srcattr->name, srcattr->num_values, NULL); - if (!dstattr) + if ((dstattr = ipp_add_attr(dst, srcattr->name, srcattr->group_tag, srctag, srcattr->num_values)) == NULL) break; - for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; - i > 0; - i --, srcval ++, dstval ++) + for (i = srcattr->num_values, srcval = srcattr->values, dstval = dstattr->values; i > 0; i --, srcval ++, dstval ++) { dstval->unknown.length = srcval->unknown.length; @@ -3089,6 +2994,13 @@ ippReadIO(void *src, /* I - Data source */ ipp->state = IPP_STATE_DATA; break; } + else if (tag == IPP_TAG_ZERO || (tag == IPP_TAG_OPERATION && ipp->curtag != IPP_TAG_ZERO)) + { + _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Invalid group tag."), 1); + DEBUG_printf(("1ippReadIO: bad tag 0x%02x.", tag)); + _cupsBufferRelease((char *)buffer); + return (IPP_STATE_ERROR); + } else if (tag < IPP_TAG_UNSUPPORTED_VALUE) { /* @@ -3386,7 +3298,10 @@ ippReadIO(void *src, /* I - Data source */ value->boolean = (char)buffer[0]; break; - case IPP_TAG_NOVALUE : + case IPP_TAG_UNSUPPORTED_VALUE : + case IPP_TAG_DEFAULT : + case IPP_TAG_UNKNOWN : + case IPP_TAG_NOVALUE : case IPP_TAG_NOTSETTABLE : case IPP_TAG_DELETEATTR : case IPP_TAG_ADMINDEFINE : @@ -3406,6 +3321,7 @@ ippReadIO(void *src, /* I - Data source */ case IPP_TAG_TEXT : case IPP_TAG_NAME : + case IPP_TAG_RESERVED_STRING : case IPP_TAG_KEYWORD : case IPP_TAG_URI : case IPP_TAG_URISCHEME : @@ -4306,17 +4222,21 @@ ippSetString(ipp_t *ipp, /* I - IPP message */ { char *temp; /* Temporary string */ _ipp_value_t *value; /* Current value */ + ipp_tag_t value_tag; /* Value tag */ /* * Range check input... */ + if (attr && *attr) + value_tag = (*attr)->value_tag & IPP_TAG_CUPS_MASK; + else + value_tag = IPP_TAG_ZERO; + if (!ipp || !attr || !*attr || - ((*attr)->value_tag != IPP_TAG_TEXTLANG && - (*attr)->value_tag != IPP_TAG_NAMELANG && - ((*attr)->value_tag < IPP_TAG_TEXT || - (*attr)->value_tag > IPP_TAG_MIMETYPE)) || + (value_tag < IPP_TAG_TEXT && value_tag != IPP_TAG_TEXTLANG && + value_tag != IPP_TAG_NAMELANG) || value_tag > IPP_TAG_MIMETYPE || element < 0 || element > (*attr)->num_values || !strvalue) return (0); @@ -4803,21 +4723,6 @@ ippValidateAttribute( ipp_attribute_t *colattr; /* Collection attribute */ regex_t re; /* Regular expression */ ipp_uchar_t *date; /* Current date value */ - static const char * const uri_status_strings[] = - { /* URI status strings */ - "URI too large", - "Bad arguments to function", - "Bad resource in URI", - "Bad port number in URI", - "Bad hostname/address in URI", - "Bad username in URI", - "Bad scheme in URI", - "Bad/empty URI", - "OK", - "Missing scheme in URI", - "Unknown scheme in URI", - "Missing resource in URI" - }; /* @@ -5092,16 +4997,23 @@ ippValidateAttribute( } else if (*ptr & 0x80) break; + else if ((*ptr < ' ' && *ptr != '\n' && *ptr != '\r' && *ptr != '\t') || *ptr == 0x7f) + break; } - if (*ptr) - { - ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, - _("\"%s\": Bad text value \"%s\" - bad UTF-8 " - "sequence (RFC 8011 section 5.1.2)."), attr->name, - attr->values[i].string.text); - return (0); - } + if (*ptr) + { + if (*ptr < ' ' || *ptr == 0x7f) + { + ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad text value \"%s\" - bad control character (PWG 5100.14 section 8.3)."), attr->name, attr->values[i].string.text); + return (0); + } + else + { + ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad text value \"%s\" - bad UTF-8 sequence (RFC 8011 section 5.1.2)."), attr->name, attr->values[i].string.text); + return (0); + } + } if ((ptr - attr->values[i].string.text) > (IPP_MAX_TEXT - 1)) { @@ -5150,16 +5062,23 @@ ippValidateAttribute( } else if (*ptr & 0x80) break; + else if (*ptr < ' ' || *ptr == 0x7f) + break; } if (*ptr) { - ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, - _("\"%s\": Bad name value \"%s\" - bad UTF-8 " - "sequence (RFC 8011 section 5.1.3)."), attr->name, - attr->values[i].string.text); - return (0); - } + if (*ptr < ' ' || *ptr == 0x7f) + { + ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad name value \"%s\" - bad control character (PWG 5100.14 section 8.1)."), attr->name, attr->values[i].string.text); + return (0); + } + else + { + ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad name value \"%s\" - bad UTF-8 sequence (RFC 8011 section 5.1.3)."), attr->name, attr->values[i].string.text); + return (0); + } + } if ((ptr - attr->values[i].string.text) > (IPP_MAX_NAME - 1)) { @@ -5214,12 +5133,7 @@ ippValidateAttribute( if (uri_status < HTTP_URI_STATUS_OK) { - ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, - _("\"%s\": Bad URI value \"%s\" - %s " - "(RFC 8011 section 5.1.6)."), attr->name, - attr->values[i].string.text, - uri_status_strings[uri_status - - HTTP_URI_STATUS_OVERFLOW]); + ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST, _("\"%s\": Bad URI value \"%s\" - %s (RFC 8011 section 5.1.6)."), attr->name, attr->values[i].string.text, httpURIStatusString(uri_status)); return (0); } @@ -6497,6 +6411,7 @@ ipp_free_values(ipp_attribute_t *attr, /* I - Attribute to free values from */ } break; + case IPP_TAG_UNSUPPORTED_VALUE : case IPP_TAG_DEFAULT : case IPP_TAG_UNKNOWN : case IPP_TAG_NOVALUE : @@ -6838,14 +6753,14 @@ ipp_read_http(http_t *http, /* I - Client connection */ if ((bytes = httpRead2(http, (char *)buffer, length - (size_t)tbytes)) < 0) { -#ifdef WIN32 +#ifdef _WIN32 break; #else if (errno != EAGAIN && errno != EINTR) break; bytes = 0; -#endif /* WIN32 */ +#endif /* _WIN32 */ } else if (bytes == 0) break; @@ -6873,11 +6788,11 @@ ipp_read_file(int *fd, /* I - File descriptor */ ipp_uchar_t *buffer, /* O - Read buffer */ size_t length) /* I - Number of bytes to read */ { -#ifdef WIN32 +#ifdef _WIN32 return ((ssize_t)read(*fd, buffer, (unsigned)length)); #else return (read(*fd, buffer, length)); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -7045,9 +6960,9 @@ ipp_write_file(int *fd, /* I - File descriptor */ ipp_uchar_t *buffer, /* I - Data to write */ size_t length) /* I - Number of bytes to write */ { -#ifdef WIN32 +#ifdef _WIN32 return ((ssize_t)write(*fd, buffer, (unsigned)length)); #else return (write(*fd, buffer, length)); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -79,11 +79,11 @@ extern "C" { typedef enum ipp_dstate_e /**** Document states @exclude all@ ****/ { - IPP_DOCUMENT_PENDING = 3, /* Document is pending */ - IPP_DOCUMENT_PROCESSING = 5, /* Document is processing */ - IPP_DOCUMENT_CANCELED = 7, /* Document is canceled */ - IPP_DOCUMENT_ABORTED, /* Document is aborted */ - IPP_DOCUMENT_COMPLETED /* Document is completed */ + IPP_DSTATE_PENDING = 3, /* Document is pending */ + IPP_DSTATE_PROCESSING = 5, /* Document is processing */ + IPP_DSTATE_CANCELED = 7, /* Document is canceled */ + IPP_DSTATE_ABORTED, /* Document is aborted */ + IPP_DSTATE_COMPLETED /* Document is completed */ # ifndef _CUPS_NO_DEPRECATED # define IPP_DOCUMENT_PENDING IPP_DSTATE_PENDING diff --git a/cups/language-private.h b/cups/language-private.h index 49e4b713..f447ef92 100644 --- a/cups/language-private.h +++ b/cups/language-private.h @@ -1,7 +1,7 @@ /* * Private localization support for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -20,6 +20,7 @@ * Include necessary headers... */ +# include "config.h" # include <stdio.h> # include <cups/transcode.h> # ifdef __APPLE__ @@ -59,16 +60,11 @@ extern const char *_cupsAppleLocale(CFStringRef languageName, char *locale, size # endif /* __APPLE__ */ extern void _cupsCharmapFlush(void); extern const char *_cupsEncodingName(cups_encoding_t encoding); -extern void _cupsLangPrintError(const char *prefix, - const char *message); -extern int _cupsLangPrintFilter(FILE *fp, const char *prefix, - const char *message, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); -extern int _cupsLangPrintf(FILE *fp, const char *message, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); +extern void _cupsLangPrintError(const char *prefix, const char *message); +extern int _cupsLangPrintFilter(FILE *fp, const char *prefix, const char *message, ...) _CUPS_FORMAT(3, 4); +extern int _cupsLangPrintf(FILE *fp, const char *message, ...) _CUPS_FORMAT(2, 3); extern int _cupsLangPuts(FILE *fp, const char *message); -extern const char *_cupsLangString(cups_lang_t *lang, - const char *message); +extern const char *_cupsLangString(cups_lang_t *lang, const char *message); extern void _cupsMessageFree(cups_array_t *a); extern cups_array_t *_cupsMessageLoad(const char *filename, int unquote); extern const char *_cupsMessageLookup(cups_array_t *a, const char *m); diff --git a/cups/language.c b/cups/language.c index e6d2d44a..61280c0f 100644 --- a/cups/language.c +++ b/cups/language.c @@ -21,11 +21,11 @@ #ifdef HAVE_LANGINFO_H # include <langinfo.h> #endif /* HAVE_LANGINFO_H */ -#ifdef WIN32 +#ifdef _WIN32 # include <io.h> #else # include <unistd.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ #ifdef HAVE_COREFOUNDATION_H # include <CoreFoundation/CoreFoundation.h> #endif /* HAVE_COREFOUNDATION_H */ diff --git a/cups/libcups2.def b/cups/libcups2.def index a7be679f..fa4aaa3b 100644 --- a/cups/libcups2.def +++ b/cups/libcups2.def @@ -1,5 +1,5 @@ LIBRARY libcups2 -VERSION 2.12 +VERSION 2.13 EXPORTS _cupsArrayAddStrings _cupsArrayNewStrings @@ -13,6 +13,7 @@ _cupsConnect _cupsConvertOptions _cupsCreateDest _cupsEncodingName +_cupsFilePeekAhead _cupsGet1284Values _cupsGetDestResource _cupsGetDests @@ -24,9 +25,6 @@ _cupsLangPrintError _cupsLangPrintf _cupsLangPuts _cupsLangString -_cupsMD5Append -_cupsMD5Finish -_cupsMD5Init _cupsMessageFree _cupsMessageLoad _cupsMessageLookup @@ -39,18 +37,6 @@ _cupsRWInit _cupsRWLockRead _cupsRWLockWrite _cupsRWUnlock -_cupsSNMPClose -_cupsSNMPCopyOID -_cupsSNMPDefaultCommunity -_cupsSNMPIsOID -_cupsSNMPIsOIDPrefixed -_cupsSNMPOIDToString -_cupsSNMPOpen -_cupsSNMPRead -_cupsSNMPSetDebug -_cupsSNMPStringToOID -_cupsSNMPWalk -_cupsSNMPWrite _cupsSetDefaults _cupsSetError _cupsSetHTTPError @@ -65,6 +51,7 @@ _cupsStrScand _cupsStrStatistics _cupsThreadCancel _cupsThreadCreate +_cupsThreadDetach _cupsThreadWait _cupsUserDefault _cups_safe_vsnprintf @@ -81,6 +68,7 @@ _httpDisconnect _httpEncodeURI _httpFreeCredentials _httpResolveURI +_httpSetDigestAuthString _httpStatus _httpTLSInitialize _httpTLSPending @@ -124,6 +112,7 @@ _pwgMediaTable _pwgMediaTypeForType _pwgPageSizeForMedia cupsAddDest +cupsAddIntegerOption cupsAddOption cupsAdminCreateWindowsPPD cupsAdminExportSamba @@ -227,6 +216,7 @@ cupsGetDests2 cupsGetDevices cupsGetFd cupsGetFile +cupsGetIntegerOption cupsGetJobs cupsGetJobs2 cupsGetNamedDest @@ -240,6 +230,7 @@ cupsGetPrinters cupsGetResponse cupsGetServerPPD cupsHashData +cupsHashString cupsLangDefault cupsLangEncoding cupsLangFlush @@ -1,7 +1,7 @@ /* * Private MD5 implementation for CUPS. * - * Copyright 2007-2014 by Apple Inc. + * Copyright 2007-2017 by Apple Inc. * Copyright 2005 by Easy Software Products * Copyright (C) 1999 Aladdin Enterprises. All rights reserved. * @@ -43,70 +43,71 @@ #include "md5-private.h" #include "string-private.h" -#define T1 0xd76aa478 -#define T2 0xe8c7b756 -#define T3 0x242070db -#define T4 0xc1bdceee -#define T5 0xf57c0faf -#define T6 0x4787c62a -#define T7 0xa8304613 -#define T8 0xfd469501 -#define T9 0x698098d8 -#define T10 0x8b44f7af -#define T11 0xffff5bb1 -#define T12 0x895cd7be -#define T13 0x6b901122 -#define T14 0xfd987193 -#define T15 0xa679438e -#define T16 0x49b40821 -#define T17 0xf61e2562 -#define T18 0xc040b340 -#define T19 0x265e5a51 -#define T20 0xe9b6c7aa -#define T21 0xd62f105d -#define T22 0x02441453 -#define T23 0xd8a1e681 -#define T24 0xe7d3fbc8 -#define T25 0x21e1cde6 -#define T26 0xc33707d6 -#define T27 0xf4d50d87 -#define T28 0x455a14ed -#define T29 0xa9e3e905 -#define T30 0xfcefa3f8 -#define T31 0x676f02d9 -#define T32 0x8d2a4c8a -#define T33 0xfffa3942 -#define T34 0x8771f681 -#define T35 0x6d9d6122 -#define T36 0xfde5380c -#define T37 0xa4beea44 -#define T38 0x4bdecfa9 -#define T39 0xf6bb4b60 -#define T40 0xbebfbc70 -#define T41 0x289b7ec6 -#define T42 0xeaa127fa -#define T43 0xd4ef3085 -#define T44 0x04881d05 -#define T45 0xd9d4d039 -#define T46 0xe6db99e5 -#define T47 0x1fa27cf8 -#define T48 0xc4ac5665 -#define T49 0xf4292244 -#define T50 0x432aff97 -#define T51 0xab9423a7 -#define T52 0xfc93a039 -#define T53 0x655b59c3 -#define T54 0x8f0ccc92 -#define T55 0xffeff47d -#define T56 0x85845dd1 -#define T57 0x6fa87e4f -#define T58 0xfe2ce6e0 -#define T59 0xa3014314 -#define T60 0x4e0811a1 -#define T61 0xf7537e82 -#define T62 0xbd3af235 -#define T63 0x2ad7d2bb -#define T64 0xeb86d391 +#if !defined(__APPLE__) && !defined(HAVE_GNUTLS) +# define T1 0xd76aa478 +# define T2 0xe8c7b756 +# define T3 0x242070db +# define T4 0xc1bdceee +# define T5 0xf57c0faf +# define T6 0x4787c62a +# define T7 0xa8304613 +# define T8 0xfd469501 +# define T9 0x698098d8 +# define T10 0x8b44f7af +# define T11 0xffff5bb1 +# define T12 0x895cd7be +# define T13 0x6b901122 +# define T14 0xfd987193 +# define T15 0xa679438e +# define T16 0x49b40821 +# define T17 0xf61e2562 +# define T18 0xc040b340 +# define T19 0x265e5a51 +# define T20 0xe9b6c7aa +# define T21 0xd62f105d +# define T22 0x02441453 +# define T23 0xd8a1e681 +# define T24 0xe7d3fbc8 +# define T25 0x21e1cde6 +# define T26 0xc33707d6 +# define T27 0xf4d50d87 +# define T28 0x455a14ed +# define T29 0xa9e3e905 +# define T30 0xfcefa3f8 +# define T31 0x676f02d9 +# define T32 0x8d2a4c8a +# define T33 0xfffa3942 +# define T34 0x8771f681 +# define T35 0x6d9d6122 +# define T36 0xfde5380c +# define T37 0xa4beea44 +# define T38 0x4bdecfa9 +# define T39 0xf6bb4b60 +# define T40 0xbebfbc70 +# define T41 0x289b7ec6 +# define T42 0xeaa127fa +# define T43 0xd4ef3085 +# define T44 0x04881d05 +# define T45 0xd9d4d039 +# define T46 0xe6db99e5 +# define T47 0x1fa27cf8 +# define T48 0xc4ac5665 +# define T49 0xf4292244 +# define T50 0x432aff97 +# define T51 0xab9423a7 +# define T52 0xfc93a039 +# define T53 0x655b59c3 +# define T54 0x8f0ccc92 +# define T55 0xffeff47d +# define T56 0x85845dd1 +# define T57 0x6fa87e4f +# define T58 0xfe2ce6e0 +# define T59 0xa3014314 +# define T60 0x4e0811a1 +# define T61 0xf7537e82 +# define T62 0xbd3af235 +# define T63 0x2ad7d2bb +# define T64 0xeb86d391 static void _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/) @@ -116,10 +117,10 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/) c = pms->abcd[2], d = pms->abcd[3]; unsigned int t; -#ifndef ARCH_IS_BIG_ENDIAN -# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ -#endif -#if ARCH_IS_BIG_ENDIAN +# ifndef ARCH_IS_BIG_ENDIAN +# define ARCH_IS_BIG_ENDIAN 1 /* slower, default implementation */ +# endif +# if ARCH_IS_BIG_ENDIAN /* * On big-endian machines, we must arrange the bytes in the right @@ -133,7 +134,7 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/) X[i] = (unsigned)xp[0] + ((unsigned)xp[1] << 8) + ((unsigned)xp[2] << 16) + ((unsigned)xp[3] << 24); -#else /* !ARCH_IS_BIG_ENDIAN */ +# else /* !ARCH_IS_BIG_ENDIAN */ /* * On little-endian machines, we can process properly aligned data @@ -150,15 +151,15 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/) memcpy(xbuf, data, 64); X = xbuf; } -#endif +# endif -#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) +# define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n)))) /* Round 1. */ /* Let [abcd k s i] denote the operation a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */ -#define F(x, y, z) (((x) & (y)) | (~(x) & (z))) -#define SET(a, b, c, d, k, s, Ti)\ +# define F(x, y, z) (((x) & (y)) | (~(x) & (z))) +# define SET(a, b, c, d, k, s, Ti)\ t = a + F(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ @@ -178,13 +179,13 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/) SET(d, a, b, c, 13, 12, T14); SET(c, d, a, b, 14, 17, T15); SET(b, c, d, a, 15, 22, T16); -#undef SET +# undef SET /* Round 2. */ /* Let [abcd k s i] denote the operation a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */ -#define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ +# define G(x, y, z) (((x) & (z)) | ((y) & ~(z))) +# define SET(a, b, c, d, k, s, Ti)\ t = a + G(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ @@ -204,13 +205,13 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/) SET(d, a, b, c, 2, 9, T30); SET(c, d, a, b, 7, 14, T31); SET(b, c, d, a, 12, 20, T32); -#undef SET +# undef SET /* Round 3. */ /* Let [abcd k s t] denote the operation a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */ -#define H(x, y, z) ((x) ^ (y) ^ (z)) -#define SET(a, b, c, d, k, s, Ti)\ +# define H(x, y, z) ((x) ^ (y) ^ (z)) +# define SET(a, b, c, d, k, s, Ti)\ t = a + H(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ @@ -230,13 +231,13 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/) SET(d, a, b, c, 12, 11, T46); SET(c, d, a, b, 15, 16, T47); SET(b, c, d, a, 2, 23, T48); -#undef SET +# undef SET /* Round 4. */ /* Let [abcd k s t] denote the operation a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */ -#define I(x, y, z) ((y) ^ ((x) | ~(z))) -#define SET(a, b, c, d, k, s, Ti)\ +# define I(x, y, z) ((y) ^ ((x) | ~(z))) +# define SET(a, b, c, d, k, s, Ti)\ t = a + I(b,c,d) + X[k] + Ti;\ a = ROTATE_LEFT(t, s) + b /* Do the following 16 operations. */ @@ -256,7 +257,7 @@ _cups_md5_process(_cups_md5_state_t *pms, const unsigned char *data /*[64]*/) SET(d, a, b, c, 11, 10, T62); SET(c, d, a, b, 2, 15, T63); SET(b, c, d, a, 9, 21, T64); -#undef SET +# undef SET /* Then perform the following additions. (That is increment each of the four registers by the value it had before this block @@ -337,3 +338,4 @@ _cupsMD5Finish(_cups_md5_state_t *pms, unsigned char digest[16]) for (i = 0; i < 16; ++i) digest[i] = (unsigned char)(pms->abcd[i >> 2] >> ((i & 3) << 3)); } +#endif /* !__APPLE__ && !HAVE_GNUTLS */ diff --git a/cups/md5passwd.c b/cups/md5passwd.c index a9817aaa..49add7d7 100644 --- a/cups/md5passwd.c +++ b/cups/md5passwd.c @@ -1,7 +1,7 @@ /* - * MD5 password support for CUPS. + * MD5 password support for CUPS (deprecated). * - * Copyright 2007-2010 by Apple Inc. + * Copyright 2007-2017 by Apple Inc. * Copyright 1997-2005 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -17,12 +17,15 @@ * Include necessary headers... */ +#include <cups/cups.h> #include "http-private.h" #include "string-private.h" /* * 'httpMD5()' - Compute the MD5 sum of the username:group:password. + * + * @deprecated@ */ char * /* O - MD5 sum */ @@ -31,7 +34,6 @@ httpMD5(const char *username, /* I - User name */ const char *passwd, /* I - Password string */ char md5[33]) /* O - MD5 string */ { - _cups_md5_state_t state; /* MD5 state info */ unsigned char sum[16]; /* Sum data */ char line[256]; /* Line to sum */ @@ -41,15 +43,13 @@ httpMD5(const char *username, /* I - User name */ */ snprintf(line, sizeof(line), "%s:%s:%s", username, realm, passwd); - _cupsMD5Init(&state); - _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line)); - _cupsMD5Finish(&state, sum); + cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); /* * Return the sum... */ - return (httpMD5String(sum, md5)); + return ((char *)cupsHashString(sum, sizeof(sum), md5, 33)); } @@ -57,6 +57,8 @@ httpMD5(const char *username, /* I - User name */ * 'httpMD5Final()' - Combine the MD5 sum of the username, group, and password * with the server-supplied nonce value, method, and * request-uri. + * + * @deprecated@ */ char * /* O - New sum */ @@ -65,7 +67,6 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ const char *resource, /* I - Resource path */ char md5[33]) /* IO - MD5 sum */ { - _cups_md5_state_t state; /* MD5 state info */ unsigned char sum[16]; /* Sum data */ char line[1024]; /* Line of data */ char a2[33]; /* Hash of method and resource */ @@ -76,10 +77,8 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ */ snprintf(line, sizeof(line), "%s:%s", method, resource); - _cupsMD5Init(&state); - _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line)); - _cupsMD5Finish(&state, sum); - httpMD5String(sum, a2); + cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); + cupsHashString(sum, sizeof(sum), a2, sizeof(a2)); /* * Then combine A1 (MD5 of username, realm, and password) with the nonce @@ -88,17 +87,16 @@ httpMD5Final(const char *nonce, /* I - Server nonce value */ */ snprintf(line, sizeof(line), "%s:%s:%s", md5, nonce, a2); + cupsHashData("md5", (unsigned char *)line, strlen(line), sum, sizeof(sum)); - _cupsMD5Init(&state); - _cupsMD5Append(&state, (unsigned char *)line, (int)strlen(line)); - _cupsMD5Finish(&state, sum); - - return (httpMD5String(sum, md5)); + return ((char *)cupsHashString(sum, sizeof(sum), md5, 33)); } /* * 'httpMD5String()' - Convert an MD5 sum to a character string. + * + * @deprecated@ */ char * /* O - MD5 sum in hex */ @@ -106,23 +104,5 @@ httpMD5String(const unsigned char *sum, /* I - MD5 sum data */ char md5[33]) /* O - MD5 sum in hex */ { - int i; /* Looping var */ - char *md5ptr; /* Pointer into MD5 string */ - static const char hex[] = "0123456789abcdef"; - /* Hex digits */ - - - /* - * Convert the MD5 sum to hexadecimal... - */ - - for (i = 16, md5ptr = md5; i > 0; i --, sum ++) - { - *md5ptr++ = hex[*sum >> 4]; - *md5ptr++ = hex[*sum & 15]; - } - - *md5ptr = '\0'; - - return (md5); + return ((char *)cupsHashString(sum, 16, md5, 33)); } diff --git a/cups/ppd-cache.c b/cups/ppd-cache.c index 925ab805..9ed946e6 100644 --- a/cups/ppd-cache.c +++ b/cups/ppd-cache.c @@ -1,7 +1,7 @@ /* * PPD cache implementation for CUPS. * - * Copyright 2010-2017 by Apple Inc. + * Copyright © 2010-2018 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -3105,8 +3105,8 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ cupsFilePrintf(fp, "*Manufacturer: \"%s\"\n", make); cupsFilePrintf(fp, "*ModelName: \"%s\"\n", model); cupsFilePrintf(fp, "*Product: \"(%s)\"\n", model); - cupsFilePrintf(fp, "*NickName: \"%s\"\n", model); - cupsFilePrintf(fp, "*ShortNickName: \"%s\"\n", model); + cupsFilePrintf(fp, "*NickName: \"%s - IPP Everywhere\"\n", model); + cupsFilePrintf(fp, "*ShortNickName: \"%s - IPP Everywhere\"\n", model); if ((attr = ippFindAttribute(response, "color-supported", IPP_TAG_BOOLEAN)) != NULL && ippGetBoolean(attr, 0)) cupsFilePuts(fp, "*ColorDevice: True\n"); @@ -3118,6 +3118,41 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ cupsFilePuts(fp, "*cupsLanguages: \"en\"\n"); /* + * Password/PIN printing... + */ + + if ((attr = ippFindAttribute(response, "job-password-supported", IPP_TAG_INTEGER)) != NULL) + { + char pattern[33]; /* Password pattern */ + int maxlen = ippGetInteger(attr, 0); + /* Maximum length */ + const char *repertoire = ippGetString(ippFindAttribute(response, "job-password-repertoire-configured", IPP_TAG_KEYWORD), 0, NULL); + /* Type of password */ + + if (maxlen > (int)(sizeof(pattern) - 1)) + maxlen = (int)sizeof(pattern) - 1; + + if (!repertoire || !strcmp(repertoire, "iana_us-ascii_digits")) + memset(pattern, '1', (size_t)maxlen); + else if (!strcmp(repertoire, "iana_us-ascii_letters")) + memset(pattern, 'A', (size_t)maxlen); + else if (!strcmp(repertoire, "iana_us-ascii_complex")) + memset(pattern, 'C', (size_t)maxlen); + else if (!strcmp(repertoire, "iana_us-ascii_any")) + memset(pattern, '.', (size_t)maxlen); + else if (!strcmp(repertoire, "iana_utf-8_digits")) + memset(pattern, 'N', (size_t)maxlen); + else if (!strcmp(repertoire, "iana_utf-8_letters")) + memset(pattern, 'U', (size_t)maxlen); + else + memset(pattern, '*', (size_t)maxlen); + + pattern[maxlen] = '\0'; + + cupsFilePrintf(fp, "*cupsPassword: \"%s\"\n", pattern); + } + + /* * Filters... */ @@ -3125,24 +3160,28 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ { is_apple = ippContainsString(attr, "image/urf"); is_pdf = ippContainsString(attr, "application/pdf"); - is_pwg = ippContainsString(attr, "image/pwg-raster"); + is_pwg = ippContainsString(attr, "image/pwg-raster") && !is_apple; - for (i = 0, count = ippGetCount(attr); i < count; i ++) + if (ippContainsString(attr, "image/jpeg")) + cupsFilePuts(fp, "*cupsFilter2: \"image/jpeg image/jpeg 0 -\"\n"); + if (ippContainsString(attr, "image/png")) + cupsFilePuts(fp, "*cupsFilter2: \"image/png image/png 0 -\"\n"); + if (is_pdf) { - const char *format = ippGetString(attr, i, NULL); - /* PDL */ - /* - * Write cupsFilter2 lines for supported formats... + * Don't locally filter PDF content when printing to a CUPS shared + * printer, otherwise the options will be applied twice... */ - if (!_cups_strcasecmp(format, "application/pdf")) + if (ippContainsString(attr, "application/vnd.cups-pdf")) + cupsFilePuts(fp, "*cupsFilter2: \"application/pdf application/pdf 0 -\"\n"); + else cupsFilePuts(fp, "*cupsFilter2: \"application/vnd.cups-pdf application/pdf 10 -\"\n"); - else if (!_cups_strcasecmp(format, "image/jpeg") || !_cups_strcasecmp(format, "image/png")) - cupsFilePrintf(fp, "*cupsFilter2: \"%s %s 0 -\"\n", format, format); - else if (!_cups_strcasecmp(format, "image/pwg-raster") || !_cups_strcasecmp(format, "image/urf")) - cupsFilePrintf(fp, "*cupsFilter2: \"%s %s 100 -\"\n", format, format); } + if (is_apple) + cupsFilePuts(fp, "*cupsFilter2: \"image/urf image/urf 100 -\"\n"); + if (is_pwg) + cupsFilePuts(fp, "*cupsFilter2: \"image/pwg-raster image/pwg-raster 100 -\"\n"); } if (!is_apple && !is_pdf && !is_pwg) @@ -3414,7 +3453,8 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ for (j = 0; j < (int)(sizeof(sources) / sizeof(sources[0])); j ++) if (!strcmp(sources[j][0], ppdname)) { - cupsFilePrintf(fp, "*InputSlot %s/%s: \"<</MediaPosition %d>>setpagedevice\"\n", ppdname, _cupsLangString(lang, sources[j][1]), j); + cupsFilePrintf(fp, "*InputSlot %s: \"<</MediaPosition %d>>setpagedevice\"\n", ppdname, j); + cupsFilePrintf(fp, "*%s.InputSlot %s/%s: \"\"\n", lang->language, ppdname, _cupsLangString(lang, sources[j][1])); break; } } @@ -3590,9 +3630,14 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ break; if (j < (int)(sizeof(media_types) / sizeof(media_types[0]))) - cupsFilePrintf(fp, "*MediaType %s/%s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, _cupsLangString(lang, media_types[j][1]), ppdname); + { + cupsFilePrintf(fp, "*MediaType %s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, ppdname); + cupsFilePrintf(fp, "*%s.MediaType %s/%s: \"\"\n", lang->language, ppdname, _cupsLangString(lang, media_types[j][1])); + } else + { cupsFilePrintf(fp, "*MediaType %s/%s: \"<</MediaType(%s)>>setpagedevice\"\n", ppdname, keyword, ppdname); + } } cupsFilePuts(fp, "*CloseUI: *MediaType\n"); } @@ -3618,10 +3663,11 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ if (!strcasecmp(keyword, "black_1") || !strcmp(keyword, "bi-level") || !strcmp(keyword, "process-bi-level")) { if (!default_color) - cupsFilePrintf(fp, "*OpenUI *ColorModel/%s: PickOne\n" - "*OrderDependency: 10 AnySetup *ColorModel\n", _cupsLangString(lang, _("Color Mode"))); + cupsFilePrintf(fp, "*OpenUI *ColorModel: PickOne\n" + "*OrderDependency: 10 AnySetup *ColorModel\n" + "*%s.Translation ColorModel/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Color Mode"))); - cupsFilePrintf(fp, "*ColorModel FastGray/%s: \"<</cupsColorSpace 3/cupsBitsPerColor 1/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n", _cupsLangString(lang, _("Fast Grayscale"))); + cupsFilePrintf(fp, "*ColorModel FastGray: \"<</cupsColorSpace 3/cupsBitsPerColor 1/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n*%s.ColorModel FastGray/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Fast Grayscale"))); if (!default_color) default_color = "FastGray"; @@ -3629,10 +3675,11 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ else if (!strcasecmp(keyword, "sgray_8") || !strcmp(keyword, "W8") || !strcmp(keyword, "monochrome") || !strcmp(keyword, "process-monochrome")) { if (!default_color) - cupsFilePrintf(fp, "*OpenUI *ColorModel/%s: PickOne\n" - "*OrderDependency: 10 AnySetup *ColorModel\n", _cupsLangString(lang, _("Color Mode"))); + cupsFilePrintf(fp, "*OpenUI *ColorModel: PickOne\n" + "*OrderDependency: 10 AnySetup *ColorModel\n" + "*%s.Translation ColorModel/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Color Mode"))); - cupsFilePrintf(fp, "*ColorModel Gray/%s: \"<</cupsColorSpace 18/cupsBitsPerColor 8/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n", _cupsLangString(lang, _("Grayscale"))); + cupsFilePrintf(fp, "*ColorModel Gray: \"<</cupsColorSpace 18/cupsBitsPerColor 8/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n*%s.ColorModel Gray/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Grayscale"))); if (!default_color || !strcmp(default_color, "FastGray")) default_color = "Gray"; @@ -3640,20 +3687,22 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ else if (!strcasecmp(keyword, "srgb_8") || !strcmp(keyword, "SRGB24") || !strcmp(keyword, "color")) { if (!default_color) - cupsFilePrintf(fp, "*OpenUI *ColorModel/%s: PickOne\n" - "*OrderDependency: 10 AnySetup *ColorModel\n", _cupsLangString(lang, _("Color Mode"))); + cupsFilePrintf(fp, "*OpenUI *ColorModel: PickOne\n" + "*OrderDependency: 10 AnySetup *ColorModel\n" + "*%s.Translation ColorModel/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Color Mode"))); - cupsFilePrintf(fp, "*ColorModel RGB/%s: \"<</cupsColorSpace 19/cupsBitsPerColor 8/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n", _cupsLangString(lang, _("Color"))); + cupsFilePrintf(fp, "*ColorModel RGB: \"<</cupsColorSpace 19/cupsBitsPerColor 8/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n*%s.ColorModel RGB/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Color"))); default_color = "RGB"; } else if (!strcasecmp(keyword, "adobe-rgb_16") || !strcmp(keyword, "ADOBERGB48")) { if (!default_color) - cupsFilePrintf(fp, "*OpenUI *ColorModel/%s: PickOne\n" - "*OrderDependency: 10 AnySetup *ColorModel\n", _cupsLangString(lang, _("Color Mode"))); + cupsFilePrintf(fp, "*OpenUI *ColorModel: PickOne\n" + "*OrderDependency: 10 AnySetup *ColorModel\n" + "*%s.Translation ColorModel/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Color Mode"))); - cupsFilePrintf(fp, "*ColorModel AdobeRGB/%s: \"<</cupsColorSpace 20/cupsBitsPerColor 16/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n", _cupsLangString(lang, _("Deep Color"))); + cupsFilePrintf(fp, "*ColorModel AdobeRGB: \"<</cupsColorSpace 20/cupsBitsPerColor 16/cupsColorOrder 0/cupsCompression 0>>setpagedevice\"\n*%s.ColorModel AdobeRGB/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Deep Color"))); if (!default_color) default_color = "AdobeRGB"; @@ -3673,13 +3722,17 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ if ((attr = ippFindAttribute(response, "sides-supported", IPP_TAG_KEYWORD)) != NULL && ippContainsString(attr, "two-sided-long-edge")) { - cupsFilePrintf(fp, "*OpenUI *Duplex/%s: PickOne\n" + cupsFilePrintf(fp, "*OpenUI *Duplex: PickOne\n" "*OrderDependency: 10 AnySetup *Duplex\n" + "*%s.Translation Duplex/%s: \"\"\n" "*DefaultDuplex: None\n" - "*Duplex None/%s: \"<</Duplex false>>setpagedevice\"\n" - "*Duplex DuplexNoTumble/%s: \"<</Duplex true/Tumble false>>setpagedevice\"\n" - "*Duplex DuplexTumble/%s: \"<</Duplex true/Tumble true>>setpagedevice\"\n" - "*CloseUI: *Duplex\n", _cupsLangString(lang, _("2-Sided Printing")), _cupsLangString(lang, _("Off (1-Sided)")), _cupsLangString(lang, _("Long-Edge (Portrait)")), _cupsLangString(lang, _("Short-Edge (Landscape)"))); + "*Duplex None: \"<</Duplex false>>setpagedevice\"\n" + "*%s.Duplex None/%s: \"\"\n" + "*Duplex DuplexNoTumble: \"<</Duplex true/Tumble false>>setpagedevice\"\n" + "*%s.Duplex DuplexNoTumble/%s: \"\"\n" + "*Duplex DuplexTumble: \"<</Duplex true/Tumble true>>setpagedevice\"\n" + "*%s.Duplex DuplexTumble/%s: \"\"\n" + "*CloseUI: *Duplex\n", lang->language, _cupsLangString(lang, _("2-Sided Printing")), lang->language, _cupsLangString(lang, _("Off (1-Sided)")), lang->language, _cupsLangString(lang, _("Long-Edge (Portrait)")), lang->language, _cupsLangString(lang, _("Short-Edge (Landscape)"))); if ((attr = ippFindAttribute(response, "urf-supported", IPP_TAG_KEYWORD)) != NULL) { @@ -3737,6 +3790,12 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ if ((attr = ippFindAttribute(response, "output-bin-supported", IPP_TAG_ZERO)) != NULL && (count = ippGetCount(attr)) > 1) { + ipp_attribute_t *trays = ippFindAttribute(response, "printer-output-tray", IPP_TAG_STRING); + /* printer-output-tray attribute, if any */ + const char *tray_ptr; /* printer-output-tray value */ + int tray_len; /* Len of printer-output-tray value */ + char tray[IPP_MAX_OCTETSTRING]; + /* printer-output-tray string value */ static const char * const output_bins[][2] = { /* "output-bin" strings */ { "auto", _("Automatic") }, @@ -3787,6 +3846,11 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ cupsFilePrintf(fp, "*OpenUI *OutputBin: PickOne\n" "*OrderDependency: 10 AnySetup *OutputBin\n" "*DefaultOutputBin: %s\n", ppdname); + if (!strcmp(ppdname, "FaceUp")) + cupsFilePuts(fp, "*DefaultOutputOrder: Reverse\n"); + else + cupsFilePuts(fp, "*DefaultOutputOrder: Normal\n"); + for (i = 0; i < (int)(sizeof(output_bins) / sizeof(output_bins[0])); i ++) { if (!ippContainsString(attr, output_bins[i][0])) @@ -3794,7 +3858,26 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ pwg_ppdize_name(output_bins[i][0], ppdname, sizeof(ppdname)); - cupsFilePrintf(fp, "*OutputBin %s/%s: \"\"\n", ppdname, _cupsLangString(lang, output_bins[i][1])); + cupsFilePrintf(fp, "*OutputBin %s: \"\"\n", ppdname); + cupsFilePrintf(fp, "*%s.OutputBin %s/%s: \"\"\n", lang->language, ppdname, _cupsLangString(lang, output_bins[i][1])); + + if ((tray_ptr = ippGetOctetString(trays, i, &tray_len)) != NULL) + { + if (tray_len >= (int)sizeof(tray)) + tray_len = (int)sizeof(tray) - 1; + + memcpy(tray, tray_ptr, (size_t)tray_len); + tray[tray_len] = '\0'; + + if (strstr(tray, "stackingorder=lastToFirst;")) + cupsFilePrintf(fp, "*PageStackOrder %s: Reverse\n", ppdname); + else + cupsFilePrintf(fp, "*PageStackOrder %s: Normal\n", ppdname); + } + else if (!strcmp(ppdname, "FaceUp")) + cupsFilePrintf(fp, "*PageStackOrder %s: Reverse\n", ppdname); + else + cupsFilePrintf(fp, "*PageStackOrder %s: Normal\n", ppdname); } cupsFilePuts(fp, "*CloseUI: *OutputBin\n"); } @@ -3832,10 +3915,12 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ if (i < count) { - cupsFilePrintf(fp, "*OpenUI *StapleLocation/%s: PickOne\n", _cupsLangString(lang, _("Staple"))); + cupsFilePuts(fp, "*OpenUI *StapleLocation: PickOne\n"); cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *StapleLocation\n"); + cupsFilePrintf(fp, "*%s.Translation StapleLocation/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Staple"))); cupsFilePuts(fp, "*DefaultStapleLocation: None\n"); - cupsFilePrintf(fp, "*StapleLocation None/%s: \"\"\n", _cupsLangString(lang, _("None"))); + cupsFilePuts(fp, "*StapleLocation None: \"\"\n"); + cupsFilePrintf(fp, "*%s.StapleLocation None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None"))); for (; i < count; i ++) { @@ -3854,7 +3939,8 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ { if (!strcmp(finishings[j][0], name)) { - cupsFilePrintf(fp, "*StapleLocation %s/%s: \"\"\n", name, _cupsLangString(lang, finishings[j][1])); + cupsFilePrintf(fp, "*StapleLocation %s: \"\"\n", name); + cupsFilePrintf(fp, "*%s.StapleLocation %s/%s: \"\"\n", lang->language, name, _cupsLangString(lang, finishings[j][1])); cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*StapleLocation %s\"\n", value, name, name); break; } @@ -3879,10 +3965,12 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ if (i < count) { - cupsFilePrintf(fp, "*OpenUI *FoldType/%s: PickOne\n", _cupsLangString(lang, _("Fold"))); + cupsFilePuts(fp, "*OpenUI *FoldType: PickOne\n"); cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *FoldType\n"); + cupsFilePrintf(fp, "*%s.Translation FoldType/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Fold"))); cupsFilePuts(fp, "*DefaultFoldType: None\n"); - cupsFilePrintf(fp, "*FoldType None/%s: \"\"\n", _cupsLangString(lang, _("None"))); + cupsFilePuts(fp, "*FoldType None: \"\"\n"); + cupsFilePrintf(fp, "*%s.FoldType None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None"))); for (; i < count; i ++) { @@ -3901,7 +3989,8 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ { if (!strcmp(finishings[j][0], name)) { - cupsFilePrintf(fp, "*FoldType %s/%s: \"\"\n", name, _cupsLangString(lang, finishings[j][1])); + cupsFilePrintf(fp, "*FoldType %s: \"\"\n", name); + cupsFilePrintf(fp, "*%s.FoldType %s/%s: \"\"\n", lang->language, name, _cupsLangString(lang, finishings[j][1])); cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*FoldType %s\"\n", value, name, name); break; } @@ -3926,10 +4015,12 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ if (i < count) { - cupsFilePrintf(fp, "*OpenUI *PunchMedia/%s: PickOne\n", _cupsLangString(lang, _("Punch"))); + cupsFilePuts(fp, "*OpenUI *PunchMedia: PickOne\n"); cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *PunchMedia\n"); + cupsFilePrintf(fp, "*%s.Translation PunchMedia/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Punch"))); cupsFilePuts(fp, "*DefaultPunchMedia: None\n"); - cupsFilePrintf(fp, "*PunchMedia None/%s: \"\"\n", _cupsLangString(lang, _("None"))); + cupsFilePuts(fp, "*PunchMedia None: \"\"\n"); + cupsFilePrintf(fp, "*%s.PunchMedia None/%s: \"\"\n", lang->language, _cupsLangString(lang, _("None"))); for (i = 0; i < count; i ++) { @@ -3948,7 +4039,8 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ { if (!strcmp(finishings[j][0], name)) { - cupsFilePrintf(fp, "*PunchMedia %s/%s: \"\"\n", name, _cupsLangString(lang, finishings[j][1])); + cupsFilePrintf(fp, "*PunchMedia %s: \"\"\n", name); + cupsFilePrintf(fp, "*%s.PunchMedia %s/%s: \"\"\n", lang->language, name, _cupsLangString(lang, finishings[j][1])); cupsFilePrintf(fp, "*cupsIPPFinishings %d/%s: \"*PunchMedia %s\"\n", value, name, name); break; } @@ -3964,8 +4056,9 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ if (ippContainsInteger(attr, IPP_FINISHINGS_BOOKLET_MAKER)) { - cupsFilePrintf(fp, "*OpenUI *Booklet/%s: Boolean\n", _cupsLangString(lang, _("Booklet"))); + cupsFilePuts(fp, "*OpenUI *Booklet: Boolean\n"); cupsFilePuts(fp, "*OrderDependency: 10 AnySetup *Booklet\n"); + cupsFilePrintf(fp, "*%s.Translation Booklet/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Booklet"))); cupsFilePuts(fp, "*DefaultBooklet: False\n"); cupsFilePuts(fp, "*Booklet False: \"\"\n"); cupsFilePuts(fp, "*Booklet True: \"\"\n"); @@ -4018,16 +4111,19 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ cupsFilePrintf(fp, "*DefaultResolution: %ddpi\n", lowdpi); - cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality/%s: PickOne\n" - "*OrderDependency: 10 AnySetup *cupsPrintQuality\n" - "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality"))); + cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n" + "*OrderDependency: 10 AnySetup *cupsPrintQuality\n" + "*%s.Translation cupsPrintQuality/%s: \"\"\n" + "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality"))); if ((lowdpi & 1) == 0) - cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), lowdpi, lowdpi / 2); + cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", lowdpi, lowdpi / 2, lang->language, _cupsLangString(lang, _("Draft"))); else if (ippContainsInteger(quality, IPP_QUALITY_DRAFT)) - cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), lowdpi, lowdpi); - cupsFilePrintf(fp, "*cupsPrintQuality Normal/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Normal")), lowdpi, lowdpi); + cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", lowdpi, lowdpi, lang->language, _cupsLangString(lang, _("Draft"))); + + cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Normal/%s: \"\"\n", lowdpi, lowdpi, lang->language, _cupsLangString(lang, _("Normal"))); + if (hidpi > lowdpi || ippContainsInteger(quality, IPP_QUALITY_HIGH)) - cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), hidpi, hidpi); + cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality High/%s: \"\"\n", hidpi, hidpi, lang->language, _cupsLangString(lang, _("High"))); cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n"); } } @@ -4041,7 +4137,8 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ if (count > (int)(sizeof(resolutions) / sizeof(resolutions[0]))) count = (int)(sizeof(resolutions) / sizeof(resolutions[0])); - for (i = 0; i < count; i ++) + resolutions[0] = 0; /* Not in loop to silence Clang static analyzer... */ + for (i = 1; i < count; i ++) resolutions[i] = i; for (i = 0; i < (count - 1); i ++) @@ -4076,20 +4173,26 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, ppdname, sizeof(ppdname)); cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname); - cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality/%s: PickOne\n" - "*OrderDependency: 10 AnySetup *cupsPrintQuality\n" - "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality"))); + cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n" + "*OrderDependency: 10 AnySetup *cupsPrintQuality\n" + "*%s.Translation cupsPrintQuality/%s: \"\"\n" + "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality"))); if (count > 2 || ippContainsInteger(quality, IPP_QUALITY_DRAFT)) { pwg_ppdize_resolution(attr, resolutions[0], &xres, &yres, NULL, 0); - cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), xres, yres); + cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres); + cupsFilePrintf(fp, "*%s.cupsPrintQuality Draft/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Draft"))); } + pwg_ppdize_resolution(attr, resolutions[count / 2], &xres, &yres, NULL, 0); - cupsFilePrintf(fp, "*cupsPrintQuality Normal/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Normal")), xres, yres); + cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres); + cupsFilePrintf(fp, "*%s.cupsPrintQuality Normal/%s: \"\"\n", lang->language, _cupsLangString(lang, _("Normal"))); + if (count > 1 || ippContainsInteger(quality, IPP_QUALITY_HIGH)) { pwg_ppdize_resolution(attr, resolutions[count - 1], &xres, &yres, NULL, 0); - cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), xres, yres); + cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n", xres, yres); + cupsFilePrintf(fp, "*%s.cupsPrintQuality High/%s: \"\"\n", lang->language, _cupsLangString(lang, _("High"))); } cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n"); @@ -4110,14 +4213,17 @@ _ppdCreateFromIPP(char *buffer, /* I - Filename buffer */ cupsFilePrintf(fp, "*DefaultResolution: %s\n", ppdname); - cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality/%s: PickOne\n" + cupsFilePrintf(fp, "*OpenUI *cupsPrintQuality: PickOne\n" "*OrderDependency: 10 AnySetup *cupsPrintQuality\n" - "*DefaultcupsPrintQuality: Normal\n", _cupsLangString(lang, _("Print Quality"))); + "*%s.Translation cupsPrintQuality/%s: \"\"\n" + "*DefaultcupsPrintQuality: Normal\n", lang->language, _cupsLangString(lang, _("Print Quality"))); if (ippContainsInteger(quality, IPP_QUALITY_DRAFT)) - cupsFilePrintf(fp, "*cupsPrintQuality Draft/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Draft")), xres, yres); - cupsFilePrintf(fp, "*cupsPrintQuality Normal/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("Normal")), xres, yres); + cupsFilePrintf(fp, "*cupsPrintQuality Draft: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Draft/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("Draft"))); + + cupsFilePrintf(fp, "*cupsPrintQuality Normal: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality Normal/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("Normal"))); + if (ippContainsInteger(quality, IPP_QUALITY_HIGH)) - cupsFilePrintf(fp, "*cupsPrintQuality High/%s: \"<</HWResolution[%d %d]>>setpagedevice\"\n", _cupsLangString(lang, _("High")), xres, yres); + cupsFilePrintf(fp, "*cupsPrintQuality High: \"<</HWResolution[%d %d]>>setpagedevice\"\n*%s.cupsPrintQuality High/%s: \"\"\n", xres, yres, lang->language, _cupsLangString(lang, _("High"))); cupsFilePuts(fp, "*CloseUI: *cupsPrintQuality\n"); } diff --git a/cups/ppd-conflicts.c b/cups/ppd-conflicts.c index 8f875a57..24330ecb 100644 --- a/cups/ppd-conflicts.c +++ b/cups/ppd-conflicts.c @@ -1,7 +1,7 @@ /* * Option conflict management routines for CUPS. * - * Copyright 2007-2015 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -29,7 +29,6 @@ enum { - _PPD_NORMAL_CONSTRAINTS, _PPD_OPTION_CONSTRAINTS, _PPD_INSTALLABLE_CONSTRAINTS, _PPD_ALL_CONSTRAINTS @@ -998,7 +997,7 @@ ppd_test_constraints( if (!consts->installable && which == _PPD_INSTALLABLE_CONSTRAINTS) continue; /* Skip non-installable option constraint */ - if (which == _PPD_OPTION_CONSTRAINTS && option) + if ((which == _PPD_OPTION_CONSTRAINTS || which == _PPD_INSTALLABLE_CONSTRAINTS) && option) { /* * Skip constraints that do not involve the current option... diff --git a/cups/ppd-emit.c b/cups/ppd-emit.c index 36e5bcaf..4b153aca 100644 --- a/cups/ppd-emit.c +++ b/cups/ppd-emit.c @@ -21,11 +21,11 @@ #include "cups-private.h" #include "ppd.h" -#if defined(WIN32) || defined(__EMX__) +#if defined(_WIN32) || defined(__EMX__) # include <io.h> #else # include <unistd.h> -#endif /* WIN32 || __EMX__ */ +#endif /* _WIN32 || __EMX__ */ /* @@ -328,11 +328,11 @@ ppdEmitFd(ppd_file_t *ppd, /* I - PPD file record */ while (buflength > 0) { -#ifdef WIN32 +#ifdef _WIN32 if ((bytes = (ssize_t)write(fd, bufptr, (unsigned)buflength)) < 0) #else if ((bytes = write(fd, bufptr, buflength)) < 0) -#endif /* WIN32 */ +#endif /* _WIN32 */ { if (errno == EAGAIN || errno == EINTR) continue; diff --git a/cups/ppd-localize.c b/cups/ppd-localize.c index ed75bf86..9537ef5b 100644 --- a/cups/ppd-localize.c +++ b/cups/ppd-localize.c @@ -1,7 +1,7 @@ /* * PPD localization routines for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -277,7 +277,7 @@ ppdLocalizeIPPReason( if (!locattr) { - if (lang && (!scheme || !strcmp(scheme, "text"))) + if (lang && (!scheme || !strcmp(scheme, "text")) && strcmp(reason, "none")) { /* * Try to localize a standard printer-state-reason keyword... diff --git a/cups/ppd-util.c b/cups/ppd-util.c index d0194c80..0974bae9 100644 --- a/cups/ppd-util.c +++ b/cups/ppd-util.c @@ -1,8 +1,8 @@ /* * PPD utilities for CUPS. * - * Copyright 2007-2015 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -21,11 +21,11 @@ #include "ppd-private.h" #include <fcntl.h> #include <sys/stat.h> -#if defined(WIN32) || defined(__EMX__) +#if defined(_WIN32) || defined(__EMX__) # include <io.h> #else # include <unistd.h> -#endif /* WIN32 || __EMX__ */ +#endif /* _WIN32 || __EMX__ */ /* @@ -171,7 +171,7 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL return (HTTP_STATUS_NOT_ACCEPTABLE); } -#ifndef WIN32 +#ifndef _WIN32 /* * See if the PPD file is available locally... */ @@ -216,6 +216,27 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL const char *tmpdir; /* TMPDIR environment variable */ struct timeval curtime; /* Current time */ +#ifdef __APPLE__ + /* + * On macOS and iOS, the TMPDIR environment variable is not always the + * best location to place temporary files due to sandboxing. Instead, + * the confstr function should be called to get the proper per-user, + * per-process TMPDIR value. + */ + + char tmppath[1024]; /* Temporary directory */ + + if ((tmpdir = getenv("TMPDIR")) != NULL && access(tmpdir, W_OK)) + tmpdir = NULL; + + if (!tmpdir) + { + if (confstr(_CS_DARWIN_USER_TEMP_DIR, tmppath, sizeof(tmppath))) + tmpdir = tmppath; + else + tmpdir = "/private/tmp"; /* This should never happen */ + } +#else /* * Previously we put root temporary files in the default CUPS temporary * directory under /var/spool/cups. However, since the scheduler cleans @@ -224,11 +245,8 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL */ if ((tmpdir = getenv("TMPDIR")) == NULL) -# ifdef __APPLE__ - tmpdir = "/private/tmp"; /* /tmp is a symlink to /private/tmp */ -# else - tmpdir = "/tmp"; -# endif /* __APPLE__ */ + tmpdir = "/tmp"; +#endif /* __APPLE__ */ /* * Make the temporary name using the specified directory... @@ -280,7 +298,7 @@ cupsGetPPD3(http_t *http, /* I - HTTP connection or @code CUPS_HTTP_DEFAUL } } } -#endif /* !WIN32 */ +#endif /* !_WIN32 */ /* * Try finding a printer URI for this printer... @@ -511,23 +529,16 @@ cups_get_printer_uri( int depth) /* I - Depth of query */ { int i; /* Looping var */ - int http_port; /* Port number */ - http_t *http2; /* Alternate HTTP connection */ ipp_t *request, /* IPP request */ *response; /* IPP response */ ipp_attribute_t *attr; /* Current attribute */ char uri[HTTP_MAX_URI], /* printer-uri attribute */ scheme[HTTP_MAX_URI], /* Scheme name */ - username[HTTP_MAX_URI], /* Username:password */ - classname[255], /* Temporary class name */ - http_hostname[HTTP_MAX_HOST]; - /* Hostname associated with connection */ + username[HTTP_MAX_URI]; /* Username:password */ static const char * const requested_attrs[] = { /* Requested attributes */ - "device-uri", "member-uris", - "printer-uri-supported", - "printer-type" + "printer-uri-supported" }; @@ -550,15 +561,6 @@ cups_get_printer_uri( DEBUG_printf(("5cups_get_printer_uri: printer-uri=\"%s\"", uri)); /* - * Get the hostname and port number we are connected to... - */ - - httpGetHostname(http, http_hostname, sizeof(http_hostname)); - http_port = httpAddrPort(http->hostaddr); - - DEBUG_printf(("5cups_get_printer_uri: http_hostname=\"%s\"", http_hostname)); - - /* * Build an IPP_GET_PRINTER_ATTRIBUTES request, which requires the following * attributes: * @@ -582,31 +584,7 @@ cups_get_printer_uri( if ((response = cupsDoRequest(http, request, resource)) != NULL) { - const char *device_uri = NULL; /* device-uri value */ - - if ((attr = ippFindAttribute(response, "device-uri", IPP_TAG_URI)) != NULL) - { - device_uri = attr->values[0].string.text; - DEBUG_printf(("5cups_get_printer_uri: device-uri=\"%s\"", device_uri)); - } - - if (device_uri && - (((!strncmp(device_uri, "ipp://", 6) || !strncmp(device_uri, "ipps://", 7)) && - (strstr(device_uri, "/printers/") != NULL || strstr(device_uri, "/classes/") != NULL)) || - ((strstr(device_uri, "._ipp.") != NULL || strstr(device_uri, "._ipps.") != NULL) && - !strcmp(device_uri + strlen(device_uri) - 5, "/cups")))) - { - /* - * Statically-configured shared printer. - */ - - httpSeparateURI(HTTP_URI_CODING_ALL, _httpResolveURI(device_uri, uri, sizeof(uri), _HTTP_RESOLVE_DEFAULT, NULL, NULL), scheme, sizeof(scheme), username, sizeof(username), host, hostsize, port, resource, resourcesize); - ippDelete(response); - - DEBUG_printf(("5cups_get_printer_uri: Resolved to host=\"%s\", port=%d, resource=\"%s\"", host, *port, resource)); - return (1); - } - else if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL) + if ((attr = ippFindAttribute(response, "member-uris", IPP_TAG_URI)) != NULL) { /* * Get the first actual printer name in the class... @@ -631,55 +609,6 @@ cups_get_printer_uri( return (1); } } - - /* - * No printers in this class - try recursively looking for a printer, - * but not more than 3 levels deep... - */ - - if (depth < 3) - { - for (i = 0; i < attr->num_values; i ++) - { - httpSeparateURI(HTTP_URI_CODING_ALL, attr->values[i].string.text, - scheme, sizeof(scheme), username, sizeof(username), - host, hostsize, port, resource, resourcesize); - if (!strncmp(resource, "/classes/", 9)) - { - /* - * Found a class! Connect to the right server... - */ - - if (!_cups_strcasecmp(http_hostname, host) && *port == http_port) - http2 = http; - else if ((http2 = httpConnect2(host, *port, NULL, AF_UNSPEC, cupsEncryption(), 1, 30000, NULL)) == NULL) - { - DEBUG_puts("8cups_get_printer_uri: Unable to connect to server"); - - continue; - } - - /* - * Look up printers on that server... - */ - - strlcpy(classname, resource + 9, sizeof(classname)); - - cups_get_printer_uri(http2, classname, host, hostsize, port, - resource, resourcesize, depth + 1); - - /* - * Close the connection as needed... - */ - - if (http2 != http) - httpClose(http2); - - if (*host) - return (1); - } - } - } } else if ((attr = ippFindAttribute(response, "printer-uri-supported", IPP_TAG_URI)) != NULL) { @@ -1,7 +1,7 @@ /* * PPD file routines for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the @@ -94,9 +94,9 @@ static ppd_group_t *ppd_get_group(ppd_file_t *ppd, const char *name, cups_encoding_t encoding); static ppd_option_t *ppd_get_option(ppd_group_t *group, const char *name); static _ppd_globals_t *ppd_globals_alloc(void); -#if defined(HAVE_PTHREAD_H) || defined(WIN32) +#if defined(HAVE_PTHREAD_H) || defined(_WIN32) static void ppd_globals_free(_ppd_globals_t *g); -#endif /* HAVE_PTHREAD_H || WIN32 */ +#endif /* HAVE_PTHREAD_H || _WIN32 */ #ifdef HAVE_PTHREAD_H static void ppd_globals_init(void); #endif /* HAVE_PTHREAD_H */ @@ -333,7 +333,9 @@ ppdErrorString(ppd_status_t status) /* I - PPD status */ _("Bad custom parameter"), _("Missing option keyword"), _("Bad value string"), - _("Missing CloseGroup") + _("Missing CloseGroup"), + _("Bad CloseUI/JCLCloseUI"), + _("Missing CloseUI/JCLCloseUI") }; @@ -1542,8 +1544,29 @@ _ppdOpen( choice->code = _cupsStrRetain(custom_attr->value); } } - else if (!strcmp(keyword, "CloseUI") || !strcmp(keyword, "JCLCloseUI")) + else if (!strcmp(keyword, "CloseUI")) { + if ((!option || option->section == PPD_ORDER_JCL) && pg->ppd_conform == PPD_CONFORM_STRICT) + { + pg->ppd_status = PPD_BAD_CLOSE_UI; + + goto error; + } + + option = NULL; + + _cupsStrFree(string); + string = NULL; + } + else if (!strcmp(keyword, "JCLCloseUI")) + { + if ((!option || option->section != PPD_ORDER_JCL) && pg->ppd_conform == PPD_CONFORM_STRICT) + { + pg->ppd_status = PPD_BAD_CLOSE_UI; + + goto error; + } + option = NULL; _cupsStrFree(string); @@ -2007,6 +2030,16 @@ _ppdOpen( } /* + * Check for a missing CloseUI/JCLCloseUI... + */ + + if (option && pg->ppd_conform == PPD_CONFORM_STRICT) + { + pg->ppd_status = PPD_MISSING_CLOSE_UI; + goto error; + } + + /* * Check for a missing CloseGroup... */ @@ -2804,13 +2837,13 @@ ppd_globals_alloc(void) * 'ppd_globals_free()' - Free global data. */ -#if defined(HAVE_PTHREAD_H) || defined(WIN32) +#if defined(HAVE_PTHREAD_H) || defined(_WIN32) static void ppd_globals_free(_ppd_globals_t *pg) /* I - Pointer to global data */ { free(pg); } -#endif /* HAVE_PTHREAD_H || WIN32 */ +#endif /* HAVE_PTHREAD_H || _WIN32 */ #ifdef HAVE_PTHREAD_H @@ -132,6 +132,8 @@ typedef enum ppd_status_e /**** Status Codes @since CUPS 1.1.19/macOS 10.3@ *** PPD_MISSING_OPTION_KEYWORD, /* Missing option keyword */ PPD_BAD_VALUE, /* Bad value string */ PPD_MISSING_CLOSE_GROUP, /* Missing CloseGroup */ + PPD_BAD_CLOSE_UI, /* Bad CloseUI/JCLCloseUI */ + PPD_MISSING_CLOSE_UI, /* Missing CloseUI/JCLCloseUI */ PPD_MAX_STATUS /* @private@ */ } ppd_status_t; diff --git a/cups/raster-private.h b/cups/raster-private.h index 38135815..94dd951c 100644 --- a/cups/raster-private.h +++ b/cups/raster-private.h @@ -1,7 +1,7 @@ /* * Private image library definitions for CUPS. * - * Copyright 2007-2015 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1993-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -24,13 +24,13 @@ # include <cups/cups.h> # include <cups/debug-private.h> # include <cups/string-private.h> -# ifdef WIN32 +# ifdef _WIN32 # include <io.h> # include <winsock2.h> /* for htonl() definition */ # else # include <unistd.h> # include <fcntl.h> -# endif /* WIN32 */ +# endif /* _WIN32 */ /* @@ -49,12 +49,8 @@ * Prototypes... */ -extern int _cupsRasterExecPS(cups_page_header2_t *h, - int *preferred_bits, - const char *code) - __attribute__((nonnull(3))); -extern void _cupsRasterAddError(const char *f, ...) - __attribute__((__format__(__printf__, 1, 2))); +extern int _cupsRasterExecPS(cups_page_header2_t *h, int *preferred_bits, const char *code) _CUPS_NONNULL((3)); +extern void _cupsRasterAddError(const char *f, ...) _CUPS_FORMAT(1,2); extern void _cupsRasterClearError(void); #endif /* !_CUPS_RASTER_PRIVATE_H_ */ diff --git a/cups/request.c b/cups/request.c index efbc06eb..a4e4b905 100644 --- a/cups/request.c +++ b/cups/request.c @@ -20,11 +20,11 @@ #include "cups-private.h" #include <fcntl.h> #include <sys/stat.h> -#if defined(WIN32) || defined(__EMX__) +#if defined(_WIN32) || defined(__EMX__) # include <io.h> #else # include <unistd.h> -#endif /* WIN32 || __EMX__ */ +#endif /* _WIN32 || __EMX__ */ #ifndef O_BINARY # define O_BINARY 0 #endif /* O_BINARY */ @@ -156,11 +156,11 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP return (NULL); } -#ifdef WIN32 +#ifdef _WIN32 if (fileinfo.st_mode & _S_IFDIR) #else if (S_ISDIR(fileinfo.st_mode)) -#endif /* WIN32 */ +#endif /* _WIN32 */ { /* * Can't send a directory... @@ -172,11 +172,11 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP return (NULL); } -#ifndef WIN32 +#ifndef _WIN32 if (!S_ISREG(fileinfo.st_mode)) length = 0; /* Chunk when piping */ else -#endif /* !WIN32 */ +#endif /* !_WIN32 */ length = ippLength(request) + (size_t)fileinfo.st_size; } else @@ -215,9 +215,9 @@ cupsDoIORequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP * Send the file with the request... */ -#ifndef WIN32 +#ifndef _WIN32 if (S_ISREG(fileinfo.st_mode)) -#endif /* WIN32 */ +#endif /* _WIN32 */ lseek(infile, 0, SEEK_SET); while ((bytes = read(infile, buffer, sizeof(buffer))) > 0) @@ -591,7 +591,8 @@ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP int got_status; /* Did we get the status? */ ipp_state_t state; /* State of IPP processing */ http_status_t expect; /* Expect: header to use */ - char date[256]; /* Date: header value */ + char date[256]; /* Date: header value */ + int digest; /* Are we using Digest authentication? */ DEBUG_printf(("cupsSendRequest(http=%p, request=%p(%s), resource=\"%s\", length=" CUPS_LLFMT ")", (void *)http, (void *)request, request ? ippOpString(request->request.op.operation_id) : "?", resource, CUPS_LLCAST length)); @@ -683,6 +684,17 @@ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP httpSetField(http, HTTP_FIELD_DATE, httpGetDateString2(time(NULL), date, (int)sizeof(date))); httpSetLength(http, length); + digest = http->authstring && !strncmp(http->authstring, "Digest ", 7); + + if (digest) + { + /* + * Update the Digest authentication string... + */ + + _httpSetDigestAuthString(http, http->nextnonce, "POST", resource); + } + #ifdef HAVE_GSSAPI if (http->authstring && !strncmp(http->authstring, "Negotiate", 9)) { @@ -767,9 +779,9 @@ cupsSendRequest(http_t *http, /* I - Connection to server or @code CUPS_HTTP * Wait up to 1 second to get the 100-continue response as needed... */ - if (!got_status) + if (!got_status || (digest && status == HTTP_STATUS_CONTINUE)) { - if (expect == HTTP_STATUS_CONTINUE) + if (expect == HTTP_STATUS_CONTINUE || digest) { DEBUG_puts("2cupsSendRequest: Waiting for 100-continue..."); @@ -1016,13 +1028,13 @@ _cupsConnect(void) char ch; /* Connection check byte */ ssize_t n; /* Number of bytes */ -#ifdef WIN32 +#ifdef _WIN32 if ((n = recv(cg->http->fd, &ch, 1, MSG_PEEK)) == 0 || (n < 0 && WSAGetLastError() != WSAEWOULDBLOCK)) #else if ((n = recv(cg->http->fd, &ch, 1, MSG_PEEK | MSG_DONTWAIT)) == 0 || (n < 0 && errno != EWOULDBLOCK)) -#endif /* WIN32 */ +#endif /* _WIN32 */ { /* * Nope, close the connection... diff --git a/cups/sidechannel.c b/cups/sidechannel.c index a4cd960a..f2dbabd6 100644 --- a/cups/sidechannel.c +++ b/cups/sidechannel.c @@ -19,15 +19,15 @@ #include "sidechannel.h" #include "cups-private.h" -#ifdef WIN32 +#ifdef _WIN32 # include <io.h> #else # include <unistd.h> -#endif /* WIN32 */ -#ifndef WIN32 +#endif /* _WIN32 */ +#ifndef _WIN32 # include <sys/select.h> # include <sys/time.h> -#endif /* !WIN32 */ +#endif /* !_WIN32 */ #ifdef HAVE_POLL # include <poll.h> #endif /* HAVE_POLL */ diff --git a/cups/snmp.c b/cups/snmp.c index 7958b93e..8437528d 100644 --- a/cups/snmp.c +++ b/cups/snmp.c @@ -395,11 +395,11 @@ _cupsSNMPRead(int fd, /* I - SNMP socket file descriptor */ ready = select(fd + 1, &input_set, NULL, NULL, &stimeout); } -# ifdef WIN32 +# ifdef _WIN32 while (ready < 0 && WSAGetLastError() == WSAEINTR); # else while (ready < 0 && (errno == EINTR || errno == EAGAIN)); -# endif /* WIN32 */ +# endif /* _WIN32 */ #endif /* HAVE_POLL */ /* diff --git a/cups/string-private.h b/cups/string-private.h index e8448d17..ced24923 100644 --- a/cups/string-private.h +++ b/cups/string-private.h @@ -1,7 +1,7 @@ /* * Private string definitions for CUPS. * - * Copyright 2007-2015 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -42,12 +42,12 @@ # include <bstring.h> # endif /* HAVE_BSTRING_H */ -# if defined(WIN32) && !defined(__CUPS_SSIZE_T_DEFINED) +# if defined(_WIN32) && !defined(__CUPS_SSIZE_T_DEFINED) # define __CUPS_SSIZE_T_DEFINED # include <stddef.h> /* Windows does not support the ssize_t type, so map it to long... */ typedef long ssize_t; /* @private@ */ -# endif /* WIN32 && !__CUPS_SSIZE_T_DEFINED */ +# endif /* _WIN32 && !__CUPS_SSIZE_T_DEFINED */ /* @@ -175,8 +175,7 @@ extern size_t _cups_strlcpy(char *, const char *, size_t); # endif /* !HAVE_STRLCPY */ # ifndef HAVE_SNPRINTF -extern int _cups_snprintf(char *, size_t, const char *, ...) - __attribute__ ((__format__ (__printf__, 3, 4))); +extern int _cups_snprintf(char *, size_t, const char *, ...) _CUPS_FORMAT(3, 4); # define snprintf _cups_snprintf # endif /* !HAVE_SNPRINTF */ diff --git a/cups/tempfile.c b/cups/tempfile.c index da705a94..7b341e13 100644 --- a/cups/tempfile.c +++ b/cups/tempfile.c @@ -1,8 +1,8 @@ /* * Temp file utilities for CUPS. * - * Copyright 2007-2014 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -21,11 +21,11 @@ #include <stdlib.h> #include <fcntl.h> #include <sys/stat.h> -#if defined(WIN32) || defined(__EMX__) +#if defined(_WIN32) || defined(__EMX__) # include <io.h> #else # include <unistd.h> -#endif /* WIN32 || __EMX__ */ +#endif /* _WIN32 || __EMX__ */ /* @@ -42,24 +42,46 @@ cupsTempFd(char *filename, /* I - Pointer to buffer */ int fd; /* File descriptor for temp file */ int tries; /* Number of tries */ const char *tmpdir; /* TMPDIR environment var */ -#ifdef WIN32 - char tmppath[1024]; /* Windows temporary directory */ +#if defined(__APPLE__) || defined(_WIN32) + char tmppath[1024]; /* Temporary directory */ +#endif /* __APPLE__ || _WIN32 */ +#ifdef _WIN32 DWORD curtime; /* Current time */ #else struct timeval curtime; /* Current time */ -#endif /* WIN32 */ +#endif /* _WIN32 */ /* * See if TMPDIR is defined... */ -#ifdef WIN32 +#ifdef _WIN32 if ((tmpdir = getenv("TEMP")) == NULL) { GetTempPath(sizeof(tmppath), tmppath); tmpdir = tmppath; } + +#elif defined(__APPLE__) + /* + * On macOS and iOS, the TMPDIR environment variable is not always the best + * location to place temporary files due to sandboxing. Instead, the confstr + * function should be called to get the proper per-user, per-process TMPDIR + * value. + */ + + if ((tmpdir = getenv("TMPDIR")) != NULL && access(tmpdir, W_OK)) + tmpdir = NULL; + + if (!tmpdir) + { + if (confstr(_CS_DARWIN_USER_TEMP_DIR, tmppath, sizeof(tmppath))) + tmpdir = tmppath; + else + tmpdir = "/private/tmp"; /* This should never happen */ + } + #else /* * Previously we put root temporary files in the default CUPS temporary @@ -69,12 +91,8 @@ cupsTempFd(char *filename, /* I - Pointer to buffer */ */ if ((tmpdir = getenv("TMPDIR")) == NULL) -# if defined(__APPLE__) && !TARGET_OS_IOS - tmpdir = "/private/tmp"; /* /tmp is a symlink to /private/tmp */ -# else tmpdir = "/tmp"; -# endif /* __APPLE__ && !TARGET_OS_IOS */ -#endif /* WIN32 */ +#endif /* _WIN32 */ /* * Make the temporary name using the specified directory... @@ -84,7 +102,7 @@ cupsTempFd(char *filename, /* I - Pointer to buffer */ do { -#ifdef WIN32 +#ifdef _WIN32 /* * Get the current time of day... */ @@ -108,21 +126,21 @@ cupsTempFd(char *filename, /* I - Pointer to buffer */ */ snprintf(filename, (size_t)len - 1, "%s/%05x%08x", tmpdir, (unsigned)getpid(), (unsigned)(curtime.tv_sec + curtime.tv_usec + tries)); -#endif /* WIN32 */ +#endif /* _WIN32 */ /* * Open the file in "exclusive" mode, making sure that we don't * stomp on an existing file or someone's symlink crack... */ -#ifdef WIN32 +#ifdef _WIN32 fd = open(filename, _O_CREAT | _O_RDWR | _O_TRUNC | _O_BINARY, _S_IREAD | _S_IWRITE); #elif defined(O_NOFOLLOW) fd = open(filename, O_RDWR | O_CREAT | O_EXCL | O_NOFOLLOW, 0600); #else fd = open(filename, O_RDWR | O_CREAT | O_EXCL, 0600); -#endif /* WIN32 */ +#endif /* _WIN32 */ if (fd < 0 && errno != EEXIST) break; diff --git a/cups/testarray.c b/cups/testarray.c index 6164ffc6..892e3250 100644 --- a/cups/testarray.c +++ b/cups/testarray.c @@ -494,7 +494,7 @@ main(void) * 'get_seconds()' - Get the current time in seconds... */ -#ifdef WIN32 +#ifdef _WIN32 # include <windows.h> @@ -515,7 +515,7 @@ get_seconds(void) gettimeofday(&curtime, NULL); return (curtime.tv_sec + 0.000001 * curtime.tv_usec); } -#endif /* WIN32 */ +#endif /* _WIN32 */ /* diff --git a/cups/testdest.c b/cups/testdest.c index c5c20528..9eab8d2e 100644 --- a/cups/testdest.c +++ b/cups/testdest.c @@ -1,7 +1,7 @@ /* * CUPS destination API test program for CUPS. * - * Copyright 2012-2017 by Apple Inc. + * Copyright 2012-2018 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -32,7 +32,7 @@ static void show_conflicts(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, static void show_default(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option); static void show_media(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, unsigned flags, const char *name); static void show_supported(http_t *http, cups_dest_t *dest, cups_dinfo_t *dinfo, const char *option, const char *value); -static void usage(const char *arg) __attribute__((noreturn)); +static void usage(const char *arg) _CUPS_NORETURN; /* diff --git a/cups/testfile.c b/cups/testfile.c index b2ec8cd5..1473a4a0 100644 --- a/cups/testfile.c +++ b/cups/testfile.c @@ -1,7 +1,7 @@ /* * File test program for CUPS. * - * Copyright 2007-2015 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -22,14 +22,11 @@ #include "file.h" #include <stdlib.h> #include <time.h> -#ifdef HAVE_LIBZ -# include <zlib.h> -#endif /* HAVE_LIBZ */ -#ifdef WIN32 +#ifdef _WIN32 # include <io.h> #else # include <unistd.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ #include <fcntl.h> @@ -53,10 +50,10 @@ main(int argc, /* I - Number of command-line arguments */ int status; /* Exit status */ char filename[1024]; /* Filename buffer */ cups_file_t *fp; /* File pointer */ -#ifndef WIN32 +#ifndef _WIN32 int fds[2]; /* Open file descriptors */ cups_file_t *fdfile; /* File opened with cupsFileOpenFd() */ -#endif /* !WIN32 */ +#endif /* !_WIN32 */ int count; /* Number of lines in file */ @@ -84,7 +81,7 @@ main(int argc, /* I - Number of command-line arguments */ status += random_tests(); -#ifndef WIN32 +#ifndef _WIN32 /* * Test fdopen and close without reading... */ @@ -118,7 +115,7 @@ main(int argc, /* I - Number of command-line arguments */ puts("PASS"); } -#endif /* !WIN32 */ +#endif /* !_WIN32 */ /* * Count lines in psglyphs, rewind, then count again. @@ -174,13 +171,13 @@ main(int argc, /* I - Number of command-line arguments */ */ fputs("\ncupsFileFind: ", stdout); -#ifdef WIN32 +#ifdef _WIN32 if (cupsFileFind("notepad.exe", "C:/WINDOWS", 1, filename, sizeof(filename)) && cupsFileFind("notepad.exe", "C:/WINDOWS;C:/WINDOWS/SYSTEM32", 1, filename, sizeof(filename))) #else if (cupsFileFind("cat", "/bin", 1, filename, sizeof(filename)) && cupsFileFind("cat", "/bin:/usr/bin", 1, filename, sizeof(filename))) -#endif /* WIN32 */ +#endif /* _WIN32 */ printf("PASS (%s)\n", filename); else { diff --git a/cups/testhttp.c b/cups/testhttp.c index 376d71f6..7d8ec06d 100644 --- a/cups/testhttp.c +++ b/cups/testhttp.c @@ -1,8 +1,8 @@ /* * HTTP test program for CUPS. * - * Copyright 2007-2014 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -120,6 +120,9 @@ static uri_test_t uri_tests[] = /* URI test data */ { HTTP_URI_STATUS_OK, "ipp://%22%23%2F%3A%3C%3E%3F%40%5B%5C%5D%5E%60%7B%7C%7D/", "ipp", "", "\"#/:<>?@[\\]^`{|}", "/", 631, 0, HTTP_URI_CODING_MOST }, + { HTTP_URI_STATUS_UNKNOWN_SCHEME, "smb://server/Some%20Printer", + "smb", "", "server", "/Some Printer", 0, 0, + HTTP_URI_CODING_ALL }, /* Missing scheme */ { HTTP_URI_STATUS_MISSING_SCHEME, "/path/to/file/index.html", @@ -148,6 +151,9 @@ static uri_test_t uri_tests[] = /* URI test data */ HTTP_URI_CODING_MOST }, /* Bad scheme */ + { HTTP_URI_STATUS_BAD_SCHEME, "://server/ipp", + "", "", "", "", 0, 0, + HTTP_URI_CODING_MOST }, { HTTP_URI_STATUS_BAD_SCHEME, "bad_scheme://server/resource", "", "", "", "", 0, 0, HTTP_URI_CODING_MOST }, @@ -180,6 +186,9 @@ static uri_test_t uri_tests[] = /* URI test data */ HTTP_URI_CODING_MOST }, /* Bad resource */ + { HTTP_URI_STATUS_BAD_RESOURCE, "mailto:\r\nbla", + "mailto", "", "", "", 0, 0, + HTTP_URI_CODING_MOST }, { HTTP_URI_STATUS_BAD_RESOURCE, "http://server/index.html%", "http", "", "server", "", 80, 0, HTTP_URI_CODING_MOST }, @@ -332,6 +341,40 @@ main(int argc, /* I - Number of command-line arguments */ if (!j) puts("PASS"); +#if 0 + /* + * _httpDigest() + */ + + fputs("_httpDigest(MD5): ", stdout); + if (!_httpDigest(buffer, sizeof(buffer), "MD5", "Mufasa", "http-auth@example.org", "Circle of Life", "7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", 1, "f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ", "auth", "GET", "/dir/index.html")) + { + failures ++; + puts("FAIL (unable to calculate hash)"); + } + else if (strcmp(buffer, "8ca523f5e9506fed4657c9700eebdbec")) + { + failures ++; + printf("FAIL (got \"%s\", expected \"8ca523f5e9506fed4657c9700eebdbec\")\n", buffer); + } + else + puts("PASS"); + + fputs("_httpDigest(SHA-256): ", stdout); + if (!_httpDigest(buffer, sizeof(buffer), "SHA-256", "Mufasa", "http-auth@example.org", "Circle of Life", "7ypf/xlj9XXwfDPEoM4URrv/xwf94BcCAzFZH4GiTo0v", 1, "f2/wE4q74E6zIJEtWaHKaf5wv/H5QzzpXusqGemxURZJ", "auth", "GET", "/dir/index.html")) + { + failures ++; + puts("FAIL (unable to calculate hash)"); + } + else if (strcmp(buffer, "753927fa0e85d155564e2e272a28d1802ca10daf4496794697cf8db5856cb6c1")) + { + failures ++; + printf("FAIL (got \"%s\", expected \"753927fa0e85d155564e2e272a28d1802ca10daf4496794697cf8db5856cb6c1\")\n", buffer); + } + else + puts("PASS"); +#endif /* 0 */ + /* * httpGetHostname() */ @@ -590,6 +633,8 @@ main(int argc, /* I - Number of command-line arguments */ for (i = 1; i < argc; i ++) { + int new_auth; + if (!strcmp(argv[i], "-o")) { i ++; @@ -673,6 +718,8 @@ main(int argc, /* I - Number of command-line arguments */ printf("Checking file \"%s\"...\n", resource); + new_auth = 0; + do { if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close")) @@ -685,9 +732,13 @@ main(int argc, /* I - Number of command-line arguments */ } } + if (http->authstring && !strncmp(http->authstring, "Digest ", 7) && !new_auth) + _httpSetDigestAuthString(http, http->nextnonce, "HEAD", resource); + httpClearFields(http); httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http)); httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); + if (httpHead(http, resource)) { if (httpReconnect2(http, 30000, NULL)) @@ -704,6 +755,8 @@ main(int argc, /* I - Number of command-line arguments */ while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); + new_auth = 0; + if (status == HTTP_STATUS_UNAUTHORIZED) { /* @@ -716,7 +769,9 @@ main(int argc, /* I - Number of command-line arguments */ * See if we can do authentication... */ - if (cupsDoAuthentication(http, "GET", resource)) + new_auth = 1; + + if (cupsDoAuthentication(http, "HEAD", resource)) { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; break; @@ -764,6 +819,8 @@ main(int argc, /* I - Number of command-line arguments */ printf("Requesting file \"%s\" (Accept-Encoding: %s)...\n", resource, encoding ? encoding : "identity"); + new_auth = 0; + do { if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close")) @@ -776,6 +833,9 @@ main(int argc, /* I - Number of command-line arguments */ } } + if (http->authstring && !strncmp(http->authstring, "Digest ", 7) && !new_auth) + _httpSetDigestAuthString(http, http->nextnonce, "GET", resource); + httpClearFields(http); httpSetField(http, HTTP_FIELD_AUTHORIZATION, httpGetAuthString(http)); httpSetField(http, HTTP_FIELD_ACCEPT_LANGUAGE, "en"); @@ -797,6 +857,8 @@ main(int argc, /* I - Number of command-line arguments */ while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE); + new_auth = 0; + if (status == HTTP_STATUS_UNAUTHORIZED) { /* @@ -809,6 +871,8 @@ main(int argc, /* I - Number of command-line arguments */ * See if we can do authentication... */ + new_auth = 1; + if (cupsDoAuthentication(http, "GET", resource)) { status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED; diff --git a/cups/testipp.c b/cups/testipp.c index ea8f9d78..2ef2496e 100644 --- a/cups/testipp.c +++ b/cups/testipp.c @@ -20,12 +20,12 @@ #include "file.h" #include "string-private.h" #include "ipp-private.h" -#ifdef WIN32 +#ifdef _WIN32 # include <io.h> #else # include <unistd.h> # include <fcntl.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ /* diff --git a/cups/testppd.c b/cups/testppd.c index e1b51564..a127a794 100644 --- a/cups/testppd.c +++ b/cups/testppd.c @@ -21,12 +21,12 @@ #include "cups-private.h" #include "ppd-private.h" #include <sys/stat.h> -#ifdef WIN32 +#ifdef _WIN32 # include <io.h> #else # include <unistd.h> # include <fcntl.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ #include <math.h> @@ -876,6 +876,13 @@ main(int argc, /* I - Number of command-line arguments */ host[256], /* Hostname */ resource[256]; /* Resource path */ int port; /* Port number */ + static const char * const pattrs[] =/* Requested printer attributes */ + { + "job-template", + "printer-defaults", + "printer-description", + "media-col-database" + }; if (httpSeparateURI(HTTP_URI_CODING_ALL, argv[1], scheme, sizeof(scheme), userpass, sizeof(userpass), host, sizeof(host), &port, resource, sizeof(resource)) < HTTP_URI_STATUS_OK) { @@ -892,6 +899,7 @@ main(int argc, /* I - Number of command-line arguments */ request = ippNewRequest(IPP_OP_GET_PRINTER_ATTRIBUTES); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, argv[1]); + ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD, "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]), NULL, pattrs); response = cupsDoRequest(http, request, resource); if (_ppdCreateFromIPP(buffer, sizeof(buffer), response)) diff --git a/cups/testsnmp.c b/cups/testsnmp.c index 4026a28b..9e168ab7 100644 --- a/cups/testsnmp.c +++ b/cups/testsnmp.c @@ -1,7 +1,7 @@ /* * SNMP test program for CUPS. * - * Copyright 2008-2014 by Apple Inc. + * Copyright 2008-2018 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -27,7 +27,7 @@ static void print_packet(cups_snmp_t *packet, void *data); static int show_oid(int fd, const char *community, http_addr_t *addr, const char *s, int walk); -static void usage(void) __attribute__((noreturn)); +static void usage(void) _CUPS_NORETURN; /* diff --git a/cups/thread-private.h b/cups/thread-private.h index 79d24386..ae8163d1 100644 --- a/cups/thread-private.h +++ b/cups/thread-private.h @@ -46,7 +46,7 @@ typedef pthread_key_t _cups_threadkey_t; # define _cupsThreadGetData(k) pthread_getspecific(k) # define _cupsThreadSetData(k,p) pthread_setspecific(k,p) -# elif defined(WIN32) /* Windows threading */ +# elif defined(_WIN32) /* Windows threading */ # include <winsock2.h> # include <windows.h> typedef void *(__stdcall *_cups_thread_func_t)(void *arg); diff --git a/cups/thread.c b/cups/thread.c index 65257aa1..7ffc2ec0 100644 --- a/cups/thread.c +++ b/cups/thread.c @@ -1,7 +1,7 @@ /* * Threading primitives for CUPS. * - * Copyright 2009-2017 by Apple Inc. + * Copyright © 2009-2018 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -56,8 +56,16 @@ _cupsCondWait(_cups_cond_t *cond, /* I - Condition */ { struct timespec abstime; /* Timeout */ - abstime.tv_sec = (long)timeout; - abstime.tv_nsec = (long)(1000000000 * (timeout - (long)timeout)); + clock_gettime(CLOCK_REALTIME, &abstime); + + abstime.tv_sec += (long)timeout; + abstime.tv_nsec += (long)(1000000000 * (timeout - (long)timeout)); + + while (abstime.tv_nsec >= 1000000000) + { + abstime.tv_nsec -= 1000000000; + abstime.tv_sec ++; + }; pthread_cond_timedwait(cond, mutex, &abstime); } @@ -200,7 +208,7 @@ _cupsThreadWait(_cups_thread_t thread) /* I - Thread ID */ } -#elif defined(WIN32) +#elif defined(_WIN32) # include <process.h> @@ -513,8 +521,7 @@ _cupsThreadCreate( _cups_thread_func_t func, /* I - Entry point */ void *arg) /* I - Entry point context */ { - fputs("DEBUG: CUPS was compiled without threading support, no thread " - "created.\n", stderr); + fputs("DEBUG: CUPS was compiled without threading support, no thread created.\n", stderr); (void)func; (void)arg; @@ -524,6 +531,17 @@ _cupsThreadCreate( /* + * '_cupsThreadDetach()' - Tell the OS that the thread is running independently. + */ + +void +_cupsThreadDetach(_cups_thread_t thread)/* I - Thread ID */ +{ + (void)thread; +} + + +/* * '_cupsThreadWait()' - Wait for a thread to exit. */ diff --git a/cups/tls-boringssl.c b/cups/tls-boringssl.c index a8b7de54..c3f9abc4 100644 --- a/cups/tls-boringssl.c +++ b/cups/tls-boringssl.c @@ -29,7 +29,9 @@ static char *tls_keypath = NULL; /* Server cert keychain path */ -static int tls_options = -1;/* Options for TLS connections */ +static int tls_options = -1,/* Options for TLS connections */ + tls_min_version = _HTTP_TLS_1_0, + tls_max_version = _HTTP_TLS_MAX; /* @@ -309,9 +311,11 @@ _httpTLSRead(http_t *http, /* I - Connection to server */ */ void -_httpTLSSetOptions(int options) /* I - Options */ +_httpTLSSetOptions(int options, int min_version, int max_version) /* I - Options */ { tls_options = options; + tls_min_version = min_version; + tls_max_version = max_version; } @@ -349,8 +353,8 @@ _httpTLSStart(http_t *http) /* I - Connection to server */ } context = SSL_CTX_new(TLS_method()); - if (tls_options & _HTTP_TLS_DENY_TLS10) - SSL_CTX_set_min_proto_version(context, TLS1_1_VERSION); + SSL_CTX_set_min_proto_version(context, tls_min_version); + SSL_CTX_set_max_proto_version(context, tls_max_version); bio = BIO_new(_httpBIOMethods()); BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http); diff --git a/cups/tls-darwin.c b/cups/tls-darwin.c index 92430aca..c4f0ccb2 100644 --- a/cups/tls-darwin.c +++ b/cups/tls-darwin.c @@ -1,8 +1,8 @@ /* * TLS support code for CUPS on macOS. * - * Copyright 2007-2017 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -53,7 +53,9 @@ static char *tls_keypath = NULL; /* Server cert keychain path */ static _cups_mutex_t tls_mutex = _CUPS_MUTEX_INITIALIZER; /* Mutex for keychain/certs */ -static int tls_options = -1;/* Options for TLS connections */ +static int tls_options = -1,/* Options for TLS connections */ + tls_min_version = _HTTP_TLS_1_0, + tls_max_version = _HTTP_TLS_MAX; /* @@ -807,7 +809,6 @@ httpCredentialsString( CFStringRef cf_name; /* CF common name string */ char name[256]; /* Common name associated with cert */ time_t expiration; /* Expiration date of cert */ - _cups_md5_state_t md5_state; /* MD5 state */ unsigned char md5_digest[16]; /* MD5 result */ if ((cf_name = SecCertificateCopySubjectSummary(secCert)) != NULL) @@ -820,9 +821,7 @@ httpCredentialsString( expiration = (time_t)(SecCertificateNotValidAfter(secCert) + kCFAbsoluteTimeIntervalSince1970); - _cupsMD5Init(&md5_state); - _cupsMD5Append(&md5_state, first->data, (int)first->datalen); - _cupsMD5Finish(&md5_state, md5_digest); + cupsHashData("md5", first->data, first->datalen, md5_digest, sizeof(md5_digest)); snprintf(buffer, bufsize, "%s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", name, httpGetDateString(expiration), md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]); @@ -1139,10 +1138,16 @@ _httpTLSRead(http_t *http, /* I - HTTP connection */ */ void -_httpTLSSetOptions(int options) /* I - Options */ +_httpTLSSetOptions(int options, /* I - Options */ + int min_version, /* I - Minimum TLS version */ + int max_version) /* I - Maximum TLS version */ { if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0) - tls_options = options; + { + tls_options = options; + tls_min_version = min_version; + tls_max_version = max_version; + } } @@ -1174,7 +1179,7 @@ _httpTLSStart(http_t *http) /* I - HTTP connection */ { DEBUG_puts("4_httpTLSStart: Setting defaults."); _cupsSetDefaults(); - DEBUG_printf(("4_httpTLSStart: tls_options=%x", tls_options)); + DEBUG_printf(("4_httpTLSStart: tls_options=%x, tls_min_version=%d, tls_max_version=%d", tls_options, tls_min_version, tls_max_version)); } #ifdef HAVE_SECKEYCHAINOPEN @@ -1217,22 +1222,25 @@ _httpTLSStart(http_t *http) /* I - HTTP connection */ if (!error) { - SSLProtocol minProtocol; - - if (tls_options & _HTTP_TLS_DENY_TLS10) - minProtocol = kTLSProtocol11; - else if (tls_options & _HTTP_TLS_ALLOW_SSL3) - minProtocol = kSSLProtocol3; - else - minProtocol = kTLSProtocol1; - - error = SSLSetProtocolVersionMin(http->tls, minProtocol); - DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMin(%d), error=%d", minProtocol, (int)error)); + static const SSLProtocol protocols[] = /* Min/max protocol versions */ + { + kSSLProtocol3, + kTLSProtocol1, + kTLSProtocol11, + kTLSProtocol12, + kTLSProtocol13 + }; + + if (tls_min_version < _HTTP_TLS_MAX) + { + error = SSLSetProtocolVersionMin(http->tls, protocols[tls_min_version]); + DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMin(%d), error=%d", protocols[tls_min_version], (int)error)); + } - if (!error && (tls_options & _HTTP_TLS_ONLY_TLS10)) + if (!error && tls_max_version < _HTTP_TLS_MAX) { - error = SSLSetProtocolVersionMax(http->tls, kTLSProtocol1); - DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMax(kTLSProtocol1), error=%d", (int)error)); + error = SSLSetProtocolVersionMax(http->tls, protocols[tls_max_version]); + DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMax(%d), error=%d", protocols[tls_max_version], (int)error)); } } @@ -1532,7 +1540,28 @@ _httpTLSStart(http_t *http) /* I - HTTP connection */ if (!error) { - int done = 0; /* Are we done yet? */ + int done = 0; /* Are we done yet? */ + double old_timeout; /* Old timeout value */ + http_timeout_cb_t old_cb; /* Old timeout callback */ + void *old_data; /* Old timeout data */ + + /* + * Enforce a minimum timeout of 10 seconds for the TLS handshake... + */ + + old_timeout = http->timeout_value; + old_cb = http->timeout_cb; + old_data = http->timeout_data; + + if (!old_cb || old_timeout < 10.0) + { + DEBUG_puts("4_httpTLSStart: Setting timeout to 10 seconds."); + httpSetTimeout(http, 10.0, NULL, NULL); + } + + /* + * Do the TLS handshake... + */ while (!error && !done) { @@ -1653,6 +1682,12 @@ _httpTLSStart(http_t *http) /* I - HTTP connection */ break; } } + + /* + * Restore the previous timeout settings... + */ + + httpSetTimeout(http, old_timeout, old_cb, old_data); } if (error) @@ -1864,7 +1899,9 @@ http_cdsa_copy_server( DEBUG_printf(("4http_cdsa_copy_server: Returning %p.", (void *)certificates)); return (certificates); + #else + (void)common_name; if (!tls_selfsigned) return (NULL); @@ -2085,7 +2122,7 @@ http_cdsa_read( http = (http_t *)connection; - if (!http->blocking) + if (!http->blocking || http->timeout_value > 0.0) { /* * Make sure we have data before we read... diff --git a/cups/tls-gnutls.c b/cups/tls-gnutls.c index 2dcb7fe3..606b45af 100644 --- a/cups/tls-gnutls.c +++ b/cups/tls-gnutls.c @@ -1,8 +1,8 @@ /* * TLS support code for CUPS using GNU TLS. * - * Copyright 2007-2017 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products, all rights reserved. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -35,7 +35,9 @@ static char *tls_keypath = NULL; /* Server cert keychain path */ static _cups_mutex_t tls_mutex = _CUPS_MUTEX_INITIALIZER; /* Mutex for keychain/certs */ -static int tls_options = -1;/* Options for TLS connections */ +static int tls_options = -1,/* Options for TLS connections */ + tls_min_version = _HTTP_TLS_1_0, + tls_max_version = _HTTP_TLS_MAX; /* @@ -646,7 +648,6 @@ httpCredentialsString( char name[256]; /* Common name associated with cert */ size_t namelen; /* Length of name */ time_t expiration; /* Expiration date of cert */ - _cups_md5_state_t md5_state; /* MD5 state */ unsigned char md5_digest[16]; /* MD5 result */ namelen = sizeof(name) - 1; @@ -657,9 +658,7 @@ httpCredentialsString( expiration = gnutls_x509_crt_get_expiration_time(cert); - _cupsMD5Init(&md5_state); - _cupsMD5Append(&md5_state, first->data, (int)first->datalen); - _cupsMD5Finish(&md5_state, md5_digest); + cupsHashData("md5", first->data, first->datalen, md5_digest, sizeof(md5_digest)); snprintf(buffer, bufsize, "%s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", name, httpGetDateString(expiration), md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]); @@ -1094,7 +1093,7 @@ http_gnutls_read( http = (http_t *)ptr; - if (!http->blocking) + if (!http->blocking || http->timeout_value > 0.0) { /* * Make sure we have data before we read... @@ -1224,10 +1223,16 @@ _httpTLSSetCredentials(http_t *http) /* I - Connection to server */ */ void -_httpTLSSetOptions(int options) /* I - Options */ +_httpTLSSetOptions(int options, /* I - Options */ + int min_version, /* I - Minimum TLS version */ + int max_version) /* I - Maximum TLS version */ { if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0) - tls_options = options; + { + tls_options = options; + tls_min_version = min_version; + tls_max_version = max_version; + } } @@ -1245,6 +1250,19 @@ _httpTLSStart(http_t *http) /* I - Connection to server */ /* TLS credentials */ char priority_string[2048]; /* Priority string */ + int version; /* Current version */ + double old_timeout; /* Old timeout value */ + http_timeout_cb_t old_cb; /* Old timeout callback */ + void *old_data; /* Old timeout data */ + static const char * const versions[] =/* SSL/TLS versions */ + { + "VERS-SSL3.0", + "VERS-TLS1.0", + "VERS-TLS1.1", + "VERS-TLS1.2", + "VERS-TLS1.3", + "VERS-TLS-ALL" + }; DEBUG_printf(("3_httpTLSStart(http=%p)", http)); @@ -1506,14 +1524,40 @@ _httpTLSStart(http_t *http) /* I - Connection to server */ strlcpy(priority_string, "NORMAL", sizeof(priority_string)); - if (tls_options & _HTTP_TLS_DENY_TLS10) - strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-TLS1.0:-VERS-SSL3.0", sizeof(priority_string)); - else if (tls_options & _HTTP_TLS_ALLOW_SSL3) + if (tls_max_version < _HTTP_TLS_MAX) + { + /* + * Require specific TLS versions... + */ + + strlcat(priority_string, ":-VERS-TLS-ALL", sizeof(priority_string)); + for (version = tls_min_version; version <= tls_max_version; version ++) + { + strlcat(priority_string, ":+", sizeof(priority_string)); + strlcat(priority_string, versions[version], sizeof(priority_string)); + } + } + else if (tls_min_version == _HTTP_TLS_SSL3) + { + /* + * Allow all versions of TLS and SSL/3.0... + */ + strlcat(priority_string, ":+VERS-TLS-ALL:+VERS-SSL3.0", sizeof(priority_string)); - else if (tls_options & _HTTP_TLS_ONLY_TLS10) - strlcat(priority_string, ":-VERS-TLS-ALL:-VERS-SSL3.0:+VERS-TLS1.0", sizeof(priority_string)); + } else - strlcat(priority_string, ":+VERS-TLS-ALL:-VERS-SSL3.0", sizeof(priority_string)); + { + /* + * Require a minimum version... + */ + + strlcat(priority_string, ":+VERS-TLS-ALL", sizeof(priority_string)); + for (version = 0; version < tls_min_version; version ++) + { + strlcat(priority_string, ":-", sizeof(priority_string)); + strlcat(priority_string, versions[version], sizeof(priority_string)); + } + } if (tls_options & _HTTP_TLS_ALLOW_RC4) strlcat(priority_string, ":+ARCFOUR-128", sizeof(priority_string)); @@ -1543,6 +1587,24 @@ _httpTLSStart(http_t *http) /* I - Connection to server */ #endif /* HAVE_GNUTLS_TRANSPORT_SET_PULL_TIMEOUT_FUNCTION */ gnutls_transport_set_push_function(http->tls, http_gnutls_write); + /* + * Enforce a minimum timeout of 10 seconds for the TLS handshake... + */ + + old_timeout = http->timeout_value; + old_cb = http->timeout_cb; + old_data = http->timeout_data; + + if (!old_cb || old_timeout < 10.0) + { + DEBUG_puts("4_httpTLSStart: Setting timeout to 10 seconds."); + httpSetTimeout(http, 10.0, NULL, NULL); + } + + /* + * Do the TLS handshake... + */ + while ((status = gnutls_handshake(http->tls)) != GNUTLS_E_SUCCESS) { DEBUG_printf(("5_httpStartTLS: gnutls_handshake returned %d (%s)", @@ -1560,10 +1622,18 @@ _httpTLSStart(http_t *http) /* I - Connection to server */ free(credentials); http->tls = NULL; + httpSetTimeout(http, old_timeout, old_cb, old_data); + return (-1); } } + /* + * Restore the previous timeout settings... + */ + + httpSetTimeout(http, old_timeout, old_cb, old_data); + http->tls_credentials = credentials; return (0); diff --git a/cups/tls-sspi.c b/cups/tls-sspi.c index 6eaec4c8..ea3fb007 100644 --- a/cups/tls-sspi.c +++ b/cups/tls-sspi.c @@ -2,7 +2,7 @@ * TLS support for CUPS on Windows using the Security Support Provider * Interface (SSPI). * - * Copyright 2010-2017 by Apple Inc. + * Copyright 2010-2018 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -52,7 +52,9 @@ * Local globals... */ -static int tls_options = -1;/* Options for TLS connections */ +static int tls_options = -1,/* Options for TLS connections */ + tls_min_version = _HTTP_TLS_1_0, + tls_max_version = _HTTP_TLS_MAX; /* @@ -351,7 +353,6 @@ httpCredentialsString( SYSTEMTIME systime; /* System time */ struct tm tm; /* UNIX date/time */ time_t expiration; /* Expiration date of cert */ - _cups_md5_state_t md5_state; /* MD5 state */ unsigned char md5_digest[16]; /* MD5 result */ FileTimeToSystemTime(&(cert->pCertInfo->NotAfter), &systime); @@ -378,9 +379,7 @@ httpCredentialsString( else strlcpy(cert_name, "unknown", sizeof(cert_name)); - _cupsMD5Init(&md5_state); - _cupsMD5Append(&md5_state, first->data, (int)first->datalen); - _cupsMD5Finish(&md5_state, md5_digest); + cupsHashData("md5", first->data, first->datalen, md5_digest, sizeof(md5_digest)); snprintf(buffer, bufsize, "%s / %s / %02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", cert_name, httpGetDateString(expiration), md5_digest[0], md5_digest[1], md5_digest[2], md5_digest[3], md5_digest[4], md5_digest[5], md5_digest[6], md5_digest[7], md5_digest[8], md5_digest[9], md5_digest[10], md5_digest[11], md5_digest[12], md5_digest[13], md5_digest[14], md5_digest[15]); @@ -911,10 +910,16 @@ _httpTLSRead(http_t *http, /* I - HTTP connection */ */ void -_httpTLSSetOptions(int options) /* I - Options */ +_httpTLSSetOptions(int options, /* I - Options */ + int min_version, /* I - Minimum TLS version */ + int max_version) /* I - Maximum TLS version */ { if (!(options & _HTTP_TLS_SET_DEFAULT) || tls_options < 0) - tls_options = options; + { + tls_options = options; + tls_min_version = min_version; + tls_max_version = max_version; + } } @@ -1762,34 +1767,38 @@ http_sspi_find_credentials( #ifdef SP_PROT_TLS1_2_SERVER if (http->mode == _HTTP_MODE_SERVER) { - if (tls_options & _HTTP_TLS_DENY_TLS10) - SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_1_SERVER; - else if (tls_options & _HTTP_TLS_ALLOW_SSL3) + if (tls_min_version == _HTTP_TLS_SSL3) SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_0_SERVER | SP_PROT_SSL3_SERVER; - else + else if (tls_min_version == _HTTP_TLS_1_0) SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_1_SERVER | SP_PROT_TLS1_0_SERVER; + else if (tls_min_version == _HTTP_TLS_1_1) + SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER | SP_PROT_TLS1_1_SERVER; + else + SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_SERVER; } else { - if (tls_options & _HTTP_TLS_DENY_TLS10) - SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_1_CLIENT; - else if (tls_options & _HTTP_TLS_ALLOW_SSL3) + if (tls_min_version == _HTTP_TLS_SSL3) SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_0_CLIENT | SP_PROT_SSL3_CLIENT; - else + else if (tls_min_version == _HTTP_TLS_1_0) SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_0_CLIENT; + else if (tls_min_version == _HTTP_TLS_1_1) + SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT | SP_PROT_TLS1_1_CLIENT; + else + SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_2_CLIENT; } #else if (http->mode == _HTTP_MODE_SERVER) { - if (tls_options & _HTTP_TLS_ALLOW_SSL3) + if (tls_min_version == _HTTP_TLS_SSL3) SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER | SP_PROT_SSL3_SERVER; else SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_SERVER; } else { - if (tls_options & _HTTP_TLS_ALLOW_SSL3) + if (tls_min_version == _HTTP_TLS_SSL3) SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT | SP_PROT_SSL3_CLIENT; else SchannelCred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT; @@ -23,20 +23,20 @@ #include "cups-private.h" #include <fcntl.h> #include <math.h> -#ifdef WIN32 +#ifdef _WIN32 # include <tchar.h> #else # include <signal.h> # include <sys/time.h> # include <sys/resource.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ #ifdef HAVE_POLL # include <poll.h> #endif /* HAVE_POLL */ /* - * Local functions... + * Include platform-specific TLS code... */ #ifdef HAVE_SSL diff --git a/cups/tlscheck.c b/cups/tlscheck.c index 997e7aaf..d16bf1e4 100644 --- a/cups/tlscheck.c +++ b/cups/tlscheck.c @@ -54,6 +54,8 @@ main(int argc, /* I - Number of command-line arguments */ int af = AF_UNSPEC, /* Address family */ tls_options = _HTTP_TLS_NONE, /* TLS options */ + tls_min_version = _HTTP_TLS_1_0, + tls_max_version = _HTTP_TLS_MAX, verbose = 0; /* Verbosity */ ipp_t *request, /* IPP Get-Printer-Attributes request */ *response; /* IPP Get-Printer-Attributes response */ @@ -88,11 +90,27 @@ main(int argc, /* I - Number of command-line arguments */ } else if (!strcmp(argv[i], "--no-tls10")) { - tls_options |= _HTTP_TLS_DENY_TLS10; + tls_min_version = _HTTP_TLS_1_1; } else if (!strcmp(argv[i], "--tls10")) { - tls_options |= _HTTP_TLS_ONLY_TLS10; + tls_min_version = _HTTP_TLS_1_0; + tls_max_version = _HTTP_TLS_1_0; + } + else if (!strcmp(argv[i], "--tls11")) + { + tls_min_version = _HTTP_TLS_1_1; + tls_max_version = _HTTP_TLS_1_1; + } + else if (!strcmp(argv[i], "--tls12")) + { + tls_min_version = _HTTP_TLS_1_2; + tls_max_version = _HTTP_TLS_1_2; + } + else if (!strcmp(argv[i], "--tls13")) + { + tls_min_version = _HTTP_TLS_1_3; + tls_max_version = _HTTP_TLS_1_3; } else if (!strcmp(argv[i], "--rc4")) { @@ -148,7 +166,7 @@ main(int argc, /* I - Number of command-line arguments */ if (!port) port = 631; - _httpTLSSetOptions(tls_options); + _httpTLSSetOptions(tls_options, tls_min_version, tls_max_version); http = httpConnect2(server, port, NULL, af, HTTP_ENCRYPTION_ALWAYS, 1, 30000, NULL); if (!http) @@ -741,6 +759,9 @@ usage(void) puts(" --no-tls10 Disable TLS/1.0"); puts(" --rc4 Allow RC4 encryption"); puts(" --tls10 Only use TLS/1.0"); + puts(" --tls11 Only use TLS/1.1"); + puts(" --tls12 Only use TLS/1.2"); + puts(" --tls13 Only use TLS/1.3"); puts(" --verbose Be verbose"); puts(" -4 Connect using IPv4 addresses only"); puts(" -6 Connect using IPv6 addresses only"); diff --git a/cups/usersys.c b/cups/usersys.c index 2a004b54..781f27bb 100644 --- a/cups/usersys.c +++ b/cups/usersys.c @@ -20,13 +20,13 @@ #include "cups-private.h" #include <stdlib.h> #include <sys/stat.h> -#ifdef WIN32 +#ifdef _WIN32 # include <windows.h> #else # include <pwd.h> # include <termios.h> # include <sys/utsname.h> -#endif /* WIN32 */ +#endif /* _WIN32 */ /* @@ -54,7 +54,9 @@ typedef struct _cups_client_conf_s /**** client.conf config data ****/ { #ifdef HAVE_SSL - int ssl_options; /* SSLOptions values */ + int ssl_options, /* SSLOptions values */ + ssl_min_version,/* Minimum SSL/TLS version */ + ssl_max_version;/* Maximum SSL/TLS version */ #endif /* HAVE_SSL */ int trust_first, /* Trust on first use? */ any_root, /* Allow any (e.g., self-signed) root */ @@ -488,12 +490,12 @@ cupsSetUserAgent(const char *user_agent)/* I - User-Agent string or @code NULL@ { _cups_globals_t *cg = _cupsGlobals(); /* Thread globals */ -#ifdef WIN32 +#ifdef _WIN32 SYSTEM_INFO sysinfo; /* System information */ OSVERSIONINFO version; /* OS version info */ #else struct utsname name; /* uname info */ -#endif /* WIN32 */ +#endif /* _WIN32 */ if (user_agent) @@ -502,7 +504,7 @@ cupsSetUserAgent(const char *user_agent)/* I - User-Agent string or @code NULL@ return; } -#ifdef WIN32 +#ifdef _WIN32 version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&version); GetNativeSystemInfo(&sysinfo); @@ -526,7 +528,7 @@ cupsSetUserAgent(const char *user_agent)/* I - User-Agent string or @code NULL@ snprintf(cg->user_agent, sizeof(cg->user_agent), CUPS_MINIMAL " (%s %s; %s) IPP/2.0", name.sysname, name.release, name.machine); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -578,7 +580,7 @@ cupsUserAgent(void) const char * /* O - Password or @code NULL@ if none */ _cupsGetPassword(const char *prompt) /* I - Prompt string */ { -#ifdef WIN32 +#ifdef _WIN32 HANDLE tty; /* Console handle */ DWORD mode; /* Console mode */ char passch, /* Current key press */ @@ -844,7 +846,7 @@ _cupsGetPassword(const char *prompt) /* I - Prompt string */ memset(cg->password, 0, sizeof(cg->password)); return (NULL); } -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -903,7 +905,7 @@ _cupsSetDefaults(void) # ifdef HAVE_GETEUID if ((geteuid() == getuid() || !getuid()) && getegid() == getgid() && (home = getenv("HOME")) != NULL) -# elif !defined(WIN32) +# elif !defined(_WIN32) if (getuid() && (home = getenv("HOME")) != NULL) # else if ((home = getenv("HOME")) != NULL) @@ -957,7 +959,7 @@ _cupsSetDefaults(void) cg->validate_certs = cc.validate_certs; #ifdef HAVE_SSL - _httpTLSSetOptions(cc.ssl_options | _HTTP_TLS_SET_DEFAULT); + _httpTLSSetOptions(cc.ssl_options | _HTTP_TLS_SET_DEFAULT, cc.ssl_min_version, cc.ssl_max_version); #endif /* HAVE_SSL */ } @@ -1099,7 +1101,7 @@ cups_finalize_client_conf( if (!cc->user[0]) { -#ifdef WIN32 +#ifdef _WIN32 /* * Get the current user name from the OS... */ @@ -1135,7 +1137,7 @@ cups_finalize_client_conf( if (pw) strlcpy(cc->user, pw->pw_name, sizeof(cc->user)); else -#endif /* WIN32 */ +#endif /* _WIN32 */ { /* * Use the default "unknown" user name... @@ -1164,11 +1166,15 @@ cups_init_client_conf( memset(cc, 0, sizeof(_cups_client_conf_t)); - cc->encryption = (http_encryption_t)-1; - cc->trust_first = -1; - cc->any_root = -1; - cc->expired_certs = -1; - cc->validate_certs = -1; +#ifdef HAVE_SSL + cc->ssl_min_version = _HTTP_TLS_1_0; + cc->ssl_max_version = _HTTP_TLS_MAX; +#endif /* HAVE_SSL */ + cc->encryption = (http_encryption_t)-1; + cc->trust_first = -1; + cc->any_root = -1; + cc->expired_certs = -1; + cc->validate_certs = -1; /* * Load settings from the org.cups.PrintingPrefs plist (which trump @@ -1336,7 +1342,9 @@ cups_set_ssl_options( * SSLOptions [AllowRC4] [AllowSSL3] [AllowDH] [DenyTLS1.0] [None] */ - int options = _HTTP_TLS_NONE; /* SSL/TLS options */ + int options = _HTTP_TLS_NONE, /* SSL/TLS options */ + min_version = _HTTP_TLS_1_0, /* Minimum SSL/TLS version */ + max_version = _HTTP_TLS_MAX; /* Maximum SSL/TLS version */ char temp[256], /* Copy of value */ *start, /* Start of option */ *end; /* End of option */ @@ -1364,20 +1372,38 @@ cups_set_ssl_options( if (!_cups_strcasecmp(start, "AllowRC4")) options |= _HTTP_TLS_ALLOW_RC4; else if (!_cups_strcasecmp(start, "AllowSSL3")) - options |= _HTTP_TLS_ALLOW_SSL3; + min_version = _HTTP_TLS_SSL3; else if (!_cups_strcasecmp(start, "AllowDH")) options |= _HTTP_TLS_ALLOW_DH; else if (!_cups_strcasecmp(start, "DenyCBC")) options |= _HTTP_TLS_DENY_CBC; else if (!_cups_strcasecmp(start, "DenyTLS1.0")) - options |= _HTTP_TLS_DENY_TLS10; + min_version = _HTTP_TLS_1_1; + else if (!_cups_strcasecmp(start, "MaxTLS1.0")) + max_version = _HTTP_TLS_1_0; + else if (!_cups_strcasecmp(start, "MaxTLS1.1")) + max_version = _HTTP_TLS_1_1; + else if (!_cups_strcasecmp(start, "MaxTLS1.2")) + max_version = _HTTP_TLS_1_2; + else if (!_cups_strcasecmp(start, "MaxTLS1.3")) + max_version = _HTTP_TLS_1_3; + else if (!_cups_strcasecmp(start, "MinTLS1.0")) + min_version = _HTTP_TLS_1_0; + else if (!_cups_strcasecmp(start, "MinTLS1.1")) + min_version = _HTTP_TLS_1_1; + else if (!_cups_strcasecmp(start, "MinTLS1.2")) + min_version = _HTTP_TLS_1_2; + else if (!_cups_strcasecmp(start, "MinTLS1.3")) + min_version = _HTTP_TLS_1_3; else if (!_cups_strcasecmp(start, "None")) options = _HTTP_TLS_NONE; } - cc->ssl_options = options; + cc->ssl_options = options; + cc->ssl_max_version = max_version; + cc->ssl_min_version = min_version; - DEBUG_printf(("4cups_set_ssl_options(cc=%p, value=\"%s\") options=%x", (void *)cc, value, options)); + DEBUG_printf(("4cups_set_ssl_options(cc=%p, value=\"%s\") options=%x, min_version=%d, max_version=%d", (void *)cc, value, options, min_version, max_version)); } #endif /* HAVE_SSL */ diff --git a/cups/util.c b/cups/util.c index 2f5ebdf4..ef1709c5 100644 --- a/cups/util.c +++ b/cups/util.c @@ -1,8 +1,8 @@ /* * Printing utilities for CUPS. * - * Copyright 2007-2017 by Apple Inc. - * Copyright 1997-2006 by Easy Software Products. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1997-2006 by Easy Software Products. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -20,24 +20,11 @@ #include "cups-private.h" #include <fcntl.h> #include <sys/stat.h> -#if defined(WIN32) || defined(__EMX__) +#if defined(_WIN32) || defined(__EMX__) # include <io.h> #else # include <unistd.h> -#endif /* WIN32 || __EMX__ */ - - -/* - * Enumeration data and callback... - */ - -typedef struct _cups_createdata_s -{ - const char *name; /* Destination name */ - cups_dest_t *dest; /* Matching destination */ -} _cups_createdata_t; - -static int cups_create_cb(_cups_createdata_t *data, unsigned flags, cups_dest_t *dest); +#endif /* _WIN32 || __EMX__ */ /* @@ -174,7 +161,7 @@ cupsCreateJob( { int job_id = 0; /* job-id value */ ipp_status_t status; /* Create-Job status */ - _cups_createdata_t data; /* Enumeration data */ + cups_dest_t *dest; /* Destination */ cups_dinfo_t *info; /* Destination information */ @@ -194,12 +181,7 @@ cupsCreateJob( * Lookup the destination... */ - data.name = name; - data.dest = NULL; - - cupsEnumDests(0, 1000, NULL, 0, 0, (cups_dest_cb_t)cups_create_cb, &data); - - if (!data.dest) + if ((dest = cupsGetNamedDest(http, name, NULL)) == NULL) { DEBUG_puts("1cupsCreateJob: Destination not found."); _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(ENOENT), 0); @@ -211,18 +193,18 @@ cupsCreateJob( */ DEBUG_puts("1cupsCreateJob: Querying destination info."); - if ((info = cupsCopyDestInfo(http, data.dest)) == NULL) + if ((info = cupsCopyDestInfo(http, dest)) == NULL) { DEBUG_puts("1cupsCreateJob: Query failed."); - cupsFreeDests(1, data.dest); + cupsFreeDests(1, dest); return (0); } - status = cupsCreateDestJob(http, data.dest, info, &job_id, title, num_options, options); + status = cupsCreateDestJob(http, dest, info, &job_id, title, num_options, options); DEBUG_printf(("1cupsCreateJob: cupsCreateDestJob returned %04x (%s)", status, ippErrorString(status))); cupsFreeDestInfo(info); - cupsFreeDests(1, data.dest); + cupsFreeDests(1, dest); /* * Return the job... @@ -974,25 +956,3 @@ cupsStartDocument( return (status); } - -/* - * 'cups_create_cb()' - Find the destination for printing. - */ - -static int /* O - 0 on match */ -cups_create_cb( - _cups_createdata_t *data, /* I - Data from cupsCreateJob call */ - unsigned flags, /* I - Enumeration flags */ - cups_dest_t *dest) /* I - Destination */ -{ - DEBUG_printf(("2cups_create_cb(data=%p(%s), flags=%08x, dest=%p(%s))", (void *)data, data->name, flags, (void *)dest, dest->name)); - - (void)flags; - - if (dest->instance || strcasecmp(data->name, dest->name)) - return (1); - - cupsCopyDest(dest, 0, &data->dest); - - return (0); -} diff --git a/cups/versioning.h b/cups/versioning.h index 5a000c05..620396f7 100644 --- a/cups/versioning.h +++ b/cups/versioning.h @@ -1,7 +1,7 @@ /* * API versioning definitions for CUPS. * - * Copyright 2007-2017 by Apple Inc. + * Copyright © 2007-2018 by Apple Inc. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -16,83 +16,41 @@ # define _CUPS_VERSIONING_H_ /* - * This header defines several constants - _CUPS_DEPRECATED, - * _CUPS_DEPRECATED_MSG, _CUPS_INTERNAL_MSG, _CUPS_API_major_minor, and - * _CUPS_API_major_minor_patch - which add compiler-specific attributes that - * flag functions that are deprecated, added in particular releases, or internal - * to CUPS. + * This header defines several macros that add compiler-specific attributes for + * functions: * - * On macOS, the _CUPS_API_* constants are defined based on the values of - * the MAC_OS_X_VERSION_MIN_ALLOWED and MAC_OS_X_VERSION_MAX_ALLOWED constants - * provided by the compiler. + * - _CUPS_API_major_minor[_patch]: Specifies when an API became available by + * CUPS version. + * - _CUPS_DEPRECATED: Function is deprecated with no replacement. + * - _CUPS_DEPRECATED_MSG("message"): Function is deprecated and has a + * replacement. + * - _CUPS_FORMAT(format-index, additional-args-index): Function has a + * printf-style format argument followed by zero or more additional + * arguments. Indices start at 1. + * - _CUPS_INTERNAL: Function is internal with no replacement API. + * - _CUPS_INTERNAL_MSG("msg"): Function is internal - use specified API + * instead. + * - _CUPS_NONNULL((arg list)): Specifies the comma-separated argument indices + * are assumed non-NULL. Indices start at 1. + * - _CUPS_NORETURN: Specifies the function does not return. + * - _CUPS_PRIVATE: Specifies the function is private to CUPS. + * - _CUPS_PUBLIC: Specifies the function is public API. */ -# if defined(__APPLE__) && !defined(_CUPS_SOURCE) && !TARGET_OS_IOS -# include <AvailabilityMacros.h> -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER */ -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER */ -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER */ -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER */ -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER */ -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER */ -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_9_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_9_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_9_AND_LATER */ -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER */ -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER */ -# ifndef AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER -# define AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER __attribute__((unavailable)) -# endif /* !AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER */ -# define _CUPS_API_1_1_19 AVAILABLE_MAC_OS_X_VERSION_10_3_AND_LATER -# define _CUPS_API_1_1_20 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER -# define _CUPS_API_1_1_21 AVAILABLE_MAC_OS_X_VERSION_10_4_AND_LATER -# define _CUPS_API_1_2 AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER -# define _CUPS_API_1_3 AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER -# define _CUPS_API_1_4 AVAILABLE_MAC_OS_X_VERSION_10_6_AND_LATER -# define _CUPS_API_1_5 AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER -# define _CUPS_API_1_6 AVAILABLE_MAC_OS_X_VERSION_10_8_AND_LATER -# define _CUPS_API_1_7 AVAILABLE_MAC_OS_X_VERSION_10_9_AND_LATER -# define _CUPS_API_2_0 AVAILABLE_MAC_OS_X_VERSION_10_10_AND_LATER -# define _CUPS_API_2_2 AVAILABLE_MAC_OS_X_VERSION_10_12_AND_LATER -# define _CUPS_API_2_2_4 AVAILABLE_MAC_OS_X_VERSION_10_13_AND_LATER -# else -# define _CUPS_API_1_1_19 -# define _CUPS_API_1_1_20 -# define _CUPS_API_1_1_21 -# define _CUPS_API_1_2 -# define _CUPS_API_1_3 -# define _CUPS_API_1_4 -# define _CUPS_API_1_5 -# define _CUPS_API_1_6 -# define _CUPS_API_1_7 -# define _CUPS_API_2_0 -# define _CUPS_API_2_2 -# define _CUPS_API_2_2_4 -# endif /* __APPLE__ && !_CUPS_SOURCE */ - /* - * With GCC and Clang we can mark old APIs as "deprecated" or "unavailable" with - * messages so you get warnings/errors are compile-time... + * Determine which compiler is being used and what annotation features are + * available... */ +# ifdef __APPLE__ +# include <os/availability.h> +# endif /* __APPLE__ */ + # ifdef __has_extension /* Clang */ # define _CUPS_HAS_DEPRECATED +# define _CUPS_HAS_FORMAT +# define _CUPS_HAS_NORETURN +# define _CUPS_HAS_VISIBILITY # if __has_extension(attribute_deprecated_with_message) # define _CUPS_HAS_DEPRECATED_WITH_MESSAGE # endif @@ -102,6 +60,9 @@ # elif defined(__GNUC__) /* GCC and compatible */ # if __GNUC__ >= 3 /* GCC 3.0 or higher */ # define _CUPS_HAS_DEPRECATED +# define _CUPS_HAS_FORMAT +# define _CUPS_HAS_NORETURN +# define _CUPS_HAS_VISIBILITY # endif /* __GNUC__ >= 3 */ # if __GNUC__ >= 5 /* GCC 5.x */ # define _CUPS_HAS_DEPRECATED_WITH_MESSAGE @@ -109,61 +70,197 @@ /* GCC 4.5 or higher */ # define _CUPS_HAS_DEPRECATED_WITH_MESSAGE # endif /* __GNUC__ >= 5 */ +# elif defined(_WIN32) +# define __attribute__(...) # endif /* __has_extension */ + +/* + * Define _CUPS_INTERNAL, _CUPS_PRIVATE, and _CUPS_PUBLIC visibilty macros for + * internal/private/public functions... + */ + +# ifdef _CUPS_HAS_VISIBILITY +# define _CUPS_INTERNAL __attribute__ ((visibility("hidden"))) +# define _CUPS_PRIVATE __attribute__ ((visibility("default"))) +# define _CUPS_PUBLIC __attribute__ ((visibility("default"))) +# else +# define _CUPS_INTERNAL +# define _CUPS_PRIVATE +# define _CUPS_PUBLIC +# endif /* _CUPS_HAS_VISIBILITY */ + + +/* + * Define _CUPS_API_major_minor[_patch] availability macros for CUPS. + * + * Note: Using any of the _CUPS_API macros automatically adds _CUPS_PUBLIC. + */ + +# if defined(__APPLE__) && !defined(_CUPS_SOURCE) && !TARGET_OS_IOS +/* + * On Apple operating systems, the _CUPS_API_* constants are defined using the + * API_ macros in <os/availability.h>. + * + * On iOS, we don't actually have libcups available directly, but the supplied + * libcups_static target in the Xcode project supports building on iOS 11.0 and + * later. + */ +# define _CUPS_API_1_1_19 API_AVAILABLE(macos(10.3), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_1_1_20 API_AVAILABLE(macos(10.4), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_1_1_21 API_AVAILABLE(macos(10.4), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_1_2 API_AVAILABLE(macos(10.5), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_1_3 API_AVAILABLE(macos(10.5), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_1_4 API_AVAILABLE(macos(10.6), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_1_5 API_AVAILABLE(macos(10.7), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_1_6 API_AVAILABLE(macos(10.8), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_1_7 API_AVAILABLE(macos(10.9), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_2_0 API_AVAILABLE(macos(10.10), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_2_2 API_AVAILABLE(macos(10.12), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_2_2_4 API_AVAILABLE(macos(10.13), ios(11.0)) _CUPS_PUBLIC +# define _CUPS_API_2_2_7 API_AVAILABLE(macos(10.14), ios(11.0)) _CUPS_PUBLIC +# else +# define _CUPS_API_1_1_19 _CUPS_PUBLIC +# define _CUPS_API_1_1_20 _CUPS_PUBLIC +# define _CUPS_API_1_1_21 _CUPS_PUBLIC +# define _CUPS_API_1_2 _CUPS_PUBLIC +# define _CUPS_API_1_3 _CUPS_PUBLIC +# define _CUPS_API_1_4 _CUPS_PUBLIC +# define _CUPS_API_1_5 _CUPS_PUBLIC +# define _CUPS_API_1_6 _CUPS_PUBLIC +# define _CUPS_API_1_7 _CUPS_PUBLIC +# define _CUPS_API_2_0 _CUPS_PUBLIC +# define _CUPS_API_2_2 _CUPS_PUBLIC +# define _CUPS_API_2_2_4 _CUPS_PUBLIC +# define _CUPS_API_2_2_7 _CUPS_PUBLIC +# endif /* __APPLE__ && !_CUPS_SOURCE */ + + +/* + * Define _CUPS_DEPRECATED and _CUPS_INTERNAL macros to mark old APIs as + * "deprecated" or "unavailable" with messages so you get warnings/errors are + * compile-time... + * + * Note: Using any of the _CUPS_DEPRECATED macros automatically adds + * _CUPS_PUBLIC. + */ + # if !defined(_CUPS_HAS_DEPRECATED) || (defined(_CUPS_SOURCE) && !defined(_CUPS_NO_DEPRECATED)) /* * Don't mark functions deprecated if the compiler doesn't support it * or we are building CUPS source that doesn't care. */ -# define _CUPS_DEPRECATED -# define _CUPS_DEPRECATED_MSG(m) -# define _CUPS_DEPRECATED_1_6_MSG(m) -# define _CUPS_DEPRECATED_1_7_MSG(m) -# define _CUPS_INTERNAL_MSG(m) +# define _CUPS_DEPRECATED _CUPS_PUBLIC +# define _CUPS_DEPRECATED_MSG(m) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_2_MSG(m) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_6_MSG(m) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_7_MSG(m) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_2_2_MSG(m) _CUPS_PUBLIC +# elif defined(__APPLE__) && defined(_CUPS_NO_DEPRECATED) + /* + * Compiler supports the unavailable attribute, so use it when the code + * wants to exclude the use of deprecated API. + */ +# define _CUPS_DEPRECATED __attribute__ ((unavailable)) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((unavailable(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_2_MSG(m) API_DEPRECATED(m, macos(10.2,10.5)) API_UNAVAILABLE(ios) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_6_MSG(m) API_DEPRECATED(m, macos(10.2,10.8)) API_UNAVAILABLE(ios) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_7_MSG(m) API_DEPRECATED(m, macos(10.2,10.9)) API_UNAVAILABLE(ios) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_2_2_MSG(m) API_DEPRECATED(m, macos(10.2,10.12)) API_UNAVAILABLE(ios) _CUPS_PUBLIC + +# elif defined(__APPLE__) + /* + * Just mark things as deprecated... + */ +# define _CUPS_DEPRECATED __attribute__ ((deprecated)) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((deprecated(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_2_MSG(m) API_DEPRECATED(m, macos(10.2,10.5)) API_UNAVAILABLE(ios) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_6_MSG(m) API_DEPRECATED(m, macos(10.2,10.8)) API_UNAVAILABLE(ios) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_7_MSG(m) API_DEPRECATED(m, macos(10.2,10.9)) API_UNAVAILABLE(ios) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_2_2_MSG(m) API_DEPRECATED(m, macos(10.2,10.12)) API_UNAVAILABLE(ios) _CUPS_PUBLIC + # elif defined(_CUPS_HAS_UNAVAILABLE_WITH_MESSAGE) && defined(_CUPS_NO_DEPRECATED) /* * Compiler supports the unavailable attribute, so use it when the code * wants to exclude the use of deprecated API. */ -# define _CUPS_DEPRECATED __attribute__ ((unavailable)) -# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((unavailable(m))) -# define _CUPS_DEPRECATED_1_6_MSG(m) __attribute__ ((unavailable(m))) -# define _CUPS_DEPRECATED_1_7_MSG(m) __attribute__ ((unavailable(m))) -# define _CUPS_INTERNAL_MSG(m) __attribute__ ((unavailable(m))) +# define _CUPS_DEPRECATED __attribute__ ((unavailable)) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((unavailable(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_2_MSG(m) __attribute__ ((unavailable(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_6_MSG(m) __attribute__ ((unavailable(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_7_MSG(m) __attribute__ ((unavailable(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_2_2_MSG(m) __attribute__ ((unavailable(m))) _CUPS_PUBLIC # else /* * Compiler supports the deprecated attribute, so use it. */ -# define _CUPS_DEPRECATED __attribute__ ((deprecated)) +# define _CUPS_DEPRECATED __attribute__ ((deprecated)) _CUPS_PUBLIC # ifdef _CUPS_HAS_DEPRECATED_WITH_MESSAGE -# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((deprecated(m))) +# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((deprecated(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_2_MSG(m) __attribute__ ((deprecated(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_6_MSG(m) __attribute__ ((deprecated(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_7_MSG(m) __attribute__ ((deprecated(m))) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_2_2_MSG(m) __attribute__ ((deprecated(m))) _CUPS_PUBLIC # else -# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((deprecated)) +# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((deprecated)) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_2_MSG(m) __attribute__ ((deprecated)) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_6_MSG(m) __attribute__ ((deprecated)) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_1_7_MSG(m) __attribute__ ((deprecated)) _CUPS_PUBLIC +# define _CUPS_DEPRECATED_2_2_MSG(m) __attribute__ ((deprecated)) _CUPS_PUBLIC # endif /* _CUPS_HAS_DEPRECATED_WITH_MESSAGE */ -# if defined(MAC_OS_X_VERSION_10_8) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_8 -# define _CUPS_DEPRECATED_1_6_MSG(m) _CUPS_DEPRECATED_MSG(m) -# else -# define _CUPS_DEPRECATED_1_6_MSG(m) -# endif /* MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_8 */ -# if defined(MAC_OS_X_VERSION_10_9) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_9 -# define _CUPS_DEPRECATED_1_7_MSG(m) _CUPS_DEPRECATED_MSG(m) -# else -# define _CUPS_DEPRECATED_1_7_MSG(m) -# endif /* MAC_OS_X_VERSION_MIN_REQUIRED > MAC_OS_X_VERSION_10_9 */ -# ifdef _CUPS_SOURCE -# define _CUPS_INTERNAL_MSG(m) -# elif defined(_CUPS_HAS_UNAVAILABLE_WITH_MESSAGE) -# define _CUPS_INTERNAL_MSG(m) __attribute__ ((unavailable(m))) -# elif defined(_CUPS_HAS_DEPRECATED_WITH_MESSAGE) -# define _CUPS_INTERNAL_MSG(m) __attribute__ ((deprecated(m))) -# else -# define _CUPS_INTERNAL_MSG(m) __attribute__ ((deprecated)) -# endif /* _CUPS_SOURCE */ # endif /* !_CUPS_HAS_DEPRECATED || (_CUPS_SOURCE && !_CUPS_NO_DEPRECATED) */ -# ifndef __GNUC__ -# define __attribute__(x) -# endif /* !__GNUC__ */ + +/* + * Define _CUPS_FORMAT macro for printf-style functions... + */ + +# ifdef _CUPS_HAS_FORMAT +# define _CUPS_FORMAT(a,b) __attribute__ ((__format__(__printf__, a,b))) +# else +# define _CUPS_FORMAT(a,b) +# endif /* _CUPS_HAS_FORMAT */ + + +/* + * Define _CUPS_INTERNAL_MSG macro for private APIs that have (historical) + * public visibility. + * + * Note: Using the _CUPS_INTERNAL_MSG macro automatically adds _CUPS_PUBLIC. + */ + +# ifdef _CUPS_SOURCE +# define _CUPS_INTERNAL_MSG(m) _CUPS_PUBLIC +# elif defined(_CUPS_HAS_UNAVAILABLE_WITH_MESSAGE) +# define _CUPS_INTERNAL_MSG(m) __attribute__ ((unavailable(m))) _CUPS_PUBLIC +# elif defined(_CUPS_HAS_DEPRECATED_WITH_MESSAGE) +# define _CUPS_INTERNAL_MSG(m) __attribute__ ((deprecated(m))) _CUPS_PUBLIC +# else +# define _CUPS_INTERNAL_MSG(m) __attribute__ ((deprecated)) _CUPS_PUBLIC +# endif /* _CUPS_SOURCE */ + + +/* + * Define _CUPS_NONNULL macro for functions that don't expect non-null + * arguments... + */ + +# ifdef _CUPS_HAS_NONNULL +# define _CUPS_NONNULL(...) __attribute__ ((nonnull(__VA_ARGS__))) +# else +# define _CUPS_NONNULL(...) +# endif /* _CUPS_HAS_FORMAT */ + + +/* + * Define _CUPS_NORETURN macro for functions that don't return. + */ + +# ifdef _CUPS_HAS_NORETURN +# define _CUPS_NORETURN __attribute__ ((noreturn)) +# else +# define _CUPS_NORETURN +# endif /* _CUPS_HAS_NORETURN */ + #endif /* !_CUPS_VERSIONING_H_ */ diff --git a/filter/Makefile b/filter/Makefile index 02aab14d..74fd46f4 100644 --- a/filter/Makefile +++ b/filter/Makefile @@ -218,6 +218,7 @@ apihelp: commandtops: commandtops.o ../cups/$(LIBCUPS) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ commandtops.o $(LIBS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -227,6 +228,7 @@ commandtops: commandtops.o ../cups/$(LIBCUPS) gziptoany: gziptoany.o ../Makedefs ../cups/$(LIBCUPS) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ gziptoany.o $(LIBZ) $(LIBS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -235,8 +237,9 @@ gziptoany: gziptoany.o ../Makedefs ../cups/$(LIBCUPS) libcupsimage.so.2 libcupsimage.sl.2: $(IMAGEOBJS) echo Linking $@... - $(DSO) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(IMAGEOBJS) $(DSOLIBS) \ + $(DSO) $(ARCHFLAGS) $(LDFLAGS) $(DSOFLAGS) -o $@ $(IMAGEOBJS) $(DSOLIBS) \ -L../cups $(LINKCUPS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ $(RM) `basename $@ .2` $(LN) $@ `basename $@ .2` @@ -247,34 +250,23 @@ libcupsimage.so.2 libcupsimage.sl.2: $(IMAGEOBJS) libcupsimage.2.dylib: $(IMAGEOBJS) $(LIBCUPSIMAGEORDER) echo Linking $@... - $(DSO) $(ARCHFLAGS) $(DSOFLAGS) -o $@ \ + $(DSO) $(ARCHFLAGS) $(LDFLAGS) $(DSOFLAGS) -o $@ \ -install_name $(libdir)/$@ \ -current_version 2.3.0 \ -compatibility_version 2.0.0 \ $(IMAGEOBJS) $(DSOLIBS) -L../cups $(LINKCUPS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ $(RM) libcupsimage.dylib $(LN) $@ libcupsimage.dylib # -# libcupsimage_s.a -# - -libcupsimage_s.a: $(IMAGEOBJS) libcupsimage_s.exp - echo Linking $@... - $(DSO) $(DSOFLAGS) -Wl,-berok,-bexport:libcupsimage_s.exp \ - -o libcupsimage_s.o $(IMAGEOBJS) $(DSOLIBS) - $(RM) $@ - $(AR) $(ARFLAGS) $@ libcupsimage_s.o - - -# # libcupsimage.la # libcupsimage.la: $(IMAGEOBJS) echo Linking $@... - $(DSO) $(ARCHFLAGS) $(DSOFLAGS) -o $@ $(IMAGEOBJS:.o=.lo) $(DSOLIBS) \ + $(DSO) $(ARCHFLAGS) $(LDFLAGS) $(DSOFLAGS) -o $@ $(IMAGEOBJS:.o=.lo) $(DSOLIBS) \ -L../cups $(LINKCUPS) \ -rpath $(LIBDIR) -version-info 2:3 @@ -297,6 +289,7 @@ libcupsimage.a: $(IMAGEOBJS) pstops: pstops.o common.o ../cups/$(LIBCUPS) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ pstops.o common.o $(LIBS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -306,6 +299,7 @@ pstops: pstops.o common.o ../cups/$(LIBCUPS) rastertoepson: rastertoepson.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ rastertoepson.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -315,6 +309,7 @@ rastertoepson: rastertoepson.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) rastertohp: rastertohp.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ rastertohp.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -324,6 +319,7 @@ rastertohp: rastertohp.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) rastertolabel: rastertolabel.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ rastertolabel.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -333,12 +329,14 @@ rastertolabel: rastertolabel.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) rastertopwg: rastertopwg.o ../cups/$(LIBCUPS) $(LIBCUPSIMAGE) echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ rastertopwg.o $(LINKCUPSIMAGE) $(IMGLIBS) $(LIBS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ rastertopwg-static: rastertopwg.o ../cups/$(LIBCUPSSTATIC) libcupsimage.a echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ rastertopwg.o libcupsimage.a \ ../cups/$(LIBCUPSSTATIC) $(IMGLIBS) $(DSOLIBS) $(COMMONLIBS) \ $(SSLLIBS) $(DNSSDLIBS) $(LIBGSSAPI) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -350,6 +348,7 @@ testclient: testclient.o ../cups/$(LIBCUPSSTATIC) libcupsimage.a $(LD_CC) $(LDFLAGS) -o $@ testclient.o \ libcupsimage.a ../cups/$(LIBCUPSSTATIC) \ $(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # @@ -361,6 +360,7 @@ testraster: testraster.o ../cups/$(LIBCUPSSTATIC) libcupsimage.a $(LD_CC) $(ARCHFLAGS) $(LDFLAGS) -o $@ testraster.o libcupsimage.a \ ../cups/$(LIBCUPSSTATIC) $(IMGLIBS) $(DSOLIBS) $(COMMONLIBS) \ $(SSLLIBS) $(DNSSDLIBS) $(LIBGSSAPI) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ echo Running raster API tests... ./testraster @@ -372,6 +372,7 @@ testraster: testraster.o ../cups/$(LIBCUPSSTATIC) libcupsimage.a rasterbench: rasterbench.o libcupsimage.a echo Linking $@... $(LD_CC) $(LDFLAGS) -o $@ rasterbench.o libcupsimage.a $(LIBS) + $(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@ # diff --git a/filter/pstops.c b/filter/pstops.c index 072356e2..fab60d93 100644 --- a/filter/pstops.c +++ b/filter/pstops.c @@ -1,8 +1,8 @@ /* * PostScript filter for CUPS. * - * Copyright 2007-2015 by Apple Inc. - * Copyright 1993-2007 by Easy Software Products. + * Copyright © 2007-2018 by Apple Inc. + * Copyright © 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the * property of Apple Inc. and are protected by Federal copyright @@ -162,8 +162,7 @@ static ssize_t copy_trailer(cups_file_t *fp, pstops_doc_t *doc, ssize_t linelen, size_t linesize); static void do_prolog(pstops_doc_t *doc, ppd_file_t *ppd); static void do_setup(pstops_doc_t *doc, ppd_file_t *ppd); -static void doc_printf(pstops_doc_t *doc, const char *format, ...) - __attribute__ ((__format__ (__printf__, 2, 3))); +static void doc_printf(pstops_doc_t *doc, const char *format, ...) _CUPS_FORMAT(2, 3); static void doc_puts(pstops_doc_t *doc, const char *s); static void doc_write(pstops_doc_t *doc, const char *s, size_t len); static void end_nup(pstops_doc_t *doc, int number); @@ -2235,7 +2234,7 @@ parse_text(const char *start, /* I - Start of text value */ bufptr = buffer; bufend = buffer + bufsize - 1; - while (bufptr < bufend) + while (*start && bufptr < bufend) { if (isspace(*start & 255) && !level) break; diff --git a/filter/raster.c b/filter/raster.c index bacf5ba7..3ff03008 100644 --- a/filter/raster.c +++ b/filter/raster.c @@ -1,7 +1,7 @@ /* * Raster file routines for CUPS. * - * Copyright 2007-2016 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1997-2006 by Easy Software Products. * * This file is part of the CUPS Imaging library. @@ -50,11 +50,96 @@ struct _cups_raster_s /**** Raster stream data ****/ *bufend; /* End of current (read) buffer */ size_t bufsize; /* Buffer size */ #ifdef DEBUG - size_t iocount; /* Number of bytes read/written */ + size_t iostart, /* Start of read/write buffer */ + iocount; /* Number of bytes read/written */ #endif /* DEBUG */ unsigned apple_page_count;/* Apple raster page count */ }; +typedef void (*_cups_copyfunc_t)(void *dst, const void *src, size_t bytes); + + +/* + * Local globals... + */ + +#ifdef DEBUG + static const char * const cups_color_spaces[] = + { /* Color spaces */ + "CUPS_CSPACE_W", + "CUPS_CSPACE_RGB", + "CUPS_CSPACE_RGBA", + "CUPS_CSPACE_K", + "CUPS_CSPACE_CMY", + "CUPS_CSPACE_YMC", + "CUPS_CSPACE_CMYK", + "CUPS_CSPACE_YMCK", + "CUPS_CSPACE_KCMY", + "CUPS_CSPACE_KCMYcm", + "CUPS_CSPACE_GMCK", + "CUPS_CSPACE_GMCS", + "CUPS_CSPACE_WHITE", + "CUPS_CSPACE_GOLD", + "CUPS_CSPACE_SILVER", + "CUPS_CSPACE_CIEXYZ", + "CUPS_CSPACE_CIELab", + "CUPS_CSPACE_RGBW", + "CUPS_CSPACE_SW", + "CUPS_CSPACE_SRGB", + "CUPS_CSPACE_ADOBERGB", + "21", + "22", + "23", + "24", + "25", + "26", + "27", + "28", + "29", + "30", + "31", + "CUPS_CSPACE_ICC1", + "CUPS_CSPACE_ICC2", + "CUPS_CSPACE_ICC3", + "CUPS_CSPACE_ICC4", + "CUPS_CSPACE_ICC5", + "CUPS_CSPACE_ICC6", + "CUPS_CSPACE_ICC7", + "CUPS_CSPACE_ICC8", + "CUPS_CSPACE_ICC9", + "CUPS_CSPACE_ICCA", + "CUPS_CSPACE_ICCB", + "CUPS_CSPACE_ICCC", + "CUPS_CSPACE_ICCD", + "CUPS_CSPACE_ICCE", + "CUPS_CSPACE_ICCF", + "47", + "CUPS_CSPACE_DEVICE1", + "CUPS_CSPACE_DEVICE2", + "CUPS_CSPACE_DEVICE3", + "CUPS_CSPACE_DEVICE4", + "CUPS_CSPACE_DEVICE5", + "CUPS_CSPACE_DEVICE6", + "CUPS_CSPACE_DEVICE7", + "CUPS_CSPACE_DEVICE8", + "CUPS_CSPACE_DEVICE9", + "CUPS_CSPACE_DEVICEA", + "CUPS_CSPACE_DEVICEB", + "CUPS_CSPACE_DEVICEC", + "CUPS_CSPACE_DEVICED", + "CUPS_CSPACE_DEVICEE", + "CUPS_CSPACE_DEVICEF" + }; + static const char * const cups_modes[] = + { /* Open modes */ + "CUPS_RASTER_READ", + "CUPS_RASTER_WRITE", + "CUPS_RASTER_WRITE_COMPRESSED", + "CUPS_RASTER_WRITE_PWG", + "CUPS_RASTER_WRITE_APPLE" + }; +#endif /* DEBUG */ + /* * Local functions... @@ -62,13 +147,12 @@ struct _cups_raster_s /**** Raster stream data ****/ static ssize_t cups_raster_io(cups_raster_t *r, unsigned char *buf, size_t bytes); static unsigned cups_raster_read_header(cups_raster_t *r); -static ssize_t cups_raster_read(cups_raster_t *r, unsigned char *buf, - size_t bytes); +static ssize_t cups_raster_read(cups_raster_t *r, unsigned char *buf, size_t bytes); static int cups_raster_update(cups_raster_t *r); -static ssize_t cups_raster_write(cups_raster_t *r, - const unsigned char *pixels); +static ssize_t cups_raster_write(cups_raster_t *r, const unsigned char *pixels); static ssize_t cups_read_fd(void *ctx, unsigned char *buf, size_t bytes); static void cups_swap(unsigned char *buf, size_t bytes); +static void cups_swap_copy(unsigned char *dst, const unsigned char *src, size_t bytes); static ssize_t cups_write_fd(void *ctx, unsigned char *buf, size_t bytes); @@ -356,6 +440,8 @@ cupsRasterOpen(int fd, /* I - File descriptor */ @code CUPS_RASTER_WRITE_COMPRESSED@, or @code CUPS_RASTER_WRITE_PWG@ */ { + DEBUG_printf(("cupsRasterOpen(fd=%d, mode=%s)", fd, cups_modes[mode])); + if (mode == CUPS_RASTER_READ) return (cupsRasterOpenIO(cups_read_fd, (void *)((intptr_t)fd), mode)); else @@ -387,12 +473,15 @@ cupsRasterOpenIO( cups_raster_t *r; /* New stream */ + DEBUG_printf(("cupsRasterOpenIO(iocb=%p, ctx=%p, mode=%s)", (void *)iocb, ctx, cups_modes[mode])); + _cupsRasterClearError(); if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL) { _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n", strerror(errno)); + DEBUG_puts("1cupsRasterOpenIO: Returning NULL."); return (NULL); } @@ -412,6 +501,7 @@ cupsRasterOpenIO( _cupsRasterAddError("Unable to read header from raster stream: %s\n", strerror(errno)); free(r); + DEBUG_puts("1cupsRasterOpenIO: Unable to read header, returning NULL."); return (NULL); } @@ -426,6 +516,7 @@ cupsRasterOpenIO( { _cupsRasterAddError("Unknown raster format %08x!\n", r->sync); free(r); + DEBUG_puts("1cupsRasterOpenIO: Unknown format, returning NULL."); return (NULL); } @@ -435,6 +526,8 @@ cupsRasterOpenIO( r->sync == CUPS_RASTER_REVSYNCapple) r->compressed = 1; + DEBUG_printf(("1cupsRasterOpenIO: sync=%08x", r->sync)); + if (r->sync == CUPS_RASTER_REVSYNC || r->sync == CUPS_RASTER_REVSYNCv1 || r->sync == CUPS_RASTER_REVSYNCv2 || @@ -452,12 +545,14 @@ cupsRasterOpenIO( _cupsRasterAddError("Unable to read header from raster stream: %s\n", strerror(errno)); free(r); + DEBUG_puts("1cupsRasterOpenIO: Unable to read header, returning NULL."); return (NULL); } - } - DEBUG_printf(("1cupsRasterOpenIO: r->swapped=%d, r->sync=%08x\n", r->swapped, r->sync)); +#ifdef DEBUG + r->iostart = r->iocount; +#endif /* DEBUG */ } else { @@ -496,10 +591,13 @@ cupsRasterOpenIO( _cupsRasterAddError("Unable to write raster stream header: %s\n", strerror(errno)); free(r); + DEBUG_puts("1cupsRasterOpenIO: Unable to write header, returning NULL."); return (NULL); } } + DEBUG_printf(("1cupsRasterOpenIO: compressed=%d, swapped=%d, returning %p", r->compressed, r->swapped, (void *)r)); + return (r); } @@ -522,6 +620,8 @@ cupsRasterReadHeader( cups_raster_t *r, /* I - Raster stream */ cups_page_header_t *h) /* I - Pointer to header data */ { + DEBUG_printf(("cupsRasterReadHeader(r=%p, h=%p)", (void *)r, (void *)h)); + /* * Get the raster header... */ @@ -529,6 +629,7 @@ cupsRasterReadHeader( if (!cups_raster_read_header(r)) { memset(h, 0, sizeof(cups_page_header_t)); + DEBUG_puts("1cupsRasterReadHeader: Unable to read page header, returning 0."); return (0); } @@ -538,6 +639,14 @@ cupsRasterReadHeader( memcpy(h, &(r->header), sizeof(cups_page_header_t)); + DEBUG_printf(("1cupsRasterReadHeader: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace])); + DEBUG_printf(("1cupsRasterReadHeader: cupsBitsPerColor=%u", h->cupsBitsPerColor)); + DEBUG_printf(("1cupsRasterReadHeader: cupsBitsPerPixel=%u", h->cupsBitsPerPixel)); + DEBUG_printf(("1cupsRasterReadHeader: cupsBytesPerLine=%u", h->cupsBytesPerLine)); + DEBUG_printf(("1cupsRasterReadHeader: cupsWidth=%u", h->cupsWidth)); + DEBUG_printf(("1cupsRasterReadHeader: cupsHeight=%u", h->cupsHeight)); + + DEBUG_puts("1cupsRasterReadHeader: Returning 1."); return (1); } @@ -563,6 +672,7 @@ cupsRasterReadHeader2( if (!cups_raster_read_header(r)) { memset(h, 0, sizeof(cups_page_header2_t)); + DEBUG_puts("1cupsRasterReadHeader2: Unable to read header, returning 0."); return (0); } @@ -572,6 +682,14 @@ cupsRasterReadHeader2( memcpy(h, &(r->header), sizeof(cups_page_header2_t)); + DEBUG_printf(("1cupsRasterReadHeader2: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace])); + DEBUG_printf(("1cupsRasterReadHeader2: cupsBitsPerColor=%u", h->cupsBitsPerColor)); + DEBUG_printf(("1cupsRasterReadHeader2: cupsBitsPerPixel=%u", h->cupsBitsPerPixel)); + DEBUG_printf(("1cupsRasterReadHeader2: cupsBytesPerLine=%u", h->cupsBytesPerLine)); + DEBUG_printf(("1cupsRasterReadHeader2: cupsWidth=%u", h->cupsWidth)); + DEBUG_printf(("1cupsRasterReadHeader2: cupsHeight=%u", h->cupsHeight)); + + DEBUG_puts("1cupsRasterReadHeader2: Returning 1."); return (1); } @@ -777,7 +895,10 @@ cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */ r->header.cupsBitsPerPixel == 12 || r->header.cupsBitsPerPixel == 16) && r->swapped) - cups_swap(ptr, (size_t)bytes); + { + DEBUG_puts("1cupsRasterReadPixels: Swapping bytes."); + cups_swap(ptr, (size_t)cupsBytesPerLine); + } /* * Update pointers... @@ -847,8 +968,20 @@ cupsRasterWriteHeader( cups_raster_t *r, /* I - Raster stream */ cups_page_header_t *h) /* I - Raster page header */ { + DEBUG_printf(("cupsRasterWriteHeader(r=%p, h=%p)", (void *)r, (void *)h)); + if (r == NULL || r->mode == CUPS_RASTER_READ) + { + DEBUG_puts("1cupsRasterWriteHeader: Returning 0."); return (0); + } + + DEBUG_printf(("1cupsRasterWriteHeader: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace])); + DEBUG_printf(("1cupsRasterWriteHeader: cupsBitsPerColor=%u", h->cupsBitsPerColor)); + DEBUG_printf(("1cupsRasterWriteHeader: cupsBitsPerPixel=%u", h->cupsBitsPerPixel)); + DEBUG_printf(("1cupsRasterWriteHeader: cupsBytesPerLine=%u", h->cupsBytesPerLine)); + DEBUG_printf(("1cupsRasterWriteHeader: cupsWidth=%u", h->cupsWidth)); + DEBUG_printf(("1cupsRasterWriteHeader: cupsHeight=%u", h->cupsHeight)); /* * Make a copy of the header, and compute the number of raster @@ -859,7 +992,20 @@ cupsRasterWriteHeader( memcpy(&(r->header), h, sizeof(cups_page_header_t)); if (!cups_raster_update(r)) + { + DEBUG_puts("1cupsRasterWriteHeader: Unable to update parameters, returning 0."); return (0); + } + + if (r->mode == CUPS_RASTER_WRITE_APPLE) + { + r->rowheight = h->HWResolution[0] / h->HWResolution[1]; + + if (h->HWResolution[0] != (r->rowheight * h->HWResolution[1])) + return (0); + } + else + r->rowheight = 1; /* * Write the raster header... @@ -1019,8 +1165,20 @@ cupsRasterWriteHeader2( cups_raster_t *r, /* I - Raster stream */ cups_page_header2_t *h) /* I - Raster page header */ { + DEBUG_printf(("cupsRasterWriteHeader(r=%p, h=%p)", (void *)r, (void *)h)); + if (r == NULL || r->mode == CUPS_RASTER_READ) + { + DEBUG_puts("1cupsRasterWriteHeader2: Returning 0."); return (0); + } + + DEBUG_printf(("1cupsRasterWriteHeader2: cupsColorSpace=%s", cups_color_spaces[h->cupsColorSpace])); + DEBUG_printf(("1cupsRasterWriteHeader2: cupsBitsPerColor=%u", h->cupsBitsPerColor)); + DEBUG_printf(("1cupsRasterWriteHeader2: cupsBitsPerPixel=%u", h->cupsBitsPerPixel)); + DEBUG_printf(("1cupsRasterWriteHeader2: cupsBytesPerLine=%u", h->cupsBytesPerLine)); + DEBUG_printf(("1cupsRasterWriteHeader2: cupsWidth=%u", h->cupsWidth)); + DEBUG_printf(("1cupsRasterWriteHeader2: cupsHeight=%u", h->cupsHeight)); /* * Make a copy of the header, and compute the number of raster @@ -1030,7 +1188,10 @@ cupsRasterWriteHeader2( memcpy(&(r->header), h, sizeof(cups_page_header2_t)); if (!cups_raster_update(r)) + { + DEBUG_puts("1cupsRasterWriteHeader: Unable to update parameters, returning 0."); return (0); + } if (r->mode == CUPS_RASTER_WRITE_APPLE) { @@ -1202,7 +1363,6 @@ cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */ r->header.cupsBitsPerPixel == 16)) { unsigned char *bufptr; /* Pointer into write buffer */ - unsigned count; /* Remaining count */ /* * Allocate a write buffer as needed... @@ -1223,21 +1383,10 @@ cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */ } /* - * Byte swap the pixels... + * Byte swap the pixels and write them... */ - for (bufptr = r->buffer, count = len; count > 1; count -= 2, bufptr += 2) - { - bufptr[1] = *p++; - bufptr[0] = *p++; - } - - if (count) /* This should never happen... */ - *bufptr = *p; - - /* - * Write the byte-swapped buffer... - */ + cups_swap_copy(r->buffer, p, len); bytes = cups_raster_io(r, r->buffer, len); } @@ -1368,7 +1517,7 @@ cups_raster_read_header( size_t len; /* Length for read/swap */ - DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%d", (void *)r, r ? r->mode : 0)); + DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%s", (void *)r, r ? cups_modes[r->mode] : "")); if (r == NULL || r->mode != CUPS_RASTER_READ) return (0); @@ -1523,10 +1672,7 @@ cups_raster_io(cups_raster_t *r, /* I - Raster stream */ DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count, (int)total)); if (count == 0) - { - DEBUG_puts("6cups_raster_io: Returning 0."); - return (0); - } + break; else if (count < 0) { DEBUG_puts("6cups_raster_io: Returning -1 on error."); @@ -1538,6 +1684,7 @@ cups_raster_io(cups_raster_t *r, /* I - Raster stream */ #endif /* DEBUG */ } + DEBUG_printf(("6cups_raster_io: iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount)); DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT ".", CUPS_LLCAST total)); return (total); @@ -1558,7 +1705,7 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */ total; /* Total bytes read */ - DEBUG_printf(("5cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)r, (void *)buf, CUPS_LLCAST bytes)); + DEBUG_printf(("4cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT "), offset=" CUPS_LLFMT, (void *)r, (void *)buf, CUPS_LLCAST bytes, CUPS_LLCAST (r->iostart + r->bufptr - r->buffer))); if (!r->compressed) return (cups_raster_io(r, buf, bytes)); @@ -1602,7 +1749,7 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */ { count = (ssize_t)bytes - total; - DEBUG_printf(("6cups_raster_read: count=" CUPS_LLFMT ", remaining=" CUPS_LLFMT ", buf=%p, bufptr=%p, bufend=%p", CUPS_LLCAST count, CUPS_LLCAST remaining, (void *)buf, (void *)r->bufptr, (void *)r->bufend)); + DEBUG_printf(("5cups_raster_read: count=" CUPS_LLFMT ", remaining=" CUPS_LLFMT ", buf=%p, bufptr=%p, bufend=%p", CUPS_LLCAST count, CUPS_LLCAST remaining, (void *)buf, (void *)r->bufptr, (void *)r->bufend)); if (remaining == 0) { @@ -1612,6 +1759,10 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */ * Read into the raster buffer and then copy... */ +#ifdef DEBUG + r->iostart += (size_t)(r->bufend - r->buffer); +#endif /* DEBUG */ + remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize); if (remaining <= 0) return (0); @@ -1635,6 +1786,7 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */ return (0); #ifdef DEBUG + r->iostart += (size_t)count; r->iocount += (size_t)count; #endif /* DEBUG */ @@ -1687,7 +1839,7 @@ cups_raster_read(cups_raster_t *r, /* I - Raster stream */ } } - DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total)); + DEBUG_printf(("5cups_raster_read: Returning %ld", (long)total)); return (total); } @@ -1850,11 +2002,24 @@ cups_raster_write( unsigned char *wptr; /* Pointer into write buffer */ unsigned bpp, /* Bytes per pixel */ count; /* Count */ + _cups_copyfunc_t cf; /* Copy function */ DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r, (void *)pixels)); /* + * Determine whether we need to swap bytes... + */ + + if (r->swapped && (r->header.cupsBitsPerColor == 16 || r->header.cupsBitsPerPixel == 12 || r->header.cupsBitsPerPixel == 16)) + { + DEBUG_puts("4cups_raster_write: Swapping bytes when writing."); + cf = (_cups_copyfunc_t)cups_swap_copy; + } + else + cf = (_cups_copyfunc_t)memcpy; + + /* * Allocate a write buffer as needed... */ @@ -1905,8 +2070,8 @@ cups_raster_write( */ *wptr++ = 0; - for (count = bpp; count > 0; count --) - *wptr++ = *start++; + (*cf)(wptr, start, bpp); + wptr += bpp; } else if (!memcmp(start, ptr, bpp)) { @@ -1919,8 +2084,9 @@ cups_raster_write( break; *wptr++ = (unsigned char)(count - 1); - for (count = bpp; count > 0; count --) - *wptr++ = *ptr++; + (*cf)(wptr, ptr, bpp); + wptr += bpp; + ptr += bpp; } else { @@ -1941,7 +2107,7 @@ cups_raster_write( *wptr++ = (unsigned char)(257 - count); count *= bpp; - memcpy(wptr, start, count); + (*cf)(wptr, start, count); wptr += count; } } @@ -1966,18 +2132,18 @@ cups_read_fd(void *ctx, /* I - File descriptor as pointer */ ssize_t count; /* Number of bytes read */ -#ifdef WIN32 /* Sigh */ +#ifdef _WIN32 /* Sigh */ while ((count = read(fd, buf, (unsigned)bytes)) < 0) #else while ((count = read(fd, buf, bytes)) < 0) -#endif /* WIN32 */ +#endif /* _WIN32 */ if (errno != EINTR && errno != EAGAIN) { - DEBUG_printf(("4cups_read_fd: %s", strerror(errno))); + DEBUG_printf(("8cups_read_fd: %s", strerror(errno))); return (-1); } - DEBUG_printf(("4cups_read_fd: Returning %d bytes.", (int)count)); + DEBUG_printf(("8cups_read_fd: Returning %d bytes.", (int)count)); return (count); } @@ -2010,6 +2176,30 @@ cups_swap(unsigned char *buf, /* I - Buffer to swap */ /* + * 'cups_swap_copy()' - Copy and swap bytes in raster data... + */ + +static void +cups_swap_copy( + unsigned char *dst, /* I - Destination */ + const unsigned char *src, /* I - Source */ + size_t bytes) /* I - Number of bytes to swap */ +{ + bytes /= 2; + + while (bytes > 0) + { + dst[0] = src[1]; + dst[1] = src[0]; + + dst += 2; + src += 2; + bytes --; + } +} + + +/* * 'cups_write_fd()' - Write bytes to a file. */ @@ -2023,14 +2213,14 @@ cups_write_fd(void *ctx, /* I - File descriptor pointer */ ssize_t count; /* Number of bytes written */ -#ifdef WIN32 /* Sigh */ +#ifdef _WIN32 /* Sigh */ while ((count = write(fd, buf, (unsigned)bytes)) < 0) #else while ((count = write(fd, buf, bytes)) < 0) -#endif /* WIN32 */ +#endif /* _WIN32 */ if (errno != EINTR && errno != EAGAIN) { - DEBUG_printf(("4cups_write_fd: %s", strerror(errno))); + DEBUG_printf(("8cups_write_fd: %s", strerror(errno))); return (-1); } diff --git a/filter/rastertoepson.c b/filter/rastertoepson.c index 4efe6692..3de491f9 100644 --- a/filter/rastertoepson.c +++ b/filter/rastertoepson.c @@ -1,7 +1,7 @@ /* * EPSON ESC/P and ESC/P2 filter for CUPS. * - * Copyright 2007-2015 by Apple Inc. + * Copyright 2007-2018 by Apple Inc. * Copyright 1993-2007 by Easy Software Products. * * These coded instructions, statements, and computer programs are the @@ -307,7 +307,7 @@ StartPage( if (DotBytes) { - if ((LineBuffers[0] = calloc((size_t)DotBytes, header->cupsWidth * (size_t)(Shingling + 1))) == NULL) + if ((LineBuffers[0] = calloc((size_t)DotBytes, (header->cupsWidth + 7) * (size_t)(Shingling + 1))) == NULL) { fputs("ERROR: Unable to allocate memory\n", stderr); exit(1); diff --git a/filter/rastertolabel.c b/filter/rastertolabel.c index 4e491811..6ad6c625 100644 --- a/filter/rastertolabel.c +++ b/filter/rastertolabel.c @@ -305,7 +305,7 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */ header->HWResolution[1], header->cupsHeight, header->NumCopies); printf("PAGE-WIDTH %u\r\n", header->cupsWidth); - printf("PAGE-HEIGHT %u\r\n", header->cupsWidth); + printf("PAGE-HEIGHT %u\r\n", header->cupsHeight); break; case INTELLITECH_PCL : @@ -374,7 +374,7 @@ StartPage(ppd_file_t *ppd, /* I - PPD file */ if (header->cupsCompression != ~0U) /* inPrintDensity */ - printf("\033&d%uA", 30 * header->cupsCompression / 100 - 15); + printf("\033&d%dA", 30 * header->cupsCompression / 100 - 15); if ((choice = ppdFindMarkedChoice(ppd, "inPrintMode")) != NULL) { diff --git a/filter/spec-ppd.shtml b/filter/spec-ppd.shtml index 3b754308..53494ade 100644 --- a/filter/spec-ppd.shtml +++ b/filter/spec-ppd.shtml @@ -1297,7 +1297,20 @@ http://www.vendor.com/help" <p class='summary'>*cupsJobPassword: "format"</p> -<p>This keyword defines the format of the job-password IPP attribute, if supported by the printer. Currently the only supported format is "1111" indicating a 4-digit PIN code.</p> +<p>This keyword defines the format of the "job-password" IPP attribute, if supported by the printer. The following format characters are supported:</p> + +<ul> + <li><code>1</code>: US ASCII digits.</li> + <li><code>A</code>: US ASCII letters.</li> + <li><code>C</code>: US ASCII letters, numbers, and punctuation.</li> + <li><code>.</code>: Any US ASCII printable character (0x20 to 0x7e).</li> + <li><code>N</code>: Any Unicode digit character.</li> + <li><code>U</code>: Any Unicode letter character.</li> + <li><code>*</code>: Any Unicode (utf-8) character.</li> +</ul> + +<p>The format characters are repeated to indicate the length of the +password string. For example, "1111" indicated a 4-digit US ASCII PIN code.</p> <p>Example:</p> @@ -1581,7 +1594,7 @@ PPD file extensions was used. Currently it must be the string <h2 class='title'><a name='MACOSX'>macOS Attributes</a></h2> -<h3><span class='info'>macOS 10.3</span><a name='APDialogExtension'>APDialogExtension</a></h3> +<h3><span class='info'>Deprecated</span><a name='APDialogExtension'>APDialogExtension</a></h3> <p class='summary'>*APDialogExtension: "/Library/Printers/vendor/filename.plugin"</p> @@ -1593,9 +1606,13 @@ plug-ins.</p> <blockquote><b>Note:</b> -<p>Starting with macOS 10.5, each plug-in must be compiled "4-way fat" -(32-bit and 64-bit for both PowerPC and Intel) with garbage collection enabled -in order to be usable with all applications.</p> +<p>Since 2010, AirPrint has enabled the printing of full quality photos and +documents from the Mac without requiring driver software. Starting with macOS +10.12, system level security features prevent print dialog plug-ins from being +loaded into applications that have enabled the library validation security +feature. As of macOS 10.14 the <code>APDialogExtension</code> attribute used to +create macOS print drivers is deprecated. All new printer models should support +AirPrint moving forward.</p> </blockquote> diff --git a/libcups_version b/libcups_version index 437a354a..2a644933 100644 --- a/libcups_version +++ b/libcups_version @@ -1 +1 @@ -v2.2.6 +v2.2.9 |