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