]> git.ipfire.org Git - thirdparty/cups.git/commitdiff
Merge changes from CUPS 1.7svn-r10755.
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 12 Dec 2012 20:54:21 +0000 (20:54 +0000)
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>
Wed, 12 Dec 2012 20:54:21 +0000 (20:54 +0000)
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@4074 a1ca3aef-8c08-0410-bb20-df032aa958be

40 files changed:
CHANGES-1.6.txt
backend/Makefile
backend/dnssd.c
backend/snmp-supplies.c
berkeley/Makefile
conf/Makefile
conf/cups-files.conf.in
config-scripts/cups-opsys.m4
config-scripts/cups-ssl.m4
cups/Makefile
cups/cups-private.h
cups/dest.c
cups/globals.c
cups/http-addr.c
cups/http-private.h
cups/http-support.c
cups/http.c
cups/http.h
cups/ipp.c
cups/ipp.h
cups/ppd-cache.c
cups/ppd-private.h
cups/pwg-media.c
cups/util.c
cups/versioning.h
doc/Makefile
doc/help/man-ipptoolfile.html
locale/cups_ca.po
locale/cups_es.po
locale/cups_ja.po
man/cupsctl.man
man/ipptoolfile.man
man/ppdcfile.man
notifier/Makefile
systemv/Makefile
systemv/cupstestppd.c
test/Makefile
test/ippserver.c
test/ipptool.c
test/run-stp-tests.sh

index 5ace73229cacb18754203428d521dd16d76a796b..c59c1ca548fbc7f48ad4cebf3130e5a12808c8c6 100644 (file)
@@ -3,10 +3,18 @@ CHANGES-1.6.txt
 
 CHANGES IN CUPS V1.6.2
 
