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