X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=cups%2Fhttp.c;h=ff8f6918f8bebe403c7706bb4d0553717d4cd201;hb=HEAD;hp=b3abbe73e0d02e9951599dfc3a5bcd72a5053692;hpb=f689a8a955f1829f46a74863062be0c8a30ca524;p=thirdparty%2Fcups.git diff --git a/cups/http.c b/cups/http.c index b3abbe73e..43ace18f4 100644 --- a/cups/http.c +++ b/cups/http.c @@ -1,19 +1,14 @@ /* * HTTP routines for CUPS. * - * Copyright 2007-2015 by Apple Inc. - * Copyright 1997-2007 by Easy Software Products, all rights reserved. + * Copyright © 2007-2021 by Apple Inc. + * Copyright © 1997-2007 by Easy Software Products, all rights reserved. * * This file contains Kerberos support code, copyright 2006 by * Jelmer Vernooij. * - * These coded instructions, statements, and computer programs are the - * property of Apple Inc. and are protected by Federal copyright - * law. Distribution and use rights are outlined in the file "LICENSE.txt" - * 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/". - * - * This file is subject to the Apple OS-Developed Software exception. + * Licensed under Apache License v2.0. See the file "LICENSE" for more + * information. */ /* @@ -21,24 +16,29 @@ */ #include "cups-private.h" +#include "debug-internal.h" #include #include -#ifdef WIN32 +#ifdef _WIN32 # include #else # include # include # include -#endif /* WIN32 */ +#endif /* _WIN32 */ #ifdef HAVE_POLL # include #endif /* HAVE_POLL */ +# ifdef HAVE_LIBZ +# include +# endif /* HAVE_LIBZ */ /* * Local functions... */ +static void http_add_field(http_t *http, http_field_t field, const char *value, int append); #ifdef HAVE_LIBZ static void http_content_coding_finish(http_t *http); static void http_content_coding_start(http_t *http, @@ -105,7 +105,8 @@ static const char * const http_fields[] = "WWW-Authenticate", "Accept-Encoding", "Allow", - "Server" + "Server", + "Authentication-Info" }; @@ -287,11 +288,22 @@ httpClearCookie(http_t *http) /* I - HTTP connection */ void httpClearFields(http_t *http) /* I - HTTP connection */ { + http_field_t field; /* Current field */ + + DEBUG_printf(("httpClearFields(http=%p)", (void *)http)); if (http) { - memset(http->fields, 0, sizeof(http->fields)); + memset(http->_fields, 0, sizeof(http->fields)); + + for (field = HTTP_FIELD_ACCEPT_LANGUAGE; field < HTTP_FIELD_MAX; field ++) + { + if (http->fields[field] && http->fields[field] != http->_fields[field]) + free(http->fields[field]); + + http->fields[field] = NULL; + } if (http->mode == _HTTP_MODE_CLIENT) { @@ -301,30 +313,6 @@ httpClearFields(http_t *http) /* I - HTTP connection */ httpSetField(http, HTTP_FIELD_HOST, http->hostname); } - if (http->field_authorization) - { - free(http->field_authorization); - http->field_authorization = NULL; - } - - if (http->accept_encoding) - { - _cupsStrFree(http->accept_encoding); - http->accept_encoding = NULL; - } - - if (http->allow) - { - _cupsStrFree(http->allow); - http->allow = NULL; - } - - if (http->server) - { - _cupsStrFree(http->server); - http->server = NULL; - } - http->expect = (http_status_t)0; } } @@ -417,7 +405,7 @@ httpCompareCredentials( * * This function is deprecated - use @link httpConnect2@ instead. * - * @deprecated@ + * @deprecated@ @exclude all@ */ http_t * /* O - New HTTP connection */ @@ -439,7 +427,7 @@ http_t * /* O - New HTTP connection */ httpConnect2( const char *host, /* I - Host to connect to */ int port, /* I - Port number */ - http_addrlist_t *addrlist, /* I - List of addresses or NULL to lookup */ + http_addrlist_t *addrlist, /* I - List of addresses or @code NULL@ to lookup */ int family, /* I - Address family to use or @code AF_UNSPEC@ for any */ http_encryption_t encryption, /* I - Type of encryption to use */ int blocking, /* I - 1 for blocking connection, 0 for non-blocking */ @@ -482,7 +470,7 @@ httpConnect2( * This function is now deprecated. Please use the @link httpConnect2@ function * instead. * - * @deprecated@ + * @deprecated@ @exclude all@ */ http_t * /* O - New HTTP connection */ @@ -609,7 +597,7 @@ httpFieldValue(const char *name) /* I - String name */ /* - * 'httpFlush()' - Flush data from a HTTP connection. + * 'httpFlush()' - Flush data read from a HTTP connection. */ void @@ -679,7 +667,7 @@ httpFlush(http_t *http) /* I - HTTP connection */ /* - * 'httpFlushWrite()' - Flush data in write buffer. + * 'httpFlushWrite()' - Flush data written to a HTTP connection. * * @since CUPS 1.2/macOS 10.5@ */ @@ -751,7 +739,7 @@ httpGet(http_t *http, /* I - HTTP connection */ /* * 'httpGetActivity()' - Get the most recent activity for a connection. * - * The return value is the UNIX time of the last read or write. + * The return value is the time in seconds of the last read or write. * * @since CUPS 2.0/OS 10.10@ */ @@ -766,10 +754,10 @@ httpGetActivity(http_t *http) /* I - HTTP connection */ /* * 'httpGetAuthString()' - Get the current authorization string. * - * The authorization string is set by cupsDoAuthentication() and - * httpSetAuthString(). Use httpGetAuthString() to retrieve the - * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION - * value. + * The authorization string is set by @link cupsDoAuthentication@ and + * @link httpSetAuthString@. Use @link httpGetAuthString@ to retrieve the + * string to use with @link httpSetField@ for the + * @code HTTP_FIELD_AUTHORIZATION@ value. * * @since CUPS 1.3/macOS 10.5@ */ @@ -815,7 +803,7 @@ const char * /* O - Content-Coding value or httpGetContentEncoding(http_t *http) /* I - HTTP connection */ { #ifdef HAVE_LIBZ - if (http && http->accept_encoding) + if (http && http->fields[HTTP_FIELD_ACCEPT_ENCODING]) { int i; /* Looping var */ char temp[HTTP_MAX_VALUE], /* Copy of Accepts-Encoding value */ @@ -831,7 +819,7 @@ httpGetContentEncoding(http_t *http) /* I - HTTP connection */ "x-gzip" }; - strlcpy(temp, http->accept_encoding, sizeof(temp)); + strlcpy(temp, http->fields[HTTP_FIELD_ACCEPT_ENCODING], sizeof(temp)); for (start = temp; *start; start = end) { @@ -891,7 +879,7 @@ httpGetContentEncoding(http_t *http) /* I - HTTP connection */ * @since CUPS 1.1.19/macOS 10.3@ */ -const char * /* O - Cookie data or NULL */ +const char * /* O - Cookie data or @code NULL@ */ httpGetCookie(http_t *http) /* I - HTTP connection */ { return (http ? http->cookie : NULL); @@ -957,32 +945,10 @@ httpGetField(http_t *http, /* I - HTTP connection */ { if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX) return (NULL); - - switch (field) - { - case HTTP_FIELD_ACCEPT_ENCODING : - return (http->accept_encoding); - - case HTTP_FIELD_ALLOW : - return (http->allow); - - case HTTP_FIELD_SERVER : - return (http->server); - - case HTTP_FIELD_AUTHORIZATION : - if (http->field_authorization) - { - /* - * Special case for WWW-Authenticate: as its contents can be - * longer than HTTP_MAX_VALUE... - */ - - return (http->field_authorization); - } - - default : - return (http->fields[field]); - } + else if (http->fields[field]) + return (http->fields[field]); + else + return (""); } @@ -1006,7 +972,7 @@ httpGetKeepAlive(http_t *http) /* I - HTTP connection */ * This function is deprecated and will not return lengths larger than * 2^31 - 1; use httpGetLength2() instead. * - * @deprecated@ + * @deprecated@ @exclude all@ */ int /* O - Content length */ @@ -1048,7 +1014,7 @@ httpGetLength2(http_t *http) /* I - HTTP connection */ if (!http) return (-1); - if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked")) + if (http->fields[HTTP_FIELD_TRANSFER_ENCODING] && !_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked")) { DEBUG_puts("4httpGetLength2: chunked request!"); remaining = 0; @@ -1063,7 +1029,7 @@ httpGetLength2(http_t *http) /* I - HTTP connection */ * after the transfer is complete... */ - if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0]) + if (!http->fields[HTTP_FIELD_CONTENT_LENGTH] || !http->fields[HTTP_FIELD_CONTENT_LENGTH][0]) { /* * Default content length is 0 for errors and certain types of operations, @@ -1150,7 +1116,7 @@ httpGetRemaining(http_t *http) /* I - HTTP connection */ * 'httpGets()' - Get a line of text from a HTTP connection. */ -char * /* O - Line or NULL */ +char * /* O - Line or @code NULL@ */ httpGets(char *line, /* I - Line to read into */ int length, /* I - Max length of buffer */ http_t *http) /* I - HTTP connection */ @@ -1183,11 +1149,11 @@ httpGets(char *line, /* I - Line to read into */ * Pre-load the buffer as needed... */ -#ifdef WIN32 +#ifdef _WIN32 WSASetLastError(0); #else errno = 0; -#endif /* WIN32 */ +#endif /* _WIN32 */ while (http->used == 0) { @@ -1201,11 +1167,11 @@ httpGets(char *line, /* I - Line to read into */ continue; DEBUG_puts("3httpGets: Timed out!"); -#ifdef WIN32 +#ifdef _WIN32 http->error = WSAETIMEDOUT; #else http->error = ETIMEDOUT; -#endif /* WIN32 */ +#endif /* _WIN32 */ return (NULL); } @@ -1219,7 +1185,7 @@ httpGets(char *line, /* I - Line to read into */ * Nope, can't get a line this time... */ -#ifdef WIN32 +#ifdef _WIN32 DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError())); if (WSAGetLastError() == WSAEINTR) @@ -1256,7 +1222,7 @@ httpGets(char *line, /* I - Line to read into */ http->error = errno; continue; } -#endif /* WIN32 */ +#endif /* _WIN32 */ return (NULL); } @@ -1346,10 +1312,10 @@ httpGetStatus(http_t *http) /* I - HTTP connection */ /* * 'httpGetSubField()' - Get a sub-field value. * - * @deprecated@ + * @deprecated@ @exclude all@ */ -char * /* O - Value or NULL */ +char * /* O - Value or @code NULL@ */ httpGetSubField(http_t *http, /* I - HTTP connection */ http_field_t field, /* I - Field index */ const char *name, /* I - Name of sub-field */ @@ -1365,7 +1331,7 @@ httpGetSubField(http_t *http, /* I - HTTP connection */ * @since CUPS 1.2/macOS 10.5@ */ -char * /* O - Value or NULL */ +char * /* O - Value or @code NULL@ */ httpGetSubField2(http_t *http, /* I - HTTP connection */ http_field_t field, /* I - Field index */ const char *name, /* I - Name of sub-field */ @@ -1379,8 +1345,11 @@ httpGetSubField2(http_t *http, /* I - HTTP connection */ DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, valuelen=%d)", (void *)http, field, name, (void *)value, valuelen)); + if (value) + *value = '\0'; + if (!http || !name || !value || valuelen < 2 || - field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX) + field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX || !http->fields[field]) return (NULL); end = value + valuelen - 1; @@ -1523,9 +1492,9 @@ void httpInitialize(void) { static int initialized = 0; /* Have we been called before? */ -#ifdef WIN32 +#ifdef _WIN32 WSADATA winsockdata; /* WinSock data */ -#endif /* WIN32 */ +#endif /* _WIN32 */ _cupsGlobalLock(); @@ -1535,7 +1504,7 @@ httpInitialize(void) return; } -#ifdef WIN32 +#ifdef _WIN32 WSAStartup(MAKEWORD(2,2), &winsockdata); #elif !defined(SO_NOSIGPIPE) @@ -1557,7 +1526,7 @@ httpInitialize(void) # else signal(SIGPIPE, SIG_IGN); # endif /* !SO_NOSIGPIPE */ -#endif /* WIN32 */ +#endif /* _WIN32 */ # ifdef HAVE_SSL _httpTLSInitialize(); @@ -1616,7 +1585,7 @@ httpOptions(http_t *http, /* I - HTTP connection */ * * This function copies available data from the given HTTP connection, reading * a buffer as needed. The data is still available for reading using - * @link httpRead@ or @link httpRead2@. + * @link httpRead2@. * * For non-blocking connections the usual timeouts apply. * @@ -1713,7 +1682,7 @@ httpPeek(http_t *http, /* I - HTTP connection */ #ifdef HAVE_LIBZ if (http->used == 0 && (http->coding == _HTTP_CODING_IDENTITY || - (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in == 0))) + (http->coding >= _HTTP_CODING_GUNZIP && ((z_stream *)http->stream)->avail_in == 0))) #else if (http->used == 0) #endif /* HAVE_LIBZ */ @@ -1762,16 +1731,16 @@ httpPeek(http_t *http, /* I - HTTP connection */ int zerr; /* Decompressor error */ z_stream stream; /* Copy of decompressor stream */ - if (http->used > 0 && http->stream.avail_in < HTTP_MAX_BUFFER) + if (http->used > 0 && ((z_stream *)http->stream)->avail_in < HTTP_MAX_BUFFER) { - size_t buflen = buflen = HTTP_MAX_BUFFER - http->stream.avail_in; + size_t buflen = HTTP_MAX_BUFFER - ((z_stream *)http->stream)->avail_in; /* Number of bytes to copy */ - if (http->stream.avail_in > 0 && - http->stream.next_in > http->sbuffer) - memmove(http->sbuffer, http->stream.next_in, http->stream.avail_in); + if (((z_stream *)http->stream)->avail_in > 0 && + ((z_stream *)http->stream)->next_in > http->sbuffer) + memmove(http->sbuffer, ((z_stream *)http->stream)->next_in, ((z_stream *)http->stream)->avail_in); - http->stream.next_in = http->sbuffer; + ((z_stream *)http->stream)->next_in = http->sbuffer; if (buflen > (size_t)http->data_remaining) buflen = (size_t)http->data_remaining; @@ -1782,8 +1751,8 @@ httpPeek(http_t *http, /* I - HTTP connection */ DEBUG_printf(("1httpPeek: Copying %d more bytes of data into " "decompression buffer.", (int)buflen)); - memcpy(http->sbuffer + http->stream.avail_in, http->buffer, buflen); - http->stream.avail_in += buflen; + memcpy(http->sbuffer + ((z_stream *)http->stream)->avail_in, http->buffer, buflen); + ((z_stream *)http->stream)->avail_in += buflen; http->used -= (int)buflen; http->data_remaining -= (off_t)buflen; @@ -1792,9 +1761,9 @@ httpPeek(http_t *http, /* I - HTTP connection */ } DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length, - (int)http->stream.avail_in)); + (int)((z_stream *)http->stream)->avail_in)); - if (inflateCopy(&stream, &(http->stream)) != Z_OK) + if (inflateCopy(&stream, (z_stream *)http->stream) != Z_OK) { DEBUG_puts("2httpPeek: Unable to copy decompressor stream."); http->error = ENOMEM; @@ -1811,14 +1780,14 @@ httpPeek(http_t *http, /* I - HTTP connection */ { DEBUG_printf(("2httpPeek: zerr=%d", zerr)); #ifdef DEBUG - http_debug_hex("2httpPeek", (char *)http->sbuffer, (int)http->stream.avail_in); + http_debug_hex("2httpPeek", (char *)http->sbuffer, (int)((z_stream *)http->stream)->avail_in); #endif /* DEBUG */ http->error = EIO; return (-1); } - bytes = (ssize_t)(length - http->stream.avail_out); + bytes = (ssize_t)(length - ((z_stream *)http->stream)->avail_out); # else DEBUG_puts("2httpPeek: No inflateCopy on this platform, httpPeek does not " @@ -1845,7 +1814,7 @@ httpPeek(http_t *http, /* I - HTTP connection */ if (bytes < 0) { -#ifdef WIN32 +#ifdef _WIN32 if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK) bytes = 0; else @@ -1855,7 +1824,7 @@ httpPeek(http_t *http, /* I - HTTP connection */ bytes = 0; else http->error = errno; -#endif /* WIN32 */ +#endif /* _WIN32 */ } else if (bytes == 0) { @@ -1891,7 +1860,7 @@ httpPrintf(http_t *http, /* I - HTTP connection */ ...) /* I - Additional args as needed */ { ssize_t bytes; /* Number of bytes to write */ - char buf[16384]; /* Buffer for formatted string */ + char buf[65536]; /* Buffer for formatted string */ va_list ap; /* Variable argument pointer */ @@ -1903,7 +1872,12 @@ httpPrintf(http_t *http, /* I - HTTP connection */ DEBUG_printf(("3httpPrintf: (" CUPS_LLFMT " bytes) %s", CUPS_LLCAST bytes, buf)); - if (http->data_encoding == HTTP_ENCODING_FIELDS) + if (bytes > (ssize_t)(sizeof(buf) - 1)) + { + http->error = ENOMEM; + return (-1); + } + else if (http->data_encoding == HTTP_ENCODING_FIELDS) return ((int)httpWrite2(http, buf, (size_t)bytes)); else { @@ -1939,7 +1913,7 @@ httpPut(http_t *http, /* I - HTTP connection */ * This function is deprecated. Use the httpRead2() function which can * read more than 2GB of data. * - * @deprecated@ + * @deprecated@ @exclude all@ */ int /* O - Number of bytes read */ @@ -1985,31 +1959,31 @@ httpRead2(http_t *http, /* I - HTTP connection */ { do { - if (http->stream.avail_in > 0) + if (((z_stream *)http->stream)->avail_in > 0) { int zerr; /* Decompressor error */ DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d", - (int)http->stream.avail_in, (int)length)); + (int)((z_stream *)http->stream)->avail_in, (int)length)); - http->stream.next_out = (Bytef *)buffer; - http->stream.avail_out = (uInt)length; + ((z_stream *)http->stream)->next_out = (Bytef *)buffer; + ((z_stream *)http->stream)->avail_out = (uInt)length; - if ((zerr = inflate(&(http->stream), Z_SYNC_FLUSH)) < Z_OK) + if ((zerr = inflate((z_stream *)http->stream, Z_SYNC_FLUSH)) < Z_OK) { DEBUG_printf(("2httpRead2: zerr=%d", zerr)); #ifdef DEBUG - http_debug_hex("2httpRead2", (char *)http->sbuffer, (int)http->stream.avail_in); + http_debug_hex("2httpRead2", (char *)http->sbuffer, (int)((z_stream *)http->stream)->avail_in); #endif /* DEBUG */ http->error = EIO; return (-1); } - bytes = (ssize_t)(length - http->stream.avail_out); + bytes = (ssize_t)(length - ((z_stream *)http->stream)->avail_out); DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d", - http->stream.avail_in, http->stream.avail_out, + ((z_stream *)http->stream)->avail_in, ((z_stream *)http->stream)->avail_out, (int)bytes)); } else @@ -2017,16 +1991,16 @@ httpRead2(http_t *http, /* I - HTTP connection */ if (bytes == 0) { - ssize_t buflen = HTTP_MAX_BUFFER - (ssize_t)http->stream.avail_in; + ssize_t buflen = HTTP_MAX_BUFFER - (ssize_t)((z_stream *)http->stream)->avail_in; /* Additional bytes for buffer */ if (buflen > 0) { - if (http->stream.avail_in > 0 && - http->stream.next_in > http->sbuffer) - memmove(http->sbuffer, http->stream.next_in, http->stream.avail_in); + if (((z_stream *)http->stream)->avail_in > 0 && + ((z_stream *)http->stream)->next_in > http->sbuffer) + memmove(http->sbuffer, ((z_stream *)http->stream)->next_in, ((z_stream *)http->stream)->avail_in); - http->stream.next_in = http->sbuffer; + ((z_stream *)http->stream)->next_in = http->sbuffer; DEBUG_printf(("1httpRead2: Reading up to %d more bytes of data into " "decompression buffer.", (int)buflen)); @@ -2036,10 +2010,10 @@ httpRead2(http_t *http, /* I - HTTP connection */ if (buflen > http->data_remaining) buflen = (ssize_t)http->data_remaining; - bytes = http_read_buffered(http, (char *)http->sbuffer + http->stream.avail_in, (size_t)buflen); + bytes = http_read_buffered(http, (char *)http->sbuffer + ((z_stream *)http->stream)->avail_in, (size_t)buflen); } else if (http->data_encoding == HTTP_ENCODING_CHUNKED) - bytes = http_read_chunk(http, (char *)http->sbuffer + http->stream.avail_in, (size_t)buflen); + bytes = http_read_chunk(http, (char *)http->sbuffer + ((z_stream *)http->stream)->avail_in, (size_t)buflen); else bytes = 0; @@ -2052,7 +2026,7 @@ httpRead2(http_t *http, /* I - HTTP connection */ "decompression buffer.", CUPS_LLCAST bytes)); http->data_remaining -= bytes; - http->stream.avail_in += (uInt)bytes; + ((z_stream *)http->stream)->avail_in += (uInt)bytes; if (http->data_remaining <= 0 && http->data_encoding == HTTP_ENCODING_CHUNKED) @@ -2131,7 +2105,7 @@ httpRead2(http_t *http, /* I - HTTP connection */ if ( #ifdef HAVE_LIBZ (http->coding == _HTTP_CODING_IDENTITY || - (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in == 0)) && + (http->coding >= _HTTP_CODING_GUNZIP && ((z_stream *)http->stream)->avail_in == 0)) && #endif /* HAVE_LIBZ */ ((http->data_remaining <= 0 && http->data_encoding == HTTP_ENCODING_LENGTH) || @@ -2326,7 +2300,7 @@ httpReadRequest(http_t *http, /* I - HTTP connection */ * This function is deprecated. Please use the @link httpReconnect2@ function * instead. * - * @deprecated@ + * @deprecated@ @exclude all@ */ int /* O - 0 on success, non-zero on failure */ @@ -2416,11 +2390,11 @@ httpReconnect2(http_t *http, /* I - HTTP connection */ * Unable to connect... */ -#ifdef WIN32 +#ifdef _WIN32 http->error = WSAGetLastError(); #else http->error = errno; -#endif /* WIN32 */ +#endif /* _WIN32 */ http->status = HTTP_STATUS_ERROR; DEBUG_printf(("1httpReconnect2: httpAddrConnect failed: %s", @@ -2447,6 +2421,7 @@ httpReconnect2(http_t *http, /* I - HTTP connection */ if (_httpTLSStart(http) != 0) { httpAddrClose(NULL, http->fd); + http->fd = -1; return (-1); } @@ -2467,9 +2442,10 @@ httpReconnect2(http_t *http, /* I - HTTP connection */ * 'httpSetAuthString()' - Set the current authorization string. * * This function just stores a copy of the current authorization string in - * the HTTP connection object. You must still call httpSetField() to set - * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(), - * httpHead(), httpOptions(), httpPost, or httpPut(). + * the HTTP connection object. You must still call @link httpSetField@ to set + * @code HTTP_FIELD_AUTHORIZATION@ prior to issuing a HTTP request using + * @link httpGet@, @link httpHead@, @link httpOptions@, @link httpPost@, or + * @link httpPut@. * * @since CUPS 1.3/macOS 10.5@ */ @@ -2587,36 +2563,13 @@ httpSetDefaultField(http_t *http, /* I - HTTP connection */ { DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")", (void *)http, field, http_fields[field], value)); - if (!http) + if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX) return; - switch (field) - { - case HTTP_FIELD_ACCEPT_ENCODING : - if (http->default_accept_encoding) - _cupsStrFree(http->default_accept_encoding); + if (http->default_fields[field]) + free(http->default_fields[field]); - 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; - } + http->default_fields[field] = value ? strdup(value) : NULL; } @@ -2652,111 +2605,10 @@ httpSetField(http_t *http, /* I - HTTP connection */ { DEBUG_printf(("httpSetField(http=%p, field=%d(%s), value=\"%s\")", (void *)http, field, http_fields[field], value)); - if (http == NULL || - field < HTTP_FIELD_ACCEPT_LANGUAGE || - field >= HTTP_FIELD_MAX || - value == NULL) + if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX || !value) return; - switch (field) - { - case HTTP_FIELD_ACCEPT_ENCODING : - if (http->accept_encoding) - _cupsStrFree(http->accept_encoding); - - http->accept_encoding = _cupsStrAlloc(value); - break; - - case HTTP_FIELD_ALLOW : - if (http->allow) - _cupsStrFree(http->allow); - - http->allow = _cupsStrAlloc(value); - break; - - case HTTP_FIELD_SERVER : - if (http->server) - _cupsStrFree(http->server); - - http->server = _cupsStrAlloc(value); - break; - - case HTTP_FIELD_WWW_AUTHENTICATE : - /* CUPS STR #4503 - don't override WWW-Authenticate for unknown auth schemes */ - if (http->fields[HTTP_FIELD_WWW_AUTHENTICATE][0] && - _cups_strncasecmp(value, "Basic ", 6) && - _cups_strncasecmp(value, "Digest ", 7) && - _cups_strncasecmp(value, "Negotiate ", 10)) - { - DEBUG_printf(("1httpSetField: Ignoring unknown auth scheme in \"%s\".", value)); - return; - } - - /* Fall through to copy */ - - default : - strlcpy(http->fields[field], value, HTTP_MAX_VALUE); - break; - } - - if (field == HTTP_FIELD_AUTHORIZATION) - { - /* - * Special case for Authorization: as its contents can be - * longer than HTTP_MAX_VALUE - */ - - if (http->field_authorization) - free(http->field_authorization); - - http->field_authorization = strdup(value); - } - else if (field == HTTP_FIELD_HOST) - { - /* - * Special-case for Host: as we don't want a trailing "." on the hostname and - * need to bracket IPv6 numeric addresses. - */ - - char *ptr = strchr(value, ':'); - - if (value[0] != '[' && ptr && strchr(ptr + 1, ':')) - { - /* - * Bracket IPv6 numeric addresses... - * - * This is slightly inefficient (basically copying twice), but is an edge - * case and not worth optimizing... - */ - - snprintf(http->fields[HTTP_FIELD_HOST], - sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value); - } - else - { - /* - * Check for a trailing dot on the hostname... - */ - - ptr = http->fields[HTTP_FIELD_HOST]; - - if (*ptr) - { - ptr += strlen(ptr) - 1; - - if (*ptr == '.') - *ptr = '\0'; - } - } - } -#ifdef HAVE_LIBZ - else if (field == HTTP_FIELD_CONTENT_ENCODING && - http->data_encoding != HTTP_ENCODING_FIELDS) - { - DEBUG_puts("1httpSetField: Calling http_content_coding_start."); - http_content_coding_start(http, value); - } -#endif /* HAVE_LIBZ */ + http_add_field(http, field, value, 0); } @@ -2793,15 +2645,17 @@ httpSetLength(http_t *http, /* I - HTTP connection */ if (!length) { - strlcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked", - HTTP_MAX_VALUE); - http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0'; + httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked"); + httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, ""); } else { - http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0'; - snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE, - CUPS_LLFMT, CUPS_LLCAST length); + char len[32]; /* Length string */ + + + snprintf(len, sizeof(len), CUPS_LLFMT, CUPS_LLCAST length); + httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, ""); + httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, len); } } @@ -2820,7 +2674,7 @@ httpSetTimeout( http_t *http, /* I - HTTP connection */ double timeout, /* I - Number of seconds for timeout, must be greater than 0 */ - http_timeout_cb_t cb, /* I - Callback function or NULL */ + http_timeout_cb_t cb, /* I - Callback function or @code NULL@ */ void *user_data) /* I - User data pointer */ { if (!http || timeout <= 0.0) @@ -2854,16 +2708,18 @@ httpShutdown(http_t *http) /* I - HTTP connection */ _httpTLSStop(http); #endif /* HAVE_SSL */ -#ifdef WIN32 +#ifdef _WIN32 shutdown(http->fd, SD_RECEIVE); /* Microsoft-ism... */ #else shutdown(http->fd, SHUT_RD); -#endif /* WIN32 */ +#endif /* _WIN32 */ } /* * 'httpTrace()' - Send an TRACE request to the server. + * + * @exclude all@ */ int /* O - Status of call (0 = success) */ @@ -2931,6 +2787,7 @@ _httpUpdate(http_t *http, /* I - HTTP connection */ if (_httpTLSStart(http) != 0) { httpAddrClose(NULL, http->fd); + http->fd = -1; *status = http->status = HTTP_STATUS_ERROR; return (0); @@ -3032,7 +2889,12 @@ _httpUpdate(http_t *http, /* I - HTTP connection */ httpSetCookie(http, value); } else if ((field = httpFieldValue(line)) != HTTP_FIELD_UNKNOWN) - httpSetField(http, field, value); + { + http_add_field(http, field, value, 1); + + if (field == HTTP_FIELD_AUTHENTICATION_INFO) + httpGetSubField2(http, HTTP_FIELD_AUTHENTICATION_INFO, "nextnonce", http->nextnonce, (int)sizeof(http->nextnonce)); + } #ifdef DEBUG else DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line)); @@ -3185,12 +3047,12 @@ _httpWait(http_t *http, /* I - HTTP connection */ DEBUG_printf(("6_httpWait: select() returned %d...", nfds)); } -# ifdef WIN32 +# ifdef _WIN32 while (nfds < 0 && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)); # else while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); -# endif /* WIN32 */ +# endif /* _WIN32 */ #endif /* HAVE_POLL */ DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds, @@ -3226,7 +3088,7 @@ httpWait(http_t *http, /* I - HTTP connection */ } #ifdef HAVE_LIBZ - if (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in > 0) + if (http->coding >= _HTTP_CODING_GUNZIP && ((z_stream *)http->stream)->avail_in > 0) { DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready."); return (1); @@ -3259,7 +3121,7 @@ httpWait(http_t *http, /* I - HTTP connection */ * This function is deprecated. Use the httpWrite2() function which can * write more than 2GB of data. * - * @deprecated@ + * @deprecated@ @exclude all@ */ int /* O - Number of bytes written */ @@ -3322,17 +3184,17 @@ httpWrite2(http_t *http, /* I - HTTP connection */ size_t slen; /* Bytes to write */ ssize_t sret; /* Bytes written */ - http->stream.next_in = (Bytef *)buffer; - http->stream.avail_in = (uInt)length; + ((z_stream *)http->stream)->next_in = (Bytef *)buffer; + ((z_stream *)http->stream)->avail_in = (uInt)length; - while (deflate(&(http->stream), Z_NO_FLUSH) == Z_OK) + while (deflate((z_stream *)http->stream, Z_NO_FLUSH) == Z_OK) { - DEBUG_printf(("1httpWrite2: avail_out=%d", http->stream.avail_out)); + DEBUG_printf(("1httpWrite2: avail_out=%d", ((z_stream *)http->stream)->avail_out)); - if (http->stream.avail_out > 0) + if (((z_stream *)http->stream)->avail_out > 0) continue; - slen = _HTTP_MAX_SBUFFER - http->stream.avail_out; + slen = _HTTP_MAX_SBUFFER - ((z_stream *)http->stream)->avail_out; DEBUG_printf(("1httpWrite2: Writing intermediate chunk, len=%d", (int)slen)); @@ -3349,8 +3211,8 @@ httpWrite2(http_t *http, /* I - HTTP connection */ return (-1); } - http->stream.next_out = (Bytef *)http->sbuffer; - http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER; + ((z_stream *)http->stream)->next_out = (Bytef *)http->sbuffer; + ((z_stream *)http->stream)->avail_out = (uInt)_HTTP_MAX_SBUFFER; } bytes = (ssize_t)length; @@ -3492,7 +3354,7 @@ httpWriteResponse(http_t *http, /* I - HTTP connection */ * Set the various standard fields if they aren't already... */ - if (!http->fields[HTTP_FIELD_DATE][0]) + if (!http->fields[HTTP_FIELD_DATE]) httpSetField(http, HTTP_FIELD_DATE, httpGetDateString(time(NULL))); if (status >= HTTP_STATUS_BAD_REQUEST && http->keep_alive) @@ -3503,7 +3365,7 @@ httpWriteResponse(http_t *http, /* I - HTTP connection */ if (http->version == HTTP_VERSION_1_1) { - if (!http->fields[HTTP_FIELD_CONNECTION][0]) + if (!http->fields[HTTP_FIELD_CONNECTION]) { if (http->keep_alive) httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive"); @@ -3511,7 +3373,7 @@ httpWriteResponse(http_t *http, /* I - HTTP connection */ httpSetField(http, HTTP_FIELD_CONNECTION, "close"); } - if (http->keep_alive && !http->fields[HTTP_FIELD_KEEP_ALIVE][0]) + if (http->keep_alive && !http->fields[HTTP_FIELD_KEEP_ALIVE]) httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "timeout=10"); } @@ -3519,28 +3381,26 @@ httpWriteResponse(http_t *http, /* I - HTTP connection */ if (status == HTTP_STATUS_UPGRADE_REQUIRED || status == HTTP_STATUS_SWITCHING_PROTOCOLS) { - if (!http->fields[HTTP_FIELD_CONNECTION][0]) + if (!http->fields[HTTP_FIELD_CONNECTION]) httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade"); - if (!http->fields[HTTP_FIELD_UPGRADE][0]) + if (!http->fields[HTTP_FIELD_UPGRADE]) httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0"); - if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0]) + if (!http->fields[HTTP_FIELD_CONTENT_LENGTH]) httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, "0"); } #endif /* HAVE_SSL */ - if (!http->server) - httpSetField(http, HTTP_FIELD_SERVER, - http->default_server ? http->default_server : CUPS_MINIMAL); + if (!http->fields[HTTP_FIELD_SERVER]) + httpSetField(http, HTTP_FIELD_SERVER, http->default_fields[HTTP_FIELD_SERVER] ? http->default_fields[HTTP_FIELD_SERVER] : CUPS_MINIMAL); /* * Set the Accept-Encoding field if it isn't already... */ - if (!http->accept_encoding) - httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, - http->default_accept_encoding ? http->default_accept_encoding : + if (!http->fields[HTTP_FIELD_ACCEPT_ENCODING]) + httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, http->default_fields[HTTP_FIELD_ACCEPT_ENCODING] ? http->default_fields[HTTP_FIELD_ACCEPT_ENCODING] : #ifdef HAVE_LIBZ "gzip, deflate, identity"); #else @@ -3555,8 +3415,7 @@ httpWriteResponse(http_t *http, /* I - HTTP connection */ old_remaining = http->data_remaining; http->data_encoding = HTTP_ENCODING_FIELDS; - if (httpPrintf(http, "HTTP/%d.%d %d %s\r\n", http->version / 100, - http->version % 100, (int)status, httpStatus(status)) < 0) + if (httpPrintf(http, "HTTP/%d.%d %d %s\r\n", http->version / 100, http->version % 100, (int)status, httpStatus(status)) < 0) { http->status = HTTP_STATUS_ERROR; return (-1); @@ -3667,6 +3526,9 @@ httpWriteResponse(http_t *http, /* I - HTTP connection */ return (0); } + if (http->state == HTTP_STATE_POST_RECV || http->state == HTTP_STATE_GET) + http->state ++; + #ifdef HAVE_LIBZ /* * Then start any content encoding... @@ -3683,6 +3545,149 @@ httpWriteResponse(http_t *http, /* I - HTTP connection */ } +/* + * 'http_add_field()' - Add a value for a HTTP field, appending if needed. + */ + +static void +http_add_field(http_t *http, /* I - HTTP connection */ + http_field_t field, /* I - HTTP field */ + const char *value, /* I - Value string */ + int append) /* I - Append value? */ +{ + char temp[1024]; /* Temporary value string */ + size_t fieldlen, /* Length of existing value */ + valuelen, /* Length of value string */ + total; /* Total length of string */ + + + if (field == HTTP_FIELD_HOST) + { + /* + * Special-case for Host: as we don't want a trailing "." on the hostname and + * need to bracket IPv6 numeric addresses. + */ + + char *ptr = strchr(value, ':'); + + if (value[0] != '[' && ptr && strchr(ptr + 1, ':')) + { + /* + * Bracket IPv6 numeric addresses... + * + * This is slightly inefficient (basically copying twice), but is an edge + * case and not worth optimizing... + */ + + snprintf(temp, sizeof(temp), "[%s]", value); + value = temp; + } + else if (*value) + { + /* + * Check for a trailing dot on the hostname... + */ + + strlcpy(temp, value, sizeof(temp)); + value = temp; + ptr = temp + strlen(temp) - 1; + + if (*ptr == '.') + *ptr = '\0'; + } + } + + if (append && field != HTTP_FIELD_ACCEPT_ENCODING && field != HTTP_FIELD_ACCEPT_LANGUAGE && field != HTTP_FIELD_ACCEPT_RANGES && field != HTTP_FIELD_ALLOW && field != HTTP_FIELD_LINK && field != HTTP_FIELD_TRANSFER_ENCODING && field != HTTP_FIELD_UPGRADE && field != HTTP_FIELD_WWW_AUTHENTICATE) + append = 0; + + if (!append && http->fields[field]) + { + if (http->fields[field] != http->_fields[field]) + free(http->fields[field]); + + http->fields[field] = NULL; + } + + valuelen = strlen(value); + + if (!valuelen) + { + http->_fields[field][0] = '\0'; + return; + } + + if (http->fields[field]) + { + fieldlen = strlen(http->fields[field]); + total = fieldlen + 2 + valuelen; + } + else + { + fieldlen = 0; + total = valuelen; + } + + if (total < HTTP_MAX_VALUE && field < HTTP_FIELD_ACCEPT_ENCODING) + { + /* + * Copy short values to legacy char arrays (maintained for binary + * compatibility with CUPS 1.2.x and earlier applications...) + */ + + if (fieldlen) + { + char combined[HTTP_MAX_VALUE]; + /* Combined value string */ + + snprintf(combined, sizeof(combined), "%s, %s", http->_fields[field], value); + value = combined; + } + + strlcpy(http->_fields[field], value, sizeof(http->_fields[field])); + http->fields[field] = http->_fields[field]; + } + else if (fieldlen) + { + /* + * Expand the field value... + */ + + char *combined; /* New value string */ + + if (http->fields[field] == http->_fields[field]) + { + if ((combined = malloc(total + 1)) != NULL) + { + http->fields[field] = combined; + snprintf(combined, total + 1, "%s, %s", http->_fields[field], value); + } + } + else if ((combined = realloc(http->fields[field], total + 1)) != NULL) + { + http->fields[field] = combined; + strlcat(combined, ", ", total + 1); + strlcat(combined, value, total + 1); + } + } + else + { + /* + * Allocate the field value... + */ + + http->fields[field] = strdup(value); + } + +#ifdef HAVE_LIBZ + if (field == HTTP_FIELD_CONTENT_ENCODING && http->data_encoding != HTTP_ENCODING_FIELDS) + { + DEBUG_puts("1httpSetField: Calling http_content_coding_start."); + http_content_coding_start(http, value); + } +#endif /* HAVE_LIBZ */ +} + + #ifdef HAVE_LIBZ /* * 'http_content_coding_finish()' - Finish doing any content encoding. @@ -3704,13 +3709,13 @@ http_content_coding_finish( { case _HTTP_CODING_DEFLATE : case _HTTP_CODING_GZIP : - http->stream.next_in = dummy; - http->stream.avail_in = 0; + ((z_stream *)http->stream)->next_in = dummy; + ((z_stream *)http->stream)->avail_in = 0; do { - zerr = deflate(&(http->stream), Z_FINISH); - bytes = _HTTP_MAX_SBUFFER - http->stream.avail_out; + zerr = deflate((z_stream *)http->stream, Z_FINISH); + bytes = _HTTP_MAX_SBUFFER - ((z_stream *)http->stream)->avail_out; if (bytes > 0) { @@ -3722,15 +3727,18 @@ http_content_coding_finish( http_write(http, (char *)http->sbuffer, bytes); } - http->stream.next_out = (Bytef *)http->sbuffer; - http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER; + ((z_stream *)http->stream)->next_out = (Bytef *)http->sbuffer; + ((z_stream *)http->stream)->avail_out = (uInt)_HTTP_MAX_SBUFFER; } while (zerr == Z_OK); - deflateEnd(&(http->stream)); + deflateEnd((z_stream *)http->stream); free(http->sbuffer); + free(http->stream); + http->sbuffer = NULL; + http->stream = NULL; if (http->wused) httpFlushWrite(http); @@ -3738,9 +3746,13 @@ http_content_coding_finish( case _HTTP_CODING_INFLATE : case _HTTP_CODING_GUNZIP : - inflateEnd(&(http->stream)); + inflateEnd((z_stream *)http->stream); + free(http->sbuffer); + free(http->stream); + http->sbuffer = NULL; + http->stream = NULL; break; default : @@ -3810,8 +3822,6 @@ http_content_coding_start( return; } - memset(&(http->stream), 0, sizeof(http->stream)); - switch (coding) { case _HTTP_CODING_DEFLATE : @@ -3832,18 +3842,30 @@ http_content_coding_start( * documentation. */ - if ((zerr = deflateInit2(&(http->stream), Z_DEFAULT_COMPRESSION, - Z_DEFLATED, - coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7, - Z_DEFAULT_STRATEGY)) < Z_OK) + if ((http->stream = calloc(1, sizeof(z_stream))) == NULL) + { + free(http->sbuffer); + + http->sbuffer = NULL; + http->status = HTTP_STATUS_ERROR; + http->error = errno; + return; + } + + if ((zerr = deflateInit2((z_stream *)http->stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7, Z_DEFAULT_STRATEGY)) < Z_OK) { - http->status = HTTP_STATUS_ERROR; - http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL; + free(http->sbuffer); + free(http->stream); + + http->sbuffer = NULL; + http->stream = NULL; + http->status = HTTP_STATUS_ERROR; + http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL; return; } - http->stream.next_out = (Bytef *)http->sbuffer; - http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER; + ((z_stream *)http->stream)->next_out = (Bytef *)http->sbuffer; + ((z_stream *)http->stream)->avail_out = (uInt)_HTTP_MAX_SBUFFER; break; case _HTTP_CODING_INFLATE : @@ -3860,19 +3882,30 @@ http_content_coding_start( * -15 is raw inflate, 31 is gunzip, per ZLIB documentation. */ - if ((zerr = inflateInit2(&(http->stream), - coding == _HTTP_CODING_INFLATE ? -15 : 31)) - < Z_OK) + if ((http->stream = calloc(1, sizeof(z_stream))) == NULL) + { + free(http->sbuffer); + + http->sbuffer = NULL; + http->status = HTTP_STATUS_ERROR; + http->error = errno; + return; + } + + if ((zerr = inflateInit2((z_stream *)http->stream, coding == _HTTP_CODING_INFLATE ? -15 : 31)) < Z_OK) { free(http->sbuffer); + free(http->stream); + http->sbuffer = NULL; + http->stream = NULL; http->status = HTTP_STATUS_ERROR; http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL; return; } - http->stream.avail_in = 0; - http->stream.next_in = http->sbuffer; + ((z_stream *)http->stream)->avail_in = 0; + ((z_stream *)http->stream)->next_in = http->sbuffer; break; default : @@ -3895,7 +3928,7 @@ static http_t * /* O - HTTP connection */ http_create( const char *host, /* I - Hostname */ int port, /* I - Port number */ - http_addrlist_t *addrlist, /* I - Address list or NULL */ + http_addrlist_t *addrlist, /* I - Address list or @code NULL@ */ int family, /* I - Address family or AF_UNSPEC */ http_encryption_t encryption, /* I - Encryption to use */ int blocking, /* I - 1 for blocking mode */ @@ -3938,7 +3971,7 @@ http_create( if ((http = calloc(sizeof(http_t), 1)) == NULL) { _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0); - httpAddrFreeList(addrlist); + httpAddrFreeList(myaddrlist); return (NULL); } @@ -4050,7 +4083,7 @@ http_read(http_t *http, /* I - HTTP connection */ DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length)); - if (!http->blocking) + if (!http->blocking || http->timeout_value > 0.0) { while (!httpWait(http, http->wait_value)) { @@ -4075,7 +4108,7 @@ http_read(http_t *http, /* I - HTTP connection */ if (bytes < 0) { -#ifdef WIN32 +#ifdef _WIN32 if (WSAGetLastError() != WSAEINTR) { http->error = WSAGetLastError(); @@ -4111,7 +4144,7 @@ http_read(http_t *http, /* I - HTTP connection */ http->error = errno; return (-1); } -#endif /* WIN32 */ +#endif /* _WIN32 */ } } while (bytes < 0); @@ -4125,7 +4158,7 @@ http_read(http_t *http, /* I - HTTP connection */ if (bytes < 0) { -#ifdef WIN32 +#ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) bytes = 0; else @@ -4135,7 +4168,7 @@ http_read(http_t *http, /* I - HTTP connection */ bytes = 0; else http->error = errno; -#endif /* WIN32 */ +#endif /* _WIN32 */ } else if (bytes == 0) { @@ -4295,10 +4328,10 @@ http_send(http_t *http, /* I - HTTP connection */ * Set the User-Agent field if it isn't already... */ - if (!http->fields[HTTP_FIELD_USER_AGENT][0]) + if (!http->fields[HTTP_FIELD_USER_AGENT]) { - if (http->default_user_agent) - httpSetField(http, HTTP_FIELD_USER_AGENT, http->default_user_agent); + if (http->default_fields[HTTP_FIELD_USER_AGENT]) + httpSetField(http, HTTP_FIELD_USER_AGENT, http->default_fields[HTTP_FIELD_USER_AGENT]); else httpSetField(http, HTTP_FIELD_USER_AGENT, cupsUserAgent()); } @@ -4307,9 +4340,8 @@ http_send(http_t *http, /* I - HTTP connection */ * Set the Accept-Encoding field if it isn't already... */ - if (!http->accept_encoding && http->default_accept_encoding) - httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, - http->default_accept_encoding); + if (!http->fields[HTTP_FIELD_ACCEPT_ENCODING] && http->default_fields[HTTP_FIELD_ACCEPT_ENCODING]) + httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING, http->default_fields[HTTP_FIELD_ACCEPT_ENCODING]); /* * Encode the URI as needed... @@ -4424,7 +4456,7 @@ http_send(http_t *http, /* I - HTTP connection */ * The Kerberos and AuthRef authentication strings can only be used once... */ - if (http->field_authorization && http->authstring && + if (http->fields[HTTP_FIELD_AUTHORIZATION] && http->authstring && (!strncmp(http->authstring, "Negotiate", 9) || !strncmp(http->authstring, "AuthRef", 7))) { @@ -4464,8 +4496,7 @@ http_set_length(http_t *http) /* I - Connection */ return (remaining); } - if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], - "chunked")) + if (!_cups_strcasecmp(httpGetField(http, HTTP_FIELD_TRANSFER_ENCODING), "chunked")) { DEBUG_puts("1http_set_length: Setting data_encoding to " "HTTP_ENCODING_CHUNKED."); @@ -4499,7 +4530,7 @@ static void http_set_timeout(int fd, /* I - File descriptor */ double timeout) /* I - Timeout in seconds */ { -#ifdef WIN32 +#ifdef _WIN32 DWORD tv = (DWORD)(timeout * 1000); /* Timeout in milliseconds */ @@ -4514,7 +4545,7 @@ http_set_timeout(int fd, /* I - File descriptor */ setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv)); setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv)); -#endif /* WIN32 */ +#endif /* _WIN32 */ } @@ -4570,10 +4601,15 @@ http_tls_upgrade(http_t *http) /* I - HTTP connection */ * encryption on the link... */ - http->tls_upgrade = 1; - http->field_authorization = NULL; /* Don't free the auth string */ + http->tls_upgrade = 1; + memset(http->fields, 0, sizeof(http->fields)); + http->expect = (http_status_t)0; + + if (http->hostname[0] == '/') + httpSetField(http, HTTP_FIELD_HOST, "localhost"); + else + httpSetField(http, HTTP_FIELD_HOST, http->hostname); - httpClearFields(http); httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade"); httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0"); @@ -4590,14 +4626,15 @@ http_tls_upgrade(http_t *http) /* I - HTTP connection */ * Restore the HTTP request data... */ + memcpy(http->_fields, myhttp._fields, sizeof(http->_fields)); memcpy(http->fields, myhttp.fields, sizeof(http->fields)); - http->data_encoding = myhttp.data_encoding; - http->data_remaining = myhttp.data_remaining; - http->_data_remaining = myhttp._data_remaining; - http->expect = myhttp.expect; - http->field_authorization = myhttp.field_authorization; - http->digest_tries = myhttp.digest_tries; - http->tls_upgrade = 0; + + http->data_encoding = myhttp.data_encoding; + http->data_remaining = myhttp.data_remaining; + http->_data_remaining = myhttp._data_remaining; + http->expect = myhttp.expect; + http->digest_tries = myhttp.digest_tries; + http->tls_upgrade = 0; /* * See if we actually went secure... @@ -4645,7 +4682,7 @@ http_write(http_t *http, /* I - HTTP connection */ { DEBUG_printf(("3http_write: About to write %d bytes.", (int)length)); - if (http->timeout_cb) + if (http->timeout_value > 0.0) { #ifdef HAVE_POLL struct pollfd pfd; /* Polled file descriptor */ @@ -4676,12 +4713,12 @@ http_write(http_t *http, /* I - HTTP connection */ nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout); } -# ifdef WIN32 +# ifdef _WIN32 while (nfds < 0 && (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)); # else while (nfds < 0 && (errno == EINTR || errno == EAGAIN)); -# endif /* WIN32 */ +# endif /* _WIN32 */ #endif /* HAVE_POLL */ if (nfds < 0) @@ -4689,13 +4726,13 @@ http_write(http_t *http, /* I - HTTP connection */ http->error = errno; return (-1); } - else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data)) + else if (nfds == 0 && (!http->timeout_cb || !(*http->timeout_cb)(http, http->timeout_data))) { -#ifdef WIN32 +#ifdef _WIN32 http->error = WSAEWOULDBLOCK; #else http->error = EWOULDBLOCK; -#endif /* WIN32 */ +#endif /* _WIN32 */ return (-1); } } @@ -4714,7 +4751,7 @@ http_write(http_t *http, /* I - HTTP connection */ if (bytes < 0) { -#ifdef WIN32 +#ifdef _WIN32 if (WSAGetLastError() == WSAEINTR) continue; else if (WSAGetLastError() == WSAEWOULDBLOCK) @@ -4748,7 +4785,7 @@ http_write(http_t *http, /* I - HTTP connection */ http->error = errno; continue; } -#endif /* WIN32 */ +#endif /* _WIN32 */ DEBUG_printf(("3http_write: error writing data (%s).", strerror(http->error)));