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