-       - Documentation fixes
+       - Documentation fixes (STR #4239)
        - Security: All file, directory, user, and group settings are now stored
          in a separate cups-files.conf configuration file that cannot be set
          through the CUPS web interface or APIs (STR #4223)
+       - The XML output of ipptool contained empty dictionaries (STR #4136)
+       - The scheduler did not delete job control backup files (STR #4244)
+       - cupsGetPPD3 could return a local PPD instead of the correct remote
+         PPD.
+       - The scheduler incorrectly advertised auth-info-required for local
+         queues needing local authentication (STR #4205)
+       - CUPS 1.6 clients using the ServerName directive in client.conf did not
+         work with CUPS 1.3.x or older servers (STR #4231)
        - The SNMP backend now tries to work around broken printers that use a
          newline to separate key/value pairs.
        - The IPP backend did not send a cancel request to printers when a job
index 902bf6e80195642e477540d5df68cdaf88c95982..c6ddb95b0309006de47bd3b3f6b7414984f873a9 100644 (file)
@@ -134,8 +134,9 @@ install-exec:       $(INSTALLXPC)
        fi
        if test "x$(SYMROOT)" != "x"; then \
                $(INSTALL_DIR) $(SYMROOT); \
-               for file in $(TARGETS); do \
+               for file in $(RBACKENDS) $(UBACKENDS); do \
                        cp $$file $(SYMROOT); \
+                       dsymutil $(SYMROOT)/$$file; \
                done \
        fi
 
index 46c0f134711bf311f5e6a568fcc27e544a91e6d0..9cea92e037d2849655532afe16caa033699760c1 100644 (file)
@@ -1031,6 +1031,7 @@ query_callback(
                value[256],             /* Value string */
                make_and_model[512],    /* Manufacturer and model */
                model[256],             /* Model */
+               pdl[256],               /* PDL */
                device_id[2048];        /* 1284 device ID */
 
 
@@ -1079,6 +1080,7 @@ query_callback(
 
   device_id[0]      = '\0';
   make_and_model[0] = '\0';
+  pdl[0]            = '\0';
 
   strlcpy(model, "Unknown", sizeof(model));
 
@@ -1160,6 +1162,8 @@ query_callback(
       if ((ptr = strchr(model, ',')) != NULL)
        *ptr = '\0';
     }
+    else if (!_cups_strcasecmp(key, "pdl"))
+      strlcpy(pdl, value, sizeof(pdl));
     else if (!_cups_strcasecmp(key, "priority"))
       device->priority = atoi(value);
     else if ((device->type == CUPS_DEVICE_IPP ||
@@ -1204,6 +1208,46 @@ query_callback(
     }
   }
 
+  if (device_id[0] &&
+      !strstr(device_id, "CMD:") &&
+      !strstr(device_id, "COMMAND SET:") &&
+      (strstr(pdl, "application/pdf") ||
+       strstr(pdl, "application/postscript") ||
+       strstr(pdl, "application/vnd.hp-PCL") ||
+       strstr(pdl, "image/")))
+  {
+    value[0] = '\0';
+    if (strstr(pdl, "application/pdf"))
+      strlcat(value, ",PDF", sizeof(value));
+    if (strstr(pdl, "application/postscript"))
+      strlcat(value, ",PS", sizeof(value));
+    if (strstr(pdl, "application/vnd.hp-PCL"))
+      strlcat(value, ",PCL", sizeof(value));
+    for (ptr = strstr(pdl, "image/"); ptr; ptr = strstr(ptr, "image/"))
+    {
+      char *valptr = value + strlen(value);
+                                       /* Pointer into value */
+
+      if (valptr < (value + sizeof(value) - 1))
+        *valptr++ = ',';
+
+      ptr += 6;
+      while (isalnum(*ptr & 255) || *ptr == '-' || *ptr == '.')
+      {
+        if (isalnum(*ptr & 255) && valptr < (value + sizeof(value) - 1))
+          *valptr++ = toupper(*ptr++ & 255);
+        else
+          break;
+      }
+
+      *valptr = '\0';
+    }
+
+    ptr = device_id + strlen(device_id);
+    snprintf(ptr, sizeof(device_id) - (ptr - device_id), "CMD:%s;",
+            value + 1);
+  }
+
   if (device_id[0])
     device->device_id = strdup(device_id);
   else
index 4c0258ddd8ae24ffd0cb9046fa2e433b7c43578b..c669b5db9b95eaec9838a01aae09d61c2af2954d 100644 (file)
@@ -163,7 +163,7 @@ static const int    prtMarkerSuppliesSupplyUnit[] =
                         sizeof(prtMarkerSuppliesSupplyUnit[0]));
                                        /* Offset to supply index */
 
-static const backend_state_t const printer_states[] =
+static const backend_state_t printer_states[] =
                        {
                          /* { CUPS_TC_lowPaper, "media-low-report" }, */
                          { CUPS_TC_noPaper | CUPS_TC_inputTrayEmpty, "media-empty-warning" },
@@ -180,7 +180,7 @@ static const backend_state_t const printer_states[] =
                          { CUPS_TC_outputFull, "output-area-full-warning" }
                        };
 
-static const backend_state_t const supply_states[] =
+static const backend_state_t supply_states[] =
                        {
                          { CUPS_DEVELOPER_LOW, "developer-low-report" },
                          { CUPS_DEVELOPER_EMPTY, "developer-empty-warning" },
index 8a154c5047365ff01deb0befbd8ed4dcfd5ec1f4..8459ea291136fd86cd471be89e97957ad2aec235 100644 (file)
@@ -88,6 +88,7 @@ install-exec:
                $(INSTALL_DIR) $(SYMROOT); \
                for file in $(TARGETS); do \
                        cp $$file $(SYMROOT); \
+                       dsymutil $(SYMROOT)/$$file; \
                done \
        fi
 
index a68a58b16e1c3719d05ca23b142b2a92631a5c60..04cc1e739c044e88f55a3b8ba3cf3200fb48bfff 100644 (file)
@@ -3,7 +3,7 @@
 #
 #   Configuration file makefile for CUPS.
 #
-#   Copyright 2007-2011 by Apple Inc.
+#   Copyright 2007-2012 by Apple Inc.
 #   Copyright 1993-2006 by Easy Software Products.
 #
 #   These coded instructions, statements, and computer programs are the
index 8c3a1b58ce5a4587b4059ff5d2864864ad2f034c..01ee93317a0b7836877e6c845ef8217ed98eaf04 100644 (file)
@@ -39,7 +39,7 @@ AccessLog @CUPS_LOGDIR@/access_log
 #DataDir @CUPS_DATADIR@
 
 # Location of the static web content served by the scheduler...
-#DocRoot @CUPS_DOCROOT@
+#DocumentRoot @CUPS_DOCROOT@
 
 # Location of the file logging all messages produced by the scheduler and any
 # helper programs; may be the name "syslog". If not an absolute path, the value
index ed4dbbc5e48be4db3e93d07c1a13d4970414c37b..acf5b51a34834b6d0ed886c72a809801625854e7 100644 (file)
@@ -19,6 +19,13 @@ uversion=`uname -r | sed -e '1,$s/^[[^0-9]]*\([[0-9]]*\)\.\([[0-9]]*\).*/\1\2/'`
 uarch=`uname -m`
 
 case "$uname" in
+       Darwin*)
+               uname="Darwin"
+               if test $uversion -lt 120; then
+                       AC_MSG_ERROR([Sorry, this version of CUPS requires OS X 10.8 or higher.])
+               fi
+               ;;
+
        GNU* | GNU/*)
                uname="GNU"
                ;;
index 03f7530a362c31a2da45599deee9498480f0f36c..f3dc0595f9be270a89626f2dafa8971fccbdbd51 100644 (file)
@@ -59,34 +59,7 @@ if test x$enable_ssl != xno; then
                AC_CHECK_HEADER(Security/SecIdentitySearchPriv.h,
                    AC_DEFINE(HAVE_SECIDENTITYSEARCHPRIV_H))
 
-               dnl Check for SecCertificateCopyData..
-               AC_MSG_CHECKING(for SecCertificateCopyData)
-               if test $uversion -ge 100; then
-                   AC_DEFINE(HAVE_SECCERTIFICATECOPYDATA)
-                   AC_MSG_RESULT(yes)
-               else
-                   AC_MSG_RESULT(no)
-               fi
-
-               dnl Check for SecIdentitySearchCreateWithPolicy...
-               AC_MSG_CHECKING(for SecIdentitySearchCreateWithPolicy)
-               if test $uversion -ge 80; then
-                   AC_DEFINE(HAVE_SECIDENTITYSEARCHCREATEWITHPOLICY)
-                   AC_MSG_RESULT(yes)
-               else
-                   AC_MSG_RESULT(no)
-               fi
-
-               dnl Check for SecPolicyCreateSSL...
-               AC_MSG_CHECKING(for SecPolicyCreateSSL)
-               if test $uversion -ge 110; then
-                   AC_DEFINE(HAVE_SECPOLICYCREATESSL)
-                   AC_MSG_RESULT(yes)
-               else
-                   AC_MSG_RESULT(no)
-               fi])
-
-               AC_DEFINE(HAVE_CSSMERRORSTRING)
+               AC_DEFINE(HAVE_CSSMERRORSTRING)])
        fi
     fi
 
index 8d5cefd8bb5354c3e7f49329e1f1978273cdb404..8bab2d405140cf421cec7978096394ed9967fc5d 100644 (file)
@@ -251,6 +251,7 @@ install-libs: $(INSTALLSTATIC)
        if test "x$(SYMROOT)" != "x"; then \
                $(INSTALL_DIR) $(SYMROOT); \
                cp $(LIBCUPS) $(SYMROOT); \
+               dsymutil $(SYMROOT)/$(LIBCUPS); \
        fi
 
 installstatic:
index babc0d0814ea637a1d13b2fd01634963e5a85af9..1dd7e8a76420a44d6d6ca8114976d5a1a33ad17b 100644 (file)
@@ -92,6 +92,9 @@ typedef struct _cups_globals_s                /**** CUPS global state data ****/
   int                  thread_id;      /* Friendly thread ID */
 #  endif /* DEBUG */
 
+  /* dest.c, util.c */
+  int                  server_version; /* Server IPP version */
+
   /* file.c */
   cups_file_t          *stdio_files[3];/* stdin, stdout, stderr */
 
index 1474eb41e141ca1a373aa1acdd2da3b56d95739a..ee3fbc12a4c1e4a98a781e360e030727fd798f3a 100644 (file)
@@ -1388,6 +1388,7 @@ _cupsGetDests(http_t       *http, /* I  - Connection to server or
   char         optname[1024],          /* Option name */
                value[2048],            /* Option value */
                *ptr;                   /* Pointer into name/value */
+  _cups_globals_t *cg = _cupsGlobals();        /* Thread global data */
   static const char * const pattrs[] = /* Attributes we're interested in */
                {
                  "auth-info-required",
@@ -1429,45 +1430,62 @@ _cupsGetDests(http_t       *http,       /* I  - Connection to server or
   appleGetPaperSize(media_default, sizeof(media_default));
 #endif /* __APPLE__ */
 
- /*
-  * Build a CUPS_GET_PRINTERS or IPP_GET_PRINTER_ATTRIBUTES request, which
-  * require the following attributes:
-  *
-  *    attributes-charset
-  *    attributes-natural-language
-  *    requesting-user-name
-  *    printer-uri [for IPP_GET_PRINTER_ATTRIBUTES]
-  */
+  for (;;)
+  {
+   /*
+    * Build a CUPS_GET_PRINTERS or IPP_GET_PRINTER_ATTRIBUTES request, which
+    * require the following attributes:
+    *
+    *    attributes-charset
+    *    attributes-natural-language
+    *    requesting-user-name
+    *    printer-uri [for IPP_GET_PRINTER_ATTRIBUTES]
+    */
 
-  request = ippNewRequest(op);
+    request = ippNewRequest(op);
 
-  ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
-                "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
-               NULL, pattrs);
+    ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
 
-  ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
-               "requesting-user-name", NULL, cupsUser());
+    ippAddStrings(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
+                 "requested-attributes", sizeof(pattrs) / sizeof(pattrs[0]),
+                 NULL, pattrs);
 
-  if (name && op != CUPS_GET_DEFAULT)
-  {
-    httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
-                     "localhost", ippPort(), "/printers/%s", name);
-    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
-                 uri);
-  }
-  else if (mask)
-  {
-    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
-                  type);
-    ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
-                  mask);
-  }
+    ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME,
+                "requesting-user-name", NULL, cupsUser());
 
- /*
-  * Do the request and get back a response...
-  */
+    if (name && op != CUPS_GET_DEFAULT)
+    {
+      httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
+                      "localhost", ippPort(), "/printers/%s", name);
+      ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL,
+                  uri);
+    }
+    else if (mask)
+    {
+      ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type",
+                   type);
+      ippAddInteger(request, IPP_TAG_OPERATION, IPP_TAG_ENUM, "printer-type-mask",
+                   mask);
+    }
+
+   /*
+    * Do the request and get back a response...
+    */
+
+    response = cupsDoRequest(http, request, "/");
+    if (cg->server_version != 20 || !response ||
+        cupsLastError() != IPP_BAD_REQUEST)
+      break;
+
+   /*
+    * Retry as an IPP/1.1 request...
+    */
+
+    cg->server_version = 11;
+    ippDelete(response);
+  }
 
-  if ((response = cupsDoRequest(http, request, "/")) != NULL)
+  if (response)
   {
     for (attr = response->attrs; attr != NULL; attr = attr->next)
     {
index eed949f839eff1578328d077943a5b7f104d1b9d..6a7102aa170e5fb0877b3ab260c52bb39bb96b7c 100644 (file)
@@ -214,11 +214,12 @@ cups_globals_alloc(void)
   */
 
   memset(cg, 0, sizeof(_cups_globals_t));
-  cg->encryption    = (http_encryption_t)-1;
-  cg->password_cb   = (cups_password_cb2_t)_cupsGetPassword;
-  cg->any_root      = 1;
-  cg->expired_certs = 1;
-  cg->expired_root  = 1;
+  cg->encryption     = (http_encryption_t)-1;
+  cg->password_cb    = (cups_password_cb2_t)_cupsGetPassword;
+  cg->any_root       = 1;
+  cg->expired_certs  = 1;
+  cg->expired_root   = 1;
+  cg->server_version = 20;
 
 #ifdef DEBUG
  /*
index 3e050e705b9dc2ccb55a61325e8d95becaa61da9..ed6df805741c94b486fe90966867b651d9a3999b 100644 (file)
@@ -382,6 +382,9 @@ httpAddrPort(http_addr_t *addr)             /* I - Address */
     return (ippPort());
 }
 
+/* For OS X 10.8 and earlier */
+int _httpAddrPort(http_addr_t *addr) { return (httpAddrPort(addr)); }
+
 
 /*
  * '_httpAddrSetPort()' - Set the port number associated with an address.
index 12ae6ddb95c8e247052d5e65d8e8d250ccb389cc..a789917de0155d0bb16d110d3b46be434bfac42e 100644 (file)
@@ -291,7 +291,7 @@ struct _http_s                              /**** HTTP connection structure ****/
 
   /**** New in CUPS 1.1.20 ****/
   char                 _authstring[HTTP_MAX_VALUE],
-                                       /* Current Authentication value (deprecated) */
+                                       /* Current Authorization value (deprecated) */
                        userpass[HTTP_MAX_VALUE];
                                        /* Username:password string */
   int                  digest_tries;   /* Number of tries for digest auth */
@@ -307,7 +307,7 @@ struct _http_s                              /**** HTTP connection structure ****/
   /**** New in CUPS 1.3 ****/
   char                 *field_authorization;
                                        /* Authorization field */
-  char                 *authstring;    /* Current authorization field */
+  char                 *authstring;    /* Current Authorization field */
 #  ifdef HAVE_GSSAPI
   gss_OID              gssmech;        /* Authentication mechanism */
   gss_ctx_id_t         gssctx;         /* Authentication context */
@@ -333,7 +333,11 @@ struct _http_s                             /**** HTTP connection structure ****/
   char                 *accept_encoding,
                                        /* Accept-Encoding field */
                        *allow,         /* Allow field */
-                       *server;        /* Server field */
+                       *server,        /* Server field */
+                       *default_accept_encoding,
+                       *default_server,
+                       *default_user_agent;
+                                       /* Default field values */
 #  ifdef HAVE_LIBZ
   _http_coding_t       coding;         /* _HTTP_CODING_xxx */
   z_stream             stream;         /* (De)compression stream */
index 2b0d9a827b35b08510a12deec4c2a5716dd704c4..d0f36c3e151c1a9d1543b2872cec0fe45a214f46 100644 (file)
@@ -327,8 +327,7 @@ httpAssembleURI(
      /*
       * Otherwise, just copy the host string...
       */
-
-      ptr = http_copy_encode(ptr, host, end, ":/?#[]@\\\"", NULL,
+      ptr = http_copy_encode(ptr, host, end, "<>{}|^:/?#[]@\\\"", NULL,
                              encoding & HTTP_URI_CODING_HOSTNAME);
 
       if (!ptr)
index d5099b2721470dcba3d8694d2adc962fe150197b..12e7338ad8263b20d9d3043a3a5b9d1a044431cd 100644 (file)
@@ -176,9 +176,9 @@ static int          http_write_chunk(http_t *http, const char *buffer,
                                         int length);
 #ifdef HAVE_SSL
 static int             http_read_ssl(http_t *http, char *buf, int len);
-#  if defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
+#  ifdef HAVE_CDSASSL
 static int             http_set_credentials(http_t *http);
-#  endif /* HAVE_CDSASSL ** HAVE_SECCERTIFICATECOPYDATA */
+#  endif /* HAVE_CDSASSL */
 #endif /* HAVE_SSL */
 static off_t           http_set_length(http_t *http);
 static void            http_set_timeout(int fd, double timeout);
@@ -671,10 +671,10 @@ httpCopyCredentials(
 {
 #  ifdef HAVE_LIBSSL
 #  elif defined(HAVE_GNUTLS)
-#  elif defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
+#  elif defined(HAVE_CDSASSL)
   OSStatus             error;          /* Error code */
+  SecTrustRef          peerTrust;      /* Peer trust reference */
   CFIndex              count;          /* Number of credentials */
-  CFArrayRef           peerCerts;      /* Peer certificates */
   SecCertificateRef    secCert;        /* Certificate reference */
   CFDataRef            data;           /* Certificate data */
   int                  i;              /* Looping var */
@@ -694,14 +694,16 @@ httpCopyCredentials(
 #  elif defined(HAVE_GNUTLS)
   return (-1);
 
-#  elif defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
-  if (!(error = SSLCopyPeerCertificates(http->tls, &peerCerts)) && peerCerts)
+#  elif defined(HAVE_CDSASSL)
+  if (!(error = SSLCopyPeerTrust(http->tls, &peerTrust)) && peerTrust)
   {
     if ((*credentials = cupsArrayNew(NULL, NULL)) != NULL)
     {
-      for (i = 0, count = CFArrayGetCount(peerCerts); i < count; i++)
+      count = SecTrustGetCertificateCount(peerTrust);
+
+      for (i = 0; i < count; i ++)
       {
-       secCert = (SecCertificateRef)CFArrayGetValueAtIndex(peerCerts, i);
+       secCert = SecTrustGetCertificateAtIndex(peerTrust, i);
        if ((data = SecCertificateCopyData(secCert)))
        {
          httpAddCredential(*credentials, CFDataGetBytePtr(data),
@@ -711,7 +713,7 @@ httpCopyCredentials(
       }
     }
 
-    CFRelease(peerCerts);
+    CFRelease(peerTrust);
   }
 
   return (error);
@@ -832,7 +834,7 @@ _httpCreateCredentials(
 #  elif defined(HAVE_GNUTLS)
   return (NULL);
 
-#  elif defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
+#  elif defined(HAVE_CDSASSL)
   CFMutableArrayRef    peerCerts;      /* Peer credentials reference */
   SecCertificateRef    secCert;        /* Certificate reference */
   CFDataRef            data;           /* Credential data reference */
@@ -968,6 +970,13 @@ httpFlush(http_t *http)                    /* I - Connection to server */
   DEBUG_printf(("httpFlush(http=%p), state=%s", http,
                 http_states[http->state + 1]));
 
+ /*
+  * Nothing to do if we are in the "waiting" state...
+  */
+
+  if (http->state == HTTP_STATE_WAITING)
+    return;
+
  /*
   * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
   */
@@ -1981,7 +1990,9 @@ httpPeek(http_t *http,                    /* I - Connection to server */
 
     return (0);
   }
-  else if (length > (size_t)http->data_remaining)
+  else if ((http->data_encoding == HTTP_ENCODING_LENGTH ||
+            http->coding == _HTTP_CODING_IDENTITY) &&
+           length > (size_t)http->data_remaining)
     length = (size_t)http->data_remaining;
 
   if (http->used == 0)
@@ -2069,6 +2080,47 @@ httpPeek(http_t *http,                   /* I - Connection to server */
     http->used = bytes;
   }
 
+#ifdef HAVE_LIBZ
+  if (http->coding)
+  {
+    int                zerr;                   /* Decompressor error */
+    off_t      comp_avail;             /* Maximum bytes for decompression */
+    z_stream   stream;                 /* Copy of decompressor stream */
+
+    if (http->used > http->data_remaining)
+      comp_avail = http->data_remaining;
+    else
+      comp_avail = http->used;
+
+    DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length,
+                  (int)comp_avail));
+
+    if (inflateCopy(&stream, &(http->stream)) != Z_OK)
+    {
+      DEBUG_puts("2httpPeek: Unable to copy decompressor stream.");
+      http->error = ENOMEM;
+      return (-1);
+    }
+
+    stream.next_in   = (Bytef *)http->buffer;
+    stream.avail_in  = comp_avail;
+    stream.next_out  = (Bytef *)buffer;
+    stream.avail_out = length;
+
+    zerr = inflate(&stream, Z_SYNC_FLUSH);
+    inflateEnd(&stream);
+
+    if (zerr < Z_OK)
+    {
+      DEBUG_printf(("2httpPeek: zerr=%d", zerr));
+      http->error = EIO;
+      return (-1);
+    }
+
+    bytes = length - http->stream.avail_out;
+  }
+  else
+#endif /* HAVE_LIBZ */
   if (http->used > 0)
   {
     if (length > (size_t)http->used)
@@ -2111,6 +2163,10 @@ httpPeek(http_t *http,                   /* I - Connection to server */
   return (bytes);
 }
 
+/* For OS X 10.8 and earlier */
+ssize_t _httpPeek(http_t *http, char *buffer, size_t length)
+{ return (httpPeek(http, buffer, length)); }
+
 
 /*
  * 'httpPost()' - Send a POST request to the server.
@@ -3123,6 +3179,56 @@ httpSetCookie(http_t     *http,          /* I - Connection */
 }
 
 
+/*
+ * 'httpSetDefaultField()' - Set the default value of an HTTP header.
+ *
+ * Currently only HTTP_FIELD_ACCEPT_ENCODING, HTTP_FIELD_SERVER, and
+ * HTTP_FIELD_USER_AGENT can be set.
+ *
+ * @since CUPS 1.7@
+ */
+
+void
+httpSetDefaultField(http_t       *http,        /* I - Connection to server */
+                    http_field_t field,        /* I - Field index */
+                   const char   *value)/* I - Value */
+{
+  DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")",
+                http, field, http_fields[field], value));
+
+  if (!http)
+    return;
+
+  switch (field)
+  {
+    case HTTP_FIELD_ACCEPT_ENCODING :
+        if (http->default_accept_encoding)
+          _cupsStrFree(http->default_accept_encoding);
+
+        http->default_accept_encoding = value ? _cupsStrAlloc(value) : NULL;
+        break;
+
+    case HTTP_FIELD_SERVER :
+        if (http->default_server)
+          _cupsStrFree(http->default_server);
+
+        http->default_server = value ? _cupsStrAlloc(value) : NULL;
+        break;
+
+    case HTTP_FIELD_USER_AGENT :
+        if (http->default_user_agent)
+          _cupsStrFree(http->default_user_agent);
+
+        http->default_user_agent = value ? _cupsStrAlloc(value) : NULL;
+        break;
+
+    default :
+        DEBUG_puts("1httpSetDefaultField: Ignored.");
+       break;
+  }
+}
+
+
 /*
  * 'httpSetExpect()' - Set the Expect: header in a request.
  *
@@ -4061,15 +4167,20 @@ httpWriteResponse(http_t        *http,  /* I - HTTP connection */
 #endif /* HAVE_SSL */
 
   if (!http->server)
-    httpSetField(http, HTTP_FIELD_SERVER, CUPS_MINIMAL);
+    httpSetField(http, HTTP_FIELD_SERVER,
+                 http->default_server ? http->default_server : CUPS_MINIMAL);
 
-#ifdef HAVE_LIBZ
  /*
   * Set the Accept-Encoding field if it isn't already...
   */
 
   if (!http->accept_encoding)
-    httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, "gzip, deflate, identity");
+    httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
+                 http->default_accept_encoding ? http->default_accept_encoding :
+#ifdef HAVE_LIBZ
+                                                 "gzip, deflate, identity");
+#else
+                                                 "identity");
 #endif /* HAVE_LIBZ */
 
  /*
@@ -4681,16 +4792,17 @@ http_send(http_t       *http,           /* I - Connection to server */
   */
 
   if (!http->fields[HTTP_FIELD_USER_AGENT][0])
-    httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
+    httpSetField(http, HTTP_FIELD_USER_AGENT,
+                 http->default_user_agent ? http->default_user_agent :
+                                            CUPS_MINIMAL);
 
-#ifdef HAVE_LIBZ
  /*
   * Set the Accept-Encoding field if it isn't already...
   */
 
-  if (!http->accept_encoding)
-    httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, "gzip, deflate, identity");
-#endif /* HAVE_LIBZ */
+  if (!http->accept_encoding && http->default_accept_encoding)
+    httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
+                 http->default_accept_encoding);
 
  /*
   * Encode the URI as needed...
@@ -4813,7 +4925,7 @@ http_send(http_t       *http,             /* I - Connection to server */
 
 
 #ifdef HAVE_SSL
-#  if defined(HAVE_CDSASSL) && defined(HAVE_SECCERTIFICATECOPYDATA)
+#  if defined(HAVE_CDSASSL)
 /*
  * 'http_set_credentials()' - Set the SSL/TLS credentials.
  */
@@ -4836,7 +4948,6 @@ http_set_credentials(http_t *http)        /* I - Connection to server */
   if ((credentials = http->tls_credentials) == NULL)
     credentials = cg->tls_credentials;
 
-#    if HAVE_SECPOLICYCREATESSL
  /*
   * Otherwise root around in the user's keychain to see if one can be found...
   */
@@ -4891,7 +5002,6 @@ http_set_credentials(http_t *http)        /* I - Connection to server */
     if (dn_array)
       CFRelease(dn_array);
   }
-#    endif /* HAVE_SECPOLICYCREATESSL */
 
   if (credentials)
   {
@@ -4904,7 +5014,7 @@ http_set_credentials(http_t *http)        /* I - Connection to server */
 
   return (error);
 }
-#  endif /* HAVE_CDSASSL && HAVE_SECCERTIFICATECOPYDATA */
+#  endif /* HAVE_CDSASSL */
 #endif /* HAVE_SSL */
 
 
@@ -5016,7 +5126,6 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
 {
   _cups_globals_t      *cg = _cupsGlobals();
                                        /* Pointer to library globals */
-  int                  any_root;       /* Allow any root */
   char                 hostname[256],  /* Hostname */
                        *hostptr;       /* Pointer into hostname */
 
@@ -5031,7 +5140,6 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
 #  elif defined(HAVE_CDSASSL)
   OSStatus             error;          /* Error code */
   const char           *message = NULL;/* Error message */
-#    ifdef HAVE_SECCERTIFICATECOPYDATA
   cups_array_t         *credentials;   /* Credentials array */
   cups_array_t         *names;         /* CUPS distinguished names */
   CFArrayRef           dn_array;       /* CF distinguished names array */
@@ -5039,7 +5147,6 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
   CFDataRef            data;           /* Certificate data */
   int                  i;              /* Looping var */
   http_credential_t    *credential;    /* Credential data */
-#    endif /* HAVE_SECCERTIFICATECOPYDATA */
 #  elif defined(HAVE_SSPISSL)
   TCHAR                        username[256];  /* Username returned from GetUserName() */
   TCHAR                        commonName[256];/* Common name for certificate */
@@ -5050,23 +5157,19 @@ http_setup_ssl(http_t *http)            /* I - Connection to server */
   DEBUG_printf(("7http_setup_ssl(http=%p)", http));
 
  /*
-  * Always allow self-signed certificates for the local loopback address...
+  * Get the hostname to use for SSL...
   */
 
   if (httpAddrLocalhost(http->hostaddr))
   {
-    any_root = 1;
     strlcpy(hostname, "localhost", sizeof(hostname));
   }
   else
   {
    /*
-    * Otherwise use the system-wide setting and make sure the hostname we have
-    * does not end in a trailing dot.
+    * Otherwise make sure the hostname we have does not end in a trailing dot.
     */
 
-    any_root = cg->any_root;
-
     strlcpy(hostname, http->hostname, sizeof(hostname));
     if ((hostptr = hostname + strlen(hostname) - 1) >= hostname &&
         *hostptr == '.')
@@ -5074,8 +5177,6 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
   }
 
 #  ifdef HAVE_LIBSSL
-  (void)any_root;
-
   context = SSL_CTX_new(SSLv23_client_method());
 
   SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
@@ -5120,8 +5221,6 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
   }
 
 #  elif defined(HAVE_GNUTLS)
-  (void)any_root;
-
   credentials = (gnutls_certificate_client_credentials *)
                     malloc(sizeof(gnutls_certificate_client_credentials));
   if (credentials == NULL)
@@ -5170,9 +5269,11 @@ http_setup_ssl(http_t *http)             /* I - Connection to server */
   http->tls_credentials = credentials;
 
 #  elif defined(HAVE_CDSASSL)
-  if ((error = SSLNewContext(false, &http->tls)))
+  if ((http->tls = SSLCreateContext(kCFAllocatorDefault, kSSLClientSide,
+                                    kSSLStreamType)) == NULL)
   {
-    http->error  = errno;
+    DEBUG_puts("4http_setup_ssl: SSLCreateContext failed.");
+    http->error  = errno = ENOMEM;
     http->status = HTTP_ERROR;
     _cupsSetHTTPError(HTTP_ERROR);
 
@@ -5190,38 +5291,12 @@ http_setup_ssl(http_t *http)            /* I - Connection to server */
 
   if (!error)
   {
-    error = SSLSetAllowsAnyRoot(http->tls, any_root);
-    DEBUG_printf(("4http_setup_ssl: SSLSetAllowsAnyRoot(%d), error=%d",
-                  any_root, (int)error));
-  }
-
-  if (!error)
-  {
-    error = SSLSetAllowsExpiredCerts(http->tls, cg->expired_certs);
-    DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredCerts(%d), error=%d",
-                  cg->expired_certs, (int)error));
-  }
-
-  if (!error)
-  {
-    error = SSLSetAllowsExpiredRoots(http->tls, cg->expired_root);
-    DEBUG_printf(("4http_setup_ssl: SSLSetAllowsExpiredRoots(%d), error=%d",
-                  cg->expired_root, (int)error));
-  }
-
- /*
-  * In general, don't verify certificates since things like the common name
-  * often do not match...
-  */
-
-  if (!error)
-  {
-    error = SSLSetEnableCertVerify(http->tls, false);
-    DEBUG_printf(("4http_setup_ssl: SSLSetEnableCertVerify, error=%d",
+    error = SSLSetSessionOption(http->tls, kSSLSessionOptionBreakOnServerAuth,
+                                true);
+    DEBUG_printf(("4http_setup_ssl: SSLSetSessionOption, error=%d",
                   (int)error));
   }
 
-#    ifdef HAVE_SECCERTIFICATECOPYDATA
   if (!error)
   {
     if (cg->client_cert_cb)
@@ -5239,20 +5314,6 @@ http_setup_ssl(http_t *http)             /* I - Connection to server */
     }
   }
 
- /*
-  * If there's a server certificate callback installed let it evaluate the
-  * certificate(s) during the handshake...
-  */
-
-  if (!error && cg->server_cert_cb != NULL)
-  {
-    error = SSLSetSessionOption(http->tls,
-                               kSSLSessionOptionBreakOnServerAuth, true);
-    DEBUG_printf(("4http_setup_ssl: kSSLSessionOptionBreakOnServerAuth, "
-                 "error=%d", (int)error));
-  }
-#    endif /* HAVE_SECCERTIFICATECOPYDATA */
-
  /*
   * Let the server know which hostname/domain we are trying to connect to
   * in case it wants to serve up a certificate with a matching common name.
@@ -5287,7 +5348,6 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
            usleep(1000);               /* in 1 millisecond */
            break;
 
-#    ifdef HAVE_SECCERTIFICATECOPYDATA
        case errSSLServerAuthCompleted :
            error = 0;
            if (cg->server_cert_cb)
@@ -5350,7 +5410,6 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
              httpFreeCredentials(names);
            }
            break;
