summaryrefslogtreecommitdiff
path: root/cups
diff options
context:
space:
mode:
authormsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2013-01-10 17:01:44 +0000
committermsweet <msweet@a1ca3aef-8c08-0410-bb20-df032aa958be>2013-01-10 17:01:44 +0000
commit0fa6c7fa54164ee70ee9ccfa936b889a637d5ecd (patch)
treed84095ec3813ddd6d09ac71499ab00df3f9450f2 /cups
parentc1420c8744235de1249c34b956b7c11ccafd659d (diff)
Merge changes from CUPS 1.7svn-r10791.
git-svn-id: svn+ssh://src.apple.com/svn/cups/easysw/current@4120 a1ca3aef-8c08-0410-bb20-df032aa958be
Diffstat (limited to 'cups')
-rw-r--r--cups/dest-options.c2
-rw-r--r--cups/http-private.h28
-rw-r--r--cups/http-support.c34
-rw-r--r--cups/http.c833
-rw-r--r--cups/http.h4
-rw-r--r--cups/ipp-support.c20
-rw-r--r--cups/ipp.c8
-rw-r--r--cups/request.c19
-rw-r--r--cups/versioning.h85
9 files changed, 575 insertions, 458 deletions
diff --git a/cups/dest-options.c b/cups/dest-options.c
index d8eff72e5..8477ab30a 100644
--- a/cups/dest-options.c
+++ b/cups/dest-options.c
@@ -485,7 +485,7 @@ cupsCopyDestConflicts(
active = NULL;
}
- if (tries >= 0)
+ if (tries >= 100)
{
DEBUG_puts("1cupsCopyDestConflicts: Unable to resolve after 100 tries.");
have_conflicts = -1;
diff --git a/cups/http-private.h b/cups/http-private.h
index a789917de..9259b1f4a 100644
--- a/cups/http-private.h
+++ b/cups/http-private.h
@@ -3,7 +3,7 @@
*
* Private HTTP definitions for CUPS.
*
- * Copyright 2007-2012 by Apple Inc.
+ * Copyright 2007-2013 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -44,29 +44,14 @@
# ifdef HAVE_GSSAPI
# ifdef HAVE_GSS_GSSAPI_H
# include <GSS/gssapi.h>
-# ifdef HAVE_GSSAPI_GENERIC_H
-# include <GSS/gssapi_generic.h>
-# endif /* HAVE_GSSAPI_GENERIC_H */
-# ifdef HAVE_GSSAPI_KRB5_H
-# include <GSS/gssapi_krb5.h>
-# endif /* HAVE_GSSAPI_KRB5_H */
# elif defined(HAVE_GSSAPI_GSSAPI_H)
# include <gssapi/gssapi.h>
-# ifdef HAVE_GSSAPI_GENERIC_H
-# include <gssapi/gssapi_generic.h>
-# endif /* HAVE_GSSAPI_GENERIC_H */
-# ifdef HAVE_GSSAPI_KRB5_H
-# include <gssapi/gssapi_krb5.h>
-# endif /* HAVE_GSSAPI_KRB5_H */
# elif defined(HAVE_GSSAPI_H)
# include <gssapi.h>
# endif /* HAVE_GSS_GSSAPI_H */
# ifndef HAVE_GSS_C_NT_HOSTBASED_SERVICE
# define GSS_C_NT_HOSTBASED_SERVICE gss_nt_service_name
# endif /* !HAVE_GSS_C_NT_HOSTBASED_SERVICE */
-# ifdef HAVE_KRB5_H
-# include <krb5.h>
-# endif /* HAVE_KRB5_H */
# endif /* HAVE_GSSAPI */
# ifdef HAVE_AUTHORIZATION_H
@@ -341,6 +326,7 @@ struct _http_s /**** HTTP connection structure ****/
# ifdef HAVE_LIBZ
_http_coding_t coding; /* _HTTP_CODING_xxx */
z_stream stream; /* (De)compression stream */
+ Bytef *dbuffer; /* Decompression buffer */
# endif /* HAVE_LIBZ */
};
@@ -407,14 +393,18 @@ extern void _cups_freeifaddrs(struct ifaddrs *addrs);
*/
#define _httpAddrFamily(addrp) (addrp)->addr.sa_family
+extern int _httpAddrPort(http_addr_t *addr)
+ _CUPS_INTERNAL_MSG("Use httpAddrPort instead.");
extern void _httpAddrSetPort(http_addr_t *addr, int port);
extern char *_httpAssembleUUID(const char *server, int port,
const char *name, int number,
- char *buffer, size_t bufsize);
+ char *buffer, size_t bufsize)
+ _CUPS_INTERNAL_MSG("Use httpAssembleUUID instead.");
extern http_t *_httpCreate(const char *host, int port,
http_addrlist_t *addrlist, int family,
http_encryption_t encryption,
- int blocking, _http_mode_t mode);
+ int blocking, _http_mode_t mode)
+ _CUPS_INTERNAL_MSG("Use httpConnect2 or httpAccept instead.");
extern http_tls_credentials_t
_httpCreateCredentials(cups_array_t *credentials);
extern char *_httpDecodeURI(char *dst, const char *src,
@@ -423,6 +413,8 @@ extern void _httpDisconnect(http_t *http);
extern char *_httpEncodeURI(char *dst, const char *src,
size_t dstsize);
extern void _httpFreeCredentials(http_tls_credentials_t credentials);
+extern ssize_t _httpPeek(http_t *http, char *buffer, size_t length)
+ _CUPS_INTERNAL_MSG("Use httpPeek instead.");
extern const char *_httpResolveURI(const char *uri, char *resolved_uri,
size_t resolved_size, int options,
int (*cb)(void *context),
diff --git a/cups/http-support.c b/cups/http-support.c
index d0f36c3e1..cd1565ded 100644
--- a/cups/http-support.c
+++ b/cups/http-support.c
@@ -3,7 +3,7 @@
*
* HTTP support routines for CUPS.
*
- * Copyright 2007-2012 by Apple Inc.
+ * Copyright 2007-2013 by Apple Inc.
* Copyright 1997-2007 by Easy Software Products, all rights reserved.
*
* These coded instructions, statements, and computer programs are the
@@ -20,7 +20,8 @@
* components.
* httpAssembleURIf() - Assemble a uniform resource identifier from its
* components with a formatted resource.
- * _httpAssembleUUID() - Make a UUID URI conforming to RFC 4122.
+ * httpAssembleUUID() - Assemble a name-based UUID URN conforming to RFC
+ * 4122.
* httpDecode64() - Base64-decode a string.
* httpDecode64_2() - Base64-decode a string.
* httpEncode64() - Base64-encode a string.
@@ -466,18 +467,22 @@ httpAssembleURIf(
/*
- * '_httpAssembleUUID()' - Make a UUID URI conforming to RFC 4122.
+ * 'httpAssembleUUID()' - Assemble a name-based UUID URN conforming to RFC 4122.
+ *
+ * This function creates a unique 128-bit identifying number using the server
+ * name, port number, random data, and optionally an object name and/or object
+ * number. The result is formatted as a UUID URN as defined in RFC 4122.
*
* The buffer needs to be at least 46 bytes in size.
*/
char * /* I - UUID string */
-_httpAssembleUUID(const char *server, /* I - Server name */
- int port, /* I - Port number */
- const char *name, /* I - Object name or NULL */
- int number, /* I - Object number or 0 */
- char *buffer, /* I - String buffer */
- size_t bufsize) /* I - Size of buffer */
+httpAssembleUUID(const char *server, /* I - Server name */
+ int port, /* I - Port number */
+ const char *name, /* I - Object name or NULL */
+ int number, /* I - Object number or 0 */
+ char *buffer, /* I - String buffer */
+ size_t bufsize) /* I - Size of buffer */
{
char data[1024]; /* Source string for MD5 */
_cups_md5_state_t md5state; /* MD5 state */
@@ -514,6 +519,13 @@ _httpAssembleUUID(const char *server, /* I - Server name */
return (buffer);
}
+/* For OS X 10.8 and earlier */
+char *_httpAssembleUUID(const char *server, int port, const char *name,
+ int number, char *buffer, size_t bufsize)
+{
+ return (httpAssembleUUID(server, port, name, number, buffer, bufsize));
+}
+
/*
* 'httpDecode64()' - Base64-decode a string.
@@ -2064,6 +2076,8 @@ http_resolve_cb(
error));
#endif /* DEBUG */
}
+
+ httpAddrFreeList(addrlist);
}
}
@@ -2279,6 +2293,8 @@ http_resolve_cb(
error));
#endif /* DEBUG */
}
+
+ httpAddrFreeList(addrlist);
}
}
diff --git a/cups/http.c b/cups/http.c
index 12e7338ad..35b2799dd 100644
--- a/cups/http.c
+++ b/cups/http.c
@@ -48,13 +48,13 @@
* _httpFreeCredentials() - Free internal credentials.
* httpFreeCredentials() - Free an array of credentials.
* httpGet() - Send a GET request to the server.
- * httpGetContentEncoding() - Get a common content encoding, if any,
- * between the client and server.
+ * httpGetContentEncoding() - Get a common content encoding, if any,
+ * between the client and server.
* httpGetAuthString() - Get the current authorization string.
* httpGetBlocking() - Get the blocking/non-block state of a
* connection.
* httpGetCookie() - Get any cookie data from the response.
- * httpGetExpect() - Get the value of the Expect header, if any.
+ * httpGetExpect() - Get the value of the Expect header, if any.
* httpGetFd() - Get the file descriptor associated with a
* connection.
* httpGetField() - Get a field value from a request/response.
@@ -89,6 +89,7 @@
* httpSetCredentials() - Set the credentials associated with an
* encrypted connection.
* httpSetCookie() - Set the cookie value(s).
+ * httpSetDefaultField() - Set the default value of an HTTP header.
* httpSetExpect() - Set the Expect: header in a request.
* httpSetField() - Set the value of an HTTP header.
* httpSetLength() - Set the content-length and
@@ -119,12 +120,15 @@
* http_content_coding_start() - Start doing content encoding.
* http_debug_hex() - Do a hex dump of a buffer.
* http_field() - Return the field index for a field name.
+ * http_read() - Read a buffer from a HTTP connection.
+ * http_read_buffered() - Do a buffered read from a HTTP connection.
+ * http_read_chunk() - Read a chunk from a HTTP connection.
* http_read_ssl() - Read from a SSL/TLS connection.
* http_send() - Send a request with all fields and the
* trailing blank line.
* http_set_credentials() - Set the SSL/TLS credentials.
- * http_set_length() - Set the data_encoding and data_remaining
- * values.
+ * http_set_length() - Set the data_encoding and data_remaining
+ * values.
* http_set_timeout() - Set the socket timeout values.
* http_set_wait() - Set the default wait value for reads.
* http_setup_ssl() - Set up SSL/TLS support on a connection.
@@ -168,12 +172,15 @@ static void http_debug_hex(const char *prefix, const char *buffer,
int bytes);
#endif /* DEBUG */
static http_field_t http_field(const char *name);
+static ssize_t http_read(http_t *http, char *buffer, size_t length);
+static ssize_t http_read_buffered(http_t *http, char *buffer, size_t length);
+static ssize_t http_read_chunk(http_t *http, char *buffer, size_t length);
static int http_send(http_t *http, http_state_t request,
const char *uri);
-static int http_write(http_t *http, const char *buffer,
- int length);
-static int http_write_chunk(http_t *http, const char *buffer,
- int length);
+static ssize_t http_write(http_t *http, const char *buffer,
+ size_t length);
+static ssize_t http_write_chunk(http_t *http, const char *buffer,
+ size_t length);
#ifdef HAVE_SSL
static int http_read_ssl(http_t *http, char *buf, int len);
# ifdef HAVE_CDSASSL
@@ -1449,7 +1456,7 @@ httpGets(char *line, /* I - Line to read into */
DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", line, length, http));
- if (http == NULL || line == NULL)
+ if (!http || !line || length <= 1)
return (NULL);
/*
@@ -1493,20 +1500,10 @@ httpGets(char *line, /* I - Line to read into */
return (NULL);
}
-#ifdef HAVE_SSL
- if (http->tls)
- bytes = http_read_ssl(http, http->buffer + http->used,
- HTTP_MAX_BUFFER - http->used);
- else
-#endif /* HAVE_SSL */
- bytes = recv(http->fd, http->buffer + http->used,
- HTTP_MAX_BUFFER - http->used, 0);
+ bytes = http_read(http, http->buffer + http->used,
+ HTTP_MAX_BUFFER - http->used);
- DEBUG_printf(("4httpGets: read %d bytes...", bytes));
-
-#ifdef DEBUG
- http_debug_hex("httpGets", http->buffer + http->used, bytes);
-#endif /* DEBUG */
+ DEBUG_printf(("4httpGets: read %d bytes.", bytes));
if (bytes < 0)
{
@@ -1918,8 +1915,8 @@ httpOptions(http_t *http, /* I - Connection to server */
ssize_t /* O - Number of bytes copied */
httpPeek(http_t *http, /* I - Connection to server */
- char *buffer, /* I - Buffer for data */
- size_t length) /* I - Maximum number of bytes */
+ char *buffer, /* I - Buffer for data */
+ size_t length) /* I - Maximum number of bytes */
{
ssize_t bytes; /* Bytes read */
char len[32]; /* Length string */
@@ -1959,21 +1956,21 @@ httpPeek(http_t *http, /* I - Connection to server */
DEBUG_printf(("2httpPeek: data_remaining=" CUPS_LLFMT,
CUPS_LLCAST http->data_remaining));
- if (http->data_remaining <= 0)
+ if (http->data_remaining <= 0 && http->data_encoding != HTTP_ENCODING_FIELDS)
{
/*
* A zero-length chunk ends a transfer; unless we are reading POST
* data, go idle...
*/
- if (http->data_encoding == HTTP_ENCODING_CHUNKED)
- httpGets(len, sizeof(len), http);
-
#ifdef HAVE_LIBZ
if (http->coding)
http_content_coding_finish(http);
#endif /* HAVE_LIBZ */
+ if (http->data_encoding == HTTP_ENCODING_CHUNKED)
+ httpGets(len, sizeof(len), http);
+
if (http->state == HTTP_STATE_POST_RECV)
http->state ++;
else
@@ -1990,12 +1987,15 @@ httpPeek(http_t *http, /* I - Connection to server */
return (0);
}
- else if ((http->data_encoding == HTTP_ENCODING_LENGTH ||
- http->coding == _HTTP_CODING_IDENTITY) &&
- length > (size_t)http->data_remaining)
+ else if (length > (size_t)http->data_remaining)
length = (size_t)http->data_remaining;
+#ifdef HAVE_LIBZ
+ if (http->used == 0 &&
+ (http->coding == _HTTP_CODING_IDENTITY || http->stream.avail_in == 0))
+#else
if (http->used == 0)
+#endif /* HAVE_LIBZ */
{
/*
* Buffer small reads for better performance...
@@ -2084,16 +2084,39 @@ httpPeek(http_t *http, /* I - Connection to server */
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;
+ if (http->used > 0 && http->stream.avail_in < HTTP_MAX_BUFFER)
+ {
+ size_t buflen = buflen = HTTP_MAX_BUFFER - http->stream.avail_in;
+ /* Number of bytes to copy */
+
+ if (http->stream.avail_in > 0 &&
+ http->stream.next_in > http->dbuffer)
+ memmove(http->dbuffer, http->stream.next_in, http->stream.avail_in);
+
+ http->stream.next_in = http->dbuffer;
+
+ if (buflen > http->data_remaining)
+ buflen = http->data_remaining;
+
+ if (buflen > http->used)
+ buflen = http->used;
+
+ DEBUG_printf(("1httpPeek: Copying %d more bytes of data into "
+ "decompression buffer.", (int)buflen));
+
+ memcpy(http->dbuffer + http->stream.avail_in, http->buffer, buflen);
+ http->stream.avail_in += buflen;
+ http->used -= buflen;
+ http->data_remaining -= buflen;
+
+ if (http->used > 0)
+ memmove(http->buffer, http->buffer + buflen, http->used);
+ }
DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length,
- (int)comp_avail));
+ (int)http->stream.avail_in));
if (inflateCopy(&stream, &(http->stream)) != Z_OK)
{
@@ -2102,8 +2125,6 @@ httpPeek(http_t *http, /* I - Connection to server */
return (-1);
}
- stream.next_in = (Bytef *)http->buffer;
- stream.avail_in = comp_avail;
stream.next_out = (Bytef *)buffer;
stream.avail_out = length;
@@ -2113,6 +2134,11 @@ httpPeek(http_t *http, /* I - Connection to server */
if (zerr < Z_OK)
{
DEBUG_printf(("2httpPeek: zerr=%d", zerr));
+#ifdef DEBUG
+ http_debug_hex("2httpPeek", (char *)http->dbuffer,
+ http->stream.avail_in);
+#endif /* DEBUG */
+
http->error = EIO;
return (-1);
}
@@ -2264,12 +2290,12 @@ httpRead2(http_t *http, /* I - Connection to server */
size_t length) /* I - Maximum number of bytes */
{
ssize_t bytes; /* Bytes read */
- char len[32]; /* Length string */
DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT
- ") coding=%d", http, buffer, CUPS_LLCAST length,
- http->coding));
+ ") coding=%d data_encoding=%d data_remaining=" CUPS_LLFMT,
+ http, buffer, CUPS_LLCAST length, http->coding,
+ http->data_encoding, CUPS_LLCAST http->data_remaining));
if (http == NULL || buffer == NULL)
return (-1);
@@ -2280,371 +2306,135 @@ httpRead2(http_t *http, /* I - Connection to server */
if (length <= 0)
return (0);
- if (http->data_encoding == HTTP_ENCODING_CHUNKED &&
- http->data_remaining <= 0)
- {
- if (!httpGets(len, sizeof(len), http))
- {
- DEBUG_puts("1httpRead2: Could not get chunk length.");
- return (0);
- }
-
- if (!len[0])
- {
- DEBUG_puts("1httpRead2: Blank chunk length, trying again...");
- if (!httpGets(len, sizeof(len), http))
- {
- DEBUG_puts("1httpRead2: Could not get chunk length.");
- return (0);
- }
- }
-
- http->data_remaining = strtoll(len, NULL, 16);
-
- if (http->data_remaining < 0)
- {
- DEBUG_printf(("1httpRead2: Negative chunk length \"%s\" (" CUPS_LLFMT ")",
- len, CUPS_LLCAST http->data_remaining));
- return (0);
- }
-
- DEBUG_printf(("2httpRead2: Got chunk length \"%s\" (" CUPS_LLFMT ")", len,
- CUPS_LLCAST http->data_remaining));
- }
-
- DEBUG_printf(("2httpRead2: data_remaining=" CUPS_LLFMT ", used=%d",
- CUPS_LLCAST http->data_remaining, http->used));
-
- if (http->data_remaining <= 0 && http->data_encoding != HTTP_ENCODING_FIELDS)
- {
- /*
- * A zero-length chunk ends a transfer; unless we are reading POST
- * data, go idle...
- */
-
#ifdef HAVE_LIBZ
- if (http->coding)
- http_content_coding_finish(http);
-#endif /* HAVE_LIBZ */
-
- if (http->data_encoding == HTTP_ENCODING_CHUNKED)
- httpGets(len, sizeof(len), http);
-
- if (http->state == HTTP_STATE_POST_RECV)
- http->state ++;
- else
- http->state = HTTP_STATE_WAITING;
-
- DEBUG_printf(("1httpRead2: 0-length chunk, set state to %s.",
- http_states[http->state + 1]));
-
- /*
- * Prevent future reads for this request...
- */
-
- http->data_encoding = HTTP_ENCODING_FIELDS;
-
- return (0);
- }
- 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;
-
-#ifdef HAVE_LIBZ
- if (http->used == 0 && (length <= 256 || http->coding))
-#else
- if (http->used == 0 && length <= 256)
-#endif /* HAVE_LIBZ */
+ if (http->coding)
{
- /*
- * Buffer small/compressed reads for better performance...
- */
-
- ssize_t buflen; /* Length of read for buffer */
-
- if (!http->blocking)
+ do
{
- while (!httpWait(http, http->wait_value))
+ if (http->stream.avail_in > 0)
{
- if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
- continue;
+ int zerr; /* Decompressor error */
- return (0);
- }
- }
+ DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d",
+ (int)http->stream.avail_in, (int)length));
- if (http->data_remaining > sizeof(http->buffer))
- buflen = sizeof(http->buffer);
- else
- buflen = http->data_remaining;
-
- DEBUG_printf(("2httpRead2: Reading %d bytes into buffer.", (int)buflen));
+ http->stream.next_out = (Bytef *)buffer;
+ http->stream.avail_out = length;
- do
- {
-#ifdef HAVE_SSL
- if (http->tls)
- bytes = http_read_ssl(http, http->buffer, buflen);
- else
-#endif /* HAVE_SSL */
- bytes = recv(http->fd, http->buffer, buflen, 0);
-
- if (bytes < 0)
- {
-#ifdef WIN32
- if (WSAGetLastError() != WSAEINTR)
- {
- http->error = WSAGetLastError();
- return (-1);
- }
- else if (WSAGetLastError() == WSAEWOULDBLOCK)
+ if ((zerr = inflate(&(http->stream), Z_SYNC_FLUSH)) < Z_OK)
{
- if (!http->timeout_cb ||
- !(*http->timeout_cb)(http, http->timeout_data))
- {
- http->error = WSAEWOULDBLOCK;
- return (-1);
- }
- }
-#else
- if (errno == EWOULDBLOCK || errno == EAGAIN)
- {
- if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
- {
- http->error = errno;
- return (-1);
- }
- else if (!http->timeout_cb && errno != EAGAIN)
- {
- http->error = errno;
- return (-1);
- }
- }
- else if (errno != EINTR)
- {
- http->error = errno;
- return (-1);
- }
-#endif /* WIN32 */
- }
- }
- while (bytes < 0);
-
- DEBUG_printf(("2httpRead2: Read " CUPS_LLFMT " bytes into buffer.",
- CUPS_LLCAST bytes));
+ DEBUG_printf(("2httpRead2: zerr=%d", zerr));
#ifdef DEBUG
- http_debug_hex("httpRead2", http->buffer, (int)bytes);
+ http_debug_hex("2httpRead2", (char *)http->dbuffer,
+ http->stream.avail_in);
#endif /* DEBUG */
- http->used = bytes;
- }
-
-#ifdef HAVE_LIBZ
- if (http->coding)
- {
- int zerr; /* Decompressor error */
- off_t comp_avail, /* Maximum bytes for decompression */
- comp_bytes; /* Compressed bytes "used" */
-
- if (http->used > http->data_remaining)
- comp_avail = http->data_remaining;
- else
- comp_avail = http->used;
-
- DEBUG_printf(("2httpRead2: length=%d, avail_in=%d", (int)length,
- (int)comp_avail));
+ http->error = EIO;
+ return (-1);
+ }
- http->stream.next_in = (Bytef *)http->buffer;
- http->stream.avail_in = comp_avail;
- http->stream.next_out = (Bytef *)buffer;
- http->stream.avail_out = length;
+ bytes = length - http->stream.avail_out;
- if ((zerr = inflate(&(http->stream), Z_SYNC_FLUSH)) < Z_OK)
- {
- DEBUG_printf(("2httpRead2: zerr=%d", zerr));
- http->error = EIO;
- return (-1);
- }
-
- bytes = length - http->stream.avail_out;
- comp_bytes = comp_avail - http->stream.avail_in;
+ DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d",
+ http->stream.avail_in, http->stream.avail_out,
+ (int)bytes));
+ }
+ else
+ bytes = 0;
- DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d, "
- "comp_bytes=%d", http->stream.avail_in,
- http->stream.avail_out, (int)bytes, (int)comp_bytes));
+ if (bytes == 0)
+ {
+ ssize_t buflen = HTTP_MAX_BUFFER - http->stream.avail_in;
+ /* Additional bytes for buffer */
- if ((http->used - comp_bytes) > 0)
- {
- http->used -= comp_bytes;
- memmove(http->buffer, http->stream.next_in, http->used);
+ if (buflen > 0)
+ {
+ if (http->stream.avail_in > 0 &&
+ http->stream.next_in > http->dbuffer)
+ memmove(http->dbuffer, http->stream.next_in, http->stream.avail_in);
+
+ http->stream.next_in = http->dbuffer;
+
+ DEBUG_printf(("1httpRead2: Reading up to %d more bytes of data into "
+ "decompression buffer.", (int)buflen));
+
+ if (http->data_remaining > 0)
+ {
+ if (buflen > http->data_remaining)
+ buflen = http->data_remaining;
+
+ bytes = http_read_buffered(http,
+ (char *)http->dbuffer +
+ http->stream.avail_in, buflen);
+ }
+ else if (http->data_encoding == HTTP_ENCODING_CHUNKED)
+ bytes = http_read_chunk(http,
+ (char *)http->dbuffer +
+ http->stream.avail_in, buflen);
+ else
+ bytes = 0;
+
+ if (bytes < 0)
+ return (bytes);
+ else if (bytes == 0)
+ break;
+
+ http->data_remaining -= bytes;
+ http->stream.avail_in += bytes;
+ }
+ else
+ return (0);
+ }
}
- else
- http->used = 0;
-
- /*
- * Adjust remaining bytes since chunk/content lengths are compressed while
- * CUPS HTTP APIs return uncompressed sizes...
- */
-
- http->data_remaining += bytes - comp_bytes;
+ while (bytes == 0);
}
else
#endif /* HAVE_LIBZ */
- if (http->used > 0)
+ if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODING_CHUNKED)
{
- if (length > (size_t)http->used)
- length = (size_t)http->used;
-
- bytes = (ssize_t)length;
-
- DEBUG_printf(("2httpRead2: grabbing %d bytes from input buffer...",
- (int)bytes));
-
- memcpy(buffer, http->buffer, length);
- http->used -= (int)length;
-
- if (http->used > 0)
- memmove(http->buffer, http->buffer + length, http->used);
+ if ((bytes = http_read_chunk(http, buffer, length)) > 0)
+ http->data_remaining -= bytes;
}
-#ifdef HAVE_SSL
- else if (http->tls)
+ else if (http->data_remaining <= 0)
{
- if (!http->blocking)
- {
- while (!httpWait(http, http->wait_value))
- {
- if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
- continue;
-
- return (0);
- }
- }
+ /*
+ * No more data to read...
+ */
- while ((bytes = (ssize_t)http_read_ssl(http, buffer, (int)length)) < 0)
- {
-#ifdef WIN32
- if (WSAGetLastError() == WSAEWOULDBLOCK)
- {
- if (!http->timeout_cb || !(*http->timeout_cb)(http, http->timeout_data))
- break;
- }
- else if (WSAGetLastError() != WSAEINTR)
- break;
-#else
- if (errno == EWOULDBLOCK || errno == EAGAIN)
- {
- if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
- break;
- else if (!http->timeout_cb && errno != EAGAIN)
- break;
- }
- else if (errno != EINTR)
- break;
-#endif /* WIN32 */
- }
+ return (0);
}
-#endif /* HAVE_SSL */
else
{
- if (!http->blocking)
- {
- while (!httpWait(http, http->wait_value))
- {
- if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
- continue;
-
- return (0);
- }
- }
-
- DEBUG_printf(("2httpRead2: reading " CUPS_LLFMT " bytes from socket...",
- CUPS_LLCAST length));
-
-#ifdef WIN32
- while ((bytes = (ssize_t)recv(http->fd, buffer, (int)length, 0)) < 0)
- {
- if (WSAGetLastError() == WSAEWOULDBLOCK)
- {
- if (!http->timeout_cb || !(*http->timeout_cb)(http, http->timeout_data))
- break;
- }
- else if (WSAGetLastError() != WSAEINTR)
- break;
- }
-#else
- while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
- {
- if (errno == EWOULDBLOCK || errno == EAGAIN)
- {
- if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
- break;
- else if (!http->timeout_cb && errno != EAGAIN)
- break;
- }
- else if (errno != EINTR)
- break;
- }
-#endif /* WIN32 */
-
- DEBUG_printf(("2httpRead2: read " CUPS_LLFMT " bytes from socket...",
- CUPS_LLCAST bytes));
-#ifdef DEBUG
- http_debug_hex("httpRead2", buffer, (int)bytes);
-#endif /* DEBUG */
- }
+ DEBUG_printf(("1httpRead2: Reading up to %d bytes into buffer.",
+ (int)length));
- if (bytes > 0)
- {
- http->data_remaining -= bytes;
+ if (length > http->data_remaining)
+ length = http->data_remaining;
- if (http->data_remaining <= INT_MAX)
- http->_data_remaining = (int)http->data_remaining;
- else
- http->_data_remaining = INT_MAX;
- }
- else if (bytes < 0)
- {
-#ifdef WIN32
- if (WSAGetLastError() == WSAEINTR)
- bytes = 0;
- else
- http->error = WSAGetLastError();
-#else
- if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
- bytes = 0;
- else
- http->error = errno;
-#endif /* WIN32 */
- }
- else
- {
- http->error = EPIPE;
- return (0);
+ if ((bytes = http_read_buffered(http, buffer, length)) > 0)
+ http->data_remaining -= bytes;
}
- if (http->data_remaining <= 0)
+ if (
+#ifdef HAVE_LIBZ
+ (http->coding == _HTTP_CODING_IDENTITY || http->stream.avail_in == 0) &&
+#endif /* HAVE_LIBZ */
+ ((http->data_remaining <= 0 &&
+ http->data_encoding == HTTP_ENCODING_LENGTH) ||
+ (http->data_encoding == HTTP_ENCODING_CHUNKED && bytes == 0)))
{
- if (http->data_encoding == HTTP_ENCODING_CHUNKED)
- {
- DEBUG_puts("1httpRead2: Reading trailing line for chunk.");
- httpGets(len, sizeof(len), http);
- }
- else
- {
#ifdef HAVE_LIBZ
- if (http->coding)
- http_content_coding_finish(http);
+ if (http->coding)
+ http_content_coding_finish(http);
#endif /* HAVE_LIBZ */
- if (http->state == HTTP_STATE_POST_RECV)
- http->state ++;
- else
- http->state = HTTP_STATE_WAITING;
+ if (http->state == HTTP_STATE_POST_RECV)
+ http->state ++;
+ else
+ http->state = HTTP_STATE_WAITING;
- DEBUG_printf(("1httpRead2: End of content, set state to %s.",
- http_states[http->state + 1]));
- }
+ DEBUG_printf(("1httpRead2: End of content, set state to %s.",
+ http_states[http->state + 1]));
}
return (bytes);
@@ -3809,6 +3599,14 @@ httpWait(http_t *http, /* I - Connection to server */
return (1);
}
+#ifdef HAVE_LIBZ
+ if (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in > 0)
+ {
+ DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
+ return (1);
+ }
+#endif /* HAVE_LIBZ */
+
/*
* Flush pending data, if any...
*/
@@ -4475,6 +4273,8 @@ http_content_coding_finish(
case _HTTP_CODING_INFLATE :
case _HTTP_CODING_GUNZIP :
inflateEnd(&(http->stream));
+ free(http->dbuffer);
+ http->dbuffer = NULL;
break;
default :
@@ -4563,12 +4363,26 @@ http_content_coding_start(
case _HTTP_CODING_INFLATE :
case _HTTP_CODING_GUNZIP :
- if ((zerr = inflateInit2(&(http->stream), 32 + 15)) < Z_OK)
+ if ((http->dbuffer = malloc(HTTP_MAX_BUFFER)) == NULL)
{
http->status = HTTP_ERROR;
- http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
+ http->error = errno;
return;
}
+
+ if ((zerr = inflateInit2(&(http->stream),
+ coding == _HTTP_CODING_INFLATE ? 15 : 31))
+ < Z_OK)
+ {
+ free(http->dbuffer);
+ http->dbuffer = NULL;
+ http->status = HTTP_ERROR;
+ http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
+ return;
+ }
+
+ http->stream.avail_in = 0;
+ http->stream.next_in = http->dbuffer;
break;
default :
@@ -4658,6 +4472,231 @@ http_field(const char *name) /* I - String name */
}
+/*
+ * 'http_read()' - Read a buffer from a HTTP connection.
+ *
+ * This function does the low-level read from the socket, retrying and timing
+ * out as needed.
+ */
+
+static ssize_t /* O - Number of bytes read or -1 on error */
+http_read(http_t *http, /* I - Connection to server */
+ char *buffer, /* I - Buffer */
+ size_t length) /* I - Maximum bytes to read */
+{
+ ssize_t bytes; /* Bytes read */
+
+
+ DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
+ buffer, CUPS_LLCAST length));
+
+ if (!http->blocking)
+ {
+ while (!httpWait(http, http->wait_value))
+ {
+ if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
+ continue;
+
+ DEBUG_puts("2http_read: Timeout.");
+ return (0);
+ }
+ }
+
+ DEBUG_printf(("2http_read: Reading %d bytes into buffer.", (int)length));
+
+ do
+ {
+#ifdef HAVE_SSL
+ if (http->tls)
+ bytes = http_read_ssl(http, buffer, length);
+ else
+#endif /* HAVE_SSL */
+ bytes = recv(http->fd, buffer, length, 0);
+
+ if (bytes < 0)
+ {
+#ifdef WIN32
+ if (WSAGetLastError() != WSAEINTR)
+ {
+ http->error = WSAGetLastError();
+ return (-1);
+ }
+ else if (WSAGetLastError() == WSAEWOULDBLOCK)
+ {
+ if (!http->timeout_cb ||
+ !(*http->timeout_cb)(http, http->timeout_data))
+ {
+ http->error = WSAEWOULDBLOCK;
+ return (-1);
+ }
+ }
+#else
+ DEBUG_printf(("2http_read: %s", strerror(errno)));
+
+ if (errno == EWOULDBLOCK || errno == EAGAIN)
+ {
+ if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
+ {
+ http->error = errno;
+ return (-1);
+ }
+ else if (!http->timeout_cb && errno != EAGAIN)
+ {
+ http->error = errno;
+ return (-1);
+ }
+ }
+ else if (errno != EINTR)
+ {
+ http->error = errno;
+ return (-1);
+ }
+#endif /* WIN32 */
+ }
+ }
+ while (bytes < 0);
+
+ DEBUG_printf(("2http_read: Read " CUPS_LLFMT " bytes into buffer.",
+ CUPS_LLCAST bytes));
+#ifdef DEBUG
+ if (bytes > 0)
+ http_debug_hex("http_read", http->buffer, (int)bytes);
+#endif /* DEBUG */
+
+ if (bytes < 0)
+ {
+#ifdef WIN32
+ if (WSAGetLastError() == WSAEINTR)
+ bytes = 0;
+ else
+ http->error = WSAGetLastError();
+#else
+ if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
+ bytes = 0;
+ else
+ http->error = errno;
+#endif /* WIN32 */
+ }
+ else if (bytes == 0)
+ {
+ http->error = EPIPE;
+ return (0);
+ }
+
+ return (bytes);
+}
+
+
+/*
+ * 'http_read_buffered()' - Do a buffered read from a HTTP connection.
+ *
+ * This function reads data from the HTTP buffer or from the socket, as needed.
+ */
+
+static ssize_t /* O - Number of bytes read or -1 on error */
+http_read_buffered(http_t *http, /* I - Connection to server */
+ char *buffer, /* I - Buffer */
+ size_t length) /* I - Maximum bytes to read */
+{
+ ssize_t bytes; /* Bytes read */
+
+
+ DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT
+ ") used=%d",
+ http, buffer, CUPS_LLCAST length, http->used));
+
+ if (http->used > 0)
+ {
+ if (length > (size_t)http->used)
+ bytes = (size_t)http->used;
+ else
+ bytes = length;
+
+ DEBUG_printf(("2http_read: Grabbing %d bytes from input buffer.",
+ (int)bytes));
+
+ memcpy(buffer, http->buffer, bytes);
+ http->used -= (int)bytes;
+
+ if (http->used > 0)
+ memmove(http->buffer, http->buffer + bytes, http->used);
+ }
+ else
+ bytes = http_read(http, buffer, length);
+
+ return (bytes);
+}
+
+
+/*
+ * 'http_read_chunk()' - Read a chunk from a HTTP connection.
+ *
+ * This function reads and validates the chunk length, then does a buffered read
+ * returning the number of bytes placed in the buffer.
+ */
+
+static ssize_t /* O - Number of bytes read or -1 on error */
+http_read_chunk(http_t *http, /* I - Connection to server */
+ char *buffer, /* I - Buffer */
+ size_t length) /* I - Maximum bytes to read */
+{
+ DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
+ http, buffer, CUPS_LLCAST length));
+
+ if (http->data_remaining <= 0)
+ {
+ char len[32]; /* Length string */
+
+ if (!httpGets(len, sizeof(len), http))
+ {
+ DEBUG_puts("1http_read_chunk: Could not get chunk length.");
+ return (0);
+ }
+
+ if (!len[0])
+ {
+ DEBUG_puts("1http_read_chunk: Blank chunk length, trying again...");
+ if (!httpGets(len, sizeof(len), http))
+ {
+ DEBUG_puts("1http_read_chunk: Could not get chunk length.");
+ return (0);
+ }
+ }
+
+ http->data_remaining = strtoll(len, NULL, 16);
+
+ if (http->data_remaining < 0)
+ {
+ DEBUG_printf(("1http_read_chunk: Negative chunk length \"%s\" ("
+ CUPS_LLFMT ")", len, CUPS_LLCAST http->data_remaining));
+ return (0);
+ }
+
+ DEBUG_printf(("2http_read_chunk: Got chunk length \"%s\" (" CUPS_LLFMT ")",
+ len, CUPS_LLCAST http->data_remaining));
+
+ if (http->data_remaining == 0)
+ {
+ /*
+ * 0-length chunk, grab trailing blank line...
+ */
+
+ httpGets(len, sizeof(len), http);
+ }
+ }
+
+ DEBUG_printf(("2http_read_chunk: data_remaining=" CUPS_LLFMT,
+ CUPS_LLCAST http->data_remaining));
+
+ if (http->data_remaining <= 0)
+ return (0);
+ else if (length > (size_t)http->data_remaining)
+ length = (size_t)http->data_remaining;
+
+ return (http_read_buffered(http, buffer, length));
+}
+
+
#ifdef HAVE_SSL
/*
* 'http_read_ssl()' - Read from a SSL/TLS connection.
@@ -5124,8 +5163,6 @@ http_set_wait(http_t *http) /* I - Connection to server */
static int /* O - 0 on success, -1 on failure */
http_setup_ssl(http_t *http) /* I - Connection to server */
{
- _cups_globals_t *cg = _cupsGlobals();
- /* Pointer to library globals */
char hostname[256], /* Hostname */
*hostptr; /* Pointer into hostname */
@@ -5138,6 +5175,8 @@ http_setup_ssl(http_t *http) /* I - Connection to server */
gnutls_certificate_client_credentials *credentials;
/* TLS credentials */
# elif defined(HAVE_CDSASSL)
+ _cups_globals_t *cg = _cupsGlobals();
+ /* Pointer to library globals */
OSStatus error; /* Error code */
const char *message = NULL;/* Error message */
cups_array_t *credentials; /* Credentials array */
@@ -5667,17 +5706,17 @@ http_upgrade(http_t *http) /* I - Connection to server */
* 'http_write()' - Write a buffer to a HTTP connection.
*/
-static int /* O - Number of bytes written */
+static ssize_t /* O - Number of bytes written */
http_write(http_t *http, /* I - Connection to server */
const char *buffer, /* I - Buffer for data */
- int length) /* I - Number of bytes to write */
+ size_t length) /* I - Number of bytes to write */
{
- int tbytes, /* Total bytes sent */
- bytes; /* Bytes sent */
+ ssize_t tbytes, /* Total bytes sent */
+ bytes; /* Bytes sent */
- DEBUG_printf(("2http_write(http=%p, buffer=%p, length=%d)", http, buffer,
- length));
+ DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
+ buffer, CUPS_LLCAST length));
http->error = 0;
tbytes = 0;
@@ -5749,8 +5788,8 @@ http_write(http_t *http, /* I - Connection to server */
#endif /* HAVE_SSL */
bytes = send(http->fd, buffer, length, 0);
- DEBUG_printf(("3http_write: Write of %d bytes returned %d.", (int)length,
- (int)bytes));
+ DEBUG_printf(("3http_write: Write of " CUPS_LLFMT " bytes returned "
+ CUPS_LLFMT ".", CUPS_LLCAST length, CUPS_LLCAST bytes));
if (bytes < 0)
{
@@ -5805,7 +5844,7 @@ http_write(http_t *http, /* I - Connection to server */
http_debug_hex("http_write", buffer - tbytes, tbytes);
#endif /* DEBUG */
- DEBUG_printf(("3http_write: Returning %d.", tbytes));
+ DEBUG_printf(("3http_write: Returning " CUPS_LLFMT ".", CUPS_LLCAST tbytes));
return (tbytes);
}
@@ -5815,38 +5854,38 @@ http_write(http_t *http, /* I - Connection to server */
* 'http_write_chunk()' - Write a chunked buffer.
*/
-static int /* O - Number bytes written */
+static ssize_t /* O - Number bytes written */
http_write_chunk(http_t *http, /* I - Connection to server */
const char *buffer, /* I - Buffer to write */
- int length) /* I - Length of buffer */
+ size_t length) /* I - Length of buffer */
{
- char header[255]; /* Chunk header */
- int bytes; /* Bytes written */
+ char header[16]; /* Chunk header */
+ ssize_t bytes; /* Bytes written */
- DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=%d)",
- http, buffer, length));
+ DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
+ http, buffer, CUPS_LLCAST length));
/*
* Write the chunk header, data, and trailer.
*/
- sprintf(header, "%x\r\n", length);
- if (http_write(http, header, (int)strlen(header)) < 0)
+ snprintf(header, sizeof(header), "%x\r\n", (unsigned)length);
+ if (http_write(http, header, strlen(header)) < 0)
{
- DEBUG_puts("8http_write_chunk: http_write of length failed!");
+ DEBUG_puts("8http_write_chunk: http_write of length failed.");
return (-1);
}
if ((bytes = http_write(http, buffer, length)) < 0)
{
- DEBUG_puts("8http_write_chunk: http_write of buffer failed!");
+ DEBUG_puts("8http_write_chunk: http_write of buffer failed.");
return (-1);
}
if (http_write(http, "\r\n", 2) < 0)
{
- DEBUG_puts("8http_write_chunk: http_write of CR LF failed!");
+ DEBUG_puts("8http_write_chunk: http_write of CR LF failed.");
return (-1);
}
diff --git a/cups/http.h b/cups/http.h
index de782aaa3..345bf27f9 100644
--- a/cups/http.h
+++ b/cups/http.h
@@ -591,6 +591,10 @@ extern http_addrlist_t *httpAddrCopyList(http_addrlist_t *src) _CUPS_API_1_7;
extern int httpAddrListen(http_addr_t *addr, int port)
_CUPS_API_1_7;
extern int httpAddrPort(http_addr_t *addr) _CUPS_API_1_7;
+extern char *httpAssembleUUID(const char *server, int port,
+ const char *name, int number,
+ char *buffer, size_t bufsize)
+ _CUPS_API_1_7;
extern http_t *httpConnect2(const char *host, int port,
http_addrlist_t *addrlist,
int family, http_encryption_t encryption,
diff --git a/cups/ipp-support.c b/cups/ipp-support.c
index dfe610352..28abbba00 100644
--- a/cups/ipp-support.c
+++ b/cups/ipp-support.c
@@ -777,8 +777,8 @@ ippEnumString(const char *attrname, /* I - Attribute name */
if (!strcmp(attrname, "document-state") &&
enumvalue >= 3 &&
- enumvalue <= (3 + (int)(sizeof(ipp_document_states) /
- sizeof(ipp_document_states[0]))))
+ enumvalue < (3 + (int)(sizeof(ipp_document_states) /
+ sizeof(ipp_document_states[0]))))
return (ipp_document_states[enumvalue - 3]);
else if (!strcmp(attrname, "finishings") ||
!strcmp(attrname, "finishings-actual") ||
@@ -787,8 +787,8 @@ ippEnumString(const char *attrname, /* I - Attribute name */
!strcmp(attrname, "finishings-supported"))
{
if (enumvalue >= 3 &&
- enumvalue <= (3 + (int)(sizeof(ipp_finishings) /
- sizeof(ipp_finishings[0]))))
+ enumvalue < (3 + (int)(sizeof(ipp_finishings) /
+ sizeof(ipp_finishings[0]))))
return (ipp_finishings[enumvalue - 3]);
else if (enumvalue >= 0x40000000 &&
enumvalue <= (0x40000000 + (int)(sizeof(ipp_finishings_vendor) /
@@ -798,8 +798,8 @@ ippEnumString(const char *attrname, /* I - Attribute name */
else if ((!strcmp(attrname, "job-collation-type") ||
!strcmp(attrname, "job-collation-type-actual")) &&
enumvalue >= 3 &&
- enumvalue <= (3 + (int)(sizeof(ipp_job_collation_types) /
- sizeof(ipp_job_collation_types[0]))))
+ enumvalue < (3 + (int)(sizeof(ipp_job_collation_types) /
+ sizeof(ipp_job_collation_types[0]))))
return (ipp_job_collation_types[enumvalue - 3]);
else if (!strcmp(attrname, "job-state") &&
enumvalue >= IPP_JOB_PENDING && enumvalue <= IPP_JOB_COMPLETED)
@@ -811,16 +811,16 @@ ippEnumString(const char *attrname, /* I - Attribute name */
!strcmp(attrname, "orientation-requested-default") ||
!strcmp(attrname, "orientation-requested-supported")) &&
enumvalue >= 3 &&
- enumvalue <= (3 + (int)(sizeof(ipp_orientation_requesteds) /
- sizeof(ipp_orientation_requesteds[0]))))
+ enumvalue < (3 + (int)(sizeof(ipp_orientation_requesteds) /
+ sizeof(ipp_orientation_requesteds[0]))))
return (ipp_orientation_requesteds[enumvalue - 3]);
else if ((!strcmp(attrname, "print-quality") ||
!strcmp(attrname, "print-quality-actual") ||
!strcmp(attrname, "print-quality-default") ||
!strcmp(attrname, "print-quality-supported")) &&
enumvalue >= 3 &&
- enumvalue <= (3 + (int)(sizeof(ipp_print_qualities) /
- sizeof(ipp_print_qualities[0]))))
+ enumvalue < (3 + (int)(sizeof(ipp_print_qualities) /
+ sizeof(ipp_print_qualities[0]))))
return (ipp_print_qualities[enumvalue - 3]);
else if (!strcmp(attrname, "printer-state") &&
enumvalue >= IPP_PRINTER_IDLE && enumvalue <= IPP_PRINTER_STOPPED)
diff --git a/cups/ipp.c b/cups/ipp.c
index 76ee409d3..28b8961d7 100644
--- a/cups/ipp.c
+++ b/cups/ipp.c
@@ -3239,6 +3239,13 @@ ippReadIO(void *src, /* I - Data source */
ipp->prev = ipp->current;
attr = ipp->current = ipp_add_attr(ipp, NULL, ipp->curtag, IPP_TAG_ZERO, 1);
+ if (!attr)
+ {
+ _cupsSetHTTPError(HTTP_ERROR);
+ DEBUG_puts("1ippReadIO: unable to allocate attribute.");
+ _cupsBufferRelease((char *)buffer);
+ return (IPP_ERROR);
+ }
DEBUG_printf(("2ippReadIO: membername, ipp->current=%p, ipp->prev=%p",
ipp->current, ipp->prev));
@@ -6364,6 +6371,7 @@ ipp_free_values(ipp_attribute_t *attr, /* I - Attribute to free values from */
_cupsStrFree(attr->values[0].string.language);
attr->values[0].string.language = NULL;
}
+ /* Fall through to other string values */
case IPP_TAG_TEXT :
case IPP_TAG_NAME :
diff --git a/cups/request.c b/cups/request.c
index 01b8764ef..c1fbb5a04 100644
--- a/cups/request.c
+++ b/cups/request.c
@@ -1007,6 +1007,25 @@ _cupsConnect(void)
httpClose(cg->http);
cg->http = NULL;
}
+ else
+ {
+ /*
+ * Same server, see if the connection is still established...
+ */
+
+ char ch; /* Connection check byte */
+
+ if (recv(cg->http->fd, &ch, 1, MSG_PEEK | MSG_DONTWAIT) < 0 &&
+ errno != EWOULDBLOCK)
+ {
+ /*
+ * Nope, close the connection...
+ */
+
+ httpClose(cg->http);
+ cg->http = NULL;
+ }
+ }
}
/*
diff --git a/cups/versioning.h b/cups/versioning.h
index 808a10c2e..a9aab7246 100644
--- a/cups/versioning.h
+++ b/cups/versioning.h
@@ -3,7 +3,7 @@
*
* API versioning definitions for CUPS.
*
- * Copyright 2007-2012 by Apple Inc.
+ * Copyright 2007-2013 by Apple Inc.
*
* These coded instructions, statements, and computer programs are the
* property of Apple Inc. and are protected by Federal copyright
@@ -19,10 +19,11 @@
/*
* This header defines several constants - _CUPS_DEPRECATED,
- * _CUPS_API_1_1, _CUPS_API_1_1_19, _CUPS_API_1_1_20, _CUPS_API_1_1_21,
- * _CUPS_API_1_2, _CUPS_API_1_3, _CUPS_API_1_4, _CUPS_API_1_5, _CUPS_API_1_6,
- * and _CUPS_API_1_7 - which add compiler-specific attributes that flag
- * functions that are deprecated or added in particular releases.
+ * _CUPS_DEPRECATED_MSG, _CUPS_INTERNAL_MSG, _CUPS_API_1_1, _CUPS_API_1_1_19,
+ * _CUPS_API_1_1_20, _CUPS_API_1_1_21, _CUPS_API_1_2, _CUPS_API_1_3,
+ * _CUPS_API_1_4, _CUPS_API_1_5, _CUPS_API_1_6, and _CUPS_API_1_7 - which add
+ * compiler-specific attributes that flag functions that are deprecated, added
+ * in particular releases, or internal to CUPS.
*
* On OS X, the _CUPS_API_* constants are defined based on the values of
* the MAC_OS_X_VERSION_MIN_ALLOWED and MAC_OS_X_VERSION_MAX_ALLOWED constants
@@ -74,28 +75,66 @@
# endif /* __APPLE__ && !_CUPS_SOURCE */
/*
- * With GCC 3.0 and higher, we can mark old APIs "deprecated" so you get
- * a warning at compile-time.
+ * With GCC and Clang we can mark old APIs as "deprecated" or "unavailable" with
+ * messages so you get warnings/errors are compile-time...
*/
-# if defined(__GNUC__) && __GNUC__ > 2
-# 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 _CUPS_DEPRECATED __attribute__ ((deprecated))
-# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((deprecated(m)))
-# else
-# define _CUPS_DEPRECATED
-# define _CUPS_DEPRECATED_MSG(m)
-# endif /* !_CUPS_SOURCE || _CUPS_NO_DEPRECATED */
-# else
+# ifdef __has_extension /* Clang */
+# define _CUPS_HAS_DEPRECATED
+# if __has_extension(attribute_deprecated_with_message)
+# define _CUPS_HAS_DEPRECATED_WITH_MESSAGE
+# endif
+# if __has_extension(attribute_unavailable_with_message)
+# define _CUPS_HAS_UNAVAILABLE_WITH_MESSAGE
+# endif
+# elif defined(__GNUC__) /* GCC and compatible */
+# if __GNUC__ >= 3 /* GCC 3.0 or higher */
+# define _CUPS_HAS_DEPRECATED
+# endif /* __GNUC__ >= 3 */
+# if __GNUC__ >= 5 /* GCC 5.x */
+# define _CUPS_HAS_DEPRECATED_WITH_MESSAGE
+# elif __GNUC__ == 4 && __GNUC_MINOR__ >= 5
+ /* GCC 4.5 or higher */
+# define _CUPS_HAS_DEPRECATED_WITH_MESSAGE
+# endif /* __GNUC__ >= 5 */
+# endif /* __has_extension */
+
+# if !defined(_CUPS_HAS_DEPRECATED) || (defined(_CUPS_SOURCE) && !defined(_CUPS_NO_DEPRECATED))
+ /*
+ * Don't mark functions deprecated if the compiler doesn't support it
+ * or we are building CUPS source that doesn't care.
+ */
# define _CUPS_DEPRECATED
# define _CUPS_DEPRECATED_MSG(m)
-# endif /* __GNUC__ && __GNUC__ > 2 */
+# define _CUPS_INTERNAL_MSG(m)
+# elif defined(_CUPS_HAS_UNAVAILABLE_WITH_MESSAGE) && defined(_CUPS_NO_DEPRECATED)
+ /*
+ * Compiler supports the unsupported attribute, so use it when the code
+ * wants to exclude the use of deprecated API.
+ */
+# define _CUPS_DEPRECATED __attribute__ ((unavailable))
+# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((unavailable(m)))
+# define _CUPS_INTERNAL_MSG(m) __attribute__ ((unavailable(m)))
+# else
+ /*
+ * Compiler supports the deprecated attribute, so use it.
+ */
+# define _CUPS_DEPRECATED __attribute__ ((deprecated))
+# ifdef _CUPS_HAS_DEPRECATED_WITH_MESSAGE
+# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((deprecated(m)))
+# else
+# define _CUPS_DEPRECATED_MSG(m) __attribute__ ((deprecated))
+# endif /* _CUPS_HAS_DEPRECATED_WITH_MESSAGE */
+# ifdef _CUPS_SOURCE
+# define _CUPS_INTERNAL_MSG(m)
+# elif defined(_CUPS_HAS_UNAVAILABLE_WITH_MESSAGE)
+# define _CUPS_INTERNAL_MSG(m) __attribute__ ((unavailable(m)))
+# elif defined(_CUPS_HAS_DEPRECATED_WITH_MESSAGE)
+# define _CUPS_INTERNAL_MSG(m) __attribute__ ((deprecated(m)))
+# else
+# define _CUPS_INTERNAL_MSG(m) __attribute__ ((deprecated))
+# endif /* _CUPS_SOURCE */
+# endif /* !_CUPS_HAS_DEPRECATED || (_CUPS_SOURCE && !_CUPS_NO_DEPRECATED) */
# ifndef __GNUC__
# define __attribute__(x)