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