-#    endif /* HAVE_SECCERTIFICATECOPYDATA */
 
        case errSSLUnknownRootCert :
            message = _("Unable to establish a secure connection to host "
@@ -5399,7 +5458,7 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
     http->status = HTTP_ERROR;
     errno        = ECONNREFUSED;
 
-    SSLDisposeContext(http->tls);
+    CFRelease(http->tls);
     http->tls = NULL;
 
    /*
@@ -5448,7 +5507,7 @@ http_setup_ssl(http_t *http)              /* I - Connection to server */
     return (-1);
   }
 
-  _sspiSetAllowsAnyRoot(http->tls_credentials, any_root);
+  _sspiSetAllowsAnyRoot(http->tls_credentials, TRUE);
   _sspiSetAllowsExpiredCerts(http->tls_credentials, TRUE);
 
   if (!_sspiConnect(http->tls_credentials, hostname))
@@ -5501,7 +5560,7 @@ http_shutdown_ssl(http_t *http)           /* I - Connection to server */
   while (SSLClose(http->tls) == errSSLWouldBlock)
     usleep(1000);
 
-  SSLDisposeContext(http->tls);
+  CFRelease(http->tls);
 
   if (http->tls_credentials)
     CFRelease(http->tls_credentials);
index 3c8a32113e09097b217aa6fdb85d802cdd695343..de782aaa3c0b18e173cecb27b6b2290ca1e7a484 100644 (file)
@@ -602,6 +602,8 @@ extern ssize_t              httpPeek(http_t *http, char *buffer, size_t length)
                                 _CUPS_API_1_7;
 extern http_state_t    httpReadRequest(http_t *http, char *resource,
                                        size_t resourcelen) _CUPS_API_1_7;
+extern void            httpSetDefaultField(http_t *http, http_field_t field,
+                                           const char *value) _CUPS_API_1_7;
 extern http_state_t    httpWriteResponse(http_t *http,
                                          http_status_t status) _CUPS_API_1_7;
 
index 0c54a28038305f0ced71607c4eff01bc703cd7cc..76ee409d369d6ecedaefcd9be1ab542412131655 100644 (file)
  *
  * Contents:
  *
