Merge the android-9.0.0_r55 release tag
Android 9.0.0 Release 55 (6197209)

* tag 'android-9.0.0_r55':
  Update libcups to v2.2.9

Change-Id: I07cfaec053f0fad91638ad8cfc2b73ff0cb87744
diff --git a/config.h b/config.h
index 28fe034..03e12da 100644
--- a/config.h
+++ b/config.h
@@ -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 9a220c8..f83c937 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 @@
 
 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 @@
 		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.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 @@
 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 @@
 	echo Linking $@...
 	$(LD_CC) $(LDFLAGS) -o $@ testadmin.o $(LIBCUPSSTATIC) \
 		$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+	$(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@
 
 
 #
@@ -397,6 +400,7 @@
 	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 @@
 	echo Linking $@...
 	$(LD_CC) $(LDFLAGS) -o $@ testcache.o $(LIBCUPSSTATIC) \
 		$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+	$(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@
 
 
 #
@@ -419,6 +424,7 @@
 	echo Linking $@...
 	$(LD_CC) $(LDFLAGS) -o $@ testconflicts.o $(LIBCUPSSTATIC) \
 		$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+	$(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@
 
 
 #
@@ -429,6 +435,7 @@
 	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 @@
 	echo Linking $@...
 	$(LD_CC) $(LDFLAGS) -o $@ testcups.o $(LIBCUPSSTATIC) \
 		$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+	$(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@
 
 
 #
@@ -449,6 +457,7 @@
 	echo Linking $@...
 	$(LD_CC) $(LDFLAGS) -o $@ testdest.o $(LIBCUPSSTATIC) \
 		$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+	$(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@
 
 
 #
@@ -459,6 +468,7 @@
 	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 @@
 	echo Linking $@...
 	$(LD_CC) $(LDFLAGS) -o $@ testgetdests.o $(LIBCUPSSTATIC) \
 		$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+	$(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@
 
 
 #
@@ -481,6 +492,7 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	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 @@
 	echo Linking $@...
 	$(LD_CC) $(LDFLAGS) -o $@ testsnmp.o $(LIBCUPSSTATIC) \
 		$(LIBGSSAPI) $(SSLLIBS) $(DNSSDLIBS) $(COMMONLIBS) $(LIBZ)
+	$(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@
 
 
 #
@@ -587,6 +606,7 @@
 	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 adb1f7a..375b905 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 @@
 		 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 @@
     return (WEXITSTATUS(status));
   else
     return (-WTERMSIG(status));
-#endif /* WIN32 */
+#endif /* _WIN32 */
 }
 
 
@@ -2172,9 +2172,9 @@
     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 @@
   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 @@
       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 50c4850..4940946 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 c051c86..a1f5042 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 @@
  * 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 @@
     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 @@
   }
 
  /*
-  * 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 */
-
-    cg = _cupsGlobals();
-
-    if (!cg->lang_default)
-      cg->lang_default = cupsLangDefault();
-
-    if (httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "username",
-                        default_username))
-      cupsSetUser(default_username);
-
-    snprintf(prompt, sizeof(prompt),
-             _cupsLangString(cg->lang_default, _("Password for %s on %s? ")),
-	     cupsUser(),
-	     http->hostname[0] == '/' ? "localhost" : http->hostname);
-
-    http->digest_tries  = _cups_strncasecmp(www_auth, "Digest", 6) != 0;
-    http->userpass[0]   = '\0';
-
-    if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
-    {
-      http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
-      return (-1);
-    }
-
-    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);
-  }
-
- /*
-  * Got a password; encode it for the server...
-  */
-
 #ifdef HAVE_GSSAPI
-  if (!_cups_strncasecmp(www_auth, "Negotiate", 9))
-  {
+    if (!_cups_strcasecmp(scheme, "Negotiate"))
+    {
+     /*
+      * Kerberos authentication...
+      */
+
+      if (_cupsSetNegotiateAuthString(http, method, resource))
+      {
+	http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
+	return (-1);
+      }
+
+      break;
+    }
+    else
+#endif /* HAVE_GSSAPI */
+    if (_cups_strcasecmp(scheme, "Basic") && _cups_strcasecmp(scheme, "Digest"))
+      continue;				/* Not supported (yet) */
+
    /*
-    * Kerberos authentication...
+    * See if we should retry the current username:password...
     */
 
-    if (_cupsSetNegotiateAuthString(http, method, resource))
+    if ((http->digest_tries > 1 || !http->userpass[0]) && (!_cups_strcasecmp(scheme, "Basic") || (!_cups_strcasecmp(scheme, "Digest"))))
     {
+     /*
+      * Nope - get a new password from the user...
+      */
+
+      char default_username[HTTP_MAX_VALUE];
+					/* Default username */
+
+      cg = _cupsGlobals();
+
+      if (!cg->lang_default)
+	cg->lang_default = cupsLangDefault();
+
+      if (cups_auth_param(schemedata, "username", default_username, sizeof(default_username)))
+	cupsSetUser(default_username);
+
+      snprintf(prompt, sizeof(prompt), _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), cupsUser(), http->hostname[0] == '/' ? "localhost" : http->hostname);
+
+      http->digest_tries  = _cups_strncasecmp(scheme, "Digest", 6) != 0;
+      http->userpass[0]   = '\0';
+
+      if ((password = cupsGetPassword2(prompt, http, method, resource)) == NULL)
+      {
+	http->status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
+	return (-1);
+      }
+
+      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);
+      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 nonce[HTTP_MAX_VALUE];	/* nonce="xyz" string */
+
+      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));
+
+      if (_httpSetDigestAuthString(http, nonce, method, resource))
+        break;
+    }
   }
