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