- *   _cupsBufferGet()      - Get a read/write buffer.
- *   _cupsBufferRelease()   - Release a read/write buffer.
- *   ippAddBoolean()       - Add a boolean attribute to an IPP message.
- *   ippAddBooleans()      - Add an array of boolean values.
- *   ippAddCollection()     - Add a collection value.
- *   ippAddCollections()    - Add an array of collection values.
- *   ippAddDate()          - Add a date attribute to an IPP message.
- *   ippAddInteger()       - Add a integer attribute to an IPP message.
- *   ippAddIntegers()      - Add an array of integer values.
- *   ippAddOctetString()    - Add an octetString value to an IPP message.
- *   ippAddOutOfBand()     - Add an out-of-band value to an IPP message.
- *   ippAddRange()         - Add a range of values to an IPP message.
- *   ippAddRanges()        - Add ranges of values to an IPP message.
- *   ippAddResolution()     - Add a resolution value to an IPP message.
- *   ippAddResolutions()    - Add resolution values to an IPP message.
- *   ippAddSeparator()     - Add a group separator to an IPP message.
- *   ippAddString()        - Add a language-encoded string to an IPP message.
- *   ippAddStringf()       - Add a formatted string to an IPP message.
- *   ippAddStringfv()      - Add a formatted string to an IPP message.
- *   ippAddStrings()       - Add language-encoded strings to an IPP message.
- *   ippContainsInteger()   - Determine whether an attribute contains the
- *                           specified value or is within the list of ranges.
- *   ippContainsString()    - Determine whether an attribute contains the
- *                           specified string value.
- *   ippCopyAttribute()     - Copy an attribute.
- *   ippCopyAttributes()    - Copy attributes from one IPP message to another.
- *   ippDateToTime()       - Convert from RFC 1903 Date/Time format to UNIX
- *                           time in seconds.
- *   ippDelete()           - Delete an IPP message.
- *   ippDeleteAttribute()   - Delete a single attribute in an IPP message.
- *   ippDeleteValues()     - Delete values in an attribute.
- *   ippFindAttribute()     - Find a named attribute in a request.
- *   ippFindNextAttribute() - Find the next named attribute in a request.
- *   ippFirstAttribute()    - Return the first attribute in the message.
- *   ippGetBoolean()       - Get a boolean value for an attribute.
- *   ippGetCollection()     - Get a collection value for an attribute.
- *   ippGetCount()         - Get the number of values in an attribute.
- *   ippGetDate()          - Get a date value for an attribute.
- *   ippGetGroupTag()      - Get the group associated with an attribute.
- *   ippGetInteger()       - Get the integer/enum value for an attribute.
- *   ippGetName()          - Get the attribute name.
- *   ippGetOperation()     - Get the operation ID in an IPP message.
- *   ippGetRange()         - Get a rangeOfInteger value from an attribute.
- *   ippGetRequestId()     - Get the request ID from an IPP message.
- *   ippGetResolution()     - Get a resolution value for an attribute.
- *   ippGetState()         - Get the IPP message state.
- *   ippGetStatusCode()     - Get the status code from an IPP response or event
- *                           message.
- *   ippGetString()        - Get the string and optionally the language code
- *                           for an attribute.
- *   ippGetValueTag()      - Get the value tag for an attribute.
- *   ippGetVersion()       - Get the major and minor version number from an
- *                           IPP message.
- *   ippLength()           - Compute the length of an IPP message.
- *   ippNextAttribute()     - Return the next attribute in the message.
- *   ippNew()              - Allocate a new IPP message.
- *   ippNewRequest()       - Allocate a new IPP request message.
- *   ippNewResponse()      - Allocate a new IPP response message.
- *   ippRead()             - Read data for an IPP message from a HTTP
- *                           connection.
- *   ippReadFile()         - Read data for an IPP message from a file.
- *   ippReadIO()           - Read data for an IPP message.
- *   ippSetBoolean()       - Set a boolean value in an attribute.
- *   ippSetCollection()     - Set a collection value in an attribute.
- *   ippSetDate()          - Set a date value in an attribute.
- *   ippSetGroupTag()      - Set the group tag of an attribute.
- *   ippSetInteger()       - Set an integer or enum value in an attribute.
- *   ippSetName()          - Set the name of an attribute.
- *   ippSetOperation()     - Set the operation ID in an IPP request message.
- *   ippSetRange()         - Set a rangeOfInteger value in an attribute.
- *   ippSetRequestId()     - Set the request ID in an IPP message.
- *   ippSetResolution()     - Set a resolution value in an attribute.
- *   ippSetState()         - Set the current state of the IPP message.
- *   ippSetStatusCode()     - Set the status code in an IPP response or event
- *                           message.
- *   ippSetString()        - Set a string value in an attribute.
- *   ippSetStringf()       - Set a formatted string value of an attribute.
- *   ippSetStringf()       - Set a formatted string value of an attribute.
- *   ippSetValueTag()      - Set the value tag of an attribute.
- *   ippSetVersion()       - Set the version number in an IPP message.
- *   ippTimeToDate()       - Convert from UNIX time to RFC 1903 format.
- *   ippWrite()            - Write data for an IPP message to a HTTP
- *                           connection.
- *   ippWriteFile()        - Write data for an IPP message to a file.
- *   ippWriteIO()          - Write data for an IPP message.
- *   ipp_add_attr()        - Add a new attribute to the message.
- *   ipp_free_values()     - Free attribute values.
- *   ipp_get_code()        - Convert a C locale/charset name into an IPP
- *                           language/charset code.
- *   ipp_lang_code()       - Convert a C locale name into an IPP language
- *                           code.
- *   ipp_length()          - Compute the length of an IPP message or
- *                           collection value.
- *   ipp_read_http()       - Semi-blocking read on a HTTP connection...
- *   ipp_read_file()       - Read IPP data from a file.
- *   ipp_set_value()       - Get the value element from an attribute,
- *                           expanding it as needed.
- *   ipp_write_file()      - Write IPP data to a file.
+ *   _cupsBufferGet()       - Get a read/write buffer.
+ *   _cupsBufferRelease()    - Release a read/write buffer.
+ *   ippAddBoolean()        - Add a boolean attribute to an IPP message.
+ *   ippAddBooleans()       - Add an array of boolean values.
+ *   ippAddCollection()      - Add a collection value.
+ *   ippAddCollections()     - Add an array of collection values.
+ *   ippAddDate()           - Add a date attribute to an IPP message.
+ *   ippAddInteger()        - Add a integer attribute to an IPP message.
+ *   ippAddIntegers()       - Add an array of integer values.
+ *   ippAddOctetString()     - Add an octetString value to an IPP message.
+ *   ippAddOutOfBand()      - Add an out-of-band value to an IPP message.
+ *   ippAddRange()          - Add a range of values to an IPP message.
+ *   ippAddRanges()         - Add ranges of values to an IPP message.
+ *   ippAddResolution()      - Add a resolution value to an IPP message.
+ *   ippAddResolutions()     - Add resolution values to an IPP message.
+ *   ippAddSeparator()      - Add a group separator to an IPP message.
+ *   ippAddString()         - Add a language-encoded string to an IPP message.
+ *   ippAddStringf()        - Add a formatted string to an IPP message.
+ *   ippAddStringfv()       - Add a formatted string to an IPP message.
+ *   ippAddStrings()        - Add language-encoded strings to an IPP message.
+ *   ippContainsInteger()    - Determine whether an attribute contains the
+ *                            specified value or is within the list of ranges.
+ *   ippContainsString()     - Determine whether an attribute contains the
+ *                            specified string value.
+ *   ippCopyAttribute()      - Copy an attribute.
+ *   ippCopyAttributes()     - Copy attributes from one IPP message to another.
+ *   ippDateToTime()        - Convert from RFC 1903 Date/Time format to UNIX
+ *                            time in seconds.
+ *   ippDelete()            - Delete an IPP message.
+ *   ippDeleteAttribute()    - Delete a single attribute in an IPP message.
+ *   ippDeleteValues()      - Delete values in an attribute.
+ *   ippFindAttribute()      - Find a named attribute in a request.
+ *   ippFindNextAttribute()  - Find the next named attribute in a request.
+ *   ippFirstAttribute()     - Return the first attribute in the message.
+ *   ippGetBoolean()        - Get a boolean value for an attribute.
+ *   ippGetCollection()      - Get a collection value for an attribute.
+ *   ippGetCount()          - Get the number of values in an attribute.
+ *   ippGetDate()           - Get a date value for an attribute.
+ *   ippGetGroupTag()       - Get the group associated with an attribute.
+ *   ippGetInteger()        - Get the integer/enum value for an attribute.
+ *   ippGetName()           - Get the attribute name.
+ *   ippGetOperation()      - Get the operation ID in an IPP message.
+ *   ippGetRange()          - Get a rangeOfInteger value from an attribute.
+ *   ippGetRequestId()      - Get the request ID from an IPP message.
+ *   ippGetResolution()      - Get a resolution value for an attribute.
+ *   ippGetState()          - Get the IPP message state.
+ *   ippGetStatusCode()      - Get the status code from an IPP response or
+ *                            event message.
+ *   ippGetString()         - Get the string and optionally the language code
+ *                            for an attribute.
+ *   ippGetValueTag()       - Get the value tag for an attribute.
+ *   ippGetVersion()        - Get the major and minor version number from an
+ *                            IPP message.
+ *   ippLength()            - Compute the length of an IPP message.
+ *   ippNextAttribute()      - Return the next attribute in the message.
+ *   ippNew()               - Allocate a new IPP message.
+ *   ippNewRequest()        - Allocate a new IPP request message.
+ *   ippNewResponse()       - Allocate a new IPP response message.
+ *   ippRead()              - Read data for an IPP message from a HTTP
+ *                            connection.
+ *   ippReadFile()          - Read data for an IPP message from a file.
+ *   ippReadIO()            - Read data for an IPP message.
+ *   ippSetBoolean()        - Set a boolean value in an attribute.
+ *   ippSetCollection()      - Set a collection value in an attribute.
+ *   ippSetDate()           - Set a date value in an attribute.
+ *   ippSetGroupTag()       - Set the group tag of an attribute.
+ *   ippSetInteger()        - Set an integer or enum value in an attribute.
+ *   ippSetName()           - Set the name of an attribute.
+ *   ippSetOperation()      - Set the operation ID in an IPP request message.
+ *   ippSetRange()          - Set a rangeOfInteger value in an attribute.
+ *   ippSetRequestId()      - Set the request ID in an IPP message.
+ *   ippSetResolution()      - Set a resolution value in an attribute.
+ *   ippSetState()          - Set the current state of the IPP message.
+ *   ippSetStatusCode()      - Set the status code in an IPP response or event
+ *                            message.
+ *   ippSetString()         - Set a string value in an attribute.
+ *   ippSetStringf()        - Set a formatted string value of an attribute.
+ *   ippSetStringf()        - Set a formatted string value of an attribute.
+ *   ippSetValueTag()       - Set the value tag of an attribute.
+ *   ippSetVersion()        - Set the version number in an IPP message.
+ *   ippTimeToDate()        - Convert from UNIX time to RFC 1903 format.
+ *   ippValidateAttribute()  - Validate the contents of an attribute.
+ *   ippValidateAttributes() - Validate all attributes in an IPP message.
+ *   ippWrite()             - Write data for an IPP message to a HTTP
+ *                            connection.
+ *   ippWriteFile()         - Write data for an IPP message to a file.
+ *   ippWriteIO()           - Write data for an IPP message.
+ *   ipp_add_attr()         - Add a new attribute to the message.
+ *   ipp_free_values()      - Free attribute values.
+ *   ipp_get_code()         - Convert a C locale/charset name into an IPP
+ *                            language/charset code.
+ *   ipp_lang_code()        - Convert a C locale name into an IPP language
+ *                            code.
+ *   ipp_length()           - Compute the length of an IPP message or
+ *                            collection value.
+ *   ipp_read_http()        - Semi-blocking read on a HTTP connection...
+ *   ipp_read_file()        - Read IPP data from a file.
+ *   ipp_set_error()        - Set a formatted, localized error string.
+ *   ipp_set_value()        - Get the value element from an attribute,
+ *                            expanding it as needed.
+ *   ipp_write_file()       - Write IPP data to a file.
  */
 
 /*
  */
 
 #include "cups-private.h"
+#include <regex.h>
 #ifdef WIN32
 #  include <io.h>
 #endif /* WIN32 */
@@ -146,6 +150,8 @@ static ssize_t              ipp_read_http(http_t *http, ipp_uchar_t *buffer,
                                      size_t length);
 static ssize_t         ipp_read_file(int *fd, ipp_uchar_t *buffer,
                                      size_t length);
