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