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