]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Merge changes from CUPS 1.4svn-r7696.
[thirdparty/cups.git] / cups / http.c
CommitLineData
ef416fc2 1/*
75bd9771 2 * "$Id: http.c 7661 2008-06-16 21:46:51Z mike $"
ef416fc2 3 *
4 * HTTP routines for the Common UNIX Printing System (CUPS).
5 *
91c84a35 6 * Copyright 2007-2008 by Apple Inc.
b86bc4cf 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 8 *
f7deaa1a 9 * This file contains Kerberos support code, copyright 2006 by
10 * Jelmer Vernooij.
11 *
ef416fc2 12 * These coded instructions, statements, and computer programs are the
bc44d920 13 * property of Apple Inc. and are protected by Federal copyright
14 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
15 * which should have been included with this file. If this file is
16 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 17 *
18 * This file is subject to the Apple OS-Developed Software exception.
19 *
20 * Contents:
21 *
411affcf 22 * _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP connections.
ecdc0628 23 * httpBlocking() - Set blocking/non-blocking behavior on a connection.
ef416fc2 24 * httpCheck() - Check to see if there is a pending response from
25 * the server.
26 * httpClearCookie() - Clear the cookie value(s).
ecdc0628 27 * httpClearFields() - Clear HTTP request fields.
ef416fc2 28 * httpClose() - Close an HTTP connection...
29 * httpConnect() - Connect to a HTTP server.
30 * httpConnectEncrypt() - Connect to a HTTP server using encryption.
31 * httpDelete() - Send a DELETE request to the server.
32 * httpEncryption() - Set the required encryption on the link.
ecdc0628 33 * httpError() - Get the last error on a connection.
ef416fc2 34 * httpFlush() - Flush data from a HTTP connection.
35 * httpFlushWrite() - Flush data in write buffer.
36 * httpGet() - Send a GET request to the server.
355e94dc 37 * httpGetAuthString() - Get the current authorization string.
ecdc0628 38 * httpGetBlocking() - Get the blocking/non-block state of a connection.
39 * httpGetCookie() - Get any cookie data from the response.
40 * httpGetFd() - Get the file descriptor associated with a
41 * connection.
42 * httpGetField() - Get a field value from a request/response.
ef416fc2 43 * httpGetLength() - Get the amount of data remaining from the
44 * content-length or transfer-encoding fields.
45 * httpGetLength2() - Get the amount of data remaining from the
46 * content-length or transfer-encoding fields.
ecdc0628 47 * httpGetStatus() - Get the status of the last HTTP request.
ef416fc2 48 * httpGetSubField() - Get a sub-field value.
49 * httpGets() - Get a line of text from a HTTP connection.
50 * httpHead() - Send a HEAD request to the server.
51 * httpInitialize() - Initialize the HTTP interface library and set the
52 * default HTTP proxy (if any).
53 * httpOptions() - Send an OPTIONS request to the server.
54 * httpPost() - Send a POST request to the server.
55 * httpPrintf() - Print a formatted string to a HTTP connection.
56 * httpPut() - Send a PUT request to the server.
57 * httpRead() - Read data from a HTTP connection.
a4d04587 58 * httpRead2() - Read data from a HTTP connection.
411affcf 59 * _httpReadCDSA() - Read function for the CDSA library.
60 * _httpReadGNUTLS() - Read function for the GNU TLS library.
ef416fc2 61 * httpReconnect() - Reconnect to a HTTP server...
355e94dc 62 * httpSetAuthString() - Set the current authorization string.
ef416fc2 63 * httpSetCookie() - Set the cookie value(s)...
b423cd4c 64 * httpSetExpect() - Set the Expect: header in a request.
ef416fc2 65 * httpSetField() - Set the value of an HTTP header.
66 * httpSetLength() - Set the content-length and transfer-encoding.
67 * httpTrace() - Send an TRACE request to the server.
68 * httpUpdate() - Update the current HTTP state for incoming data.
69 * httpWait() - Wait for data available on a connection.
70 * httpWrite() - Write data to a HTTP connection.
a4d04587 71 * httpWrite2() - Write data to a HTTP connection.
411affcf 72 * _httpWriteCDSA() - Write function for the CDSA library.
73 * _httpWriteGNUTLS() - Write function for the GNU TLS library.
74 * http_bio_ctrl() - Control the HTTP connection.
75 * http_bio_free() - Free OpenSSL data.
76 * http_bio_new() - Initialize an OpenSSL BIO structure.
77 * http_bio_puts() - Send a string for OpenSSL.
78 * http_bio_read() - Read data for OpenSSL.
79 * http_bio_write() - Write data for OpenSSL.
ae71f5de 80 * http_debug_hex() - Do a hex dump of a buffer.
ef416fc2 81 * http_field() - Return the field index for a field name.
82 * http_read_ssl() - Read from a SSL/TLS connection.
83 * http_send() - Send a request with all fields and the trailing
84 * blank line.
85 * http_setup_ssl() - Set up SSL/TLS on a connection.
86 * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
87 * http_upgrade() - Force upgrade to TLS encryption.
88 * http_wait() - Wait for data available on a connection.
89 * http_write() - Write data to a connection.
90 * http_write_ssl() - Write to a SSL/TLS connection.
91 */
92
93/*
94 * Include necessary headers...
95 */
96
97#include "http-private.h"
98#include "globals.h"
99#include "debug.h"
100#include <stdlib.h>
101#include <fcntl.h>
102#include <errno.h>
103#ifndef WIN32
104# include <signal.h>
105# include <sys/time.h>
106# include <sys/resource.h>
107#endif /* !WIN32 */
f7deaa1a 108#ifdef HAVE_POLL
109# include <sys/poll.h>
110#endif /* HAVE_POLL */
ef416fc2 111
112
113/*
114 * Some operating systems have done away with the Fxxxx constants for
115 * the fcntl() call; this works around that "feature"...
116 */
117
118#ifndef FNONBLK
119# define FNONBLK O_NONBLOCK
120#endif /* !FNONBLK */
121
122
123/*
124 * Local functions...
125 */
126
ae71f5de
MS
127#ifdef DEBUG
128static void http_debug_hex(const char *prefix, const char *buffer,
129 int bytes);
130#endif /* DEBUG */
ef416fc2 131static http_field_t http_field(const char *name);
132static int http_send(http_t *http, http_state_t request,
133 const char *uri);
411affcf 134static int http_wait(http_t *http, int msec, int usessl);
ef416fc2 135static int http_write(http_t *http, const char *buffer,
136 int length);
137static int http_write_chunk(http_t *http, const char *buffer,
138 int length);
139#ifdef HAVE_SSL
140static int http_read_ssl(http_t *http, char *buf, int len);
141static int http_setup_ssl(http_t *http);
142static void http_shutdown_ssl(http_t *http);
143static int http_upgrade(http_t *http);
144static int http_write_ssl(http_t *http, const char *buf, int len);
145#endif /* HAVE_SSL */
146
147
148/*
149 * Local globals...
150 */
151
152static const char * const http_fields[] =
153 {
154 "Accept-Language",
155 "Accept-Ranges",
156 "Authorization",
157 "Connection",
158 "Content-Encoding",
159 "Content-Language",
160 "Content-Length",
161 "Content-Location",
162 "Content-MD5",
163 "Content-Range",
164 "Content-Type",
165 "Content-Version",
166 "Date",
167 "Host",
168 "If-Modified-Since",
169 "If-Unmodified-since",
170 "Keep-Alive",
171 "Last-Modified",
172 "Link",
173 "Location",
174 "Range",
175 "Referer",
176 "Retry-After",
177 "Transfer-Encoding",
178 "Upgrade",
179 "User-Agent",
180 "WWW-Authenticate"
181 };
182
183
411affcf 184#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
185/*
186 * BIO methods for OpenSSL...
187 */
188
189static int http_bio_write(BIO *h, const char *buf, int num);
190static int http_bio_read(BIO *h, char *buf, int size);
191static int http_bio_puts(BIO *h, const char *str);
192static long http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
193static int http_bio_new(BIO *h);
194static int http_bio_free(BIO *data);
195
196static BIO_METHOD http_bio_methods =
197 {
198 BIO_TYPE_SOCKET,
199 "http",
200 http_bio_write,
201 http_bio_read,
202 http_bio_puts,
203 NULL, /* http_bio_gets, */
204 http_bio_ctrl,
205 http_bio_new,
206 http_bio_free,
207 NULL,
208 };
209
210
211/*
212 * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
213 */
214
215BIO_METHOD * /* O - BIO methods for OpenSSL */
216_httpBIOMethods(void)
217{
218 return (&http_bio_methods);
219}
220#endif /* HAVE_SSL && HAVE_LIBSSL */
221
222
ecdc0628 223/*
224 * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
225 */
226
227void
568fa3fa 228httpBlocking(http_t *http, /* I - Connection to server */
ecdc0628 229 int b) /* I - 1 = blocking, 0 = non-blocking */
230{
231 if (http)
232 http->blocking = b;
233}
234
235
ef416fc2 236/*
237 * 'httpCheck()' - Check to see if there is a pending response from the server.
238 */
239
ecdc0628 240int /* O - 0 = no data, 1 = data available */
568fa3fa 241httpCheck(http_t *http) /* I - Connection to server */
ef416fc2 242{
243 return (httpWait(http, 0));
244}
245
246
247/*
248 * 'httpClearCookie()' - Clear the cookie value(s).
249 *
250 * @since CUPS 1.1.19@
251 */
252
253void
568fa3fa 254httpClearCookie(http_t *http) /* I - Connection to server */
ef416fc2 255{
256 if (!http)
257 return;
258
259 if (http->cookie)
260 {
261 free(http->cookie);
262 http->cookie = NULL;
263 }
264}
265
266
ecdc0628 267/*
268 * 'httpClearFields()' - Clear HTTP request fields.
269 */
270
271void
568fa3fa 272httpClearFields(http_t *http) /* I - Connection to server */
ecdc0628 273{
274 if (http)
275 {
276 memset(http->fields, 0, sizeof(http->fields));
07725fee 277 if (http->hostname[0] == '/')
278 httpSetField(http, HTTP_FIELD_HOST, "localhost");
279 else
280 httpSetField(http, HTTP_FIELD_HOST, http->hostname);
b423cd4c 281
f7deaa1a 282 if (http->field_authorization)
283 {
284 free(http->field_authorization);
285 http->field_authorization = NULL;
286 }
287
b423cd4c 288 http->expect = (http_status_t)0;
ecdc0628 289 }
290}
291
292
ef416fc2 293/*
294 * 'httpClose()' - Close an HTTP connection...
295 */
296
297void
568fa3fa 298httpClose(http_t *http) /* I - Connection to server */
ef416fc2 299{
f7deaa1a 300#ifdef HAVE_GSSAPI
301 OM_uint32 minor_status, /* Minor status code */
302 major_status; /* Major status code */
303#endif /* HAVE_GSSAPI */
304
305
ef416fc2 306 DEBUG_printf(("httpClose(http=%p)\n", http));
307
308 if (!http)
309 return;
310
311 httpAddrFreeList(http->addrlist);
312
ef416fc2 313 if (http->cookie)
314 free(http->cookie);
315
316#ifdef HAVE_SSL
317 if (http->tls)
318 http_shutdown_ssl(http);
319#endif /* HAVE_SSL */
320
321#ifdef WIN32
322 closesocket(http->fd);
323#else
324 close(http->fd);
325#endif /* WIN32 */
326
f7deaa1a 327#ifdef HAVE_GSSAPI
328 if (http->gssctx != GSS_C_NO_CONTEXT)
329 major_status = gss_delete_sec_context(&minor_status, &http->gssctx,
330 GSS_C_NO_BUFFER);
331
332 if (http->gssname != GSS_C_NO_NAME)
333 major_status = gss_release_name(&minor_status, &http->gssname);
334#endif /* HAVE_GSSAPI */
335
b94498cf 336#ifdef HAVE_AUTHORIZATION_H
337 if (http->auth_ref)
338 AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
339#endif /* HAVE_AUTHORIZATION_H */
340
f7deaa1a 341 httpClearFields(http);
342
343 if (http->authstring && http->authstring != http->_authstring)
344 free(http->authstring);
345
ef416fc2 346 free(http);
347}
348
349
350/*
351 * 'httpConnect()' - Connect to a HTTP server.
352 */
353
354http_t * /* O - New HTTP connection */
355httpConnect(const char *host, /* I - Host to connect to */
356 int port) /* I - Port number */
357{
358 http_encryption_t encryption; /* Type of encryption to use */
359
360
361 /*
362 * Set the default encryption status...
363 */
364
365 if (port == 443)
366 encryption = HTTP_ENCRYPT_ALWAYS;
367 else
368 encryption = HTTP_ENCRYPT_IF_REQUESTED;
369
370 return (httpConnectEncrypt(host, port, encryption));
371}
372
373
374/*
375 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
376 */
377
378http_t * /* O - New HTTP connection */
379httpConnectEncrypt(
380 const char *host, /* I - Host to connect to */
381 int port, /* I - Port number */
382 http_encryption_t encryption) /* I - Type of encryption to use */
383{
384 http_t *http; /* New HTTP connection */
385 http_addrlist_t *addrlist; /* Host address data */
386 char service[255]; /* Service name */
387
388
389 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)\n",
390 host ? host : "(null)", port, encryption));
391
392 if (!host)
393 return (NULL);
394
395 httpInitialize();
396
397 /*
398 * Lookup the host...
399 */
400
401 sprintf(service, "%d", port);
402
403 if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
404 return (NULL);
405
406 /*
407 * Allocate memory for the structure...
408 */
409
91c84a35
MS
410 if ((http = calloc(sizeof(http_t), 1)) == NULL)
411 {
412 httpAddrFreeList(addrlist);
ef416fc2 413 return (NULL);
91c84a35 414 }
ef416fc2 415
416 http->version = HTTP_1_1;
417 http->blocking = 1;
418 http->activity = time(NULL);
419 http->fd = -1;
420
f7deaa1a 421#ifdef HAVE_GSSAPI
422 http->gssctx = GSS_C_NO_CONTEXT;
423 http->gssname = GSS_C_NO_NAME;
424#endif /* HAVE_GSSAPI */
425
ef416fc2 426 /*
427 * Set the encryption status...
428 */
429
430 if (port == 443) /* Always use encryption for https */
431 http->encryption = HTTP_ENCRYPT_ALWAYS;
432 else
433 http->encryption = encryption;
434
435 /*
436 * Loop through the addresses we have until one of them connects...
437 */
438
439 strlcpy(http->hostname, host, sizeof(http->hostname));
440
441 /*
442 * Connect to the remote system...
443 */
444
445 http->addrlist = addrlist;
446
447 if (!httpReconnect(http))
448 return (http);
449
450 /*
451 * Could not connect to any known address - bail out!
452 */
453
454 httpAddrFreeList(addrlist);
455
456 free(http);
457
458 return (NULL);
459}
460
461
462/*
463 * 'httpDelete()' - Send a DELETE request to the server.
464 */
465
466int /* O - Status of call (0 = success) */
568fa3fa 467httpDelete(http_t *http, /* I - Connection to server */
ef416fc2 468 const char *uri) /* I - URI to delete */
469{
470 return (http_send(http, HTTP_DELETE, uri));
471}
472
473
474/*
475 * 'httpEncryption()' - Set the required encryption on the link.
476 */
477
478int /* O - -1 on error, 0 on success */
568fa3fa 479httpEncryption(http_t *http, /* I - Connection to server */
ef416fc2 480 http_encryption_t e) /* I - New encryption preference */
481{
482 DEBUG_printf(("httpEncryption(http=%p, e=%d)\n", http, e));
483
484#ifdef HAVE_SSL
485 if (!http)
486 return (0);
487
488 http->encryption = e;
489
490 if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
491 (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
492 return (httpReconnect(http));
493 else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
494 return (http_upgrade(http));
495 else
496 return (0);
497#else
498 if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
499 return (-1);
500 else
501 return (0);
502#endif /* HAVE_SSL */
503}
504
505
ecdc0628 506/*
507 * 'httpError()' - Get the last error on a connection.
508 */
509
510int /* O - Error code (errno) value */
568fa3fa 511httpError(http_t *http) /* I - Connection to server */
ecdc0628 512{
513 if (http)
514 return (http->error);
515 else
516 return (EINVAL);
517}
518
519
ef416fc2 520/*
521 * 'httpFlush()' - Flush data from a HTTP connection.
522 */
523
524void
568fa3fa 525httpFlush(http_t *http) /* I - Connection to server */
ef416fc2 526{
527 char buffer[8192]; /* Junk buffer */
fa73b229 528 int blocking; /* To block or not to block */
ef416fc2 529
530
531 DEBUG_printf(("httpFlush(http=%p), state=%d\n", http, http->state));
532
fa73b229 533 /*
534 * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
535 */
536
537 blocking = http->blocking;
538 http->blocking = 0;
539
540 /*
541 * Read any data we can...
542 */
543
a4d04587 544 while (httpRead2(http, buffer, sizeof(buffer)) > 0);
fa73b229 545
546 /*
547 * Restore blocking and reset the connection if we didn't get all of
548 * the remaining data...
549 */
550
551 http->blocking = blocking;
552
553 if (http->state != HTTP_WAITING && http->fd >= 0)
554 {
555 /*
556 * Didn't get the data back, so close the current connection.
557 */
558
559 http->state = HTTP_WAITING;
560
561#ifdef HAVE_SSL
562 if (http->tls)
563 http_shutdown_ssl(http);
564#endif /* HAVE_SSL */
565
566#ifdef WIN32
567 closesocket(http->fd);
568#else
569 close(http->fd);
570#endif /* WIN32 */
571
572 http->fd = -1;
573 }
ef416fc2 574}
575
576
577/*
578 * 'httpFlushWrite()' - Flush data in write buffer.
579 *
580 * @since CUPS 1.2@
581 */
582
583int /* O - Bytes written or -1 on error */
568fa3fa 584httpFlushWrite(http_t *http) /* I - Connection to server */
ef416fc2 585{
586 int bytes; /* Bytes written */
587
588
589 DEBUG_printf(("httpFlushWrite(http=%p)\n", http));
590
591 if (!http || !http->wused)
592 return (0);
593
594 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
595 bytes = http_write_chunk(http, http->wbuffer, http->wused);
596 else
597 bytes = http_write(http, http->wbuffer, http->wused);
598
599 http->wused = 0;
600
601 return (bytes);
602}
603
604
605/*
606 * 'httpGet()' - Send a GET request to the server.
607 */
608
609int /* O - Status of call (0 = success) */
568fa3fa 610httpGet(http_t *http, /* I - Connection to server */
ef416fc2 611 const char *uri) /* I - URI to get */
612{
613 return (http_send(http, HTTP_GET, uri));
614}
615
616
355e94dc
MS
617/*
618 * 'httpGetAuthString()' - Get the current authorization string.
619 *
620 * The authorization string is set by cupsDoAuthentication() and
621 * httpSetAuthString(). Use httpGetAuthString() to retrieve the
622 * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
623 * value.
624 *
625 * @since CUPS 1.3@
626 */
627
628char * /* O - Authorization string */
568fa3fa 629httpGetAuthString(http_t *http) /* I - Connection to server */
355e94dc
MS
630{
631 if (http)
632 return (http->authstring);
633 else
634 return (NULL);
635}
636
637
ecdc0628 638/*
639 * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
640 *
641 * @since CUPS 1.2@
642 */
643
644int /* O - 1 if blocking, 0 if non-blocking */
568fa3fa 645httpGetBlocking(http_t *http) /* I - Connection to server */
ecdc0628 646{
647 return (http ? http->blocking : 0);
648}
649
650
651/*
652 * 'httpGetCookie()' - Get any cookie data from the response.
757d2cad 653 *
654 * @since CUPS 1.1.19@
ecdc0628 655 */
656
657const char * /* O - Cookie data or NULL */
658httpGetCookie(http_t *http) /* I - HTTP connecion */
659{
660 return (http ? http->cookie : NULL);
661}
662
663
664/*
665 * 'httpGetFd()' - Get the file descriptor associated with a connection.
666 *
667 * @since CUPS 1.2@
668 */
669
670int /* O - File descriptor or -1 if none */
568fa3fa 671httpGetFd(http_t *http) /* I - Connection to server */
ecdc0628 672{
673 return (http ? http->fd : -1);
674}
675
676
677/*
678 * 'httpGetField()' - Get a field value from a request/response.
679 */
680
681const char * /* O - Field value */
568fa3fa 682httpGetField(http_t *http, /* I - Connection to server */
ecdc0628 683 http_field_t field) /* I - Field to get */
684{
685 if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
686 return (NULL);
f7deaa1a 687 else if (field == HTTP_FIELD_AUTHORIZATION &&
688 http->field_authorization)
689 {
690 /*
691 * Special case for WWW-Authenticate: as its contents can be
692 * longer than HTTP_MAX_VALUE...
693 */
694
695 return (http->field_authorization);
696 }
ecdc0628 697 else
698 return (http->fields[field]);
699}
700
701
702/*
703 * 'httpGetLength()' - Get the amount of data remaining from the
704 * content-length or transfer-encoding fields.
705 *
706 * This function is deprecated and will not return lengths larger than
707 * 2^31 - 1; use httpGetLength2() instead.
708 *
709 * @deprecated@
710 */
711
712int /* O - Content length */
568fa3fa 713httpGetLength(http_t *http) /* I - Connection to server */
ecdc0628 714{
715 /*
716 * Get the read content length and return the 32-bit value.
717 */
718
719 if (http)
720 {
721 httpGetLength2(http);
722
723 return (http->_data_remaining);
724 }
725 else
726 return (-1);
727}
728
729
730/*
731 * 'httpGetLength2()' - Get the amount of data remaining from the
732 * content-length or transfer-encoding fields.
733 *
734 * This function returns the complete content length, even for
735 * content larger than 2^31 - 1.
736 *
737 * @since CUPS 1.2@
738 */
739
740off_t /* O - Content length */
568fa3fa 741httpGetLength2(http_t *http) /* I - Connection to server */
ecdc0628 742{
743 DEBUG_printf(("httpGetLength2(http=%p), state=%d\n", http, http->state));
744
745 if (!http)
746 return (-1);
747
748 if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
749 {
750 DEBUG_puts("httpGetLength2: chunked request!");
751
752 http->data_encoding = HTTP_ENCODE_CHUNKED;
753 http->data_remaining = 0;
754 }
755 else
756 {
757 http->data_encoding = HTTP_ENCODE_LENGTH;
758
759 /*
760 * The following is a hack for HTTP servers that don't send a
761 * content-length or transfer-encoding field...
762 *
763 * If there is no content-length then the connection must close
764 * after the transfer is complete...
765 */
766
b86bc4cf 767 if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
768 {
769 /*
770 * Default content length is 0 for errors and 2^31-1 for other
771 * successful requests...
772 */
773
774 if (http->status >= HTTP_MULTIPLE_CHOICES)
775 http->data_remaining = 0;
776 else
777 http->data_remaining = 2147483647;
778 }
ecdc0628 779 else
780 http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
781 NULL, 10);
782
783 DEBUG_printf(("httpGetLength2: content_length=" CUPS_LLFMT "\n",
784 CUPS_LLCAST http->data_remaining));
785 }
786
787 if (http->data_remaining <= INT_MAX)
788 http->_data_remaining = (int)http->data_remaining;
789 else
790 http->_data_remaining = INT_MAX;
791
792 return (http->data_remaining);
793}
794
795
796/*
797 * 'httpGetStatus()' - Get the status of the last HTTP request.
798 *
799 * @since CUPS 1.2@
800 */
801
802http_status_t /* O - HTTP status */
568fa3fa 803httpGetStatus(http_t *http) /* I - Connection to server */
ecdc0628 804{
805 return (http ? http->status : HTTP_ERROR);
806}
807
808
ef416fc2 809/*
810 * 'httpGetSubField()' - Get a sub-field value.
811 *
812 * @deprecated@
813 */
814
815char * /* O - Value or NULL */
568fa3fa 816httpGetSubField(http_t *http, /* I - Connection to server */
ef416fc2 817 http_field_t field, /* I - Field index */
818 const char *name, /* I - Name of sub-field */
819 char *value) /* O - Value string */
820{
821 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
822}
823
824
825/*
826 * 'httpGetSubField2()' - Get a sub-field value.
827 *
828 * @since CUPS 1.2@
829 */
830
831char * /* O - Value or NULL */
568fa3fa 832httpGetSubField2(http_t *http, /* I - Connection to server */
ef416fc2 833 http_field_t field, /* I - Field index */
834 const char *name, /* I - Name of sub-field */
835 char *value, /* O - Value string */
836 int valuelen) /* I - Size of value buffer */
837{
838 const char *fptr; /* Pointer into field */
839 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
840 *ptr, /* Pointer into string buffer */
841 *end; /* End of value buffer */
842
843 DEBUG_printf(("httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, valuelen=%d)\n",
844 http, field, name, value, valuelen));
845
846 if (!http || !name || !value || valuelen < 2 ||
ecdc0628 847 field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
ef416fc2 848 return (NULL);
849
850 end = value + valuelen - 1;
851
852 for (fptr = http->fields[field]; *fptr;)
853 {
854 /*
855 * Skip leading whitespace...
856 */
857
858 while (isspace(*fptr & 255))
859 fptr ++;
860
861 if (*fptr == ',')
862 {
863 fptr ++;
864 continue;
865 }
866
867 /*
868 * Get the sub-field name...
869 */
870
871 for (ptr = temp;
872 *fptr && *fptr != '=' && !isspace(*fptr & 255) &&
873 ptr < (temp + sizeof(temp) - 1);
874 *ptr++ = *fptr++);
875
876 *ptr = '\0';
877
878 DEBUG_printf(("httpGetSubField: name=\"%s\"\n", temp));
879
880 /*
881 * Skip trailing chars up to the '='...
882 */
883
884 while (isspace(*fptr & 255))
885 fptr ++;
886
887 if (!*fptr)
888 break;
889
890 if (*fptr != '=')
891 continue;
892
893 /*
894 * Skip = and leading whitespace...
895 */
896
897 fptr ++;
898
899 while (isspace(*fptr & 255))
900 fptr ++;
901
902 if (*fptr == '\"')
903 {
904 /*
905 * Read quoted string...
906 */
907
908 for (ptr = value, fptr ++;
909 *fptr && *fptr != '\"' && ptr < end;
910 *ptr++ = *fptr++);
911
912 *ptr = '\0';
913
914 while (*fptr && *fptr != '\"')
915 fptr ++;
916
917 if (*fptr)
918 fptr ++;
919 }
920 else
921 {
922 /*
923 * Read unquoted string...
924 */
925
926 for (ptr = value;
927 *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < end;
928 *ptr++ = *fptr++);
929
930 *ptr = '\0';
931
932 while (*fptr && !isspace(*fptr & 255) && *fptr != ',')
933 fptr ++;
934 }
935
936 DEBUG_printf(("httpGetSubField: value=\"%s\"\n", value));
937
938 /*
939 * See if this is the one...
940 */
941
942 if (!strcmp(name, temp))
943 return (value);
944 }
945
946 value[0] = '\0';
947
948 return (NULL);
949}
950
951
ef416fc2 952/*
953 * 'httpGets()' - Get a line of text from a HTTP connection.
954 */
955
956char * /* O - Line or NULL */
957httpGets(char *line, /* I - Line to read into */
958 int length, /* I - Max length of buffer */
568fa3fa 959 http_t *http) /* I - Connection to server */
ef416fc2 960{
961 char *lineptr, /* Pointer into line */
962 *lineend, /* End of line */
963 *bufptr, /* Pointer into input buffer */
964 *bufend; /* Pointer to end of buffer */
965 int bytes, /* Number of bytes read */
966 eol; /* End-of-line? */
967
968
969 DEBUG_printf(("httpGets(line=%p, length=%d, http=%p)\n", line, length, http));
970
971 if (http == NULL || line == NULL)
972 return (NULL);
973
974 /*
975 * Read a line from the buffer...
976 */
977
978 lineptr = line;
979 lineend = line + length - 1;
980 eol = 0;
981
982 while (lineptr < lineend)
983 {
984 /*
985 * Pre-load the buffer as needed...
986 */
987
988#ifdef WIN32
989 WSASetLastError(0);
990#else
991 errno = 0;
992#endif /* WIN32 */
993
994 while (http->used == 0)
995 {
996 /*
997 * No newline; see if there is more data to be read...
998 */
999
411affcf 1000 if (!http->blocking && !http_wait(http, 10000, 1))
89d46774 1001 {
1002 DEBUG_puts("httpGets: Timed out!");
b86bc4cf 1003#ifdef WIN32
1004 http->error = WSAETIMEDOUT;
1005#else
89d46774 1006 http->error = ETIMEDOUT;
b86bc4cf 1007#endif /* WIN32 */
ef416fc2 1008 return (NULL);
89d46774 1009 }
ef416fc2 1010
1011#ifdef HAVE_SSL
1012 if (http->tls)
1013 bytes = http_read_ssl(http, http->buffer + http->used,
1014 HTTP_MAX_BUFFER - http->used);
1015 else
1016#endif /* HAVE_SSL */
1017 bytes = recv(http->fd, http->buffer + http->used,
1018 HTTP_MAX_BUFFER - http->used, 0);
1019
1020 DEBUG_printf(("httpGets: read %d bytes...\n", bytes));
1021
1022 if (bytes < 0)
1023 {
1024 /*
1025 * Nope, can't get a line this time...
1026 */
1027
1028#ifdef WIN32
1029 if (WSAGetLastError() != http->error)
1030 {
1031 http->error = WSAGetLastError();
1032 continue;
1033 }
1034
1035 DEBUG_printf(("httpGets: recv() error %d!\n", WSAGetLastError()));
1036#else
1037 DEBUG_printf(("httpGets: recv() error %d!\n", errno));
1038
1039 if (errno == EINTR)
1040 continue;
1041 else if (errno != http->error)
1042 {
1043 http->error = errno;
1044 continue;
1045 }
1046#endif /* WIN32 */
1047
1048 return (NULL);
1049 }
1050 else if (bytes == 0)
1051 {
1052 http->error = EPIPE;
1053
1054 return (NULL);
1055 }
1056
1057 /*
1058 * Yup, update the amount used...
1059 */
1060
1061 http->used += bytes;
1062 }
1063
1064 /*
1065 * Now copy as much of the current line as possible...
1066 */
1067
1068 for (bufptr = http->buffer, bufend = http->buffer + http->used;
1069 lineptr < lineend && bufptr < bufend;)
1070 {
1071 if (*bufptr == 0x0a)
1072 {
1073 eol = 1;
1074 bufptr ++;
1075 break;
1076 }
1077 else if (*bufptr == 0x0d)
1078 bufptr ++;
1079 else
1080 *lineptr++ = *bufptr++;
1081 }
1082
b86bc4cf 1083 http->used -= (int)(bufptr - http->buffer);
ef416fc2 1084 if (http->used > 0)
1085 memmove(http->buffer, bufptr, http->used);
1086
1087 if (eol)
1088 {
1089 /*
1090 * End of line...
1091 */
1092
1093 http->activity = time(NULL);
1094
1095 *lineptr = '\0';
1096
1097 DEBUG_printf(("httpGets: Returning \"%s\"\n", line));
1098
1099 return (line);
1100 }
1101 }
1102
1103 DEBUG_puts("httpGets: No new line available!");
1104
1105 return (NULL);
1106}
1107
1108
1109/*
1110 * 'httpHead()' - Send a HEAD request to the server.
1111 */
1112
1113int /* O - Status of call (0 = success) */
568fa3fa 1114httpHead(http_t *http, /* I - Connection to server */
ef416fc2 1115 const char *uri) /* I - URI for head */
1116{
1117 return (http_send(http, HTTP_HEAD, uri));
1118}
1119
1120
1121/*
1122 * 'httpInitialize()' - Initialize the HTTP interface library and set the
1123 * default HTTP proxy (if any).
1124 */
1125
1126void
1127httpInitialize(void)
1128{
1129#ifdef HAVE_LIBSSL
1130# ifndef WIN32
1131 struct timeval curtime; /* Current time in microseconds */
1132# endif /* !WIN32 */
1133 int i; /* Looping var */
1134 unsigned char data[1024]; /* Seed data */
1135#endif /* HAVE_LIBSSL */
1136
1137#ifdef WIN32
1138 WSADATA winsockdata; /* WinSock data */
1139 static int initialized = 0; /* Has WinSock been initialized? */
1140
1141
1142 if (!initialized)
1143 WSAStartup(MAKEWORD(1,1), &winsockdata);
fa73b229 1144#elif !defined(SO_NOSIGPIPE)
ef416fc2 1145 /*
1146 * Ignore SIGPIPE signals...
1147 */
1148
fa73b229 1149# ifdef HAVE_SIGSET
1150 sigset(SIGPIPE, SIG_IGN);
1151# elif defined(HAVE_SIGACTION)
1152 struct sigaction action; /* POSIX sigaction data */
1153
1154
ef416fc2 1155 memset(&action, 0, sizeof(action));
1156 action.sa_handler = SIG_IGN;
1157 sigaction(SIGPIPE, &action, NULL);
fa73b229 1158# else
ef416fc2 1159 signal(SIGPIPE, SIG_IGN);
fa73b229 1160# endif /* !SO_NOSIGPIPE */
ef416fc2 1161#endif /* WIN32 */
1162
1163#ifdef HAVE_GNUTLS
1164 gnutls_global_init();
1165#endif /* HAVE_GNUTLS */
1166
1167#ifdef HAVE_LIBSSL
1168 SSL_load_error_strings();
1169 SSL_library_init();
1170
1171 /*
1172 * Using the current time is a dubious random seed, but on some systems
1173 * it is the best we can do (on others, this seed isn't even used...)
1174 */
1175
1176#ifdef WIN32
1177#else
1178 gettimeofday(&curtime, NULL);
1179 srand(curtime.tv_sec + curtime.tv_usec);
1180#endif /* WIN32 */
1181
1182 for (i = 0; i < sizeof(data); i ++)
1183 data[i] = rand(); /* Yes, this is a poor source of random data... */
1184
1185 RAND_seed(&data, sizeof(data));
1186#endif /* HAVE_LIBSSL */
1187}
1188
1189
1190/*
1191 * 'httpOptions()' - Send an OPTIONS request to the server.
1192 */
1193
1194int /* O - Status of call (0 = success) */
568fa3fa 1195httpOptions(http_t *http, /* I - Connection to server */
ef416fc2 1196 const char *uri) /* I - URI for options */
1197{
1198 return (http_send(http, HTTP_OPTIONS, uri));
1199}
1200
1201
1202/*
1203 * 'httpPost()' - Send a POST request to the server.
1204 */
1205
1206int /* O - Status of call (0 = success) */
568fa3fa 1207httpPost(http_t *http, /* I - Connection to server */
ef416fc2 1208 const char *uri) /* I - URI for post */
1209{
1210 return (http_send(http, HTTP_POST, uri));
1211}
1212
1213
1214/*
1215 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
ecdc0628 1216 *
1217 * @private@
ef416fc2 1218 */
1219
1220int /* O - Number of bytes written */
568fa3fa 1221httpPrintf(http_t *http, /* I - Connection to server */
ef416fc2 1222 const char *format, /* I - printf-style format string */
1223 ...) /* I - Additional args as needed */
1224{
1225 int bytes; /* Number of bytes to write */
1226 char buf[16384]; /* Buffer for formatted string */
1227 va_list ap; /* Variable argument pointer */
1228
1229
1230 DEBUG_printf(("httpPrintf(http=%p, format=\"%s\", ...)\n", http, format));
1231
1232 va_start(ap, format);
1233 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1234 va_end(ap);
1235
1236 DEBUG_printf(("httpPrintf: %s", buf));
1237
d09495fa 1238 if (http->data_encoding == HTTP_ENCODE_FIELDS)
1239 return (httpWrite2(http, buf, bytes));
1240 else
ef416fc2 1241 {
d09495fa 1242 if (http->wused)
1243 {
1244 DEBUG_puts(" flushing existing data...");
ef416fc2 1245
d09495fa 1246 if (httpFlushWrite(http) < 0)
1247 return (-1);
1248 }
ef416fc2 1249
d09495fa 1250 return (http_write(http, buf, bytes));
1251 }
ef416fc2 1252}
1253
1254
1255/*
1256 * 'httpPut()' - Send a PUT request to the server.
1257 */
1258
1259int /* O - Status of call (0 = success) */
568fa3fa 1260httpPut(http_t *http, /* I - Connection to server */
ef416fc2 1261 const char *uri) /* I - URI to put */
1262{
1263 return (http_send(http, HTTP_PUT, uri));
1264}
1265
1266
1267/*
1268 * 'httpRead()' - Read data from a HTTP connection.
a4d04587 1269 *
1270 * This function is deprecated. Use the httpRead2() function which can
1271 * read more than 2GB of data.
1272 *
1273 * @deprecated@
ef416fc2 1274 */
1275
1276int /* O - Number of bytes read */
568fa3fa 1277httpRead(http_t *http, /* I - Connection to server */
ef416fc2 1278 char *buffer, /* I - Buffer for data */
1279 int length) /* I - Maximum number of bytes */
1280{
a4d04587 1281 return ((int)httpRead2(http, buffer, length));
1282}
1283
1284
1285/*
1286 * 'httpRead2()' - Read data from a HTTP connection.
ecdc0628 1287 *
1288 * @since CUPS 1.2@
a4d04587 1289 */
1290
1291ssize_t /* O - Number of bytes read */
568fa3fa 1292httpRead2(http_t *http, /* I - Connection to server */
a4d04587 1293 char *buffer, /* I - Buffer for data */
1294 size_t length) /* I - Maximum number of bytes */
1295{
1296 ssize_t bytes; /* Bytes read */
ef416fc2 1297 char len[32]; /* Length string */
1298
1299
ae71f5de 1300 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ")\n",
a603edef 1301 http, buffer, CUPS_LLCAST length));
ef416fc2 1302
1303 if (http == NULL || buffer == NULL)
1304 return (-1);
1305
1306 http->activity = time(NULL);
1307
1308 if (length <= 0)
1309 return (0);
1310
1311 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1312 http->data_remaining <= 0)
1313 {
a4d04587 1314 DEBUG_puts("httpRead2: Getting chunk length...");
ef416fc2 1315
1316 if (httpGets(len, sizeof(len), http) == NULL)
1317 {
a4d04587 1318 DEBUG_puts("httpRead2: Could not get length!");
ef416fc2 1319 return (0);
1320 }
1321
1322 http->data_remaining = strtoll(len, NULL, 16);
1323 if (http->data_remaining < 0)
1324 {
a4d04587 1325 DEBUG_puts("httpRead2: Negative chunk length!");
ef416fc2 1326 return (0);
1327 }
1328 }
1329
a4d04587 1330 DEBUG_printf(("httpRead2: data_remaining=" CUPS_LLFMT "\n",
ef416fc2 1331 CUPS_LLCAST http->data_remaining));
1332
1333 if (http->data_remaining <= 0)
1334 {
1335 /*
1336 * A zero-length chunk ends a transfer; unless we are reading POST
1337 * data, go idle...
1338 */
1339
1340 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1341 httpGets(len, sizeof(len), http);
1342
1343 if (http->state == HTTP_POST_RECV)
1344 http->state ++;
1345 else
1346 http->state = HTTP_WAITING;
1347
1348 /*
1349 * Prevent future reads for this request...
1350 */
1351
1352 http->data_encoding = HTTP_ENCODE_LENGTH;
1353
1354 return (0);
1355 }
b86bc4cf 1356 else if (length > (size_t)http->data_remaining)
1357 length = (size_t)http->data_remaining;
ef416fc2 1358
1359 if (http->used == 0 && length <= 256)
1360 {
1361 /*
1362 * Buffer small reads for better performance...
1363 */
1364
ed486911 1365 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1366 return (0);
1367
1368 if (http->data_remaining > sizeof(http->buffer))
1369 bytes = sizeof(http->buffer);
1370 else
1371 bytes = http->data_remaining;
1372
1373#ifdef HAVE_SSL
1374 if (http->tls)
1375 bytes = http_read_ssl(http, http->buffer, bytes);
1376 else
1377#endif /* HAVE_SSL */
1378 {
a4d04587 1379 DEBUG_printf(("httpRead2: reading %d bytes from socket into buffer...\n",
a603edef 1380 (int)bytes));
ef416fc2 1381
1382 bytes = recv(http->fd, http->buffer, bytes, 0);
1383
a4d04587 1384 DEBUG_printf(("httpRead2: read %d bytes from socket into buffer...\n",
a603edef 1385 (int)bytes));
ef416fc2 1386 }
1387
1388 if (bytes > 0)
1389 http->used = bytes;
1390 else if (bytes < 0)
1391 {
1392#ifdef WIN32
1393 http->error = WSAGetLastError();
1394 return (-1);
1395#else
1396 if (errno != EINTR)
1397 {
1398 http->error = errno;
1399 return (-1);
1400 }
1401#endif /* WIN32 */
1402 }
1403 else
1404 {
1405 http->error = EPIPE;
1406 return (0);
1407 }
1408 }
1409
1410 if (http->used > 0)
1411 {
b86bc4cf 1412 if (length > (size_t)http->used)
1413 length = (size_t)http->used;
ef416fc2 1414
b86bc4cf 1415 bytes = (ssize_t)length;
ef416fc2 1416
a603edef
MS
1417 DEBUG_printf(("httpRead2: grabbing %d bytes from input buffer...\n",
1418 (int)bytes));
ef416fc2 1419
1420 memcpy(buffer, http->buffer, length);
b86bc4cf 1421 http->used -= (int)length;
ef416fc2 1422
1423 if (http->used > 0)
1424 memmove(http->buffer, http->buffer + length, http->used);
1425 }
1426#ifdef HAVE_SSL
1427 else if (http->tls)
1428 {
ed486911 1429 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1430 return (0);
1431
b86bc4cf 1432 bytes = (ssize_t)http_read_ssl(http, buffer, (int)length);
ef416fc2 1433 }
1434#endif /* HAVE_SSL */
1435 else
1436 {
ed486911 1437 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1438 return (0);
1439
a603edef
MS
1440 DEBUG_printf(("httpRead2: reading " CUPS_LLFMT " bytes from socket...\n",
1441 CUPS_LLCAST length));
ef416fc2 1442
b86bc4cf 1443#ifdef WIN32
1444 bytes = (ssize_t)recv(http->fd, buffer, (int)length, 0);
1445#else
ef416fc2 1446 while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
1447 if (errno != EINTR)
1448 break;
b86bc4cf 1449#endif /* WIN32 */
ef416fc2 1450
a603edef
MS
1451 DEBUG_printf(("httpRead2: read " CUPS_LLFMT " bytes from socket...\n",
1452 CUPS_LLCAST bytes));
ef416fc2 1453 }
1454
1455 if (bytes > 0)
1456 {
1457 http->data_remaining -= bytes;
1458
1459 if (http->data_remaining <= INT_MAX)
1460 http->_data_remaining = (int)http->data_remaining;
1461 else
1462 http->_data_remaining = INT_MAX;
1463 }
1464 else if (bytes < 0)
1465 {
1466#ifdef WIN32
1467 http->error = WSAGetLastError();
1468#else
1469 if (errno == EINTR)
1470 bytes = 0;
1471 else
1472 http->error = errno;
1473#endif /* WIN32 */
1474 }
1475 else
1476 {
1477 http->error = EPIPE;
1478 return (0);
1479 }
1480
1481 if (http->data_remaining == 0)
1482 {
1483 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1484 httpGets(len, sizeof(len), http);
1485
1486 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1487 {
1488 if (http->state == HTTP_POST_RECV)
1489 http->state ++;
1490 else
1491 http->state = HTTP_WAITING;
1492 }
1493 }
1494
1495#ifdef DEBUG
ae71f5de 1496 http_debug_hex("httpRead2", buffer, (int)bytes);
ef416fc2 1497#endif /* DEBUG */
1498
1499 return (bytes);
1500}
1501
1502
1503#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
1504/*
411affcf 1505 * '_httpReadCDSA()' - Read function for the CDSA library.
ef416fc2 1506 */
1507
1508OSStatus /* O - -1 on error, 0 on success */
1509_httpReadCDSA(
1510 SSLConnectionRef connection, /* I - SSL/TLS connection */
1511 void *data, /* I - Data buffer */
1512 size_t *dataLength) /* IO - Number of bytes */
1513{
411affcf 1514 OSStatus result; /* Return value */
1515 ssize_t bytes; /* Number of bytes read */
1516 http_t *http; /* HTTP connection */
1517
1518
1519 http = (http_t *)connection;
e53920b9 1520
411affcf 1521 if (!http->blocking)
1522 {
1523 /*
1524 * Make sure we have data before we read...
1525 */
e53920b9 1526
411affcf 1527 if (!http_wait(http, 10000, 0))
1528 {
1529 http->error = ETIMEDOUT;
1530 return (-1);
1531 }
1532 }
ef416fc2 1533
b423cd4c 1534 do
411affcf 1535 {
1536 bytes = recv(http->fd, data, *dataLength, 0);
1537 }
b423cd4c 1538 while (bytes == -1 && errno == EINTR);
fa73b229 1539
b423cd4c 1540 if (bytes == *dataLength)
411affcf 1541 {
b423cd4c 1542 result = 0;
411affcf 1543 }
b423cd4c 1544 else if (bytes > 0)
1545 {
1546 *dataLength = bytes;
1547 result = errSSLWouldBlock;
1548 }
1549 else
1550 {
1551 *dataLength = 0;
fa73b229 1552
1553 if (bytes == 0)
ed486911 1554 result = errSSLClosedGraceful;
b423cd4c 1555 else if (errno == EAGAIN)
1556 result = errSSLWouldBlock;
b423cd4c 1557 else
ed486911 1558 result = errSSLClosedAbort;
ef416fc2 1559 }
b423cd4c 1560
411affcf 1561 return (result);
ef416fc2 1562}
1563#endif /* HAVE_SSL && HAVE_CDSASSL */
1564
1565
411affcf 1566#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
1567/*
1568 * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
1569 */
1570
1571ssize_t /* O - Number of bytes read or -1 on error */
1572_httpReadGNUTLS(
568fa3fa 1573 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 1574 void *data, /* I - Buffer */
1575 size_t length) /* I - Number of bytes to read */
1576{
1577 http_t *http; /* HTTP connection */
1578
1579
1580 http = (http_t *)ptr;
1581
1582 if (!http->blocking)
1583 {
1584 /*
1585 * Make sure we have data before we read...
1586 */
1587
1588 if (!http_wait(http, 10000, 0))
1589 {
1590 http->error = ETIMEDOUT;
1591 return (-1);
1592 }
1593 }
1594
1595 return (recv(http->fd, data, length, 0));
1596}
1597#endif /* HAVE_SSL && HAVE_GNUTLS */
1598
1599
ef416fc2 1600/*
ecdc0628 1601 * 'httpReconnect()' - Reconnect to a HTTP server.
ef416fc2 1602 */
1603
1604int /* O - 0 on success, non-zero on failure */
568fa3fa 1605httpReconnect(http_t *http) /* I - Connection to server */
ef416fc2 1606{
1607 http_addrlist_t *addr; /* Connected address */
1608
1609
1610 DEBUG_printf(("httpReconnect(http=%p)\n", http));
1611
1612 if (!http)
1613 return (-1);
1614
1615#ifdef HAVE_SSL
1616 if (http->tls)
1617 http_shutdown_ssl(http);
1618#endif /* HAVE_SSL */
1619
1620 /*
1621 * Close any previously open socket...
1622 */
1623
1624 if (http->fd >= 0)
bd7854cb 1625 {
ef416fc2 1626#ifdef WIN32
1627 closesocket(http->fd);
1628#else
1629 close(http->fd);
1630#endif /* WIN32 */
1631
bd7854cb 1632 http->fd = -1;
1633 }
1634
ef416fc2 1635 /*
1636 * Connect to the server...
1637 */
1638
1639 if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
1640 {
1641 /*
1642 * Unable to connect...
1643 */
1644
1645#ifdef WIN32
1646 http->error = WSAGetLastError();
1647#else
1648 http->error = errno;
1649#endif /* WIN32 */
1650 http->status = HTTP_ERROR;
1651
1652 return (-1);
1653 }
1654
1655 http->hostaddr = &(addr->addr);
1656 http->error = 0;
1657 http->status = HTTP_CONTINUE;
1658
1659#ifdef HAVE_SSL
1660 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
1661 {
1662 /*
1663 * Always do encryption via SSL.
1664 */
1665
1666 if (http_setup_ssl(http) != 0)
1667 {
f7deaa1a 1668# ifdef WIN32
ef416fc2 1669 closesocket(http->fd);
f7deaa1a 1670# else
ef416fc2 1671 close(http->fd);
f7deaa1a 1672# endif /* WIN32 */
ef416fc2 1673
1674 return (-1);
1675 }
1676 }
1677 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
1678 return (http_upgrade(http));
1679#endif /* HAVE_SSL */
1680
1681 return (0);
1682}
1683
1684
355e94dc
MS
1685/*
1686 * 'httpSetAuthString()' - Set the current authorization string.
1687 *
1688 * This function just stores a copy of the current authorization string in
1689 * the HTTP connection object. You must still call httpSetField() to set
1690 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
1691 * httpHead(), httpOptions(), httpPost, or httpPut().
1692 *
1693 * @since CUPS 1.3@
1694 */
1695
1696void
568fa3fa 1697httpSetAuthString(http_t *http, /* I - Connection to server */
355e94dc
MS
1698 const char *scheme, /* I - Auth scheme (NULL to clear it) */
1699 const char *data) /* I - Auth data (NULL for none) */
1700{
1701 /*
1702 * Range check input...
1703 */
1704
1705 if (!http)
1706 return;
1707
1708 if (http->authstring && http->authstring != http->_authstring)
1709 free(http->authstring);
1710
1711 http->authstring = http->_authstring;
1712
1713 if (scheme)
1714 {
1715 /*
1716 * Set the current authorization string...
1717 */
1718
1719 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
91c84a35 1720 char *temp;
355e94dc
MS
1721
1722 if (len > (int)sizeof(http->_authstring))
91c84a35
MS
1723 {
1724 if ((temp = malloc(len)) == NULL)
1725 len = sizeof(http->_authstring);
1726 else
1727 http->authstring = temp;
1728 }
355e94dc
MS
1729
1730 if (data)
1731 snprintf(http->authstring, len, "%s %s", scheme, data);
1732 else
1733 strlcpy(http->authstring, scheme, len);
1734 }
1735 else
1736 {
1737 /*
1738 * Clear the current authorization string...
1739 */
1740
1741 http->_authstring[0] = '\0';
1742 }
1743}
1744
1745
ef416fc2 1746/*
1747 * 'httpSetCookie()' - Set the cookie value(s)...
1748 *
1749 * @since CUPS 1.1.19@
1750 */
1751
1752void
1753httpSetCookie(http_t *http, /* I - Connection */
1754 const char *cookie) /* I - Cookie string */
1755{
1756 if (!http)
1757 return;
1758
1759 if (http->cookie)
1760 free(http->cookie);
1761
1762 if (cookie)
1763 http->cookie = strdup(cookie);
1764 else
1765 http->cookie = NULL;
1766}
1767
1768
b423cd4c 1769/*
1770 * 'httpSetExpect()' - Set the Expect: header in a request.
1771 *
1772 * Currently only HTTP_CONTINUE is supported for the "expect" argument.
1773 *
1774 * @since CUPS 1.2@
1775 */
1776
1777void
568fa3fa 1778httpSetExpect(http_t *http, /* I - Connection to server */
b423cd4c 1779 http_status_t expect) /* I - HTTP status to expect (HTTP_CONTINUE) */
1780{
1781 if (http)
1782 http->expect = expect;
1783}
1784
1785
ef416fc2 1786/*
1787 * 'httpSetField()' - Set the value of an HTTP header.
1788 */
1789
1790void
568fa3fa 1791httpSetField(http_t *http, /* I - Connection to server */
ef416fc2 1792 http_field_t field, /* I - Field index */
1793 const char *value) /* I - Value */
1794{
1795 if (http == NULL ||
1796 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
1797 field > HTTP_FIELD_WWW_AUTHENTICATE ||
1798 value == NULL)
1799 return;
1800
1801 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
f7deaa1a 1802
1803 /*
1804 * Special case for Authorization: as its contents can be
1805 * longer than HTTP_MAX_VALUE
1806 */
1807
1808 if (field == HTTP_FIELD_AUTHORIZATION)
1809 {
1810 if (http->field_authorization)
1811 free(http->field_authorization);
1812
1813 http->field_authorization = strdup(value);
1814 }
ef416fc2 1815}
1816
1817
1818/*
1819 * 'httpSetLength()' - Set the content-length and content-encoding.
1820 *
1821 * @since CUPS 1.2@
1822 */
1823
1824void
568fa3fa 1825httpSetLength(http_t *http, /* I - Connection to server */
ef416fc2 1826 size_t length) /* I - Length (0 for chunked) */
1827{
1828 if (!http)
1829 return;
1830
1831 if (!length)
1832 {
1833 strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
1834 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
1835 }
1836 else
1837 {
1838 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
1839 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
1840 CUPS_LLFMT, CUPS_LLCAST length);
1841 }
1842}
1843
1844
1845/*
1846 * 'httpTrace()' - Send an TRACE request to the server.
1847 */
1848
1849int /* O - Status of call (0 = success) */
568fa3fa 1850httpTrace(http_t *http, /* I - Connection to server */
ef416fc2 1851 const char *uri) /* I - URI for trace */
1852{
1853 return (http_send(http, HTTP_TRACE, uri));
1854}
1855
1856
1857/*
1858 * 'httpUpdate()' - Update the current HTTP state for incoming data.
1859 */
1860
1861http_status_t /* O - HTTP status */
568fa3fa 1862httpUpdate(http_t *http) /* I - Connection to server */
ef416fc2 1863{
1864 char line[32768], /* Line from connection... */
1865 *value; /* Pointer to value on line */
1866 http_field_t field; /* Field index */
1867 int major, minor, /* HTTP version numbers */
1868 status; /* Request status */
1869
1870
1871 DEBUG_printf(("httpUpdate(http=%p), state=%d\n", http, http->state));
1872
1873 /*
1874 * Flush pending data, if any...
1875 */
1876
1877 if (http->wused)
1878 {
1879 DEBUG_puts(" flushing buffer...");
1880
1881 if (httpFlushWrite(http) < 0)
1882 return (HTTP_ERROR);
1883 }
1884
1885 /*
1886 * If we haven't issued any commands, then there is nothing to "update"...
1887 */
1888
1889 if (http->state == HTTP_WAITING)
1890 return (HTTP_CONTINUE);
1891
1892 /*
1893 * Grab all of the lines we can from the connection...
1894 */
1895
1896 while (httpGets(line, sizeof(line), http) != NULL)
1897 {
1898 DEBUG_printf(("httpUpdate: Got \"%s\"\n", line));
1899
1900 if (line[0] == '\0')
1901 {
1902 /*
1903 * Blank line means the start of the data section (if any). Return
1904 * the result code, too...
1905 *
1906 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
1907 * Instead, we just return HTTP_CONTINUE to the caller and keep on
1908 * tryin'...
1909 */
1910
1911 if (http->status == HTTP_CONTINUE)
1912 return (http->status);
1913
1914 if (http->status < HTTP_BAD_REQUEST)
1915 http->digest_tries = 0;
1916
1917#ifdef HAVE_SSL
1918 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
1919 {
1920 if (http_setup_ssl(http) != 0)
1921 {
1922# ifdef WIN32
1923 closesocket(http->fd);
1924# else
1925 close(http->fd);
1926# endif /* WIN32 */
1927
1928 return (HTTP_ERROR);
1929 }
1930
1931 return (HTTP_CONTINUE);
1932 }
1933#endif /* HAVE_SSL */
1934
1935 httpGetLength2(http);
1936
1937 switch (http->state)
1938 {
1939 case HTTP_GET :
1940 case HTTP_POST :
1941 case HTTP_POST_RECV :
1942 case HTTP_PUT :
1943 http->state ++;
1944 case HTTP_POST_SEND :
e1d6a774 1945 case HTTP_HEAD :
ef416fc2 1946 break;
1947
1948 default :
1949 http->state = HTTP_WAITING;
1950 break;
1951 }
1952
1953 return (http->status);
1954 }
1955 else if (strncmp(line, "HTTP/", 5) == 0)
1956 {
1957 /*
1958 * Got the beginning of a response...
1959 */
1960
1961 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
1962 return (HTTP_ERROR);
1963
1964 http->version = (http_version_t)(major * 100 + minor);
1965 http->status = (http_status_t)status;
1966 }
1967 else if ((value = strchr(line, ':')) != NULL)
1968 {
1969 /*
1970 * Got a value...
1971 */
1972
1973 *value++ = '\0';
1974 while (isspace(*value & 255))
1975 value ++;
1976
1977 /*
1978 * Be tolerants of servers that send unknown attribute fields...
1979 */
1980
1981 if (!strcasecmp(line, "expect"))
1982 {
1983 /*
1984 * "Expect: 100-continue" or similar...
1985 */
1986
1987 http->expect = (http_status_t)atoi(value);
1988 }
1989 else if (!strcasecmp(line, "cookie"))
1990 {
1991 /*
1992 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
1993 */
1994
1995 httpSetCookie(http, value);
1996 }
1997 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
1998 {
1999 DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line));
2000 continue;
2001 }
2002 else
2003 httpSetField(http, field, value);
2004 }
2005 else
2006 {
2007 http->status = HTTP_ERROR;
2008 return (HTTP_ERROR);
2009 }
2010 }
2011
2012 /*
2013 * See if there was an error...
2014 */
2015
2016 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
2017 return (http->status);
2018
2019 if (http->error)
2020 {
2021 DEBUG_printf(("httpUpdate: socket error %d - %s\n", http->error,
2022 strerror(http->error)));
2023 http->status = HTTP_ERROR;
2024 return (HTTP_ERROR);
2025 }
2026
2027 /*
2028 * If we haven't already returned, then there is nothing new...
2029 */
2030
2031 return (HTTP_CONTINUE);
2032}
2033
2034
2035/*
2036 * 'httpWait()' - Wait for data available on a connection.
2037 *
2038 * @since CUPS 1.1.19@
2039 */
2040
2041int /* O - 1 if data is available, 0 otherwise */
568fa3fa 2042httpWait(http_t *http, /* I - Connection to server */
ef416fc2 2043 int msec) /* I - Milliseconds to wait */
2044{
2045 /*
2046 * First see if there is data in the buffer...
2047 */
2048
2049 if (http == NULL)
2050 return (0);
2051
2052 if (http->used)
2053 return (1);
2054
8ca02f3c 2055 /*
2056 * Flush pending data, if any...
2057 */
2058
2059 if (http->wused)
2060 {
2061 if (httpFlushWrite(http) < 0)
2062 return (0);
2063 }
2064
ef416fc2 2065 /*
2066 * If not, check the SSL/TLS buffers and do a select() on the connection...
2067 */
2068
411affcf 2069 return (http_wait(http, msec, 1));
ef416fc2 2070}
2071
2072
2073/*
2074 * 'httpWrite()' - Write data to a HTTP connection.
a4d04587 2075 *
2076 * This function is deprecated. Use the httpWrite2() function which can
2077 * write more than 2GB of data.
2078 *
2079 * @deprecated@
ef416fc2 2080 */
2081
2082int /* O - Number of bytes written */
568fa3fa 2083httpWrite(http_t *http, /* I - Connection to server */
ef416fc2 2084 const char *buffer, /* I - Buffer for data */
2085 int length) /* I - Number of bytes to write */
2086{
a4d04587 2087 return ((int)httpWrite2(http, buffer, length));
2088}
2089
2090
2091/*
2092 * 'httpWrite2()' - Write data to a HTTP connection.
ecdc0628 2093 *
2094 * @since CUPS 1.2@
a4d04587 2095 */
2096
2097ssize_t /* O - Number of bytes written */
568fa3fa 2098httpWrite2(http_t *http, /* I - Connection to server */
a4d04587 2099 const char *buffer, /* I - Buffer for data */
2100 size_t length) /* I - Number of bytes to write */
2101{
2102 ssize_t bytes; /* Bytes written */
ef416fc2 2103
2104
ae71f5de 2105 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")\n", http,
a603edef 2106 buffer, CUPS_LLCAST length));
ef416fc2 2107
2108 /*
2109 * Range check input...
2110 */
2111
2112 if (http == NULL || buffer == NULL)
2113 return (-1);
2114
2115 /*
2116 * Mark activity on the connection...
2117 */
2118
2119 http->activity = time(NULL);
2120
2121 /*
2122 * Buffer small writes for better performance...
2123 */
2124
2125 if (length > 0)
2126 {
2127 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
2128 {
ae71f5de
MS
2129 DEBUG_printf(("httpWrite2: Flushing buffer (wused=%d, length="
2130 CUPS_LLFMT ")\n", http->wused, CUPS_LLCAST length));
ef416fc2 2131
2132 httpFlushWrite(http);
2133 }
2134
07725fee 2135 if ((length + http->wused) <= sizeof(http->wbuffer))
ef416fc2 2136 {
2137 /*
2138 * Write to buffer...
2139 */
2140
ae71f5de 2141 DEBUG_printf(("httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...\n",
a603edef 2142 CUPS_LLCAST length));
ef416fc2 2143
2144 memcpy(http->wbuffer + http->wused, buffer, length);
b86bc4cf 2145 http->wused += (int)length;
2146 bytes = (ssize_t)length;
ef416fc2 2147 }
2148 else
2149 {
2150 /*
2151 * Otherwise write the data directly...
2152 */
2153
ae71f5de 2154 DEBUG_printf(("httpWrite2: Writing " CUPS_LLFMT " bytes to socket...\n",
a603edef 2155 CUPS_LLCAST length));
ef416fc2 2156
2157 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
b86bc4cf 2158 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
ef416fc2 2159 else
b86bc4cf 2160 bytes = (ssize_t)http_write(http, buffer, (int)length);
ef416fc2 2161
ae71f5de
MS
2162 DEBUG_printf(("httpWrite2: Wrote " CUPS_LLFMT " bytes...\n",
2163 CUPS_LLCAST bytes));
ef416fc2 2164 }
2165
2166 if (http->data_encoding == HTTP_ENCODE_LENGTH)
2167 http->data_remaining -= bytes;
2168 }
2169 else
2170 bytes = 0;
2171
2172 /*
2173 * Handle end-of-request processing...
2174 */
2175
2176 if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
2177 (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
2178 {
2179 /*
2180 * Finished with the transfer; unless we are sending POST or PUT
2181 * data, go idle...
2182 */
2183
2184 DEBUG_puts("httpWrite: changing states...");
2185
2186 if (http->wused)
2187 httpFlushWrite(http);
2188
2189 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
2190 {
2191 /*
2192 * Send a 0-length chunk at the end of the request...
2193 */
2194
2195 http_write(http, "0\r\n\r\n", 5);
2196
2197 /*
2198 * Reset the data state...
2199 */
2200
2201 http->data_encoding = HTTP_ENCODE_LENGTH;
2202 http->data_remaining = 0;
2203 }
2204
2205 if (http->state == HTTP_POST_RECV)
2206 http->state ++;
2207 else if (http->state == HTTP_PUT_RECV)
2208 http->state = HTTP_STATUS;
2209 else
2210 http->state = HTTP_WAITING;
2211 }
2212
2213 return (bytes);
2214}
2215
2216
2217#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2218/*
411affcf 2219 * '_httpWriteCDSA()' - Write function for the CDSA library.
ef416fc2 2220 */
2221
2222OSStatus /* O - -1 on error, 0 on success */
2223_httpWriteCDSA(
2224 SSLConnectionRef connection, /* I - SSL/TLS connection */
2225 const void *data, /* I - Data buffer */
2226 size_t *dataLength) /* IO - Number of bytes */
2227{
411affcf 2228 OSStatus result; /* Return value */
2229 ssize_t bytes; /* Number of bytes read */
2230 http_t *http; /* HTTP connection */
e53920b9 2231
2232
411affcf 2233 http = (http_t *)connection;
ef416fc2 2234
b423cd4c 2235 do
411affcf 2236 {
2237 bytes = write(http->fd, data, *dataLength);
2238 }
b423cd4c 2239 while (bytes == -1 && errno == EINTR);
fa73b229 2240
b423cd4c 2241 if (bytes == *dataLength)
411affcf 2242 {
b423cd4c 2243 result = 0;
411affcf 2244 }
b423cd4c 2245 else if (bytes >= 0)
2246 {
2247 *dataLength = bytes;
2248 result = errSSLWouldBlock;
2249 }
2250 else
2251 {
2252 *dataLength = 0;
2253
fa73b229 2254 if (errno == EAGAIN)
b423cd4c 2255 result = errSSLWouldBlock;
b423cd4c 2256 else
ed486911 2257 result = errSSLClosedAbort;
ef416fc2 2258 }
b423cd4c 2259
411affcf 2260 return (result);
ef416fc2 2261}
2262#endif /* HAVE_SSL && HAVE_CDSASSL */
2263
2264
411affcf 2265#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
2266/*
2267 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
2268 */
2269
2270ssize_t /* O - Number of bytes written or -1 on error */
2271_httpWriteGNUTLS(
568fa3fa 2272 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 2273 const void *data, /* I - Data buffer */
2274 size_t length) /* I - Number of bytes to write */
2275{
2276 return (send(((http_t *)ptr)->fd, data, length, 0));
2277}
2278#endif /* HAVE_SSL && HAVE_GNUTLS */
2279
2280
2281#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
2282/*
2283 * 'http_bio_ctrl()' - Control the HTTP connection.
2284 */
2285
2286static long /* O - Result/data */
2287http_bio_ctrl(BIO *h, /* I - BIO data */
2288 int cmd, /* I - Control command */
2289 long arg1, /* I - First argument */
2290 void *arg2) /* I - Second argument */
2291{
2292 switch (cmd)
2293 {
2294 default :
2295 return (0);
2296
2297 case BIO_CTRL_RESET :
2298 h->ptr = NULL;
2299 return (0);
2300
2301 case BIO_C_SET_FILE_PTR :
2302 h->ptr = arg2;
2303 h->init = 1;
2304 return (1);
2305
2306 case BIO_C_GET_FILE_PTR :
2307 if (arg2)
2308 {
2309 *((void **)arg2) = h->ptr;
2310 return (1);
2311 }
2312 else
2313 return (0);
2314
2315 case BIO_CTRL_DUP :
2316 case BIO_CTRL_FLUSH :
2317 return (1);
2318 }
2319}
2320
2321
2322/*
2323 * 'http_bio_free()' - Free OpenSSL data.
2324 */
2325
2326static int /* O - 1 on success, 0 on failure */
2327http_bio_free(BIO *h) /* I - BIO data */
2328{
2329 if (!h)
2330 return (0);
2331
2332 if (h->shutdown)
2333 {
2334 h->init = 0;
2335 h->flags = 0;
2336 }
2337
2338 return (1);
2339}
2340
2341
2342/*
2343 * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
2344 */
2345
2346static int /* O - 1 on success, 0 on failure */
2347http_bio_new(BIO *h) /* I - BIO data */
2348{
2349 if (!h)
2350 return (0);
2351
2352 h->init = 0;
2353 h->num = 0;
2354 h->ptr = NULL;
2355 h->flags = 0;
2356
2357 return (1);
2358}
2359
2360
2361/*
2362 * 'http_bio_puts()' - Send a string for OpenSSL.
2363 */
2364
2365static int /* O - Bytes written */
2366http_bio_puts(BIO *h, /* I - BIO data */
2367 const char *str) /* I - String to write */
2368{
b86bc4cf 2369#ifdef WIN32
2370 return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0));
2371#else
411affcf 2372 return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
b86bc4cf 2373#endif /* WIN32 */
411affcf 2374}
2375
2376
2377/*
2378 * 'http_bio_read()' - Read data for OpenSSL.
2379 */
2380
2381static int /* O - Bytes read */
2382http_bio_read(BIO *h, /* I - BIO data */
2383 char *buf, /* I - Buffer */
2384 int size) /* I - Number of bytes to read */
2385{
2386 http_t *http; /* HTTP connection */
2387
2388
2389 http = (http_t *)h->ptr;
2390
2391 if (!http->blocking)
2392 {
2393 /*
2394 * Make sure we have data before we read...
2395 */
2396
2397 if (!http_wait(http, 10000, 0))
2398 {
b86bc4cf 2399#ifdef WIN32
2400 http->error = WSAETIMEDOUT;
2401#else
411affcf 2402 http->error = ETIMEDOUT;
b86bc4cf 2403#endif /* WIN32 */
2404
411affcf 2405 return (-1);
2406 }
2407 }
2408
2409 return (recv(http->fd, buf, size, 0));
2410}
2411
2412
2413/*
2414 * 'http_bio_write()' - Write data for OpenSSL.
2415 */
2416
2417static int /* O - Bytes written */
2418http_bio_write(BIO *h, /* I - BIO data */
2419 const char *buf, /* I - Buffer to write */
2420 int num) /* I - Number of bytes to write */
2421{
2422 return (send(((http_t *)h->ptr)->fd, buf, num, 0));
2423}
2424#endif /* HAVE_SSL && HAVE_LIBSSL */
2425
2426
ae71f5de
MS
2427#ifdef DEBUG
2428/*
2429 * 'http_debug_hex()' - Do a hex dump of a buffer.
2430 */
2431
2432static void
2433http_debug_hex(const char *prefix, /* I - Prefix for line */
2434 const char *buffer, /* I - Buffer to dump */
2435 int bytes) /* I - Bytes to dump */
2436{
2437 int i, j, /* Looping vars */
2438 ch; /* Current character */
2439 char line[255], /* Line buffer */
2440 *start, /* Start of line after prefix */
2441 *ptr; /* Pointer into line */
dd1abb6b 2442 _cups_globals_t *cg = _cupsGlobals(); /* Global data */
ae71f5de
MS
2443
2444
dd1abb6b
MS
2445 if (cg->debug_init && cg->debug_fd < 0)
2446 return;
2447
ae71f5de
MS
2448 DEBUG_printf(("%s: %d bytes:\n", prefix, bytes));
2449
2450 snprintf(line, sizeof(line), "%s: ", prefix);
2451 start = line + strlen(line);
2452
2453 for (i = 0; i < bytes; i += 16)
2454 {
2455 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
2456 sprintf(ptr, "%02X", buffer[i + j] & 255);
2457
2458 while (j < 16)
2459 {
2460 strcpy(ptr, " ");
2461 ptr += 2;
2462 j ++;
2463 }
2464
2465 strcpy(ptr, " ");
2466 ptr += 2;
2467
2468 for (j = 0; j < 16 && (i + j) < bytes; j ++)
2469 {
2470 ch = buffer[i + j] & 255;
2471
2472 if (ch < ' ' || ch >= 127)
2473 ch = '.';
2474
2475 *ptr++ = ch;
2476 }
2477
2478 *ptr = '\0';
2479 DEBUG_puts(line);
2480 }
2481}
2482#endif /* DEBUG */
2483
2484
ef416fc2 2485/*
2486 * 'http_field()' - Return the field index for a field name.
2487 */
2488
ae71f5de
MS
2489static http_field_t /* O - Field index */
2490http_field(const char *name) /* I - String name */
ef416fc2 2491{
ae71f5de 2492 int i; /* Looping var */
ef416fc2 2493
2494
2495 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2496 if (strcasecmp(name, http_fields[i]) == 0)
2497 return ((http_field_t)i);
2498
2499 return (HTTP_FIELD_UNKNOWN);
2500}
2501
2502
2503#ifdef HAVE_SSL
2504/*
2505 * 'http_read_ssl()' - Read from a SSL/TLS connection.
2506 */
2507
2508static int /* O - Bytes read */
568fa3fa 2509http_read_ssl(http_t *http, /* I - Connection to server */
ef416fc2 2510 char *buf, /* I - Buffer to store data */
2511 int len) /* I - Length of buffer */
2512{
2513# if defined(HAVE_LIBSSL)
2514 return (SSL_read((SSL *)(http->tls), buf, len));
2515
2516# elif defined(HAVE_GNUTLS)
2517 return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
2518
2519# elif defined(HAVE_CDSASSL)
fa73b229 2520 int result; /* Return value */
ef416fc2 2521 OSStatus error; /* Error info */
2522 size_t processed; /* Number of bytes processed */
2523
2524
89d46774 2525 error = SSLRead(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 2526
fa73b229 2527 switch (error)
ef416fc2 2528 {
fa73b229 2529 case 0 :
2530 result = (int)processed;
2531 break;
2532 case errSSLClosedGraceful :
2533 result = 0;
2534 break;
2535 case errSSLWouldBlock :
b423cd4c 2536 if (processed)
2537 result = (int)processed;
2538 else
2539 {
2540 result = -1;
2541 errno = EINTR;
2542 }
fa73b229 2543 break;
2544 default :
2545 errno = EPIPE;
2546 result = -1;
2547 break;
ef416fc2 2548 }
fa73b229 2549
2550 return (result);
ef416fc2 2551# endif /* HAVE_LIBSSL */
2552}
2553#endif /* HAVE_SSL */
2554
2555
2556/*
2557 * 'http_send()' - Send a request with all fields and the trailing blank line.
2558 */
2559
2560static int /* O - 0 on success, non-zero on error */
568fa3fa 2561http_send(http_t *http, /* I - Connection to server */
ef416fc2 2562 http_state_t request, /* I - Request code */
2563 const char *uri) /* I - URI */
2564{
2565 int i; /* Looping var */
839a51c8 2566 char buf[1024]; /* Encoded URI buffer */
ef416fc2 2567 static const char * const codes[] =
2568 { /* Request code strings */
2569 NULL,
2570 "OPTIONS",
2571 "GET",
2572 NULL,
2573 "HEAD",
2574 "POST",
2575 NULL,
2576 NULL,
2577 "PUT",
2578 NULL,
2579 "DELETE",
2580 "TRACE",
2581 "CLOSE"
2582 };
ef416fc2 2583
2584
2585 DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n",
2586 http, codes[request], uri));
2587
2588 if (http == NULL || uri == NULL)
2589 return (-1);
2590
2591 /*
2592 * Set the User-Agent field if it isn't already...
2593 */
2594
2595 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
2596 httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
2597
2598 /*
2599 * Encode the URI as needed...
2600 */
2601
839a51c8 2602 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 2603
2604 /*
2605 * See if we had an error the last time around; if so, reconnect...
2606 */
2607
2608 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
fa73b229 2609 if (httpReconnect(http))
2610 return (-1);
ef416fc2 2611
d09495fa 2612 /*
2613 * Flush any written data that is pending...
2614 */
2615
2616 if (http->wused)
2617 httpFlushWrite(http);
2618
ef416fc2 2619 /*
2620 * Send the request header...
2621 */
2622
d09495fa 2623 http->state = request;
2624 http->data_encoding = HTTP_ENCODE_FIELDS;
2625
ef416fc2 2626 if (request == HTTP_POST || request == HTTP_PUT)
2627 http->state ++;
2628
2629 http->status = HTTP_CONTINUE;
2630
2631#ifdef HAVE_SSL
2632 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
2633 {
2634 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
2635 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
2636 }
2637#endif /* HAVE_SSL */
2638
2639 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
2640 {
2641 http->status = HTTP_ERROR;
2642 return (-1);
2643 }
2644
2645 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2646 if (http->fields[i][0] != '\0')
2647 {
ae71f5de
MS
2648 DEBUG_printf(("http_send: %s: %s\n", http_fields[i],
2649 httpGetField(http, i)));
ef416fc2 2650
f7deaa1a 2651 if (httpPrintf(http, "%s: %s\r\n", http_fields[i],
2652 httpGetField(http, i)) < 1)
ef416fc2 2653 {
2654 http->status = HTTP_ERROR;
2655 return (-1);
2656 }
2657 }
2658
2659 if (http->cookie)
2660 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
2661 {
2662 http->status = HTTP_ERROR;
2663 return (-1);
2664 }
2665
b423cd4c 2666 if (http->expect == HTTP_CONTINUE &&
2667 (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
2668 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
2669 {
2670 http->status = HTTP_ERROR;
2671 return (-1);
2672 }
2673
ef416fc2 2674 if (httpPrintf(http, "\r\n") < 1)
2675 {
2676 http->status = HTTP_ERROR;
2677 return (-1);
2678 }
2679
d09495fa 2680 httpFlushWrite(http);
ef416fc2 2681 httpGetLength2(http);
2682 httpClearFields(http);
2683
f7deaa1a 2684 /*
b94498cf 2685 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 2686 */
2687
bc44d920 2688 if (http->field_authorization && http->authstring &&
b94498cf 2689 (!strncmp(http->authstring, "Negotiate", 9) ||
2690 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 2691 {
2692 http->_authstring[0] = '\0';
2693
2694 if (http->authstring != http->_authstring)
2695 free(http->authstring);
2696
2697 http->authstring = http->_authstring;
2698 }
2699
ef416fc2 2700 return (0);
2701}
2702
2703
2704#ifdef HAVE_SSL
2705/*
2706 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
2707 */
2708
2709static int /* O - Status of connection */
568fa3fa 2710http_setup_ssl(http_t *http) /* I - Connection to server */
ef416fc2 2711{
2712# ifdef HAVE_LIBSSL
89d46774 2713 SSL_CTX *context; /* Context for encryption */
2714 SSL *conn; /* Connection for encryption */
411affcf 2715 BIO *bio; /* BIO data */
ef416fc2 2716# elif defined(HAVE_GNUTLS)
89d46774 2717 http_tls_t *conn; /* TLS session object */
ef416fc2 2718 gnutls_certificate_client_credentials *credentials;
89d46774 2719 /* TLS credentials */
ef416fc2 2720# elif defined(HAVE_CDSASSL)
89d46774 2721 OSStatus error; /* Error code */
2722 http_tls_t *conn; /* CDSA connection information */
ef416fc2 2723# endif /* HAVE_LIBSSL */
2724
2725
2726 DEBUG_printf(("http_setup_ssl(http=%p)\n", http));
2727
2728# ifdef HAVE_LIBSSL
2729 context = SSL_CTX_new(SSLv23_client_method());
2730
2731 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
2732
411affcf 2733 bio = BIO_new(_httpBIOMethods());
2734 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
2735
ef416fc2 2736 conn = SSL_new(context);
411affcf 2737 SSL_set_bio(conn, bio, bio);
ef416fc2 2738
ef416fc2 2739 if (SSL_connect(conn) != 1)
2740 {
2741# ifdef DEBUG
2742 unsigned long error; /* Error code */
2743
2744 while ((error = ERR_get_error()) != 0)
2745 printf("http_setup_ssl: %s\n", ERR_error_string(error, NULL));
2746# endif /* DEBUG */
2747
2748 SSL_CTX_free(context);
2749 SSL_free(conn);
2750
2751# ifdef WIN32
2752 http->error = WSAGetLastError();
2753# else
2754 http->error = errno;
2755# endif /* WIN32 */
2756 http->status = HTTP_ERROR;
2757
2758 return (HTTP_ERROR);
2759 }
2760
2761# elif defined(HAVE_GNUTLS)
89d46774 2762 if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
ef416fc2 2763 {
2764 http->error = errno;
2765 http->status = HTTP_ERROR;
2766
2767 return (-1);
2768 }
2769
2770 credentials = (gnutls_certificate_client_credentials *)
2771 malloc(sizeof(gnutls_certificate_client_credentials));
2772 if (credentials == NULL)
2773 {
2774 free(conn);
2775
2776 http->error = errno;
2777 http->status = HTTP_ERROR;
2778
2779 return (-1);
2780 }
2781
2782 gnutls_certificate_allocate_credentials(credentials);
2783
2784 gnutls_init(&(conn->session), GNUTLS_CLIENT);
2785 gnutls_set_default_priority(conn->session);
2786 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
411affcf 2787 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)http);
2788 gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
2789 gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
ef416fc2 2790
2791 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
2792 {
2793 http->error = errno;
2794 http->status = HTTP_ERROR;
2795
2796 return (-1);
2797 }
2798
2799 conn->credentials = credentials;
2800
2801# elif defined(HAVE_CDSASSL)
89d46774 2802 conn = (http_tls_t *)calloc(1, sizeof(http_tls_t));
e53920b9 2803
89d46774 2804 if (conn == NULL)
2805 return (-1);
e53920b9 2806
89d46774 2807 if ((error = SSLNewContext(false, &conn->session)))
e53920b9 2808 {
89d46774 2809 http->error = error;
2810 http->status = HTTP_ERROR;
e53920b9 2811
89d46774 2812 free(conn);
2813 return (-1);
e53920b9 2814 }
ef416fc2 2815
89d46774 2816 /*
2817 * Use a union to resolve warnings about int/pointer size mismatches...
2818 */
2819
411affcf 2820 error = SSLSetConnection(conn->session, http);
89d46774 2821
2822 if (!error)
2823 error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
2824
ef416fc2 2825 if (!error)
89d46774 2826 error = SSLSetAllowsExpiredCerts(conn->session, true);
ef416fc2 2827
2828 if (!error)
89d46774 2829 error = SSLSetAllowsAnyRoot(conn->session, true);
ef416fc2 2830
ed486911 2831 if (!error)
2832 error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
2833
ef416fc2 2834 if (!error)
b423cd4c 2835 {
89d46774 2836 while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
b423cd4c 2837 usleep(1000);
2838 }
ef416fc2 2839
89d46774 2840 if (error)
ef416fc2 2841 {
2842 http->error = error;
2843 http->status = HTTP_ERROR;
2844
89d46774 2845 SSLDisposeContext(conn->session);
ef416fc2 2846
89d46774 2847 free(conn);
ef416fc2 2848
2849 return (-1);
2850 }
2851# endif /* HAVE_CDSASSL */
2852
2853 http->tls = conn;
2854 return (0);
2855}
2856#endif /* HAVE_SSL */
2857
2858
2859#ifdef HAVE_SSL
2860/*
2861 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
2862 */
2863
2864static void
568fa3fa 2865http_shutdown_ssl(http_t *http) /* I - Connection to server */
ef416fc2 2866{
2867# ifdef HAVE_LIBSSL
89d46774 2868 SSL_CTX *context; /* Context for encryption */
2869 SSL *conn; /* Connection for encryption */
ef416fc2 2870
2871
2872 conn = (SSL *)(http->tls);
2873 context = SSL_get_SSL_CTX(conn);
2874
2875 SSL_shutdown(conn);
2876 SSL_CTX_free(context);
2877 SSL_free(conn);
2878
2879# elif defined(HAVE_GNUTLS)
89d46774 2880 http_tls_t *conn; /* Encryption session */
ef416fc2 2881 gnutls_certificate_client_credentials *credentials;
89d46774 2882 /* TLS credentials */
ef416fc2 2883
2884
2885 conn = (http_tls_t *)(http->tls);
2886 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
2887
2888 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
2889 gnutls_deinit(conn->session);
2890 gnutls_certificate_free_credentials(*credentials);
2891 free(credentials);
2892 free(conn);
2893
2894# elif defined(HAVE_CDSASSL)
89d46774 2895 http_tls_t *conn; /* CDSA connection information */
2896
2897
2898 conn = (http_tls_t *)(http->tls);
2899
2900 while (SSLClose(conn->session) == errSSLWouldBlock)
b423cd4c 2901 usleep(1000);
2902
89d46774 2903 SSLDisposeContext(conn->session);
2904
2905 if (conn->certsArray)
2906 CFRelease(conn->certsArray);
2907
2908 free(conn);
ef416fc2 2909# endif /* HAVE_LIBSSL */
2910
2911 http->tls = NULL;
2912}
2913#endif /* HAVE_SSL */
2914
2915
2916#ifdef HAVE_SSL
2917/*
2918 * 'http_upgrade()' - Force upgrade to TLS encryption.
2919 */
2920
89d46774 2921static int /* O - Status of connection */
568fa3fa 2922http_upgrade(http_t *http) /* I - Connection to server */
ef416fc2 2923{
89d46774 2924 int ret; /* Return value */
2925 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 2926
2927
2928 DEBUG_printf(("http_upgrade(%p)\n", http));
2929
2930 /*
2931 * Copy the HTTP data to a local variable so we can do the OPTIONS
2932 * request without interfering with the existing request data...
2933 */
2934
2935 memcpy(&myhttp, http, sizeof(myhttp));
2936
2937 /*
2938 * Send an OPTIONS request to the server, requiring SSL or TLS
2939 * encryption on the link...
2940 */
2941
f7deaa1a 2942 http->field_authorization = NULL; /* Don't free the auth string */
2943
b86bc4cf 2944 httpClearFields(http);
2945 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
2946 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
ef416fc2 2947
b86bc4cf 2948 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 2949 {
2950 /*
2951 * Wait for the secure connection...
2952 */
2953
b86bc4cf 2954 while (httpUpdate(http) == HTTP_CONTINUE);
ef416fc2 2955 }
2956
b86bc4cf 2957 httpFlush(http);
ef416fc2 2958
2959 /*
b86bc4cf 2960 * Restore the HTTP request data...
ef416fc2 2961 */
2962
b86bc4cf 2963 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 2964 http->data_encoding = myhttp.data_encoding;
2965 http->data_remaining = myhttp.data_remaining;
2966 http->_data_remaining = myhttp._data_remaining;
2967 http->expect = myhttp.expect;
2968 http->field_authorization = myhttp.field_authorization;
bc44d920 2969 http->digest_tries = myhttp.digest_tries;
ef416fc2 2970
2971 /*
2972 * See if we actually went secure...
2973 */
2974
2975 if (!http->tls)
2976 {
2977 /*
2978 * Server does not support HTTP upgrade...
2979 */
2980
2981 DEBUG_puts("Server does not support HTTP upgrade!");
2982
2983# ifdef WIN32
2984 closesocket(http->fd);
2985# else
2986 close(http->fd);
2987# endif
2988
2989 http->fd = -1;
2990
2991 return (-1);
2992 }
2993 else
2994 return (ret);
2995}
2996#endif /* HAVE_SSL */
2997
2998
2999/*
3000 * 'http_wait()' - Wait for data available on a connection.
3001 */
3002
3003static int /* O - 1 if data is available, 0 otherwise */
568fa3fa 3004http_wait(http_t *http, /* I - Connection to server */
411affcf 3005 int msec, /* I - Milliseconds to wait */
3006 int usessl) /* I - Use SSL context? */
ef416fc2 3007{
f7deaa1a 3008#ifdef HAVE_POLL
3009 struct pollfd pfd; /* Polled file descriptor */
3010#else
3011 fd_set input_set; /* select() input set */
ef416fc2 3012 struct timeval timeout; /* Timeout */
f7deaa1a 3013#endif /* HAVE_POLL */
3014 int nfds; /* Result from select()/poll() */
ef416fc2 3015
3016
3017 DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
3018
fa73b229 3019 if (http->fd < 0)
3020 return (0);
3021
ef416fc2 3022 /*
3023 * Check the SSL/TLS buffers for data first...
3024 */
3025
3026#ifdef HAVE_SSL
411affcf 3027 if (http->tls && usessl)
ef416fc2 3028 {
3029# ifdef HAVE_LIBSSL
3030 if (SSL_pending((SSL *)(http->tls)))
3031 return (1);
3032# elif defined(HAVE_GNUTLS)
3033 if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
3034 return (1);
3035# elif defined(HAVE_CDSASSL)
3036 size_t bytes; /* Bytes that are available */
3037
89d46774 3038 if (!SSLGetBufferedReadSize(((http_tls_t *)http->tls)->session, &bytes) && bytes > 0)
ef416fc2 3039 return (1);
3040# endif /* HAVE_LIBSSL */
3041 }
3042#endif /* HAVE_SSL */
3043
3044 /*
f7deaa1a 3045 * Then try doing a select() or poll() to poll the socket...
ef416fc2 3046 */
3047
f7deaa1a 3048#ifdef HAVE_POLL
3049 pfd.fd = http->fd;
3050 pfd.events = POLLIN;
ef416fc2 3051
f7deaa1a 3052 while ((nfds = poll(&pfd, 1, msec)) < 0 && errno == EINTR);
ef416fc2 3053
f7deaa1a 3054#else
ef416fc2 3055 do
3056 {
f7deaa1a 3057 FD_ZERO(&input_set);
3058 FD_SET(http->fd, &input_set);
ef416fc2 3059
89d46774 3060 DEBUG_printf(("http_wait: msec=%d, http->fd=%d\n", msec, http->fd));
3061
ef416fc2 3062 if (msec >= 0)
3063 {
3064 timeout.tv_sec = msec / 1000;
3065 timeout.tv_usec = (msec % 1000) * 1000;
3066
f7deaa1a 3067 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
ef416fc2 3068 }
3069 else
f7deaa1a 3070 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
89d46774 3071
3072 DEBUG_printf(("http_wait: select() returned %d...\n", nfds));
ef416fc2 3073 }
f7deaa1a 3074# ifdef WIN32
ef416fc2 3075 while (nfds < 0 && WSAGetLastError() == WSAEINTR);
f7deaa1a 3076# else
ef416fc2 3077 while (nfds < 0 && errno == EINTR);
f7deaa1a 3078# endif /* WIN32 */
3079#endif /* HAVE_POLL */
ef416fc2 3080
89d46774 3081 DEBUG_printf(("http_wait: returning with nfds=%d...\n", nfds));
3082
ef416fc2 3083 return (nfds > 0);
3084}
3085
3086
3087/*
3088 * 'http_write()' - Write a buffer to a HTTP connection.
3089 */
3090
3091static int /* O - Number of bytes written */
568fa3fa 3092http_write(http_t *http, /* I - Connection to server */
ef416fc2 3093 const char *buffer, /* I - Buffer for data */
3094 int length) /* I - Number of bytes to write */
3095{
3096 int tbytes, /* Total bytes sent */
3097 bytes; /* Bytes sent */
3098
3099
3100 tbytes = 0;
3101
3102 while (length > 0)
3103 {
3104#ifdef HAVE_SSL
3105 if (http->tls)
3106 bytes = http_write_ssl(http, buffer, length);
3107 else
3108#endif /* HAVE_SSL */
3109 bytes = send(http->fd, buffer, length, 0);
3110
3111 if (bytes < 0)
3112 {
3113#ifdef WIN32
3114 if (WSAGetLastError() != http->error)
3115 {
3116 http->error = WSAGetLastError();
3117 continue;
3118 }
3119#else
3120 if (errno == EINTR)
3121 continue;
3122 else if (errno != http->error && errno != ECONNRESET)
3123 {
3124 http->error = errno;
3125 continue;
3126 }
3127#endif /* WIN32 */
3128
3129 DEBUG_puts("http_write: error writing data...\n");
3130
3131 return (-1);
3132 }
3133
3134 buffer += bytes;
3135 tbytes += bytes;
3136 length -= bytes;
3137 }
3138
3139#ifdef DEBUG
ae71f5de 3140 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 3141#endif /* DEBUG */
3142
3143 return (tbytes);
3144}
3145
3146
3147/*
3148 * 'http_write_chunk()' - Write a chunked buffer.
3149 */
3150
3151static int /* O - Number bytes written */
568fa3fa 3152http_write_chunk(http_t *http, /* I - Connection to server */
ef416fc2 3153 const char *buffer, /* I - Buffer to write */
3154 int length) /* I - Length of buffer */
3155{
3156 char header[255]; /* Chunk header */
3157 int bytes; /* Bytes written */
3158
3159 DEBUG_printf(("http_write_chunk(http=%p, buffer=%p, length=%d)\n",
3160 http, buffer, length));
3161
3162 /*
3163 * Write the chunk header, data, and trailer.
3164 */
3165
3166 sprintf(header, "%x\r\n", length);
b86bc4cf 3167 if (http_write(http, header, (int)strlen(header)) < 0)
ef416fc2 3168 {
3169 DEBUG_puts(" http_write of length failed!");
3170 return (-1);
3171 }
3172
3173 if ((bytes = http_write(http, buffer, length)) < 0)
3174 {
3175 DEBUG_puts(" http_write of buffer failed!");
3176 return (-1);
3177 }
3178
3179 if (http_write(http, "\r\n", 2) < 0)
3180 {
3181 DEBUG_puts(" http_write of CR LF failed!");
3182 return (-1);
3183 }
3184
3185 return (bytes);
3186}
3187
3188
3189#ifdef HAVE_SSL
3190/*
3191 * 'http_write_ssl()' - Write to a SSL/TLS connection.
3192 */
3193
3194static int /* O - Bytes written */
568fa3fa 3195http_write_ssl(http_t *http, /* I - Connection to server */
ef416fc2 3196 const char *buf, /* I - Buffer holding data */
3197 int len) /* I - Length of buffer */
3198{
3199# if defined(HAVE_LIBSSL)
3200 return (SSL_write((SSL *)(http->tls), buf, len));
3201
3202# elif defined(HAVE_GNUTLS)
3203 return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
3204# elif defined(HAVE_CDSASSL)
fa73b229 3205 int result; /* Return value */
ef416fc2 3206 OSStatus error; /* Error info */
3207 size_t processed; /* Number of bytes processed */
3208
3209
89d46774 3210 error = SSLWrite(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 3211
fa73b229 3212 switch (error)
ef416fc2 3213 {
fa73b229 3214 case 0 :
3215 result = (int)processed;
3216 break;
3217 case errSSLClosedGraceful :
3218 result = 0;
3219 break;
3220 case errSSLWouldBlock :
b423cd4c 3221 if (processed)
3222 result = (int)processed;
3223 else
3224 {
3225 result = -1;
3226 errno = EINTR;
3227 }
fa73b229 3228 break;
3229 default :
3230 errno = EPIPE;
3231 result = -1;
3232 break;
ef416fc2 3233 }
fa73b229 3234
3235 return (result);
ef416fc2 3236# endif /* HAVE_LIBSSL */
3237}
3238#endif /* HAVE_SSL */
3239
3240
3241/*
75bd9771 3242 * End of "$Id: http.c 7661 2008-06-16 21:46:51Z mike $".
ef416fc2 3243 */