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