Home | History | Annotate | Download | only in cups
      1 /*
      2  * HTTP routines for CUPS.
      3  *
      4  * Copyright 2007-2015 by Apple Inc.
      5  * Copyright 1997-2007 by Easy Software Products, all rights reserved.
      6  *
      7  * This file contains Kerberos support code, copyright 2006 by
      8  * Jelmer Vernooij.
      9  *
     10  * These coded instructions, statements, and computer programs are the
     11  * property of Apple Inc. and are protected by Federal copyright
     12  * law.  Distribution and use rights are outlined in the file "LICENSE.txt"
     13  * which should have been included with this file.  If this file is
     14  * missing or damaged, see the license at "http://www.cups.org/".
     15  *
     16  * This file is subject to the Apple OS-Developed Software exception.
     17  */
     18 
     19 /*
     20  * Include necessary headers...
     21  */
     22 
     23 #include "cups-private.h"
     24 #include <fcntl.h>
     25 #include <math.h>
     26 #ifdef WIN32
     27 #  include <tchar.h>
     28 #else
     29 #  include <signal.h>
     30 #  include <sys/time.h>
     31 #  include <sys/resource.h>
     32 #endif /* WIN32 */
     33 #ifdef HAVE_POLL
     34 #  include <poll.h>
     35 #endif /* HAVE_POLL */
     36 
     37 
     38 /*
     39  * Local functions...
     40  */
     41 
     42 #ifdef HAVE_LIBZ
     43 static void		http_content_coding_finish(http_t *http);
     44 static void		http_content_coding_start(http_t *http,
     45 						  const char *value);
     46 #endif /* HAVE_LIBZ */
     47 static http_t		*http_create(const char *host, int port,
     48 			             http_addrlist_t *addrlist, int family,
     49 				     http_encryption_t encryption,
     50 				     int blocking, _http_mode_t mode);
     51 #ifdef DEBUG
     52 static void		http_debug_hex(const char *prefix, const char *buffer,
     53 			               int bytes);
     54 #endif /* DEBUG */
     55 static ssize_t		http_read(http_t *http, char *buffer, size_t length);
     56 static ssize_t		http_read_buffered(http_t *http, char *buffer, size_t length);
     57 static ssize_t		http_read_chunk(http_t *http, char *buffer, size_t length);
     58 static int		http_send(http_t *http, http_state_t request,
     59 			          const char *uri);
     60 static ssize_t		http_write(http_t *http, const char *buffer,
     61 			           size_t length);
     62 static ssize_t		http_write_chunk(http_t *http, const char *buffer,
     63 			                 size_t length);
     64 static off_t		http_set_length(http_t *http);
     65 static void		http_set_timeout(int fd, double timeout);
     66 static void		http_set_wait(http_t *http);
     67 
     68 #ifdef HAVE_SSL
     69 static int		http_tls_upgrade(http_t *http);
     70 #endif /* HAVE_SSL */
     71 
     72 
     73 /*
     74  * Local globals...
     75  */
     76 
     77 static const char * const http_fields[] =
     78 			{
     79 			  "Accept-Language",
     80 			  "Accept-Ranges",
     81 			  "Authorization",
     82 			  "Connection",
     83 			  "Content-Encoding",
     84 			  "Content-Language",
     85 			  "Content-Length",
     86 			  "Content-Location",
     87 			  "Content-MD5",
     88 			  "Content-Range",
     89 			  "Content-Type",
     90 			  "Content-Version",
     91 			  "Date",
     92 			  "Host",
     93 			  "If-Modified-Since",
     94 			  "If-Unmodified-since",
     95 			  "Keep-Alive",
     96 			  "Last-Modified",
     97 			  "Link",
     98 			  "Location",
     99 			  "Range",
    100 			  "Referer",
    101 			  "Retry-After",
    102 			  "Transfer-Encoding",
    103 			  "Upgrade",
    104 			  "User-Agent",
    105 			  "WWW-Authenticate",
    106 			  "Accept-Encoding",
    107 			  "Allow",
    108 			  "Server"
    109 			};
    110 
    111 
    112 /*
    113  * 'httpAcceptConnection()' - Accept a new HTTP client connection from the
    114  *                            specified listening socket.
    115  *
    116  * @since CUPS 1.7/macOS 10.9@
    117  */
    118 
    119 http_t *				/* O - HTTP connection or @code NULL@ */
    120 httpAcceptConnection(int fd,		/* I - Listen socket file descriptor */
    121                      int blocking)	/* I - 1 if the connection should be
    122         				       blocking, 0 otherwise */
    123 {
    124   http_t		*http;		/* HTTP connection */
    125   http_addrlist_t	addrlist;	/* Dummy address list */
    126   socklen_t		addrlen;	/* Length of address */
    127   int			val;		/* Socket option value */
    128 
    129 
    130  /*
    131   * Range check input...
    132   */
    133 
    134   if (fd < 0)
    135     return (NULL);
    136 
    137  /*
    138   * Create the client connection...
    139   */
    140 
    141   memset(&addrlist, 0, sizeof(addrlist));
    142 
    143   if ((http = http_create(NULL, 0, &addrlist, AF_UNSPEC,
    144                           HTTP_ENCRYPTION_IF_REQUESTED, blocking,
    145                           _HTTP_MODE_SERVER)) == NULL)
    146     return (NULL);
    147 
    148  /*
    149   * Accept the client and get the remote address...
    150   */
    151 
    152   addrlen = sizeof(http_addr_t);
    153 
    154   if ((http->fd = accept(fd, (struct sockaddr *)&(http->addrlist->addr),
    155 			 &addrlen)) < 0)
    156   {
    157     _cupsSetHTTPError(HTTP_STATUS_ERROR);
    158     httpClose(http);
    159 
    160     return (NULL);
    161   }
    162 
    163   http->hostaddr = &(http->addrlist->addr);
    164 
    165   if (httpAddrLocalhost(http->hostaddr))
    166     strlcpy(http->hostname, "localhost", sizeof(http->hostname));
    167   else
    168     httpAddrString(http->hostaddr, http->hostname, sizeof(http->hostname));
    169 
    170 #ifdef SO_NOSIGPIPE
    171  /*
    172   * Disable SIGPIPE for this socket.
    173   */
    174 
    175   val = 1;
    176   setsockopt(http->fd, SOL_SOCKET, SO_NOSIGPIPE, CUPS_SOCAST &val, sizeof(val));
    177 #endif /* SO_NOSIGPIPE */
    178 
    179  /*
    180   * Using TCP_NODELAY improves responsiveness, especially on systems
    181   * with a slow loopback interface.  Since we write large buffers
    182   * when sending print files and requests, there shouldn't be any
    183   * performance penalty for this...
    184   */
    185 
    186   val = 1;
    187   setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, CUPS_SOCAST &val, sizeof(val));
    188 
    189 #ifdef FD_CLOEXEC
    190  /*
    191   * Close this socket when starting another process...
    192   */
    193 
    194   fcntl(http->fd, F_SETFD, FD_CLOEXEC);
    195 #endif /* FD_CLOEXEC */
    196 
    197   return (http);
    198 }
    199 
    200 
    201 /*
    202  * 'httpAddCredential()' - Allocates and adds a single credential to an array.
    203  *
    204  * Use @code cupsArrayNew(NULL, NULL)@ to create a credentials array.
    205  *
    206  * @since CUPS 1.5/macOS 10.7@
    207  */
    208 
    209 int					/* O - 0 on success, -1 on error */
    210 httpAddCredential(
    211     cups_array_t *credentials,		/* I - Credentials array */
    212     const void   *data,			/* I - PEM-encoded X.509 data */
    213     size_t       datalen)		/* I - Length of data */
    214 {
    215   http_credential_t	*credential;	/* Credential data */
    216 
    217 
    218   if ((credential = malloc(sizeof(http_credential_t))) != NULL)
    219   {
    220     credential->datalen = datalen;
    221 
    222     if ((credential->data = malloc(datalen)) != NULL)
    223     {
    224       memcpy(credential->data, data, datalen);
    225       cupsArrayAdd(credentials, credential);
    226       return (0);
    227     }
    228 
    229     free(credential);
    230   }
    231 
    232   return (-1);
    233 }
    234 
    235 
    236 /*
    237  * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
    238  */
    239 
    240 void
    241 httpBlocking(http_t *http,		/* I - HTTP connection */
    242              int    b)			/* I - 1 = blocking, 0 = non-blocking */
    243 {
    244   if (http)
    245   {
    246     http->blocking = b;
    247     http_set_wait(http);
    248   }
    249 }
    250 
    251 
    252 /*
    253  * 'httpCheck()' - Check to see if there is a pending response from the server.
    254  */
    255 
    256 int					/* O - 0 = no data, 1 = data available */
    257 httpCheck(http_t *http)			/* I - HTTP connection */
    258 {
    259   return (httpWait(http, 0));
    260 }
    261 
    262 
    263 /*
    264  * 'httpClearCookie()' - Clear the cookie value(s).
    265  *
    266  * @since CUPS 1.1.19/macOS 10.3@
    267  */
    268 
    269 void
    270 httpClearCookie(http_t *http)		/* I - HTTP connection */
    271 {
    272   if (!http)
    273     return;
    274 
    275   if (http->cookie)
    276   {
    277     free(http->cookie);
    278     http->cookie = NULL;
    279   }
    280 }
    281 
    282 
    283 /*
    284  * 'httpClearFields()' - Clear HTTP request fields.
    285  */
    286 
    287 void
    288 httpClearFields(http_t *http)		/* I - HTTP connection */
    289 {
    290   DEBUG_printf(("httpClearFields(http=%p)", (void *)http));
    291 
    292   if (http)
    293   {
    294     memset(http->fields, 0, sizeof(http->fields));
    295 
    296     if (http->mode == _HTTP_MODE_CLIENT)
    297     {
    298       if (http->hostname[0] == '/')
    299 	httpSetField(http, HTTP_FIELD_HOST, "localhost");
    300       else
    301 	httpSetField(http, HTTP_FIELD_HOST, http->hostname);
    302     }
    303 
    304     if (http->field_authorization)
    305     {
    306       free(http->field_authorization);
    307       http->field_authorization = NULL;
    308     }
    309 
    310     if (http->accept_encoding)
    311     {
    312       _cupsStrFree(http->accept_encoding);
    313       http->accept_encoding = NULL;
    314     }
    315 
    316     if (http->allow)
    317     {
    318       _cupsStrFree(http->allow);
    319       http->allow = NULL;
    320     }
    321 
    322     if (http->server)
    323     {
    324       _cupsStrFree(http->server);
    325       http->server = NULL;
    326     }
    327 
    328     http->expect = (http_status_t)0;
    329   }
    330 }
    331 
    332 
    333 /*
    334  * 'httpClose()' - Close an HTTP connection.
    335  */
    336 
    337 void
    338 httpClose(http_t *http)			/* I - HTTP connection */
    339 {
    340 #ifdef HAVE_GSSAPI
    341   OM_uint32	minor_status;		/* Minor status code */
    342 #endif /* HAVE_GSSAPI */
    343 
    344 
    345   DEBUG_printf(("httpClose(http=%p)", (void *)http));
    346 
    347  /*
    348   * Range check input...
    349   */
    350 
    351   if (!http)
    352     return;
    353 
    354  /*
    355   * Close any open connection...
    356   */
    357 
    358   _httpDisconnect(http);
    359 
    360  /*
    361   * Free memory used...
    362   */
    363 
    364   httpAddrFreeList(http->addrlist);
    365 
    366   if (http->cookie)
    367     free(http->cookie);
    368 
    369 #ifdef HAVE_GSSAPI
    370   if (http->gssctx != GSS_C_NO_CONTEXT)
    371     gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
    372 
    373   if (http->gssname != GSS_C_NO_NAME)
    374     gss_release_name(&minor_status, &http->gssname);
    375 #endif /* HAVE_GSSAPI */
    376 
    377 #ifdef HAVE_AUTHORIZATION_H
    378   if (http->auth_ref)
    379     AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
    380 #endif /* HAVE_AUTHORIZATION_H */
    381 
    382   httpClearFields(http);
    383 
    384   if (http->authstring && http->authstring != http->_authstring)
    385     free(http->authstring);
    386 
    387   free(http);
    388 }
    389 
    390 
    391 /*
    392  * 'httpCompareCredentials()' - Compare two sets of X.509 credentials.
    393  *
    394  * @since CUPS 2.0/OS 10.10@
    395  */
    396 
    397 int					/* O - 1 if they match, 0 if they do not */
    398 httpCompareCredentials(
    399     cups_array_t *cred1,		/* I - First set of X.509 credentials */
    400     cups_array_t *cred2)		/* I - Second set of X.509 credentials */
    401 {
    402   http_credential_t	*temp1, *temp2;	/* Temporary credentials */
    403 
    404 
    405   for (temp1 = (http_credential_t *)cupsArrayFirst(cred1), temp2 = (http_credential_t *)cupsArrayFirst(cred2); temp1 && temp2; temp1 = (http_credential_t *)cupsArrayNext(cred1), temp2 = (http_credential_t *)cupsArrayNext(cred2))
    406     if (temp1->datalen != temp2->datalen)
    407       return (0);
    408     else if (memcmp(temp1->data, temp2->data, temp1->datalen))
    409       return (0);
    410 
    411   return (temp1 == temp2);
    412 }
    413 
    414 
    415 /*
    416  * 'httpConnect()' - Connect to a HTTP server.
    417  *
    418  * This function is deprecated - use @link httpConnect2@ instead.
    419  *
    420  * @deprecated@
    421  */
    422 
    423 http_t *				/* O - New HTTP connection */
    424 httpConnect(const char *host,		/* I - Host to connect to */
    425             int        port)		/* I - Port number */
    426 {
    427   return (httpConnect2(host, port, NULL, AF_UNSPEC,
    428                        HTTP_ENCRYPTION_IF_REQUESTED, 1, 30000, NULL));
    429 }
    430 
    431 
    432 /*
    433  * 'httpConnect2()' - Connect to a HTTP server.
    434  *
    435  * @since CUPS 1.7/macOS 10.9@
    436  */
    437 
    438 http_t *				/* O - New HTTP connection */
    439 httpConnect2(
    440     const char        *host,		/* I - Host to connect to */
    441     int               port,		/* I - Port number */
    442     http_addrlist_t   *addrlist,	/* I - List of addresses or NULL to lookup */
    443     int               family,		/* I - Address family to use or @code AF_UNSPEC@ for any */
    444     http_encryption_t encryption,	/* I - Type of encryption to use */
    445     int               blocking,		/* I - 1 for blocking connection, 0 for non-blocking */
    446     int               msec,		/* I - Connection timeout in milliseconds, 0 means don't connect */
    447     int               *cancel)		/* I - Pointer to "cancel" variable */
    448 {
    449   http_t	*http;			/* New HTTP connection */
    450 
    451 
    452   DEBUG_printf(("httpConnect2(host=\"%s\", port=%d, addrlist=%p, family=%d, encryption=%d, blocking=%d, msec=%d, cancel=%p)", host, port, (void *)addrlist, family, encryption, blocking, msec, (void *)cancel));
    453 
    454  /*
    455   * Create the HTTP structure...
    456   */
    457 
    458   if ((http = http_create(host, port, addrlist, family, encryption, blocking,
    459                           _HTTP_MODE_CLIENT)) == NULL)
    460     return (NULL);
    461 
    462  /*
    463   * Optionally connect to the remote system...
    464   */
    465 
    466   if (msec == 0 || !httpReconnect2(http, msec, cancel))
    467     return (http);
    468 
    469  /*
    470   * Could not connect to any known address - bail out!
    471   */
    472 
    473   httpClose(http);
    474 
    475   return (NULL);
    476 }
    477 
    478 
    479 /*
    480  * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
    481  *
    482  * This function is now deprecated. Please use the @link httpConnect2@ function
    483  * instead.
    484  *
    485  * @deprecated@
    486  */
    487 
    488 http_t *				/* O - New HTTP connection */
    489 httpConnectEncrypt(
    490     const char        *host,		/* I - Host to connect to */
    491     int               port,		/* I - Port number */
    492     http_encryption_t encryption)	/* I - Type of encryption to use */
    493 {
    494   DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)",
    495                 host, port, encryption));
    496 
    497   return (httpConnect2(host, port, NULL, AF_UNSPEC, encryption, 1, 30000,
    498                        NULL));
    499 }
    500 
    501 
    502 /*
    503  * 'httpDelete()' - Send a DELETE request to the server.
    504  */
    505 
    506 int					/* O - Status of call (0 = success) */
    507 httpDelete(http_t     *http,		/* I - HTTP connection */
    508            const char *uri)		/* I - URI to delete */
    509 {
    510   return (http_send(http, HTTP_STATE_DELETE, uri));
    511 }
    512 
    513 
    514 /*
    515  * '_httpDisconnect()' - Disconnect a HTTP connection.
    516  */
    517 
    518 void
    519 _httpDisconnect(http_t *http)		/* I - HTTP connection */
    520 {
    521 #ifdef HAVE_SSL
    522   if (http->tls)
    523     _httpTLSStop(http);
    524 #endif /* HAVE_SSL */
    525 
    526   httpAddrClose(NULL, http->fd);
    527 
    528   http->fd = -1;
    529 }
    530 
    531 
    532 /*
    533  * 'httpEncryption()' - Set the required encryption on the link.
    534  */
    535 
    536 int					/* O - -1 on error, 0 on success */
    537 httpEncryption(http_t            *http,	/* I - HTTP connection */
    538                http_encryption_t e)	/* I - New encryption preference */
    539 {
    540   DEBUG_printf(("httpEncryption(http=%p, e=%d)", (void *)http, e));
    541 
    542 #ifdef HAVE_SSL
    543   if (!http)
    544     return (0);
    545 
    546   if (http->mode == _HTTP_MODE_CLIENT)
    547   {
    548     http->encryption = e;
    549 
    550     if ((http->encryption == HTTP_ENCRYPTION_ALWAYS && !http->tls) ||
    551         (http->encryption == HTTP_ENCRYPTION_NEVER && http->tls))
    552       return (httpReconnect2(http, 30000, NULL));
    553     else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls)
    554       return (http_tls_upgrade(http));
    555     else
    556       return (0);
    557   }
    558   else
    559   {
    560     if (e == HTTP_ENCRYPTION_NEVER && http->tls)
    561       return (-1);
    562 
    563     http->encryption = e;
    564     if (e != HTTP_ENCRYPTION_IF_REQUESTED && !http->tls)
    565       return (_httpTLSStart(http));
    566     else
    567       return (0);
    568   }
    569 #else
    570   if (e == HTTP_ENCRYPTION_ALWAYS || e == HTTP_ENCRYPTION_REQUIRED)
    571     return (-1);
    572   else
    573     return (0);
    574 #endif /* HAVE_SSL */
    575 }
    576 
    577 
    578 /*
    579  * 'httpError()' - Get the last error on a connection.
    580  */
    581 
    582 int					/* O - Error code (errno) value */
    583 httpError(http_t *http)			/* I - HTTP connection */
    584 {
    585   if (http)
    586     return (http->error);
    587   else
    588     return (EINVAL);
    589 }
    590 
    591 
    592 /*
    593  * 'httpFieldValue()' - Return the HTTP field enumeration value for a field
    594  *                      name.
    595  */
    596 
    597 http_field_t				/* O - Field index */
    598 httpFieldValue(const char *name)	/* I - String name */
    599 {
    600   int	i;				/* Looping var */
    601 
    602 
    603   for (i = 0; i < HTTP_FIELD_MAX; i ++)
    604     if (!_cups_strcasecmp(name, http_fields[i]))
    605       return ((http_field_t)i);
    606 
    607   return (HTTP_FIELD_UNKNOWN);
    608 }
    609 
    610 
    611 /*
    612  * 'httpFlush()' - Flush data from a HTTP connection.
    613  */
    614 
    615 void
    616 httpFlush(http_t *http)			/* I - HTTP connection */
    617 {
    618   char		buffer[8192];		/* Junk buffer */
    619   int		blocking;		/* To block or not to block */
    620   http_state_t	oldstate;		/* Old state */
    621 
    622 
    623   DEBUG_printf(("httpFlush(http=%p), state=%s", (void *)http, httpStateString(http->state)));
    624 
    625  /*
    626   * Nothing to do if we are in the "waiting" state...
    627   */
    628 
    629   if (http->state == HTTP_STATE_WAITING)
    630     return;
    631 
    632  /*
    633   * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
    634   */
    635 
    636   blocking = http->blocking;
    637   http->blocking = 0;
    638 
    639  /*
    640   * Read any data we can...
    641   */
    642 
    643   oldstate = http->state;
    644   while (httpRead2(http, buffer, sizeof(buffer)) > 0);
    645 
    646  /*
    647   * Restore blocking and reset the connection if we didn't get all of
    648   * the remaining data...
    649   */
    650 
    651   http->blocking = blocking;
    652 
    653   if (http->state == oldstate && http->state != HTTP_STATE_WAITING &&
    654       http->fd >= 0)
    655   {
    656    /*
    657     * Didn't get the data back, so close the current connection.
    658     */
    659 
    660 #ifdef HAVE_LIBZ
    661     if (http->coding)
    662       http_content_coding_finish(http);
    663 #endif /* HAVE_LIBZ */
    664 
    665     DEBUG_puts("1httpFlush: Setting state to HTTP_STATE_WAITING and closing.");
    666 
    667     http->state = HTTP_STATE_WAITING;
    668 
    669 #ifdef HAVE_SSL
    670     if (http->tls)
    671       _httpTLSStop(http);
    672 #endif /* HAVE_SSL */
    673 
    674     httpAddrClose(NULL, http->fd);
    675 
    676     http->fd = -1;
    677   }
    678 }
    679 
    680 
    681 /*
    682  * 'httpFlushWrite()' - Flush data in write buffer.
    683  *
    684  * @since CUPS 1.2/macOS 10.5@
    685  */
    686 
    687 int					/* O - Bytes written or -1 on error */
    688 httpFlushWrite(http_t *http)		/* I - HTTP connection */
    689 {
    690   ssize_t	bytes;			/* Bytes written */
    691 
    692 
    693   DEBUG_printf(("httpFlushWrite(http=%p) data_encoding=%d", (void *)http, http ? http->data_encoding : 100));
    694 
    695   if (!http || !http->wused)
    696   {
    697     DEBUG_puts(http ? "1httpFlushWrite: Write buffer is empty." :
    698                       "1httpFlushWrite: No connection.");
    699     return (0);
    700   }
    701 
    702   if (http->data_encoding == HTTP_ENCODING_CHUNKED)
    703     bytes = http_write_chunk(http, http->wbuffer, (size_t)http->wused);
    704   else
    705     bytes = http_write(http, http->wbuffer, (size_t)http->wused);
    706 
    707   http->wused = 0;
    708 
    709   DEBUG_printf(("1httpFlushWrite: Returning %d, errno=%d.", (int)bytes, errno));
    710 
    711   return ((int)bytes);
    712 }
    713 
    714 
    715 /*
    716  * 'httpFreeCredentials()' - Free an array of credentials.
    717  */
    718 
    719 void
    720 httpFreeCredentials(
    721     cups_array_t *credentials)		/* I - Array of credentials */
    722 {
    723   http_credential_t	*credential;	/* Credential */
    724 
    725 
    726   for (credential = (http_credential_t *)cupsArrayFirst(credentials);
    727        credential;
    728        credential = (http_credential_t *)cupsArrayNext(credentials))
    729   {
    730     cupsArrayRemove(credentials, credential);
    731     free((void *)credential->data);
    732     free(credential);
    733   }
    734 
    735   cupsArrayDelete(credentials);
    736 }
    737 
    738 
    739 /*
    740  * 'httpGet()' - Send a GET request to the server.
    741  */
    742 
    743 int					/* O - Status of call (0 = success) */
    744 httpGet(http_t     *http,		/* I - HTTP connection */
    745         const char *uri)		/* I - URI to get */
    746 {
    747   return (http_send(http, HTTP_STATE_GET, uri));
    748 }
    749 
    750 
    751 /*
    752  * 'httpGetActivity()' - Get the most recent activity for a connection.
    753  *
    754  * The return value is the UNIX time of the last read or write.
    755  *
    756  * @since CUPS 2.0/OS 10.10@
    757  */
    758 
    759 time_t					/* O - Time of last read or write */
    760 httpGetActivity(http_t *http)		/* I - HTTP connection */
    761 {
    762   return (http ? http->activity : 0);
    763 }
    764 
    765 
    766 /*
    767  * 'httpGetAuthString()' - Get the current authorization string.
    768  *
    769  * The authorization string is set by cupsDoAuthentication() and
    770  * httpSetAuthString().  Use httpGetAuthString() to retrieve the
    771  * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
    772  * value.
    773  *
    774  * @since CUPS 1.3/macOS 10.5@
    775  */
    776 
    777 char *					/* O - Authorization string */
    778 httpGetAuthString(http_t *http)		/* I - HTTP connection */
    779 {
    780   if (http)
    781     return (http->authstring);
    782   else
    783     return (NULL);
    784 }
    785 
    786 
    787 /*
    788  * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
    789  *
    790  * @since CUPS 1.2/macOS 10.5@
    791  */
    792 
    793 int					/* O - 1 if blocking, 0 if non-blocking */
    794 httpGetBlocking(http_t *http)		/* I - HTTP connection */
    795 {
    796   return (http ? http->blocking : 0);
    797 }
    798 
    799 
    800 /*
    801  * 'httpGetContentEncoding()' - Get a common content encoding, if any, between
    802  *                              the client and server.
    803  *
    804  * This function uses the value of the Accepts-Encoding HTTP header and must be
    805  * called after receiving a response from the server or a request from the
    806  * client.  The value returned can be use in subsequent requests (for clients)
    807  * or in the response (for servers) in order to compress the content stream.
    808  *
    809  * @since CUPS 1.7/macOS 10.9@
    810  */
    811 
    812 const char *				/* O - Content-Coding value or
    813 					       @code NULL@ for the identity
    814 					       coding. */
    815 httpGetContentEncoding(http_t *http)	/* I - HTTP connection */
    816 {
    817 #ifdef HAVE_LIBZ
    818   if (http && http->accept_encoding)
    819   {
    820     int		i;			/* Looping var */
    821     char	temp[HTTP_MAX_VALUE],	/* Copy of Accepts-Encoding value */
    822 		*start,			/* Start of coding value */
    823 		*end;			/* End of coding value */
    824     double	qvalue;			/* "qvalue" for coding */
    825     struct lconv *loc = localeconv();	/* Locale data */
    826     static const char * const codings[] =
    827     {					/* Supported content codings */
    828       "deflate",
    829       "gzip",
    830       "x-deflate",
    831       "x-gzip"
    832     };
    833 
    834     strlcpy(temp, http->accept_encoding, sizeof(temp));
    835 
    836     for (start = temp; *start; start = end)
    837     {
    838      /*
    839       * Find the end of the coding name...
    840       */
    841 
    842       qvalue = 1.0;
    843       end    = start;
    844       while (*end && *end != ';' && *end != ',' && !isspace(*end & 255))
    845         end ++;
    846 
    847       if (*end == ';')
    848       {
    849        /*
    850         * Grab the qvalue as needed...
    851         */
    852 
    853         if (!strncmp(end, ";q=", 3))
    854           qvalue = _cupsStrScand(end + 3, NULL, loc);
    855 
    856        /*
    857         * Skip past all attributes...
    858         */
    859 
    860         *end++ = '\0';
    861         while (*end && *end != ',' && !isspace(*end & 255))
    862           end ++;
    863       }
    864       else if (*end)
    865         *end++ = '\0';
    866 
    867       while (*end && isspace(*end & 255))
    868 	end ++;
    869 
    870      /*
    871       * Check value if it matches something we support...
    872       */
    873 
    874       if (qvalue <= 0.0)
    875         continue;
    876 
    877       for (i = 0; i < (int)(sizeof(codings) / sizeof(codings[0])); i ++)
    878         if (!strcmp(start, codings[i]))
    879           return (codings[i]);
    880     }
    881   }
    882 #endif /* HAVE_LIBZ */
    883 
    884   return (NULL);
    885 }
    886 
    887 
    888 /*
    889  * 'httpGetCookie()' - Get any cookie data from the response.
    890  *
    891  * @since CUPS 1.1.19/macOS 10.3@
    892  */
    893 
    894 const char *				/* O - Cookie data or NULL */
    895 httpGetCookie(http_t *http)		/* I - HTTP connection */
    896 {
    897   return (http ? http->cookie : NULL);
    898 }
    899 
    900 
    901 /*
    902  * 'httpGetEncryption()' - Get the current encryption mode of a connection.
    903  *
    904  * This function returns the encryption mode for the connection. Use the
    905  * @link httpIsEncrypted@ function to determine whether a TLS session has
    906  * been established.
    907  *
    908  * @since CUPS 2.0/OS 10.10@
    909  */
    910 
    911 http_encryption_t			/* O - Current encryption mode */
    912 httpGetEncryption(http_t *http)		/* I - HTTP connection */
    913 {
    914   return (http ? http->encryption : HTTP_ENCRYPTION_IF_REQUESTED);
    915 }
    916 
    917 
    918 /*
    919  * 'httpGetExpect()' - Get the value of the Expect header, if any.
    920  *
    921  * Returns @code HTTP_STATUS_NONE@ if there is no Expect header, otherwise
    922  * returns the expected HTTP status code, typically @code HTTP_STATUS_CONTINUE@.
    923  *
    924  * @since CUPS 1.7/macOS 10.9@
    925  */
    926 
    927 http_status_t				/* O - Expect: status, if any */
    928 httpGetExpect(http_t *http)		/* I - HTTP connection */
    929 {
    930   if (!http)
    931     return (HTTP_STATUS_ERROR);
    932   else
    933     return (http->expect);
    934 }
    935 
    936 
    937 /*
    938  * 'httpGetFd()' - Get the file descriptor associated with a connection.
    939  *
    940  * @since CUPS 1.2/macOS 10.5@
    941  */
    942 
    943 int					/* O - File descriptor or -1 if none */
    944 httpGetFd(http_t *http)			/* I - HTTP connection */
    945 {
    946   return (http ? http->fd : -1);
    947 }
    948 
    949 
    950 /*
    951  * 'httpGetField()' - Get a field value from a request/response.
    952  */
    953 
    954 const char *				/* O - Field value */
    955 httpGetField(http_t       *http,	/* I - HTTP connection */
    956              http_field_t field)	/* I - Field to get */
    957 {
    958   if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
    959     return (NULL);
    960 
    961   switch (field)
    962   {
    963     case HTTP_FIELD_ACCEPT_ENCODING :
    964         return (http->accept_encoding);
    965 
    966     case HTTP_FIELD_ALLOW :
    967         return (http->allow);
    968 
    969     case HTTP_FIELD_SERVER :
    970         return (http->server);
    971 
    972     case HTTP_FIELD_AUTHORIZATION :
    973         if (http->field_authorization)
    974 	{
    975 	 /*
    976 	  * Special case for WWW-Authenticate: as its contents can be
    977 	  * longer than HTTP_MAX_VALUE...
    978 	  */
    979 
    980 	  return (http->field_authorization);
    981 	}
    982 
    983     default :
    984         return (http->fields[field]);
    985   }
    986 }
    987 
    988 
    989 /*
    990  * 'httpGetKeepAlive()' - Get the current Keep-Alive state of the connection.
    991  *
    992  * @since CUPS 2.0/OS 10.10@
    993  */
    994 
    995 http_keepalive_t			/* O - Keep-Alive state */
    996 httpGetKeepAlive(http_t *http)		/* I - HTTP connection */
    997 {
    998   return (http ? http->keep_alive : HTTP_KEEPALIVE_OFF);
    999 }
   1000 
   1001 
   1002 /*
   1003  * 'httpGetLength()' - Get the amount of data remaining from the
   1004  *                     content-length or transfer-encoding fields.
   1005  *
   1006  * This function is deprecated and will not return lengths larger than
   1007  * 2^31 - 1; use httpGetLength2() instead.
   1008  *
   1009  * @deprecated@
   1010  */
   1011 
   1012 int					/* O - Content length */
   1013 httpGetLength(http_t *http)		/* I - HTTP connection */
   1014 {
   1015  /*
   1016   * Get the read content length and return the 32-bit value.
   1017   */
   1018 
   1019   if (http)
   1020   {
   1021     httpGetLength2(http);
   1022 
   1023     return (http->_data_remaining);
   1024   }
   1025   else
   1026     return (-1);
   1027 }
   1028 
   1029 
   1030 /*
   1031  * 'httpGetLength2()' - Get the amount of data remaining from the
   1032  *                      content-length or transfer-encoding fields.
   1033  *
   1034  * This function returns the complete content length, even for
   1035  * content larger than 2^31 - 1.
   1036  *
   1037  * @since CUPS 1.2/macOS 10.5@
   1038  */
   1039 
   1040 off_t					/* O - Content length */
   1041 httpGetLength2(http_t *http)		/* I - HTTP connection */
   1042 {
   1043   off_t			remaining;	/* Remaining length */
   1044 
   1045 
   1046   DEBUG_printf(("2httpGetLength2(http=%p), state=%s", (void *)http, httpStateString(http->state)));
   1047 
   1048   if (!http)
   1049     return (-1);
   1050 
   1051   if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
   1052   {
   1053     DEBUG_puts("4httpGetLength2: chunked request!");
   1054     remaining = 0;
   1055   }
   1056   else
   1057   {
   1058    /*
   1059     * The following is a hack for HTTP servers that don't send a
   1060     * Content-Length or Transfer-Encoding field...
   1061     *
   1062     * If there is no Content-Length then the connection must close
   1063     * after the transfer is complete...
   1064     */
   1065 
   1066     if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
   1067     {
   1068      /*
   1069       * Default content length is 0 for errors and certain types of operations,
   1070       * and 2^31-1 for other successful requests...
   1071       */
   1072 
   1073       if (http->status >= HTTP_STATUS_MULTIPLE_CHOICES ||
   1074           http->state == HTTP_STATE_OPTIONS ||
   1075           (http->state == HTTP_STATE_GET && http->mode == _HTTP_MODE_SERVER) ||
   1076           http->state == HTTP_STATE_HEAD ||
   1077           (http->state == HTTP_STATE_PUT && http->mode == _HTTP_MODE_CLIENT) ||
   1078           http->state == HTTP_STATE_DELETE ||
   1079           http->state == HTTP_STATE_TRACE ||
   1080           http->state == HTTP_STATE_CONNECT)
   1081         remaining = 0;
   1082       else
   1083         remaining = 2147483647;
   1084     }
   1085     else if ((remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
   1086 			          NULL, 10)) < 0)
   1087       remaining = -1;
   1088 
   1089     DEBUG_printf(("4httpGetLength2: content_length=" CUPS_LLFMT,
   1090                   CUPS_LLCAST remaining));
   1091   }
   1092 
   1093   return (remaining);
   1094 }
   1095 
   1096 
   1097 /*
   1098  * 'httpGetPending()' - Get the number of bytes that are buffered for writing.
   1099  *
   1100  * @since CUPS 2.0/OS 10.10@
   1101  */
   1102 
   1103 size_t					/* O - Number of bytes buffered */
   1104 httpGetPending(http_t *http)		/* I - HTTP connection */
   1105 {
   1106   return (http ? (size_t)http->wused : 0);
   1107 }
   1108 
   1109 
   1110 /*
   1111  * 'httpGetReady()' - Get the number of bytes that can be read without blocking.
   1112  *
   1113  * @since CUPS 2.0/OS 10.10@
   1114  */
   1115 
   1116 size_t					/* O - Number of bytes available */
   1117 httpGetReady(http_t *http)		/* I - HTTP connection */
   1118 {
   1119   if (!http)
   1120     return (0);
   1121   else if (http->used > 0)
   1122     return ((size_t)http->used);
   1123 #ifdef HAVE_SSL
   1124   else if (http->tls)
   1125     return (_httpTLSPending(http));
   1126 #endif /* HAVE_SSL */
   1127 
   1128   return (0);
   1129 }
   1130 
   1131 
   1132 /*
   1133  * 'httpGetRemaining()' - Get the number of remaining bytes in the message
   1134  *                        body or current chunk.
   1135  *
   1136  * The @link httpIsChunked@ function can be used to determine whether the
   1137  * message body is chunked or fixed-length.
   1138  *
   1139  * @since CUPS 2.0/OS 10.10@
   1140  */
   1141 
   1142 size_t					/* O - Remaining bytes */
   1143 httpGetRemaining(http_t *http)		/* I - HTTP connection */
   1144 {
   1145   return (http ? (size_t)http->data_remaining : 0);
   1146 }
   1147 
   1148 
   1149 /*
   1150  * 'httpGets()' - Get a line of text from a HTTP connection.
   1151  */
   1152 
   1153 char *					/* O - Line or NULL */
   1154 httpGets(char   *line,			/* I - Line to read into */
   1155          int    length,			/* I - Max length of buffer */
   1156 	 http_t *http)			/* I - HTTP connection */
   1157 {
   1158   char		*lineptr,		/* Pointer into line */
   1159 		*lineend,		/* End of line */
   1160 		*bufptr,		/* Pointer into input buffer */
   1161 	        *bufend;		/* Pointer to end of buffer */
   1162   ssize_t	bytes;			/* Number of bytes read */
   1163   int		eol;			/* End-of-line? */
   1164 
   1165 
   1166   DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", (void *)line, length, (void *)http));
   1167 
   1168   if (!http || !line || length <= 1)
   1169     return (NULL);
   1170 
   1171  /*
   1172   * Read a line from the buffer...
   1173   */
   1174 
   1175   http->error = 0;
   1176   lineptr     = line;
   1177   lineend     = line + length - 1;
   1178   eol         = 0;
   1179 
   1180   while (lineptr < lineend)
   1181   {
   1182    /*
   1183     * Pre-load the buffer as needed...
   1184     */
   1185 
   1186 #ifdef WIN32
   1187     WSASetLastError(0);
   1188 #else
   1189     errno = 0;
   1190 #endif /* WIN32 */
   1191 
   1192     while (http->used == 0)
   1193     {
   1194      /*
   1195       * No newline; see if there is more data to be read...
   1196       */
   1197 
   1198       while (!_httpWait(http, http->wait_value, 1))
   1199       {
   1200 	if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   1201 	  continue;
   1202 
   1203         DEBUG_puts("3httpGets: Timed out!");
   1204 #ifdef WIN32
   1205         http->error = WSAETIMEDOUT;
   1206 #else
   1207         http->error = ETIMEDOUT;
   1208 #endif /* WIN32 */
   1209         return (NULL);
   1210       }
   1211 
   1212       bytes = http_read(http, http->buffer + http->used, (size_t)(HTTP_MAX_BUFFER - http->used));
   1213 
   1214       DEBUG_printf(("4httpGets: read " CUPS_LLFMT " bytes.", CUPS_LLCAST bytes));
   1215 
   1216       if (bytes < 0)
   1217       {
   1218        /*
   1219 	* Nope, can't get a line this time...
   1220 	*/
   1221 
   1222 #ifdef WIN32
   1223         DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError()));
   1224 
   1225         if (WSAGetLastError() == WSAEINTR)
   1226 	  continue;
   1227 	else if (WSAGetLastError() == WSAEWOULDBLOCK)
   1228 	{
   1229 	  if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   1230 	    continue;
   1231 
   1232 	  http->error = WSAGetLastError();
   1233 	}
   1234 	else if (WSAGetLastError() != http->error)
   1235 	{
   1236 	  http->error = WSAGetLastError();
   1237 	  continue;
   1238 	}
   1239 
   1240 #else
   1241         DEBUG_printf(("3httpGets: recv() error %d!", errno));
   1242 
   1243         if (errno == EINTR)
   1244 	  continue;
   1245 	else if (errno == EWOULDBLOCK || errno == EAGAIN)
   1246 	{
   1247 	  if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   1248 	    continue;
   1249 	  else if (!http->timeout_cb && errno == EAGAIN)
   1250 	    continue;
   1251 
   1252 	  http->error = errno;
   1253 	}
   1254 	else if (errno != http->error)
   1255 	{
   1256 	  http->error = errno;
   1257 	  continue;
   1258 	}
   1259 #endif /* WIN32 */
   1260 
   1261         return (NULL);
   1262       }
   1263       else if (bytes == 0)
   1264       {
   1265 	http->error = EPIPE;
   1266 
   1267         return (NULL);
   1268       }
   1269 
   1270      /*
   1271       * Yup, update the amount used...
   1272       */
   1273 
   1274       http->used += (int)bytes;
   1275     }
   1276 
   1277    /*
   1278     * Now copy as much of the current line as possible...
   1279     */
   1280 
   1281     for (bufptr = http->buffer, bufend = http->buffer + http->used;
   1282          lineptr < lineend && bufptr < bufend;)
   1283     {
   1284       if (*bufptr == 0x0a)
   1285       {
   1286         eol = 1;
   1287 	bufptr ++;
   1288 	break;
   1289       }
   1290       else if (*bufptr == 0x0d)
   1291 	bufptr ++;
   1292       else
   1293 	*lineptr++ = *bufptr++;
   1294     }
   1295 
   1296     http->used -= (int)(bufptr - http->buffer);
   1297     if (http->used > 0)
   1298       memmove(http->buffer, bufptr, (size_t)http->used);
   1299 
   1300     if (eol)
   1301     {
   1302      /*
   1303       * End of line...
   1304       */
   1305 
   1306       http->activity = time(NULL);
   1307 
   1308       *lineptr = '\0';
   1309 
   1310       DEBUG_printf(("3httpGets: Returning \"%s\"", line));
   1311 
   1312       return (line);
   1313     }
   1314   }
   1315 
   1316   DEBUG_puts("3httpGets: No new line available!");
   1317 
   1318   return (NULL);
   1319 }
   1320 
   1321 
   1322 /*
   1323  * 'httpGetState()' - Get the current state of the HTTP request.
   1324  */
   1325 
   1326 http_state_t				/* O - HTTP state */
   1327 httpGetState(http_t *http)		/* I - HTTP connection */
   1328 {
   1329   return (http ? http->state : HTTP_STATE_ERROR);
   1330 }
   1331 
   1332 
   1333 /*
   1334  * 'httpGetStatus()' - Get the status of the last HTTP request.
   1335  *
   1336  * @since CUPS 1.2/macOS 10.5@
   1337  */
   1338 
   1339 http_status_t				/* O - HTTP status */
   1340 httpGetStatus(http_t *http)		/* I - HTTP connection */
   1341 {
   1342   return (http ? http->status : HTTP_STATUS_ERROR);
   1343 }
   1344 
   1345 
   1346 /*
   1347  * 'httpGetSubField()' - Get a sub-field value.
   1348  *
   1349  * @deprecated@
   1350  */
   1351 
   1352 char *					/* O - Value or NULL */
   1353 httpGetSubField(http_t       *http,	/* I - HTTP connection */
   1354                 http_field_t field,	/* I - Field index */
   1355                 const char   *name,	/* I - Name of sub-field */
   1356 		char         *value)	/* O - Value string */
   1357 {
   1358   return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
   1359 }
   1360 
   1361 
   1362 /*
   1363  * 'httpGetSubField2()' - Get a sub-field value.
   1364  *
   1365  * @since CUPS 1.2/macOS 10.5@
   1366  */
   1367 
   1368 char *					/* O - Value or NULL */
   1369 httpGetSubField2(http_t       *http,	/* I - HTTP connection */
   1370                  http_field_t field,	/* I - Field index */
   1371                  const char   *name,	/* I - Name of sub-field */
   1372 		 char         *value,	/* O - Value string */
   1373 		 int          valuelen)	/* I - Size of value buffer */
   1374 {
   1375   const char	*fptr;			/* Pointer into field */
   1376   char		temp[HTTP_MAX_VALUE],	/* Temporary buffer for name */
   1377 		*ptr,			/* Pointer into string buffer */
   1378 		*end;			/* End of value buffer */
   1379 
   1380   DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, valuelen=%d)", (void *)http, field, name, (void *)value, valuelen));
   1381 
   1382   if (!http || !name || !value || valuelen < 2 ||
   1383       field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
   1384     return (NULL);
   1385 
   1386   end = value + valuelen - 1;
   1387 
   1388   for (fptr = http->fields[field]; *fptr;)
   1389   {
   1390    /*
   1391     * Skip leading whitespace...
   1392     */
   1393 
   1394     while (_cups_isspace(*fptr))
   1395       fptr ++;
   1396 
   1397     if (*fptr == ',')
   1398     {
   1399       fptr ++;
   1400       continue;
   1401     }
   1402 
   1403    /*
   1404     * Get the sub-field name...
   1405     */
   1406 
   1407     for (ptr = temp;
   1408          *fptr && *fptr != '=' && !_cups_isspace(*fptr) &&
   1409 	     ptr < (temp + sizeof(temp) - 1);
   1410          *ptr++ = *fptr++);
   1411 
   1412     *ptr = '\0';
   1413 
   1414     DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
   1415 
   1416    /*
   1417     * Skip trailing chars up to the '='...
   1418     */
   1419 
   1420     while (_cups_isspace(*fptr))
   1421       fptr ++;
   1422 
   1423     if (!*fptr)
   1424       break;
   1425 
   1426     if (*fptr != '=')
   1427       continue;
   1428 
   1429    /*
   1430     * Skip = and leading whitespace...
   1431     */
   1432 
   1433     fptr ++;
   1434 
   1435     while (_cups_isspace(*fptr))
   1436       fptr ++;
   1437 
   1438     if (*fptr == '\"')
   1439     {
   1440      /*
   1441       * Read quoted string...
   1442       */
   1443 
   1444       for (ptr = value, fptr ++;
   1445            *fptr && *fptr != '\"' && ptr < end;
   1446 	   *ptr++ = *fptr++);
   1447 
   1448       *ptr = '\0';
   1449 
   1450       while (*fptr && *fptr != '\"')
   1451         fptr ++;
   1452 
   1453       if (*fptr)
   1454         fptr ++;
   1455     }
   1456     else
   1457     {
   1458      /*
   1459       * Read unquoted string...
   1460       */
   1461 
   1462       for (ptr = value;
   1463            *fptr && !_cups_isspace(*fptr) && *fptr != ',' && ptr < end;
   1464 	   *ptr++ = *fptr++);
   1465 
   1466       *ptr = '\0';
   1467 
   1468       while (*fptr && !_cups_isspace(*fptr) && *fptr != ',')
   1469         fptr ++;
   1470     }
   1471 
   1472     DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
   1473 
   1474    /*
   1475     * See if this is the one...
   1476     */
   1477 
   1478     if (!strcmp(name, temp))
   1479     {
   1480       DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
   1481       return (value);
   1482     }
   1483   }
   1484 
   1485   value[0] = '\0';
   1486 
   1487   DEBUG_puts("3httpGetSubField2: Returning NULL");
   1488 
   1489   return (NULL);
   1490 }
   1491 
   1492 
   1493 /*
   1494  * 'httpGetVersion()' - Get the HTTP version at the other end.
   1495  */
   1496 
   1497 http_version_t				/* O - Version number */
   1498 httpGetVersion(http_t *http)		/* I - HTTP connection */
   1499 {
   1500   return (http ? http->version : HTTP_VERSION_1_0);
   1501 }
   1502 
   1503 
   1504 /*
   1505  * 'httpHead()' - Send a HEAD request to the server.
   1506  */
   1507 
   1508 int					/* O - Status of call (0 = success) */
   1509 httpHead(http_t     *http,		/* I - HTTP connection */
   1510          const char *uri)		/* I - URI for head */
   1511 {
   1512   DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", (void *)http, uri));
   1513   return (http_send(http, HTTP_STATE_HEAD, uri));
   1514 }
   1515 
   1516 
   1517 /*
   1518  * 'httpInitialize()' - Initialize the HTTP interface library and set the
   1519  *                      default HTTP proxy (if any).
   1520  */
   1521 
   1522 void
   1523 httpInitialize(void)
   1524 {
   1525   static int	initialized = 0;	/* Have we been called before? */
   1526 #ifdef WIN32
   1527   WSADATA	winsockdata;		/* WinSock data */
   1528 #endif /* WIN32 */
   1529 
   1530 
   1531   _cupsGlobalLock();
   1532   if (initialized)
   1533   {
   1534     _cupsGlobalUnlock();
   1535     return;
   1536   }
   1537 
   1538 #ifdef WIN32
   1539   WSAStartup(MAKEWORD(2,2), &winsockdata);
   1540 
   1541 #elif !defined(SO_NOSIGPIPE)
   1542  /*
   1543   * Ignore SIGPIPE signals...
   1544   */
   1545 
   1546 #  ifdef HAVE_SIGSET
   1547   sigset(SIGPIPE, SIG_IGN);
   1548 
   1549 #  elif defined(HAVE_SIGACTION)
   1550   struct sigaction	action;		/* POSIX sigaction data */
   1551 
   1552 
   1553   memset(&action, 0, sizeof(action));
   1554   action.sa_handler = SIG_IGN;
   1555   sigaction(SIGPIPE, &action, NULL);
   1556 
   1557 #  else
   1558   signal(SIGPIPE, SIG_IGN);
   1559 #  endif /* !SO_NOSIGPIPE */
   1560 #endif /* WIN32 */
   1561 
   1562 #  ifdef HAVE_SSL
   1563   _httpTLSInitialize();
   1564 #  endif /* HAVE_SSL */
   1565 
   1566   initialized = 1;
   1567   _cupsGlobalUnlock();
   1568 }
   1569 
   1570 
   1571 /*
   1572  * 'httpIsChunked()' - Report whether a message body is chunked.
   1573  *
   1574  * This function returns non-zero if the message body is composed of
   1575  * variable-length chunks.
   1576  *
   1577  * @since CUPS 2.0/OS 10.10@
   1578  */
   1579 
   1580 int					/* O - 1 if chunked, 0 if not */
   1581 httpIsChunked(http_t *http)		/* I - HTTP connection */
   1582 {
   1583   return (http ? http->data_encoding == HTTP_ENCODING_CHUNKED : 0);
   1584 }
   1585 
   1586 
   1587 /*
   1588  * 'httpIsEncrypted()' - Report whether a connection is encrypted.
   1589  *
   1590  * This function returns non-zero if the connection is currently encrypted.
   1591  *
   1592  * @since CUPS 2.0/OS 10.10@
   1593  */
   1594 
   1595 int					/* O - 1 if encrypted, 0 if not */
   1596 httpIsEncrypted(http_t *http)		/* I - HTTP connection */
   1597 {
   1598   return (http ? http->tls != NULL : 0);
   1599 }
   1600 
   1601 
   1602 /*
   1603  * 'httpOptions()' - Send an OPTIONS request to the server.
   1604  */
   1605 
   1606 int					/* O - Status of call (0 = success) */
   1607 httpOptions(http_t     *http,		/* I - HTTP connection */
   1608             const char *uri)		/* I - URI for options */
   1609 {
   1610   return (http_send(http, HTTP_STATE_OPTIONS, uri));
   1611 }
   1612 
   1613 
   1614 /*
   1615  * 'httpPeek()' - Peek at data from a HTTP connection.
   1616  *
   1617  * This function copies available data from the given HTTP connection, reading
   1618  * a buffer as needed.  The data is still available for reading using
   1619  * @link httpRead@ or @link httpRead2@.
   1620  *
   1621  * For non-blocking connections the usual timeouts apply.
   1622  *
   1623  * @since CUPS 1.7/macOS 10.9@
   1624  */
   1625 
   1626 ssize_t					/* O - Number of bytes copied */
   1627 httpPeek(http_t *http,			/* I - HTTP connection */
   1628          char   *buffer,		/* I - Buffer for data */
   1629 	 size_t length)			/* I - Maximum number of bytes */
   1630 {
   1631   ssize_t	bytes;			/* Bytes read */
   1632   char		len[32];		/* Length string */
   1633 
   1634 
   1635   DEBUG_printf(("httpPeek(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   1636 
   1637   if (http == NULL || buffer == NULL)
   1638     return (-1);
   1639 
   1640   http->activity = time(NULL);
   1641   http->error    = 0;
   1642 
   1643   if (length <= 0)
   1644     return (0);
   1645 
   1646   if (http->data_encoding == HTTP_ENCODING_CHUNKED &&
   1647       http->data_remaining <= 0)
   1648   {
   1649     DEBUG_puts("2httpPeek: Getting chunk length...");
   1650 
   1651     if (httpGets(len, sizeof(len), http) == NULL)
   1652     {
   1653       DEBUG_puts("1httpPeek: Could not get length!");
   1654       return (0);
   1655     }
   1656 
   1657     if (!len[0])
   1658     {
   1659       DEBUG_puts("1httpPeek: Blank chunk length, trying again...");
   1660       if (!httpGets(len, sizeof(len), http))
   1661       {
   1662 	DEBUG_puts("1httpPeek: Could not get chunk length.");
   1663 	return (0);
   1664       }
   1665     }
   1666 
   1667     http->data_remaining = strtoll(len, NULL, 16);
   1668 
   1669     if (http->data_remaining < 0)
   1670     {
   1671       DEBUG_puts("1httpPeek: Negative chunk length!");
   1672       return (0);
   1673     }
   1674   }
   1675 
   1676   DEBUG_printf(("2httpPeek: data_remaining=" CUPS_LLFMT,
   1677                 CUPS_LLCAST http->data_remaining));
   1678 
   1679   if (http->data_remaining <= 0 && http->data_encoding != HTTP_ENCODING_FIELDS)
   1680   {
   1681    /*
   1682     * A zero-length chunk ends a transfer; unless we are reading POST
   1683     * data, go idle...
   1684     */
   1685 
   1686 #ifdef HAVE_LIBZ
   1687     if (http->coding >= _HTTP_CODING_GUNZIP)
   1688       http_content_coding_finish(http);
   1689 #endif /* HAVE_LIBZ */
   1690 
   1691     if (http->data_encoding == HTTP_ENCODING_CHUNKED)
   1692       httpGets(len, sizeof(len), http);
   1693 
   1694     if (http->state == HTTP_STATE_POST_RECV)
   1695       http->state ++;
   1696     else
   1697       http->state = HTTP_STATE_STATUS;
   1698 
   1699     DEBUG_printf(("1httpPeek: 0-length chunk, set state to %s.",
   1700                   httpStateString(http->state)));
   1701 
   1702    /*
   1703     * Prevent future reads for this request...
   1704     */
   1705 
   1706     http->data_encoding = HTTP_ENCODING_FIELDS;
   1707 
   1708     return (0);
   1709   }
   1710   else if (length > (size_t)http->data_remaining)
   1711     length = (size_t)http->data_remaining;
   1712 
   1713 #ifdef HAVE_LIBZ
   1714   if (http->used == 0 &&
   1715       (http->coding == _HTTP_CODING_IDENTITY ||
   1716        (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in == 0)))
   1717 #else
   1718   if (http->used == 0)
   1719 #endif /* HAVE_LIBZ */
   1720   {
   1721    /*
   1722     * Buffer small reads for better performance...
   1723     */
   1724 
   1725     ssize_t	buflen;			/* Length of read for buffer */
   1726 
   1727     if (!http->blocking)
   1728     {
   1729       while (!httpWait(http, http->wait_value))
   1730       {
   1731 	if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   1732 	  continue;
   1733 
   1734 	return (0);
   1735       }
   1736     }
   1737 
   1738     if ((size_t)http->data_remaining > sizeof(http->buffer))
   1739       buflen = sizeof(http->buffer);
   1740     else
   1741       buflen = (ssize_t)http->data_remaining;
   1742 
   1743     DEBUG_printf(("2httpPeek: Reading %d bytes into buffer.", (int)buflen));
   1744     bytes = http_read(http, http->buffer, (size_t)buflen);
   1745 
   1746     DEBUG_printf(("2httpPeek: Read " CUPS_LLFMT " bytes into buffer.",
   1747                   CUPS_LLCAST bytes));
   1748     if (bytes > 0)
   1749     {
   1750 #ifdef DEBUG
   1751       http_debug_hex("httpPeek", http->buffer, (int)bytes);
   1752 #endif /* DEBUG */
   1753 
   1754       http->used = (int)bytes;
   1755     }
   1756   }
   1757 
   1758 #ifdef HAVE_LIBZ
   1759   if (http->coding >= _HTTP_CODING_GUNZIP)
   1760   {
   1761 #  ifdef HAVE_INFLATECOPY
   1762     int		zerr;			/* Decompressor error */
   1763     z_stream	stream;			/* Copy of decompressor stream */
   1764 
   1765     if (http->used > 0 && http->stream.avail_in < HTTP_MAX_BUFFER)
   1766     {
   1767       size_t buflen = buflen = HTTP_MAX_BUFFER - http->stream.avail_in;
   1768 					/* Number of bytes to copy */
   1769 
   1770       if (http->stream.avail_in > 0 &&
   1771 	  http->stream.next_in > http->sbuffer)
   1772         memmove(http->sbuffer, http->stream.next_in, http->stream.avail_in);
   1773 
   1774       http->stream.next_in = http->sbuffer;
   1775 
   1776       if (buflen > (size_t)http->data_remaining)
   1777         buflen = (size_t)http->data_remaining;
   1778 
   1779       if (buflen > (size_t)http->used)
   1780         buflen = (size_t)http->used;
   1781 
   1782       DEBUG_printf(("1httpPeek: Copying %d more bytes of data into "
   1783 		    "decompression buffer.", (int)buflen));
   1784 
   1785       memcpy(http->sbuffer + http->stream.avail_in, http->buffer, buflen);
   1786       http->stream.avail_in += buflen;
   1787       http->used            -= (int)buflen;
   1788       http->data_remaining  -= (off_t)buflen;
   1789 
   1790       if (http->used > 0)
   1791         memmove(http->buffer, http->buffer + buflen, (size_t)http->used);
   1792     }
   1793 
   1794     DEBUG_printf(("2httpPeek: length=%d, avail_in=%d", (int)length,
   1795                   (int)http->stream.avail_in));
   1796 
   1797     if (inflateCopy(&stream, &(http->stream)) != Z_OK)
   1798     {
   1799       DEBUG_puts("2httpPeek: Unable to copy decompressor stream.");
   1800       http->error = ENOMEM;
   1801       return (-1);
   1802     }
   1803 
   1804     stream.next_out  = (Bytef *)buffer;
   1805     stream.avail_out = (uInt)length;
   1806 
   1807     zerr = inflate(&stream, Z_SYNC_FLUSH);
   1808     inflateEnd(&stream);
   1809 
   1810     if (zerr < Z_OK)
   1811     {
   1812       DEBUG_printf(("2httpPeek: zerr=%d", zerr));
   1813 #ifdef DEBUG
   1814       http_debug_hex("2httpPeek", (char *)http->sbuffer, (int)http->stream.avail_in);
   1815 #endif /* DEBUG */
   1816 
   1817       http->error = EIO;
   1818       return (-1);
   1819     }
   1820 
   1821     bytes = (ssize_t)(length - http->stream.avail_out);
   1822 
   1823 #  else
   1824     DEBUG_puts("2httpPeek: No inflateCopy on this platform, httpPeek does not "
   1825                "work with compressed streams.");
   1826     return (-1);
   1827 #  endif /* HAVE_INFLATECOPY */
   1828   }
   1829   else
   1830 #endif /* HAVE_LIBZ */
   1831   if (http->used > 0)
   1832   {
   1833     if (length > (size_t)http->used)
   1834       length = (size_t)http->used;
   1835 
   1836     bytes = (ssize_t)length;
   1837 
   1838     DEBUG_printf(("2httpPeek: grabbing %d bytes from input buffer...",
   1839                   (int)bytes));
   1840 
   1841     memcpy(buffer, http->buffer, length);
   1842   }
   1843   else
   1844     bytes = 0;
   1845 
   1846   if (bytes < 0)
   1847   {
   1848 #ifdef WIN32
   1849     if (WSAGetLastError() == WSAEINTR || WSAGetLastError() == WSAEWOULDBLOCK)
   1850       bytes = 0;
   1851     else
   1852       http->error = WSAGetLastError();
   1853 #else
   1854     if (errno == EINTR || errno == EAGAIN)
   1855       bytes = 0;
   1856     else
   1857       http->error = errno;
   1858 #endif /* WIN32 */
   1859   }
   1860   else if (bytes == 0)
   1861   {
   1862     http->error = EPIPE;
   1863     return (0);
   1864   }
   1865 
   1866   return (bytes);
   1867 }
   1868 
   1869 
   1870 /*
   1871  * 'httpPost()' - Send a POST request to the server.
   1872  */
   1873 
   1874 int					/* O - Status of call (0 = success) */
   1875 httpPost(http_t     *http,		/* I - HTTP connection */
   1876          const char *uri)		/* I - URI for post */
   1877 {
   1878   return (http_send(http, HTTP_STATE_POST, uri));
   1879 }
   1880 
   1881 
   1882 /*
   1883  * 'httpPrintf()' - Print a formatted string to a HTTP connection.
   1884  *
   1885  * @private@
   1886  */
   1887 
   1888 int					/* O - Number of bytes written */
   1889 httpPrintf(http_t     *http,		/* I - HTTP connection */
   1890            const char *format,		/* I - printf-style format string */
   1891 	   ...)				/* I - Additional args as needed */
   1892 {
   1893   ssize_t	bytes;			/* Number of bytes to write */
   1894   char		buf[16384];		/* Buffer for formatted string */
   1895   va_list	ap;			/* Variable argument pointer */
   1896 
   1897 
   1898   DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", (void *)http, format));
   1899 
   1900   va_start(ap, format);
   1901   bytes = vsnprintf(buf, sizeof(buf), format, ap);
   1902   va_end(ap);
   1903 
   1904   DEBUG_printf(("3httpPrintf: (" CUPS_LLFMT " bytes) %s", CUPS_LLCAST bytes, buf));
   1905 
   1906   if (http->data_encoding == HTTP_ENCODING_FIELDS)
   1907     return ((int)httpWrite2(http, buf, (size_t)bytes));
   1908   else
   1909   {
   1910     if (http->wused)
   1911     {
   1912       DEBUG_puts("4httpPrintf: flushing existing data...");
   1913 
   1914       if (httpFlushWrite(http) < 0)
   1915 	return (-1);
   1916     }
   1917 
   1918     return ((int)http_write(http, buf, (size_t)bytes));
   1919   }
   1920 }
   1921 
   1922 
   1923 /*
   1924  * 'httpPut()' - Send a PUT request to the server.
   1925  */
   1926 
   1927 int					/* O - Status of call (0 = success) */
   1928 httpPut(http_t     *http,		/* I - HTTP connection */
   1929         const char *uri)		/* I - URI to put */
   1930 {
   1931   DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", (void *)http, uri));
   1932   return (http_send(http, HTTP_STATE_PUT, uri));
   1933 }
   1934 
   1935 
   1936 /*
   1937  * 'httpRead()' - Read data from a HTTP connection.
   1938  *
   1939  * This function is deprecated. Use the httpRead2() function which can
   1940  * read more than 2GB of data.
   1941  *
   1942  * @deprecated@
   1943  */
   1944 
   1945 int					/* O - Number of bytes read */
   1946 httpRead(http_t *http,			/* I - HTTP connection */
   1947          char   *buffer,		/* I - Buffer for data */
   1948 	 int    length)			/* I - Maximum number of bytes */
   1949 {
   1950   return ((int)httpRead2(http, buffer, (size_t)length));
   1951 }
   1952 
   1953 
   1954 /*
   1955  * 'httpRead2()' - Read data from a HTTP connection.
   1956  *
   1957  * @since CUPS 1.2/macOS 10.5@
   1958  */
   1959 
   1960 ssize_t					/* O - Number of bytes read */
   1961 httpRead2(http_t *http,			/* I - HTTP connection */
   1962           char   *buffer,		/* I - Buffer for data */
   1963 	  size_t length)		/* I - Maximum number of bytes */
   1964 {
   1965   ssize_t	bytes;			/* Bytes read */
   1966 
   1967 
   1968 #ifdef HAVE_LIBZ
   1969   DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ") coding=%d data_encoding=%d data_remaining=" CUPS_LLFMT, (void *)http, (void *)buffer, CUPS_LLCAST length, http->coding, http->data_encoding, CUPS_LLCAST http->data_remaining));
   1970 #else
   1971   DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ") data_encoding=%d data_remaining=" CUPS_LLFMT, (void *)http, (void *)buffer, CUPS_LLCAST length, http->data_encoding, CUPS_LLCAST http->data_remaining));
   1972 #endif /* HAVE_LIBZ */
   1973 
   1974   if (http == NULL || buffer == NULL)
   1975     return (-1);
   1976 
   1977   http->activity = time(NULL);
   1978   http->error    = 0;
   1979 
   1980   if (length <= 0)
   1981     return (0);
   1982 
   1983 #ifdef HAVE_LIBZ
   1984   if (http->coding >= _HTTP_CODING_GUNZIP)
   1985   {
   1986     do
   1987     {
   1988       if (http->stream.avail_in > 0)
   1989       {
   1990 	int	zerr;			/* Decompressor error */
   1991 
   1992 	DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d",
   1993 	              (int)http->stream.avail_in, (int)length));
   1994 
   1995 	http->stream.next_out  = (Bytef *)buffer;
   1996 	http->stream.avail_out = (uInt)length;
   1997 
   1998 	if ((zerr = inflate(&(http->stream), Z_SYNC_FLUSH)) < Z_OK)
   1999 	{
   2000 	  DEBUG_printf(("2httpRead2: zerr=%d", zerr));
   2001 #ifdef DEBUG
   2002           http_debug_hex("2httpRead2", (char *)http->sbuffer, (int)http->stream.avail_in);
   2003 #endif /* DEBUG */
   2004 
   2005 	  http->error = EIO;
   2006 	  return (-1);
   2007 	}
   2008 
   2009 	bytes = (ssize_t)(length - http->stream.avail_out);
   2010 
   2011 	DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d",
   2012 		      http->stream.avail_in, http->stream.avail_out,
   2013 		      (int)bytes));
   2014       }
   2015       else
   2016         bytes = 0;
   2017 
   2018       if (bytes == 0)
   2019       {
   2020         ssize_t buflen = HTTP_MAX_BUFFER - (ssize_t)http->stream.avail_in;
   2021 					/* Additional bytes for buffer */
   2022 
   2023         if (buflen > 0)
   2024         {
   2025           if (http->stream.avail_in > 0 &&
   2026               http->stream.next_in > http->sbuffer)
   2027             memmove(http->sbuffer, http->stream.next_in, http->stream.avail_in);
   2028 
   2029 	  http->stream.next_in = http->sbuffer;
   2030 
   2031           DEBUG_printf(("1httpRead2: Reading up to %d more bytes of data into "
   2032                         "decompression buffer.", (int)buflen));
   2033 
   2034           if (http->data_remaining > 0)
   2035           {
   2036 	    if (buflen > http->data_remaining)
   2037 	      buflen = (ssize_t)http->data_remaining;
   2038 
   2039 	    bytes = http_read_buffered(http, (char *)http->sbuffer + http->stream.avail_in, (size_t)buflen);
   2040           }
   2041           else if (http->data_encoding == HTTP_ENCODING_CHUNKED)
   2042             bytes = http_read_chunk(http, (char *)http->sbuffer + http->stream.avail_in, (size_t)buflen);
   2043           else
   2044             bytes = 0;
   2045 
   2046           if (bytes < 0)
   2047             return (bytes);
   2048           else if (bytes == 0)
   2049             break;
   2050 
   2051           DEBUG_printf(("1httpRead2: Adding " CUPS_LLFMT " bytes to "
   2052                         "decompression buffer.", CUPS_LLCAST bytes));
   2053 
   2054           http->data_remaining  -= bytes;
   2055           http->stream.avail_in += (uInt)bytes;
   2056 
   2057 	  if (http->data_remaining <= 0 &&
   2058 	      http->data_encoding == HTTP_ENCODING_CHUNKED)
   2059 	  {
   2060 	   /*
   2061 	    * Read the trailing blank line now...
   2062 	    */
   2063 
   2064 	    char	len[32];		/* Length string */
   2065 
   2066 	    httpGets(len, sizeof(len), http);
   2067 	  }
   2068 
   2069           bytes = 0;
   2070         }
   2071         else
   2072           return (0);
   2073       }
   2074     }
   2075     while (bytes == 0);
   2076   }
   2077   else
   2078 #endif /* HAVE_LIBZ */
   2079   if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODING_CHUNKED)
   2080   {
   2081     if ((bytes = http_read_chunk(http, buffer, length)) > 0)
   2082     {
   2083       http->data_remaining -= bytes;
   2084 
   2085       if (http->data_remaining <= 0)
   2086       {
   2087        /*
   2088         * Read the trailing blank line now...
   2089         */
   2090 
   2091         char	len[32];		/* Length string */
   2092 
   2093         httpGets(len, sizeof(len), http);
   2094       }
   2095     }
   2096   }
   2097   else if (http->data_remaining <= 0)
   2098   {
   2099    /*
   2100     * No more data to read...
   2101     */
   2102 
   2103     return (0);
   2104   }
   2105   else
   2106   {
   2107     DEBUG_printf(("1httpRead2: Reading up to %d bytes into buffer.",
   2108                   (int)length));
   2109 
   2110     if (length > (size_t)http->data_remaining)
   2111       length = (size_t)http->data_remaining;
   2112 
   2113     if ((bytes = http_read_buffered(http, buffer, length)) > 0)
   2114     {
   2115       http->data_remaining -= bytes;
   2116 
   2117       if (http->data_remaining <= 0 &&
   2118           http->data_encoding == HTTP_ENCODING_CHUNKED)
   2119       {
   2120        /*
   2121         * Read the trailing blank line now...
   2122         */
   2123 
   2124         char	len[32];		/* Length string */
   2125 
   2126         httpGets(len, sizeof(len), http);
   2127       }
   2128     }
   2129   }
   2130 
   2131   if (
   2132 #ifdef HAVE_LIBZ
   2133       (http->coding == _HTTP_CODING_IDENTITY ||
   2134        (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in == 0)) &&
   2135 #endif /* HAVE_LIBZ */
   2136       ((http->data_remaining <= 0 &&
   2137         http->data_encoding == HTTP_ENCODING_LENGTH) ||
   2138        (http->data_encoding == HTTP_ENCODING_CHUNKED && bytes == 0)))
   2139   {
   2140 #ifdef HAVE_LIBZ
   2141     if (http->coding >= _HTTP_CODING_GUNZIP)
   2142       http_content_coding_finish(http);
   2143 #endif /* HAVE_LIBZ */
   2144 
   2145     if (http->state == HTTP_STATE_POST_RECV)
   2146       http->state ++;
   2147     else if (http->state == HTTP_STATE_GET_SEND ||
   2148              http->state == HTTP_STATE_POST_SEND)
   2149       http->state = HTTP_STATE_WAITING;
   2150     else
   2151       http->state = HTTP_STATE_STATUS;
   2152 
   2153     DEBUG_printf(("1httpRead2: End of content, set state to %s.",
   2154 		  httpStateString(http->state)));
   2155   }
   2156 
   2157   return (bytes);
   2158 }
   2159 
   2160 
   2161 /*
   2162  * 'httpReadRequest()' - Read a HTTP request from a connection.
   2163  *
   2164  * @since CUPS 1.7/macOS 10.9@
   2165  */
   2166 
   2167 http_state_t				/* O - New state of connection */
   2168 httpReadRequest(http_t *http,		/* I - HTTP connection */
   2169                 char   *uri,		/* I - URI buffer */
   2170 		size_t urilen)		/* I - Size of URI buffer */
   2171 {
   2172   char	line[4096],			/* HTTP request line */
   2173 	*req_method,			/* HTTP request method */
   2174 	*req_uri,			/* HTTP request URI */
   2175 	*req_version;			/* HTTP request version number string */
   2176 
   2177 
   2178  /*
   2179   * Range check input...
   2180   */
   2181 
   2182   DEBUG_printf(("httpReadRequest(http=%p, uri=%p, urilen=" CUPS_LLFMT ")", (void *)http, (void *)uri, CUPS_LLCAST urilen));
   2183 
   2184   if (uri)
   2185     *uri = '\0';
   2186 
   2187   if (!http || !uri || urilen < 1)
   2188   {
   2189     DEBUG_puts("1httpReadRequest: Bad arguments, returning HTTP_STATE_ERROR.");
   2190     return (HTTP_STATE_ERROR);
   2191   }
   2192   else if (http->state != HTTP_STATE_WAITING)
   2193   {
   2194     DEBUG_printf(("1httpReadRequest: Bad state %s, returning HTTP_STATE_ERROR.",
   2195                   httpStateString(http->state)));
   2196     return (HTTP_STATE_ERROR);
   2197   }
   2198 
   2199  /*
   2200   * Reset state...
   2201   */
   2202 
   2203   httpClearFields(http);
   2204 
   2205   http->activity       = time(NULL);
   2206   http->data_encoding  = HTTP_ENCODING_FIELDS;
   2207   http->data_remaining = 0;
   2208   http->keep_alive     = HTTP_KEEPALIVE_OFF;
   2209   http->status         = HTTP_STATUS_OK;
   2210   http->version        = HTTP_VERSION_1_1;
   2211 
   2212  /*
   2213   * Read a line from the socket...
   2214   */
   2215 
   2216   if (!httpGets(line, sizeof(line), http))
   2217   {
   2218     DEBUG_puts("1httpReadRequest: Unable to read, returning HTTP_STATE_ERROR");
   2219     return (HTTP_STATE_ERROR);
   2220   }
   2221 
   2222   if (!line[0])
   2223   {
   2224     DEBUG_puts("1httpReadRequest: Blank line, returning HTTP_STATE_WAITING");
   2225     return (HTTP_STATE_WAITING);
   2226   }
   2227 
   2228   DEBUG_printf(("1httpReadRequest: %s", line));
   2229 
   2230  /*
   2231   * Parse it...
   2232   */
   2233 
   2234   req_method = line;
   2235   req_uri    = line;
   2236 
   2237   while (*req_uri && !isspace(*req_uri & 255))
   2238     req_uri ++;
   2239 
   2240   if (!*req_uri)
   2241   {
   2242     DEBUG_puts("1httpReadRequest: No request URI.");
   2243     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No request URI."), 1);
   2244     return (HTTP_STATE_ERROR);
   2245   }
   2246 
   2247   *req_uri++ = '\0';
   2248 
   2249   while (*req_uri && isspace(*req_uri & 255))
   2250     req_uri ++;
   2251 
   2252   req_version = req_uri;
   2253 
   2254   while (*req_version && !isspace(*req_version & 255))
   2255     req_version ++;
   2256 
   2257   if (!*req_version)
   2258   {
   2259     DEBUG_puts("1httpReadRequest: No request protocol version.");
   2260     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No request protocol version."), 1);
   2261     return (HTTP_STATE_ERROR);
   2262   }
   2263 
   2264   *req_version++ = '\0';
   2265 
   2266   while (*req_version && isspace(*req_version & 255))
   2267     req_version ++;
   2268 
   2269  /*
   2270   * Validate...
   2271   */
   2272 
   2273   if (!strcmp(req_method, "OPTIONS"))
   2274     http->state = HTTP_STATE_OPTIONS;
   2275   else if (!strcmp(req_method, "GET"))
   2276     http->state = HTTP_STATE_GET;
   2277   else if (!strcmp(req_method, "HEAD"))
   2278     http->state = HTTP_STATE_HEAD;
   2279   else if (!strcmp(req_method, "POST"))
   2280     http->state = HTTP_STATE_POST;
   2281   else if (!strcmp(req_method, "PUT"))
   2282     http->state = HTTP_STATE_PUT;
   2283   else if (!strcmp(req_method, "DELETE"))
   2284     http->state = HTTP_STATE_DELETE;
   2285   else if (!strcmp(req_method, "TRACE"))
   2286     http->state = HTTP_STATE_TRACE;
   2287   else if (!strcmp(req_method, "CONNECT"))
   2288     http->state = HTTP_STATE_CONNECT;
   2289   else
   2290   {
   2291     DEBUG_printf(("1httpReadRequest: Unknown method \"%s\".", req_method));
   2292     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown request method."), 1);
   2293     return (HTTP_STATE_UNKNOWN_METHOD);
   2294   }
   2295 
   2296   DEBUG_printf(("1httpReadRequest: Set state to %s.",
   2297                 httpStateString(http->state)));
   2298 
   2299   if (!strcmp(req_version, "HTTP/1.0"))
   2300   {
   2301     http->version    = HTTP_VERSION_1_0;
   2302     http->keep_alive = HTTP_KEEPALIVE_OFF;
   2303   }
   2304   else if (!strcmp(req_version, "HTTP/1.1"))
   2305   {
   2306     http->version    = HTTP_VERSION_1_1;
   2307     http->keep_alive = HTTP_KEEPALIVE_ON;
   2308   }
   2309   else
   2310   {
   2311     DEBUG_printf(("1httpReadRequest: Unknown version \"%s\".", req_version));
   2312     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown request version."), 1);
   2313     return (HTTP_STATE_UNKNOWN_VERSION);
   2314   }
   2315 
   2316   DEBUG_printf(("1httpReadRequest: URI is \"%s\".", req_uri));
   2317   strlcpy(uri, req_uri, urilen);
   2318 
   2319   return (http->state);
   2320 }
   2321 
   2322 
   2323 /*
   2324  * 'httpReconnect()' - Reconnect to a HTTP server.
   2325  *
   2326  * This function is deprecated. Please use the @link httpReconnect2@ function
   2327  * instead.
   2328  *
   2329  * @deprecated@
   2330  */
   2331 
   2332 int					/* O - 0 on success, non-zero on failure */
   2333 httpReconnect(http_t *http)		/* I - HTTP connection */
   2334 {
   2335   DEBUG_printf(("httpReconnect(http=%p)", (void *)http));
   2336 
   2337   return (httpReconnect2(http, 30000, NULL));
   2338 }
   2339 
   2340 
   2341 /*
   2342  * 'httpReconnect2()' - Reconnect to a HTTP server with timeout and optional
   2343  *                      cancel.
   2344  */
   2345 
   2346 int					/* O - 0 on success, non-zero on failure */
   2347 httpReconnect2(http_t *http,		/* I - HTTP connection */
   2348 	       int    msec,		/* I - Timeout in milliseconds */
   2349 	       int    *cancel)		/* I - Pointer to "cancel" variable */
   2350 {
   2351   http_addrlist_t	*addr;		/* Connected address */
   2352 #ifdef DEBUG
   2353   http_addrlist_t	*current;	/* Current address */
   2354   char			temp[256];	/* Temporary address string */
   2355 #endif /* DEBUG */
   2356 
   2357 
   2358   DEBUG_printf(("httpReconnect2(http=%p, msec=%d, cancel=%p)", (void *)http, msec, (void *)cancel));
   2359 
   2360   if (!http)
   2361   {
   2362     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
   2363     return (-1);
   2364   }
   2365 
   2366 #ifdef HAVE_SSL
   2367   if (http->tls)
   2368   {
   2369     DEBUG_puts("2httpReconnect2: Shutting down SSL/TLS...");
   2370     _httpTLSStop(http);
   2371   }
   2372 #endif /* HAVE_SSL */
   2373 
   2374  /*
   2375   * Close any previously open socket...
   2376   */
   2377 
   2378   if (http->fd >= 0)
   2379   {
   2380     DEBUG_printf(("2httpReconnect2: Closing socket %d...", http->fd));
   2381 
   2382     httpAddrClose(NULL, http->fd);
   2383 
   2384     http->fd = -1;
   2385   }
   2386 
   2387  /*
   2388   * Reset all state (except fields, which may be reused)...
   2389   */
   2390 
   2391   http->state           = HTTP_STATE_WAITING;
   2392   http->version         = HTTP_VERSION_1_1;
   2393   http->keep_alive      = HTTP_KEEPALIVE_OFF;
   2394   memset(&http->_hostaddr, 0, sizeof(http->_hostaddr));
   2395   http->data_encoding   = HTTP_ENCODING_FIELDS;
   2396   http->_data_remaining = 0;
   2397   http->used            = 0;
   2398   http->data_remaining  = 0;
   2399   http->hostaddr        = NULL;
   2400   http->wused           = 0;
   2401 
   2402  /*
   2403   * Connect to the server...
   2404   */
   2405 
   2406 #ifdef DEBUG
   2407   for (current = http->addrlist; current; current = current->next)
   2408     DEBUG_printf(("2httpReconnect2: Address %s:%d",
   2409                   httpAddrString(&(current->addr), temp, sizeof(temp)),
   2410                   httpAddrPort(&(current->addr))));
   2411 #endif /* DEBUG */
   2412 
   2413   if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec, cancel)) == NULL)
   2414   {
   2415    /*
   2416     * Unable to connect...
   2417     */
   2418 
   2419 #ifdef WIN32
   2420     http->error  = WSAGetLastError();
   2421 #else
   2422     http->error  = errno;
   2423 #endif /* WIN32 */
   2424     http->status = HTTP_STATUS_ERROR;
   2425 
   2426     DEBUG_printf(("1httpReconnect2: httpAddrConnect failed: %s",
   2427                   strerror(http->error)));
   2428 
   2429     return (-1);
   2430   }
   2431 
   2432   DEBUG_printf(("2httpReconnect2: New socket=%d", http->fd));
   2433 
   2434   if (http->timeout_value > 0)
   2435     http_set_timeout(http->fd, http->timeout_value);
   2436 
   2437   http->hostaddr = &(addr->addr);
   2438   http->error    = 0;
   2439 
   2440 #ifdef HAVE_SSL
   2441   if (http->encryption == HTTP_ENCRYPTION_ALWAYS)
   2442   {
   2443    /*
   2444     * Always do encryption via SSL.
   2445     */
   2446 
   2447     if (_httpTLSStart(http) != 0)
   2448     {
   2449       httpAddrClose(NULL, http->fd);
   2450 
   2451       return (-1);
   2452     }
   2453   }
   2454   else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls_upgrade)
   2455     return (http_tls_upgrade(http));
   2456 #endif /* HAVE_SSL */
   2457 
   2458   DEBUG_printf(("1httpReconnect2: Connected to %s:%d...",
   2459 		httpAddrString(http->hostaddr, temp, sizeof(temp)),
   2460 		httpAddrPort(http->hostaddr)));
   2461 
   2462   return (0);
   2463 }
   2464 
   2465 
   2466 /*
   2467  * 'httpSetAuthString()' - Set the current authorization string.
   2468  *
   2469  * This function just stores a copy of the current authorization string in
   2470  * the HTTP connection object.  You must still call httpSetField() to set
   2471  * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
   2472  * httpHead(), httpOptions(), httpPost, or httpPut().
   2473  *
   2474  * @since CUPS 1.3/macOS 10.5@
   2475  */
   2476 
   2477 void
   2478 httpSetAuthString(http_t     *http,	/* I - HTTP connection */
   2479                   const char *scheme,	/* I - Auth scheme (NULL to clear it) */
   2480 		  const char *data)	/* I - Auth data (NULL for none) */
   2481 {
   2482  /*
   2483   * Range check input...
   2484   */
   2485 
   2486   if (!http)
   2487     return;
   2488 
   2489   if (http->authstring && http->authstring != http->_authstring)
   2490     free(http->authstring);
   2491 
   2492   http->authstring = http->_authstring;
   2493 
   2494   if (scheme)
   2495   {
   2496    /*
   2497     * Set the current authorization string...
   2498     */
   2499 
   2500     size_t len = strlen(scheme) + (data ? strlen(data) + 1 : 0) + 1;
   2501     char *temp;
   2502 
   2503     if (len > sizeof(http->_authstring))
   2504     {
   2505       if ((temp = malloc(len)) == NULL)
   2506         len = sizeof(http->_authstring);
   2507       else
   2508         http->authstring = temp;
   2509     }
   2510 
   2511     if (data)
   2512       snprintf(http->authstring, len, "%s %s", scheme, data);
   2513     else
   2514       strlcpy(http->authstring, scheme, len);
   2515   }
   2516   else
   2517   {
   2518    /*
   2519     * Clear the current authorization string...
   2520     */
   2521 
   2522     http->_authstring[0] = '\0';
   2523   }
   2524 }
   2525 
   2526 
   2527 /*
   2528  * 'httpSetCredentials()' - Set the credentials associated with an encrypted
   2529  *			    connection.
   2530  *
   2531  * @since CUPS 1.5/macOS 10.7@
   2532  */
   2533 
   2534 int						/* O - Status of call (0 = success) */
   2535 httpSetCredentials(http_t	*http,		/* I - HTTP connection */
   2536 		   cups_array_t *credentials)	/* I - Array of credentials */
   2537 {
   2538   if (!http || cupsArrayCount(credentials) < 1)
   2539     return (-1);
   2540 
   2541 #ifdef HAVE_SSL
   2542   _httpFreeCredentials(http->tls_credentials);
   2543 
   2544   http->tls_credentials = _httpCreateCredentials(credentials);
   2545 #endif /* HAVE_SSL */
   2546 
   2547   return (http->tls_credentials ? 0 : -1);
   2548 }
   2549 
   2550 
   2551 /*
   2552  * 'httpSetCookie()' - Set the cookie value(s).
   2553  *
   2554  * @since CUPS 1.1.19/macOS 10.3@
   2555  */
   2556 
   2557 void
   2558 httpSetCookie(http_t     *http,		/* I - Connection */
   2559               const char *cookie)	/* I - Cookie string */
   2560 {
   2561   if (!http)
   2562     return;
   2563 
   2564   if (http->cookie)
   2565     free(http->cookie);
   2566 
   2567   if (cookie)
   2568     http->cookie = strdup(cookie);
   2569   else
   2570     http->cookie = NULL;
   2571 }
   2572 
   2573 
   2574 /*
   2575  * 'httpSetDefaultField()' - Set the default value of an HTTP header.
   2576  *
   2577  * Currently only @code HTTP_FIELD_ACCEPT_ENCODING@, @code HTTP_FIELD_SERVER@,
   2578  * and @code HTTP_FIELD_USER_AGENT@ can be set.
   2579  *
   2580  * @since CUPS 1.7/macOS 10.9@
   2581  */
   2582 
   2583 void
   2584 httpSetDefaultField(http_t       *http,	/* I - HTTP connection */
   2585                     http_field_t field,	/* I - Field index */
   2586 	            const char   *value)/* I - Value */
   2587 {
   2588   DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")", (void *)http, field, http_fields[field], value));
   2589 
   2590   if (!http)
   2591     return;
   2592 
   2593   switch (field)
   2594   {
   2595     case HTTP_FIELD_ACCEPT_ENCODING :
   2596         if (http->default_accept_encoding)
   2597           _cupsStrFree(http->default_accept_encoding);
   2598 
   2599         http->default_accept_encoding = value ? _cupsStrAlloc(value) : NULL;
   2600         break;
   2601 
   2602     case HTTP_FIELD_SERVER :
   2603         if (http->default_server)
   2604           _cupsStrFree(http->default_server);
   2605 
   2606         http->default_server = value ? _cupsStrAlloc(value) : NULL;
   2607         break;
   2608 
   2609     case HTTP_FIELD_USER_AGENT :
   2610         if (http->default_user_agent)
   2611           _cupsStrFree(http->default_user_agent);
   2612 
   2613         http->default_user_agent = value ? _cupsStrAlloc(value) : NULL;
   2614         break;
   2615 
   2616     default :
   2617         DEBUG_puts("1httpSetDefaultField: Ignored.");
   2618 	break;
   2619   }
   2620 }
   2621 
   2622 
   2623 /*
   2624  * 'httpSetExpect()' - Set the Expect: header in a request.
   2625  *
   2626  * Currently only @code HTTP_STATUS_CONTINUE@ is supported for the "expect"
   2627  * argument.
   2628  *
   2629  * @since CUPS 1.2/macOS 10.5@
   2630  */
   2631 
   2632 void
   2633 httpSetExpect(http_t        *http,	/* I - HTTP connection */
   2634               http_status_t expect)	/* I - HTTP status to expect
   2635               				       (@code HTTP_STATUS_CONTINUE@) */
   2636 {
   2637   DEBUG_printf(("httpSetExpect(http=%p, expect=%d)", (void *)http, expect));
   2638 
   2639   if (http)
   2640     http->expect = expect;
   2641 }
   2642 
   2643 
   2644 /*
   2645  * 'httpSetField()' - Set the value of an HTTP header.
   2646  */
   2647 
   2648 void
   2649 httpSetField(http_t       *http,	/* I - HTTP connection */
   2650              http_field_t field,	/* I - Field index */
   2651 	     const char   *value)	/* I - Value */
   2652 {
   2653   DEBUG_printf(("httpSetField(http=%p, field=%d(%s), value=\"%s\")", (void *)http, field, http_fields[field], value));
   2654 
   2655   if (http == NULL ||
   2656       field < HTTP_FIELD_ACCEPT_LANGUAGE ||
   2657       field >= HTTP_FIELD_MAX ||
   2658       value == NULL)
   2659     return;
   2660 
   2661   switch (field)
   2662   {
   2663     case HTTP_FIELD_ACCEPT_ENCODING :
   2664         if (http->accept_encoding)
   2665           _cupsStrFree(http->accept_encoding);
   2666 
   2667         http->accept_encoding = _cupsStrAlloc(value);
   2668         break;
   2669 
   2670     case HTTP_FIELD_ALLOW :
   2671         if (http->allow)
   2672           _cupsStrFree(http->allow);
   2673 
   2674         http->allow = _cupsStrAlloc(value);
   2675         break;
   2676 
   2677     case HTTP_FIELD_SERVER :
   2678         if (http->server)
   2679           _cupsStrFree(http->server);
   2680 
   2681         http->server = _cupsStrAlloc(value);
   2682         break;
   2683 
   2684     case HTTP_FIELD_WWW_AUTHENTICATE :
   2685        /* CUPS STR #4503 - don't override WWW-Authenticate for unknown auth schemes */
   2686         if (http->fields[HTTP_FIELD_WWW_AUTHENTICATE][0] &&
   2687 	    _cups_strncasecmp(value, "Basic ", 6) &&
   2688 	    _cups_strncasecmp(value, "Digest ", 7) &&
   2689 	    _cups_strncasecmp(value, "Negotiate ", 10))
   2690 	{
   2691 	  DEBUG_printf(("1httpSetField: Ignoring unknown auth scheme in \"%s\".", value));
   2692           return;
   2693 	}
   2694 
   2695 	/* Fall through to copy */
   2696 
   2697     default :
   2698 	strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
   2699 	break;
   2700   }
   2701 
   2702   if (field == HTTP_FIELD_AUTHORIZATION)
   2703   {
   2704    /*
   2705     * Special case for Authorization: as its contents can be
   2706     * longer than HTTP_MAX_VALUE
   2707     */
   2708 
   2709     if (http->field_authorization)
   2710       free(http->field_authorization);
   2711 
   2712     http->field_authorization = strdup(value);
   2713   }
   2714   else if (field == HTTP_FIELD_HOST)
   2715   {
   2716    /*
   2717     * Special-case for Host: as we don't want a trailing "." on the hostname and
   2718     * need to bracket IPv6 numeric addresses.
   2719     */
   2720 
   2721     char *ptr = strchr(value, ':');
   2722 
   2723     if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
   2724     {
   2725      /*
   2726       * Bracket IPv6 numeric addresses...
   2727       *
   2728       * This is slightly inefficient (basically copying twice), but is an edge
   2729       * case and not worth optimizing...
   2730       */
   2731 
   2732       snprintf(http->fields[HTTP_FIELD_HOST],
   2733                sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
   2734     }
   2735     else
   2736     {
   2737      /*
   2738       * Check for a trailing dot on the hostname...
   2739       */
   2740 
   2741       ptr = http->fields[HTTP_FIELD_HOST];
   2742 
   2743       if (*ptr)
   2744       {
   2745 	ptr += strlen(ptr) - 1;
   2746 
   2747 	if (*ptr == '.')
   2748 	  *ptr = '\0';
   2749       }
   2750     }
   2751   }
   2752 #ifdef HAVE_LIBZ
   2753   else if (field == HTTP_FIELD_CONTENT_ENCODING &&
   2754            http->data_encoding != HTTP_ENCODING_FIELDS)
   2755   {
   2756     DEBUG_puts("1httpSetField: Calling http_content_coding_start.");
   2757     http_content_coding_start(http, value);
   2758   }
   2759 #endif /* HAVE_LIBZ */
   2760 }
   2761 
   2762 
   2763 /*
   2764  * 'httpSetKeepAlive()' - Set the current Keep-Alive state of a connection.
   2765  *
   2766  * @since CUPS 2.0/OS 10.10@
   2767  */
   2768 
   2769 void
   2770 httpSetKeepAlive(
   2771     http_t           *http,		/* I - HTTP connection */
   2772     http_keepalive_t keep_alive)	/* I - New Keep-Alive value */
   2773 {
   2774   if (http)
   2775     http->keep_alive = keep_alive;
   2776 }
   2777 
   2778 
   2779 /*
   2780  * 'httpSetLength()' - Set the content-length and content-encoding.
   2781  *
   2782  * @since CUPS 1.2/macOS 10.5@
   2783  */
   2784 
   2785 void
   2786 httpSetLength(http_t *http,		/* I - HTTP connection */
   2787               size_t length)		/* I - Length (0 for chunked) */
   2788 {
   2789   DEBUG_printf(("httpSetLength(http=%p, length=" CUPS_LLFMT ")", (void *)http, CUPS_LLCAST length));
   2790 
   2791   if (!http)
   2792     return;
   2793 
   2794   if (!length)
   2795   {
   2796     strlcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked",
   2797             HTTP_MAX_VALUE);
   2798     http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
   2799   }
   2800   else
   2801   {
   2802     http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
   2803     snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
   2804              CUPS_LLFMT, CUPS_LLCAST length);
   2805   }
   2806 }
   2807 
   2808 
   2809 /*
   2810  * 'httpSetTimeout()' - Set read/write timeouts and an optional callback.
   2811  *
   2812  * The optional timeout callback receives both the HTTP connection and a user
   2813  * data pointer and must return 1 to continue or 0 to error (time) out.
   2814  *
   2815  * @since CUPS 1.5/macOS 10.7@
   2816  */
   2817 
   2818 void
   2819 httpSetTimeout(
   2820     http_t            *http,		/* I - HTTP connection */
   2821     double            timeout,		/* I - Number of seconds for timeout,
   2822                                                must be greater than 0 */
   2823     http_timeout_cb_t cb,		/* I - Callback function or NULL */
   2824     void              *user_data)	/* I - User data pointer */
   2825 {
   2826   if (!http || timeout <= 0.0)
   2827     return;
   2828 
   2829   http->timeout_cb    = cb;
   2830   http->timeout_data  = user_data;
   2831   http->timeout_value = timeout;
   2832 
   2833   if (http->fd >= 0)
   2834     http_set_timeout(http->fd, timeout);
   2835 
   2836   http_set_wait(http);
   2837 }
   2838 
   2839 
   2840 /*
   2841  * 'httpShutdown()' - Shutdown one side of an HTTP connection.
   2842  *
   2843  * @since CUPS 2.0/OS 10.10@
   2844  */
   2845 
   2846 void
   2847 httpShutdown(http_t *http)		/* I - HTTP connection */
   2848 {
   2849   if (!http || http->fd < 0)
   2850     return;
   2851 
   2852 #ifdef HAVE_SSL
   2853   if (http->tls)
   2854     _httpTLSStop(http);
   2855 #endif /* HAVE_SSL */
   2856 
   2857 #ifdef WIN32
   2858   shutdown(http->fd, SD_RECEIVE);	/* Microsoft-ism... */
   2859 #else
   2860   shutdown(http->fd, SHUT_RD);
   2861 #endif /* WIN32 */
   2862 }
   2863 
   2864 
   2865 /*
   2866  * 'httpTrace()' - Send an TRACE request to the server.
   2867  */
   2868 
   2869 int					/* O - Status of call (0 = success) */
   2870 httpTrace(http_t     *http,		/* I - HTTP connection */
   2871           const char *uri)		/* I - URI for trace */
   2872 {
   2873   return (http_send(http, HTTP_STATE_TRACE, uri));
   2874 }
   2875 
   2876 
   2877 /*
   2878  * '_httpUpdate()' - Update the current HTTP status for incoming data.
   2879  *
   2880  * Note: Unlike httpUpdate(), this function does not flush pending write data
   2881  * and only retrieves a single status line from the HTTP connection.
   2882  */
   2883 
   2884 int					/* O - 1 to continue, 0 to stop */
   2885 _httpUpdate(http_t        *http,	/* I - HTTP connection */
   2886             http_status_t *status)	/* O - Current HTTP status */
   2887 {
   2888   char		line[32768],		/* Line from connection... */
   2889 		*value;			/* Pointer to value on line */
   2890   http_field_t	field;			/* Field index */
   2891   int		major, minor;		/* HTTP version numbers */
   2892 
   2893 
   2894   DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", (void *)http, (void *)status, httpStateString(http->state)));
   2895 
   2896  /*
   2897   * Grab a single line from the connection...
   2898   */
   2899 
   2900   if (!httpGets(line, sizeof(line), http))
   2901   {
   2902     *status = HTTP_STATUS_ERROR;
   2903     return (0);
   2904   }
   2905 
   2906   DEBUG_printf(("2_httpUpdate: Got \"%s\"", line));
   2907 
   2908   if (line[0] == '\0')
   2909   {
   2910    /*
   2911     * Blank line means the start of the data section (if any).  Return
   2912     * the result code, too...
   2913     *
   2914     * If we get status 100 (HTTP_STATUS_CONTINUE), then we *don't* change
   2915     * states.  Instead, we just return HTTP_STATUS_CONTINUE to the caller and
   2916     * keep on tryin'...
   2917     */
   2918 
   2919     if (http->status == HTTP_STATUS_CONTINUE)
   2920     {
   2921       *status = http->status;
   2922       return (0);
   2923     }
   2924 
   2925     if (http->status < HTTP_STATUS_BAD_REQUEST)
   2926       http->digest_tries = 0;
   2927 
   2928 #ifdef HAVE_SSL
   2929     if (http->status == HTTP_STATUS_SWITCHING_PROTOCOLS && !http->tls)
   2930     {
   2931       if (_httpTLSStart(http) != 0)
   2932       {
   2933         httpAddrClose(NULL, http->fd);
   2934 
   2935 	*status = http->status = HTTP_STATUS_ERROR;
   2936 	return (0);
   2937       }
   2938 
   2939       *status = HTTP_STATUS_CONTINUE;
   2940       return (0);
   2941     }
   2942 #endif /* HAVE_SSL */
   2943 
   2944     if (http_set_length(http) < 0)
   2945     {
   2946       DEBUG_puts("1_httpUpdate: Bad Content-Length.");
   2947       http->error  = EINVAL;
   2948       http->status = *status = HTTP_STATUS_ERROR;
   2949       return (0);
   2950     }
   2951 
   2952     switch (http->state)
   2953     {
   2954       case HTTP_STATE_GET :
   2955       case HTTP_STATE_POST :
   2956       case HTTP_STATE_POST_RECV :
   2957       case HTTP_STATE_PUT :
   2958 	  http->state ++;
   2959 
   2960 	  DEBUG_printf(("1_httpUpdate: Set state to %s.",
   2961 	                httpStateString(http->state)));
   2962 
   2963       case HTTP_STATE_POST_SEND :
   2964       case HTTP_STATE_HEAD :
   2965 	  break;
   2966 
   2967       default :
   2968 	  http->state = HTTP_STATE_WAITING;
   2969 
   2970 	  DEBUG_puts("1_httpUpdate: Reset state to HTTP_STATE_WAITING.");
   2971 	  break;
   2972     }
   2973 
   2974 #ifdef HAVE_LIBZ
   2975     DEBUG_puts("1_httpUpdate: Calling http_content_coding_start.");
   2976     http_content_coding_start(http,
   2977                               httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
   2978 #endif /* HAVE_LIBZ */
   2979 
   2980     *status = http->status;
   2981     return (0);
   2982   }
   2983   else if (!strncmp(line, "HTTP/", 5) && http->mode == _HTTP_MODE_CLIENT)
   2984   {
   2985    /*
   2986     * Got the beginning of a response...
   2987     */
   2988 
   2989     int	intstatus;			/* Status value as an integer */
   2990 
   2991     if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3)
   2992     {
   2993       *status = http->status = HTTP_STATUS_ERROR;
   2994       return (0);
   2995     }
   2996 
   2997     httpClearFields(http);
   2998 
   2999     http->version = (http_version_t)(major * 100 + minor);
   3000     *status       = http->status = (http_status_t)intstatus;
   3001   }
   3002   else if ((value = strchr(line, ':')) != NULL)
   3003   {
   3004    /*
   3005     * Got a value...
   3006     */
   3007 
   3008     *value++ = '\0';
   3009     while (_cups_isspace(*value))
   3010       value ++;
   3011 
   3012     DEBUG_printf(("1_httpUpdate: Header %s: %s", line, value));
   3013 
   3014    /*
   3015     * Be tolerants of servers that send unknown attribute fields...
   3016     */
   3017 
   3018     if (!_cups_strcasecmp(line, "expect"))
   3019     {
   3020      /*
   3021       * "Expect: 100-continue" or similar...
   3022       */
   3023 
   3024       http->expect = (http_status_t)atoi(value);
   3025     }
   3026     else if (!_cups_strcasecmp(line, "cookie"))
   3027     {
   3028      /*
   3029       * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
   3030       */
   3031 
   3032       httpSetCookie(http, value);
   3033     }
   3034     else if ((field = httpFieldValue(line)) != HTTP_FIELD_UNKNOWN)
   3035       httpSetField(http, field, value);
   3036 #ifdef DEBUG
   3037     else
   3038       DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line));
   3039 #endif /* DEBUG */
   3040   }
   3041   else
   3042   {
   3043     DEBUG_printf(("1_httpUpdate: Bad response line \"%s\"!", line));
   3044     http->error  = EINVAL;
   3045     http->status = *status = HTTP_STATUS_ERROR;
   3046     return (0);
   3047   }
   3048 
   3049   return (1);
   3050 }
   3051 
   3052 
   3053 /*
   3054  * 'httpUpdate()' - Update the current HTTP state for incoming data.
   3055  */
   3056 
   3057 http_status_t				/* O - HTTP status */
   3058 httpUpdate(http_t *http)		/* I - HTTP connection */
   3059 {
   3060   http_status_t	status;			/* Request status */
   3061 
   3062 
   3063   DEBUG_printf(("httpUpdate(http=%p), state=%s", (void *)http, httpStateString(http->state)));
   3064 
   3065  /*
   3066   * Flush pending data, if any...
   3067   */
   3068 
   3069   if (http->wused)
   3070   {
   3071     DEBUG_puts("2httpUpdate: flushing buffer...");
   3072 
   3073     if (httpFlushWrite(http) < 0)
   3074       return (HTTP_STATUS_ERROR);
   3075   }
   3076 
   3077  /*
   3078   * If we haven't issued any commands, then there is nothing to "update"...
   3079   */
   3080 
   3081   if (http->state == HTTP_STATE_WAITING)
   3082     return (HTTP_STATUS_CONTINUE);
   3083 
   3084  /*
   3085   * Grab all of the lines we can from the connection...
   3086   */
   3087 
   3088   while (_httpUpdate(http, &status));
   3089 
   3090  /*
   3091   * See if there was an error...
   3092   */
   3093 
   3094   if (http->error == EPIPE && http->status > HTTP_STATUS_CONTINUE)
   3095   {
   3096     DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
   3097     return (http->status);
   3098   }
   3099 
   3100   if (http->error)
   3101   {
   3102     DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
   3103                   strerror(http->error)));
   3104     http->status = HTTP_STATUS_ERROR;
   3105     return (HTTP_STATUS_ERROR);
   3106   }
   3107 
   3108  /*
   3109   * Return the current status...
   3110   */
   3111 
   3112   return (status);
   3113 }
   3114 
   3115 
   3116 /*
   3117  * '_httpWait()' - Wait for data available on a connection (no flush).
   3118  */
   3119 
   3120 int					/* O - 1 if data is available, 0 otherwise */
   3121 _httpWait(http_t *http,			/* I - HTTP connection */
   3122           int    msec,			/* I - Milliseconds to wait */
   3123 	  int    usessl)		/* I - Use SSL context? */
   3124 {
   3125 #ifdef HAVE_POLL
   3126   struct pollfd		pfd;		/* Polled file descriptor */
   3127 #else
   3128   fd_set		input_set;	/* select() input set */
   3129   struct timeval	timeout;	/* Timeout */
   3130 #endif /* HAVE_POLL */
   3131   int			nfds;		/* Result from select()/poll() */
   3132 
   3133 
   3134   DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", (void *)http, msec, usessl));
   3135 
   3136   if (http->fd < 0)
   3137   {
   3138     DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd));
   3139     return (0);
   3140   }
   3141 
   3142  /*
   3143   * Check the SSL/TLS buffers for data first...
   3144   */
   3145 
   3146 #ifdef HAVE_SSL
   3147   if (http->tls && _httpTLSPending(http))
   3148   {
   3149     DEBUG_puts("5_httpWait: Return 1 since there is pending TLS data.");
   3150     return (1);
   3151   }
   3152 #endif /* HAVE_SSL */
   3153 
   3154  /*
   3155   * Then try doing a select() or poll() to poll the socket...
   3156   */
   3157 
   3158 #ifdef HAVE_POLL
   3159   pfd.fd     = http->fd;
   3160   pfd.events = POLLIN;
   3161 
   3162   do
   3163   {
   3164     nfds = poll(&pfd, 1, msec);
   3165   }
   3166   while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
   3167 
   3168 #else
   3169   do
   3170   {
   3171     FD_ZERO(&input_set);
   3172     FD_SET(http->fd, &input_set);
   3173 
   3174     DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
   3175 
   3176     if (msec >= 0)
   3177     {
   3178       timeout.tv_sec  = msec / 1000;
   3179       timeout.tv_usec = (msec % 1000) * 1000;
   3180 
   3181       nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
   3182     }
   3183     else
   3184       nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
   3185 
   3186     DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
   3187   }
   3188 #  ifdef WIN32
   3189   while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
   3190                       WSAGetLastError() == WSAEWOULDBLOCK));
   3191 #  else
   3192   while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
   3193 #  endif /* WIN32 */
   3194 #endif /* HAVE_POLL */
   3195 
   3196   DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds,
   3197                 errno));
   3198 
   3199   return (nfds > 0);
   3200 }
   3201 
   3202 
   3203 /*
   3204  * 'httpWait()' - Wait for data available on a connection.
   3205  *
   3206  * @since CUPS 1.1.19/macOS 10.3@
   3207  */
   3208 
   3209 int					/* O - 1 if data is available, 0 otherwise */
   3210 httpWait(http_t *http,			/* I - HTTP connection */
   3211          int    msec)			/* I - Milliseconds to wait */
   3212 {
   3213  /*
   3214   * First see if there is data in the buffer...
   3215   */
   3216 
   3217   DEBUG_printf(("2httpWait(http=%p, msec=%d)", (void *)http, msec));
   3218 
   3219   if (http == NULL)
   3220     return (0);
   3221 
   3222   if (http->used)
   3223   {
   3224     DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
   3225     return (1);
   3226   }
   3227 
   3228 #ifdef HAVE_LIBZ
   3229   if (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in > 0)
   3230   {
   3231     DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
   3232     return (1);
   3233   }
   3234 #endif /* HAVE_LIBZ */
   3235 
   3236  /*
   3237   * Flush pending data, if any...
   3238   */
   3239 
   3240   if (http->wused)
   3241   {
   3242     DEBUG_puts("3httpWait: Flushing write buffer.");
   3243 
   3244     if (httpFlushWrite(http) < 0)
   3245       return (0);
   3246   }
   3247 
   3248  /*
   3249   * If not, check the SSL/TLS buffers and do a select() on the connection...
   3250   */
   3251 
   3252   return (_httpWait(http, msec, 1));
   3253 }
   3254 
   3255 
   3256 /*
   3257  * 'httpWrite()' - Write data to a HTTP connection.
   3258  *
   3259  * This function is deprecated. Use the httpWrite2() function which can
   3260  * write more than 2GB of data.
   3261  *
   3262  * @deprecated@
   3263  */
   3264 
   3265 int					/* O - Number of bytes written */
   3266 httpWrite(http_t     *http,		/* I - HTTP connection */
   3267           const char *buffer,		/* I - Buffer for data */
   3268 	  int        length)		/* I - Number of bytes to write */
   3269 {
   3270   return ((int)httpWrite2(http, buffer, (size_t)length));
   3271 }
   3272 
   3273 
   3274 /*
   3275  * 'httpWrite2()' - Write data to a HTTP connection.
   3276  *
   3277  * @since CUPS 1.2/macOS 10.5@
   3278  */
   3279 
   3280 ssize_t					/* O - Number of bytes written */
   3281 httpWrite2(http_t     *http,		/* I - HTTP connection */
   3282            const char *buffer,		/* I - Buffer for data */
   3283 	   size_t     length)		/* I - Number of bytes to write */
   3284 {
   3285   ssize_t	bytes;			/* Bytes written */
   3286 
   3287 
   3288   DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   3289 
   3290  /*
   3291   * Range check input...
   3292   */
   3293 
   3294   if (!http || !buffer)
   3295   {
   3296     DEBUG_puts("1httpWrite2: Returning -1 due to bad input.");
   3297     return (-1);
   3298   }
   3299 
   3300  /*
   3301   * Mark activity on the connection...
   3302   */
   3303 
   3304   http->activity = time(NULL);
   3305 
   3306  /*
   3307   * Buffer small writes for better performance...
   3308   */
   3309 
   3310 #ifdef HAVE_LIBZ
   3311   if (http->coding == _HTTP_CODING_GZIP || http->coding == _HTTP_CODING_DEFLATE)
   3312   {
   3313     DEBUG_printf(("1httpWrite2: http->coding=%d", http->coding));
   3314 
   3315     if (length == 0)
   3316     {
   3317       http_content_coding_finish(http);
   3318       bytes = 0;
   3319     }
   3320     else
   3321     {
   3322       size_t	slen;			/* Bytes to write */
   3323       ssize_t	sret;			/* Bytes written */
   3324 
   3325       http->stream.next_in   = (Bytef *)buffer;
   3326       http->stream.avail_in  = (uInt)length;
   3327 
   3328       while (deflate(&(http->stream), Z_NO_FLUSH) == Z_OK)
   3329       {
   3330         DEBUG_printf(("1httpWrite2: avail_out=%d", http->stream.avail_out));
   3331 
   3332         if (http->stream.avail_out > 0)
   3333 	  continue;
   3334 
   3335 	slen = _HTTP_MAX_SBUFFER - http->stream.avail_out;
   3336 
   3337         DEBUG_printf(("1httpWrite2: Writing intermediate chunk, len=%d", (int)slen));
   3338 
   3339 	if (slen > 0 && http->data_encoding == HTTP_ENCODING_CHUNKED)
   3340 	  sret = http_write_chunk(http, (char *)http->sbuffer, slen);
   3341 	else if (slen > 0)
   3342 	  sret = http_write(http, (char *)http->sbuffer, slen);
   3343 	else
   3344 	  sret = 0;
   3345 
   3346         if (sret < 0)
   3347 	{
   3348 	  DEBUG_puts("1httpWrite2: Unable to write, returning -1.");
   3349 	  return (-1);
   3350 	}
   3351 
   3352 	http->stream.next_out  = (Bytef *)http->sbuffer;
   3353 	http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER;
   3354       }
   3355 
   3356       bytes = (ssize_t)length;
   3357     }
   3358   }
   3359   else
   3360 #endif /* HAVE_LIBZ */
   3361   if (length > 0)
   3362   {
   3363     if (http->wused && (length + (size_t)http->wused) > sizeof(http->wbuffer))
   3364     {
   3365       DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
   3366                     CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
   3367 
   3368       httpFlushWrite(http);
   3369     }
   3370 
   3371     if ((length + (size_t)http->wused) <= sizeof(http->wbuffer) && length < sizeof(http->wbuffer))
   3372     {
   3373      /*
   3374       * Write to buffer...
   3375       */
   3376 
   3377       DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
   3378                     CUPS_LLCAST length));
   3379 
   3380       memcpy(http->wbuffer + http->wused, buffer, length);
   3381       http->wused += (int)length;
   3382       bytes = (ssize_t)length;
   3383     }
   3384     else
   3385     {
   3386      /*
   3387       * Otherwise write the data directly...
   3388       */
   3389 
   3390       DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
   3391                     CUPS_LLCAST length));
   3392 
   3393       if (http->data_encoding == HTTP_ENCODING_CHUNKED)
   3394 	bytes = (ssize_t)http_write_chunk(http, buffer, length);
   3395       else
   3396 	bytes = (ssize_t)http_write(http, buffer, length);
   3397 
   3398       DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
   3399                     CUPS_LLCAST bytes));
   3400     }
   3401 
   3402     if (http->data_encoding == HTTP_ENCODING_LENGTH)
   3403       http->data_remaining -= bytes;
   3404   }
   3405   else
   3406     bytes = 0;
   3407 
   3408  /*
   3409   * Handle end-of-request processing...
   3410   */
   3411 
   3412   if ((http->data_encoding == HTTP_ENCODING_CHUNKED && length == 0) ||
   3413       (http->data_encoding == HTTP_ENCODING_LENGTH && http->data_remaining == 0))
   3414   {
   3415    /*
   3416     * Finished with the transfer; unless we are sending POST or PUT
   3417     * data, go idle...
   3418     */
   3419 
   3420 #ifdef HAVE_LIBZ
   3421     if (http->coding == _HTTP_CODING_GZIP || http->coding == _HTTP_CODING_DEFLATE)
   3422       http_content_coding_finish(http);
   3423 #endif /* HAVE_LIBZ */
   3424 
   3425     if (http->wused)
   3426     {
   3427       if (httpFlushWrite(http) < 0)
   3428         return (-1);
   3429     }
   3430 
   3431     if (http->data_encoding == HTTP_ENCODING_CHUNKED)
   3432     {
   3433      /*
   3434       * Send a 0-length chunk at the end of the request...
   3435       */
   3436 
   3437       http_write(http, "0\r\n\r\n", 5);
   3438 
   3439      /*
   3440       * Reset the data state...
   3441       */
   3442 
   3443       http->data_encoding  = HTTP_ENCODING_FIELDS;
   3444       http->data_remaining = 0;
   3445     }
   3446 
   3447     if (http->state == HTTP_STATE_POST_RECV)
   3448       http->state ++;
   3449     else if (http->state == HTTP_STATE_POST_SEND ||
   3450              http->state == HTTP_STATE_GET_SEND)
   3451       http->state = HTTP_STATE_WAITING;
   3452     else
   3453       http->state = HTTP_STATE_STATUS;
   3454 
   3455     DEBUG_printf(("2httpWrite2: Changed state to %s.",
   3456 		  httpStateString(http->state)));
   3457   }
   3458 
   3459   DEBUG_printf(("1httpWrite2: Returning " CUPS_LLFMT ".", CUPS_LLCAST bytes));
   3460 
   3461   return (bytes);
   3462 }
   3463 
   3464 
   3465 /*
   3466  * 'httpWriteResponse()' - Write a HTTP response to a client connection.
   3467  *
   3468  * @since CUPS 1.7/macOS 10.9@
   3469  */
   3470 
   3471 int					/* O - 0 on success, -1 on error */
   3472 httpWriteResponse(http_t        *http,	/* I - HTTP connection */
   3473 		  http_status_t status)	/* I - Status code */
   3474 {
   3475   http_encoding_t	old_encoding;	/* Old data_encoding value */
   3476   off_t			old_remaining;	/* Old data_remaining value */
   3477 
   3478 
   3479  /*
   3480   * Range check input...
   3481   */
   3482 
   3483   DEBUG_printf(("httpWriteResponse(http=%p, status=%d)", (void *)http, status));
   3484 
   3485   if (!http || status < HTTP_STATUS_CONTINUE)
   3486   {
   3487     DEBUG_puts("1httpWriteResponse: Bad input.");
   3488     return (-1);
   3489   }
   3490 
   3491  /*
   3492   * Set the various standard fields if they aren't already...
   3493   */
   3494 
   3495   if (!http->fields[HTTP_FIELD_DATE][0])
   3496     httpSetField(http, HTTP_FIELD_DATE, httpGetDateString(time(NULL)));
   3497 
   3498   if (status >= HTTP_STATUS_BAD_REQUEST && http->keep_alive)
   3499   {
   3500     http->keep_alive = HTTP_KEEPALIVE_OFF;
   3501     httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "");
   3502   }
   3503 
   3504   if (http->version == HTTP_VERSION_1_1)
   3505   {
   3506     if (!http->fields[HTTP_FIELD_CONNECTION][0])
   3507     {
   3508       if (http->keep_alive)
   3509 	httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive");
   3510       else
   3511 	httpSetField(http, HTTP_FIELD_CONNECTION, "close");
   3512     }
   3513 
   3514     if (http->keep_alive && !http->fields[HTTP_FIELD_KEEP_ALIVE][0])
   3515       httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "timeout=10");
   3516   }
   3517 
   3518 #ifdef HAVE_SSL
   3519   if (status == HTTP_STATUS_UPGRADE_REQUIRED ||
   3520       status == HTTP_STATUS_SWITCHING_PROTOCOLS)
   3521   {
   3522     if (!http->fields[HTTP_FIELD_CONNECTION][0])
   3523       httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
   3524 
   3525     if (!http->fields[HTTP_FIELD_UPGRADE][0])
   3526       httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
   3527 
   3528     if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
   3529       httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, "0");
   3530   }
   3531 #endif /* HAVE_SSL */
   3532 
   3533   if (!http->server)
   3534     httpSetField(http, HTTP_FIELD_SERVER,
   3535                  http->default_server ? http->default_server : CUPS_MINIMAL);
   3536 
   3537  /*
   3538   * Set the Accept-Encoding field if it isn't already...
   3539   */
   3540 
   3541   if (!http->accept_encoding)
   3542     httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
   3543                  http->default_accept_encoding ? http->default_accept_encoding :
   3544 #ifdef HAVE_LIBZ
   3545                                                  "gzip, deflate, identity");
   3546 #else
   3547                                                  "identity");
   3548 #endif /* HAVE_LIBZ */
   3549 
   3550  /*
   3551   * Send the response header...
   3552   */
   3553 
   3554   old_encoding        = http->data_encoding;
   3555   old_remaining       = http->data_remaining;
   3556   http->data_encoding = HTTP_ENCODING_FIELDS;
   3557 
   3558   if (httpPrintf(http, "HTTP/%d.%d %d %s\r\n", http->version / 100,
   3559                  http->version % 100, (int)status, httpStatus(status)) < 0)
   3560   {
   3561     http->status = HTTP_STATUS_ERROR;
   3562     return (-1);
   3563   }
   3564 
   3565   if (status != HTTP_STATUS_CONTINUE)
   3566   {
   3567    /*
   3568     * 100 Continue doesn't have the rest of the response headers...
   3569     */
   3570 
   3571     int		i;			/* Looping var */
   3572     const char	*value;			/* Field value */
   3573 
   3574     for (i = 0; i < HTTP_FIELD_MAX; i ++)
   3575     {
   3576       if ((value = httpGetField(http, i)) != NULL && *value)
   3577       {
   3578 	if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
   3579 	{
   3580 	  http->status = HTTP_STATUS_ERROR;
   3581 	  return (-1);
   3582 	}
   3583       }
   3584     }
   3585 
   3586     if (http->cookie)
   3587     {
   3588       if (strchr(http->cookie, ';'))
   3589       {
   3590         if (httpPrintf(http, "Set-Cookie: %s\r\n", http->cookie) < 1)
   3591 	{
   3592 	  http->status = HTTP_STATUS_ERROR;
   3593 	  return (-1);
   3594 	}
   3595       }
   3596       else if (httpPrintf(http, "Set-Cookie: %s; path=/; httponly;%s\r\n", http->cookie, http->tls ? " secure;" : "") < 1)
   3597       {
   3598 	http->status = HTTP_STATUS_ERROR;
   3599 	return (-1);
   3600       }
   3601     }
   3602 
   3603    /*
   3604     * "Click-jacking" defense (STR #4492)...
   3605     */
   3606 
   3607     if (httpPrintf(http, "X-Frame-Options: DENY\r\n"
   3608                          "Content-Security-Policy: frame-ancestors 'none'\r\n") < 1)
   3609     {
   3610       http->status = HTTP_STATUS_ERROR;
   3611       return (-1);
   3612     }
   3613   }
   3614 
   3615   if (httpWrite2(http, "\r\n", 2) < 2)
   3616   {
   3617     http->status = HTTP_STATUS_ERROR;
   3618     return (-1);
   3619   }
   3620 
   3621   if (httpFlushWrite(http) < 0)
   3622   {
   3623     http->status = HTTP_STATUS_ERROR;
   3624     return (-1);
   3625   }
   3626 
   3627   if (status == HTTP_STATUS_CONTINUE ||
   3628       status == HTTP_STATUS_SWITCHING_PROTOCOLS)
   3629   {
   3630    /*
   3631     * Restore the old data_encoding and data_length values...
   3632     */
   3633 
   3634     http->data_encoding  = old_encoding;
   3635     http->data_remaining = old_remaining;
   3636 
   3637     if (old_remaining <= INT_MAX)
   3638       http->_data_remaining = (int)old_remaining;
   3639     else
   3640       http->_data_remaining = INT_MAX;
   3641   }
   3642   else if (http->state == HTTP_STATE_OPTIONS ||
   3643            http->state == HTTP_STATE_HEAD ||
   3644            http->state == HTTP_STATE_PUT ||
   3645            http->state == HTTP_STATE_TRACE ||
   3646            http->state == HTTP_STATE_CONNECT ||
   3647            http->state == HTTP_STATE_STATUS)
   3648   {
   3649     DEBUG_printf(("1httpWriteResponse: Resetting state to HTTP_STATE_WAITING, "
   3650                   "was %s.", httpStateString(http->state)));
   3651     http->state = HTTP_STATE_WAITING;
   3652   }
   3653   else
   3654   {
   3655    /*
   3656     * Force data_encoding and data_length to be set according to the response
   3657     * headers...
   3658     */
   3659 
   3660     http_set_length(http);
   3661 
   3662     if (http->data_encoding == HTTP_ENCODING_LENGTH && http->data_remaining == 0)
   3663     {
   3664       DEBUG_printf(("1httpWriteResponse: Resetting state to HTTP_STATE_WAITING, "
   3665                     "was %s.", httpStateString(http->state)));
   3666       http->state = HTTP_STATE_WAITING;
   3667       return (0);
   3668     }
   3669 
   3670     if (http->state == HTTP_STATE_POST_RECV || http->state == HTTP_STATE_GET)
   3671       http->state ++;
   3672 
   3673 #ifdef HAVE_LIBZ
   3674    /*
   3675     * Then start any content encoding...
   3676     */
   3677 
   3678     DEBUG_puts("1httpWriteResponse: Calling http_content_coding_start.");
   3679     http_content_coding_start(http,
   3680 			      httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
   3681 #endif /* HAVE_LIBZ */
   3682 
   3683   }
   3684 
   3685   return (0);
   3686 }
   3687 
   3688 
   3689 #ifdef HAVE_LIBZ
   3690 /*
   3691  * 'http_content_coding_finish()' - Finish doing any content encoding.
   3692  */
   3693 
   3694 static void
   3695 http_content_coding_finish(
   3696     http_t *http)			/* I - HTTP connection */
   3697 {
   3698   int		zerr;			/* Compression status */
   3699   Byte		dummy[1];		/* Dummy read buffer */
   3700   size_t	bytes;			/* Number of bytes to write */
   3701 
   3702 
   3703   DEBUG_printf(("http_content_coding_finish(http=%p)", (void *)http));
   3704   DEBUG_printf(("1http_content_coding_finishing: http->coding=%d", http->coding));
   3705 
   3706   switch (http->coding)
   3707   {
   3708     case _HTTP_CODING_DEFLATE :
   3709     case _HTTP_CODING_GZIP :
   3710         http->stream.next_in  = dummy;
   3711         http->stream.avail_in = 0;
   3712 
   3713         do
   3714         {
   3715           zerr  = deflate(&(http->stream), Z_FINISH);
   3716 	  bytes = _HTTP_MAX_SBUFFER - http->stream.avail_out;
   3717 
   3718           if (bytes > 0)
   3719 	  {
   3720 	    DEBUG_printf(("1http_content_coding_finish: Writing trailing chunk, len=%d", (int)bytes));
   3721 
   3722 	    if (http->data_encoding == HTTP_ENCODING_CHUNKED)
   3723 	      http_write_chunk(http, (char *)http->sbuffer, bytes);
   3724 	    else
   3725 	      http_write(http, (char *)http->sbuffer, bytes);
   3726           }
   3727 
   3728           http->stream.next_out  = (Bytef *)http->sbuffer;
   3729           http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER;
   3730 	}
   3731         while (zerr == Z_OK);
   3732 
   3733         deflateEnd(&(http->stream));
   3734 
   3735         free(http->sbuffer);
   3736         http->sbuffer = NULL;
   3737 
   3738         if (http->wused)
   3739           httpFlushWrite(http);
   3740         break;
   3741 
   3742     case _HTTP_CODING_INFLATE :
   3743     case _HTTP_CODING_GUNZIP :
   3744         inflateEnd(&(http->stream));
   3745         free(http->sbuffer);
   3746         http->sbuffer = NULL;
   3747         break;
   3748 
   3749     default :
   3750         break;
   3751   }
   3752 
   3753   http->coding = _HTTP_CODING_IDENTITY;
   3754 }
   3755 
   3756 
   3757 /*
   3758  * 'http_content_coding_start()' - Start doing content encoding.
   3759  */
   3760 
   3761 static void
   3762 http_content_coding_start(
   3763     http_t     *http,			/* I - HTTP connection */
   3764     const char *value)			/* I - Value of Content-Encoding */
   3765 {
   3766   int			zerr;		/* Error/status */
   3767   _http_coding_t	coding;		/* Content coding value */
   3768 
   3769 
   3770   DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", (void *)http, value));
   3771 
   3772   if (http->coding != _HTTP_CODING_IDENTITY)
   3773   {
   3774     DEBUG_printf(("1http_content_coding_start: http->coding already %d.",
   3775                   http->coding));
   3776     return;
   3777   }
   3778   else if (!strcmp(value, "x-gzip") || !strcmp(value, "gzip"))
   3779   {
   3780     if (http->state == HTTP_STATE_GET_SEND ||
   3781         http->state == HTTP_STATE_POST_SEND)
   3782       coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_GZIP :
   3783                                                  _HTTP_CODING_GUNZIP;
   3784     else if (http->state == HTTP_STATE_POST_RECV ||
   3785              http->state == HTTP_STATE_PUT_RECV)
   3786       coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_GZIP :
   3787                                                  _HTTP_CODING_GUNZIP;
   3788     else
   3789     {
   3790       DEBUG_puts("1http_content_coding_start: Not doing content coding.");
   3791       return;
   3792     }
   3793   }
   3794   else if (!strcmp(value, "x-deflate") || !strcmp(value, "deflate"))
   3795   {
   3796     if (http->state == HTTP_STATE_GET_SEND ||
   3797         http->state == HTTP_STATE_POST_SEND)
   3798       coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_DEFLATE :
   3799                                                  _HTTP_CODING_INFLATE;
   3800     else if (http->state == HTTP_STATE_POST_RECV ||
   3801              http->state == HTTP_STATE_PUT_RECV)
   3802       coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_DEFLATE :
   3803                                                  _HTTP_CODING_INFLATE;
   3804     else
   3805     {
   3806       DEBUG_puts("1http_content_coding_start: Not doing content coding.");
   3807       return;
   3808     }
   3809   }
   3810   else
   3811   {
   3812     DEBUG_puts("1http_content_coding_start: Not doing content coding.");
   3813     return;
   3814   }
   3815 
   3816   memset(&(http->stream), 0, sizeof(http->stream));
   3817 
   3818   switch (coding)
   3819   {
   3820     case _HTTP_CODING_DEFLATE :
   3821     case _HTTP_CODING_GZIP :
   3822         if (http->wused)
   3823           httpFlushWrite(http);
   3824 
   3825         if ((http->sbuffer = malloc(_HTTP_MAX_SBUFFER)) == NULL)
   3826         {
   3827           http->status = HTTP_STATUS_ERROR;
   3828           http->error  = errno;
   3829           return;
   3830         }
   3831 
   3832        /*
   3833         * Window size for compression is 11 bits - optimal based on PWG Raster
   3834         * sample files on pwg.org.  -11 is raw deflate, 27 is gzip, per ZLIB
   3835         * documentation.
   3836         */
   3837 
   3838         if ((zerr = deflateInit2(&(http->stream), Z_DEFAULT_COMPRESSION,
   3839                                  Z_DEFLATED,
   3840 				 coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7,
   3841 				 Z_DEFAULT_STRATEGY)) < Z_OK)
   3842         {
   3843           http->status = HTTP_STATUS_ERROR;
   3844           http->error  = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
   3845           return;
   3846         }
   3847 
   3848 	http->stream.next_out  = (Bytef *)http->sbuffer;
   3849 	http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER;
   3850         break;
   3851 
   3852     case _HTTP_CODING_INFLATE :
   3853     case _HTTP_CODING_GUNZIP :
   3854         if ((http->sbuffer = malloc(_HTTP_MAX_SBUFFER)) == NULL)
   3855         {
   3856           http->status = HTTP_STATUS_ERROR;
   3857           http->error  = errno;
   3858           return;
   3859         }
   3860 
   3861        /*
   3862         * Window size for decompression is up to 15 bits (maximum supported).
   3863         * -15 is raw inflate, 31 is gunzip, per ZLIB documentation.
   3864         */
   3865 
   3866         if ((zerr = inflateInit2(&(http->stream),
   3867                                  coding == _HTTP_CODING_INFLATE ? -15 : 31))
   3868 		< Z_OK)
   3869         {
   3870           free(http->sbuffer);
   3871           http->sbuffer = NULL;
   3872           http->status  = HTTP_STATUS_ERROR;
   3873           http->error   = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
   3874           return;
   3875         }
   3876 
   3877         http->stream.avail_in = 0;
   3878         http->stream.next_in  = http->sbuffer;
   3879         break;
   3880 
   3881     default :
   3882         break;
   3883   }
   3884 
   3885   http->coding = coding;
   3886 
   3887   DEBUG_printf(("1http_content_coding_start: http->coding now %d.",
   3888 		http->coding));
   3889 }
   3890 #endif /* HAVE_LIBZ */
   3891 
   3892 
   3893 /*
   3894  * 'http_create()' - Create an unconnected HTTP connection.
   3895  */
   3896 
   3897 static http_t *				/* O - HTTP connection */
   3898 http_create(
   3899     const char        *host,		/* I - Hostname */
   3900     int               port,		/* I - Port number */
   3901     http_addrlist_t   *addrlist,	/* I - Address list or NULL */
   3902     int               family,		/* I - Address family or AF_UNSPEC */
   3903     http_encryption_t encryption,	/* I - Encryption to use */
   3904     int               blocking,		/* I - 1 for blocking mode */
   3905     _http_mode_t      mode)		/* I - _HTTP_MODE_CLIENT or _SERVER */
   3906 {
   3907   http_t	*http;			/* New HTTP connection */
   3908   char		service[255];		/* Service name */
   3909   http_addrlist_t *myaddrlist = NULL;	/* My address list */
   3910 
   3911 
   3912   DEBUG_printf(("4http_create(host=\"%s\", port=%d, addrlist=%p, family=%d, encryption=%d, blocking=%d, mode=%d)", host, port, (void *)addrlist, family, encryption, blocking, mode));
   3913 
   3914   if (!host && mode == _HTTP_MODE_CLIENT)
   3915     return (NULL);
   3916 
   3917   httpInitialize();
   3918 
   3919  /*
   3920   * Lookup the host...
   3921   */
   3922 
   3923   if (addrlist)
   3924   {
   3925     myaddrlist = httpAddrCopyList(addrlist);
   3926   }
   3927   else
   3928   {
   3929     snprintf(service, sizeof(service), "%d", port);
   3930 
   3931     myaddrlist = httpAddrGetList(host, family, service);
   3932   }
   3933 
   3934   if (!myaddrlist)
   3935     return (NULL);
   3936 
   3937  /*
   3938   * Allocate memory for the structure...
   3939   */
   3940 
   3941   if ((http = calloc(sizeof(http_t), 1)) == NULL)
   3942   {
   3943     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
   3944     httpAddrFreeList(addrlist);
   3945     return (NULL);
   3946   }
   3947 
   3948  /*
   3949   * Initialize the HTTP data...
   3950   */
   3951 
   3952   http->mode     = mode;
   3953   http->activity = time(NULL);
   3954   http->addrlist = myaddrlist;
   3955   http->blocking = blocking;
   3956   http->fd       = -1;
   3957 #ifdef HAVE_GSSAPI
   3958   http->gssctx   = GSS_C_NO_CONTEXT;
   3959   http->gssname  = GSS_C_NO_NAME;
   3960 #endif /* HAVE_GSSAPI */
   3961   http->status   = HTTP_STATUS_CONTINUE;
   3962   http->version  = HTTP_VERSION_1_1;
   3963 
   3964   if (host)
   3965     strlcpy(http->hostname, host, sizeof(http->hostname));
   3966 
   3967   if (port == 443)			/* Always use encryption for https */
   3968     http->encryption = HTTP_ENCRYPTION_ALWAYS;
   3969   else
   3970     http->encryption = encryption;
   3971 
   3972   http_set_wait(http);
   3973 
   3974  /*
   3975   * Return the new structure...
   3976   */
   3977 
   3978   return (http);
   3979 }
   3980 
   3981 
   3982 #ifdef DEBUG
   3983 /*
   3984  * 'http_debug_hex()' - Do a hex dump of a buffer.
   3985  */
   3986 
   3987 static void
   3988 http_debug_hex(const char *prefix,	/* I - Prefix for line */
   3989                const char *buffer,	/* I - Buffer to dump */
   3990                int        bytes)	/* I - Bytes to dump */
   3991 {
   3992   int	i, j,				/* Looping vars */
   3993 	ch;				/* Current character */
   3994   char	line[255],			/* Line buffer */
   3995 	*start,				/* Start of line after prefix */
   3996 	*ptr;				/* Pointer into line */
   3997 
   3998 
   3999   if (_cups_debug_fd < 0 || _cups_debug_level < 6)
   4000     return;
   4001 
   4002   DEBUG_printf(("6%s: %d bytes:", prefix, bytes));
   4003 
   4004   snprintf(line, sizeof(line), "6%s: ", prefix);
   4005   start = line + strlen(line);
   4006 
   4007   for (i = 0; i < bytes; i += 16)
   4008   {
   4009     for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
   4010       snprintf(ptr, 3, "%02X", buffer[i + j] & 255);
   4011 
   4012     while (j < 16)
   4013     {
   4014       memcpy(ptr, "  ", 3);
   4015       ptr += 2;
   4016       j ++;
   4017     }
   4018 
   4019     memcpy(ptr, "  ", 3);
   4020     ptr += 2;
   4021 
   4022     for (j = 0; j < 16 && (i + j) < bytes; j ++)
   4023     {
   4024       ch = buffer[i + j] & 255;
   4025 
   4026       if (ch < ' ' || ch >= 127)
   4027 	ch = '.';
   4028 
   4029       *ptr++ = (char)ch;
   4030     }
   4031 
   4032     *ptr = '\0';
   4033     DEBUG_puts(line);
   4034   }
   4035 }
   4036 #endif /* DEBUG */
   4037 
   4038 
   4039 /*
   4040  * 'http_read()' - Read a buffer from a HTTP connection.
   4041  *
   4042  * This function does the low-level read from the socket, retrying and timing
   4043  * out as needed.
   4044  */
   4045 
   4046 static ssize_t				/* O - Number of bytes read or -1 on error */
   4047 http_read(http_t *http,			/* I - HTTP connection */
   4048           char   *buffer,		/* I - Buffer */
   4049           size_t length)		/* I - Maximum bytes to read */
   4050 {
   4051   ssize_t	bytes;			/* Bytes read */
   4052 
   4053 
   4054   DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   4055 
   4056   if (!http->blocking)
   4057   {
   4058     while (!httpWait(http, http->wait_value))
   4059     {
   4060       if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   4061 	continue;
   4062 
   4063       DEBUG_puts("2http_read: Timeout.");
   4064       return (0);
   4065     }
   4066   }
   4067 
   4068   DEBUG_printf(("2http_read: Reading %d bytes into buffer.", (int)length));
   4069 
   4070   do
   4071   {
   4072 #ifdef HAVE_SSL
   4073     if (http->tls)
   4074       bytes = _httpTLSRead(http, buffer, (int)length);
   4075     else
   4076 #endif /* HAVE_SSL */
   4077     bytes = recv(http->fd, buffer, length, 0);
   4078 
   4079     if (bytes < 0)
   4080     {
   4081 #ifdef WIN32
   4082       if (WSAGetLastError() != WSAEINTR)
   4083       {
   4084 	http->error = WSAGetLastError();
   4085 	return (-1);
   4086       }
   4087       else if (WSAGetLastError() == WSAEWOULDBLOCK)
   4088       {
   4089 	if (!http->timeout_cb ||
   4090 	    !(*http->timeout_cb)(http, http->timeout_data))
   4091 	{
   4092 	  http->error = WSAEWOULDBLOCK;
   4093 	  return (-1);
   4094 	}
   4095       }
   4096 #else
   4097       DEBUG_printf(("2http_read: %s", strerror(errno)));
   4098 
   4099       if (errno == EWOULDBLOCK || errno == EAGAIN)
   4100       {
   4101 	if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
   4102 	{
   4103 	  http->error = errno;
   4104 	  return (-1);
   4105 	}
   4106 	else if (!http->timeout_cb && errno != EAGAIN)
   4107 	{
   4108 	  http->error = errno;
   4109 	  return (-1);
   4110 	}
   4111       }
   4112       else if (errno != EINTR)
   4113       {
   4114 	http->error = errno;
   4115 	return (-1);
   4116       }
   4117 #endif /* WIN32 */
   4118     }
   4119   }
   4120   while (bytes < 0);
   4121 
   4122   DEBUG_printf(("2http_read: Read " CUPS_LLFMT " bytes into buffer.",
   4123 		CUPS_LLCAST bytes));
   4124 #ifdef DEBUG
   4125   if (bytes > 0)
   4126     http_debug_hex("http_read", buffer, (int)bytes);
   4127 #endif /* DEBUG */
   4128 
   4129   if (bytes < 0)
   4130   {
   4131 #ifdef WIN32
   4132     if (WSAGetLastError() == WSAEINTR)
   4133       bytes = 0;
   4134     else
   4135       http->error = WSAGetLastError();
   4136 #else
   4137     if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
   4138       bytes = 0;
   4139     else
   4140       http->error = errno;
   4141 #endif /* WIN32 */
   4142   }
   4143   else if (bytes == 0)
   4144   {
   4145     http->error = EPIPE;
   4146     return (0);
   4147   }
   4148 
   4149   return (bytes);
   4150 }
   4151 
   4152 
   4153 /*
   4154  * 'http_read_buffered()' - Do a buffered read from a HTTP connection.
   4155  *
   4156  * This function reads data from the HTTP buffer or from the socket, as needed.
   4157  */
   4158 
   4159 static ssize_t				/* O - Number of bytes read or -1 on error */
   4160 http_read_buffered(http_t *http,	/* I - HTTP connection */
   4161                    char   *buffer,	/* I - Buffer */
   4162                    size_t length)	/* I - Maximum bytes to read */
   4163 {
   4164   ssize_t	bytes;			/* Bytes read */
   4165 
   4166 
   4167   DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT ") used=%d", (void *)http, (void *)buffer, CUPS_LLCAST length, http->used));
   4168 
   4169   if (http->used > 0)
   4170   {
   4171     if (length > (size_t)http->used)
   4172       bytes = (ssize_t)http->used;
   4173     else
   4174       bytes = (ssize_t)length;
   4175 
   4176     DEBUG_printf(("2http_read: Grabbing %d bytes from input buffer.",
   4177                   (int)bytes));
   4178 
   4179     memcpy(buffer, http->buffer, (size_t)bytes);
   4180     http->used -= (int)bytes;
   4181 
   4182     if (http->used > 0)
   4183       memmove(http->buffer, http->buffer + bytes, (size_t)http->used);
   4184   }
   4185   else
   4186     bytes = http_read(http, buffer, length);
   4187 
   4188   return (bytes);
   4189 }
   4190 
   4191 
   4192 /*
   4193  * 'http_read_chunk()' - Read a chunk from a HTTP connection.
   4194  *
   4195  * This function reads and validates the chunk length, then does a buffered read
   4196  * returning the number of bytes placed in the buffer.
   4197  */
   4198 
   4199 static ssize_t				/* O - Number of bytes read or -1 on error */
   4200 http_read_chunk(http_t *http,		/* I - HTTP connection */
   4201 		char   *buffer,		/* I - Buffer */
   4202 		size_t length)		/* I - Maximum bytes to read */
   4203 {
   4204   DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   4205 
   4206   if (http->data_remaining <= 0)
   4207   {
   4208     char	len[32];		/* Length string */
   4209 
   4210     if (!httpGets(len, sizeof(len), http))
   4211     {
   4212       DEBUG_puts("1http_read_chunk: Could not get chunk length.");
   4213       return (0);
   4214     }
   4215 
   4216     if (!len[0])
   4217     {
   4218       DEBUG_puts("1http_read_chunk: Blank chunk length, trying again...");
   4219       if (!httpGets(len, sizeof(len), http))
   4220       {
   4221 	DEBUG_puts("1http_read_chunk: Could not get chunk length.");
   4222 	return (0);
   4223       }
   4224     }
   4225 
   4226     http->data_remaining = strtoll(len, NULL, 16);
   4227 
   4228     if (http->data_remaining < 0)
   4229     {
   4230       DEBUG_printf(("1http_read_chunk: Negative chunk length \"%s\" ("
   4231                     CUPS_LLFMT ")", len, CUPS_LLCAST http->data_remaining));
   4232       return (0);
   4233     }
   4234 
   4235     DEBUG_printf(("2http_read_chunk: Got chunk length \"%s\" (" CUPS_LLFMT ")",
   4236                   len, CUPS_LLCAST http->data_remaining));
   4237 
   4238     if (http->data_remaining == 0)
   4239     {
   4240      /*
   4241       * 0-length chunk, grab trailing blank line...
   4242       */
   4243 
   4244       httpGets(len, sizeof(len), http);
   4245     }
   4246   }
   4247 
   4248   DEBUG_printf(("2http_read_chunk: data_remaining=" CUPS_LLFMT,
   4249                 CUPS_LLCAST http->data_remaining));
   4250 
   4251   if (http->data_remaining <= 0)
   4252     return (0);
   4253   else if (length > (size_t)http->data_remaining)
   4254     length = (size_t)http->data_remaining;
   4255 
   4256   return (http_read_buffered(http, buffer, length));
   4257 }
   4258 
   4259 
   4260 /*
   4261  * 'http_send()' - Send a request with all fields and the trailing blank line.
   4262  */
   4263 
   4264 static int				/* O - 0 on success, non-zero on error */
   4265 http_send(http_t       *http,		/* I - HTTP connection */
   4266           http_state_t request,		/* I - Request code */
   4267 	  const char   *uri)		/* I - URI */
   4268 {
   4269   int		i;			/* Looping var */
   4270   char		buf[1024];		/* Encoded URI buffer */
   4271   const char	*value;			/* Field value */
   4272   static const char * const codes[] =	/* Request code strings */
   4273 		{
   4274 		  NULL,
   4275 		  "OPTIONS",
   4276 		  "GET",
   4277 		  NULL,
   4278 		  "HEAD",
   4279 		  "POST",
   4280 		  NULL,
   4281 		  NULL,
   4282 		  "PUT",
   4283 		  NULL,
   4284 		  "DELETE",
   4285 		  "TRACE",
   4286 		  "CLOSE",
   4287 		  NULL,
   4288 		  NULL
   4289 		};
   4290 
   4291 
   4292   DEBUG_printf(("4http_send(http=%p, request=HTTP_%s, uri=\"%s\")", (void *)http, codes[request], uri));
   4293 
   4294   if (http == NULL || uri == NULL)
   4295     return (-1);
   4296 
   4297  /*
   4298   * Set the User-Agent field if it isn't already...
   4299   */
   4300 
   4301   if (!http->fields[HTTP_FIELD_USER_AGENT][0])
   4302   {
   4303     if (http->default_user_agent)
   4304       httpSetField(http, HTTP_FIELD_USER_AGENT, http->default_user_agent);
   4305     else
   4306       httpSetField(http, HTTP_FIELD_USER_AGENT, cupsUserAgent());
   4307   }
   4308 
   4309  /*
   4310   * Set the Accept-Encoding field if it isn't already...
   4311   */
   4312 
   4313   if (!http->accept_encoding && http->default_accept_encoding)
   4314     httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
   4315                  http->default_accept_encoding);
   4316 
   4317  /*
   4318   * Encode the URI as needed...
   4319   */
   4320 
   4321   _httpEncodeURI(buf, uri, sizeof(buf));
   4322 
   4323  /*
   4324   * See if we had an error the last time around; if so, reconnect...
   4325   */
   4326 
   4327   if (http->fd < 0 || http->status == HTTP_STATUS_ERROR ||
   4328       http->status >= HTTP_STATUS_BAD_REQUEST)
   4329   {
   4330     DEBUG_printf(("5http_send: Reconnecting, fd=%d, status=%d, tls_upgrade=%d",
   4331                   http->fd, http->status, http->tls_upgrade));
   4332 
   4333     if (httpReconnect2(http, 30000, NULL))
   4334       return (-1);
   4335   }
   4336 
   4337  /*
   4338   * Flush any written data that is pending...
   4339   */
   4340 
   4341   if (http->wused)
   4342   {
   4343     if (httpFlushWrite(http) < 0)
   4344       if (httpReconnect2(http, 30000, NULL))
   4345         return (-1);
   4346   }
   4347 
   4348  /*
   4349   * Send the request header...
   4350   */
   4351 
   4352   http->state         = request;
   4353   http->data_encoding = HTTP_ENCODING_FIELDS;
   4354 
   4355   if (request == HTTP_STATE_POST || request == HTTP_STATE_PUT)
   4356     http->state ++;
   4357 
   4358   http->status = HTTP_STATUS_CONTINUE;
   4359 
   4360 #ifdef HAVE_SSL
   4361   if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls)
   4362   {
   4363     httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
   4364     httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
   4365   }
   4366 #endif /* HAVE_SSL */
   4367 
   4368   if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
   4369   {
   4370     http->status = HTTP_STATUS_ERROR;
   4371     return (-1);
   4372   }
   4373 
   4374   for (i = 0; i < HTTP_FIELD_MAX; i ++)
   4375     if ((value = httpGetField(http, i)) != NULL && *value)
   4376     {
   4377       DEBUG_printf(("5http_send: %s: %s", http_fields[i], value));
   4378 
   4379       if (i == HTTP_FIELD_HOST)
   4380       {
   4381 	if (httpPrintf(http, "Host: %s:%d\r\n", value,
   4382 	               httpAddrPort(http->hostaddr)) < 1)
   4383 	{
   4384 	  http->status = HTTP_STATUS_ERROR;
   4385 	  return (-1);
   4386 	}
   4387       }
   4388       else if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
   4389       {
   4390 	http->status = HTTP_STATUS_ERROR;
   4391 	return (-1);
   4392       }
   4393     }
   4394 
   4395   if (http->cookie)
   4396     if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
   4397     {
   4398       http->status = HTTP_STATUS_ERROR;
   4399       return (-1);
   4400     }
   4401 
   4402   DEBUG_printf(("5http_send: expect=%d, mode=%d, state=%d", http->expect,
   4403                 http->mode, http->state));
   4404 
   4405   if (http->expect == HTTP_STATUS_CONTINUE && http->mode == _HTTP_MODE_CLIENT &&
   4406       (http->state == HTTP_STATE_POST_RECV ||
   4407        http->state == HTTP_STATE_PUT_RECV))
   4408     if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
   4409     {
   4410       http->status = HTTP_STATUS_ERROR;
   4411       return (-1);
   4412     }
   4413 
   4414   if (httpPrintf(http, "\r\n") < 1)
   4415   {
   4416     http->status = HTTP_STATUS_ERROR;
   4417     return (-1);
   4418   }
   4419 
   4420   if (httpFlushWrite(http) < 0)
   4421     return (-1);
   4422 
   4423   http_set_length(http);
   4424   httpClearFields(http);
   4425 
   4426  /*
   4427   * The Kerberos and AuthRef authentication strings can only be used once...
   4428   */
   4429 
   4430   if (http->field_authorization && http->authstring &&
   4431       (!strncmp(http->authstring, "Negotiate", 9) ||
   4432        !strncmp(http->authstring, "AuthRef", 7)))
   4433   {
   4434     http->_authstring[0] = '\0';
   4435 
   4436     if (http->authstring != http->_authstring)
   4437       free(http->authstring);
   4438 
   4439     http->authstring = http->_authstring;
   4440   }
   4441 
   4442   return (0);
   4443 }
   4444 
   4445 
   4446 /*
   4447  * 'http_set_length()' - Set the data_encoding and data_remaining values.
   4448  */
   4449 
   4450 static off_t				/* O - Remainder or -1 on error */
   4451 http_set_length(http_t *http)		/* I - Connection */
   4452 {
   4453   off_t	remaining;			/* Remainder */
   4454 
   4455 
   4456   DEBUG_printf(("http_set_length(http=%p) mode=%d state=%s", (void *)http, http->mode, httpStateString(http->state)));
   4457 
   4458   if ((remaining = httpGetLength2(http)) >= 0)
   4459   {
   4460     if (http->mode == _HTTP_MODE_SERVER &&
   4461 	http->state != HTTP_STATE_GET_SEND &&
   4462 	http->state != HTTP_STATE_PUT &&
   4463 	http->state != HTTP_STATE_POST &&
   4464 	http->state != HTTP_STATE_POST_SEND)
   4465     {
   4466       DEBUG_puts("1http_set_length: Not setting data_encoding/remaining.");
   4467       return (remaining);
   4468     }
   4469 
   4470     if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING],
   4471                           "chunked"))
   4472     {
   4473       DEBUG_puts("1http_set_length: Setting data_encoding to "
   4474                  "HTTP_ENCODING_CHUNKED.");
   4475       http->data_encoding = HTTP_ENCODING_CHUNKED;
   4476     }
   4477     else
   4478     {
   4479       DEBUG_puts("1http_set_length: Setting data_encoding to "
   4480                  "HTTP_ENCODING_LENGTH.");
   4481       http->data_encoding = HTTP_ENCODING_LENGTH;
   4482     }
   4483 
   4484     DEBUG_printf(("1http_set_length: Setting data_remaining to " CUPS_LLFMT ".",
   4485                   CUPS_LLCAST remaining));
   4486     http->data_remaining = remaining;
   4487 
   4488     if (remaining <= INT_MAX)
   4489       http->_data_remaining = (int)remaining;
   4490     else
   4491       http->_data_remaining = INT_MAX;
   4492   }
   4493 
   4494   return (remaining);
   4495 }
   4496 
   4497 /*
   4498  * 'http_set_timeout()' - Set the socket timeout values.
   4499  */
   4500 
   4501 static void
   4502 http_set_timeout(int    fd,		/* I - File descriptor */
   4503                  double timeout)	/* I - Timeout in seconds */
   4504 {
   4505 #ifdef WIN32
   4506   DWORD tv = (DWORD)(timeout * 1000);
   4507 				      /* Timeout in milliseconds */
   4508 
   4509   setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
   4510   setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
   4511 
   4512 #else
   4513   struct timeval tv;			/* Timeout in secs and usecs */
   4514 
   4515   tv.tv_sec  = (int)timeout;
   4516   tv.tv_usec = (int)(1000000 * fmod(timeout, 1.0));
   4517 
   4518   setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
   4519   setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
   4520 #endif /* WIN32 */
   4521 }
   4522 
   4523 
   4524 /*
   4525  * 'http_set_wait()' - Set the default wait value for reads.
   4526  */
   4527 
   4528 static void
   4529 http_set_wait(http_t *http)		/* I - HTTP connection */
   4530 {
   4531   if (http->blocking)
   4532   {
   4533     http->wait_value = (int)(http->timeout_value * 1000);
   4534 
   4535     if (http->wait_value <= 0)
   4536       http->wait_value = 60000;
   4537   }
   4538   else
   4539     http->wait_value = 10000;
   4540 }
   4541 
   4542 
   4543 #ifdef HAVE_SSL
   4544 /*
   4545  * 'http_tls_upgrade()' - Force upgrade to TLS encryption.
   4546  */
   4547 
   4548 static int				/* O - Status of connection */
   4549 http_tls_upgrade(http_t *http)		/* I - HTTP connection */
   4550 {
   4551   int		ret;			/* Return value */
   4552   http_t	myhttp;			/* Local copy of HTTP data */
   4553 
   4554 
   4555   DEBUG_printf(("7http_tls_upgrade(%p)", (void *)http));
   4556 
   4557  /*
   4558   * Flush the connection to make sure any previous "Upgrade" message
   4559   * has been read.
   4560   */
   4561 
   4562   httpFlush(http);
   4563 
   4564  /*
   4565   * Copy the HTTP data to a local variable so we can do the OPTIONS
   4566   * request without interfering with the existing request data...
   4567   */
   4568 
   4569   memcpy(&myhttp, http, sizeof(myhttp));
   4570 
   4571  /*
   4572   * Send an OPTIONS request to the server, requiring SSL or TLS
   4573   * encryption on the link...
   4574   */
   4575 
   4576   http->tls_upgrade         = 1;
   4577   http->field_authorization = NULL;	/* Don't free the auth string */
   4578 
   4579   httpClearFields(http);
   4580   httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
   4581   httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
   4582 
   4583   if ((ret = httpOptions(http, "*")) == 0)
   4584   {
   4585    /*
   4586     * Wait for the secure connection...
   4587     */
   4588 
   4589     while (httpUpdate(http) == HTTP_STATUS_CONTINUE);
   4590   }
   4591 
   4592  /*
   4593   * Restore the HTTP request data...
   4594   */
   4595 
   4596   memcpy(http->fields, myhttp.fields, sizeof(http->fields));
   4597   http->data_encoding       = myhttp.data_encoding;
   4598   http->data_remaining      = myhttp.data_remaining;
   4599   http->_data_remaining     = myhttp._data_remaining;
   4600   http->expect              = myhttp.expect;
   4601   http->field_authorization = myhttp.field_authorization;
   4602   http->digest_tries        = myhttp.digest_tries;
   4603   http->tls_upgrade         = 0;
   4604 
   4605  /*
   4606   * See if we actually went secure...
   4607   */
   4608 
   4609   if (!http->tls)
   4610   {
   4611    /*
   4612     * Server does not support HTTP upgrade...
   4613     */
   4614 
   4615     DEBUG_puts("8http_tls_upgrade: Server does not support HTTP upgrade!");
   4616 
   4617     _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Encryption is not supported."), 1);
   4618     httpAddrClose(NULL, http->fd);
   4619 
   4620     http->fd = -1;
   4621 
   4622     return (-1);
   4623   }
   4624   else
   4625     return (ret);
   4626 }
   4627 #endif /* HAVE_SSL */
   4628 
   4629 
   4630 /*
   4631  * 'http_write()' - Write a buffer to a HTTP connection.
   4632  */
   4633 
   4634 static ssize_t				/* O - Number of bytes written */
   4635 http_write(http_t     *http,		/* I - HTTP connection */
   4636            const char *buffer,		/* I - Buffer for data */
   4637 	   size_t     length)		/* I - Number of bytes to write */
   4638 {
   4639   ssize_t	tbytes,			/* Total bytes sent */
   4640 		bytes;			/* Bytes sent */
   4641 
   4642 
   4643   DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   4644   http->error = 0;
   4645   tbytes      = 0;
   4646 
   4647   while (length > 0)
   4648   {
   4649     DEBUG_printf(("3http_write: About to write %d bytes.", (int)length));
   4650 
   4651     if (http->timeout_cb)
   4652     {
   4653 #ifdef HAVE_POLL
   4654       struct pollfd	pfd;		/* Polled file descriptor */
   4655 #else
   4656       fd_set		output_set;	/* Output ready for write? */
   4657       struct timeval	timeout;	/* Timeout value */
   4658 #endif /* HAVE_POLL */
   4659       int		nfds;		/* Result from select()/poll() */
   4660 
   4661       do
   4662       {
   4663 #ifdef HAVE_POLL
   4664 	pfd.fd     = http->fd;
   4665 	pfd.events = POLLOUT;
   4666 
   4667 	while ((nfds = poll(&pfd, 1, http->wait_value)) < 0 &&
   4668 	       (errno == EINTR || errno == EAGAIN))
   4669 	  /* do nothing */;
   4670 
   4671 #else
   4672 	do
   4673 	{
   4674 	  FD_ZERO(&output_set);
   4675 	  FD_SET(http->fd, &output_set);
   4676 
   4677 	  timeout.tv_sec  = http->wait_value / 1000;
   4678 	  timeout.tv_usec = 1000 * (http->wait_value % 1000);
   4679 
   4680 	  nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout);
   4681 	}
   4682 #  ifdef WIN32
   4683 	while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
   4684 			    WSAGetLastError() == WSAEWOULDBLOCK));
   4685 #  else
   4686 	while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
   4687 #  endif /* WIN32 */
   4688 #endif /* HAVE_POLL */
   4689 
   4690         if (nfds < 0)
   4691 	{
   4692 	  http->error = errno;
   4693 	  return (-1);
   4694 	}
   4695 	else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data))
   4696 	{
   4697 #ifdef WIN32
   4698 	  http->error = WSAEWOULDBLOCK;
   4699 #else
   4700 	  http->error = EWOULDBLOCK;
   4701 #endif /* WIN32 */
   4702 	  return (-1);
   4703 	}
   4704       }
   4705       while (nfds <= 0);
   4706     }
   4707 
   4708 #ifdef HAVE_SSL
   4709     if (http->tls)
   4710       bytes = _httpTLSWrite(http, buffer, (int)length);
   4711     else
   4712 #endif /* HAVE_SSL */
   4713     bytes = send(http->fd, buffer, length, 0);
   4714 
   4715     DEBUG_printf(("3http_write: Write of " CUPS_LLFMT " bytes returned "
   4716                   CUPS_LLFMT ".", CUPS_LLCAST length, CUPS_LLCAST bytes));
   4717 
   4718     if (bytes < 0)
   4719     {
   4720 #ifdef WIN32
   4721       if (WSAGetLastError() == WSAEINTR)
   4722         continue;
   4723       else if (WSAGetLastError() == WSAEWOULDBLOCK)
   4724       {
   4725         if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   4726           continue;
   4727 
   4728         http->error = WSAGetLastError();
   4729       }
   4730       else if (WSAGetLastError() != http->error &&
   4731                WSAGetLastError() != WSAECONNRESET)
   4732       {
   4733         http->error = WSAGetLastError();
   4734 	continue;
   4735       }
   4736 
   4737 #else
   4738       if (errno == EINTR)
   4739         continue;
   4740       else if (errno == EWOULDBLOCK || errno == EAGAIN)
   4741       {
   4742 	if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   4743           continue;
   4744         else if (!http->timeout_cb && errno == EAGAIN)
   4745 	  continue;
   4746 
   4747         http->error = errno;
   4748       }
   4749       else if (errno != http->error && errno != ECONNRESET)
   4750       {
   4751         http->error = errno;
   4752 	continue;
   4753       }
   4754 #endif /* WIN32 */
   4755 
   4756       DEBUG_printf(("3http_write: error writing data (%s).",
   4757                     strerror(http->error)));
   4758 
   4759       return (-1);
   4760     }
   4761 
   4762     buffer += bytes;
   4763     tbytes += bytes;
   4764     length -= (size_t)bytes;
   4765   }
   4766 
   4767 #ifdef DEBUG
   4768   http_debug_hex("http_write", buffer - tbytes, (int)tbytes);
   4769 #endif /* DEBUG */
   4770 
   4771   DEBUG_printf(("3http_write: Returning " CUPS_LLFMT ".", CUPS_LLCAST tbytes));
   4772 
   4773   return (tbytes);
   4774 }
   4775 
   4776 
   4777 /*
   4778  * 'http_write_chunk()' - Write a chunked buffer.
   4779  */
   4780 
   4781 static ssize_t				/* O - Number bytes written */
   4782 http_write_chunk(http_t     *http,	/* I - HTTP connection */
   4783                  const char *buffer,	/* I - Buffer to write */
   4784 		 size_t        length)	/* I - Length of buffer */
   4785 {
   4786   char		header[16];		/* Chunk header */
   4787   ssize_t	bytes;			/* Bytes written */
   4788 
   4789 
   4790   DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   4791 
   4792  /*
   4793   * Write the chunk header, data, and trailer.
   4794   */
   4795 
   4796   snprintf(header, sizeof(header), "%x\r\n", (unsigned)length);
   4797   if (http_write(http, header, strlen(header)) < 0)
   4798   {
   4799     DEBUG_puts("8http_write_chunk: http_write of length failed.");
   4800     return (-1);
   4801   }
   4802 
   4803   if ((bytes = http_write(http, buffer, length)) < 0)
   4804   {
   4805     DEBUG_puts("8http_write_chunk: http_write of buffer failed.");
   4806     return (-1);
   4807   }
   4808 
   4809   if (http_write(http, "\r\n", 2) < 0)
   4810   {
   4811     DEBUG_puts("8http_write_chunk: http_write of CR LF failed.");
   4812     return (-1);
   4813   }
   4814 
   4815   return (bytes);
   4816 }
   4817