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