-  else if (!_cups_strncasecmp(www_auth, "Digest", 6))
+
+  if (http->authstring)
   {
-   /*
-    * Digest authentication...
-    */
+    DEBUG_printf(("1cupsDoAuthentication: authstring=\"%s\"", http->authstring));
 
-    char	encode[33],		/* MD5 buffer */
-		digest[1024];		/* Digest auth data */
-
-    httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "realm", realm);
-    httpGetSubField(http, HTTP_FIELD_WWW_AUTHENTICATE, "nonce", nonce);
-
-    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);
+    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 @@
 				      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 @@
       }
     }
   }
-#endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */
+#  endif /* HAVE_GSS_ACQUIRED_CRED_EX_F */
 
   if (GSS_ERROR(major_status))
   {
@@ -422,11 +433,11 @@
     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 @@
 
   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 @@
 					/*    -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 @@
   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 @@
   * 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 @@
     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 @@
   }
 #  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 @@
   * 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 @@
   }
 #  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 @@
     * 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 @@
     }
 
     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 @@
   }
 
   return (1);
-#endif /* WIN32 || __EMX__ */
+#endif /* _WIN32 || __EMX__ */
 }
diff --git a/cups/backchannel.c b/cups/backchannel.c
index e804d45..bca04dc 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 @@
   * 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 @@
     * 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 8f5c818..cf3be12 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 @@
  * 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 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 23a0ae1..dc9fe4e 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 @@
  */
 
 #  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 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 bd244fe..b68f5ed 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 @@
 #else
 #  include <sys/time.h>
 #  include <unistd.h>
-#endif /* WIN32 */
+#endif /* _WIN32 */
 #include <regex.h>
 #include <fcntl.h>
 
@@ -83,7 +83,7 @@
  * '_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_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_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 57a8dc9..7ef85a1 100644
--- a/cups/dest.c
+++ b/cups/dest.c
@@ -2090,9 +2090,9 @@
   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 @@
 
   snprintf(filename, sizeof(filename), "%s/lpoptions", cg->cups_serverroot);
 
