Home | History | Annotate | Download | only in cups
      1 /*
      2  * HTTP routines for CUPS.
      3  *
      4  * Copyright 2007-2017 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@ @exclude all@
    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 @code 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@ @exclude all@
    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 read 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 written to a HTTP connection.
    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 time in seconds 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 @link cupsDoAuthentication@ and
    770  * @link httpSetAuthString@.  Use @link httpGetAuthString@ to retrieve the
    771  * string to use with @link httpSetField@ for the
    772  * @code HTTP_FIELD_AUTHORIZATION@ 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 @code 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@ @exclude all@
   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 @code 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@ @exclude all@
   1350  */
   1351 
   1352 char *					/* O - Value or @code 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 @code 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 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@ @exclude all@
   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@ @exclude all@
   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 @link httpSetField@ to set
   2471  * @code HTTP_FIELD_AUTHORIZATION@ prior to issuing a HTTP request using
   2472  * @link httpGet@, @link httpHead@, @link httpOptions@, @link httpPost@, or
   2473  * @link httpPut@.
   2474  *
   2475  * @since CUPS 1.3/macOS 10.5@
   2476  */
   2477 
   2478 void
   2479 httpSetAuthString(http_t     *http,	/* I - HTTP connection */
   2480                   const char *scheme,	/* I - Auth scheme (NULL to clear it) */
   2481 		  const char *data)	/* I - Auth data (NULL for none) */
   2482 {
   2483  /*
   2484   * Range check input...
   2485   */
   2486 
   2487   if (!http)
   2488     return;
   2489 
   2490   if (http->authstring && http->authstring != http->_authstring)
   2491     free(http->authstring);
   2492 
   2493   http->authstring = http->_authstring;
   2494 
   2495   if (scheme)
   2496   {
   2497    /*
   2498     * Set the current authorization string...
   2499     */
   2500 
   2501     size_t len = strlen(scheme) + (data ? strlen(data) + 1 : 0) + 1;
   2502     char *temp;
   2503 
   2504     if (len > sizeof(http->_authstring))
   2505     {
   2506       if ((temp = malloc(len)) == NULL)
   2507         len = sizeof(http->_authstring);
   2508       else
   2509         http->authstring = temp;
   2510     }
   2511 
   2512     if (data)
   2513       snprintf(http->authstring, len, "%s %s", scheme, data);
   2514     else
   2515       strlcpy(http->authstring, scheme, len);
   2516   }
   2517   else
   2518   {
   2519    /*
   2520     * Clear the current authorization string...
   2521     */
   2522 
   2523     http->_authstring[0] = '\0';
   2524   }
   2525 }
   2526 
   2527 
   2528 /*
   2529  * 'httpSetCredentials()' - Set the credentials associated with an encrypted
   2530  *			    connection.
   2531  *
   2532  * @since CUPS 1.5/macOS 10.7@
   2533  */
   2534 
   2535 int						/* O - Status of call (0 = success) */
   2536 httpSetCredentials(http_t	*http,		/* I - HTTP connection */
   2537 		   cups_array_t *credentials)	/* I - Array of credentials */
   2538 {
   2539   if (!http || cupsArrayCount(credentials) < 1)
   2540     return (-1);
   2541 
   2542 #ifdef HAVE_SSL
   2543   _httpFreeCredentials(http->tls_credentials);
   2544 
   2545   http->tls_credentials = _httpCreateCredentials(credentials);
   2546 #endif /* HAVE_SSL */
   2547 
   2548   return (http->tls_credentials ? 0 : -1);
   2549 }
   2550 
   2551 
   2552 /*
   2553  * 'httpSetCookie()' - Set the cookie value(s).
   2554  *
   2555  * @since CUPS 1.1.19/macOS 10.3@
   2556  */
   2557 
   2558 void
   2559 httpSetCookie(http_t     *http,		/* I - Connection */
   2560               const char *cookie)	/* I - Cookie string */
   2561 {
   2562   if (!http)
   2563     return;
   2564 
   2565   if (http->cookie)
   2566     free(http->cookie);
   2567 
   2568   if (cookie)
   2569     http->cookie = strdup(cookie);
   2570   else
   2571     http->cookie = NULL;
   2572 }
   2573 
   2574 
   2575 /*
   2576  * 'httpSetDefaultField()' - Set the default value of an HTTP header.
   2577  *
   2578  * Currently only @code HTTP_FIELD_ACCEPT_ENCODING@, @code HTTP_FIELD_SERVER@,
   2579  * and @code HTTP_FIELD_USER_AGENT@ can be set.
   2580  *
   2581  * @since CUPS 1.7/macOS 10.9@
   2582  */
   2583 
   2584 void
   2585 httpSetDefaultField(http_t       *http,	/* I - HTTP connection */
   2586                     http_field_t field,	/* I - Field index */
   2587 	            const char   *value)/* I - Value */
   2588 {
   2589   DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")", (void *)http, field, http_fields[field], value));
   2590 
   2591   if (!http)
   2592     return;
   2593 
   2594   switch (field)
   2595   {
   2596     case HTTP_FIELD_ACCEPT_ENCODING :
   2597         if (http->default_accept_encoding)
   2598           _cupsStrFree(http->default_accept_encoding);
   2599 
   2600         http->default_accept_encoding = value ? _cupsStrAlloc(value) : NULL;
   2601         break;
   2602 
   2603     case HTTP_FIELD_SERVER :
   2604         if (http->default_server)
   2605           _cupsStrFree(http->default_server);
   2606 
   2607         http->default_server = value ? _cupsStrAlloc(value) : NULL;
   2608         break;
   2609 
   2610     case HTTP_FIELD_USER_AGENT :
   2611         if (http->default_user_agent)
   2612           _cupsStrFree(http->default_user_agent);
   2613 
   2614         http->default_user_agent = value ? _cupsStrAlloc(value) : NULL;
   2615         break;
   2616 
   2617     default :
   2618         DEBUG_puts("1httpSetDefaultField: Ignored.");
   2619 	break;
   2620   }
   2621 }
   2622 
   2623 
   2624 /*
   2625  * 'httpSetExpect()' - Set the Expect: header in a request.
   2626  *
   2627  * Currently only @code HTTP_STATUS_CONTINUE@ is supported for the "expect"
   2628  * argument.
   2629  *
   2630  * @since CUPS 1.2/macOS 10.5@
   2631  */
   2632 
   2633 void
   2634 httpSetExpect(http_t        *http,	/* I - HTTP connection */
   2635               http_status_t expect)	/* I - HTTP status to expect
   2636               				       (@code HTTP_STATUS_CONTINUE@) */
   2637 {
   2638   DEBUG_printf(("httpSetExpect(http=%p, expect=%d)", (void *)http, expect));
   2639 
   2640   if (http)
   2641     http->expect = expect;
   2642 }
   2643 
   2644 
   2645 /*
   2646  * 'httpSetField()' - Set the value of an HTTP header.
   2647  */
   2648 
   2649 void
   2650 httpSetField(http_t       *http,	/* I - HTTP connection */
   2651              http_field_t field,	/* I - Field index */
   2652 	     const char   *value)	/* I - Value */
   2653 {
   2654   DEBUG_printf(("httpSetField(http=%p, field=%d(%s), value=\"%s\")", (void *)http, field, http_fields[field], value));
   2655 
   2656   if (http == NULL ||
   2657       field < HTTP_FIELD_ACCEPT_LANGUAGE ||
   2658       field >= HTTP_FIELD_MAX ||
   2659       value == NULL)
   2660     return;
   2661 
   2662   switch (field)
   2663   {
   2664     case HTTP_FIELD_ACCEPT_ENCODING :
   2665         if (http->accept_encoding)
   2666           _cupsStrFree(http->accept_encoding);
   2667 
   2668         http->accept_encoding = _cupsStrAlloc(value);
   2669         break;
   2670 
   2671     case HTTP_FIELD_ALLOW :
   2672         if (http->allow)
   2673           _cupsStrFree(http->allow);
   2674 
   2675         http->allow = _cupsStrAlloc(value);
   2676         break;
   2677 
   2678     case HTTP_FIELD_SERVER :
   2679         if (http->server)
   2680           _cupsStrFree(http->server);
   2681 
   2682         http->server = _cupsStrAlloc(value);
   2683         break;
   2684 
   2685     case HTTP_FIELD_WWW_AUTHENTICATE :
   2686        /* CUPS STR #4503 - don't override WWW-Authenticate for unknown auth schemes */
   2687         if (http->fields[HTTP_FIELD_WWW_AUTHENTICATE][0] &&
   2688 	    _cups_strncasecmp(value, "Basic ", 6) &&
   2689 	    _cups_strncasecmp(value, "Digest ", 7) &&
   2690 	    _cups_strncasecmp(value, "Negotiate ", 10))
   2691 	{
   2692 	  DEBUG_printf(("1httpSetField: Ignoring unknown auth scheme in \"%s\".", value));
   2693           return;
   2694 	}
   2695 
   2696 	/* Fall through to copy */
   2697 
   2698     default :
   2699 	strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
   2700 	break;
   2701   }
   2702 
   2703   if (field == HTTP_FIELD_AUTHORIZATION)
   2704   {
   2705    /*
   2706     * Special case for Authorization: as its contents can be
   2707     * longer than HTTP_MAX_VALUE
   2708     */
   2709 
   2710     if (http->field_authorization)
   2711       free(http->field_authorization);
   2712 
   2713     http->field_authorization = strdup(value);
   2714   }
   2715   else if (field == HTTP_FIELD_HOST)
   2716   {
   2717    /*
   2718     * Special-case for Host: as we don't want a trailing "." on the hostname and
   2719     * need to bracket IPv6 numeric addresses.
   2720     */
   2721 
   2722     char *ptr = strchr(value, ':');
   2723 
   2724     if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
   2725     {
   2726      /*
   2727       * Bracket IPv6 numeric addresses...
   2728       *
   2729       * This is slightly inefficient (basically copying twice), but is an edge
   2730       * case and not worth optimizing...
   2731       */
   2732 
   2733       snprintf(http->fields[HTTP_FIELD_HOST],
   2734                sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
   2735     }
   2736     else
   2737     {
   2738      /*
   2739       * Check for a trailing dot on the hostname...
   2740       */
   2741 
   2742       ptr = http->fields[HTTP_FIELD_HOST];
   2743 
   2744       if (*ptr)
   2745       {
   2746 	ptr += strlen(ptr) - 1;
   2747 
   2748 	if (*ptr == '.')
   2749 	  *ptr = '\0';
   2750       }
   2751     }
   2752   }
   2753 #ifdef HAVE_LIBZ
   2754   else if (field == HTTP_FIELD_CONTENT_ENCODING &&
   2755            http->data_encoding != HTTP_ENCODING_FIELDS)
   2756   {
   2757     DEBUG_puts("1httpSetField: Calling http_content_coding_start.");
   2758     http_content_coding_start(http, value);
   2759   }
   2760 #endif /* HAVE_LIBZ */
   2761 }
   2762 
   2763 
   2764 /*
   2765  * 'httpSetKeepAlive()' - Set the current Keep-Alive state of a connection.
   2766  *
   2767  * @since CUPS 2.0/OS 10.10@
   2768  */
   2769 
   2770 void
   2771 httpSetKeepAlive(
   2772     http_t           *http,		/* I - HTTP connection */
   2773     http_keepalive_t keep_alive)	/* I - New Keep-Alive value */
   2774 {
   2775   if (http)
   2776     http->keep_alive = keep_alive;
   2777 }
   2778 
   2779 
   2780 /*
   2781  * 'httpSetLength()' - Set the content-length and content-encoding.
   2782  *
   2783  * @since CUPS 1.2/macOS 10.5@
   2784  */
   2785 
   2786 void
   2787 httpSetLength(http_t *http,		/* I - HTTP connection */
   2788               size_t length)		/* I - Length (0 for chunked) */
   2789 {
   2790   DEBUG_printf(("httpSetLength(http=%p, length=" CUPS_LLFMT ")", (void *)http, CUPS_LLCAST length));
   2791 
   2792   if (!http)
   2793     return;
   2794 
   2795   if (!length)
   2796   {
   2797     strlcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked",
   2798             HTTP_MAX_VALUE);
   2799     http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
   2800   }
   2801   else
   2802   {
   2803     http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
   2804     snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
   2805              CUPS_LLFMT, CUPS_LLCAST length);
   2806   }
   2807 }
   2808 
   2809 
   2810 /*
   2811  * 'httpSetTimeout()' - Set read/write timeouts and an optional callback.
   2812  *
   2813  * The optional timeout callback receives both the HTTP connection and a user
   2814  * data pointer and must return 1 to continue or 0 to error (time) out.
   2815  *
   2816  * @since CUPS 1.5/macOS 10.7@
   2817  */
   2818 
   2819 void
   2820 httpSetTimeout(
   2821     http_t            *http,		/* I - HTTP connection */
   2822     double            timeout,		/* I - Number of seconds for timeout,
   2823                                                must be greater than 0 */
   2824     http_timeout_cb_t cb,		/* I - Callback function or @code NULL@ */
   2825     void              *user_data)	/* I - User data pointer */
   2826 {
   2827   if (!http || timeout <= 0.0)
   2828     return;
   2829 
   2830   http->timeout_cb    = cb;
   2831   http->timeout_data  = user_data;
   2832   http->timeout_value = timeout;
   2833 
   2834   if (http->fd >= 0)
   2835     http_set_timeout(http->fd, timeout);
   2836 
   2837   http_set_wait(http);
   2838 }
   2839 
   2840 
   2841 /*
   2842  * 'httpShutdown()' - Shutdown one side of an HTTP connection.
   2843  *
   2844  * @since CUPS 2.0/OS 10.10@
   2845  */
   2846 
   2847 void
   2848 httpShutdown(http_t *http)		/* I - HTTP connection */
   2849 {
   2850   if (!http || http->fd < 0)
   2851     return;
   2852 
   2853 #ifdef HAVE_SSL
   2854   if (http->tls)
   2855     _httpTLSStop(http);
   2856 #endif /* HAVE_SSL */
   2857 
   2858 #ifdef WIN32
   2859   shutdown(http->fd, SD_RECEIVE);	/* Microsoft-ism... */
   2860 #else
   2861   shutdown(http->fd, SHUT_RD);
   2862 #endif /* WIN32 */
   2863 }
   2864 
   2865 
   2866 /*
   2867  * 'httpTrace()' - Send an TRACE request to the server.
   2868  *
   2869  * @exclude all@
   2870  */
   2871 
   2872 int					/* O - Status of call (0 = success) */
   2873 httpTrace(http_t     *http,		/* I - HTTP connection */
   2874           const char *uri)		/* I - URI for trace */
   2875 {
   2876   return (http_send(http, HTTP_STATE_TRACE, uri));
   2877 }
   2878 
   2879 
   2880 /*
   2881  * '_httpUpdate()' - Update the current HTTP status for incoming data.
   2882  *
   2883  * Note: Unlike httpUpdate(), this function does not flush pending write data
   2884  * and only retrieves a single status line from the HTTP connection.
   2885  */
   2886 
   2887 int					/* O - 1 to continue, 0 to stop */
   2888 _httpUpdate(http_t        *http,	/* I - HTTP connection */
   2889             http_status_t *status)	/* O - Current HTTP status */
   2890 {
   2891   char		line[32768],		/* Line from connection... */
   2892 		*value;			/* Pointer to value on line */
   2893   http_field_t	field;			/* Field index */
   2894   int		major, minor;		/* HTTP version numbers */
   2895 
   2896 
   2897   DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", (void *)http, (void *)status, httpStateString(http->state)));
   2898 
   2899  /*
   2900   * Grab a single line from the connection...
   2901   */
   2902 
   2903   if (!httpGets(line, sizeof(line), http))
   2904   {
   2905     *status = HTTP_STATUS_ERROR;
   2906     return (0);
   2907   }
   2908 
   2909   DEBUG_printf(("2_httpUpdate: Got \"%s\"", line));
   2910 
   2911   if (line[0] == '\0')
   2912   {
   2913    /*
   2914     * Blank line means the start of the data section (if any).  Return
   2915     * the result code, too...
   2916     *
   2917     * If we get status 100 (HTTP_STATUS_CONTINUE), then we *don't* change
   2918     * states.  Instead, we just return HTTP_STATUS_CONTINUE to the caller and
   2919     * keep on tryin'...
   2920     */
   2921 
   2922     if (http->status == HTTP_STATUS_CONTINUE)
   2923     {
   2924       *status = http->status;
   2925       return (0);
   2926     }
   2927 
   2928     if (http->status < HTTP_STATUS_BAD_REQUEST)
   2929       http->digest_tries = 0;
   2930 
   2931 #ifdef HAVE_SSL
   2932     if (http->status == HTTP_STATUS_SWITCHING_PROTOCOLS && !http->tls)
   2933     {
   2934       if (_httpTLSStart(http) != 0)
   2935       {
   2936         httpAddrClose(NULL, http->fd);
   2937 
   2938 	*status = http->status = HTTP_STATUS_ERROR;
   2939 	return (0);
   2940       }
   2941 
   2942       *status = HTTP_STATUS_CONTINUE;
   2943       return (0);
   2944     }
   2945 #endif /* HAVE_SSL */
   2946 
   2947     if (http_set_length(http) < 0)
   2948     {
   2949       DEBUG_puts("1_httpUpdate: Bad Content-Length.");
   2950       http->error  = EINVAL;
   2951       http->status = *status = HTTP_STATUS_ERROR;
   2952       return (0);
   2953     }
   2954 
   2955     switch (http->state)
   2956     {
   2957       case HTTP_STATE_GET :
   2958       case HTTP_STATE_POST :
   2959       case HTTP_STATE_POST_RECV :
   2960       case HTTP_STATE_PUT :
   2961 	  http->state ++;
   2962 
   2963 	  DEBUG_printf(("1_httpUpdate: Set state to %s.",
   2964 	                httpStateString(http->state)));
   2965 
   2966       case HTTP_STATE_POST_SEND :
   2967       case HTTP_STATE_HEAD :
   2968 	  break;
   2969 
   2970       default :
   2971 	  http->state = HTTP_STATE_WAITING;
   2972 
   2973 	  DEBUG_puts("1_httpUpdate: Reset state to HTTP_STATE_WAITING.");
   2974 	  break;
   2975     }
   2976 
   2977 #ifdef HAVE_LIBZ
   2978     DEBUG_puts("1_httpUpdate: Calling http_content_coding_start.");
   2979     http_content_coding_start(http,
   2980                               httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
   2981 #endif /* HAVE_LIBZ */
   2982 
   2983     *status = http->status;
   2984     return (0);
   2985   }
   2986   else if (!strncmp(line, "HTTP/", 5) && http->mode == _HTTP_MODE_CLIENT)
   2987   {
   2988    /*
   2989     * Got the beginning of a response...
   2990     */
   2991 
   2992     int	intstatus;			/* Status value as an integer */
   2993 
   2994     if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3)
   2995     {
   2996       *status = http->status = HTTP_STATUS_ERROR;
   2997       return (0);
   2998     }
   2999 
   3000     httpClearFields(http);
   3001 
   3002     http->version = (http_version_t)(major * 100 + minor);
   3003     *status       = http->status = (http_status_t)intstatus;
   3004   }
   3005   else if ((value = strchr(line, ':')) != NULL)
   3006   {
   3007    /*
   3008     * Got a value...
   3009     */
   3010 
   3011     *value++ = '\0';
   3012     while (_cups_isspace(*value))
   3013       value ++;
   3014 
   3015     DEBUG_printf(("1_httpUpdate: Header %s: %s", line, value));
   3016 
   3017    /*
   3018     * Be tolerants of servers that send unknown attribute fields...
   3019     */
   3020 
   3021     if (!_cups_strcasecmp(line, "expect"))
   3022     {
   3023      /*
   3024       * "Expect: 100-continue" or similar...
   3025       */
   3026 
   3027       http->expect = (http_status_t)atoi(value);
   3028     }
   3029     else if (!_cups_strcasecmp(line, "cookie"))
   3030     {
   3031      /*
   3032       * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
   3033       */
   3034 
   3035       httpSetCookie(http, value);
   3036     }
   3037     else if ((field = httpFieldValue(line)) != HTTP_FIELD_UNKNOWN)
   3038       httpSetField(http, field, value);
   3039 #ifdef DEBUG
   3040     else
   3041       DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line));
   3042 #endif /* DEBUG */
   3043   }
   3044   else
   3045   {
   3046     DEBUG_printf(("1_httpUpdate: Bad response line \"%s\"!", line));
   3047     http->error  = EINVAL;
   3048     http->status = *status = HTTP_STATUS_ERROR;
   3049     return (0);
   3050   }
   3051 
   3052   return (1);
   3053 }
   3054 
   3055 
   3056 /*
   3057  * 'httpUpdate()' - Update the current HTTP state for incoming data.
   3058  */
   3059 
   3060 http_status_t				/* O - HTTP status */
   3061 httpUpdate(http_t *http)		/* I - HTTP connection */
   3062 {
   3063   http_status_t	status;			/* Request status */
   3064 
   3065 
   3066   DEBUG_printf(("httpUpdate(http=%p), state=%s", (void *)http, httpStateString(http->state)));
   3067 
   3068  /*
   3069   * Flush pending data, if any...
   3070   */
   3071 
   3072   if (http->wused)
   3073   {
   3074     DEBUG_puts("2httpUpdate: flushing buffer...");
   3075 
   3076     if (httpFlushWrite(http) < 0)
   3077       return (HTTP_STATUS_ERROR);
   3078   }
   3079 
   3080  /*
   3081   * If we haven't issued any commands, then there is nothing to "update"...
   3082   */
   3083 
   3084   if (http->state == HTTP_STATE_WAITING)
   3085     return (HTTP_STATUS_CONTINUE);
   3086 
   3087  /*
   3088   * Grab all of the lines we can from the connection...
   3089   */
   3090 
   3091   while (_httpUpdate(http, &status));
   3092 
   3093  /*
   3094   * See if there was an error...
   3095   */
   3096 
   3097   if (http->error == EPIPE && http->status > HTTP_STATUS_CONTINUE)
   3098   {
   3099     DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
   3100     return (http->status);
   3101   }
   3102 
   3103   if (http->error)
   3104   {
   3105     DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
   3106                   strerror(http->error)));
   3107     http->status = HTTP_STATUS_ERROR;
   3108     return (HTTP_STATUS_ERROR);
   3109   }
   3110 
   3111  /*
   3112   * Return the current status...
   3113   */
   3114 
   3115   return (status);
   3116 }
   3117 
   3118 
   3119 /*
   3120  * '_httpWait()' - Wait for data available on a connection (no flush).
   3121  */
   3122 
   3123 int					/* O - 1 if data is available, 0 otherwise */
   3124 _httpWait(http_t *http,			/* I - HTTP connection */
   3125           int    msec,			/* I - Milliseconds to wait */
   3126 	  int    usessl)		/* I - Use SSL context? */
   3127 {
   3128 #ifdef HAVE_POLL
   3129   struct pollfd		pfd;		/* Polled file descriptor */
   3130 #else
   3131   fd_set		input_set;	/* select() input set */
   3132   struct timeval	timeout;	/* Timeout */
   3133 #endif /* HAVE_POLL */
   3134   int			nfds;		/* Result from select()/poll() */
   3135 
   3136 
   3137   DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", (void *)http, msec, usessl));
   3138 
   3139   if (http->fd < 0)
   3140   {
   3141     DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd));
   3142     return (0);
   3143   }
   3144 
   3145  /*
   3146   * Check the SSL/TLS buffers for data first...
   3147   */
   3148 
   3149 #ifdef HAVE_SSL
   3150   if (http->tls && _httpTLSPending(http))
   3151   {
   3152     DEBUG_puts("5_httpWait: Return 1 since there is pending TLS data.");
   3153     return (1);
   3154   }
   3155 #endif /* HAVE_SSL */
   3156 
   3157  /*
   3158   * Then try doing a select() or poll() to poll the socket...
   3159   */
   3160 
   3161 #ifdef HAVE_POLL
   3162   pfd.fd     = http->fd;
   3163   pfd.events = POLLIN;
   3164 
   3165   do
   3166   {
   3167     nfds = poll(&pfd, 1, msec);
   3168   }
   3169   while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
   3170 
   3171 #else
   3172   do
   3173   {
   3174     FD_ZERO(&input_set);
   3175     FD_SET(http->fd, &input_set);
   3176 
   3177     DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
   3178 
   3179     if (msec >= 0)
   3180     {
   3181       timeout.tv_sec  = msec / 1000;
   3182       timeout.tv_usec = (msec % 1000) * 1000;
   3183 
   3184       nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
   3185     }
   3186     else
   3187       nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
   3188 
   3189     DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
   3190   }
   3191 #  ifdef WIN32
   3192   while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
   3193                       WSAGetLastError() == WSAEWOULDBLOCK));
   3194 #  else
   3195   while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
   3196 #  endif /* WIN32 */
   3197 #endif /* HAVE_POLL */
   3198 
   3199   DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds,
   3200                 errno));
   3201 
   3202   return (nfds > 0);
   3203 }
   3204 
   3205 
   3206 /*
   3207  * 'httpWait()' - Wait for data available on a connection.
   3208  *
   3209  * @since CUPS 1.1.19/macOS 10.3@
   3210  */
   3211 
   3212 int					/* O - 1 if data is available, 0 otherwise */
   3213 httpWait(http_t *http,			/* I - HTTP connection */
   3214          int    msec)			/* I - Milliseconds to wait */
   3215 {
   3216  /*
   3217   * First see if there is data in the buffer...
   3218   */
   3219 
   3220   DEBUG_printf(("2httpWait(http=%p, msec=%d)", (void *)http, msec));
   3221 
   3222   if (http == NULL)
   3223     return (0);
   3224 
   3225   if (http->used)
   3226   {
   3227     DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
   3228     return (1);
   3229   }
   3230 
   3231 #ifdef HAVE_LIBZ
   3232   if (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in > 0)
   3233   {
   3234     DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
   3235     return (1);
   3236   }
   3237 #endif /* HAVE_LIBZ */
   3238 
   3239  /*
   3240   * Flush pending data, if any...
   3241   */
   3242 
   3243   if (http->wused)
   3244   {
   3245     DEBUG_puts("3httpWait: Flushing write buffer.");
   3246 
   3247     if (httpFlushWrite(http) < 0)
   3248       return (0);
   3249   }
   3250 
   3251  /*
   3252   * If not, check the SSL/TLS buffers and do a select() on the connection...
   3253   */
   3254 
   3255   return (_httpWait(http, msec, 1));
   3256 }
   3257 
   3258 
   3259 /*
   3260  * 'httpWrite()' - Write data to a HTTP connection.
   3261  *
   3262  * This function is deprecated. Use the httpWrite2() function which can
   3263  * write more than 2GB of data.
   3264  *
   3265  * @deprecated@ @exclude all@
   3266  */
   3267 
   3268 int					/* O - Number of bytes written */
   3269 httpWrite(http_t     *http,		/* I - HTTP connection */
   3270           const char *buffer,		/* I - Buffer for data */
   3271 	  int        length)		/* I - Number of bytes to write */
   3272 {
   3273   return ((int)httpWrite2(http, buffer, (size_t)length));
   3274 }
   3275 
   3276 
   3277 /*
   3278  * 'httpWrite2()' - Write data to a HTTP connection.
   3279  *
   3280  * @since CUPS 1.2/macOS 10.5@
   3281  */
   3282 
   3283 ssize_t					/* O - Number of bytes written */
   3284 httpWrite2(http_t     *http,		/* I - HTTP connection */
   3285            const char *buffer,		/* I - Buffer for data */
   3286 	   size_t     length)		/* I - Number of bytes to write */
   3287 {
   3288   ssize_t	bytes;			/* Bytes written */
   3289 
   3290 
   3291   DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   3292 
   3293  /*
   3294   * Range check input...
   3295   */
   3296 
   3297   if (!http || !buffer)
   3298   {
   3299     DEBUG_puts("1httpWrite2: Returning -1 due to bad input.");
   3300     return (-1);
   3301   }
   3302 
   3303  /*
   3304   * Mark activity on the connection...
   3305   */
   3306 
   3307   http->activity = time(NULL);
   3308 
   3309  /*
   3310   * Buffer small writes for better performance...
   3311   */
   3312 
   3313 #ifdef HAVE_LIBZ
   3314   if (http->coding == _HTTP_CODING_GZIP || http->coding == _HTTP_CODING_DEFLATE)
   3315   {
   3316     DEBUG_printf(("1httpWrite2: http->coding=%d", http->coding));
   3317 
   3318     if (length == 0)
   3319     {
   3320       http_content_coding_finish(http);
   3321       bytes = 0;
   3322     }
   3323     else
   3324     {
   3325       size_t	slen;			/* Bytes to write */
   3326       ssize_t	sret;			/* Bytes written */
   3327 
   3328       http->stream.next_in   = (Bytef *)buffer;
   3329       http->stream.avail_in  = (uInt)length;
   3330 
   3331       while (deflate(&(http->stream), Z_NO_FLUSH) == Z_OK)
   3332       {
   3333         DEBUG_printf(("1httpWrite2: avail_out=%d", http->stream.avail_out));
   3334 
   3335         if (http->stream.avail_out > 0)
   3336 	  continue;
   3337 
   3338 	slen = _HTTP_MAX_SBUFFER - http->stream.avail_out;
   3339 
   3340         DEBUG_printf(("1httpWrite2: Writing intermediate chunk, len=%d", (int)slen));
   3341 
   3342 	if (slen > 0 && http->data_encoding == HTTP_ENCODING_CHUNKED)
   3343 	  sret = http_write_chunk(http, (char *)http->sbuffer, slen);
   3344 	else if (slen > 0)
   3345 	  sret = http_write(http, (char *)http->sbuffer, slen);
   3346 	else
   3347 	  sret = 0;
   3348 
   3349         if (sret < 0)
   3350 	{
   3351 	  DEBUG_puts("1httpWrite2: Unable to write, returning -1.");
   3352 	  return (-1);
   3353 	}
   3354 
   3355 	http->stream.next_out  = (Bytef *)http->sbuffer;
   3356 	http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER;
   3357       }
   3358 
   3359       bytes = (ssize_t)length;
   3360     }
   3361   }
   3362   else
   3363 #endif /* HAVE_LIBZ */
   3364   if (length > 0)
   3365   {
   3366     if (http->wused && (length + (size_t)http->wused) > sizeof(http->wbuffer))
   3367     {
   3368       DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
   3369                     CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
   3370 
   3371       httpFlushWrite(http);
   3372     }
   3373 
   3374     if ((length + (size_t)http->wused) <= sizeof(http->wbuffer) && length < sizeof(http->wbuffer))
   3375     {
   3376      /*
   3377       * Write to buffer...
   3378       */
   3379 
   3380       DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
   3381                     CUPS_LLCAST length));
   3382 
   3383       memcpy(http->wbuffer + http->wused, buffer, length);
   3384       http->wused += (int)length;
   3385       bytes = (ssize_t)length;
   3386     }
   3387     else
   3388     {
   3389      /*
   3390       * Otherwise write the data directly...
   3391       */
   3392 
   3393       DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
   3394                     CUPS_LLCAST length));
   3395 
   3396       if (http->data_encoding == HTTP_ENCODING_CHUNKED)
   3397 	bytes = (ssize_t)http_write_chunk(http, buffer, length);
   3398       else
   3399 	bytes = (ssize_t)http_write(http, buffer, length);
   3400 
   3401       DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
   3402                     CUPS_LLCAST bytes));
   3403     }
   3404 
   3405     if (http->data_encoding == HTTP_ENCODING_LENGTH)
   3406       http->data_remaining -= bytes;
   3407   }
   3408   else
   3409     bytes = 0;
   3410 
   3411  /*
   3412   * Handle end-of-request processing...
   3413   */
   3414 
   3415   if ((http->data_encoding == HTTP_ENCODING_CHUNKED && length == 0) ||
   3416       (http->data_encoding == HTTP_ENCODING_LENGTH && http->data_remaining == 0))
   3417   {
   3418    /*
   3419     * Finished with the transfer; unless we are sending POST or PUT
   3420     * data, go idle...
   3421     */
   3422 
   3423 #ifdef HAVE_LIBZ
   3424     if (http->coding == _HTTP_CODING_GZIP || http->coding == _HTTP_CODING_DEFLATE)
   3425       http_content_coding_finish(http);
   3426 #endif /* HAVE_LIBZ */
   3427 
   3428     if (http->wused)
   3429     {
   3430       if (httpFlushWrite(http) < 0)
   3431         return (-1);
   3432     }
   3433 
   3434     if (http->data_encoding == HTTP_ENCODING_CHUNKED)
   3435     {
   3436      /*
   3437       * Send a 0-length chunk at the end of the request...
   3438       */
   3439 
   3440       http_write(http, "0\r\n\r\n", 5);
   3441 
   3442      /*
   3443       * Reset the data state...
   3444       */
   3445 
   3446       http->data_encoding  = HTTP_ENCODING_FIELDS;
   3447       http->data_remaining = 0;
   3448     }
   3449 
   3450     if (http->state == HTTP_STATE_POST_RECV)
   3451       http->state ++;
   3452     else if (http->state == HTTP_STATE_POST_SEND ||
   3453              http->state == HTTP_STATE_GET_SEND)
   3454       http->state = HTTP_STATE_WAITING;
   3455     else
   3456       http->state = HTTP_STATE_STATUS;
   3457 
   3458     DEBUG_printf(("2httpWrite2: Changed state to %s.",
   3459 		  httpStateString(http->state)));
   3460   }
   3461 
   3462   DEBUG_printf(("1httpWrite2: Returning " CUPS_LLFMT ".", CUPS_LLCAST bytes));
   3463 
   3464   return (bytes);
   3465 }
   3466 
   3467 
   3468 /*
   3469  * 'httpWriteResponse()' - Write a HTTP response to a client connection.
   3470  *
   3471  * @since CUPS 1.7/macOS 10.9@
   3472  */
   3473 
   3474 int					/* O - 0 on success, -1 on error */
   3475 httpWriteResponse(http_t        *http,	/* I - HTTP connection */
   3476 		  http_status_t status)	/* I - Status code */
   3477 {
   3478   http_encoding_t	old_encoding;	/* Old data_encoding value */
   3479   off_t			old_remaining;	/* Old data_remaining value */
   3480 
   3481 
   3482  /*
   3483   * Range check input...
   3484   */
   3485 
   3486   DEBUG_printf(("httpWriteResponse(http=%p, status=%d)", (void *)http, status));
   3487 
   3488   if (!http || status < HTTP_STATUS_CONTINUE)
   3489   {
   3490     DEBUG_puts("1httpWriteResponse: Bad input.");
   3491     return (-1);
   3492   }
   3493 
   3494  /*
   3495   * Set the various standard fields if they aren't already...
   3496   */
   3497 
   3498   if (!http->fields[HTTP_FIELD_DATE][0])
   3499     httpSetField(http, HTTP_FIELD_DATE, httpGetDateString(time(NULL)));
   3500 
   3501   if (status >= HTTP_STATUS_BAD_REQUEST && http->keep_alive)
   3502   {
   3503     http->keep_alive = HTTP_KEEPALIVE_OFF;
   3504     httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "");
   3505   }
   3506 
   3507   if (http->version == HTTP_VERSION_1_1)
   3508   {
   3509     if (!http->fields[HTTP_FIELD_CONNECTION][0])
   3510     {
   3511       if (http->keep_alive)
   3512 	httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive");
   3513       else
   3514 	httpSetField(http, HTTP_FIELD_CONNECTION, "close");
   3515     }
   3516 
   3517     if (http->keep_alive && !http->fields[HTTP_FIELD_KEEP_ALIVE][0])
   3518       httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "timeout=10");
   3519   }
   3520 
   3521 #ifdef HAVE_SSL
   3522   if (status == HTTP_STATUS_UPGRADE_REQUIRED ||
   3523       status == HTTP_STATUS_SWITCHING_PROTOCOLS)
   3524   {
   3525     if (!http->fields[HTTP_FIELD_CONNECTION][0])
   3526       httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
   3527 
   3528     if (!http->fields[HTTP_FIELD_UPGRADE][0])
   3529       httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
   3530 
   3531     if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
   3532       httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, "0");
   3533   }
   3534 #endif /* HAVE_SSL */
   3535 
   3536   if (!http->server)
   3537     httpSetField(http, HTTP_FIELD_SERVER,
   3538                  http->default_server ? http->default_server : CUPS_MINIMAL);
   3539 
   3540  /*
   3541   * Set the Accept-Encoding field if it isn't already...
   3542   */
   3543 
   3544   if (!http->accept_encoding)
   3545     httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
   3546                  http->default_accept_encoding ? http->default_accept_encoding :
   3547 #ifdef HAVE_LIBZ
   3548                                                  "gzip, deflate, identity");
   3549 #else
   3550                                                  "identity");
   3551 #endif /* HAVE_LIBZ */
   3552 
   3553  /*
   3554   * Send the response header...
   3555   */
   3556 
   3557   old_encoding        = http->data_encoding;
   3558   old_remaining       = http->data_remaining;
   3559   http->data_encoding = HTTP_ENCODING_FIELDS;
   3560 
   3561   if (httpPrintf(http, "HTTP/%d.%d %d %s\r\n", http->version / 100,
   3562                  http->version % 100, (int)status, httpStatus(status)) < 0)
   3563   {
   3564     http->status = HTTP_STATUS_ERROR;
   3565     return (-1);
   3566   }
   3567 
   3568   if (status != HTTP_STATUS_CONTINUE)
   3569   {
   3570    /*
   3571     * 100 Continue doesn't have the rest of the response headers...
   3572     */
   3573 
   3574     int		i;			/* Looping var */
   3575     const char	*value;			/* Field value */
   3576 
   3577     for (i = 0; i < HTTP_FIELD_MAX; i ++)
   3578     {
   3579       if ((value = httpGetField(http, i)) != NULL && *value)
   3580       {
   3581 	if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
   3582 	{
   3583 	  http->status = HTTP_STATUS_ERROR;
   3584 	  return (-1);
   3585 	}
   3586       }
   3587     }
   3588 
   3589     if (http->cookie)
   3590     {
   3591       if (strchr(http->cookie, ';'))
   3592       {
   3593         if (httpPrintf(http, "Set-Cookie: %s\r\n", http->cookie) < 1)
   3594 	{
   3595 	  http->status = HTTP_STATUS_ERROR;
   3596 	  return (-1);
   3597 	}
   3598       }
   3599       else if (httpPrintf(http, "Set-Cookie: %s; path=/; httponly;%s\r\n", http->cookie, http->tls ? " secure;" : "") < 1)
   3600       {
   3601 	http->status = HTTP_STATUS_ERROR;
   3602 	return (-1);
   3603       }
   3604     }
   3605 
   3606    /*
   3607     * "Click-jacking" defense (STR #4492)...
   3608     */
   3609 
   3610     if (httpPrintf(http, "X-Frame-Options: DENY\r\n"
   3611                          "Content-Security-Policy: frame-ancestors 'none'\r\n") < 1)
   3612     {
   3613       http->status = HTTP_STATUS_ERROR;
   3614       return (-1);
   3615     }
   3616   }
   3617 
   3618   if (httpWrite2(http, "\r\n", 2) < 2)
   3619   {
   3620     http->status = HTTP_STATUS_ERROR;
   3621     return (-1);
   3622   }
   3623 
   3624   if (httpFlushWrite(http) < 0)
   3625   {
   3626     http->status = HTTP_STATUS_ERROR;
   3627     return (-1);
   3628   }
   3629 
   3630   if (status == HTTP_STATUS_CONTINUE ||
   3631       status == HTTP_STATUS_SWITCHING_PROTOCOLS)
   3632   {
   3633    /*
   3634     * Restore the old data_encoding and data_length values...
   3635     */
   3636 
   3637     http->data_encoding  = old_encoding;
   3638     http->data_remaining = old_remaining;
   3639 
   3640     if (old_remaining <= INT_MAX)
   3641       http->_data_remaining = (int)old_remaining;
   3642     else
   3643       http->_data_remaining = INT_MAX;
   3644   }
   3645   else if (http->state == HTTP_STATE_OPTIONS ||
   3646            http->state == HTTP_STATE_HEAD ||
   3647            http->state == HTTP_STATE_PUT ||
   3648            http->state == HTTP_STATE_TRACE ||
   3649            http->state == HTTP_STATE_CONNECT ||
   3650            http->state == HTTP_STATE_STATUS)
   3651   {
   3652     DEBUG_printf(("1httpWriteResponse: Resetting state to HTTP_STATE_WAITING, "
   3653                   "was %s.", httpStateString(http->state)));
   3654     http->state = HTTP_STATE_WAITING;
   3655   }
   3656   else
   3657   {
   3658    /*
   3659     * Force data_encoding and data_length to be set according to the response
   3660     * headers...
   3661     */
   3662 
   3663     http_set_length(http);
   3664 
   3665     if (http->data_encoding == HTTP_ENCODING_LENGTH && http->data_remaining == 0)
   3666     {
   3667       DEBUG_printf(("1httpWriteResponse: Resetting state to HTTP_STATE_WAITING, "
   3668                     "was %s.", httpStateString(http->state)));
   3669       http->state = HTTP_STATE_WAITING;
   3670       return (0);
   3671     }
   3672 
   3673     if (http->state == HTTP_STATE_POST_RECV || http->state == HTTP_STATE_GET)
   3674       http->state ++;
   3675 
   3676 #ifdef HAVE_LIBZ
   3677    /*
   3678     * Then start any content encoding...
   3679     */
   3680 
   3681     DEBUG_puts("1httpWriteResponse: Calling http_content_coding_start.");
   3682     http_content_coding_start(http,
   3683 			      httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
   3684 #endif /* HAVE_LIBZ */
   3685 
   3686   }
   3687 
   3688   return (0);
   3689 }
   3690 
   3691 
   3692 #ifdef HAVE_LIBZ
   3693 /*
   3694  * 'http_content_coding_finish()' - Finish doing any content encoding.
   3695  */
   3696 
   3697 static void
   3698 http_content_coding_finish(
   3699     http_t *http)			/* I - HTTP connection */
   3700 {
   3701   int		zerr;			/* Compression status */
   3702   Byte		dummy[1];		/* Dummy read buffer */
   3703   size_t	bytes;			/* Number of bytes to write */
   3704 
   3705 
   3706   DEBUG_printf(("http_content_coding_finish(http=%p)", (void *)http));
   3707   DEBUG_printf(("1http_content_coding_finishing: http->coding=%d", http->coding));
   3708 
   3709   switch (http->coding)
   3710   {
   3711     case _HTTP_CODING_DEFLATE :
   3712     case _HTTP_CODING_GZIP :
   3713         http->stream.next_in  = dummy;
   3714         http->stream.avail_in = 0;
   3715 
   3716         do
   3717         {
   3718           zerr  = deflate(&(http->stream), Z_FINISH);
   3719 	  bytes = _HTTP_MAX_SBUFFER - http->stream.avail_out;
   3720 
   3721           if (bytes > 0)
   3722 	  {
   3723 	    DEBUG_printf(("1http_content_coding_finish: Writing trailing chunk, len=%d", (int)bytes));
   3724 
   3725 	    if (http->data_encoding == HTTP_ENCODING_CHUNKED)
   3726 	      http_write_chunk(http, (char *)http->sbuffer, bytes);
   3727 	    else
   3728 	      http_write(http, (char *)http->sbuffer, bytes);
   3729           }
   3730 
   3731           http->stream.next_out  = (Bytef *)http->sbuffer;
   3732           http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER;
   3733 	}
   3734         while (zerr == Z_OK);
   3735 
   3736         deflateEnd(&(http->stream));
   3737 
   3738         free(http->sbuffer);
   3739         http->sbuffer = NULL;
   3740 
   3741         if (http->wused)
   3742           httpFlushWrite(http);
   3743         break;
   3744 
   3745     case _HTTP_CODING_INFLATE :
   3746     case _HTTP_CODING_GUNZIP :
   3747         inflateEnd(&(http->stream));
   3748         free(http->sbuffer);
   3749         http->sbuffer = NULL;
   3750         break;
   3751 
   3752     default :
   3753         break;
   3754   }
   3755 
   3756   http->coding = _HTTP_CODING_IDENTITY;
   3757 }
   3758 
   3759 
   3760 /*
   3761  * 'http_content_coding_start()' - Start doing content encoding.
   3762  */
   3763 
   3764 static void
   3765 http_content_coding_start(
   3766     http_t     *http,			/* I - HTTP connection */
   3767     const char *value)			/* I - Value of Content-Encoding */
   3768 {
   3769   int			zerr;		/* Error/status */
   3770   _http_coding_t	coding;		/* Content coding value */
   3771 
   3772 
   3773   DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", (void *)http, value));
   3774 
   3775   if (http->coding != _HTTP_CODING_IDENTITY)
   3776   {
   3777     DEBUG_printf(("1http_content_coding_start: http->coding already %d.",
   3778                   http->coding));
   3779     return;
   3780   }
   3781   else if (!strcmp(value, "x-gzip") || !strcmp(value, "gzip"))
   3782   {
   3783     if (http->state == HTTP_STATE_GET_SEND ||
   3784         http->state == HTTP_STATE_POST_SEND)
   3785       coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_GZIP :
   3786                                                  _HTTP_CODING_GUNZIP;
   3787     else if (http->state == HTTP_STATE_POST_RECV ||
   3788              http->state == HTTP_STATE_PUT_RECV)
   3789       coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_GZIP :
   3790                                                  _HTTP_CODING_GUNZIP;
   3791     else
   3792     {
   3793       DEBUG_puts("1http_content_coding_start: Not doing content coding.");
   3794       return;
   3795     }
   3796   }
   3797   else if (!strcmp(value, "x-deflate") || !strcmp(value, "deflate"))
   3798   {
   3799     if (http->state == HTTP_STATE_GET_SEND ||
   3800         http->state == HTTP_STATE_POST_SEND)
   3801       coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_DEFLATE :
   3802                                                  _HTTP_CODING_INFLATE;
   3803     else if (http->state == HTTP_STATE_POST_RECV ||
   3804              http->state == HTTP_STATE_PUT_RECV)
   3805       coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_DEFLATE :
   3806                                                  _HTTP_CODING_INFLATE;
   3807     else
   3808     {
   3809       DEBUG_puts("1http_content_coding_start: Not doing content coding.");
   3810       return;
   3811     }
   3812   }
   3813   else
   3814   {
   3815     DEBUG_puts("1http_content_coding_start: Not doing content coding.");
   3816     return;
   3817   }
   3818 
   3819   memset(&(http->stream), 0, sizeof(http->stream));
   3820 
   3821   switch (coding)
   3822   {
   3823     case _HTTP_CODING_DEFLATE :
   3824     case _HTTP_CODING_GZIP :
   3825         if (http->wused)
   3826           httpFlushWrite(http);
   3827 
   3828         if ((http->sbuffer = malloc(_HTTP_MAX_SBUFFER)) == NULL)
   3829         {
   3830           http->status = HTTP_STATUS_ERROR;
   3831           http->error  = errno;
   3832           return;
   3833         }
   3834 
   3835        /*
   3836         * Window size for compression is 11 bits - optimal based on PWG Raster
   3837         * sample files on pwg.org.  -11 is raw deflate, 27 is gzip, per ZLIB
   3838         * documentation.
   3839         */
   3840 
   3841         if ((zerr = deflateInit2(&(http->stream), Z_DEFAULT_COMPRESSION,
   3842                                  Z_DEFLATED,
   3843 				 coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7,
   3844 				 Z_DEFAULT_STRATEGY)) < Z_OK)
   3845         {
   3846           http->status = HTTP_STATUS_ERROR;
   3847           http->error  = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
   3848           return;
   3849         }
   3850 
   3851 	http->stream.next_out  = (Bytef *)http->sbuffer;
   3852 	http->stream.avail_out = (uInt)_HTTP_MAX_SBUFFER;
   3853         break;
   3854 
   3855     case _HTTP_CODING_INFLATE :
   3856     case _HTTP_CODING_GUNZIP :
   3857         if ((http->sbuffer = malloc(_HTTP_MAX_SBUFFER)) == NULL)
   3858         {
   3859           http->status = HTTP_STATUS_ERROR;
   3860           http->error  = errno;
   3861           return;
   3862         }
   3863 
   3864        /*
   3865         * Window size for decompression is up to 15 bits (maximum supported).
   3866         * -15 is raw inflate, 31 is gunzip, per ZLIB documentation.
   3867         */
   3868 
   3869         if ((zerr = inflateInit2(&(http->stream),
   3870                                  coding == _HTTP_CODING_INFLATE ? -15 : 31))
   3871 		< Z_OK)
   3872         {
   3873           free(http->sbuffer);
   3874           http->sbuffer = NULL;
   3875           http->status  = HTTP_STATUS_ERROR;
   3876           http->error   = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
   3877           return;
   3878         }
   3879 
   3880         http->stream.avail_in = 0;
   3881         http->stream.next_in  = http->sbuffer;
   3882         break;
   3883 
   3884     default :
   3885         break;
   3886   }
   3887 
   3888   http->coding = coding;
   3889 
   3890   DEBUG_printf(("1http_content_coding_start: http->coding now %d.",
   3891 		http->coding));
   3892 }
   3893 #endif /* HAVE_LIBZ */
   3894 
   3895 
   3896 /*
   3897  * 'http_create()' - Create an unconnected HTTP connection.
   3898  */
   3899 
   3900 static http_t *				/* O - HTTP connection */
   3901 http_create(
   3902     const char        *host,		/* I - Hostname */
   3903     int               port,		/* I - Port number */
   3904     http_addrlist_t   *addrlist,	/* I - Address list or @code NULL@ */
   3905     int               family,		/* I - Address family or AF_UNSPEC */
   3906     http_encryption_t encryption,	/* I - Encryption to use */
   3907     int               blocking,		/* I - 1 for blocking mode */
   3908     _http_mode_t      mode)		/* I - _HTTP_MODE_CLIENT or _SERVER */
   3909 {
   3910   http_t	*http;			/* New HTTP connection */
   3911   char		service[255];		/* Service name */
   3912   http_addrlist_t *myaddrlist = NULL;	/* My address list */
   3913 
   3914 
   3915   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));
   3916 
   3917   if (!host && mode == _HTTP_MODE_CLIENT)
   3918     return (NULL);
   3919 
   3920   httpInitialize();
   3921 
   3922  /*
   3923   * Lookup the host...
   3924   */
   3925 
   3926   if (addrlist)
   3927   {
   3928     myaddrlist = httpAddrCopyList(addrlist);
   3929   }
   3930   else
   3931   {
   3932     snprintf(service, sizeof(service), "%d", port);
   3933 
   3934     myaddrlist = httpAddrGetList(host, family, service);
   3935   }
   3936 
   3937   if (!myaddrlist)
   3938     return (NULL);
   3939 
   3940  /*
   3941   * Allocate memory for the structure...
   3942   */
   3943 
   3944   if ((http = calloc(sizeof(http_t), 1)) == NULL)
   3945   {
   3946     _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
   3947     httpAddrFreeList(addrlist);
   3948     return (NULL);
   3949   }
   3950 
   3951  /*
   3952   * Initialize the HTTP data...
   3953   */
   3954 
   3955   http->mode     = mode;
   3956   http->activity = time(NULL);
   3957   http->addrlist = myaddrlist;
   3958   http->blocking = blocking;
   3959   http->fd       = -1;
   3960 #ifdef HAVE_GSSAPI
   3961   http->gssctx   = GSS_C_NO_CONTEXT;
   3962   http->gssname  = GSS_C_NO_NAME;
   3963 #endif /* HAVE_GSSAPI */
   3964   http->status   = HTTP_STATUS_CONTINUE;
   3965   http->version  = HTTP_VERSION_1_1;
   3966 
   3967   if (host)
   3968     strlcpy(http->hostname, host, sizeof(http->hostname));
   3969 
   3970   if (port == 443)			/* Always use encryption for https */
   3971     http->encryption = HTTP_ENCRYPTION_ALWAYS;
   3972   else
   3973     http->encryption = encryption;
   3974 
   3975   http_set_wait(http);
   3976 
   3977  /*
   3978   * Return the new structure...
   3979   */
   3980 
   3981   return (http);
   3982 }
   3983 
   3984 
   3985 #ifdef DEBUG
   3986 /*
   3987  * 'http_debug_hex()' - Do a hex dump of a buffer.
   3988  */
   3989 
   3990 static void
   3991 http_debug_hex(const char *prefix,	/* I - Prefix for line */
   3992                const char *buffer,	/* I - Buffer to dump */
   3993                int        bytes)	/* I - Bytes to dump */
   3994 {
   3995   int	i, j,				/* Looping vars */
   3996 	ch;				/* Current character */
   3997   char	line[255],			/* Line buffer */
   3998 	*start,				/* Start of line after prefix */
   3999 	*ptr;				/* Pointer into line */
   4000 
   4001 
   4002   if (_cups_debug_fd < 0 || _cups_debug_level < 6)
   4003     return;
   4004 
   4005   DEBUG_printf(("6%s: %d bytes:", prefix, bytes));
   4006 
   4007   snprintf(line, sizeof(line), "6%s: ", prefix);
   4008   start = line + strlen(line);
   4009 
   4010   for (i = 0; i < bytes; i += 16)
   4011   {
   4012     for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
   4013       snprintf(ptr, 3, "%02X", buffer[i + j] & 255);
   4014 
   4015     while (j < 16)
   4016     {
   4017       memcpy(ptr, "  ", 3);
   4018       ptr += 2;
   4019       j ++;
   4020     }
   4021 
   4022     memcpy(ptr, "  ", 3);
   4023     ptr += 2;
   4024 
   4025     for (j = 0; j < 16 && (i + j) < bytes; j ++)
   4026     {
   4027       ch = buffer[i + j] & 255;
   4028 
   4029       if (ch < ' ' || ch >= 127)
   4030 	ch = '.';
   4031 
   4032       *ptr++ = (char)ch;
   4033     }
   4034 
   4035     *ptr = '\0';
   4036     DEBUG_puts(line);
   4037   }
   4038 }
   4039 #endif /* DEBUG */
   4040 
   4041 
   4042 /*
   4043  * 'http_read()' - Read a buffer from a HTTP connection.
   4044  *
   4045  * This function does the low-level read from the socket, retrying and timing
   4046  * out as needed.
   4047  */
   4048 
   4049 static ssize_t				/* O - Number of bytes read or -1 on error */
   4050 http_read(http_t *http,			/* I - HTTP connection */
   4051           char   *buffer,		/* I - Buffer */
   4052           size_t length)		/* I - Maximum bytes to read */
   4053 {
   4054   ssize_t	bytes;			/* Bytes read */
   4055 
   4056 
   4057   DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   4058 
   4059   if (!http->blocking)
   4060   {
   4061     while (!httpWait(http, http->wait_value))
   4062     {
   4063       if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   4064 	continue;
   4065 
   4066       DEBUG_puts("2http_read: Timeout.");
   4067       return (0);
   4068     }
   4069   }
   4070 
   4071   DEBUG_printf(("2http_read: Reading %d bytes into buffer.", (int)length));
   4072 
   4073   do
   4074   {
   4075 #ifdef HAVE_SSL
   4076     if (http->tls)
   4077       bytes = _httpTLSRead(http, buffer, (int)length);
   4078     else
   4079 #endif /* HAVE_SSL */
   4080     bytes = recv(http->fd, buffer, length, 0);
   4081 
   4082     if (bytes < 0)
   4083     {
   4084 #ifdef WIN32
   4085       if (WSAGetLastError() != WSAEINTR)
   4086       {
   4087 	http->error = WSAGetLastError();
   4088 	return (-1);
   4089       }
   4090       else if (WSAGetLastError() == WSAEWOULDBLOCK)
   4091       {
   4092 	if (!http->timeout_cb ||
   4093 	    !(*http->timeout_cb)(http, http->timeout_data))
   4094 	{
   4095 	  http->error = WSAEWOULDBLOCK;
   4096 	  return (-1);
   4097 	}
   4098       }
   4099 #else
   4100       DEBUG_printf(("2http_read: %s", strerror(errno)));
   4101 
   4102       if (errno == EWOULDBLOCK || errno == EAGAIN)
   4103       {
   4104 	if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
   4105 	{
   4106 	  http->error = errno;
   4107 	  return (-1);
   4108 	}
   4109 	else if (!http->timeout_cb && errno != EAGAIN)
   4110 	{
   4111 	  http->error = errno;
   4112 	  return (-1);
   4113 	}
   4114       }
   4115       else if (errno != EINTR)
   4116       {
   4117 	http->error = errno;
   4118 	return (-1);
   4119       }
   4120 #endif /* WIN32 */
   4121     }
   4122   }
   4123   while (bytes < 0);
   4124 
   4125   DEBUG_printf(("2http_read: Read " CUPS_LLFMT " bytes into buffer.",
   4126 		CUPS_LLCAST bytes));
   4127 #ifdef DEBUG
   4128   if (bytes > 0)
   4129     http_debug_hex("http_read", buffer, (int)bytes);
   4130 #endif /* DEBUG */
   4131 
   4132   if (bytes < 0)
   4133   {
   4134 #ifdef WIN32
   4135     if (WSAGetLastError() == WSAEINTR)
   4136       bytes = 0;
   4137     else
   4138       http->error = WSAGetLastError();
   4139 #else
   4140     if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
   4141       bytes = 0;
   4142     else
   4143       http->error = errno;
   4144 #endif /* WIN32 */
   4145   }
   4146   else if (bytes == 0)
   4147   {
   4148     http->error = EPIPE;
   4149     return (0);
   4150   }
   4151 
   4152   return (bytes);
   4153 }
   4154 
   4155 
   4156 /*
   4157  * 'http_read_buffered()' - Do a buffered read from a HTTP connection.
   4158  *
   4159  * This function reads data from the HTTP buffer or from the socket, as needed.
   4160  */
   4161 
   4162 static ssize_t				/* O - Number of bytes read or -1 on error */
   4163 http_read_buffered(http_t *http,	/* I - HTTP connection */
   4164                    char   *buffer,	/* I - Buffer */
   4165                    size_t length)	/* I - Maximum bytes to read */
   4166 {
   4167   ssize_t	bytes;			/* Bytes read */
   4168 
   4169 
   4170   DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT ") used=%d", (void *)http, (void *)buffer, CUPS_LLCAST length, http->used));
   4171 
   4172   if (http->used > 0)
   4173   {
   4174     if (length > (size_t)http->used)
   4175       bytes = (ssize_t)http->used;
   4176     else
   4177       bytes = (ssize_t)length;
   4178 
   4179     DEBUG_printf(("2http_read: Grabbing %d bytes from input buffer.",
   4180                   (int)bytes));
   4181 
   4182     memcpy(buffer, http->buffer, (size_t)bytes);
   4183     http->used -= (int)bytes;
   4184 
   4185     if (http->used > 0)
   4186       memmove(http->buffer, http->buffer + bytes, (size_t)http->used);
   4187   }
   4188   else
   4189     bytes = http_read(http, buffer, length);
   4190 
   4191   return (bytes);
   4192 }
   4193 
   4194 
   4195 /*
   4196  * 'http_read_chunk()' - Read a chunk from a HTTP connection.
   4197  *
   4198  * This function reads and validates the chunk length, then does a buffered read
   4199  * returning the number of bytes placed in the buffer.
   4200  */
   4201 
   4202 static ssize_t				/* O - Number of bytes read or -1 on error */
   4203 http_read_chunk(http_t *http,		/* I - HTTP connection */
   4204 		char   *buffer,		/* I - Buffer */
   4205 		size_t length)		/* I - Maximum bytes to read */
   4206 {
   4207   DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   4208 
   4209   if (http->data_remaining <= 0)
   4210   {
   4211     char	len[32];		/* Length string */
   4212 
   4213     if (!httpGets(len, sizeof(len), http))
   4214     {
   4215       DEBUG_puts("1http_read_chunk: Could not get chunk length.");
   4216       return (0);
   4217     }
   4218 
   4219     if (!len[0])
   4220     {
   4221       DEBUG_puts("1http_read_chunk: Blank chunk length, trying again...");
   4222       if (!httpGets(len, sizeof(len), http))
   4223       {
   4224 	DEBUG_puts("1http_read_chunk: Could not get chunk length.");
   4225 	return (0);
   4226       }
   4227     }
   4228 
   4229     http->data_remaining = strtoll(len, NULL, 16);
   4230 
   4231     if (http->data_remaining < 0)
   4232     {
   4233       DEBUG_printf(("1http_read_chunk: Negative chunk length \"%s\" ("
   4234                     CUPS_LLFMT ")", len, CUPS_LLCAST http->data_remaining));
   4235       return (0);
   4236     }
   4237 
   4238     DEBUG_printf(("2http_read_chunk: Got chunk length \"%s\" (" CUPS_LLFMT ")",
   4239                   len, CUPS_LLCAST http->data_remaining));
   4240 
   4241     if (http->data_remaining == 0)
   4242     {
   4243      /*
   4244       * 0-length chunk, grab trailing blank line...
   4245       */
   4246 
   4247       httpGets(len, sizeof(len), http);
   4248     }
   4249   }
   4250 
   4251   DEBUG_printf(("2http_read_chunk: data_remaining=" CUPS_LLFMT,
   4252                 CUPS_LLCAST http->data_remaining));
   4253 
   4254   if (http->data_remaining <= 0)
   4255     return (0);
   4256   else if (length > (size_t)http->data_remaining)
   4257     length = (size_t)http->data_remaining;
   4258 
   4259   return (http_read_buffered(http, buffer, length));
   4260 }
   4261 
   4262 
   4263 /*
   4264  * 'http_send()' - Send a request with all fields and the trailing blank line.
   4265  */
   4266 
   4267 static int				/* O - 0 on success, non-zero on error */
   4268 http_send(http_t       *http,		/* I - HTTP connection */
   4269           http_state_t request,		/* I - Request code */
   4270 	  const char   *uri)		/* I - URI */
   4271 {
   4272   int		i;			/* Looping var */
   4273   char		buf[1024];		/* Encoded URI buffer */
   4274   const char	*value;			/* Field value */
   4275   static const char * const codes[] =	/* Request code strings */
   4276 		{
   4277 		  NULL,
   4278 		  "OPTIONS",
   4279 		  "GET",
   4280 		  NULL,
   4281 		  "HEAD",
   4282 		  "POST",
   4283 		  NULL,
   4284 		  NULL,
   4285 		  "PUT",
   4286 		  NULL,
   4287 		  "DELETE",
   4288 		  "TRACE",
   4289 		  "CLOSE",
   4290 		  NULL,
   4291 		  NULL
   4292 		};
   4293 
   4294 
   4295   DEBUG_printf(("4http_send(http=%p, request=HTTP_%s, uri=\"%s\")", (void *)http, codes[request], uri));
   4296 
   4297   if (http == NULL || uri == NULL)
   4298     return (-1);
   4299 
   4300  /*
   4301   * Set the User-Agent field if it isn't already...
   4302   */
   4303 
   4304   if (!http->fields[HTTP_FIELD_USER_AGENT][0])
   4305   {
   4306     if (http->default_user_agent)
   4307       httpSetField(http, HTTP_FIELD_USER_AGENT, http->default_user_agent);
   4308     else
   4309       httpSetField(http, HTTP_FIELD_USER_AGENT, cupsUserAgent());
   4310   }
   4311 
   4312  /*
   4313   * Set the Accept-Encoding field if it isn't already...
   4314   */
   4315 
   4316   if (!http->accept_encoding && http->default_accept_encoding)
   4317     httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
   4318                  http->default_accept_encoding);
   4319 
   4320  /*
   4321   * Encode the URI as needed...
   4322   */
   4323 
   4324   _httpEncodeURI(buf, uri, sizeof(buf));
   4325 
   4326  /*
   4327   * See if we had an error the last time around; if so, reconnect...
   4328   */
   4329 
   4330   if (http->fd < 0 || http->status == HTTP_STATUS_ERROR ||
   4331       http->status >= HTTP_STATUS_BAD_REQUEST)
   4332   {
   4333     DEBUG_printf(("5http_send: Reconnecting, fd=%d, status=%d, tls_upgrade=%d",
   4334                   http->fd, http->status, http->tls_upgrade));
   4335 
   4336     if (httpReconnect2(http, 30000, NULL))
   4337       return (-1);
   4338   }
   4339 
   4340  /*
   4341   * Flush any written data that is pending...
   4342   */
   4343 
   4344   if (http->wused)
   4345   {
   4346     if (httpFlushWrite(http) < 0)
   4347       if (httpReconnect2(http, 30000, NULL))
   4348         return (-1);
   4349   }
   4350 
   4351  /*
   4352   * Send the request header...
   4353   */
   4354 
   4355   http->state         = request;
   4356   http->data_encoding = HTTP_ENCODING_FIELDS;
   4357 
   4358   if (request == HTTP_STATE_POST || request == HTTP_STATE_PUT)
   4359     http->state ++;
   4360 
   4361   http->status = HTTP_STATUS_CONTINUE;
   4362 
   4363 #ifdef HAVE_SSL
   4364   if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls)
   4365   {
   4366     httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
   4367     httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
   4368   }
   4369 #endif /* HAVE_SSL */
   4370 
   4371   if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
   4372   {
   4373     http->status = HTTP_STATUS_ERROR;
   4374     return (-1);
   4375   }
   4376 
   4377   for (i = 0; i < HTTP_FIELD_MAX; i ++)
   4378     if ((value = httpGetField(http, i)) != NULL && *value)
   4379     {
   4380       DEBUG_printf(("5http_send: %s: %s", http_fields[i], value));
   4381 
   4382       if (i == HTTP_FIELD_HOST)
   4383       {
   4384 	if (httpPrintf(http, "Host: %s:%d\r\n", value,
   4385 	               httpAddrPort(http->hostaddr)) < 1)
   4386 	{
   4387 	  http->status = HTTP_STATUS_ERROR;
   4388 	  return (-1);
   4389 	}
   4390       }
   4391       else if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
   4392       {
   4393 	http->status = HTTP_STATUS_ERROR;
   4394 	return (-1);
   4395       }
   4396     }
   4397 
   4398   if (http->cookie)
   4399     if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
   4400     {
   4401       http->status = HTTP_STATUS_ERROR;
   4402       return (-1);
   4403     }
   4404 
   4405   DEBUG_printf(("5http_send: expect=%d, mode=%d, state=%d", http->expect,
   4406                 http->mode, http->state));
   4407 
   4408   if (http->expect == HTTP_STATUS_CONTINUE && http->mode == _HTTP_MODE_CLIENT &&
   4409       (http->state == HTTP_STATE_POST_RECV ||
   4410        http->state == HTTP_STATE_PUT_RECV))
   4411     if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
   4412     {
   4413       http->status = HTTP_STATUS_ERROR;
   4414       return (-1);
   4415     }
   4416 
   4417   if (httpPrintf(http, "\r\n") < 1)
   4418   {
   4419     http->status = HTTP_STATUS_ERROR;
   4420     return (-1);
   4421   }
   4422 
   4423   if (httpFlushWrite(http) < 0)
   4424     return (-1);
   4425 
   4426   http_set_length(http);
   4427   httpClearFields(http);
   4428 
   4429  /*
   4430   * The Kerberos and AuthRef authentication strings can only be used once...
   4431   */
   4432 
   4433   if (http->field_authorization && http->authstring &&
   4434       (!strncmp(http->authstring, "Negotiate", 9) ||
   4435        !strncmp(http->authstring, "AuthRef", 7)))
   4436   {
   4437     http->_authstring[0] = '\0';
   4438 
   4439     if (http->authstring != http->_authstring)
   4440       free(http->authstring);
   4441 
   4442     http->authstring = http->_authstring;
   4443   }
   4444 
   4445   return (0);
   4446 }
   4447 
   4448 
   4449 /*
   4450  * 'http_set_length()' - Set the data_encoding and data_remaining values.
   4451  */
   4452 
   4453 static off_t				/* O - Remainder or -1 on error */
   4454 http_set_length(http_t *http)		/* I - Connection */
   4455 {
   4456   off_t	remaining;			/* Remainder */
   4457 
   4458 
   4459   DEBUG_printf(("http_set_length(http=%p) mode=%d state=%s", (void *)http, http->mode, httpStateString(http->state)));
   4460 
   4461   if ((remaining = httpGetLength2(http)) >= 0)
   4462   {
   4463     if (http->mode == _HTTP_MODE_SERVER &&
   4464 	http->state != HTTP_STATE_GET_SEND &&
   4465 	http->state != HTTP_STATE_PUT &&
   4466 	http->state != HTTP_STATE_POST &&
   4467 	http->state != HTTP_STATE_POST_SEND)
   4468     {
   4469       DEBUG_puts("1http_set_length: Not setting data_encoding/remaining.");
   4470       return (remaining);
   4471     }
   4472 
   4473     if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING],
   4474                           "chunked"))
   4475     {
   4476       DEBUG_puts("1http_set_length: Setting data_encoding to "
   4477                  "HTTP_ENCODING_CHUNKED.");
   4478       http->data_encoding = HTTP_ENCODING_CHUNKED;
   4479     }
   4480     else
   4481     {
   4482       DEBUG_puts("1http_set_length: Setting data_encoding to "
   4483                  "HTTP_ENCODING_LENGTH.");
   4484       http->data_encoding = HTTP_ENCODING_LENGTH;
   4485     }
   4486 
   4487     DEBUG_printf(("1http_set_length: Setting data_remaining to " CUPS_LLFMT ".",
   4488                   CUPS_LLCAST remaining));
   4489     http->data_remaining = remaining;
   4490 
   4491     if (remaining <= INT_MAX)
   4492       http->_data_remaining = (int)remaining;
   4493     else
   4494       http->_data_remaining = INT_MAX;
   4495   }
   4496 
   4497   return (remaining);
   4498 }
   4499 
   4500 /*
   4501  * 'http_set_timeout()' - Set the socket timeout values.
   4502  */
   4503 
   4504 static void
   4505 http_set_timeout(int    fd,		/* I - File descriptor */
   4506                  double timeout)	/* I - Timeout in seconds */
   4507 {
   4508 #ifdef WIN32
   4509   DWORD tv = (DWORD)(timeout * 1000);
   4510 				      /* Timeout in milliseconds */
   4511 
   4512   setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
   4513   setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
   4514 
   4515 #else
   4516   struct timeval tv;			/* Timeout in secs and usecs */
   4517 
   4518   tv.tv_sec  = (int)timeout;
   4519   tv.tv_usec = (int)(1000000 * fmod(timeout, 1.0));
   4520 
   4521   setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
   4522   setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
   4523 #endif /* WIN32 */
   4524 }
   4525 
   4526 
   4527 /*
   4528  * 'http_set_wait()' - Set the default wait value for reads.
   4529  */
   4530 
   4531 static void
   4532 http_set_wait(http_t *http)		/* I - HTTP connection */
   4533 {
   4534   if (http->blocking)
   4535   {
   4536     http->wait_value = (int)(http->timeout_value * 1000);
   4537 
   4538     if (http->wait_value <= 0)
   4539       http->wait_value = 60000;
   4540   }
   4541   else
   4542     http->wait_value = 10000;
   4543 }
   4544 
   4545 
   4546 #ifdef HAVE_SSL
   4547 /*
   4548  * 'http_tls_upgrade()' - Force upgrade to TLS encryption.
   4549  */
   4550 
   4551 static int				/* O - Status of connection */
   4552 http_tls_upgrade(http_t *http)		/* I - HTTP connection */
   4553 {
   4554   int		ret;			/* Return value */
   4555   http_t	myhttp;			/* Local copy of HTTP data */
   4556 
   4557 
   4558   DEBUG_printf(("7http_tls_upgrade(%p)", (void *)http));
   4559 
   4560  /*
   4561   * Flush the connection to make sure any previous "Upgrade" message
   4562   * has been read.
   4563   */
   4564 
   4565   httpFlush(http);
   4566 
   4567  /*
   4568   * Copy the HTTP data to a local variable so we can do the OPTIONS
   4569   * request without interfering with the existing request data...
   4570   */
   4571 
   4572   memcpy(&myhttp, http, sizeof(myhttp));
   4573 
   4574  /*
   4575   * Send an OPTIONS request to the server, requiring SSL or TLS
   4576   * encryption on the link...
   4577   */
   4578 
   4579   http->tls_upgrade         = 1;
   4580   http->field_authorization = NULL;	/* Don't free the auth string */
   4581 
   4582   httpClearFields(http);
   4583   httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
   4584   httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
   4585 
   4586   if ((ret = httpOptions(http, "*")) == 0)
   4587   {
   4588    /*
   4589     * Wait for the secure connection...
   4590     */
   4591 
   4592     while (httpUpdate(http) == HTTP_STATUS_CONTINUE);
   4593   }
   4594 
   4595  /*
   4596   * Restore the HTTP request data...
   4597   */
   4598 
   4599   memcpy(http->fields, myhttp.fields, sizeof(http->fields));
   4600   http->data_encoding       = myhttp.data_encoding;
   4601   http->data_remaining      = myhttp.data_remaining;
   4602   http->_data_remaining     = myhttp._data_remaining;
   4603   http->expect              = myhttp.expect;
   4604   http->field_authorization = myhttp.field_authorization;
   4605   http->digest_tries        = myhttp.digest_tries;
   4606   http->tls_upgrade         = 0;
   4607 
   4608  /*
   4609   * See if we actually went secure...
   4610   */
   4611 
   4612   if (!http->tls)
   4613   {
   4614    /*
   4615     * Server does not support HTTP upgrade...
   4616     */
   4617 
   4618     DEBUG_puts("8http_tls_upgrade: Server does not support HTTP upgrade!");
   4619 
   4620     _cupsSetError(IPP_STATUS_ERROR_CUPS_PKI, _("Encryption is not supported."), 1);
   4621     httpAddrClose(NULL, http->fd);
   4622 
   4623     http->fd = -1;
   4624 
   4625     return (-1);
   4626   }
   4627   else
   4628     return (ret);
   4629 }
   4630 #endif /* HAVE_SSL */
   4631 
   4632 
   4633 /*
   4634  * 'http_write()' - Write a buffer to a HTTP connection.
   4635  */
   4636 
   4637 static ssize_t				/* O - Number of bytes written */
   4638 http_write(http_t     *http,		/* I - HTTP connection */
   4639            const char *buffer,		/* I - Buffer for data */
   4640 	   size_t     length)		/* I - Number of bytes to write */
   4641 {
   4642   ssize_t	tbytes,			/* Total bytes sent */
   4643 		bytes;			/* Bytes sent */
   4644 
   4645 
   4646   DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   4647   http->error = 0;
   4648   tbytes      = 0;
   4649 
   4650   while (length > 0)
   4651   {
   4652     DEBUG_printf(("3http_write: About to write %d bytes.", (int)length));
   4653 
   4654     if (http->timeout_cb)
   4655     {
   4656 #ifdef HAVE_POLL
   4657       struct pollfd	pfd;		/* Polled file descriptor */
   4658 #else
   4659       fd_set		output_set;	/* Output ready for write? */
   4660       struct timeval	timeout;	/* Timeout value */
   4661 #endif /* HAVE_POLL */
   4662       int		nfds;		/* Result from select()/poll() */
   4663 
   4664       do
   4665       {
   4666 #ifdef HAVE_POLL
   4667 	pfd.fd     = http->fd;
   4668 	pfd.events = POLLOUT;
   4669 
   4670 	while ((nfds = poll(&pfd, 1, http->wait_value)) < 0 &&
   4671 	       (errno == EINTR || errno == EAGAIN))
   4672 	  /* do nothing */;
   4673 
   4674 #else
   4675 	do
   4676 	{
   4677 	  FD_ZERO(&output_set);
   4678 	  FD_SET(http->fd, &output_set);
   4679 
   4680 	  timeout.tv_sec  = http->wait_value / 1000;
   4681 	  timeout.tv_usec = 1000 * (http->wait_value % 1000);
   4682 
   4683 	  nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout);
   4684 	}
   4685 #  ifdef WIN32
   4686 	while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
   4687 			    WSAGetLastError() == WSAEWOULDBLOCK));
   4688 #  else
   4689 	while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
   4690 #  endif /* WIN32 */
   4691 #endif /* HAVE_POLL */
   4692 
   4693         if (nfds < 0)
   4694 	{
   4695 	  http->error = errno;
   4696 	  return (-1);
   4697 	}
   4698 	else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data))
   4699 	{
   4700 #ifdef WIN32
   4701 	  http->error = WSAEWOULDBLOCK;
   4702 #else
   4703 	  http->error = EWOULDBLOCK;
   4704 #endif /* WIN32 */
   4705 	  return (-1);
   4706 	}
   4707       }
   4708       while (nfds <= 0);
   4709     }
   4710 
   4711 #ifdef HAVE_SSL
   4712     if (http->tls)
   4713       bytes = _httpTLSWrite(http, buffer, (int)length);
   4714     else
   4715 #endif /* HAVE_SSL */
   4716     bytes = send(http->fd, buffer, length, 0);
   4717 
   4718     DEBUG_printf(("3http_write: Write of " CUPS_LLFMT " bytes returned "
   4719                   CUPS_LLFMT ".", CUPS_LLCAST length, CUPS_LLCAST bytes));
   4720 
   4721     if (bytes < 0)
   4722     {
   4723 #ifdef WIN32
   4724       if (WSAGetLastError() == WSAEINTR)
   4725         continue;
   4726       else if (WSAGetLastError() == WSAEWOULDBLOCK)
   4727       {
   4728         if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   4729           continue;
   4730 
   4731         http->error = WSAGetLastError();
   4732       }
   4733       else if (WSAGetLastError() != http->error &&
   4734                WSAGetLastError() != WSAECONNRESET)
   4735       {
   4736         http->error = WSAGetLastError();
   4737 	continue;
   4738       }
   4739 
   4740 #else
   4741       if (errno == EINTR)
   4742         continue;
   4743       else if (errno == EWOULDBLOCK || errno == EAGAIN)
   4744       {
   4745 	if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
   4746           continue;
   4747         else if (!http->timeout_cb && errno == EAGAIN)
   4748 	  continue;
   4749 
   4750         http->error = errno;
   4751       }
   4752       else if (errno != http->error && errno != ECONNRESET)
   4753       {
   4754         http->error = errno;
   4755 	continue;
   4756       }
   4757 #endif /* WIN32 */
   4758 
   4759       DEBUG_printf(("3http_write: error writing data (%s).",
   4760                     strerror(http->error)));
   4761 
   4762       return (-1);
   4763     }
   4764 
   4765     buffer += bytes;
   4766     tbytes += bytes;
   4767     length -= (size_t)bytes;
   4768   }
   4769 
   4770 #ifdef DEBUG
   4771   http_debug_hex("http_write", buffer - tbytes, (int)tbytes);
   4772 #endif /* DEBUG */
   4773 
   4774   DEBUG_printf(("3http_write: Returning " CUPS_LLFMT ".", CUPS_LLCAST tbytes));
   4775 
   4776   return (tbytes);
   4777 }
   4778 
   4779 
   4780 /*
   4781  * 'http_write_chunk()' - Write a chunked buffer.
   4782  */
   4783 
   4784 static ssize_t				/* O - Number bytes written */
   4785 http_write_chunk(http_t     *http,	/* I - HTTP connection */
   4786                  const char *buffer,	/* I - Buffer to write */
   4787 		 size_t        length)	/* I - Length of buffer */
   4788 {
   4789   char		header[16];		/* Chunk header */
   4790   ssize_t	bytes;			/* Bytes written */
   4791 
   4792 
   4793   DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")", (void *)http, (void *)buffer, CUPS_LLCAST length));
   4794 
   4795  /*
   4796   * Write the chunk header, data, and trailer.
   4797   */
   4798 
   4799   snprintf(header, sizeof(header), "%x\r\n", (unsigned)length);
   4800   if (http_write(http, header, strlen(header)) < 0)
   4801   {
   4802     DEBUG_puts("8http_write_chunk: http_write of length failed.");
   4803     return (-1);
   4804   }
   4805 
   4806   if ((bytes = http_write(http, buffer, length)) < 0)
   4807   {
   4808     DEBUG_puts("8http_write_chunk: http_write of buffer failed.");
   4809     return (-1);
   4810   }
   4811 
   4812   if (http_write(http, "\r\n", 2) < 0)
   4813   {
   4814     DEBUG_puts("8http_write_chunk: http_write of CR LF failed.");
   4815     return (-1);
   4816   }
   4817 
   4818   return (bytes);
   4819 }
   4820