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