-#ifndef WIN32
+#ifndef _WIN32
   if (getuid())
   {
    /*
@@ -2152,7 +2152,7 @@
       snprintf(filename, sizeof(filename), "%s/.cups/lpoptions", home);
     }
   }
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
  /*
   * Try to open the file...
@@ -2164,7 +2164,7 @@
     return (-1);
   }
 
-#ifndef WIN32
+#ifndef _WIN32
  /*
   * Set the permissions to 0644 when saving to the /etc/cups/lpoptions
   * file...
@@ -2172,7 +2172,7 @@
 
   if (!getuid())
     fchmod(fileno(fp), 0644);
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
  /*
   * Write each printer; each line looks like:
diff --git a/cups/dir.c b/cups/dir.c
index b7cd400..6b37778 100644
--- a/cups/dir.c
+++ b/cups/dir.c
@@ -26,7 +26,7 @@
  * Windows implementation...
  */
 
-#ifdef WIN32
+#ifdef _WIN32
 #  include <windows.h>
 
 /*
@@ -145,7 +145,7 @@
 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 @@
     * 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 @@
 
   rewinddir(dp->dir);
 }
-#endif /* WIN32 */
+#endif /* _WIN32 */
diff --git a/cups/file-private.h b/cups/file-private.h
index 1f4db79..6789283 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 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 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 5d15054..5c9ddf8 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_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 @@
 
   fprintf(stderr, "%s: %s\n", prefix, message);
 }
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
 
 /*
@@ -526,22 +559,22 @@
 
   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 @@
   * 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 @@
 	}
 
 	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 @@
   * 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 @@
   * 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 @@
 {
   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 @@
     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 @@
     errno = EPERM;
     return (-1);
   }
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
   return (fd);
 }
@@ -2648,7 +2693,7 @@
 
   for (;;)
   {
-#ifdef WIN32
+#ifdef _WIN32
     if (fp->mode == 's')
       total = (ssize_t)recv(fp->fd, buf, (unsigned)bytes, 0);
     else
@@ -2658,7 +2703,7 @@
       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 @@
   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 @@
       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 42abe20..0d3a2e5 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 @@
 			_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 ae33bc5..7749ae0 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 @@
   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 @@
     }
 
     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 @@
       }
     }
 
+    new_auth = 0;
+
     while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
 
     if (status == HTTP_STATUS_UNAUTHORIZED)
@@ -116,6 +144,8 @@
       * See if we can do authentication...
       */
 
