]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Merge changes from CUPS 1.4svn-r7715.
[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 */
2442
2443
4509bb49 2444 if (_cups_debug_fd < 0)
dd1abb6b
MS
2445 return;
2446
ae71f5de
MS
2447 DEBUG_printf(("%s: %d bytes:\n", prefix, bytes));
2448
2449 snprintf(line, sizeof(line), "%s: ", prefix);
2450 start = line + strlen(line);
2451
2452 for (i = 0; i < bytes; i += 16)
2453 {
2454 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
2455 sprintf(ptr, "%02X", buffer[i + j] & 255);
2456
2457 while (j < 16)
2458 {
2459 strcpy(ptr, " ");
2460 ptr += 2;
2461 j ++;
2462 }
2463
2464 strcpy(ptr, " ");
2465 ptr += 2;
2466
2467 for (j = 0; j < 16 && (i + j) < bytes; j ++)
2468 {
2469 ch = buffer[i + j] & 255;
2470
2471 if (ch < ' ' || ch >= 127)
2472 ch = '.';
2473
2474 *ptr++ = ch;
2475 }
2476
2477 *ptr = '\0';
2478 DEBUG_puts(line);
2479 }
2480}
2481#endif /* DEBUG */
2482
2483
ef416fc2 2484/*
2485 * 'http_field()' - Return the field index for a field name.
2486 */
2487
ae71f5de
MS
2488static http_field_t /* O - Field index */
2489http_field(const char *name) /* I - String name */
ef416fc2 2490{
ae71f5de 2491 int i; /* Looping var */
ef416fc2 2492
2493
2494 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2495 if (strcasecmp(name, http_fields[i]) == 0)
2496 return ((http_field_t)i);
2497
2498 return (HTTP_FIELD_UNKNOWN);
2499}
2500
2501
2502#ifdef HAVE_SSL
2503/*
2504 * 'http_read_ssl()' - Read from a SSL/TLS connection.
2505 */
2506
2507static int /* O - Bytes read */
568fa3fa 2508http_read_ssl(http_t *http, /* I - Connection to server */
ef416fc2 2509 char *buf, /* I - Buffer to store data */
2510 int len) /* I - Length of buffer */
2511{
2512# if defined(HAVE_LIBSSL)
2513 return (SSL_read((SSL *)(http->tls), buf, len));
2514
2515# elif defined(HAVE_GNUTLS)
2516 return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
2517
2518# elif defined(HAVE_CDSASSL)
fa73b229 2519 int result; /* Return value */
ef416fc2 2520 OSStatus error; /* Error info */
2521 size_t processed; /* Number of bytes processed */
2522
2523
89d46774 2524 error = SSLRead(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 2525
fa73b229 2526 switch (error)
ef416fc2 2527 {
fa73b229 2528 case 0 :
2529 result = (int)processed;
2530 break;
2531 case errSSLClosedGraceful :
2532 result = 0;
2533 break;
2534 case errSSLWouldBlock :
b423cd4c 2535 if (processed)
2536 result = (int)processed;
2537 else
2538 {
2539 result = -1;
2540 errno = EINTR;
2541 }
fa73b229 2542 break;
2543 default :
2544 errno = EPIPE;
2545 result = -1;
2546 break;
ef416fc2 2547 }
fa73b229 2548
2549 return (result);
ef416fc2 2550# endif /* HAVE_LIBSSL */
2551}
2552#endif /* HAVE_SSL */
2553
2554
2555/*
2556 * 'http_send()' - Send a request with all fields and the trailing blank line.
2557 */
2558
2559static int /* O - 0 on success, non-zero on error */
568fa3fa 2560http_send(http_t *http, /* I - Connection to server */
ef416fc2 2561 http_state_t request, /* I - Request code */
2562 const char *uri) /* I - URI */
2563{
2564 int i; /* Looping var */
839a51c8 2565 char buf[1024]; /* Encoded URI buffer */
ef416fc2 2566 static const char * const codes[] =
2567 { /* Request code strings */
2568 NULL,
2569 "OPTIONS",
2570 "GET",
2571 NULL,
2572 "HEAD",
2573 "POST",
2574 NULL,
2575 NULL,
2576 "PUT",
2577 NULL,
2578 "DELETE",
2579 "TRACE",
2580 "CLOSE"
2581 };
ef416fc2 2582
2583
2584 DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n",
2585 http, codes[request], uri));
2586
2587 if (http == NULL || uri == NULL)
2588 return (-1);
2589
2590 /*
2591 * Set the User-Agent field if it isn't already...
2592 */
2593
2594 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
2595 httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
2596
2597 /*
2598 * Encode the URI as needed...
2599 */
2600
839a51c8 2601 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 2602
2603 /*
2604 * See if we had an error the last time around; if so, reconnect...
2605 */
2606
2607 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
fa73b229 2608 if (httpReconnect(http))
2609 return (-1);
ef416fc2 2610
d09495fa 2611 /*
2612 * Flush any written data that is pending...
2613 */
2614
2615 if (http->wused)
2616 httpFlushWrite(http);
2617
ef416fc2 2618 /*
2619 * Send the request header...
2620 */
2621
d09495fa 2622 http->state = request;
2623 http->data_encoding = HTTP_ENCODE_FIELDS;
2624
ef416fc2 2625 if (request == HTTP_POST || request == HTTP_PUT)
2626 http->state ++;
2627
2628 http->status = HTTP_CONTINUE;
2629
2630#ifdef HAVE_SSL
2631 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
2632 {
2633 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
2634 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
2635 }
2636#endif /* HAVE_SSL */
2637
2638 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
2639 {
2640 http->status = HTTP_ERROR;
2641 return (-1);
2642 }
2643
2644 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2645 if (http->fields[i][0] != '\0')
2646 {
ae71f5de
MS
2647 DEBUG_printf(("http_send: %s: %s\n", http_fields[i],
2648 httpGetField(http, i)));
ef416fc2 2649
f7deaa1a 2650 if (httpPrintf(http, "%s: %s\r\n", http_fields[i],
2651 httpGetField(http, i)) < 1)
ef416fc2 2652 {
2653 http->status = HTTP_ERROR;
2654 return (-1);
2655 }
2656 }
2657
2658 if (http->cookie)
2659 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
2660 {
2661 http->status = HTTP_ERROR;
2662 return (-1);
2663 }
2664
b423cd4c 2665 if (http->expect == HTTP_CONTINUE &&
2666 (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
2667 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
2668 {
2669 http->status = HTTP_ERROR;
2670 return (-1);
2671 }
2672
ef416fc2 2673 if (httpPrintf(http, "\r\n") < 1)
2674 {
2675 http->status = HTTP_ERROR;
2676 return (-1);
2677 }
2678
d09495fa 2679 httpFlushWrite(http);
ef416fc2 2680 httpGetLength2(http);
2681 httpClearFields(http);
2682
f7deaa1a 2683 /*
b94498cf 2684 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 2685 */
2686
bc44d920 2687 if (http->field_authorization && http->authstring &&
b94498cf 2688 (!strncmp(http->authstring, "Negotiate", 9) ||
2689 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 2690 {
2691 http->_authstring[0] = '\0';
2692
2693 if (http->authstring != http->_authstring)
2694 free(http->authstring);
2695
2696 http->authstring = http->_authstring;
2697 }
2698
ef416fc2 2699 return (0);
2700}
2701
2702
2703#ifdef HAVE_SSL
2704/*
2705 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
2706 */
2707
2708static int /* O - Status of connection */
568fa3fa 2709http_setup_ssl(http_t *http) /* I - Connection to server */
ef416fc2 2710{
2711# ifdef HAVE_LIBSSL
89d46774 2712 SSL_CTX *context; /* Context for encryption */
2713 SSL *conn; /* Connection for encryption */
411affcf 2714 BIO *bio; /* BIO data */
ef416fc2 2715# elif defined(HAVE_GNUTLS)
89d46774 2716 http_tls_t *conn; /* TLS session object */
ef416fc2 2717 gnutls_certificate_client_credentials *credentials;
89d46774 2718 /* TLS credentials */
ef416fc2 2719# elif defined(HAVE_CDSASSL)
89d46774 2720 OSStatus error; /* Error code */
2721 http_tls_t *conn; /* CDSA connection information */
ef416fc2 2722# endif /* HAVE_LIBSSL */
2723
2724
2725 DEBUG_printf(("http_setup_ssl(http=%p)\n", http));
2726
2727# ifdef HAVE_LIBSSL
2728 context = SSL_CTX_new(SSLv23_client_method());
2729
2730 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
2731
411affcf 2732 bio = BIO_new(_httpBIOMethods());
2733 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
2734
ef416fc2 2735 conn = SSL_new(context);
411affcf 2736 SSL_set_bio(conn, bio, bio);
ef416fc2 2737
ef416fc2 2738 if (SSL_connect(conn) != 1)
2739 {
2740# ifdef DEBUG
2741 unsigned long error; /* Error code */
2742
2743 while ((error = ERR_get_error()) != 0)
2744 printf("http_setup_ssl: %s\n", ERR_error_string(error, NULL));
2745# endif /* DEBUG */
2746
2747 SSL_CTX_free(context);
2748 SSL_free(conn);
2749
2750# ifdef WIN32
2751 http->error = WSAGetLastError();
2752# else
2753 http->error = errno;
2754# endif /* WIN32 */
2755 http->status = HTTP_ERROR;
2756
2757 return (HTTP_ERROR);
2758 }
2759
2760# elif defined(HAVE_GNUTLS)
89d46774 2761 if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
ef416fc2 2762 {
2763 http->error = errno;
2764 http->status = HTTP_ERROR;
2765
2766 return (-1);
2767 }
2768
2769 credentials = (gnutls_certificate_client_credentials *)
2770 malloc(sizeof(gnutls_certificate_client_credentials));
2771 if (credentials == NULL)
2772 {
2773 free(conn);
2774
2775 http->error = errno;
2776 http->status = HTTP_ERROR;
2777
2778 return (-1);
2779 }
2780
2781 gnutls_certificate_allocate_credentials(credentials);
2782
2783 gnutls_init(&(conn->session), GNUTLS_CLIENT);
2784 gnutls_set_default_priority(conn->session);
2785 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
411affcf 2786 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)http);
2787 gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
2788 gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
ef416fc2 2789
2790 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
2791 {
2792 http->error = errno;
2793 http->status = HTTP_ERROR;
2794
2795 return (-1);
2796 }
2797
2798 conn->credentials = credentials;
2799
2800# elif defined(HAVE_CDSASSL)
89d46774 2801 conn = (http_tls_t *)calloc(1, sizeof(http_tls_t));
e53920b9 2802
89d46774 2803 if (conn == NULL)
2804 return (-1);
e53920b9 2805
89d46774 2806 if ((error = SSLNewContext(false, &conn->session)))
e53920b9 2807 {
89d46774 2808 http->error = error;
2809 http->status = HTTP_ERROR;
e53920b9 2810
89d46774 2811 free(conn);
2812 return (-1);
e53920b9 2813 }
ef416fc2 2814
89d46774 2815 /*
2816 * Use a union to resolve warnings about int/pointer size mismatches...
2817 */
2818
411affcf 2819 error = SSLSetConnection(conn->session, http);
89d46774 2820
2821 if (!error)
2822 error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
2823
ef416fc2 2824 if (!error)
89d46774 2825 error = SSLSetAllowsExpiredCerts(conn->session, true);
ef416fc2 2826
2827 if (!error)
89d46774 2828 error = SSLSetAllowsAnyRoot(conn->session, true);
ef416fc2 2829
ed486911 2830 if (!error)
2831 error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
2832
ef416fc2 2833 if (!error)
b423cd4c 2834 {
89d46774 2835 while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
b423cd4c 2836 usleep(1000);
2837 }
ef416fc2 2838
89d46774 2839 if (error)
ef416fc2 2840 {
2841 http->error = error;
2842 http->status = HTTP_ERROR;
2843
89d46774 2844 SSLDisposeContext(conn->session);
ef416fc2 2845
89d46774 2846 free(conn);
ef416fc2 2847
2848 return (-1);
2849 }
2850# endif /* HAVE_CDSASSL */
2851
2852 http->tls = conn;
2853 return (0);
2854}
2855#endif /* HAVE_SSL */
2856
2857
2858#ifdef HAVE_SSL
2859/*
2860 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
2861 */
2862
2863static void
568fa3fa 2864http_shutdown_ssl(http_t *http) /* I - Connection to server */
ef416fc2 2865{
2866# ifdef HAVE_LIBSSL
89d46774 2867 SSL_CTX *context; /* Context for encryption */
2868 SSL *conn; /* Connection for encryption */
ef416fc2 2869
2870
2871 conn = (SSL *)(http->tls);
2872 context = SSL_get_SSL_CTX(conn);
2873
2874 SSL_shutdown(conn);
2875 SSL_CTX_free(context);
2876 SSL_free(conn);
2877
2878# elif defined(HAVE_GNUTLS)
89d46774 2879 http_tls_t *conn; /* Encryption session */
ef416fc2 2880 gnutls_certificate_client_credentials *credentials;
89d46774 2881 /* TLS credentials */
ef416fc2 2882
2883
2884 conn = (http_tls_t *)(http->tls);
2885 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
2886
2887 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
2888 gnutls_deinit(conn->session);
2889 gnutls_certificate_free_credentials(*credentials);
2890 free(credentials);
2891 free(conn);
2892
2893# elif defined(HAVE_CDSASSL)
89d46774 2894 http_tls_t *conn; /* CDSA connection information */
2895
2896
2897 conn = (http_tls_t *)(http->tls);
2898
2899 while (SSLClose(conn->session) == errSSLWouldBlock)
b423cd4c 2900 usleep(1000);
2901
89d46774 2902 SSLDisposeContext(conn->session);
2903
2904 if (conn->certsArray)
2905 CFRelease(conn->certsArray);
2906
2907 free(conn);
ef416fc2 2908# endif /* HAVE_LIBSSL */
2909
2910 http->tls = NULL;
2911}
2912#endif /* HAVE_SSL */
2913
2914
2915#ifdef HAVE_SSL
2916/*
2917 * 'http_upgrade()' - Force upgrade to TLS encryption.
2918 */
2919
89d46774 2920static int /* O - Status of connection */
568fa3fa 2921http_upgrade(http_t *http) /* I - Connection to server */
ef416fc2 2922{
89d46774 2923 int ret; /* Return value */
2924 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 2925
2926
2927 DEBUG_printf(("http_upgrade(%p)\n", http));
2928
2929 /*
2930 * Copy the HTTP data to a local variable so we can do the OPTIONS
2931 * request without interfering with the existing request data...
2932 */
2933
2934 memcpy(&myhttp, http, sizeof(myhttp));
2935
2936 /*
2937 * Send an OPTIONS request to the server, requiring SSL or TLS
2938 * encryption on the link...
2939 */
2940
f7deaa1a 2941 http->field_authorization = NULL; /* Don't free the auth string */
2942
b86bc4cf 2943 httpClearFields(http);
2944 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
2945 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
ef416fc2 2946
b86bc4cf 2947 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 2948 {
2949 /*
2950 * Wait for the secure connection...
2951 */
2952
b86bc4cf 2953 while (httpUpdate(http) == HTTP_CONTINUE);
ef416fc2 2954 }
2955
b86bc4cf 2956 httpFlush(http);
ef416fc2 2957
2958 /*
b86bc4cf 2959 * Restore the HTTP request data...
ef416fc2 2960 */
2961
b86bc4cf 2962 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 2963 http->data_encoding = myhttp.data_encoding;
2964 http->data_remaining = myhttp.data_remaining;
2965 http->_data_remaining = myhttp._data_remaining;
2966 http->expect = myhttp.expect;
2967 http->field_authorization = myhttp.field_authorization;
bc44d920 2968 http->digest_tries = myhttp.digest_tries;
ef416fc2 2969
2970 /*
2971 * See if we actually went secure...
2972 */
2973
2974 if (!http->tls)
2975 {
2976 /*
2977 * Server does not support HTTP upgrade...
2978 */
2979
2980 DEBUG_puts("Server does not support HTTP upgrade!");
2981
2982# ifdef WIN32
2983 closesocket(http->fd);
2984# else
2985 close(http->fd);
2986# endif
2987
2988 http->fd = -1;
2989
2990 return (-1);
2991 }
2992 else
2993 return (ret);
2994}
2995#endif /* HAVE_SSL */
2996
2997
2998/*
2999 * 'http_wait()' - Wait for data available on a connection.
3000 */
3001
3002static int /* O - 1 if data is available, 0 otherwise */
568fa3fa 3003http_wait(http_t *http, /* I - Connection to server */
411affcf 3004 int msec, /* I - Milliseconds to wait */
3005 int usessl) /* I - Use SSL context? */
ef416fc2 3006{
f7deaa1a 3007#ifdef HAVE_POLL
3008 struct pollfd pfd; /* Polled file descriptor */
3009#else
3010 fd_set input_set; /* select() input set */
ef416fc2 3011 struct timeval timeout; /* Timeout */
f7deaa1a 3012#endif /* HAVE_POLL */
3013 int nfds; /* Result from select()/poll() */
ef416fc2 3014
3015
3016 DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
3017
fa73b229 3018 if (http->fd < 0)
3019 return (0);
3020
ef416fc2 3021 /*
3022 * Check the SSL/TLS buffers for data first...
3023 */
3024
3025#ifdef HAVE_SSL
411affcf 3026 if (http->tls && usessl)
ef416fc2 3027 {
3028# ifdef HAVE_LIBSSL
3029 if (SSL_pending((SSL *)(http->tls)))
3030 return (1);
3031# elif defined(HAVE_GNUTLS)
3032 if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
3033 return (1);
3034# elif defined(HAVE_CDSASSL)
3035 size_t bytes; /* Bytes that are available */
3036
89d46774 3037 if (!SSLGetBufferedReadSize(((http_tls_t *)http->tls)->session, &bytes) && bytes > 0)
ef416fc2 3038 return (1);
3039# endif /* HAVE_LIBSSL */
3040 }
3041#endif /* HAVE_SSL */
3042
3043 /*
f7deaa1a 3044 * Then try doing a select() or poll() to poll the socket...
ef416fc2 3045 */
3046
f7deaa1a 3047#ifdef HAVE_POLL
3048 pfd.fd = http->fd;
3049 pfd.events = POLLIN;
ef416fc2 3050
f7deaa1a 3051 while ((nfds = poll(&pfd, 1, msec)) < 0 && errno == EINTR);
ef416fc2 3052
f7deaa1a 3053#else
ef416fc2 3054 do
3055 {
f7deaa1a 3056 FD_ZERO(&input_set);
3057 FD_SET(http->fd, &input_set);
ef416fc2 3058
89d46774 3059 DEBUG_printf(("http_wait: msec=%d, http->fd=%d\n", msec, http->fd));
3060
ef416fc2 3061 if (msec >= 0)
3062 {
3063 timeout.tv_sec = msec / 1000;
3064 timeout.tv_usec = (msec % 1000) * 1000;
3065
f7deaa1a 3066 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
ef416fc2 3067 }
3068 else
f7deaa1a 3069 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
89d46774 3070
3071 DEBUG_printf(("http_wait: select() returned %d...\n", nfds));
ef416fc2 3072 }
f7deaa1a 3073# ifdef WIN32
ef416fc2 3074 while (nfds < 0 && WSAGetLastError() == WSAEINTR);
f7deaa1a 3075# else
ef416fc2 3076 while (nfds < 0 && errno == EINTR);
f7deaa1a 3077# endif /* WIN32 */
3078#endif /* HAVE_POLL */
ef416fc2 3079
89d46774 3080 DEBUG_printf(("http_wait: returning with nfds=%d...\n", nfds));
3081
ef416fc2 3082 return (nfds > 0);
3083}
3084
3085
3086/*
3087 * 'http_write()' - Write a buffer to a HTTP connection.
3088 */
3089
3090static int /* O - Number of bytes written */
568fa3fa 3091http_write(http_t *http, /* I - Connection to server */
ef416fc2 3092 const char *buffer, /* I - Buffer for data */
3093 int length) /* I - Number of bytes to write */
3094{
3095 int tbytes, /* Total bytes sent */
3096 bytes; /* Bytes sent */
3097
3098
3099 tbytes = 0;
3100
3101 while (length > 0)
3102 {
3103#ifdef HAVE_SSL
3104 if (http->tls)
3105 bytes = http_write_ssl(http, buffer, length);
3106 else
3107#endif /* HAVE_SSL */
3108 bytes = send(http->fd, buffer, length, 0);
3109
3110 if (bytes < 0)
3111 {
3112#ifdef WIN32
3113 if (WSAGetLastError() != http->error)
3114 {
3115 http->error = WSAGetLastError();
3116 continue;
3117 }
3118#else
3119 if (errno == EINTR)
3120 continue;
3121 else if (errno != http->error && errno != ECONNRESET)
3122 {
3123 http->error = errno;
3124 continue;
3125 }
3126#endif /* WIN32 */
3127
3128 DEBUG_puts("http_write: error writing data...\n");
3129
3130 return (-1);
3131 }
3132
3133 buffer += bytes;
3134 tbytes += bytes;
3135 length -= bytes;
3136 }
3137
3138#ifdef DEBUG
ae71f5de 3139 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 3140#endif /* DEBUG */
3141
3142 return (tbytes);
3143}
3144
3145
3146/*
3147 * 'http_write_chunk()' - Write a chunked buffer.
3148 */
3149
3150static int /* O - Number bytes written */
568fa3fa 3151http_write_chunk(http_t *http, /* I - Connection to server */
ef416fc2 3152 const char *buffer, /* I - Buffer to write */
3153 int length) /* I - Length of buffer */
3154{
3155 char header[255]; /* Chunk header */
3156 int bytes; /* Bytes written */
3157
3158 DEBUG_printf(("http_write_chunk(http=%p, buffer=%p, length=%d)\n",
3159 http, buffer, length));
3160
3161 /*
3162 * Write the chunk header, data, and trailer.
3163 */
3164
3165 sprintf(header, "%x\r\n", length);
b86bc4cf 3166 if (http_write(http, header, (int)strlen(header)) < 0)
ef416fc2 3167 {
3168 DEBUG_puts(" http_write of length failed!");
3169 return (-1);
3170 }
3171
3172 if ((bytes = http_write(http, buffer, length)) < 0)
3173 {
3174 DEBUG_puts(" http_write of buffer failed!");
3175 return (-1);
3176 }
3177
3178 if (http_write(http, "\r\n", 2) < 0)
3179 {
3180 DEBUG_puts(" http_write of CR LF failed!");
3181 return (-1);
3182 }
3183
3184 return (bytes);
3185}
3186
3187
3188#ifdef HAVE_SSL
3189/*
3190 * 'http_write_ssl()' - Write to a SSL/TLS connection.
3191 */
3192
3193static int /* O - Bytes written */
568fa3fa 3194http_write_ssl(http_t *http, /* I - Connection to server */
ef416fc2 3195 const char *buf, /* I - Buffer holding data */
3196 int len) /* I - Length of buffer */
3197{
3198# if defined(HAVE_LIBSSL)
3199 return (SSL_write((SSL *)(http->tls), buf, len));
3200
3201# elif defined(HAVE_GNUTLS)
3202 return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
3203# elif defined(HAVE_CDSASSL)
fa73b229 3204 int result; /* Return value */
ef416fc2 3205 OSStatus error; /* Error info */
3206 size_t processed; /* Number of bytes processed */
3207
3208
89d46774 3209 error = SSLWrite(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 3210
fa73b229 3211 switch (error)
ef416fc2 3212 {
fa73b229 3213 case 0 :
3214 result = (int)processed;
3215 break;
3216 case errSSLClosedGraceful :
3217 result = 0;
3218 break;
3219 case errSSLWouldBlock :
b423cd4c 3220 if (processed)
3221 result = (int)processed;
3222 else
3223 {
3224 result = -1;
3225 errno = EINTR;
3226 }
fa73b229 3227 break;
3228 default :
3229 errno = EPIPE;
3230 result = -1;
3231 break;
ef416fc2 3232 }
fa73b229 3233
3234 return (result);
ef416fc2 3235# endif /* HAVE_LIBSSL */
3236}
3237#endif /* HAVE_SSL */
3238
3239
3240/*
75bd9771 3241 * End of "$Id: http.c 7661 2008-06-16 21:46:51Z mike $".
ef416fc2 3242 */