]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/http.c
36729b122bd19be077de10cee9da91d1c0442d84
[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 /* For OS X 10.8 and earlier */
1888 ssize_t _httpPeek(http_t *http, char *buffer, size_t length)
1889 { return (httpPeek(http, buffer, length)); }
1890
1891
1892 /*
1893 * 'httpPost()' - Send a POST request to the server.
1894 */
1895
1896 int /* O - Status of call (0 = success) */
1897 httpPost(http_t *http, /* I - HTTP connection */
1898 const char *uri) /* I - URI for post */
1899 {
1900 return (http_send(http, HTTP_STATE_POST, uri));
1901 }
1902
1903
1904 /*
1905 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
1906 *
1907 * @private@
1908 */
1909
1910 int /* O - Number of bytes written */
1911 httpPrintf(http_t *http, /* I - HTTP connection */
1912 const char *format, /* I - printf-style format string */
1913 ...) /* I - Additional args as needed */
1914 {
1915 int bytes; /* Number of bytes to write */
1916 char buf[16384]; /* Buffer for formatted string */
1917 va_list ap; /* Variable argument pointer */
1918
1919
1920 DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format));
1921
1922 va_start(ap, format);
1923 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1924 va_end(ap);
1925
1926 DEBUG_printf(("3httpPrintf: (%d bytes) %s", bytes, buf));
1927
1928 if (http->data_encoding == HTTP_ENCODING_FIELDS)
1929 return (httpWrite2(http, buf, bytes));
1930 else
1931 {
1932 if (http->wused)
1933 {
1934 DEBUG_puts("4httpPrintf: flushing existing data...");
1935
1936 if (httpFlushWrite(http) < 0)
1937 return (-1);
1938 }
1939
1940 return (http_write(http, buf, bytes));
1941 }
1942 }
1943
1944
1945 /*
1946 * 'httpPut()' - Send a PUT request to the server.
1947 */
1948
1949 int /* O - Status of call (0 = success) */
1950 httpPut(http_t *http, /* I - HTTP connection */
1951 const char *uri) /* I - URI to put */
1952 {
1953 DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri));
1954 return (http_send(http, HTTP_STATE_PUT, uri));
1955 }
1956
1957
1958 /*
1959 * 'httpRead()' - Read data from a HTTP connection.
1960 *
1961 * This function is deprecated. Use the httpRead2() function which can
1962 * read more than 2GB of data.
1963 *
1964 * @deprecated@
1965 */
1966
1967 int /* O - Number of bytes read */
1968 httpRead(http_t *http, /* I - HTTP connection */
1969 char *buffer, /* I - Buffer for data */
1970 int length) /* I - Maximum number of bytes */
1971 {
1972 return ((int)httpRead2(http, buffer, length));
1973 }
1974
1975
1976 /*
1977 * 'httpRead2()' - Read data from a HTTP connection.
1978 *
1979 * @since CUPS 1.2/OS X 10.5@
1980 */
1981
1982 ssize_t /* O - Number of bytes read */
1983 httpRead2(http_t *http, /* I - HTTP connection */
1984 char *buffer, /* I - Buffer for data */
1985 size_t length) /* I - Maximum number of bytes */
1986 {
1987 ssize_t bytes; /* Bytes read */
1988
1989
1990 #ifdef HAVE_LIBZ
1991 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT
1992 ") coding=%d data_encoding=%d data_remaining=" CUPS_LLFMT,
1993 http, buffer, CUPS_LLCAST length,
1994 http->coding,
1995 http->data_encoding, CUPS_LLCAST http->data_remaining));
1996 #else
1997 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT
1998 ") data_encoding=%d data_remaining=" CUPS_LLFMT,
1999 http, buffer, CUPS_LLCAST length,
2000 http->data_encoding, CUPS_LLCAST http->data_remaining));
2001 #endif /* HAVE_LIBZ */
2002
2003 if (http == NULL || buffer == NULL)
2004 return (-1);
2005
2006 http->activity = time(NULL);
2007 http->error = 0;
2008
2009 if (length <= 0)
2010 return (0);
2011
2012 #ifdef HAVE_LIBZ
2013 if (http->coding)
2014 {
2015 do
2016 {
2017 if (http->stream.avail_in > 0)
2018 {
2019 int zerr; /* Decompressor error */
2020
2021 DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d",
2022 (int)http->stream.avail_in, (int)length));
2023
2024 http->stream.next_out = (Bytef *)buffer;
2025 http->stream.avail_out = length;
2026
2027 if ((zerr = inflate(&(http->stream), Z_SYNC_FLUSH)) < Z_OK)
2028 {
2029 DEBUG_printf(("2httpRead2: zerr=%d", zerr));
2030 #ifdef DEBUG
2031 http_debug_hex("2httpRead2", (char *)http->dbuffer,
2032 http->stream.avail_in);
2033 #endif /* DEBUG */
2034
2035 http->error = EIO;
2036 return (-1);
2037 }
2038
2039 bytes = length - http->stream.avail_out;
2040
2041 DEBUG_printf(("2httpRead2: avail_in=%d, avail_out=%d, bytes=%d",
2042 http->stream.avail_in, http->stream.avail_out,
2043 (int)bytes));
2044 }
2045 else
2046 bytes = 0;
2047
2048 if (bytes == 0)
2049 {
2050 ssize_t buflen = HTTP_MAX_BUFFER - http->stream.avail_in;
2051 /* Additional bytes for buffer */
2052
2053 if (buflen > 0)
2054 {
2055 if (http->stream.avail_in > 0 &&
2056 http->stream.next_in > http->dbuffer)
2057 memmove(http->dbuffer, http->stream.next_in, http->stream.avail_in);
2058
2059 http->stream.next_in = http->dbuffer;
2060
2061 DEBUG_printf(("1httpRead2: Reading up to %d more bytes of data into "
2062 "decompression buffer.", (int)buflen));
2063
2064 if (http->data_remaining > 0)
2065 {
2066 if (buflen > http->data_remaining)
2067 buflen = http->data_remaining;
2068
2069 bytes = http_read_buffered(http,
2070 (char *)http->dbuffer +
2071 http->stream.avail_in, buflen);
2072 }
2073 else if (http->data_encoding == HTTP_ENCODING_CHUNKED)
2074 bytes = http_read_chunk(http,
2075 (char *)http->dbuffer +
2076 http->stream.avail_in, buflen);
2077 else
2078 bytes = 0;
2079
2080 if (bytes < 0)
2081 return (bytes);
2082 else if (bytes == 0)
2083 break;
2084
2085 DEBUG_printf(("1httpRead2: Adding " CUPS_LLFMT " bytes to "
2086 "decompression buffer.", CUPS_LLCAST bytes));
2087
2088 http->data_remaining -= bytes;
2089 http->stream.avail_in += bytes;
2090
2091 if (http->data_remaining <= 0 &&
2092 http->data_encoding == HTTP_ENCODING_CHUNKED)
2093 {
2094 /*
2095 * Read the trailing blank line now...
2096 */
2097
2098 char len[32]; /* Length string */
2099
2100 httpGets(len, sizeof(len), http);
2101 }
2102
2103 bytes = 0;
2104 }
2105 else
2106 return (0);
2107 }
2108 }
2109 while (bytes == 0);
2110 }
2111 else
2112 #endif /* HAVE_LIBZ */
2113 if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODING_CHUNKED)
2114 {
2115 if ((bytes = http_read_chunk(http, buffer, length)) > 0)
2116 {
2117 http->data_remaining -= bytes;
2118
2119 if (http->data_remaining <= 0)
2120 {
2121 /*
2122 * Read the trailing blank line now...
2123 */
2124
2125 char len[32]; /* Length string */
2126
2127 httpGets(len, sizeof(len), http);
2128 }
2129 }
2130 }
2131 else if (http->data_remaining <= 0)
2132 {
2133 /*
2134 * No more data to read...
2135 */
2136
2137 return (0);
2138 }
2139 else
2140 {
2141 DEBUG_printf(("1httpRead2: Reading up to %d bytes into buffer.",
2142 (int)length));
2143
2144 if (length > (size_t)http->data_remaining)
2145 length = (size_t)http->data_remaining;
2146
2147 if ((bytes = http_read_buffered(http, buffer, length)) > 0)
2148 {
2149 http->data_remaining -= bytes;
2150
2151 if (http->data_remaining <= 0 &&
2152 http->data_encoding == HTTP_ENCODING_CHUNKED)
2153 {
2154 /*
2155 * Read the trailing blank line now...
2156 */
2157
2158 char len[32]; /* Length string */
2159
2160 httpGets(len, sizeof(len), http);
2161 }
2162 }
2163 }
2164
2165 if (
2166 #ifdef HAVE_LIBZ
2167 (http->coding == _HTTP_CODING_IDENTITY || http->stream.avail_in == 0) &&
2168 #endif /* HAVE_LIBZ */
2169 ((http->data_remaining <= 0 &&
2170 http->data_encoding == HTTP_ENCODING_LENGTH) ||
2171 (http->data_encoding == HTTP_ENCODING_CHUNKED && bytes == 0)))
2172 {
2173 #ifdef HAVE_LIBZ
2174 if (http->coding)
2175 http_content_coding_finish(http);
2176 #endif /* HAVE_LIBZ */
2177
2178 if (http->state == HTTP_STATE_POST_RECV)
2179 http->state ++;
2180 else if (http->state == HTTP_STATE_GET_SEND ||
2181 http->state == HTTP_STATE_POST_SEND)
2182 http->state = HTTP_STATE_WAITING;
2183 else
2184 http->state = HTTP_STATE_STATUS;
2185
2186 DEBUG_printf(("1httpRead2: End of content, set state to %s.",
2187 httpStateString(http->state)));
2188 }
2189
2190 return (bytes);
2191 }
2192
2193
2194 /*
2195 * 'httpReadRequest()' - Read a HTTP request from a connection.
2196 *
2197 * @since CUPS 1.7/OS X 10.9@
2198 */
2199
2200 http_state_t /* O - New state of connection */
2201 httpReadRequest(http_t *http, /* I - HTTP connection */
2202 char *uri, /* I - URI buffer */
2203 size_t urilen) /* I - Size of URI buffer */
2204 {
2205 char line[4096], /* HTTP request line */
2206 *req_method, /* HTTP request method */
2207 *req_uri, /* HTTP request URI */
2208 *req_version; /* HTTP request version number string */
2209
2210
2211 /*
2212 * Range check input...
2213 */
2214
2215 DEBUG_printf(("httpReadRequest(http=%p, uri=%p, urilen=" CUPS_LLFMT ")",
2216 http, uri, CUPS_LLCAST urilen));
2217
2218 if (uri)
2219 *uri = '\0';
2220
2221 if (!http || !uri || urilen < 1)
2222 {
2223 DEBUG_puts("1httpReadRequest: Bad arguments, returning HTTP_STATE_ERROR.");
2224 return (HTTP_STATE_ERROR);
2225 }
2226 else if (http->state != HTTP_STATE_WAITING)
2227 {
2228 DEBUG_printf(("1httpReadRequest: Bad state %s, returning HTTP_STATE_ERROR.",
2229 httpStateString(http->state)));
2230 return (HTTP_STATE_ERROR);
2231 }
2232
2233 /*
2234 * Reset state...
2235 */
2236
2237 httpClearFields(http);
2238
2239 http->activity = time(NULL);
2240 http->data_encoding = HTTP_ENCODING_FIELDS;
2241 http->data_remaining = 0;
2242 http->keep_alive = HTTP_KEEPALIVE_OFF;
2243 http->status = HTTP_STATUS_OK;
2244 http->version = HTTP_VERSION_1_1;
2245
2246 /*
2247 * Read a line from the socket...
2248 */
2249
2250 if (!httpGets(line, sizeof(line), http))
2251 {
2252 DEBUG_puts("1httpReadRequest: Unable to read, returning HTTP_STATE_ERROR");
2253 return (HTTP_STATE_ERROR);
2254 }
2255
2256 if (!line[0])
2257 {
2258 DEBUG_puts("1httpReadRequest: Blank line, returning HTTP_STATE_WAITING");
2259 return (HTTP_STATE_WAITING);
2260 }
2261
2262 DEBUG_printf(("1httpReadRequest: %s", line));
2263
2264 /*
2265 * Parse it...
2266 */
2267
2268 req_method = line;
2269 req_uri = line;
2270
2271 while (*req_uri && !isspace(*req_uri & 255))
2272 req_uri ++;
2273
2274 if (!*req_uri)
2275 {
2276 DEBUG_puts("1httpReadRequest: No request URI.");
2277 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No request URI."), 1);
2278 return (HTTP_STATE_ERROR);
2279 }
2280
2281 *req_uri++ = '\0';
2282
2283 while (*req_uri && isspace(*req_uri & 255))
2284 req_uri ++;
2285
2286 req_version = req_uri;
2287
2288 while (*req_version && !isspace(*req_version & 255))
2289 req_version ++;
2290
2291 if (!*req_version)
2292 {
2293 DEBUG_puts("1httpReadRequest: No request protocol version.");
2294 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("No request protocol version."), 1);
2295 return (HTTP_STATE_ERROR);
2296 }
2297
2298 *req_version++ = '\0';
2299
2300 while (*req_version && isspace(*req_version & 255))
2301 req_version ++;
2302
2303 /*
2304 * Validate...
2305 */
2306
2307 if (!strcmp(req_method, "OPTIONS"))
2308 http->state = HTTP_STATE_OPTIONS;
2309 else if (!strcmp(req_method, "GET"))
2310 http->state = HTTP_STATE_GET;
2311 else if (!strcmp(req_method, "HEAD"))
2312 http->state = HTTP_STATE_HEAD;
2313 else if (!strcmp(req_method, "POST"))
2314 http->state = HTTP_STATE_POST;
2315 else if (!strcmp(req_method, "PUT"))
2316 http->state = HTTP_STATE_PUT;
2317 else if (!strcmp(req_method, "DELETE"))
2318 http->state = HTTP_STATE_DELETE;
2319 else if (!strcmp(req_method, "TRACE"))
2320 http->state = HTTP_STATE_TRACE;
2321 else if (!strcmp(req_method, "CONNECT"))
2322 http->state = HTTP_STATE_CONNECT;
2323 else
2324 {
2325 DEBUG_printf(("1httpReadRequest: Unknown method \"%s\".", req_method));
2326 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown request method."), 1);
2327 return (HTTP_STATE_UNKNOWN_METHOD);
2328 }
2329
2330 DEBUG_printf(("1httpReadRequest: Set state to %s.",
2331 httpStateString(http->state)));
2332
2333 if (!strcmp(req_version, "HTTP/1.0"))
2334 {
2335 http->version = HTTP_VERSION_1_0;
2336 http->keep_alive = HTTP_KEEPALIVE_OFF;
2337 }
2338 else if (!strcmp(req_version, "HTTP/1.1"))
2339 {
2340 http->version = HTTP_VERSION_1_1;
2341 http->keep_alive = HTTP_KEEPALIVE_ON;
2342 }
2343 else
2344 {
2345 DEBUG_printf(("1httpReadRequest: Unknown version \"%s\".", req_version));
2346 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, _("Unknown request version."), 1);
2347 return (HTTP_STATE_UNKNOWN_VERSION);
2348 }
2349
2350 DEBUG_printf(("1httpReadRequest: URI is \"%s\".", req_uri));
2351 strlcpy(uri, req_uri, urilen);
2352
2353 return (http->state);
2354 }
2355
2356
2357 /*
2358 * 'httpReconnect()' - Reconnect to a HTTP server.
2359 *
2360 * This function is deprecated. Please use the @link httpReconnect2@ function
2361 * instead.
2362 *
2363 * @deprecated@
2364 */
2365
2366 int /* O - 0 on success, non-zero on failure */
2367 httpReconnect(http_t *http) /* I - HTTP connection */
2368 {
2369 DEBUG_printf(("httpReconnect(http=%p)", http));
2370
2371 return (httpReconnect2(http, 30000, NULL));
2372 }
2373
2374
2375 /*
2376 * 'httpReconnect2()' - Reconnect to a HTTP server with timeout and optional
2377 * cancel.
2378 */
2379
2380 int /* O - 0 on success, non-zero on failure */
2381 httpReconnect2(http_t *http, /* I - HTTP connection */
2382 int msec, /* I - Timeout in milliseconds */
2383 int *cancel) /* I - Pointer to "cancel" variable */
2384 {
2385 http_addrlist_t *addr; /* Connected address */
2386 #ifdef DEBUG
2387 http_addrlist_t *current; /* Current address */
2388 char temp[256]; /* Temporary address string */
2389 #endif /* DEBUG */
2390
2391
2392 DEBUG_printf(("httpReconnect2(http=%p, msec=%d, cancel=%p)", http, msec,
2393 cancel));
2394
2395 if (!http)
2396 {
2397 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(EINVAL), 0);
2398 return (-1);
2399 }
2400
2401 #ifdef HAVE_SSL
2402 if (http->tls)
2403 {
2404 DEBUG_puts("2httpReconnect2: Shutting down SSL/TLS...");
2405 http_tls_stop(http);
2406 }
2407 #endif /* HAVE_SSL */
2408
2409 /*
2410 * Close any previously open socket...
2411 */
2412
2413 if (http->fd >= 0)
2414 {
2415 DEBUG_printf(("2httpReconnect2: Closing socket %d...", http->fd));
2416
2417 httpAddrClose(NULL, http->fd);
2418
2419 http->fd = -1;
2420 }
2421
2422 /*
2423 * Reset all state (except fields, which may be reused)...
2424 */
2425
2426 http->state = HTTP_STATE_WAITING;
2427 http->version = HTTP_VERSION_1_1;
2428 http->keep_alive = HTTP_KEEPALIVE_OFF;
2429 memset(&http->_hostaddr, 0, sizeof(http->_hostaddr));
2430 http->data_encoding = HTTP_ENCODING_FIELDS;
2431 http->_data_remaining = 0;
2432 http->used = 0;
2433 http->data_remaining = 0;
2434 http->hostaddr = NULL;
2435 http->wused = 0;
2436
2437 /*
2438 * Connect to the server...
2439 */
2440
2441 #ifdef DEBUG
2442 for (current = http->addrlist; current; current = current->next)
2443 DEBUG_printf(("2httpReconnect2: Address %s:%d",
2444 httpAddrString(&(current->addr), temp, sizeof(temp)),
2445 httpAddrPort(&(current->addr))));
2446 #endif /* DEBUG */
2447
2448 if ((addr = httpAddrConnect2(http->addrlist, &(http->fd), msec,
2449 cancel)) == NULL)
2450 {
2451 /*
2452 * Unable to connect...
2453 */
2454
2455 #ifdef WIN32
2456 http->error = WSAGetLastError();
2457 #else
2458 http->error = errno;
2459 #endif /* WIN32 */
2460 http->status = HTTP_STATUS_ERROR;
2461
2462 DEBUG_printf(("1httpReconnect2: httpAddrConnect failed: %s",
2463 strerror(http->error)));
2464
2465 return (-1);
2466 }
2467
2468 DEBUG_printf(("2httpReconnect2: New socket=%d", http->fd));
2469
2470 if (http->timeout_value > 0)
2471 http_set_timeout(http->fd, http->timeout_value);
2472
2473 http->hostaddr = &(addr->addr);
2474 http->error = 0;
2475
2476 #ifdef HAVE_SSL
2477 if (http->encryption == HTTP_ENCRYPTION_ALWAYS)
2478 {
2479 /*
2480 * Always do encryption via SSL.
2481 */
2482
2483 if (http_tls_start(http) != 0)
2484 {
2485 httpAddrClose(NULL, http->fd);
2486
2487 return (-1);
2488 }
2489 }
2490 else if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls_upgrade)
2491 return (http_tls_upgrade(http));
2492 #endif /* HAVE_SSL */
2493
2494 DEBUG_printf(("1httpReconnect2: Connected to %s:%d...",
2495 httpAddrString(http->hostaddr, temp, sizeof(temp)),
2496 httpAddrPort(http->hostaddr)));
2497
2498 return (0);
2499 }
2500
2501
2502 /*
2503 * 'httpSetAuthString()' - Set the current authorization string.
2504 *
2505 * This function just stores a copy of the current authorization string in
2506 * the HTTP connection object. You must still call httpSetField() to set
2507 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
2508 * httpHead(), httpOptions(), httpPost, or httpPut().
2509 *
2510 * @since CUPS 1.3/OS X 10.5@
2511 */
2512
2513 void
2514 httpSetAuthString(http_t *http, /* I - HTTP connection */
2515 const char *scheme, /* I - Auth scheme (NULL to clear it) */
2516 const char *data) /* I - Auth data (NULL for none) */
2517 {
2518 /*
2519 * Range check input...
2520 */
2521
2522 if (!http)
2523 return;
2524
2525 if (http->authstring && http->authstring != http->_authstring)
2526 free(http->authstring);
2527
2528 http->authstring = http->_authstring;
2529
2530 if (scheme)
2531 {
2532 /*
2533 * Set the current authorization string...
2534 */
2535
2536 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
2537 char *temp;
2538
2539 if (len > (int)sizeof(http->_authstring))
2540 {
2541 if ((temp = malloc(len)) == NULL)
2542 len = sizeof(http->_authstring);
2543 else
2544 http->authstring = temp;
2545 }
2546
2547 if (data)
2548 snprintf(http->authstring, len, "%s %s", scheme, data);
2549 else
2550 strlcpy(http->authstring, scheme, len);
2551 }
2552 else
2553 {
2554 /*
2555 * Clear the current authorization string...
2556 */
2557
2558 http->_authstring[0] = '\0';
2559 }
2560 }
2561
2562
2563 /*
2564 * 'httpSetCredentials()' - Set the credentials associated with an encrypted
2565 * connection.
2566 *
2567 * @since CUPS 1.5/OS X 10.7@
2568 */
2569
2570 int /* O - Status of call (0 = success) */
2571 httpSetCredentials(http_t *http, /* I - HTTP connection */
2572 cups_array_t *credentials) /* I - Array of credentials */
2573 {
2574 if (!http || cupsArrayCount(credentials) < 1)
2575 return (-1);
2576
2577 _httpFreeCredentials(http->tls_credentials);
2578
2579 http->tls_credentials = _httpCreateCredentials(credentials);
2580
2581 return (http->tls_credentials ? 0 : -1);
2582 }
2583
2584
2585 /*
2586 * 'httpSetCookie()' - Set the cookie value(s).
2587 *
2588 * @since CUPS 1.1.19/OS X 10.3@
2589 */
2590
2591 void
2592 httpSetCookie(http_t *http, /* I - Connection */
2593 const char *cookie) /* I - Cookie string */
2594 {
2595 if (!http)
2596 return;
2597
2598 if (http->cookie)
2599 free(http->cookie);
2600
2601 if (cookie)
2602 http->cookie = strdup(cookie);
2603 else
2604 http->cookie = NULL;
2605 }
2606
2607
2608 /*
2609 * 'httpSetDefaultField()' - Set the default value of an HTTP header.
2610 *
2611 * Currently only @code HTTP_FIELD_ACCEPT_ENCODING@, @code HTTP_FIELD_SERVER@,
2612 * and @code HTTP_FIELD_USER_AGENT@ can be set.
2613 *
2614 * @since CUPS 1.7/OS X 10.9@
2615 */
2616
2617 void
2618 httpSetDefaultField(http_t *http, /* I - HTTP connection */
2619 http_field_t field, /* I - Field index */
2620 const char *value)/* I - Value */
2621 {
2622 DEBUG_printf(("httpSetDefaultField(http=%p, field=%d(%s), value=\"%s\")",
2623 http, field, http_fields[field], value));
2624
2625 if (!http)
2626 return;
2627
2628 switch (field)
2629 {
2630 case HTTP_FIELD_ACCEPT_ENCODING :
2631 if (http->default_accept_encoding)
2632 _cupsStrFree(http->default_accept_encoding);
2633
2634 http->default_accept_encoding = value ? _cupsStrAlloc(value) : NULL;
2635 break;
2636
2637 case HTTP_FIELD_SERVER :
2638 if (http->default_server)
2639 _cupsStrFree(http->default_server);
2640
2641 http->default_server = value ? _cupsStrAlloc(value) : NULL;
2642 break;
2643
2644 case HTTP_FIELD_USER_AGENT :
2645 if (http->default_user_agent)
2646 _cupsStrFree(http->default_user_agent);
2647
2648 http->default_user_agent = value ? _cupsStrAlloc(value) : NULL;
2649 break;
2650
2651 default :
2652 DEBUG_puts("1httpSetDefaultField: Ignored.");
2653 break;
2654 }
2655 }
2656
2657
2658 /*
2659 * 'httpSetExpect()' - Set the Expect: header in a request.
2660 *
2661 * Currently only @code HTTP_STATUS_CONTINUE@ is supported for the "expect"
2662 * argument.
2663 *
2664 * @since CUPS 1.2/OS X 10.5@
2665 */
2666
2667 void
2668 httpSetExpect(http_t *http, /* I - HTTP connection */
2669 http_status_t expect) /* I - HTTP status to expect
2670 (@code HTTP_STATUS_CONTINUE@) */
2671 {
2672 DEBUG_printf(("httpSetExpect(http=%p, expect=%d)", http, expect));
2673
2674 if (http)
2675 http->expect = expect;
2676 }
2677
2678
2679 /*
2680 * 'httpSetField()' - Set the value of an HTTP header.
2681 */
2682
2683 void
2684 httpSetField(http_t *http, /* I - HTTP connection */
2685 http_field_t field, /* I - Field index */
2686 const char *value) /* I - Value */
2687 {
2688 DEBUG_printf(("httpSetField(http=%p, field=%d(%s), value=\"%s\")", http,
2689 field, http_fields[field], value));
2690
2691 if (http == NULL ||
2692 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
2693 field >= HTTP_FIELD_MAX ||
2694 value == NULL)
2695 return;
2696
2697 switch (field)
2698 {
2699 case HTTP_FIELD_ACCEPT_ENCODING :
2700 if (http->accept_encoding)
2701 _cupsStrFree(http->accept_encoding);
2702
2703 http->accept_encoding = _cupsStrAlloc(value);
2704 break;
2705
2706 case HTTP_FIELD_ALLOW :
2707 if (http->allow)
2708 _cupsStrFree(http->allow);
2709
2710 http->allow = _cupsStrAlloc(value);
2711 break;
2712
2713 case HTTP_FIELD_SERVER :
2714 if (http->server)
2715 _cupsStrFree(http->server);
2716
2717 http->server = _cupsStrAlloc(value);
2718 break;
2719
2720 default :
2721 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
2722 break;
2723 }
2724
2725 if (field == HTTP_FIELD_AUTHORIZATION)
2726 {
2727 /*
2728 * Special case for Authorization: as its contents can be
2729 * longer than HTTP_MAX_VALUE
2730 */
2731
2732 if (http->field_authorization)
2733 free(http->field_authorization);
2734
2735 http->field_authorization = strdup(value);
2736 }
2737 else if (field == HTTP_FIELD_HOST)
2738 {
2739 /*
2740 * Special-case for Host: as we don't want a trailing "." on the hostname and
2741 * need to bracket IPv6 numeric addresses.
2742 */
2743
2744 char *ptr = strchr(value, ':');
2745
2746 if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
2747 {
2748 /*
2749 * Bracket IPv6 numeric addresses...
2750 *
2751 * This is slightly inefficient (basically copying twice), but is an edge
2752 * case and not worth optimizing...
2753 */
2754
2755 snprintf(http->fields[HTTP_FIELD_HOST],
2756 sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
2757 }
2758 else
2759 {
2760 /*
2761 * Check for a trailing dot on the hostname...
2762 */
2763
2764 ptr = http->fields[HTTP_FIELD_HOST];
2765
2766 if (*ptr)
2767 {
2768 ptr += strlen(ptr) - 1;
2769
2770 if (*ptr == '.')
2771 *ptr = '\0';
2772 }
2773 }
2774 }
2775 #ifdef HAVE_LIBZ
2776 else if (field == HTTP_FIELD_CONTENT_ENCODING &&
2777 http->data_encoding != HTTP_ENCODING_FIELDS)
2778 {
2779 DEBUG_puts("1httpSetField: Calling http_content_coding_start.");
2780 http_content_coding_start(http, value);
2781 }
2782 #endif /* HAVE_LIBZ */
2783 }
2784
2785
2786 /*
2787 * 'httpSetKeepAlive()' - Set the current Keep-Alive state of a connection.
2788 *
2789 * @since CUPS 2.0@
2790 */
2791
2792 void
2793 httpSetKeepAlive(
2794 http_t *http, /* I - HTTP connection */
2795 http_keepalive_t keep_alive) /* I - New Keep-Alive value */
2796 {
2797 if (http)
2798 http->keep_alive = keep_alive;
2799 }
2800
2801
2802 /*
2803 * 'httpSetLength()' - Set the content-length and content-encoding.
2804 *
2805 * @since CUPS 1.2/OS X 10.5@
2806 */
2807
2808 void
2809 httpSetLength(http_t *http, /* I - HTTP connection */
2810 size_t length) /* I - Length (0 for chunked) */
2811 {
2812 DEBUG_printf(("httpSetLength(http=%p, length=" CUPS_LLFMT ")", http,
2813 CUPS_LLCAST length));
2814
2815 if (!http)
2816 return;
2817
2818 if (!length)
2819 {
2820 strlcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked",
2821 HTTP_MAX_VALUE);
2822 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
2823 }
2824 else
2825 {
2826 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
2827 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
2828 CUPS_LLFMT, CUPS_LLCAST length);
2829 }
2830 }
2831
2832
2833 /*
2834 * 'httpSetTimeout()' - Set read/write timeouts and an optional callback.
2835 *
2836 * The optional timeout callback receives both the HTTP connection and a user
2837 * data pointer and must return 1 to continue or 0 to error (time) out.
2838 *
2839 * @since CUPS 1.5/OS X 10.7@
2840 */
2841
2842 void
2843 httpSetTimeout(
2844 http_t *http, /* I - HTTP connection */
2845 double timeout, /* I - Number of seconds for timeout,
2846 must be greater than 0 */
2847 http_timeout_cb_t cb, /* I - Callback function or NULL */
2848 void *user_data) /* I - User data pointer */
2849 {
2850 if (!http || timeout <= 0.0)
2851 return;
2852
2853 http->timeout_cb = cb;
2854 http->timeout_data = user_data;
2855 http->timeout_value = timeout;
2856
2857 if (http->fd >= 0)
2858 http_set_timeout(http->fd, timeout);
2859
2860 http_set_wait(http);
2861 }
2862
2863
2864 /*
2865 * 'httpShutdown()' - Shutdown one side of an HTTP connection.
2866 *
2867 * @since CUPS 2.0@
2868 */
2869
2870 void
2871 httpShutdown(http_t *http) /* I - HTTP connection */
2872 {
2873 if (!http || http->fd < 0)
2874 return;
2875
2876 if (http->tls)
2877 http_tls_stop(http);
2878
2879 shutdown(http->fd, SHUT_RD);
2880 }
2881
2882
2883 /*
2884 * 'httpTrace()' - Send an TRACE request to the server.
2885 */
2886
2887 int /* O - Status of call (0 = success) */
2888 httpTrace(http_t *http, /* I - HTTP connection */
2889 const char *uri) /* I - URI for trace */
2890 {
2891 return (http_send(http, HTTP_STATE_TRACE, uri));
2892 }
2893
2894
2895 /*
2896 * '_httpUpdate()' - Update the current HTTP status for incoming data.
2897 *
2898 * Note: Unlike httpUpdate(), this function does not flush pending write data
2899 * and only retrieves a single status line from the HTTP connection.
2900 */
2901
2902 int /* O - 1 to continue, 0 to stop */
2903 _httpUpdate(http_t *http, /* I - HTTP connection */
2904 http_status_t *status) /* O - Current HTTP status */
2905 {
2906 char line[32768], /* Line from connection... */
2907 *value; /* Pointer to value on line */
2908 http_field_t field; /* Field index */
2909 int major, minor; /* HTTP version numbers */
2910
2911
2912 DEBUG_printf(("_httpUpdate(http=%p, status=%p), state=%s", http, status,
2913 httpStateString(http->state)));
2914
2915 /*
2916 * Grab a single line from the connection...
2917 */
2918
2919 if (!httpGets(line, sizeof(line), http))
2920 {
2921 *status = HTTP_STATUS_ERROR;
2922 return (0);
2923 }
2924
2925 DEBUG_printf(("2_httpUpdate: Got \"%s\"", line));
2926
2927 if (line[0] == '\0')
2928 {
2929 /*
2930 * Blank line means the start of the data section (if any). Return
2931 * the result code, too...
2932 *
2933 * If we get status 100 (HTTP_STATUS_CONTINUE), then we *don't* change
2934 * states. Instead, we just return HTTP_STATUS_CONTINUE to the caller and
2935 * keep on tryin'...
2936 */
2937
2938 if (http->status == HTTP_STATUS_CONTINUE)
2939 {
2940 *status = http->status;
2941 return (0);
2942 }
2943
2944 if (http->status < HTTP_STATUS_BAD_REQUEST)
2945 http->digest_tries = 0;
2946
2947 #ifdef HAVE_SSL
2948 if (http->status == HTTP_STATUS_SWITCHING_PROTOCOLS && !http->tls)
2949 {
2950 if (http_tls_start(http) != 0)
2951 {
2952 httpAddrClose(NULL, http->fd);
2953
2954 *status = http->status = HTTP_STATUS_ERROR;
2955 return (0);
2956 }
2957
2958 *status = HTTP_STATUS_CONTINUE;
2959 return (0);
2960 }
2961 #endif /* HAVE_SSL */
2962
2963 if (http_set_length(http) < 0)
2964 {
2965 DEBUG_puts("1_httpUpdate: Bad Content-Length.");
2966 http->error = EINVAL;
2967 http->status = *status = HTTP_STATUS_ERROR;
2968 return (0);
2969 }
2970
2971 switch (http->state)
2972 {
2973 case HTTP_STATE_GET :
2974 case HTTP_STATE_POST :
2975 case HTTP_STATE_POST_RECV :
2976 case HTTP_STATE_PUT :
2977 http->state ++;
2978
2979 DEBUG_printf(("1_httpUpdate: Set state to %s.",
2980 httpStateString(http->state)));
2981
2982 case HTTP_STATE_POST_SEND :
2983 case HTTP_STATE_HEAD :
2984 break;
2985
2986 default :
2987 http->state = HTTP_STATE_WAITING;
2988
2989 DEBUG_puts("1_httpUpdate: Reset state to HTTP_STATE_WAITING.");
2990 break;
2991 }
2992
2993 #ifdef HAVE_LIBZ
2994 DEBUG_puts("1_httpUpdate: Calling http_content_coding_start.");
2995 http_content_coding_start(http,
2996 httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
2997 #endif /* HAVE_LIBZ */
2998
2999 *status = http->status;
3000 return (0);
3001 }
3002 else if (!strncmp(line, "HTTP/", 5))
3003 {
3004 /*
3005 * Got the beginning of a response...
3006 */
3007
3008 int intstatus; /* Status value as an integer */
3009
3010 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &intstatus) != 3)
3011 {
3012 *status = http->status = HTTP_STATUS_ERROR;
3013 return (0);
3014 }
3015
3016 httpClearFields(http);
3017
3018 http->version = (http_version_t)(major * 100 + minor);
3019 *status = http->status = (http_status_t)intstatus;
3020 }
3021 else if ((value = strchr(line, ':')) != NULL)
3022 {
3023 /*
3024 * Got a value...
3025 */
3026
3027 *value++ = '\0';
3028 while (_cups_isspace(*value))
3029 value ++;
3030
3031 DEBUG_printf(("1_httpUpdate: Header %s: %s", line, value));
3032
3033 /*
3034 * Be tolerants of servers that send unknown attribute fields...
3035 */
3036
3037 if (!_cups_strcasecmp(line, "expect"))
3038 {
3039 /*
3040 * "Expect: 100-continue" or similar...
3041 */
3042
3043 http->expect = (http_status_t)atoi(value);
3044 }
3045 else if (!_cups_strcasecmp(line, "cookie"))
3046 {
3047 /*
3048 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
3049 */
3050
3051 httpSetCookie(http, value);
3052 }
3053 else if ((field = httpFieldValue(line)) != HTTP_FIELD_UNKNOWN)
3054 httpSetField(http, field, value);
3055 #ifdef DEBUG
3056 else
3057 DEBUG_printf(("1_httpUpdate: unknown field %s seen!", line));
3058 #endif /* DEBUG */
3059 }
3060 else
3061 {
3062 DEBUG_printf(("1_httpUpdate: Bad response line \"%s\"!", line));
3063 http->error = EINVAL;
3064 http->status = *status = HTTP_STATUS_ERROR;
3065 return (0);
3066 }
3067
3068 return (1);
3069 }
3070
3071
3072 /*
3073 * 'httpUpdate()' - Update the current HTTP state for incoming data.
3074 */
3075
3076 http_status_t /* O - HTTP status */
3077 httpUpdate(http_t *http) /* I - HTTP connection */
3078 {
3079 http_status_t status; /* Request status */
3080
3081
3082 DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
3083 httpStateString(http->state)));
3084
3085 /*
3086 * Flush pending data, if any...
3087 */
3088
3089 if (http->wused)
3090 {
3091 DEBUG_puts("2httpUpdate: flushing buffer...");
3092
3093 if (httpFlushWrite(http) < 0)
3094 return (HTTP_STATUS_ERROR);
3095 }
3096
3097 /*
3098 * If we haven't issued any commands, then there is nothing to "update"...
3099 */
3100
3101 if (http->state == HTTP_STATE_WAITING)
3102 return (HTTP_STATUS_CONTINUE);
3103
3104 /*
3105 * Grab all of the lines we can from the connection...
3106 */
3107
3108 while (_httpUpdate(http, &status));
3109
3110 /*
3111 * See if there was an error...
3112 */
3113
3114 if (http->error == EPIPE && http->status > HTTP_STATUS_CONTINUE)
3115 {
3116 DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
3117 return (http->status);
3118 }
3119
3120 if (http->error)
3121 {
3122 DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
3123 strerror(http->error)));
3124 http->status = HTTP_STATUS_ERROR;
3125 return (HTTP_STATUS_ERROR);
3126 }
3127
3128 /*
3129 * Return the current status...
3130 */
3131
3132 return (status);
3133 }
3134
3135
3136 /*
3137 * '_httpWait()' - Wait for data available on a connection (no flush).
3138 */
3139
3140 int /* O - 1 if data is available, 0 otherwise */
3141 _httpWait(http_t *http, /* I - HTTP connection */
3142 int msec, /* I - Milliseconds to wait */
3143 int usessl) /* I - Use SSL context? */
3144 {
3145 #ifdef HAVE_POLL
3146 struct pollfd pfd; /* Polled file descriptor */
3147 #else
3148 fd_set input_set; /* select() input set */
3149 struct timeval timeout; /* Timeout */
3150 #endif /* HAVE_POLL */
3151 int nfds; /* Result from select()/poll() */
3152
3153
3154 DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
3155
3156 if (http->fd < 0)
3157 {
3158 DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd));
3159 return (0);
3160 }
3161
3162 /*
3163 * Check the SSL/TLS buffers for data first...
3164 */
3165
3166 #ifdef HAVE_SSL
3167 if (http_tls_pending(http))
3168 {
3169 DEBUG_puts("5_httpWait: Return 1 since there is pending TLS data.");
3170 return (1);
3171 }
3172 #endif /* HAVE_SSL */
3173
3174 /*
3175 * Then try doing a select() or poll() to poll the socket...
3176 */
3177
3178 #ifdef HAVE_POLL
3179 pfd.fd = http->fd;
3180 pfd.events = POLLIN;
3181
3182 do
3183 {
3184 nfds = poll(&pfd, 1, msec);
3185 }
3186 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
3187
3188 #else
3189 do
3190 {
3191 FD_ZERO(&input_set);
3192 FD_SET(http->fd, &input_set);
3193
3194 DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
3195
3196 if (msec >= 0)
3197 {
3198 timeout.tv_sec = msec / 1000;
3199 timeout.tv_usec = (msec % 1000) * 1000;
3200
3201 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
3202 }
3203 else
3204 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
3205
3206 DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
3207 }
3208 # ifdef WIN32
3209 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
3210 WSAGetLastError() == WSAEWOULDBLOCK));
3211 # else
3212 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
3213 # endif /* WIN32 */
3214 #endif /* HAVE_POLL */
3215
3216 DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds,
3217 errno));
3218
3219 return (nfds > 0);
3220 }
3221
3222
3223 /*
3224 * 'httpWait()' - Wait for data available on a connection.
3225 *
3226 * @since CUPS 1.1.19/OS X 10.3@
3227 */
3228
3229 int /* O - 1 if data is available, 0 otherwise */
3230 httpWait(http_t *http, /* I - HTTP connection */
3231 int msec) /* I - Milliseconds to wait */
3232 {
3233 /*
3234 * First see if there is data in the buffer...
3235 */
3236
3237 DEBUG_printf(("2httpWait(http=%p, msec=%d)", http, msec));
3238
3239 if (http == NULL)
3240 return (0);
3241
3242 if (http->used)
3243 {
3244 DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
3245 return (1);
3246 }
3247
3248 #ifdef HAVE_LIBZ
3249 if (http->coding >= _HTTP_CODING_GUNZIP && http->stream.avail_in > 0)
3250 {
3251 DEBUG_puts("3httpWait: Returning 1 since there is buffered data ready.");
3252 return (1);
3253 }
3254 #endif /* HAVE_LIBZ */
3255
3256 /*
3257 * Flush pending data, if any...
3258 */
3259
3260 if (http->wused)
3261 {
3262 DEBUG_puts("3httpWait: Flushing write buffer.");
3263
3264 if (httpFlushWrite(http) < 0)
3265 return (0);
3266 }
3267
3268 /*
3269 * If not, check the SSL/TLS buffers and do a select() on the connection...
3270 */
3271
3272 return (_httpWait(http, msec, 1));
3273 }
3274
3275
3276 /*
3277 * 'httpWrite()' - Write data to a HTTP connection.
3278 *
3279 * This function is deprecated. Use the httpWrite2() function which can
3280 * write more than 2GB of data.
3281 *
3282 * @deprecated@
3283 */
3284
3285 int /* O - Number of bytes written */
3286 httpWrite(http_t *http, /* I - HTTP connection */
3287 const char *buffer, /* I - Buffer for data */
3288 int length) /* I - Number of bytes to write */
3289 {
3290 return ((int)httpWrite2(http, buffer, length));
3291 }
3292
3293
3294 /*
3295 * 'httpWrite2()' - Write data to a HTTP connection.
3296 *
3297 * @since CUPS 1.2/OS X 10.5@
3298 */
3299
3300 ssize_t /* O - Number of bytes written */
3301 httpWrite2(http_t *http, /* I - HTTP connection */
3302 const char *buffer, /* I - Buffer for data */
3303 size_t length) /* I - Number of bytes to write */
3304 {
3305 ssize_t bytes; /* Bytes written */
3306
3307
3308 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
3309 buffer, CUPS_LLCAST length));
3310
3311 /*
3312 * Range check input...
3313 */
3314
3315 if (!http || !buffer)
3316 {
3317 DEBUG_puts("1httpWrite2: Returning -1 due to bad input.");
3318 return (-1);
3319 }
3320
3321 /*
3322 * Mark activity on the connection...
3323 */
3324
3325 http->activity = time(NULL);
3326
3327 /*
3328 * Buffer small writes for better performance...
3329 */
3330
3331 #ifdef HAVE_LIBZ
3332 if (http->coding)
3333 {
3334 DEBUG_printf(("1httpWrite2: http->coding=%d", http->coding));
3335
3336 if (length == 0)
3337 {
3338 http_content_coding_finish(http);
3339 bytes = 0;
3340 }
3341 else
3342 {
3343 http->stream.next_in = (Bytef *)buffer;
3344 http->stream.avail_in = length;
3345 http->stream.next_out = (Bytef *)http->wbuffer + http->wused;
3346 http->stream.avail_out = sizeof(http->wbuffer) - http->wused;
3347
3348 while (deflate(&(http->stream), Z_NO_FLUSH) == Z_OK)
3349 {
3350 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
3351
3352 if (http->stream.avail_out == 0)
3353 {
3354 if (httpFlushWrite(http) < 0)
3355 {
3356 DEBUG_puts("1httpWrite2: Unable to flush, returning -1.");
3357 return (-1);
3358 }
3359
3360 http->stream.next_out = (Bytef *)http->wbuffer;
3361 http->stream.avail_out = sizeof(http->wbuffer);
3362 }
3363 }
3364
3365 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
3366 bytes = length;
3367 }
3368 }
3369 else
3370 #endif /* HAVE_LIBZ */
3371 if (length > 0)
3372 {
3373 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
3374 {
3375 DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
3376 CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
3377
3378 httpFlushWrite(http);
3379 }
3380
3381 if ((length + http->wused) <= sizeof(http->wbuffer) &&
3382 length < sizeof(http->wbuffer))
3383 {
3384 /*
3385 * Write to buffer...
3386 */
3387
3388 DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
3389 CUPS_LLCAST length));
3390
3391 memcpy(http->wbuffer + http->wused, buffer, length);
3392 http->wused += (int)length;
3393 bytes = (ssize_t)length;
3394 }
3395 else
3396 {
3397 /*
3398 * Otherwise write the data directly...
3399 */
3400
3401 DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
3402 CUPS_LLCAST length));
3403
3404 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
3405 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
3406 else
3407 bytes = (ssize_t)http_write(http, buffer, (int)length);
3408
3409 DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
3410 CUPS_LLCAST bytes));
3411 }
3412
3413 if (http->data_encoding == HTTP_ENCODING_LENGTH)
3414 http->data_remaining -= bytes;
3415 }
3416 else
3417 bytes = 0;
3418
3419 /*
3420 * Handle end-of-request processing...
3421 */
3422
3423 if ((http->data_encoding == HTTP_ENCODING_CHUNKED && length == 0) ||
3424 (http->data_encoding == HTTP_ENCODING_LENGTH && http->data_remaining == 0))
3425 {
3426 /*
3427 * Finished with the transfer; unless we are sending POST or PUT
3428 * data, go idle...
3429 */
3430
3431 #ifdef HAVE_LIBZ
3432 if (http->coding)
3433 http_content_coding_finish(http);
3434 #endif /* HAVE_LIBZ */
3435
3436 if (http->wused)
3437 {
3438 if (httpFlushWrite(http) < 0)
3439 return (-1);
3440 }
3441
3442 if (http->data_encoding == HTTP_ENCODING_CHUNKED)
3443 {
3444 /*
3445 * Send a 0-length chunk at the end of the request...
3446 */
3447
3448 http_write(http, "0\r\n\r\n", 5);
3449
3450 /*
3451 * Reset the data state...
3452 */
3453
3454 http->data_encoding = HTTP_ENCODING_FIELDS;
3455 http->data_remaining = 0;
3456 }
3457
3458 if (http->state == HTTP_STATE_POST_RECV)
3459 http->state ++;
3460 else if (http->state == HTTP_STATE_POST_SEND)
3461 http->state = HTTP_STATE_WAITING;
3462 else
3463 http->state = HTTP_STATE_STATUS;
3464
3465 DEBUG_printf(("2httpWrite2: Changed state to %s.",
3466 httpStateString(http->state)));
3467 }
3468
3469 DEBUG_printf(("1httpWrite2: Returning " CUPS_LLFMT ".", CUPS_LLCAST bytes));
3470
3471 return (bytes);
3472 }
3473
3474
3475 /*
3476 * 'httpWriteResponse()' - Write a HTTP response to a client connection.
3477 *
3478 * @since CUPS 1.7/OS X 10.9@
3479 */
3480
3481 int /* O - 0 on success, -1 on error */
3482 httpWriteResponse(http_t *http, /* I - HTTP connection */
3483 http_status_t status) /* I - Status code */
3484 {
3485 http_encoding_t old_encoding; /* Old data_encoding value */
3486 off_t old_remaining; /* Old data_remaining value */
3487
3488
3489 /*
3490 * Range check input...
3491 */
3492
3493 DEBUG_printf(("httpWriteResponse(http=%p, status=%d)", http, status));
3494
3495 if (!http || status < HTTP_STATUS_CONTINUE)
3496 {
3497 DEBUG_puts("1httpWriteResponse: Bad input.");
3498 return (-1);
3499 }
3500
3501 /*
3502 * Set the various standard fields if they aren't already...
3503 */
3504
3505 if (!http->fields[HTTP_FIELD_DATE][0])
3506 httpSetField(http, HTTP_FIELD_DATE, httpGetDateString(time(NULL)));
3507
3508 if (status >= HTTP_STATUS_BAD_REQUEST && http->keep_alive)
3509 {
3510 http->keep_alive = HTTP_KEEPALIVE_OFF;
3511 httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "");
3512 }
3513
3514 if (http->version == HTTP_VERSION_1_1)
3515 {
3516 if (!http->fields[HTTP_FIELD_CONNECTION][0])
3517 {
3518 if (http->keep_alive)
3519 httpSetField(http, HTTP_FIELD_CONNECTION, "Keep-Alive");
3520 else
3521 httpSetField(http, HTTP_FIELD_CONNECTION, "close");
3522 }
3523
3524 if (http->keep_alive && !http->fields[HTTP_FIELD_KEEP_ALIVE][0])
3525 httpSetField(http, HTTP_FIELD_KEEP_ALIVE, "timeout=10");
3526 }
3527
3528 #ifdef HAVE_SSL
3529 if (status == HTTP_STATUS_UPGRADE_REQUIRED ||
3530 status == HTTP_STATUS_SWITCHING_PROTOCOLS)
3531 {
3532 if (!http->fields[HTTP_FIELD_CONNECTION][0])
3533 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
3534
3535 if (!http->fields[HTTP_FIELD_UPGRADE][0])
3536 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
3537
3538 if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
3539 httpSetField(http, HTTP_FIELD_CONTENT_LENGTH, "0");
3540 }
3541 #endif /* HAVE_SSL */
3542
3543 if (!http->server)
3544 httpSetField(http, HTTP_FIELD_SERVER,
3545 http->default_server ? http->default_server : CUPS_MINIMAL);
3546
3547 /*
3548 * Set the Accept-Encoding field if it isn't already...
3549 */
3550
3551 if (!http->accept_encoding)
3552 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
3553 http->default_accept_encoding ? http->default_accept_encoding :
3554 #ifdef HAVE_LIBZ
3555 "gzip, deflate, identity");
3556 #else
3557 "identity");
3558 #endif /* HAVE_LIBZ */
3559
3560 /*
3561 * Send the response header...
3562 */
3563
3564 old_encoding = http->data_encoding;
3565 old_remaining = http->data_remaining;
3566 http->data_encoding = HTTP_ENCODING_FIELDS;
3567
3568 if (httpPrintf(http, "HTTP/%d.%d %d %s\r\n", http->version / 100,
3569 http->version % 100, (int)status, httpStatus(status)) < 0)
3570 {
3571 http->status = HTTP_STATUS_ERROR;
3572 return (-1);
3573 }
3574
3575 if (status != HTTP_STATUS_CONTINUE)
3576 {
3577 /*
3578 * 100 Continue doesn't have the rest of the response headers...
3579 */
3580
3581 int i; /* Looping var */
3582 const char *value; /* Field value */
3583
3584 for (i = 0; i < HTTP_FIELD_MAX; i ++)
3585 {
3586 if ((value = httpGetField(http, i)) != NULL && *value)
3587 {
3588 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
3589 {
3590 http->status = HTTP_STATUS_ERROR;
3591 return (-1);
3592 }
3593 }
3594 }
3595
3596 if (http->cookie)
3597 {
3598 if (httpPrintf(http, "Set-Cookie: %s path=/ httponly%s\r\n",
3599 http->cookie, http->tls ? " secure" : "") < 1)
3600 {
3601 http->status = HTTP_STATUS_ERROR;
3602 return (-1);
3603 }
3604 }
3605 }
3606
3607 if (httpWrite2(http, "\r\n", 2) < 2)
3608 {
3609 http->status = HTTP_STATUS_ERROR;
3610 return (-1);
3611 }
3612
3613 if (httpFlushWrite(http) < 0)
3614 {
3615 http->status = HTTP_STATUS_ERROR;
3616 return (-1);
3617 }
3618
3619 if (status == HTTP_STATUS_CONTINUE ||
3620 status == HTTP_STATUS_SWITCHING_PROTOCOLS)
3621 {
3622 /*
3623 * Restore the old data_encoding and data_length values...
3624 */
3625
3626 http->data_encoding = old_encoding;
3627 http->data_remaining = old_remaining;
3628
3629 if (old_remaining <= INT_MAX)
3630 http->_data_remaining = (int)old_remaining;
3631 else
3632 http->_data_remaining = INT_MAX;
3633 }
3634 else if (http->state == HTTP_STATE_OPTIONS ||
3635 http->state == HTTP_STATE_HEAD ||
3636 http->state == HTTP_STATE_PUT ||
3637 http->state == HTTP_STATE_TRACE ||
3638 http->state == HTTP_STATE_CONNECT ||
3639 http->state == HTTP_STATE_STATUS)
3640 {
3641 DEBUG_printf(("1httpWriteResponse: Resetting state to HTTP_STATE_WAITING, "
3642 "was %s.", httpStateString(http->state)));
3643 http->state = HTTP_STATE_WAITING;
3644 }
3645 else
3646 {
3647 /*
3648 * Force data_encoding and data_length to be set according to the response
3649 * headers...
3650 */
3651
3652 http_set_length(http);
3653
3654 #ifdef HAVE_LIBZ
3655 /*
3656 * Then start any content encoding...
3657 */
3658
3659 DEBUG_puts("1httpWriteResponse: Calling http_content_coding_start.");
3660 http_content_coding_start(http,
3661 httpGetField(http, HTTP_FIELD_CONTENT_ENCODING));
3662 #endif /* HAVE_LIBZ */
3663 }
3664
3665 return (0);
3666 }
3667
3668
3669 #ifdef HAVE_LIBZ
3670 /*
3671 * 'http_content_coding_finish()' - Finish doing any content encoding.
3672 */
3673
3674 static void
3675 http_content_coding_finish(
3676 http_t *http) /* I - HTTP connection */
3677 {
3678 int zerr; /* Compression status */
3679
3680
3681 switch (http->coding)
3682 {
3683 case _HTTP_CODING_DEFLATE :
3684 case _HTTP_CODING_GZIP :
3685 do
3686 {
3687 http->stream.next_out = (Bytef *)http->wbuffer + http->wused;
3688 http->stream.avail_out = sizeof(http->wbuffer) - http->wused;
3689
3690 zerr = deflate(&(http->stream), Z_FINISH);
3691
3692 http->wused = sizeof(http->wbuffer) - http->stream.avail_out;
3693 if (http->wused == sizeof(http->wbuffer))
3694 httpFlushWrite(http);
3695 }
3696 while (zerr == Z_OK);
3697
3698 deflateEnd(&(http->stream));
3699
3700 if (http->wused)
3701 httpFlushWrite(http);
3702 break;
3703
3704 case _HTTP_CODING_INFLATE :
3705 case _HTTP_CODING_GUNZIP :
3706 inflateEnd(&(http->stream));
3707 free(http->dbuffer);
3708 http->dbuffer = NULL;
3709 break;
3710
3711 default :
3712 break;
3713 }
3714
3715 http->coding = _HTTP_CODING_IDENTITY;
3716 }
3717
3718
3719 /*
3720 * 'http_content_coding_start()' - Start doing content encoding.
3721 */
3722
3723 static void
3724 http_content_coding_start(
3725 http_t *http, /* I - HTTP connection */
3726 const char *value) /* I - Value of Content-Encoding */
3727 {
3728 int zerr; /* Error/status */
3729 _http_coding_t coding; /* Content coding value */
3730
3731
3732 DEBUG_printf(("http_content_coding_start(http=%p, value=\"%s\")", http,
3733 value));
3734
3735 if (http->coding != _HTTP_CODING_IDENTITY)
3736 {
3737 DEBUG_printf(("1http_content_coding_start: http->coding already %d.",
3738 http->coding));
3739 return;
3740 }
3741 else if (!strcmp(value, "x-gzip") || !strcmp(value, "gzip"))
3742 {
3743 if (http->state == HTTP_STATE_GET_SEND ||
3744 http->state == HTTP_STATE_POST_SEND)
3745 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_GZIP :
3746 _HTTP_CODING_GUNZIP;
3747 else if (http->state == HTTP_STATE_POST_RECV ||
3748 http->state == HTTP_STATE_PUT_RECV)
3749 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_GZIP :
3750 _HTTP_CODING_GUNZIP;
3751 else
3752 {
3753 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
3754 return;
3755 }
3756 }
3757 else if (!strcmp(value, "x-deflate") || !strcmp(value, "deflate"))
3758 {
3759 if (http->state == HTTP_STATE_GET_SEND ||
3760 http->state == HTTP_STATE_POST_SEND)
3761 coding = http->mode == _HTTP_MODE_SERVER ? _HTTP_CODING_DEFLATE :
3762 _HTTP_CODING_INFLATE;
3763 else if (http->state == HTTP_STATE_POST_RECV ||
3764 http->state == HTTP_STATE_PUT_RECV)
3765 coding = http->mode == _HTTP_MODE_CLIENT ? _HTTP_CODING_DEFLATE :
3766 _HTTP_CODING_INFLATE;
3767 else
3768 {
3769 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
3770 return;
3771 }
3772 }
3773 else
3774 {
3775 DEBUG_puts("1http_content_coding_start: Not doing content coding.");
3776 return;
3777 }
3778
3779 memset(&(http->stream), 0, sizeof(http->stream));
3780
3781 switch (coding)
3782 {
3783 case _HTTP_CODING_DEFLATE :
3784 case _HTTP_CODING_GZIP :
3785 if (http->wused)
3786 httpFlushWrite(http);
3787
3788 /*
3789 * Window size for compression is 11 bits - optimal based on PWG Raster
3790 * sample files on pwg.org. -11 is raw deflate, 27 is gzip, per ZLIB
3791 * documentation.
3792 */
3793
3794 if ((zerr = deflateInit2(&(http->stream), Z_DEFAULT_COMPRESSION,
3795 Z_DEFLATED,
3796 coding == _HTTP_CODING_DEFLATE ? -11 : 27, 7,
3797 Z_DEFAULT_STRATEGY)) < Z_OK)
3798 {
3799 http->status = HTTP_STATUS_ERROR;
3800 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
3801 return;
3802 }
3803 break;
3804
3805 case _HTTP_CODING_INFLATE :
3806 case _HTTP_CODING_GUNZIP :
3807 if ((http->dbuffer = malloc(HTTP_MAX_BUFFER)) == NULL)
3808 {
3809 http->status = HTTP_STATUS_ERROR;
3810 http->error = errno;
3811 return;
3812 }
3813
3814 /*
3815 * Window size for decompression is up to 15 bits (maximum supported).
3816 * -15 is raw inflate, 31 is gunzip, per ZLIB documentation.
3817 */
3818
3819 if ((zerr = inflateInit2(&(http->stream),
3820 coding == _HTTP_CODING_INFLATE ? -15 : 31))
3821 < Z_OK)
3822 {
3823 free(http->dbuffer);
3824 http->dbuffer = NULL;
3825 http->status = HTTP_STATUS_ERROR;
3826 http->error = zerr == Z_MEM_ERROR ? ENOMEM : EINVAL;
3827 return;
3828 }
3829
3830 http->stream.avail_in = 0;
3831 http->stream.next_in = http->dbuffer;
3832 break;
3833
3834 default :
3835 break;
3836 }
3837
3838 http->coding = coding;
3839
3840 DEBUG_printf(("1http_content_coding_start: http->coding now %d.",
3841 http->coding));
3842 }
3843 #endif /* HAVE_LIBZ */
3844
3845
3846 /*
3847 * 'http_create()' - Create an unconnected HTTP connection.
3848 */
3849
3850 static http_t * /* O - HTTP connection */
3851 http_create(
3852 const char *host, /* I - Hostname */
3853 int port, /* I - Port number */
3854 http_addrlist_t *addrlist, /* I - Address list or NULL */
3855 int family, /* I - Address family or AF_UNSPEC */
3856 http_encryption_t encryption, /* I - Encryption to use */
3857 int blocking, /* I - 1 for blocking mode */
3858 _http_mode_t mode) /* I - _HTTP_MODE_CLIENT or _SERVER */
3859 {
3860 http_t *http; /* New HTTP connection */
3861 char service[255]; /* Service name */
3862 http_addrlist_t *myaddrlist = NULL; /* My address list */
3863
3864
3865 DEBUG_printf(("4http_create(host=\"%s\", port=%d, addrlist=%p, family=%d, "
3866 "encryption=%d, blocking=%d, mode=%d)", host, port, addrlist,
3867 family, encryption, blocking, mode));
3868
3869 if (!host && mode == _HTTP_MODE_CLIENT)
3870 return (NULL);
3871
3872 httpInitialize();
3873
3874 /*
3875 * Lookup the host...
3876 */
3877
3878 if (addrlist)
3879 {
3880 myaddrlist = httpAddrCopyList(addrlist);
3881 }
3882 else
3883 {
3884 snprintf(service, sizeof(service), "%d", port);
3885
3886 myaddrlist = httpAddrGetList(host, family, service);
3887 }
3888
3889 if (!myaddrlist)
3890 return (NULL);
3891
3892 /*
3893 * Allocate memory for the structure...
3894 */
3895
3896 if ((http = calloc(sizeof(http_t), 1)) == NULL)
3897 {
3898 _cupsSetError(IPP_STATUS_ERROR_INTERNAL, strerror(errno), 0);
3899 httpAddrFreeList(addrlist);
3900 return (NULL);
3901 }
3902
3903 /*
3904 * Initialize the HTTP data...
3905 */
3906
3907 http->mode = mode;
3908 http->activity = time(NULL);
3909 http->addrlist = myaddrlist;
3910 http->blocking = blocking;
3911 http->fd = -1;
3912 #ifdef HAVE_GSSAPI
3913 http->gssctx = GSS_C_NO_CONTEXT;
3914 http->gssname = GSS_C_NO_NAME;
3915 #endif /* HAVE_GSSAPI */
3916 http->status = HTTP_STATUS_CONTINUE;
3917 http->version = HTTP_VERSION_1_1;
3918
3919 if (host)
3920 strlcpy(http->hostname, host, sizeof(http->hostname));
3921
3922 if (port == 443) /* Always use encryption for https */
3923 http->encryption = HTTP_ENCRYPTION_ALWAYS;
3924 else
3925 http->encryption = encryption;
3926
3927 http_set_wait(http);
3928
3929 /*
3930 * Return the new structure...
3931 */
3932
3933 return (http);
3934 }
3935
3936 /* For OS X 10.8 and earlier */
3937 http_t *_httpCreate(const char *host, int port, http_addrlist_t *addrlist,
3938 http_encryption_t encryption, int family)
3939 { return (http_create(host, port, addrlist, family, encryption, 1,
3940 _HTTP_MODE_CLIENT)); }
3941
3942
3943 #ifdef DEBUG
3944 /*
3945 * 'http_debug_hex()' - Do a hex dump of a buffer.
3946 */
3947
3948 static void
3949 http_debug_hex(const char *prefix, /* I - Prefix for line */
3950 const char *buffer, /* I - Buffer to dump */
3951 int bytes) /* I - Bytes to dump */
3952 {
3953 int i, j, /* Looping vars */
3954 ch; /* Current character */
3955 char line[255], /* Line buffer */
3956 *start, /* Start of line after prefix */
3957 *ptr; /* Pointer into line */
3958
3959
3960 if (_cups_debug_fd < 0 || _cups_debug_level < 6)
3961 return;
3962
3963 DEBUG_printf(("6%s: %d bytes:", prefix, bytes));
3964
3965 snprintf(line, sizeof(line), "6%s: ", prefix);
3966 start = line + strlen(line);
3967
3968 for (i = 0; i < bytes; i += 16)
3969 {
3970 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
3971 sprintf(ptr, "%02X", buffer[i + j] & 255);
3972
3973 while (j < 16)
3974 {
3975 memcpy(ptr, " ", 3);
3976 ptr += 2;
3977 j ++;
3978 }
3979
3980 memcpy(ptr, " ", 3);
3981 ptr += 2;
3982
3983 for (j = 0; j < 16 && (i + j) < bytes; j ++)
3984 {
3985 ch = buffer[i + j] & 255;
3986
3987 if (ch < ' ' || ch >= 127)
3988 ch = '.';
3989
3990 *ptr++ = ch;
3991 }
3992
3993 *ptr = '\0';
3994 DEBUG_puts(line);
3995 }
3996 }
3997 #endif /* DEBUG */
3998
3999
4000 /*
4001 * 'http_read()' - Read a buffer from a HTTP connection.
4002 *
4003 * This function does the low-level read from the socket, retrying and timing
4004 * out as needed.
4005 */
4006
4007 static ssize_t /* O - Number of bytes read or -1 on error */
4008 http_read(http_t *http, /* I - HTTP connection */
4009 char *buffer, /* I - Buffer */
4010 size_t length) /* I - Maximum bytes to read */
4011 {
4012 ssize_t bytes; /* Bytes read */
4013
4014
4015 DEBUG_printf(("http_read(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
4016 buffer, CUPS_LLCAST length));
4017
4018 if (!http->blocking)
4019 {
4020 while (!httpWait(http, http->wait_value))
4021 {
4022 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4023 continue;
4024
4025 DEBUG_puts("2http_read: Timeout.");
4026 return (0);
4027 }
4028 }
4029
4030 DEBUG_printf(("2http_read: Reading %d bytes into buffer.", (int)length));
4031
4032 do
4033 {
4034 #ifdef HAVE_SSL
4035 if (http->tls)
4036 bytes = http_tls_read(http, buffer, length);
4037 else
4038 #endif /* HAVE_SSL */
4039 bytes = recv(http->fd, buffer, length, 0);
4040
4041 if (bytes < 0)
4042 {
4043 #ifdef WIN32
4044 if (WSAGetLastError() != WSAEINTR)
4045 {
4046 http->error = WSAGetLastError();
4047 return (-1);
4048 }
4049 else if (WSAGetLastError() == WSAEWOULDBLOCK)
4050 {
4051 if (!http->timeout_cb ||
4052 !(*http->timeout_cb)(http, http->timeout_data))
4053 {
4054 http->error = WSAEWOULDBLOCK;
4055 return (-1);
4056 }
4057 }
4058 #else
4059 DEBUG_printf(("2http_read: %s", strerror(errno)));
4060
4061 if (errno == EWOULDBLOCK || errno == EAGAIN)
4062 {
4063 if (http->timeout_cb && !(*http->timeout_cb)(http, http->timeout_data))
4064 {
4065 http->error = errno;
4066 return (-1);
4067 }
4068 else if (!http->timeout_cb && errno != EAGAIN)
4069 {
4070 http->error = errno;
4071 return (-1);
4072 }
4073 }
4074 else if (errno != EINTR)
4075 {
4076 http->error = errno;
4077 return (-1);
4078 }
4079 #endif /* WIN32 */
4080 }
4081 }
4082 while (bytes < 0);
4083
4084 DEBUG_printf(("2http_read: Read " CUPS_LLFMT " bytes into buffer.",
4085 CUPS_LLCAST bytes));
4086 #ifdef DEBUG
4087 if (bytes > 0)
4088 http_debug_hex("http_read", buffer, (int)bytes);
4089 #endif /* DEBUG */
4090
4091 if (bytes < 0)
4092 {
4093 #ifdef WIN32
4094 if (WSAGetLastError() == WSAEINTR)
4095 bytes = 0;
4096 else
4097 http->error = WSAGetLastError();
4098 #else
4099 if (errno == EINTR || (errno == EAGAIN && !http->timeout_cb))
4100 bytes = 0;
4101 else
4102 http->error = errno;
4103 #endif /* WIN32 */
4104 }
4105 else if (bytes == 0)
4106 {
4107 http->error = EPIPE;
4108 return (0);
4109 }
4110
4111 return (bytes);
4112 }
4113
4114
4115 /*
4116 * 'http_read_buffered()' - Do a buffered read from a HTTP connection.
4117 *
4118 * This function reads data from the HTTP buffer or from the socket, as needed.
4119 */
4120
4121 static ssize_t /* O - Number of bytes read or -1 on error */
4122 http_read_buffered(http_t *http, /* I - HTTP connection */
4123 char *buffer, /* I - Buffer */
4124 size_t length) /* I - Maximum bytes to read */
4125 {
4126 ssize_t bytes; /* Bytes read */
4127
4128
4129 DEBUG_printf(("http_read_buffered(http=%p, buffer=%p, length=" CUPS_LLFMT
4130 ") used=%d",
4131 http, buffer, CUPS_LLCAST length, http->used));
4132
4133 if (http->used > 0)
4134 {
4135 if (length > (size_t)http->used)
4136 bytes = (size_t)http->used;
4137 else
4138 bytes = length;
4139
4140 DEBUG_printf(("2http_read: Grabbing %d bytes from input buffer.",
4141 (int)bytes));
4142
4143 memcpy(buffer, http->buffer, bytes);
4144 http->used -= (int)bytes;
4145
4146 if (http->used > 0)
4147 memmove(http->buffer, http->buffer + bytes, http->used);
4148 }
4149 else
4150 bytes = http_read(http, buffer, length);
4151
4152 return (bytes);
4153 }
4154
4155
4156 /*
4157 * 'http_read_chunk()' - Read a chunk from a HTTP connection.
4158 *
4159 * This function reads and validates the chunk length, then does a buffered read
4160 * returning the number of bytes placed in the buffer.
4161 */
4162
4163 static ssize_t /* O - Number of bytes read or -1 on error */
4164 http_read_chunk(http_t *http, /* I - HTTP connection */
4165 char *buffer, /* I - Buffer */
4166 size_t length) /* I - Maximum bytes to read */
4167 {
4168 DEBUG_printf(("http_read_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
4169 http, buffer, CUPS_LLCAST length));
4170
4171 if (http->data_remaining <= 0)
4172 {
4173 char len[32]; /* Length string */
4174
4175 if (!httpGets(len, sizeof(len), http))
4176 {
4177 DEBUG_puts("1http_read_chunk: Could not get chunk length.");
4178 return (0);
4179 }
4180
4181 if (!len[0])
4182 {
4183 DEBUG_puts("1http_read_chunk: Blank chunk length, trying again...");
4184 if (!httpGets(len, sizeof(len), http))
4185 {
4186 DEBUG_puts("1http_read_chunk: Could not get chunk length.");
4187 return (0);
4188 }
4189 }
4190
4191 http->data_remaining = strtoll(len, NULL, 16);
4192
4193 if (http->data_remaining < 0)
4194 {
4195 DEBUG_printf(("1http_read_chunk: Negative chunk length \"%s\" ("
4196 CUPS_LLFMT ")", len, CUPS_LLCAST http->data_remaining));
4197 return (0);
4198 }
4199
4200 DEBUG_printf(("2http_read_chunk: Got chunk length \"%s\" (" CUPS_LLFMT ")",
4201 len, CUPS_LLCAST http->data_remaining));
4202
4203 if (http->data_remaining == 0)
4204 {
4205 /*
4206 * 0-length chunk, grab trailing blank line...
4207 */
4208
4209 httpGets(len, sizeof(len), http);
4210 }
4211 }
4212
4213 DEBUG_printf(("2http_read_chunk: data_remaining=" CUPS_LLFMT,
4214 CUPS_LLCAST http->data_remaining));
4215
4216 if (http->data_remaining <= 0)
4217 return (0);
4218 else if (length > (size_t)http->data_remaining)
4219 length = (size_t)http->data_remaining;
4220
4221 return (http_read_buffered(http, buffer, length));
4222 }
4223
4224
4225 /*
4226 * 'http_send()' - Send a request with all fields and the trailing blank line.
4227 */
4228
4229 static int /* O - 0 on success, non-zero on error */
4230 http_send(http_t *http, /* I - HTTP connection */
4231 http_state_t request, /* I - Request code */
4232 const char *uri) /* I - URI */
4233 {
4234 int i; /* Looping var */
4235 char buf[1024]; /* Encoded URI buffer */
4236 const char *value; /* Field value */
4237 static const char * const codes[] = /* Request code strings */
4238 {
4239 NULL,
4240 "OPTIONS",
4241 "GET",
4242 NULL,
4243 "HEAD",
4244 "POST",
4245 NULL,
4246 NULL,
4247 "PUT",
4248 NULL,
4249 "DELETE",
4250 "TRACE",
4251 "CLOSE",
4252 NULL,
4253 NULL
4254 };
4255
4256
4257 DEBUG_printf(("4http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
4258 http, codes[request], uri));
4259
4260 if (http == NULL || uri == NULL)
4261 return (-1);
4262
4263 /*
4264 * Set the User-Agent field if it isn't already...
4265 */
4266
4267 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
4268 {
4269 if (http->default_user_agent)
4270 httpSetField(http, HTTP_FIELD_USER_AGENT, http->default_user_agent);
4271 else
4272 httpSetField(http, HTTP_FIELD_USER_AGENT, cupsUserAgent());
4273 }
4274
4275 /*
4276 * Set the Accept-Encoding field if it isn't already...
4277 */
4278
4279 if (!http->accept_encoding && http->default_accept_encoding)
4280 httpSetField(http, HTTP_FIELD_ACCEPT_ENCODING,
4281 http->default_accept_encoding);
4282
4283 /*
4284 * Encode the URI as needed...
4285 */
4286
4287 _httpEncodeURI(buf, uri, sizeof(buf));
4288
4289 /*
4290 * See if we had an error the last time around; if so, reconnect...
4291 */
4292
4293 if (http->fd < 0 || http->status == HTTP_STATUS_ERROR ||
4294 http->status >= HTTP_STATUS_BAD_REQUEST)
4295 {
4296 DEBUG_printf(("5http_send: Reconnecting, fd=%d, status=%d, tls_upgrade=%d",
4297 http->fd, http->status, http->tls_upgrade));
4298
4299 if (httpReconnect2(http, 30000, NULL))
4300 return (-1);
4301 }
4302
4303 /*
4304 * Flush any written data that is pending...
4305 */
4306
4307 if (http->wused)
4308 {
4309 if (httpFlushWrite(http) < 0)
4310 if (httpReconnect2(http, 30000, NULL))
4311 return (-1);
4312 }
4313
4314 /*
4315 * Send the request header...
4316 */
4317
4318 http->state = request;
4319 http->data_encoding = HTTP_ENCODING_FIELDS;
4320
4321 if (request == HTTP_STATE_POST || request == HTTP_STATE_PUT)
4322 http->state ++;
4323
4324 http->status = HTTP_STATUS_CONTINUE;
4325
4326 #ifdef HAVE_SSL
4327 if (http->encryption == HTTP_ENCRYPTION_REQUIRED && !http->tls)
4328 {
4329 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
4330 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
4331 }
4332 #endif /* HAVE_SSL */
4333
4334 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
4335 {
4336 http->status = HTTP_STATUS_ERROR;
4337 return (-1);
4338 }
4339
4340 for (i = 0; i < HTTP_FIELD_MAX; i ++)
4341 if ((value = httpGetField(http, i)) != NULL && *value)
4342 {
4343 DEBUG_printf(("5http_send: %s: %s", http_fields[i], value));
4344
4345 if (i == HTTP_FIELD_HOST)
4346 {
4347 if (httpPrintf(http, "Host: %s:%d\r\n", value,
4348 httpAddrPort(http->hostaddr)) < 1)
4349 {
4350 http->status = HTTP_STATUS_ERROR;
4351 return (-1);
4352 }
4353 }
4354 else if (httpPrintf(http, "%s: %s\r\n", http_fields[i], value) < 1)
4355 {
4356 http->status = HTTP_STATUS_ERROR;
4357 return (-1);
4358 }
4359 }
4360
4361 if (http->cookie)
4362 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
4363 {
4364 http->status = HTTP_STATUS_ERROR;
4365 return (-1);
4366 }
4367
4368 DEBUG_printf(("5http_send: expect=%d, mode=%d, state=%d", http->expect,
4369 http->mode, http->state));
4370
4371 if (http->expect == HTTP_STATUS_CONTINUE && http->mode == _HTTP_MODE_CLIENT &&
4372 (http->state == HTTP_STATE_POST_RECV ||
4373 http->state == HTTP_STATE_PUT_RECV))
4374 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
4375 {
4376 http->status = HTTP_STATUS_ERROR;
4377 return (-1);
4378 }
4379
4380 if (httpPrintf(http, "\r\n") < 1)
4381 {
4382 http->status = HTTP_STATUS_ERROR;
4383 return (-1);
4384 }
4385
4386 if (httpFlushWrite(http) < 0)
4387 return (-1);
4388
4389 http_set_length(http);
4390 httpClearFields(http);
4391
4392 /*
4393 * The Kerberos and AuthRef authentication strings can only be used once...
4394 */
4395
4396 if (http->field_authorization && http->authstring &&
4397 (!strncmp(http->authstring, "Negotiate", 9) ||
4398 !strncmp(http->authstring, "AuthRef", 7)))
4399 {
4400 http->_authstring[0] = '\0';
4401
4402 if (http->authstring != http->_authstring)
4403 free(http->authstring);
4404
4405 http->authstring = http->_authstring;
4406 }
4407
4408 return (0);
4409 }
4410
4411
4412 /*
4413 * 'http_set_length()' - Set the data_encoding and data_remaining values.
4414 */
4415
4416 static off_t /* O - Remainder or -1 on error */
4417 http_set_length(http_t *http) /* I - Connection */
4418 {
4419 off_t remaining; /* Remainder */
4420
4421
4422 DEBUG_printf(("http_set_length(http=%p) mode=%d state=%s", http, http->mode,
4423 httpStateString(http->state)));
4424
4425 if ((remaining = httpGetLength2(http)) >= 0)
4426 {
4427 if (http->mode == _HTTP_MODE_SERVER &&
4428 http->state != HTTP_STATE_GET_SEND &&
4429 http->state != HTTP_STATE_PUT &&
4430 http->state != HTTP_STATE_POST &&
4431 http->state != HTTP_STATE_POST_SEND)
4432 {
4433 DEBUG_puts("1http_set_length: Not setting data_encoding/remaining.");
4434 return (remaining);
4435 }
4436
4437 if (!_cups_strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING],
4438 "chunked"))
4439 {
4440 DEBUG_puts("1http_set_length: Setting data_encoding to "
4441 "HTTP_ENCODING_CHUNKED.");
4442 http->data_encoding = HTTP_ENCODING_CHUNKED;
4443 }
4444 else
4445 {
4446 DEBUG_puts("1http_set_length: Setting data_encoding to "
4447 "HTTP_ENCODING_LENGTH.");
4448 http->data_encoding = HTTP_ENCODING_LENGTH;
4449 }
4450
4451 DEBUG_printf(("1http_set_length: Setting data_remaining to " CUPS_LLFMT ".",
4452 CUPS_LLCAST remaining));
4453 http->data_remaining = remaining;
4454
4455 if (remaining <= INT_MAX)
4456 http->_data_remaining = remaining;
4457 else
4458 http->_data_remaining = INT_MAX;
4459 }
4460
4461 return (remaining);
4462 }
4463
4464 /*
4465 * 'http_set_timeout()' - Set the socket timeout values.
4466 */
4467
4468 static void
4469 http_set_timeout(int fd, /* I - File descriptor */
4470 double timeout) /* I - Timeout in seconds */
4471 {
4472 #ifdef WIN32
4473 DWORD tv = (DWORD)(timeout * 1000);
4474 /* Timeout in milliseconds */
4475
4476 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
4477 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
4478
4479 #else
4480 struct timeval tv; /* Timeout in secs and usecs */
4481
4482 tv.tv_sec = (int)timeout;
4483 tv.tv_usec = (int)(1000000 * fmod(timeout, 1.0));
4484
4485 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, CUPS_SOCAST &tv, sizeof(tv));
4486 setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, CUPS_SOCAST &tv, sizeof(tv));
4487 #endif /* WIN32 */
4488 }
4489
4490
4491 /*
4492 * 'http_set_wait()' - Set the default wait value for reads.
4493 */
4494
4495 static void
4496 http_set_wait(http_t *http) /* I - HTTP connection */
4497 {
4498 if (http->blocking)
4499 {
4500 http->wait_value = (int)(http->timeout_value * 1000);
4501
4502 if (http->wait_value <= 0)
4503 http->wait_value = 60000;
4504 }
4505 else
4506 http->wait_value = 10000;
4507 }
4508
4509
4510 #ifdef HAVE_SSL
4511 /*
4512 * 'http_tls_upgrade()' - Force upgrade to TLS encryption.
4513 */
4514
4515 static int /* O - Status of connection */
4516 http_tls_upgrade(http_t *http) /* I - HTTP connection */
4517 {
4518 int ret; /* Return value */
4519 http_t myhttp; /* Local copy of HTTP data */
4520
4521
4522 DEBUG_printf(("7http_tls_upgrade(%p)", http));
4523
4524 /*
4525 * Flush the connection to make sure any previous "Upgrade" message
4526 * has been read.
4527 */
4528
4529 httpFlush(http);
4530
4531 /*
4532 * Copy the HTTP data to a local variable so we can do the OPTIONS
4533 * request without interfering with the existing request data...
4534 */
4535
4536 memcpy(&myhttp, http, sizeof(myhttp));
4537
4538 /*
4539 * Send an OPTIONS request to the server, requiring SSL or TLS
4540 * encryption on the link...
4541 */
4542
4543 http->tls_upgrade = 1;
4544 http->field_authorization = NULL; /* Don't free the auth string */
4545
4546 httpClearFields(http);
4547 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
4548 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.2,TLS/1.1,TLS/1.0");
4549
4550 if ((ret = httpOptions(http, "*")) == 0)
4551 {
4552 /*
4553 * Wait for the secure connection...
4554 */
4555
4556 while (httpUpdate(http) == HTTP_STATUS_CONTINUE);
4557 }
4558
4559 /*
4560 * Restore the HTTP request data...
4561 */
4562
4563 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
4564 http->data_encoding = myhttp.data_encoding;
4565 http->data_remaining = myhttp.data_remaining;
4566 http->_data_remaining = myhttp._data_remaining;
4567 http->expect = myhttp.expect;
4568 http->field_authorization = myhttp.field_authorization;
4569 http->digest_tries = myhttp.digest_tries;
4570 http->tls_upgrade = 0;
4571
4572 /*
4573 * See if we actually went secure...
4574 */
4575
4576 if (!http->tls)
4577 {
4578 /*
4579 * Server does not support HTTP upgrade...
4580 */
4581
4582 DEBUG_puts("8http_tls_upgrade: Server does not support HTTP upgrade!");
4583
4584 httpAddrClose(NULL, http->fd);
4585
4586 http->fd = -1;
4587
4588 return (-1);
4589 }
4590 else
4591 return (ret);
4592 }
4593 #endif /* HAVE_SSL */
4594
4595
4596 /*
4597 * 'http_write()' - Write a buffer to a HTTP connection.
4598 */
4599
4600 static ssize_t /* O - Number of bytes written */
4601 http_write(http_t *http, /* I - HTTP connection */
4602 const char *buffer, /* I - Buffer for data */
4603 size_t length) /* I - Number of bytes to write */
4604 {
4605 ssize_t tbytes, /* Total bytes sent */
4606 bytes; /* Bytes sent */
4607
4608
4609 DEBUG_printf(("2http_write(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
4610 buffer, CUPS_LLCAST length));
4611 http->error = 0;
4612 tbytes = 0;
4613
4614 while (length > 0)
4615 {
4616 DEBUG_printf(("3http_write: About to write %d bytes.", (int)length));
4617
4618 if (http->timeout_cb)
4619 {
4620 #ifdef HAVE_POLL
4621 struct pollfd pfd; /* Polled file descriptor */
4622 #else
4623 fd_set output_set; /* Output ready for write? */
4624 struct timeval timeout; /* Timeout value */
4625 #endif /* HAVE_POLL */
4626 int nfds; /* Result from select()/poll() */
4627
4628 do
4629 {
4630 #ifdef HAVE_POLL
4631 pfd.fd = http->fd;
4632 pfd.events = POLLOUT;
4633
4634 while ((nfds = poll(&pfd, 1, http->wait_value)) < 0 &&
4635 (errno == EINTR || errno == EAGAIN))
4636 /* do nothing */;
4637
4638 #else
4639 do
4640 {
4641 FD_ZERO(&output_set);
4642 FD_SET(http->fd, &output_set);
4643
4644 timeout.tv_sec = http->wait_value / 1000;
4645 timeout.tv_usec = 1000 * (http->wait_value % 1000);
4646
4647 nfds = select(http->fd + 1, NULL, &output_set, NULL, &timeout);
4648 }
4649 # ifdef WIN32
4650 while (nfds < 0 && (WSAGetLastError() == WSAEINTR ||
4651 WSAGetLastError() == WSAEWOULDBLOCK));
4652 # else
4653 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
4654 # endif /* WIN32 */
4655 #endif /* HAVE_POLL */
4656
4657 if (nfds < 0)
4658 {
4659 http->error = errno;
4660 return (-1);
4661 }
4662 else if (nfds == 0 && !(*http->timeout_cb)(http, http->timeout_data))
4663 {
4664 #ifdef WIN32
4665 http->error = WSAEWOULDBLOCK;
4666 #else
4667 http->error = EWOULDBLOCK;
4668 #endif /* WIN32 */
4669 return (-1);
4670 }
4671 }
4672 while (nfds <= 0);
4673 }
4674
4675 #ifdef HAVE_SSL
4676 if (http->tls)
4677 bytes = http_tls_write(http, buffer, length);
4678 else
4679 #endif /* HAVE_SSL */
4680 bytes = send(http->fd, buffer, length, 0);
4681
4682 DEBUG_printf(("3http_write: Write of " CUPS_LLFMT " bytes returned "
4683 CUPS_LLFMT ".", CUPS_LLCAST length, CUPS_LLCAST bytes));
4684
4685 if (bytes < 0)
4686 {
4687 #ifdef WIN32
4688 if (WSAGetLastError() == WSAEINTR)
4689 continue;
4690 else if (WSAGetLastError() == WSAEWOULDBLOCK)
4691 {
4692 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4693 continue;
4694
4695 http->error = WSAGetLastError();
4696 }
4697 else if (WSAGetLastError() != http->error &&
4698 WSAGetLastError() != WSAECONNRESET)
4699 {
4700 http->error = WSAGetLastError();
4701 continue;
4702 }
4703
4704 #else
4705 if (errno == EINTR)
4706 continue;
4707 else if (errno == EWOULDBLOCK || errno == EAGAIN)
4708 {
4709 if (http->timeout_cb && (*http->timeout_cb)(http, http->timeout_data))
4710 continue;
4711 else if (!http->timeout_cb && errno == EAGAIN)
4712 continue;
4713
4714 http->error = errno;
4715 }
4716 else if (errno != http->error && errno != ECONNRESET)
4717 {
4718 http->error = errno;
4719 continue;
4720 }
4721 #endif /* WIN32 */
4722
4723 DEBUG_printf(("3http_write: error writing data (%s).",
4724 strerror(http->error)));
4725
4726 return (-1);
4727 }
4728
4729 buffer += bytes;
4730 tbytes += bytes;
4731 length -= bytes;
4732 }
4733
4734 #ifdef DEBUG
4735 http_debug_hex("http_write", buffer - tbytes, tbytes);
4736 #endif /* DEBUG */
4737
4738 DEBUG_printf(("3http_write: Returning " CUPS_LLFMT ".", CUPS_LLCAST tbytes));
4739
4740 return (tbytes);
4741 }
4742
4743
4744 /*
4745 * 'http_write_chunk()' - Write a chunked buffer.
4746 */
4747
4748 static ssize_t /* O - Number bytes written */
4749 http_write_chunk(http_t *http, /* I - HTTP connection */
4750 const char *buffer, /* I - Buffer to write */
4751 size_t length) /* I - Length of buffer */
4752 {
4753 char header[16]; /* Chunk header */
4754 ssize_t bytes; /* Bytes written */
4755
4756
4757 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
4758 http, buffer, CUPS_LLCAST length));
4759
4760 /*
4761 * Write the chunk header, data, and trailer.
4762 */
4763
4764 snprintf(header, sizeof(header), "%x\r\n", (unsigned)length);
4765 if (http_write(http, header, strlen(header)) < 0)
4766 {
4767 DEBUG_puts("8http_write_chunk: http_write of length failed.");
4768 return (-1);
4769 }
4770
4771 if ((bytes = http_write(http, buffer, length)) < 0)
4772 {
4773 DEBUG_puts("8http_write_chunk: http_write of buffer failed.");
4774 return (-1);
4775 }
4776
4777 if (http_write(http, "\r\n", 2) < 0)
4778 {
4779 DEBUG_puts("8http_write_chunk: http_write of CR LF failed.");
4780 return (-1);
4781 }
4782
4783 return (bytes);
4784 }
4785
4786
4787 /*
4788 * End of "$Id$".
4789 */