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