+static void            ipp_set_error(ipp_status_t status, const char *format,
+                                     ...);
 static _ipp_value_t    *ipp_set_value(ipp_t *ipp, ipp_attribute_t **attr,
                                       int element);
 static ssize_t         ipp_write_file(int *fd, ipp_uchar_t *buffer,
@@ -2935,18 +2941,6 @@ ippReadIO(void       *src,               /* I - Data source */
   ipp_tag_t            tag;            /* Current tag */
   ipp_tag_t            value_tag;      /* Current value tag */
   _ipp_value_t         *value;         /* Current value */
-  static const int     maxlen[] =      /* Maximum length of strings */
-  {
-    IPP_MAX_TEXT - 1,
-    IPP_MAX_NAME - 1,
-    0,
-    IPP_MAX_KEYWORD - 1,
-    IPP_MAX_URI - 1,
-    IPP_MAX_URISCHEME - 1,
-    IPP_MAX_CHARSET - 1,
-    IPP_MAX_LANGUAGE - 1,
-    IPP_MAX_MIMETYPE - 1
-  };
 
 
   DEBUG_printf(("ippReadIO(src=%p, cb=%p, blocking=%d, parent=%p, ipp=%p)",
@@ -3387,16 +3381,6 @@ ippReadIO(void       *src,               /* I - Data source */
            case IPP_TAG_CHARSET :
            case IPP_TAG_LANGUAGE :
            case IPP_TAG_MIMETYPE :
-               if (n > maxlen[tag - IPP_TAG_TEXT])
-               {
-                 _cupsSetError(IPP_INTERNAL_ERROR,
-                               _("IPP string value too large."), 1);
-                 DEBUG_printf(("1ippReadIO: bad %s value length %d.",
-                               ippTagString(tag), n));
-                 _cupsBufferRelease((char *)buffer);
-                 return (IPP_ERROR);
-               }
-
                if (n > 0)
                {
                  if ((*cb)(src, buffer, n) < n)
@@ -3499,21 +3483,6 @@ ippReadIO(void       *src,               /* I - Data source */
                  _cupsBufferRelease((char *)buffer);
                  return (IPP_ERROR);
                }
-               else if (n > (2 + IPP_MAX_LANGUAGE + IPP_MAX_TEXT))
-               {
-                 if (tag == IPP_TAG_TEXTLANG)
-                   _cupsSetError(IPP_INTERNAL_ERROR,
-                                 _("IPP textWithLanguage value more than "
-                                   "maximum 1090 bytes."), 1);
-                 else
-                   _cupsSetError(IPP_INTERNAL_ERROR,
-                                 _("IPP nameWithLanguage value more than "
-                                   "maximum 1090 bytes."), 1);
-                 DEBUG_printf(("1ippReadIO: bad stringWithLanguage value "
-                               "length %d.", n));
-                 _cupsBufferRelease((char *)buffer);
-                 return (IPP_ERROR);
-               }
 
                if ((*cb)(src, buffer, n) < n)
                {
@@ -3573,15 +3542,6 @@ ippReadIO(void       *src,               /* I - Data source */
                  _cupsBufferRelease((char *)buffer);
                  return (IPP_ERROR);
                }
-               else if (n >= IPP_MAX_TEXT)
-               {
-                 _cupsSetError(IPP_INTERNAL_ERROR,
-                               _("IPP text length too large."), 1);
-                 DEBUG_printf(("1ippReadIO: bad text value length %d.",
-                               n));
-                 _cupsBufferRelease((char *)buffer);
-                 return (IPP_ERROR);
-               }
 
                bufptr[2 + n] = '\0';
                 value->string.text = _cupsStrAlloc((char *)bufptr + 2);
@@ -4705,6 +4665,672 @@ ippTimeToDate(time_t t)                 /* I - UNIX time value */
 }
 
 
+/*
+ * 'ippValidateAttribute()' - Validate the contents of an attribute.
+ *
+ * This function validates the contents of an attribute based on the name and
+ * value tag.  1 is returned if the attribute is valid, 0 otherwise.  On
+ * failure, cupsLastErrorString() is set to a human-readable message.
+ *
+ * @since CUPS 1.7@
+ */
+
+int                                    /* O - 1 if valid, 0 otherwise */
+ippValidateAttribute(
+    ipp_attribute_t *attr)             /* I - Attribute */
+{
+  int          i;                      /* Looping var */
+  char         scheme[64],             /* Scheme from URI */
+               userpass[256],          /* Username/password from URI */
+               hostname[256],          /* Hostname from URI */
+               resource[1024];         /* Resource from URI */
+  int          port,                   /* Port number from URI */
+               uri_status;             /* URI separation status */
+  const char   *ptr;                   /* Pointer into string */
+  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"
+  };
+
+
+ /*
+  * Skip separators.
+  */
+
+  if (!attr->name)
+    return (1);
+
+ /*
+  * Validate the attribute name.
+  */
+
+  for (ptr = attr->name; *ptr; ptr ++)
+    if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' && *ptr != '_')
+      break;
+
+  if (*ptr || ptr == attr->name)
+  {
+    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                  _("\"%s\": Bad attribute name - invalid character "
+                   "(RFC 2911 section 4.1.3)."), attr->name);
+    return (0);
+  }
+
+  if ((ptr - attr->name) > 255)
+  {
+    ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                  _("\"%s\": Bad attribute name - bad length %d "
+                   "(RFC 2911 section 4.1.3)."), attr->name,
+                 (int)(ptr - attr->name));
+    return (0);
+  }
+
+  switch (attr->value_tag)
+  {
+    case IPP_TAG_INTEGER :
+        break;
+
+    case IPP_TAG_BOOLEAN :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].boolean != 0 &&
+             attr->values[i].boolean != 1)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                          _("\"%s\": Bad boolen value %d "
+                           "(RFC 2911 section 4.1.11)."), attr->name,
+                         attr->values[i].boolean);
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_ENUM :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].integer < 1)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad enum value %d - out of range "
+                           "(RFC 2911 section 4.1.4)."), attr->name,
+                           attr->values[i].integer);
+            return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_STRING :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].unknown.length > IPP_MAX_OCTETSTRING)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad octetString value - bad length %d "
+                           "(RFC 2911 section 4.1.10)."), attr->name,
+                           attr->values[i].unknown.length);
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_DATE :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         date = attr->values[i].date;
+
+          if (date[2] < 1 || date[2] > 12)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad dateTime month %u "
+                           "(RFC 2911 section 4.1.14)."), attr->name, date[2]);
+           return (0);
+         }
+
+          if (date[3] < 1 || date[3] > 31)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad dateTime day %u "
+                           "(RFC 2911 section 4.1.14)."), attr->name, date[3]);
+           return (0);
+         }
+
+          if (date[4] > 23)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad dateTime hours %u "
+                           "(RFC 2911 section 4.1.14)."), attr->name, date[4]);
+           return (0);
+         }
+
+          if (date[5] > 59)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad dateTime minutes %u "
+                           "(RFC 2911 section 4.1.14)."), attr->name, date[5]);
+           return (0);
+         }
+
+          if (date[6] > 60)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad dateTime seconds %u "
+                           "(RFC 2911 section 4.1.14)."), attr->name, date[6]);
+           return (0);
+         }
+
+          if (date[7] > 9)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad dateTime deciseconds %u "
+                           "(RFC 2911 section 4.1.14)."), attr->name, date[7]);
+           return (0);
+         }
+
+          if (date[8] != '-' && date[8] != '+')
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad dateTime UTC sign '%c' "
+                           "(RFC 2911 section 4.1.14)."), attr->name, date[8]);
+           return (0);
+         }
+
+          if (date[9] > 11)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad dateTime UTC hours %u "
+                           "(RFC 2911 section 4.1.14)."), attr->name, date[9]);
+           return (0);
+         }
+
+          if (date[10] > 59)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad dateTime UTC minutes %u "
+                           "(RFC 2911 section 4.1.14)."), attr->name, date[10]);
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_RESOLUTION :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].resolution.xres <= 0)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad resolution value %dx%d%s - cross "
+                           "feed resolution must be positive "
+                           "(RFC 2911 section 4.1.15)."), attr->name,
+                         attr->values[i].resolution.xres,
+                         attr->values[i].resolution.yres,
+                         attr->values[i].resolution.units ==
+                             IPP_RES_PER_INCH ? "dpi" :
+                             attr->values[i].resolution.units ==
+                                 IPP_RES_PER_CM ? "dpcm" : "unknown");
+           return (0);
+         }
+
+         if (attr->values[i].resolution.yres <= 0)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad resolution value %dx%d%s - feed "
+                           "resolution must be positive "
+                           "(RFC 2911 section 4.1.15)."), attr->name,
+                         attr->values[i].resolution.xres,
+                         attr->values[i].resolution.yres,
+                         attr->values[i].resolution.units ==
+                             IPP_RES_PER_INCH ? "dpi" :
+                             attr->values[i].resolution.units ==
+                                 IPP_RES_PER_CM ? "dpcm" : "unknown");
+            return (0);
+         }
+
+         if (attr->values[i].resolution.units != IPP_RES_PER_INCH &&
+             attr->values[i].resolution.units != IPP_RES_PER_CM)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad resolution value %dx%d%s - bad "
+                           "units value (RFC 2911 section 4.1.15)."),
+                         attr->name, attr->values[i].resolution.xres,
+                         attr->values[i].resolution.yres,
+                         attr->values[i].resolution.units ==
+                             IPP_RES_PER_INCH ? "dpi" :
+                             attr->values[i].resolution.units ==
+                                 IPP_RES_PER_CM ? "dpcm" : "unknown");
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_RANGE :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (attr->values[i].range.lower > attr->values[i].range.upper)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad rangeOfInteger value %d-%d - lower "
+                           "greater than upper (RFC 2911 section 4.1.13)."),
+                         attr->name, attr->values[i].range.lower,
+                         attr->values[i].range.upper);
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_BEGIN_COLLECTION :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (colattr = attr->values[i].collection->attrs;
+              colattr;
+              colattr = colattr->next)
+         {
+           if (!ippValidateAttribute(colattr))
+             return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_TEXT :
+    case IPP_TAG_TEXTLANG :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+         {
+           if ((*ptr & 0xe0) == 0xc0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if ((*ptr & 0xf0) == 0xe0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if ((*ptr & 0xf8) == 0xf0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if (*ptr & 0x80)
+             break;
+         }
+
+         if (*ptr)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad text value \"%s\" - bad UTF-8 "
+                           "sequence (RFC 2911 section 4.1.1)."), attr->name,
+                         attr->values[i].string.text);
+           return (0);
+         }
+
+         if ((ptr - attr->values[i].string.text) > (IPP_MAX_TEXT - 1))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad text value \"%s\" - bad length %d "
+                           "(RFC 2911 section 4.1.1)."), attr->name,
+                         attr->values[i].string.text,
+                         (int)(ptr - attr->values[i].string.text));
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_NAME :
+    case IPP_TAG_NAMELANG :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+         {
+           if ((*ptr & 0xe0) == 0xc0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if ((*ptr & 0xf0) == 0xe0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if ((*ptr & 0xf8) == 0xf0)
+           {
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+             ptr ++;
+             if ((*ptr & 0xc0) != 0x80)
+               break;
+           }
+           else if (*ptr & 0x80)
+             break;
+         }
+
+         if (*ptr)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad name value \"%s\" - bad UTF-8 "
+                           "sequence (RFC 2911 section 4.1.2)."), attr->name,
+                         attr->values[i].string.text);
+           return (0);
+         }
+
+         if ((ptr - attr->values[i].string.text) > (IPP_MAX_NAME - 1))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad name value \"%s\" - bad length %d "
+                           "(RFC 2911 section 4.1.2)."), attr->name,
+                         attr->values[i].string.text,
+                         (int)(ptr - attr->values[i].string.text));
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_KEYWORD :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+           if (!isalnum(*ptr & 255) && *ptr != '-' && *ptr != '.' &&
+               *ptr != '_')
+             break;
+
+         if (*ptr || ptr == attr->values[i].string.text)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad keyword value \"%s\" - invalid "
+                           "character (RFC 2911 section 4.1.3)."),
+                         attr->name, attr->values[i].string.text);
+           return (0);
+         }
+
+         if ((ptr - attr->values[i].string.text) > (IPP_MAX_KEYWORD - 1))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad keyword value \"%s\" - bad "
+                           "length %d (RFC 2911 section 4.1.3)."),
+                         attr->name, attr->values[i].string.text,
+                         (int)(ptr - attr->values[i].string.text));
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_URI :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         uri_status = httpSeparateURI(HTTP_URI_CODING_ALL,
+                                      attr->values[i].string.text,
+                                      scheme, sizeof(scheme),
+                                      userpass, sizeof(userpass),
+                                      hostname, sizeof(hostname),
+                                      &port, resource, sizeof(resource));
+
+         if (uri_status < HTTP_URI_OK)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad URI value \"%s\" - %s "
+                           "(RFC 2911 section 4.1.5)."), attr->name,
+                         attr->values[i].string.text,
+                         uri_status_strings[uri_status -
+                                            HTTP_URI_OVERFLOW]);
+           return (0);
+         }
+
+         if (strlen(attr->values[i].string.text) > (IPP_MAX_URI - 1))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad URI value \"%s\" - bad length %d "
+                           "(RFC 2911 section 4.1.5)."), attr->name,
+                         attr->values[i].string.text,
+                         (int)strlen(attr->values[i].string.text));
+         }
+       }
+        break;
+
+    case IPP_TAG_URISCHEME :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         ptr = attr->values[i].string.text;
+         if (islower(*ptr & 255))
+         {
+           for (ptr ++; *ptr; ptr ++)
+             if (!islower(*ptr & 255) && !isdigit(*ptr & 255) &&
+                 *ptr != '+' && *ptr != '-' && *ptr != '.')
+                break;
+         }
+
+         if (*ptr || ptr == attr->values[i].string.text)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad uriScheme value \"%s\" - bad "
+                           "characters (RFC 2911 section 4.1.6)."),
+                         attr->name, attr->values[i].string.text);
+           return (0);
+         }
+
+         if ((ptr - attr->values[i].string.text) > (IPP_MAX_URISCHEME - 1))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad uriScheme value \"%s\" - bad "
+                           "length %d (RFC 2911 section 4.1.6)."),
+                         attr->name, attr->values[i].string.text,
+                         (int)(ptr - attr->values[i].string.text));
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_CHARSET :
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         for (ptr = attr->values[i].string.text; *ptr; ptr ++)
+           if (!isprint(*ptr & 255) || isupper(*ptr & 255) ||
+               isspace(*ptr & 255))
+             break;
+
+         if (*ptr || ptr == attr->values[i].string.text)
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad charset value \"%s\" - bad "
+                           "characters (RFC 2911 section 4.1.7)."),
+                         attr->name, attr->values[i].string.text);
+           return (0);
+         }
+
+         if ((ptr - attr->values[i].string.text) > (IPP_MAX_CHARSET - 1))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad charset value \"%s\" - bad "
+                           "length %d (RFC 2911 section 4.1.7)."),
+                         attr->name, attr->values[i].string.text,
+                         (int)(ptr - attr->values[i].string.text));
+           return (0);
+         }
+       }
+        break;
+
+    case IPP_TAG_LANGUAGE :
+       /*
+        * The following regular expression is derived from the ABNF for
+       * language tags in RFC 4646.  All I can say is that this is the
+       * easiest way to check the values...
+       */
+
+        if ((i = regcomp(&re,
+                        "^("
+                        "(([a-z]{2,3}(-[a-z][a-z][a-z]){0,3})|[a-z]{4,8})"
+                                                               /* language */
+                        "(-[a-z][a-z][a-z][a-z]){0,1}"         /* script */
+                        "(-([a-z][a-z]|[0-9][0-9][0-9])){0,1}" /* region */
+                        "(-([a-z]{5,8}|[0-9][0-9][0-9]))*"     /* variant */
+                        "(-[a-wy-z](-[a-z0-9]{2,8})+)*"        /* extension */
+                        "(-x(-[a-z0-9]{1,8})+)*"               /* privateuse */
+                        "|"
+                        "x(-[a-z0-9]{1,8})+"                   /* privateuse */
+                        "|"
+                        "[a-z]{1,3}(-[a-z][0-9]{2,8}){1,2}"    /* grandfathered */
+                        ")$",
+                        REG_NOSUB | REG_EXTENDED)) != 0)
+        {
+          char temp[256];              /* Temporary error string */
+
+          regerror(i, &re, temp, sizeof(temp));
+         ipp_set_error(IPP_STATUS_ERROR_INTERNAL,
+                       _("Unable to compile naturalLanguage regular "
+                         "expression: %s."), temp);
+         return (0);
+        }
+
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad naturalLanguage value \"%s\" - bad "
+                           "characters (RFC 2911 section 4.1.8)."),
+                         attr->name, attr->values[i].string.text);
+           regfree(&re);
+           return (0);
+         }
+
+         if (strlen(attr->values[i].string.text) > (IPP_MAX_LANGUAGE - 1))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad naturalLanguage value \"%s\" - bad "
+                           "length %d (RFC 2911 section 4.1.8)."),
+                         attr->name, attr->values[i].string.text,
+                         (int)strlen(attr->values[i].string.text));
+           regfree(&re);
+           return (0);
+         }
+       }
+
+       regfree(&re);
+        break;
+
+    case IPP_TAG_MIMETYPE :
+       /*
+        * The following regular expression is derived from the ABNF for
+       * MIME media types in RFC 2045 and 4288.  All I can say is that this is
+       * the easiest way to check the values...
+       */
+
+        if ((i = regcomp(&re,
+                        "^"
+                        "[-a-zA-Z0-9!#$&.+^_]{1,127}"          /* type-name */
+                        "/"
+                        "[-a-zA-Z0-9!#$&.+^_]{1,127}"          /* subtype-name */
+                        "(;[-a-zA-Z0-9!#$&.+^_]{1,127}="       /* parameter= */
+                        "([-a-zA-Z0-9!#$&.+^_]{1,127}|\"[^\"]*\"))*"
+                                                               /* value */
+                        "$",
+                        REG_NOSUB | REG_EXTENDED)) != 0)
+        {
+          char temp[256];              /* Temporary error string */
+
+          regerror(i, &re, temp, sizeof(temp));
+         ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                       _("Unable to compile mimeMediaType regular "
+                         "expression: %s."), temp);
+         return (0);
+        }
+
+        for (i = 0; i < attr->num_values; i ++)
+       {
+         if (regexec(&re, attr->values[i].string.text, 0, NULL, 0))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad mimeMediaType value \"%s\" - bad "
+                           "characters (RFC 2911 section 4.1.9)."),
+                         attr->name, attr->values[i].string.text);
+           regfree(&re);
+           return (0);
+         }
+
+         if (strlen(attr->values[i].string.text) > (IPP_MAX_MIMETYPE - 1))
+         {
+           ipp_set_error(IPP_STATUS_ERROR_BAD_REQUEST,
+                         _("\"%s\": Bad mimeMediaType value \"%s\" - bad "
+                           "length %d (RFC 2911 section 4.1.9)."),
+                         attr->name, attr->values[i].string.text,
+                         (int)strlen(attr->values[i].string.text));
+           regfree(&re);
+           return (0);
+         }
+       }
+
+       regfree(&re);
+        break;
+
+    default :
+        break;
+  }
+
+  return (1);
+}
+
+
+/*
+ * 'ippValidateAttributes()' - Validate all attributes in an IPP message.
+ *
+ * This function validates the contents of the IPP message, including each
+ * attribute.  Like @link ippValidateAttribute@, cupsLastErrorString() is set
+ * to a human-readable message on failure.
+ *
+ * @since CUPS 1.7@
+ */
+
+int                                    /* O - 1 if valid, 0 otherwise */
+ippValidateAttributes(ipp_t *ipp)      /* I - IPP message */
+{
+  ipp_attribute_t      *attr;          /* Current attribute */
+
+
+  if (!ipp)
+    return (1);
+
+  for (attr = ipp->attrs; attr; attr = attr->next)
+    if (!ippValidateAttribute(attr))
+      return (0);
+
+  return (1);
+}
+
+
 /*
  * 'ippWrite()' - Write data for an IPP message to a HTTP connection.
  */
