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