+      new_auth = 1;
+
       if (cupsDoAuthentication(http, "GET", resource))
       {
         status = HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED;
@@ -267,6 +297,8 @@
   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 @@
                   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 @@
 
     DEBUG_printf(("2cupsPutFd: status=%d", status));
 
+    new_auth = 0;
+
     if (status == HTTP_STATUS_UNAUTHORIZED)
     {
      /*
@@ -395,6 +453,8 @@
       * 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 8a05c3e..28c993b 100644
--- a/cups/globals.c
+++ b/cups/globals.c
@@ -34,23 +34,23 @@
 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 @@
 {
 #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 @@
 {
 #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 @@
 
   return (TRUE);
 }
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 
 /*
@@ -182,13 +182,13 @@
 {
   _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 @@
   * Then set directories as appropriate...
   */
 
-#ifdef WIN32
+#ifdef _WIN32
   if (!installdir[0])
   {
    /*
@@ -315,7 +315,7 @@
     if ((cg->localedir = getenv("LOCALEDIR")) == NULL)
       cg->localedir = CUPS_LOCALEDIR;
   }
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
   return (cg);
 }
@@ -325,7 +325,7 @@
  * '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 @@
 
   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 ede5461..50dc5fb 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 @@
   }
 
 #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 @@
   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 @@
 
 #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 @@
   _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 61c8638..f8b8131 100644
--- a/cups/http-addr.c
+++ b/cups/http-addr.c
@@ -69,11 +69,11 @@
 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 @@
   * 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 e5fc940..d9a96c4 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 @@
     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 @@
 #  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 @@
 	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 @@
 	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 @@
       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 @@
     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 @@
 	  if (!temp)
 	  {
 	    httpAddrFreeList(first);
+	    freeaddrinfo(results);
 	    _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
 	    return (NULL);
 	  }
@@ -848,11 +851,11 @@
 
         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 f71e564..32cb9ea 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 @@
 #  endif /* __APPLE__ && !_SOCKLEN_T */
 
 #  include <cups/http.h>
-#  include "md5-private.h"
 #  include "ipp-private.h"
 
 #  ifdef HAVE_GNUTLS
@@ -141,7 +140,7 @@
 #    include <sspi.h>
 #  endif /* HAVE_GNUTLS */
 
-#  ifndef WIN32
+#  ifndef _WIN32
 #    include <net/if.h>
 #    include <resolv.h>
 #    ifdef HAVE_GETIFADDRS
@@ -152,11 +151,7 @@
 #        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 @@
 
 #  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 @@
   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 @@
 					/* 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 @@
  * 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 @@
 #    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 @@
 			                 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 76dbb7d..767fbf6 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 @@
 		 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 @@
            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 @@
 
     *ptr = '\0';
 
-    if (*uri != ':')
+    if (*uri != ':' || *scheme == '.' || !*scheme)
     {
       *scheme = '\0';
       return (HTTP_URI_STATUS_BAD_SCHEME);
@@ -1306,6 +1303,152 @@
 
 
 /*
+ * '_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 @@
     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 @@
     _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 @@
 	  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 61b88c9..5c14ef6 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 @@
 			  "WWW-Authenticate",
 			  "Accept-Encoding",
 			  "Allow",
-			  "Server"
+			  "Server",
+			  "Authentication-Info"
 			};
 
 
@@ -325,6 +330,12 @@
       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 @@
     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 @@
     * 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 @@
 	  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 @@
 	* 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 @@
 	  http->error = errno;
 	  continue;
 	}
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
         return (NULL);
       }
@@ -1523,9 +1537,9 @@
 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 @@
     return;
   }
 
-#ifdef WIN32
+#ifdef _WIN32
   WSAStartup(MAKEWORD(2,2), &winsockdata);
 
 #elif !defined(SO_NOSIGPIPE)
@@ -1557,7 +1571,7 @@
 #  else
   signal(SIGPIPE, SIG_IGN);
 #  endif /* !SO_NOSIGPIPE */
-#endif /* WIN32 */
+#endif /* _WIN32 */
 
 #  ifdef HAVE_SSL
   _httpTLSInitialize();
@@ -1713,7 +1727,7 @@
 #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 @@
     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 @@
       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 @@
     }
 
     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 @@
     {
       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 @@
 
   if (bytes < 0)
   {
-#ifdef WIN32
+#ifdef _WIN32
     if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)
       bytes = 0;
     else
@@ -1855,7 +1869,7 @@
       bytes = 0;
     else
       http->error = errno;
-#endif /* WIN32 */
+#endif /* _WIN32 */
   }
   else if (bytes == 0)
   {
@@ -1985,31 +1999,31 @@
   {
     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 @@
 
       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 @@
 	    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 @@
                         "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 @@
   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 @@
     * 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 @@
       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 @@
     _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 @@
       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 @@
 
     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 @@
   }
 
 #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 @@
       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 @@
 	  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 @@
 }
 
 
+/*
+ * '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 @@
   {
     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_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 @@
 
     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 @@
     return;
   }
 
-  memset(&(http->stream), 0, sizeof(http->stream));
-
   switch (coding)
   {
     case _HTTP_CODING_DEFLATE :
@@ -3838,18 +3883,30 @@
         * 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 @@
         * -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 @@
   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 @@
 
   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 @@
 
     if (bytes < 0)
     {
-#ifdef WIN32
+#ifdef _WIN32
       if (WSAGetLastError() != WSAEINTR)
       {
 	http->error = WSAGetLastError();
@@ -4117,7 +4185,7 @@
 	http->error = errno;
 	return (-1);
       }
-#endif /* WIN32 */
+#endif /* _WIN32 */
     }
   }
   while (bytes < 0);