@@ -6123,6 +6749,29 @@ ipp_read_file(int         *fd,           /* I - File descriptor */
 }
 
 
+/*
+ * 'ipp_set_error()' - Set a formatted, localized error string.
+ */
+
+static void
+ipp_set_error(ipp_status_t status,     /* I - Status code */
+              const char   *format,    /* I - Printf-style error string */
+             ...)                      /* I - Additional arguments as needed */
+{
+  va_list      ap;                     /* Pointer to additional args */
+  char         buffer[2048];           /* Message buffer */
+  cups_lang_t  *lang = cupsLangDefault();
+                                       /* Current language */
+
+
+  va_start(ap, format);
+  vsnprintf(buffer, sizeof(buffer), _cupsLangString(lang, format), ap);
+  va_end(ap);
+
+  _cupsSetError(status, buffer, 0);
+}
+
+
 /*
  * 'ipp_set_value()' - Get the value element from an attribute, expanding it as
  *                     needed.
index 65e4f285af8b281224d6d3a95db7ed56bdd717b8..a87f643a36c11188473cc232a97b89b494b48b19 100644 (file)
@@ -23,6 +23,7 @@
  */
 
 #  include "http.h"
+#  include <stdarg.h>
 
 
 /*
@@ -926,6 +927,9 @@ extern int          ippSetStringf(ipp_t *ipp, ipp_attribute_t **attr,
 extern int             ippSetStringfv(ipp_t *ipp, ipp_attribute_t **attr,
                                       int element, const char *format,
                                       va_list ap) _CUPS_API_1_7;
+extern int             ippValidateAttribute(ipp_attribute_t *attr)
+                                            _CUPS_API_1_7;
+extern int             ippValidateAttributes(ipp_t *ipp) _CUPS_API_1_7;
 
 
 /*
index be4c64e9815ca2da0e740ab1a033a84cf2222676..9fe3d6c7de50268ebd6fe8545c48f24fda92df20 100644 (file)
@@ -69,7 +69,8 @@ static int    pwg_compare_finishings(_pwg_finishings_t *a,
                                       _pwg_finishings_t *b);
 static void    pwg_free_finishings(_pwg_finishings_t *f);
 static void    pwg_ppdize_name(const char *ipp, char *name, size_t namesize);
-static void    pwg_unppdize_name(const char *ppd, char *name, size_t namesize);
+static void    pwg_unppdize_name(const char *ppd, char *name, size_t namesize,
+                                 const char *dashchars);
 
 
 /*
@@ -575,6 +576,15 @@ _ppdCacheCreateWithFile(
       else
         pc->mandatory = _cupsArrayNewStrings(value, ' ');
     }
+    else if (!_cups_strcasecmp(line, "SupportFile"))
+    {
+      if (!pc->support_files)
+        pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0,
+                                          (cups_acopy_func_t)_cupsStrAlloc,
+                                          (cups_afree_func_t)_cupsStrFree);
+
+      cupsArrayAdd(pc->support_files, value);
+    }
     else
     {
       DEBUG_printf(("_ppdCacheCreateWithFile: Unknown %s on line %d.", line,
@@ -760,7 +770,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)     /* I - PPD file */
        pwg_name      = pwg_keyword;
        new_known_pwg = 0;
 
-       pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name));
+       pwg_unppdize_name(ppd_size->name, ppd_name, sizeof(ppd_name), "_.");
        _pwgGenerateSize(pwg_keyword, sizeof(pwg_keyword), NULL, ppd_name,
                         _PWG_FROMPTS(ppd_size->width),
                         _PWG_FROMPTS(ppd_size->length));
@@ -928,7 +938,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)     /* I - PPD file */
        */
 
         pwg_name = pwg_keyword;
-       pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
+       pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword),
+                         "_");
       }
 
       map->pwg = _cupsStrAlloc(pwg_name);
@@ -992,7 +1003,8 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)    /* I - PPD file */
        */
 
         pwg_name = pwg_keyword;
-       pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
+       pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword),
+                         "_");
       }
 
       map->pwg = _cupsStrAlloc(pwg_name);
@@ -1021,7 +1033,7 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)   /* I - PPD file */
         i > 0;
         i --, choice ++, map ++)
     {
-      pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword));
+      pwg_unppdize_name(choice->choice, pwg_keyword, sizeof(pwg_keyword), "_");
 
       map->pwg = _cupsStrAlloc(pwg_keyword);
       map->ppd = _cupsStrAlloc(choice->choice);
@@ -1401,6 +1413,22 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd)  /* I - PPD file */
   if ((ppd_attr = ppdFindAttr(ppd, "cupsMandatory", NULL)) != NULL)
     pc->mandatory = _cupsArrayNewStrings(ppd_attr->value, ' ');
 
+ /*
+  * Support files...
+  */
+
+  pc->support_files = cupsArrayNew3(NULL, NULL, NULL, 0,
+                                   (cups_acopy_func_t)_cupsStrAlloc,
+                                   (cups_afree_func_t)_cupsStrFree);
+
+  for (ppd_attr = ppdFindAttr(ppd, "cupsICCProfile", NULL);
+       ppd_attr;
+       ppd_attr = ppdFindNextAttr(ppd, "cupsICCProfile", NULL))
+    cupsArrayAdd(pc->support_files, ppd_attr->value);
+
+  if ((ppd_attr = ppdFindAttr(ppd, "APPrinterIconPath", NULL)) != NULL)
+    cupsArrayAdd(pc->support_files, ppd_attr->value);
+
  /*
   * Return the cache data...
   */
@@ -1506,6 +1534,8 @@ _ppdCacheDestroy(_ppd_cache_t *pc)        /* I - PPD cache and mapping data */
 
   cupsArrayDelete(pc->mandatory);
 
+  cupsArrayDelete(pc->support_files);
+
   free(pc);
 }
 
@@ -2416,6 +2446,15 @@ _ppdCacheWriteFile(
        value = (char *)cupsArrayNext(pc->mandatory))
     cupsFilePutConf(fp, "Mandatory", value);
 
+ /*
+  * Support files...
+  */
+
+  for (value = (char *)cupsArrayFirst(pc->support_files);
+       value;
+       value = (char *)cupsArrayNext(pc->support_files))
+    cupsFilePutConf(fp, "SupportFile", value);
+
  /*
   * IPP attributes, if any...
   */
