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