summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGES-1.6.txt10
-rw-r--r--backend/Makefile3
-rw-r--r--backend/dnssd.c44
-rw-r--r--backend/snmp-supplies.c4
-rw-r--r--berkeley/Makefile1
-rw-r--r--conf/Makefile2
-rw-r--r--conf/cups-files.conf.in2
-rw-r--r--config-scripts/cups-opsys.m47
-rw-r--r--config-scripts/cups-ssl.m429
-rw-r--r--cups/Makefile1
-rw-r--r--cups/cups-private.h3
-rw-r--r--cups/dest.c84
-rw-r--r--cups/globals.c11
-rw-r--r--cups/http-addr.c3
-rw-r--r--cups/http-private.h10
-rw-r--r--cups/http-support.c3
-rw-r--r--cups/http.c231
-rw-r--r--cups/http.h2
-rw-r--r--cups/ipp.c937
-rw-r--r--cups/ipp.h4
-rw-r--r--cups/ppd-cache.c56
-rw-r--r--cups/ppd-private.h3
-rw-r--r--cups/pwg-media.c1
-rw-r--r--cups/util.c34
-rw-r--r--cups/versioning.h6
-rw-r--r--doc/Makefile1
-rw-r--r--doc/help/man-ipptoolfile.html4
-rw-r--r--locale/cups_ca.po4
-rw-r--r--locale/cups_es.po4
-rw-r--r--locale/cups_ja.po4
-rw-r--r--man/cupsctl.man7
-rw-r--r--man/ipptoolfile.man6
-rw-r--r--man/ppdcfile.man7
-rw-r--r--notifier/Makefile5
-rw-r--r--systemv/Makefile1
-rw-r--r--systemv/cupstestppd.c33
-rw-r--r--test/Makefile1
-rw-r--r--test/ippserver.c1
-rw-r--r--test/ipptool.c56
-rwxr-xr-xtest/run-stp-tests.sh4
40 files changed, 1251 insertions, 378 deletions
diff --git a/CHANGES-1.6.txt b/CHANGES-1.6.txt
index 5ace73229..c59c1ca54 100644
--- a/CHANGES-1.6.txt
+++ b/CHANGES-1.6.txt
@@ -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
diff --git a/backend/Makefile b/backend/Makefile
index 902bf6e80..c6ddb95b0 100644
--- a/backend/Makefile
+++ b/backend/Makefile
@@ -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
diff --git a/backend/dnssd.c b/backend/dnssd.c
index 46c0f1347..9cea92e03 100644
--- a/backend/dnssd.c
+++ b/backend/dnssd.c
@@ -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
diff --git a/backend/snmp-supplies.c b/backend/snmp-supplies.c
index 4c0258ddd..c669b5db9 100644
--- a/backend/snmp-supplies.c
+++ b/backend/snmp-supplies.c
@@ -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" },
diff --git a/berkeley/Makefile b/berkeley/Makefile
index 8a154c504..8459ea291 100644
--- a/berkeley/Makefile
+++ b/berkeley/Makefile
@@ -88,6 +88,7 @@ install-exec:
$(INSTALL_DIR) $(SYMROOT); \
for file in $(TARGETS); do \
cp $$file $(SYMROOT); \
+ dsymutil $(SYMROOT)/$$file; \
done \
fi
diff --git a/conf/Makefile b/conf/Makefile
index a68a58b16..04cc1e739 100644
--- a/conf/Makefile
+++ b/conf/Makefile
@@ -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
diff --git a/conf/cups-files.conf.in b/conf/cups-files.conf.in
index 8c3a1b58c..01ee93317 100644
--- a/conf/cups-files.conf.in
+++ b/conf/cups-files.conf.in
@@ -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
diff --git a/config-scripts/cups-opsys.m4 b/config-scripts/cups-opsys.m4
index ed4dbbc5e..acf5b51a3 100644
--- a/config-scripts/cups-opsys.m4
+++ b/config-scripts/cups-opsys.m4
@@ -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"
;;
diff --git a/config-scripts/cups-ssl.m4 b/config-scripts/cups-ssl.m4
index 03f7530a3..f3dc0595f 100644
--- a/config-scripts/cups-ssl.m4
+++ b/config-scripts/cups-ssl.m4
@@ -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
diff --git a/cups/Makefile b/cups/Makefile
index 8d5cefd8b..8bab2d405 100644
--- a/cups/Makefile
+++ b/cups/Makefile
@@ -251,6 +251,7 @@ install-libs: $(INSTALLSTATIC)
if test "x$(SYMROOT)" != "x"; then \
$(INSTALL_DIR) $(SYMROOT); \
cp $(LIBCUPS) $(SYMROOT); \
+ dsymutil $(SYMROOT)/$(LIBCUPS); \
fi
installstatic:
diff --git a/cups/cups-private.h b/cups/cups-private.h
index babc0d081..1dd7e8a76 100644
--- a/cups/cups-private.h
+++ b/cups/cups-private.h
@@ -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 */
diff --git a/cups/dest.c b/cups/dest.c
index 1474eb41e..ee3fbc12a 100644
--- a/cups/dest.c
+++ b/cups/dest.c
@@ -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)
{
diff --git a/cups/globals.c b/cups/globals.c
index eed949f83..6a7102aa1 100644
--- a/cups/globals.c
+++ b/cups/globals.c
@@ -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
/*
diff --git a/cups/http-addr.c b/cups/http-addr.c
index 3e050e705..ed6df8057 100644
--- a/cups/http-addr.c
+++ b/cups/http-addr.c
@@ -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.
diff --git a/cups/http-private.h b/cups/http-private.h
index 12ae6ddb9..a789917de 100644
--- a/cups/http-private.h
+++ b/cups/http-private.h
@@ -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 */
diff --git a/cups/http-support.c b/cups/http-support.c
index 2b0d9a827..d0f36c3e1 100644
--- a/cups/http-support.c
+++ b/cups/http-support.c
@@ -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)
diff --git a/cups/http.c b/cups/http.c
index d5099b272..12e7338ad 100644
--- a/cups/http.c
+++ b/cups/http.c
@@ -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 */
@@ -969,6 +971,13 @@ httpFlush(http_t *http) /* I - Connection to server */
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.
@@ -3124,6 +3180,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.
*
* Currently only @code HTTP_STATUS_CONTINUE@ is supported for the "expect"
@@ -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)
@@ -5240,20 +5315,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);
diff --git a/cups/http.h b/cups/http.h
index 3c8a32113..de782aaa3 100644
--- a/cups/http.h
+++ b/cups/http.h
@@ -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;
diff --git a/cups/ipp.c b/cups/ipp.c
index 0c54a2803..76ee409d3 100644
--- a/cups/ipp.c
+++ b/cups/ipp.c
@@ -16,104 +16,107 @@
*
* 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.
*/
/*
@@ -121,6 +124,7 @@
*/
#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);
@@ -4706,6 +4666,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.
*/
@@ -6124,6 +6750,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.
*/
diff --git a/cups/ipp.h b/cups/ipp.h
index 65e4f285a..a87f643a3 100644
--- a/cups/ipp.h
+++ b/cups/ipp.h
@@ -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;
/*
diff --git a/cups/ppd-cache.c b/cups/ppd-cache.c
index be4c64e98..9fe3d6c7d 100644
--- a/cups/ppd-cache.c
+++ b/cups/ppd-cache.c
@@ -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);
@@ -1402,6 +1414,22 @@ _ppdCacheCreateWithPPD(ppd_file_t *ppd) /* I - PPD file */
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);
}
@@ -2417,6 +2447,15 @@ _ppdCacheWriteFile(
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)
diff --git a/cups/ppd-private.h b/cups/ppd-private.h
index 03b014783..23514b440 100644
--- a/cups/ppd-private.h
+++ b/cups/ppd-private.h
@@ -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. */
};
diff --git a/cups/pwg-media.c b/cups/pwg-media.c
index a1ec90028..5802b84a1 100644
--- a/cups/pwg-media.c
+++ b/cups/pwg-media.c
@@ -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),
diff --git a/cups/util.c b/cups/util.c
index 77e3e79eb..f0ddc642d 100644
--- a/cups/util.c
+++ b/cups/util.c
@@ -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);
diff --git a/cups/versioning.h b/cups/versioning.h
index f3fe98114..808a10c2e 100644
--- a/cups/versioning.h
+++ b/cups/versioning.h
@@ -79,7 +79,10 @@
*/
# 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)
@@ -98,7 +101,6 @@
# define __attribute__(x)
# endif /* !__GNUC__ */
-#
#endif /* !_CUPS_VERSIONING_H_ */
/*
diff --git a/doc/Makefile b/doc/Makefile
index 55808b70f..ae0109485 100644
--- a/doc/Makefile
+++ b/doc/Makefile
@@ -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 \
diff --git a/doc/help/man-ipptoolfile.html b/doc/help/man-ipptoolfile.html
index 4029f4288..1c7c75b9e 100644
--- a/doc/help/man-ipptoolfile.html
+++ b/doc/help/man-ipptoolfile.html
@@ -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
diff --git a/locale/cups_ca.po b/locale/cups_ca.po
index d128cdcb3..e7447bfe1 100644
--- a/locale/cups_ca.po
+++ b/locale/cups_ca.po
@@ -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."
diff --git a/locale/cups_es.po b/locale/cups_es.po
index 148877235..4418646a1 100644
--- a/locale/cups_es.po
+++ b/locale/cups_es.po
@@ -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."
diff --git a/locale/cups_ja.po b/locale/cups_ja.po
index 7a49ad5c8..e489893b3 100644
--- a/locale/cups_ja.po
+++ b/locale/cups_ja.po
@@ -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
diff --git a/man/cupsctl.man b/man/cupsctl.man
index b347cf55d..50517a251 100644
--- a/man/cupsctl.man
+++ b/man/cupsctl.man
@@ -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
diff --git a/man/ipptoolfile.man b/man/ipptoolfile.man
index da60b843c..aea8d80cd 100644
--- a/man/ipptoolfile.man
+++ b/man/ipptoolfile.man
@@ -11,12 +11,12 @@
.\" 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
diff --git a/man/ppdcfile.man b/man/ppdcfile.man
index 6a0733853..571acaa97 100644
--- a/man/ppdcfile.man
+++ b/man/ppdcfile.man
@@ -12,22 +12,21 @@
.\" 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
diff --git a/notifier/Makefile b/notifier/Makefile
index 5587c2083..95f147fe0 100644
--- a/notifier/Makefile
+++ b/notifier/Makefile
@@ -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
diff --git a/systemv/Makefile b/systemv/Makefile
index 5fb794a9e..377b10c8b 100644
--- a/systemv/Makefile
+++ b/systemv/Makefile
@@ -110,6 +110,7 @@ install-exec:
$(INSTALL_DIR) $(SYMROOT); \
for file in $(TARGETS); do \
cp $$file $(SYMROOT); \
+ dsymutil $(SYMROOT)/$$file; \
done \
fi
diff --git a/systemv/cupstestppd.c b/systemv/cupstestppd.c
index eb918d879..9a17f3e72 100644
--- a/systemv/cupstestppd.c
+++ b/systemv/cupstestppd.c
@@ -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);
+ }
}
}
}
diff --git a/test/Makefile b/test/Makefile
index ad85720cc..c72418dc3 100644
--- a/test/Makefile
+++ b/test/Makefile
@@ -125,6 +125,7 @@ install-exec:
if test "x$(SYMROOT)" != "x"; then \
$(INSTALL_DIR) $(SYMROOT); \
cp ipptool $(SYMROOT); \
+ dsymutil $(SYMROOT)/ipptool; \
fi
diff --git a/test/ippserver.c b/test/ippserver.c
index ae604196e..3b85ad6f1 100644
--- a/test/ippserver.c
+++ b/test/ippserver.c
@@ -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>
diff --git a/test/ipptool.c b/test/ipptool.c
index e2cbc962e..56d56df67 100644
--- a/test/ipptool.c
+++ b/test/ipptool.c
@@ -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 ==
diff --git a/test/run-stp-tests.sh b/test/run-stp-tests.sh
index 3c19b2030..b021204a9 100755
--- a/test/run-stp-tests.sh
+++ b/test/run-stp-tests.sh
@@ -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...
#