@@ -2661,7 +2700,8 @@ pwg_ppdize_name(const char *ipp,  /* I - IPP keyword */
 static void
 pwg_unppdize_name(const char *ppd,     /* I - PPD keyword */
                  char       *name,     /* I - Name buffer */
-                  size_t     namesize) /* I - Size of name buffer */
+                  size_t     namesize, /* I - Size of name buffer */
+                  const char *dashchars)/* I - Characters to be replaced by dashes */
 {
   char *ptr,                           /* Pointer into name buffer */
        *end;                           /* End of name buffer */
@@ -2671,8 +2711,10 @@ pwg_unppdize_name(const char *ppd,       /* I - PPD keyword */
   {
     if (_cups_isalnum(*ppd) || *ppd == '-')
       *ptr++ = tolower(*ppd & 255);
-    else if (*ppd == '_' || *ppd == '.')
+    else if (strchr(dashchars, *ppd))
       *ptr++ = '-';
+    else
+      *ptr++ = *ppd;
 
     if (!_cups_isupper(*ppd) && _cups_isalnum(*ppd) &&
        _cups_isupper(ppd[1]) && ptr < end)
index 03b014783d3a1e8be4cd8301e4f6ea208817f732..23514b440cd38930c2315de4494ddd9f24b652e8 100644 (file)
@@ -49,7 +49,7 @@ extern "C" {
  * Constants...
  */
 
-#  define _PPD_CACHE_VERSION   5       /* Version number in cache file */
+#  define _PPD_CACHE_VERSION   6       /* Version number in cache file */
 
 
 /*
@@ -147,6 +147,7 @@ struct _ppd_cache_s                 /**** PPD cache and PWG conversion data ****/
   char         *password;              /* cupsJobPassword value */
   cups_array_t *mandatory;             /* cupsMandatory value */
   char         *charge_info_uri;       /* cupsChargeInfoURI value */
+  cups_array_t *support_files;         /* Support files - ICC profiles, etc. */
 };
 
 
index a1ec90028fc7abcd1e693aeac9c08e7fedbeae78..5802b84a10519d6b249fd2b56de1f0ee798f6341 100644 (file)
@@ -225,7 +225,6 @@ static _pwg_media_t const cups_pwg_media[] =
   _PWG_MEDIA_MM("prc_1_102x165mm", NULL, "EnvPRC1", 102, 165),
   _PWG_MEDIA_MM("prc_2_102x176mm", NULL, "EnvPRC2", 102, 176),
   _PWG_MEDIA_MM("prc_4_110x208mm", NULL, "EnvPRC4", 110, 208),
-  _PWG_MEDIA_MM("prc_5_110x220mm", NULL, "EnvPRC5", 110, 220),
   _PWG_MEDIA_MM("prc_8_120x309mm", NULL, "EnvPRC8", 120, 309),
   _PWG_MEDIA_MM("prc_6_120x320mm", NULL, NULL, 120, 320),
   _PWG_MEDIA_MM("prc_3_125x176mm", NULL, "EnvPRC3", 125, 176),
index 77e3e79eba630c975071902163ed3acfacdebae1..f0ddc642df81ecf91f541e96b2e8b7fe8ca4169b 100644 (file)
@@ -117,6 +117,7 @@ cupsCancelJob2(http_t     *http,    /* I - Connection to server or @code CUPS_HTTP_
 {
   char         uri[HTTP_MAX_URI];      /* Job/printer URI */
   ipp_t                *request;               /* IPP request */
+  _cups_globals_t *cg = _cupsGlobals();        /* Thread global data */
 
 
  /*
@@ -150,6 +151,8 @@ cupsCancelJob2(http_t     *http,    /* I - Connection to server or @code CUPS_HTTP_
 
   request = ippNewRequest(job_id < 0 ? IPP_PURGE_JOBS : IPP_CANCEL_JOB);
 
+  ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
   if (name)
   {
     httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
@@ -211,6 +214,7 @@ cupsCreateJob(
                *response;              /* Create-Job response */
   ipp_attribute_t *attr;               /* job-id attribute */
   int          job_id = 0;             /* job-id value */
+  _cups_globals_t *cg = _cupsGlobals();        /* Thread global data */
 
 
   DEBUG_printf(("cupsCreateJob(http=%p, name=\"%s\", title=\"%s\", "
@@ -237,6 +241,8 @@ cupsCreateJob(
     return (0);
   }
 
+  ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
   httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
                    NULL, "localhost", ippPort(), "/printers/%s", name);
   snprintf(resource, sizeof(resource), "/printers/%s", name);
@@ -363,6 +369,8 @@ cupsGetClasses(char ***classes)             /* O - Classes */
 
   request = ippNewRequest(CUPS_GET_CLASSES);
 
+  ippSetVersion(request, 1, 1);
+
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                "requested-attributes", NULL, "printer-name");
 
@@ -482,6 +490,8 @@ cupsGetDefault2(http_t *http)               /* I - Connection to server or @code CUPS_HTTP_DE
 
   request = ippNewRequest(CUPS_GET_DEFAULT);
 
+  ippSetVersion(request, 1, 1);
+
  /*
   * Do the request and get back a response...
   */
@@ -627,6 +637,8 @@ cupsGetJobs2(http_t     *http,              /* I - Connection to server or @code CUPS_HTTP_D
 
   request = ippNewRequest(IPP_GET_JOBS);
 
+  ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI,
                "printer-uri", NULL, uri);
 
@@ -936,10 +948,16 @@ cupsGetPPD3(http_t     *http,             /* I  - HTTP connection or @code CUPS_HTTP_DEFAUL
   * See if the PPD file is available locally...
   */
 
-  if (!cg->servername[0])
-    cupsServer();
+  if (http)
+    httpGetHostname(http, hostname, sizeof(hostname));
+  else
+  {
+    strlcpy(hostname, cupsServer(), sizeof(hostname));
+    if (hostname[0] == '/')
+      strlcpy(hostname, "localhost", sizeof(hostname));
+  }
 
-  if (!_cups_strcasecmp(cg->servername, "localhost"))
+  if (!_cups_strcasecmp(hostname, "localhost"))
   {
     char       ppdname[1024];          /* PPD filename */
     struct stat        ppdinfo;                /* PPD file information */
@@ -1209,6 +1227,8 @@ cupsGetPrinters(char ***printers) /* O - Printers */
 
   request = ippNewRequest(CUPS_GET_PRINTERS);
 
+  ippSetVersion(request, 1, 1);
+
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
                "requested-attributes", NULL, "printer-name");
 
@@ -1325,6 +1345,8 @@ cupsGetServerPPD(http_t     *http,        /* I - Connection to server or @code CUPS_HTT
   */
 
   request = ippNewRequest(CUPS_GET_PPD);
+  ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_NAME, "ppd-name", NULL,
                name);
 
@@ -1566,6 +1588,7 @@ cupsStartDocument(
                printer_uri[1024];      /* Printer URI */
   ipp_t                *request;               /* Send-Document request */
   http_status_t        status;                 /* HTTP status */
+  _cups_globals_t *cg = _cupsGlobals();        /* Thread global data */
 
 
  /*
@@ -1578,6 +1601,8 @@ cupsStartDocument(
     return (HTTP_ERROR);
   }
 
+  ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
   httpAssembleURIf(HTTP_URI_CODING_ALL, printer_uri, sizeof(printer_uri), "ipp",
                    NULL, "localhost", ippPort(), "/printers/%s", name);
   snprintf(resource, sizeof(resource), "/printers/%s", name);
@@ -1635,6 +1660,7 @@ cups_get_printer_uri(
                classname[255],         /* Temporary class name */
                http_hostname[HTTP_MAX_HOST];
                                        /* Hostname associated with connection */
+  _cups_globals_t *cg = _cupsGlobals();        /* Thread global data */
   static const char * const requested_attrs[] =
                {                       /* Requested attributes */
                  "device-uri",
@@ -1684,6 +1710,8 @@ cups_get_printer_uri(
 
   request = ippNewRequest(IPP_GET_PRINTER_ATTRIBUTES);
 
+  ippSetVersion(request, cg->server_version / 10, cg->server_version % 10);
+
   ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
                NULL, uri);
 
index f3fe9811483caa36338d4c2653c2e97e4a005b82..808a10c2eb456a8b920e517069dea45262437e17 100644 (file)
  */
 
 #  if defined(__GNUC__) && __GNUC__ > 2
-#    if defined(__clang__) && defined(_CUPS_NO_DEPRECATED)
+#    ifndef __has_extension
+#      define __has_extension(x) 0
+#    endif /* !__has_extension */
+#    if __has_extension(attribute_unavailable_with_message) && defined(_CUPS_NO_DEPRECATED)
 #      define _CUPS_DEPRECATED __attribute__ ((unavailable))
 #      define _CUPS_DEPRECATED_MSG(m) __attribute__ ((unavailable(m)))
 #    elif !defined(_CUPS_SOURCE) || defined(_CUPS_NO_DEPRECATED)
 #    define __attribute__(x)
 #  endif /* !__GNUC__ */
 
-#
 #endif /* !_CUPS_VERSIONING_H_ */
 
 /*
index 55808b70ff1ecc44b8240163e65d3df31d53807d..ae01094853b93ae43d291ad3524c50761b8c3130 100644 (file)
@@ -105,6 +105,7 @@ HELPFILES   =       \
                        help/ref-classes-conf.html \
                        help/ref-client-conf.html \
                        help/ref-cupsd-conf.html \
+                       help/ref-cups-files-conf.html \
                        help/ref-error_log.html \
                        help/ref-mailto-conf.html \
                        help/ref-page_log.html \
index 4029f42888e81d1f880d6c01f30fa67e951f6707..1c7c75b9e94633bd190f1e01130ad211f5a21a03 100644 (file)
@@ -11,7 +11,7 @@
 ipptoolfile - ipptool file format
 
 <h2 class="title"><a name="DESCRIPTION">Description</a></h2>
-The <a href='man-ipptool.html?TOPIC=Man+Pages'>ipptool(1)</a> program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curley braces, for example:
+The <a href='man-ipptool.html?TOPIC=Man+Pages'>ipptool(1)</a> program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curly braces, for example:
 <pre>
 
     # This is a comment
@@ -643,7 +643,7 @@ no job-uri has been seen.
 </dd>
 <dt>$notify-subscription-id
 </dt>
-<dd>Inserts the last notify-subscription-id value returnd in a test response or 0 if
+<dd>Inserts the last notify-subscription-id value returned in a test response or 0 if
 no notify-subscription-id has been seen.
 </dd>
 <dt>$port
index d128cdcb3da3af0c3d4811eb90df8dd267b15db0..e7447bfe19daf8b21b24bd5d4a411938b7bc9b58 100644 (file)
@@ -2853,10 +2853,10 @@ msgstr "Carpeta d'arxivador "
 #, c-format
 msgid ""
 "File device URIs have been disabled. To enable, see the FileDevice directive "
-"in \"%s/cupsd.conf\"."
+"in \"%s/cups-files.conf\"."
 msgstr ""
 "S'han deshabilitat els URIs dels dispositius de fitxers. Per habilitar-los, "
-"vegeu la directriu FileDevice a «%s/cupsd.conf»."
+"vegeu la directriu FileDevice a «%s/cups-files.conf»."
 
 #, c-format
 msgid "Finished page %d."
index 14887723583fa76295cb72b4ed010aef8c4a1e4e..4418646a100a86461353e98da612952bb9cb99c2 100644 (file)
@@ -2839,10 +2839,10 @@ msgstr "Carpeta de archivo"
 #, c-format
 msgid ""
 "File device URIs have been disabled. To enable, see the FileDevice directive "
-"in \"%s/cupsd.conf\"."
+"in \"%s/cups-files.conf\"."
 msgstr ""
 "Los URIs del dispositivo de archivo han sido deshabilitados. Para "
-"habilitarlos, vea la directiva FileDevice en \"%s/cupsd.conf\"."
+"habilitarlos, vea la directiva FileDevice en \"%s/cups-files.conf\"."
 
 #, c-format
 msgid "Finished page %d."
index 7a49ad5c8c279b76e5dfff853beb45042473cb51..e489893b374232c80144362a47a7bafb3963626f 100644 (file)
@@ -2836,9 +2836,9 @@ msgstr "ファイルフォルダー"
 #, c-format
 msgid ""
 "File device URIs have been disabled. To enable, see the FileDevice directive "
-"in \"%s/cupsd.conf\"."
+"in \"%s/cups-files.conf\"."
 msgstr ""
-"ファイルデバイス URI は無効になっています。有効にするには、\"%s/cupsd.conf\" "
+"ファイルデバイス URI は無効になっています。有効にするには、\"%s/cups-files.conf\" "
 "の FileDevice ディレクティブを参照してください。"
 
 #, c-format
index b347cf55da40831ae456a464f35ad5609274c566..50517a251547f184e36a0df1c3708f5ef570f922 100644 (file)
@@ -12,7 +12,7 @@
 .\"   which should have been included with this file.  If this file is
 .\"   file is missing or damaged, see the license at "http://www.cups.org/".
 .\"
-.TH cupsctl 8 "CUPS" "16 July 2012" "Apple Inc."
+.TH cupsctl 8 "CUPS" "12 December 2012" "Apple Inc."
 .SH NAME
 cupsctl \- configure cupsd.conf options
 .SH SYNOPSIS
@@ -84,11 +84,6 @@ Disable printer sharing:
 .nf
     cupsctl --no-shared-printers
 .fi
-.LP
-Enable printing using the file: pseudo-device:
-.nf
-    cupsctl FileDevice=Yes
-.fi
 .SH KNOWN ISSUES
 You cannot set the Listen or Port directives using \fIcupsctl\fR.
 .SH SEE ALSO
index da60b843c40aa8687b894378a11d9e9c0207ddb2..aea8d80cda29bbf8cf99c2df972d7ed29221a681 100644 (file)
 .\"   which should have been included with this file.  If this file is
 .\"   file is missing or damaged, see the license at "http://www.cups.org/".
 .\"
-.TH ipptoolfile 5 "CUPS" "16 November 2012" "Apple Inc."
+.TH ipptoolfile 5 "CUPS" "3 December 2012" "Apple Inc."
 .SH NAME
 ipptoolfile \- ipptool file format
 
 .SH DESCRIPTION
-The \fIipptool(1)\fR program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curley braces, for example:
+The \fIipptool(1)\fR program accepts free-form plain text files that describe one or more IPP requests. Comments start with the "#" character and continue to the end of the line. Each request is enclosed by curly braces, for example:
 .nf
 
     # This is a comment
@@ -547,7 +547,7 @@ $scheme
 Inserts the scheme from the URI provided to \fIipptool\fR.
 .TP 5
 $notify-subscription-id
-Inserts the last notify-subscription-id value returnd in a test response or 0 if
+Inserts the last notify-subscription-id value returned in a test response or 0 if
 no notify-subscription-id has been seen.
 .TP 5
 $port
index 6a07338533e36feb3465fe14bd9753634e78b96d..571acaa977f4905f1b0feef7e83ba258b4314323 100644 (file)
 .\"   which should have been included with this file.  If this file is
 .\"   file is missing or damaged, see the license at "http://www.cups.org/".
 .\"
-.TH ppdcfile 5 "CUPS" "20 May 2008" "Apple Inc."
+.TH ppdcfile 5 "CUPS" "3 December 2012" "Apple Inc."
 .SH NAME
 ppdcfile \- cups ppd compiler source file format
 .SH DESCRIPTION
 The CUPS PPD compiler reads meta files that contain descriptions
 of one or more PPD files to be generated by \fIppdc\fR. This man
 page provides a quick reference to the supported keywords and
-should be used in conjuction with the Common UNIX Printing System
-Developers Manual.
+should be used in conjunction with the online help for CUPS.
 .PP
 The source file format is plain ASCII text that can be edited
 using your favorite text editor. Comments are supported using
 the C (/* ... */) and C++ (// ...) comment mechanisms.
 .PP
 Printer driver information can be grouped and shared using
-curley braces ({ ... }); PPD files are written when a close
+curly braces ({ ... }); PPD files are written when a close
 brace or end-of-file is seen and a PCFileName directive has been
 defined.
 .PP
index 5587c2083d42f7ddeb7983f5aa3ad6c7dbf476a4..95f147fe0b4051f2b13a1a92639597191e71fddf 100644 (file)
@@ -77,7 +77,10 @@ install-exec:
        done
        if test "x$(SYMROOT)" != "x"; then \
                $(INSTALL_DIR) $(SYMROOT); \
-               cp $(NOTIFIERS) $(SYMROOT); \
+               for file in $(NOTIFIERS); do \
+                       cp $$file $(SYMROOT); \
+                       dsymutil $(SYMROOT)/$$file; \
+               done \
        fi
 
 
index 5fb794a9ef8fd2a59c933c88239984501d1bdaf2..377b10c8bd2938441b2882e390cfd26c2bdc4069 100644 (file)
@@ -110,6 +110,7 @@ install-exec:
                $(INSTALL_DIR) $(SYMROOT); \
                for file in $(TARGETS); do \
                        cp $$file $(SYMROOT); \
+                       dsymutil $(SYMROOT)/$$file; \
                done \
        fi
 
index eb918d879fb75e37620726d5739fec8ea4151dc9..9a17f3e722d175c11a59f997ce1843f7f507c6ca 100644 (file)
@@ -3080,8 +3080,8 @@ check_sizes(ppd_file_t *ppd,              /* I - PPD file */
   const char   *prefix;                /* WARN/FAIL prefix */
   ppd_option_t *page_size,             /* PageSize option */
                *page_region;           /* PageRegion option */
-  _pwg_media_t  *pwg_media;             /* PWG media */
-  char          buf[1024];              /* PapeSize name that is supposed to be */
+  _pwg_media_t *pwg_media;             /* PWG media */
+  char         buf[PPD_MAX_NAME];      /* PapeSize name that is supposed to be */
   const char   *ptr;                   /* Pointer into string */
   int          width_2540ths,          /* PageSize width in 2540ths */
                length_2540ths;         /* PageSize length in 2540ths */
@@ -3217,6 +3217,11 @@ check_sizes(ppd_file_t *ppd,             /* I - PPD file */
                           _PWG_FROMPTS(size->width);
       pwg_media      = _pwgMediaForSize(width_2540ths, length_2540ths);
 
+      if (pwg_media &&
+          (fabs(pwg_media->width - width_2540ths) > 34 ||
+           fabs(pwg_media->length - length_2540ths) > 34))
+        pwg_media = NULL;              /* Only flag matches within a point */
+
       if (pwg_media && pwg_media->ppd &&
           (pwg_media->ppd[0] < 'a' || pwg_media->ppd[0] > 'z'))
       {
@@ -3233,6 +3238,8 @@ check_sizes(ppd_file_t *ppd,              /* I - PPD file */
             snprintf(buf, sizeof(buf), "%s.Transverse", pwg_media->ppd);
           else
             snprintf(buf, sizeof(buf), "%sRotated", pwg_media->ppd);
+
+         ppdlen = strlen(buf);
         }
 
         if (size->left == 0 && size->bottom == 0 &&
@@ -3301,7 +3308,7 @@ check_sizes(ppd_file_t *ppd,              /* I - PPD file */
         length_tmp = (fabs(size->length - ceil(size->length)) < 0.1) ?
                         ceil(size->length) : size->length;
 
-        if (fmod(width_tmp, 18.0) == 0.0 || fmod(length_tmp, 18.0) == 0.0)
+        if (fmod(width_tmp, 9.0) == 0.0 && fmod(length_tmp, 9.0) == 0.0)
         {
           width_inch  = width_tmp / 72.0;
           length_inch = length_tmp / 72.0;
@@ -3324,14 +3331,26 @@ check_sizes(ppd_file_t *ppd,            /* I - PPD file */
 
         if (_cups_strcasecmp(size->name, buf))
         {
-          size_t buflen = strlen(buf); /* Length of proposed name */
+          size_t       buflen = strlen(buf);
+                                       /* Length of proposed name */
 
           if (_cups_strncasecmp(size->name, buf, buflen) ||
               (strcmp(size->name + buflen, "in") &&
                size->name[buflen] != '.'))
-           _cupsLangPrintf(stdout,
-                           _("      %s  Size \"%s\" should be \"%s\"."),
-                           prefix, size->name, buf);
+          {
+           char        altbuf[PPD_MAX_NAME];
+                                       /* Alternate "wNNNhNNN" name */
+           size_t      altlen;         /* Length of alternate name */
+
+           snprintf(altbuf, sizeof(altbuf), "w%.0fh%.0f", size->width,
+                    size->length);
+           altlen = strlen(altbuf);
+           if (_cups_strncasecmp(size->name, altbuf, altlen) ||
+               (size->name[altlen] && size->name[altlen] != '.'))
+             _cupsLangPrintf(stdout,
+                             _("      %s  Size \"%s\" should be \"%s\"."),
+                             prefix, size->name, buf);
+         }
         }
       }
     }
index ad85720ccb3361a0dc2adc5a7c4e8eddcb950380..c72418dc3844564494c749167db694d7a19d9d40 100644 (file)
@@ -125,6 +125,7 @@ install-exec:
        if test "x$(SYMROOT)" != "x"; then \
                $(INSTALL_DIR) $(SYMROOT); \
                cp ipptool $(SYMROOT); \
+               dsymutil $(SYMROOT)/ipptool; \
        fi
 
 
index ae604196e31495396b20a7aaf0f21e4795cf2f97..3b85ad6f1875778406ec992c80d56c05d9b8bc27 100644 (file)
@@ -94,6 +94,7 @@
 #  include <dns_sd.h>
 #endif /* HAVE_DNSSD */
 #include <sys/stat.h>
+#include <sys/fcntl.h>
 #include <poll.h>
 #ifdef HAVE_SYS_MOUNT_H
 #  include <sys/mount.h>
index e2cbc962ef9ca8155e44f4d71bccbb464534f36f..56d56df676d1649c50cce3dd35eab89d3b60365f 100644 (file)
@@ -816,8 +816,8 @@ do_tests(_cups_vars_t *vars,                /* I - Variables */
   * Connect to the server...
   */
 
-  if ((http = _httpCreate(vars->hostname, vars->port, NULL, vars->family,
-                          vars->encryption, 1, _HTTP_MODE_CLIENT)) == NULL)
+  if ((http = httpConnect2(vars->hostname, vars->port, NULL, vars->family,
+                           vars->encryption, 1, 30000, NULL)) == NULL)
   {
     print_fatal_error("Unable to connect to %s on port %d - %s", vars->hostname,
                       vars->port, cupsLastErrorString());
@@ -825,13 +825,12 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
     goto test_exit;
   }
 
-  if (httpReconnect(http))
-  {
-    print_fatal_error("Unable to connect to %s on port %d - %s", vars->hostname,
-                      vars->port, cupsLastErrorString());
-    pass = 0;
-    goto test_exit;
-  }
+#ifdef HAVE_LIBZ
+  httpSetDefaultField(http, HTTP_FIELD_ACCEPT_ENCODING,
+                      "deflate, gzip, identity");
+#else
+  httpSetDefaultField(http, HTTP_FIELD_ACCEPT_ENCODING, "identity");
+#endif /* HAVE_LIBZ */
 
   if (vars->timeout > 0.0)
     httpSetTimeout(http, vars->timeout, timeout_cb, NULL);
@@ -2300,8 +2299,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
        puts("<key>StatusCode</key>");
        print_xml_string("string", "skip");
        puts("<key>ResponseAttributes</key>");
-       puts("<dict>");
-       puts("</dict>");
+       puts("<dict />");
       }
       else if (Output == _CUPS_OUTPUT_TEST)
        puts("SKIP]");
@@ -2628,7 +2626,6 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
            int out_of_order = 0;       /* Are attribute groups out-of-order? */
            cupsArrayClear(a);
 
-
             switch (attrptr->group_tag)
             {
               case IPP_TAG_ZERO :
@@ -3025,7 +3022,7 @@ do_tests(_cups_vars_t *vars,              /* I - Variables */
     }
 
     if (num_displayed > 0 && !Verbosity && response &&
-        (Output == _CUPS_OUTPUT_TEST || Output == _CUPS_OUTPUT_PLIST))
+        Output == _CUPS_OUTPUT_TEST)
     {
       for (attrptr = response->attrs;
           attrptr != NULL;
@@ -3786,8 +3783,11 @@ print_attr(ipp_attribute_t *attr,        /* I  - Attribute to print */
   {
     if (!attr->name || (group && *group != attr->group_tag))
     {
-      puts("</dict>");
-      puts("<dict>");
+      if (attr->group_tag != IPP_TAG_ZERO)
+      {
+       puts("</dict>");
+       puts("<dict>");
+      }
 
       if (group)
         *group = attr->group_tag;
@@ -4609,7 +4609,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad boolen value %d "
-                       "(RFC 2911 section 4.1.10).", attr->name,
+                       "(RFC 2911 section 4.1.11).", attr->name,
                        attr->values[i].boolean);
          }
        }
@@ -4656,7 +4656,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad dateTime month %u "
-                       "(RFC 2911 section 4.1.13).", attr->name, date[2]);
+                       "(RFC 2911 section 4.1.14).", attr->name, date[2]);
          }
 
           if (date[3] < 1 || date[3] > 31)
@@ -4665,7 +4665,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad dateTime day %u "
-                       "(RFC 2911 section 4.1.13).", attr->name, date[3]);
+                       "(RFC 2911 section 4.1.14).", attr->name, date[3]);
          }
 
           if (date[4] > 23)
@@ -4674,7 +4674,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad dateTime hours %u "
-                       "(RFC 2911 section 4.1.13).", attr->name, date[4]);
+                       "(RFC 2911 section 4.1.14).", attr->name, date[4]);
          }
 
           if (date[5] > 59)
@@ -4683,7 +4683,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad dateTime minutes %u "
-                       "(RFC 2911 section 4.1.13).", attr->name, date[5]);
+                       "(RFC 2911 section 4.1.14).", attr->name, date[5]);
          }
 
           if (date[6] > 60)
@@ -4692,7 +4692,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad dateTime seconds %u "
-                       "(RFC 2911 section 4.1.13).", attr->name, date[6]);
+                       "(RFC 2911 section 4.1.14).", attr->name, date[6]);
          }
 
           if (date[7] > 9)
