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