@@ -4131,7 +4199,7 @@
 
   if (bytes < 0)
   {
-#ifdef WIN32
+#ifdef _WIN32
     if (WSAGetLastError() == WSAEINTR)
       bytes = 0;
     else
@@ -4141,7 +4209,7 @@
       bytes = 0;
     else
       http->error = errno;
-#endif /* WIN32 */
+#endif /* _WIN32 */
   }
   else if (bytes == 0)
   {
@@ -4505,7 +4573,7 @@
 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 @@
 
   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 @@
   {
     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 @@
 
 	  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->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 @@
 
     if (bytes < 0)
     {
-#ifdef WIN32
+#ifdef _WIN32
       if (WSAGetLastError() == WSAEINTR)
         continue;
       else if (WSAGetLastError() == WSAEWOULDBLOCK)
@@ -4754,7 +4822,7 @@
         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 c61a79e..e94adae 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 @@
 #    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 @@
 #    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 @@
   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 @@
 
   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 @@
   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 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 675e5f3..d1ad65c 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 @@
     "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 @@
     "media-bottom-margin-supported",
     "media-col",
     "media-col-default",
+    "media-col-ready",
     "media-col-supported",
     "media-color-supported",
     "media-default",
@@ -1015,6 +1019,7 @@
     "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 @@
     "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 @@
     "media-bottom-margin-supported",
     "media-col",
     "media-col-default",
+    "media-col-ready",
     "media-col-supported",
     "media-color-supported",
     "media-default",
@@ -1397,6 +1406,7 @@
     "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 @@
     "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 @@
     "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 @@
     "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",
diff --git a/cups/ipp.c b/cups/ipp.c
index fd8988f..cc9c6af 100644
--- a/cups/ipp.c
+++ b/cups/ipp.c
@@ -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 @@
 			              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 @@
     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 @@
   * 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 @@
     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;
+	 /*
+	  * Otherwise do a normal reference counted copy...
+	  */
 
-    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;
-
-        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 @@
 	    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 @@
 
     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 @@
 	    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 @@
                 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 @@
 
 	    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 @@
 {
   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 @@
   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 @@
 	    }
 	    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 @@
 	    }
 	    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 @@
 
 	  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 @@
 	  }
 	  break;
 
+      case IPP_TAG_UNSUPPORTED_VALUE :
       case IPP_TAG_DEFAULT :
       case IPP_TAG_UNKNOWN :
       case IPP_TAG_NOVALUE :
@@ -6838,14 +6753,14 @@
 
     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_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_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 */
 }
diff --git a/cups/ipp.h b/cups/ipp.h
index 2a4f546..2ee5f1d 100644
--- a/cups/ipp.h
+++ b/cups/ipp.h
@@ -79,11 +79,11 @@
 
 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 49e4b71..f447ef9 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 @@
 #  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 e6d2d44..61280c0 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 a7be679..fa4aaa3 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 @@
 _cupsConvertOptions
 _cupsCreateDest
 _cupsEncodingName
+_cupsFilePeekAhead
 _cupsGet1284Values
 _cupsGetDestResource
 _cupsGetDests
@@ -24,9 +25,6 @@
 _cupsLangPrintf
 _cupsLangPuts
 _cupsLangString
-_cupsMD5Append
-_cupsMD5Finish
-_cupsMD5Init
 _cupsMessageFree
 _cupsMessageLoad
 _cupsMessageLookup
@@ -39,18 +37,6 @@
 _cupsRWLockRead
 _cupsRWLockWrite
 _cupsRWUnlock
-_cupsSNMPClose
-_cupsSNMPCopyOID
-_cupsSNMPDefaultCommunity
-_cupsSNMPIsOID
-_cupsSNMPIsOIDPrefixed
-_cupsSNMPOIDToString
-_cupsSNMPOpen
-_cupsSNMPRead
-_cupsSNMPSetDebug
-_cupsSNMPStringToOID
-_cupsSNMPWalk
-_cupsSNMPWrite
 _cupsSetDefaults
 _cupsSetError
 _cupsSetHTTPError
@@ -65,6 +51,7 @@
 _cupsStrStatistics
 _cupsThreadCancel
 _cupsThreadCreate
+_cupsThreadDetach
 _cupsThreadWait
 _cupsUserDefault
 _cups_safe_vsnprintf