@@ -4701,7 +4701,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad dateTime deciseconds %u "
-                       "(RFC 2911 section 4.1.13).", attr->name, date[7]);
+                       "(RFC 2911 section 4.1.14).", attr->name, date[7]);
          }
 
           if (date[8] != '-' && date[8] != '+')
@@ -4710,7 +4710,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad dateTime UTC sign '%c' "
-                       "(RFC 2911 section 4.1.13).", attr->name, date[8]);
+                       "(RFC 2911 section 4.1.14).", attr->name, date[8]);
          }
 
           if (date[9] > 11)
@@ -4719,7 +4719,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad dateTime UTC hours %u "
-                       "(RFC 2911 section 4.1.13).", attr->name, date[9]);
+                       "(RFC 2911 section 4.1.14).", attr->name, date[9]);
          }
 
           if (date[10] > 59)
@@ -4728,7 +4728,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad dateTime UTC minutes %u "
-                       "(RFC 2911 section 4.1.13).", attr->name, date[10]);
+                       "(RFC 2911 section 4.1.14).", attr->name, date[10]);
          }
        }
         break;
@@ -4743,7 +4743,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
            add_stringf(errors,
                        "\"%s\": Bad resolution value %dx%d%s - cross "
                        "feed resolution must be positive "
-                       "(RFC 2911 section 4.1.13).", attr->name,
+                       "(RFC 2911 section 4.1.15).", attr->name,
                        attr->values[i].resolution.xres,
                        attr->values[i].resolution.yres,
                        attr->values[i].resolution.units ==
@@ -4759,7 +4759,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
            add_stringf(errors,
                        "\"%s\": Bad resolution value %dx%d%s - feed "
                        "resolution must be positive "
-                       "(RFC 2911 section 4.1.13).", attr->name,
+                       "(RFC 2911 section 4.1.15).", attr->name,
                        attr->values[i].resolution.xres,
                        attr->values[i].resolution.yres,
                        attr->values[i].resolution.units ==
@@ -4775,7 +4775,7 @@ validate_attr(cups_array_t    *errors,    /* I - Errors array */
 
            add_stringf(errors,
                        "\"%s\": Bad resolution value %dx%d%s - bad "
-                       "units value (RFC 2911 section 4.1.13).",
+                       "units value (RFC 2911 section 4.1.15).",
                        attr->name, attr->values[i].resolution.xres,
                        attr->values[i].resolution.yres,
                        attr->values[i].resolution.units ==
index 3c19b20303396e39f28c9dfcb8ba55eadcbe7e50..b021204a96fc94c56fccccf45a03ec42930c8176 100755 (executable)
@@ -425,6 +425,10 @@ ErrorLog /tmp/cups-$user/log/error_log
 PageLog /tmp/cups-$user/log/page_log
 EOF
 
+if test $ssltype != 0 -a `uname` = Darwin; then
+       echo "ServerCertificate $HOME/Library/Keychains/login.keychain" >> /tmp/cups-$user/cups-files.conf
+fi
+
 #
 # Setup lots of test queues - half with PPD files, half without...
 #