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