@@ -81,6 +68,7 @@
 _httpEncodeURI
 _httpFreeCredentials
 _httpResolveURI
+_httpSetDigestAuthString
 _httpStatus
 _httpTLSInitialize
 _httpTLSPending
@@ -124,6 +112,7 @@
 _pwgMediaTypeForType
 _pwgPageSizeForMedia
 cupsAddDest
+cupsAddIntegerOption
 cupsAddOption
 cupsAdminCreateWindowsPPD
 cupsAdminExportSamba
@@ -227,6 +216,7 @@
 cupsGetDevices
 cupsGetFd
 cupsGetFile
+cupsGetIntegerOption
 cupsGetJobs
 cupsGetJobs2
 cupsGetNamedDest
@@ -240,6 +230,7 @@
 cupsGetResponse
 cupsGetServerPPD
 cupsHashData
+cupsHashString
 cupsLangDefault
 cupsLangEncoding
 cupsLangFlush
diff --git a/cups/md5.c b/cups/md5.c
index c0f5dd7..d5057bf 100644
--- a/cups/md5.c
+++ b/cups/md5.c
@@ -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 @@
 	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 @@
 	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 @@
 	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 @@
     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 @@
     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 @@
     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 @@
     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 @@
     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 a9817aa..49add7d 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 @@
         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 @@
   */
 
   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 @@
  * '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 @@
 	     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 @@
   */
 
   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 @@
   */
 
   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 @@
               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 925ab80..9ed946e 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 @@
   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 @@
   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 @@
   {
     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 @@
       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 @@
           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 @@
       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 @@
       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 @@
       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 @@
 
   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 @@
 
   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 @@
     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 @@
 
       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 @@
 
     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 @@
         {
           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 @@
 
     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 @@
         {
           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 @@
 
     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 @@
         {
           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 @@
 
     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 @@
 
       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 @@
     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 @@
     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 @@
 
     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 8f875a5..24330ec 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 @@
     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 36e5bca..4b153ac 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 @@
 
     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 ed75bf8..9537ef5 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 @@
 
   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 d0194c8..0974bae 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 @@
     return (HTTP_STATUS_NOT_ACCEPTABLE);
   }
 
-#ifndef WIN32
+#ifndef _WIN32
  /*
   * See if the PPD file is available locally...
   */
@@ -216,6 +216,27 @@
         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 @@
 	*/
 
 	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 @@
       }
     }
   }
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
  /*
   * Try finding a printer URI for this printer...
@@ -511,23 +529,16 @@
     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 @@
   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 @@
 
   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 @@
 	  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)
     {
diff --git a/cups/ppd.c b/cups/ppd.c
index 5bd839d..5f27484 100644
--- a/cups/ppd.c
+++ b/cups/ppd.c
@@ -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 @@
 				       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 @@
 		  _("Bad custom parameter"),
 		  _("Missing option keyword"),
 		  _("Bad value string"),
-		  _("Missing CloseGroup")
+		  _("Missing CloseGroup"),
+		  _("Bad CloseUI/JCLCloseUI"),
+		  _("Missing CloseUI/JCLCloseUI")
 		};
 
 
@@ -1542,8 +1544,29 @@
         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 @@
   }
 
  /*
+  * 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_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
diff --git a/cups/ppd.h b/cups/ppd.h
index fb33c08..6e628cb 100644
--- a/cups/ppd.h
+++ b/cups/ppd.h
@@ -132,6 +132,8 @@
   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 3813581..94dd951 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 efbc06e..a4e4b90 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 @@
       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 @@
       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 @@
       * 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 @@
   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 @@
     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 @@
     * 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 @@
       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 a4cd960..f2dbabd 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 7958b93..8437528 100644
--- a/cups/snmp.c
+++ b/cups/snmp.c
@@ -395,11 +395,11 @@
 
       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 e8448d1..ced2492 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 @@
 #  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 da705a9..7b341e1 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 @@
   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 @@
   */
 
   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 @@
 
   do
   {
-#ifdef WIN32
+#ifdef _WIN32
    /*
     * Get the current time of day...
     */
@@ -108,21 +126,21 @@
     */
 
     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 6164ffc..892e325 100644
--- a/cups/testarray.c
+++ b/cups/testarray.c
@@ -494,7 +494,7 @@
  * 'get_seconds()' - Get the current time in seconds...
  */
 
-#ifdef WIN32
+#ifdef _WIN32
 #  include <windows.h>
 
 
@@ -515,7 +515,7 @@
   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 c5c2052..9eab8d2 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_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 b2ec8cd..1473a4a 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 @@
   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 @@
 
     status += random_tests();
 
-#ifndef WIN32
+#ifndef _WIN32
    /*
     * Test fdopen and close without reading...
     */
@@ -118,7 +115,7 @@
 
       puts("PASS");
     }
