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