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