-#endif /* !WIN32 */
+#endif /* !_WIN32 */
 
    /*
     * Count lines in psglyphs, rewind, then count again.
@@ -174,13 +171,13 @@
     */
 
     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 376d71f..7d8ec06 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 @@
 			  { 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 @@
 			    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 @@
 			    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 @@
     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 @@
 
   for (i = 1; i < argc; i ++)
   {
+    int new_auth;
+
     if (!strcmp(argv[i], "-o"))
     {
       i ++;
@@ -673,6 +718,8 @@
 
     printf("Checking file \"%s\"...\n", resource);
 
+    new_auth = 0;
+
     do
     {
       if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_CONNECTION), "close"))
@@ -685,9 +732,13 @@
 	}
       }
 
+      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 @@
 
       while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
 
+      new_auth = 0;
+
       if (status == HTTP_STATUS_UNAUTHORIZED)
       {
        /*
@@ -716,7 +769,9 @@
 	* 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 @@
     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 @@
 	}
       }
 
+      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 @@
 
       while ((status = httpUpdate(http)) == HTTP_STATUS_CONTINUE);
 
+      new_auth = 0;
+
       if (status == HTTP_STATUS_UNAUTHORIZED)
       {
        /*
@@ -809,6 +871,8 @@
 	* 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 ea8f9d7..2ef2496 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 e1b5156..a127a79 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 @@
 		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 @@
 
     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 4026a28..9e168ab 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 79d2438..ae8163d 100644
--- a/cups/thread-private.h
+++ b/cups/thread-private.h
@@ -46,7 +46,7 @@
 #    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 65257aa..7ffc2ec 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 @@
   {
     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 @@
 }
 
 
-#elif defined(WIN32)
+#elif defined(_WIN32)
 #  include <process.h>
 
 
@@ -513,8 +521,7 @@
     _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 @@
 
 
 /*
+ * '_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 a8b7de5..c3f9abc 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 @@
  */
 
 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 @@
   }
 
   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 92430ac..c4f0ccb 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 @@
 					/* 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 @@
     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 @@
 
     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 @@
  */
 
 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 @@
   {
     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 @@
 
   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));
-
-    if (!error && (tls_options & _HTTP_TLS_ONLY_TLS10))
+    static const SSLProtocol protocols[] =	/* Min/max protocol versions */
     {
-      error = SSLSetProtocolVersionMax(http->tls, kTLSProtocol1);
-      DEBUG_printf(("4_httpTLSStart: SSLSetProtocolVersionMax(kTLSProtocol1), error=%d", (int)error));
+      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_max_version < _HTTP_TLS_MAX)
+    {
+      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 @@
 
   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 @@
 	    break;
       }
     }
+
+   /*
+    * Restore the previous timeout settings...
+    */
+
+    httpSetTimeout(http, old_timeout, old_cb, old_data);
   }
 
   if (error)
@@ -1864,7 +1899,9 @@
   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 = (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 2dcb7fe..606b45a 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 @@
 					/* 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 @@
     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 @@
 
     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 = (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 @@
  */
 
 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 @@
 					/* 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 @@
 
   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 @@
 #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 @@
       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 6eaec4c..ea3fb00 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 @@
     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 @@
     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 @@
  */
 
 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 @@
 #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;
diff --git a/cups/tls.c b/cups/tls.c
index 36d484c..2539a09 100644
--- a/cups/tls.c
+++ b/cups/tls.c
@@ -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 997e7aa..d16bf1e 100644
--- a/cups/tlscheck.c
+++ b/cups/tlscheck.c
@@ -54,6 +54,8 @@
   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 @@
     }
     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 @@
   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 @@
   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 2a004b5..781f27b 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 @@
 {
   _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 @@
     return;
   }
 
