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