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