-#ifdef WIN32
+#ifdef _WIN32
   version.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
   GetVersionEx(&version);
   GetNativeSystemInfo(&sysinfo);
@@ -526,7 +528,7 @@
   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 @@
 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 @@
     memset(cg->password, 0, sizeof(cg->password));
     return (NULL);
   }
-#endif /* WIN32 */
+#endif /* _WIN32 */
 }
 
 
@@ -903,7 +905,7 @@
 
 #  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 @@
     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 @@
 
   if (!cc->user[0])
   {
-#ifdef WIN32
+#ifdef _WIN32
    /*
     * Get the current user name from the OS...
     */
@@ -1135,7 +1137,7 @@
     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 @@
 
   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 @@
   * 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 @@
     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 2f5ebdf..ef1709c 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 @@
 {
   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 @@
   * 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 @@
   */
 
   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 @@
   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 5a000c0..620396f 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 02aab14..74fd46f 100644
--- a/filter/Makefile
+++ b/filter/Makefile
@@ -218,6 +218,7 @@
 commandtops:	commandtops.o ../cups/$(LIBCUPS)
 	echo Linking $@...
 	$(LD_CC) $(LDFLAGS) -o $@ commandtops.o $(LIBS)
+	$(CODE_SIGN) -s "$(CODE_SIGN_IDENTITY)" $@
 
 
 #
@@ -227,6 +228,7 @@
 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 @@
 
 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.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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 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 @@
 	$(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 @@
 	$(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 @@
 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 072356e..fab60d9 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 @@
 				     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 @@
   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 bacf5ba..3ff0300 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 @@
 			*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 @@
 
 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 @@
 					       @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 @@
   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 @@
       _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 @@
     {
       _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
       free(r);
+      DEBUG_puts("1cupsRasterOpenIO: Unknown format, returning NULL.");
       return (NULL);
     }
 
@@ -435,6 +526,8 @@
         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 @@
 	_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 @@
       _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 @@
     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 @@
   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 @@
 
   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 @@
   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 @@
 
   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 @@
            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 @@
     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 @@
   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 @@
     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 @@
   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 @@
          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 @@
       }
 
      /*
-      * 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 @@
   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 @@
 
     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 @@
 #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 @@
 		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 @@
   {
     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 @@
         * 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 @@
 	  return (0);
 
 #ifdef DEBUG
+	r->iostart += (size_t)count;
         r->iocount += (size_t)count;
 #endif /* DEBUG */
 
@@ -1687,7 +1839,7 @@
     }
   }
 
-  DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total));
+  DEBUG_printf(("5cups_raster_read: Returning %ld", (long)total));
 
   return (total);
 }
@@ -1850,11 +2002,24 @@
   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 @@
       */
 
       *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 @@
 	  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 @@
       *wptr++ = (unsigned char)(257 - count);
 
       count *= bpp;
-      memcpy(wptr, start, count);
+      (*cf)(wptr, start, count);
       wptr += count;
     }
   }
@@ -1966,18 +2132,18 @@
   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_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 @@
   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 4efe669..3de491f 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 @@
 
   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 4e49181..6ad6c62 100644
--- a/filter/rastertolabel.c
+++ b/filter/rastertolabel.c
@@ -305,7 +305,7 @@
 	       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 @@
 
           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 3b75430..53494ad 100644
--- a/filter/spec-ppd.shtml
+++ b/filter/spec-ppd.shtml
@@ -1297,7 +1297,20 @@
 
 <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 @@
 
 <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 @@
 
 <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 437a354..2a64493 100644
--- a/libcups_version
+++ b/libcups_version
@@ -1 +1 @@
-v2.2.6
+v2.2.9