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