]> 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/*
bd7854cb 2 * "$Id: http.c 5103 2006-02-14 19:27:42Z mike $"
ef416fc2 3 *
4 * HTTP routines for the Common UNIX Printing System (CUPS).
5 *
fa73b229 6 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
ef416fc2 7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * httpCheck() - Check to see if there is a pending response from
29 * the server.
30 * httpClearCookie() - Clear the cookie value(s).
31 * httpClose() - Close an HTTP connection...
32 * httpConnect() - Connect to a HTTP server.
33 * httpConnectEncrypt() - Connect to a HTTP server using encryption.
34 * httpDelete() - Send a DELETE request to the server.
35 * httpEncryption() - Set the required encryption on the link.
36 * httpFlush() - Flush data from a HTTP connection.
37 * httpFlushWrite() - Flush data in write buffer.
38 * httpGet() - Send a GET request to the server.
39 * httpGetLength() - Get the amount of data remaining from the
40 * content-length or transfer-encoding fields.
41 * httpGetLength2() - Get the amount of data remaining from the
42 * content-length or transfer-encoding fields.
43 * httpGetSubField() - Get a sub-field value.
44 * httpGets() - Get a line of text from a HTTP connection.
45 * httpHead() - Send a HEAD request to the server.
46 * httpInitialize() - Initialize the HTTP interface library and set the
47 * default HTTP proxy (if any).
48 * httpOptions() - Send an OPTIONS request to the server.
49 * httpPost() - Send a POST request to the server.
50 * httpPrintf() - Print a formatted string to a HTTP connection.
51 * httpPut() - Send a PUT request to the server.
52 * httpRead() - Read data from a HTTP connection.
a4d04587 53 * httpRead2() - Read data from a HTTP connection.
ef416fc2 54 * _httpReadCDSA() - Read function for CDSA decryption code.
55 * httpReconnect() - Reconnect to a HTTP server...
56 * httpSetCookie() - Set the cookie value(s)...
57 * httpSetField() - Set the value of an HTTP header.
58 * httpSetLength() - Set the content-length and transfer-encoding.
59 * httpTrace() - Send an TRACE request to the server.
60 * httpUpdate() - Update the current HTTP state for incoming data.
61 * httpWait() - Wait for data available on a connection.
62 * httpWrite() - Write data to a HTTP connection.
a4d04587 63 * httpWrite2() - Write data to a HTTP connection.
ef416fc2 64 * _httpWriteCDSA() - Write function for CDSA encryption code.
65 * http_field() - Return the field index for a field name.
66 * http_read_ssl() - Read from a SSL/TLS connection.
67 * http_send() - Send a request with all fields and the trailing
68 * blank line.
69 * http_setup_ssl() - Set up SSL/TLS on a connection.
70 * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
71 * http_upgrade() - Force upgrade to TLS encryption.
72 * http_wait() - Wait for data available on a connection.
73 * http_write() - Write data to a connection.
74 * http_write_ssl() - Write to a SSL/TLS connection.
75 */
76
77/*
78 * Include necessary headers...
79 */
80
81#include "http-private.h"
82#include "globals.h"
83#include "debug.h"
84#include <stdlib.h>
85#include <fcntl.h>
86#include <errno.h>
87#ifndef WIN32
88# include <signal.h>
89# include <sys/time.h>
90# include <sys/resource.h>
91#endif /* !WIN32 */
92
93
94/*
95 * Some operating systems have done away with the Fxxxx constants for
96 * the fcntl() call; this works around that "feature"...
97 */
98
99#ifndef FNONBLK
100# define FNONBLK O_NONBLOCK
101#endif /* !FNONBLK */
102
103
104/*
105 * Local functions...
106 */
107
108static http_field_t http_field(const char *name);
109static int http_send(http_t *http, http_state_t request,
110 const char *uri);
111static int http_wait(http_t *http, int msec);
112static int http_write(http_t *http, const char *buffer,
113 int length);
114static int http_write_chunk(http_t *http, const char *buffer,
115 int length);
116#ifdef HAVE_SSL
117static int http_read_ssl(http_t *http, char *buf, int len);
118static int http_setup_ssl(http_t *http);
119static void http_shutdown_ssl(http_t *http);
120static int http_upgrade(http_t *http);
121static int http_write_ssl(http_t *http, const char *buf, int len);
122#endif /* HAVE_SSL */
123
124
125/*
126 * Local globals...
127 */
128
129static const char * const http_fields[] =
130 {
131 "Accept-Language",
132 "Accept-Ranges",
133 "Authorization",
134 "Connection",
135 "Content-Encoding",
136 "Content-Language",
137 "Content-Length",
138 "Content-Location",
139 "Content-MD5",
140 "Content-Range",
141 "Content-Type",
142 "Content-Version",
143 "Date",
144 "Host",
145 "If-Modified-Since",
146 "If-Unmodified-since",
147 "Keep-Alive",
148 "Last-Modified",
149 "Link",
150 "Location",
151 "Range",
152 "Referer",
153 "Retry-After",
154 "Transfer-Encoding",
155 "Upgrade",
156 "User-Agent",
157 "WWW-Authenticate"
158 };
159
160
161/*
162 * 'httpCheck()' - Check to see if there is a pending response from the server.
163 */
164
165int /* O - 0 = no data, 1 = data available */
166httpCheck(http_t *http) /* I - HTTP connection */
167{
168 return (httpWait(http, 0));
169}
170
171
172/*
173 * 'httpClearCookie()' - Clear the cookie value(s).
174 *
175 * @since CUPS 1.1.19@
176 */
177
178void
179httpClearCookie(http_t *http) /* I - Connection */
180{
181 if (!http)
182 return;
183
184 if (http->cookie)
185 {
186 free(http->cookie);
187 http->cookie = NULL;
188 }
189}
190
191
192/*
193 * 'httpClose()' - Close an HTTP connection...
194 */
195
196void
197httpClose(http_t *http) /* I - Connection to close */
198{
199 DEBUG_printf(("httpClose(http=%p)\n", http));
200
201 if (!http)
202 return;
203
204 httpAddrFreeList(http->addrlist);
205
206 if (http->input_set)
207 free(http->input_set);
208
209 if (http->cookie)
210 free(http->cookie);
211
212#ifdef HAVE_SSL
213 if (http->tls)
214 http_shutdown_ssl(http);
215#endif /* HAVE_SSL */
216
217#ifdef WIN32
218 closesocket(http->fd);
219#else
220 close(http->fd);
221#endif /* WIN32 */
222
223 free(http);
224}
225
226
227/*
228 * 'httpConnect()' - Connect to a HTTP server.
229 */
230
231http_t * /* O - New HTTP connection */
232httpConnect(const char *host, /* I - Host to connect to */
233 int port) /* I - Port number */
234{
235 http_encryption_t encryption; /* Type of encryption to use */
236
237
238 /*
239 * Set the default encryption status...
240 */
241
242 if (port == 443)
243 encryption = HTTP_ENCRYPT_ALWAYS;
244 else
245 encryption = HTTP_ENCRYPT_IF_REQUESTED;
246
247 return (httpConnectEncrypt(host, port, encryption));
248}
249
250
251/*
252 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
253 */
254
255http_t * /* O - New HTTP connection */
256httpConnectEncrypt(
257 const char *host, /* I - Host to connect to */
258 int port, /* I - Port number */
259 http_encryption_t encryption) /* I - Type of encryption to use */
260{
261 http_t *http; /* New HTTP connection */
262 http_addrlist_t *addrlist; /* Host address data */
263 char service[255]; /* Service name */
264
265
266 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)\n",
267 host ? host : "(null)", port, encryption));
268
269 if (!host)
270 return (NULL);
271
272 httpInitialize();
273
274 /*
275 * Lookup the host...
276 */
277
278 sprintf(service, "%d", port);
279
280 if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
281 return (NULL);
282
283 /*
284 * Allocate memory for the structure...
285 */
286
287 http = calloc(sizeof(http_t), 1);
288 if (http == NULL)
289 return (NULL);
290
291 http->version = HTTP_1_1;
292 http->blocking = 1;
293 http->activity = time(NULL);
294 http->fd = -1;
295
296 /*
297 * Set the encryption status...
298 */
299
300 if (port == 443) /* Always use encryption for https */
301 http->encryption = HTTP_ENCRYPT_ALWAYS;
302 else
303 http->encryption = encryption;
304
305 /*
306 * Loop through the addresses we have until one of them connects...
307 */
308
309 strlcpy(http->hostname, host, sizeof(http->hostname));
310
311 /*
312 * Connect to the remote system...
313 */
314
315 http->addrlist = addrlist;
316
317 if (!httpReconnect(http))
318 return (http);
319
320 /*
321 * Could not connect to any known address - bail out!
322 */
323
324 httpAddrFreeList(addrlist);
325
326 free(http);
327
328 return (NULL);
329}
330
331
332/*
333 * 'httpDelete()' - Send a DELETE request to the server.
334 */
335
336int /* O - Status of call (0 = success) */
337httpDelete(http_t *http, /* I - HTTP data */
338 const char *uri) /* I - URI to delete */
339{
340 return (http_send(http, HTTP_DELETE, uri));
341}
342
343
344/*
345 * 'httpEncryption()' - Set the required encryption on the link.
346 */
347
348int /* O - -1 on error, 0 on success */
349httpEncryption(http_t *http, /* I - HTTP data */
350 http_encryption_t e) /* I - New encryption preference */
351{
352 DEBUG_printf(("httpEncryption(http=%p, e=%d)\n", http, e));
353
354#ifdef HAVE_SSL
355 if (!http)
356 return (0);
357
358 http->encryption = e;
359
360 if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
361 (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
362 return (httpReconnect(http));
363 else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
364 return (http_upgrade(http));
365 else
366 return (0);
367#else
368 if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
369 return (-1);
370 else
371 return (0);
372#endif /* HAVE_SSL */
373}
374
375
376/*
377 * 'httpFlush()' - Flush data from a HTTP connection.
378 */
379
380void
381httpFlush(http_t *http) /* I - HTTP data */
382{
383 char buffer[8192]; /* Junk buffer */
fa73b229 384 int blocking; /* To block or not to block */
ef416fc2 385
386
387 DEBUG_printf(("httpFlush(http=%p), state=%d\n", http, http->state));
388
fa73b229 389 /*
390 * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
391 */
392
393 blocking = http->blocking;
394 http->blocking = 0;
395
396 /*
397 * Read any data we can...
398 */
399
a4d04587 400 while (httpRead2(http, buffer, sizeof(buffer)) > 0);
fa73b229 401
402 /*
403 * Restore blocking and reset the connection if we didn't get all of
404 * the remaining data...
405 */
406
407 http->blocking = blocking;
408
409 if (http->state != HTTP_WAITING && http->fd >= 0)
410 {
411 /*
412 * Didn't get the data back, so close the current connection.
413 */
414
415 http->state = HTTP_WAITING;
416
417#ifdef HAVE_SSL
418 if (http->tls)
419 http_shutdown_ssl(http);
420#endif /* HAVE_SSL */
421
422#ifdef WIN32
423 closesocket(http->fd);
424#else
425 close(http->fd);
426#endif /* WIN32 */
427
428 http->fd = -1;
429 }
ef416fc2 430}
431
432
433/*
434 * 'httpFlushWrite()' - Flush data in write buffer.
435 *
436 * @since CUPS 1.2@
437 */
438
439int /* O - Bytes written or -1 on error */
440httpFlushWrite(http_t *http) /* I - HTTP data */
441{
442 int bytes; /* Bytes written */
443
444
445 DEBUG_printf(("httpFlushWrite(http=%p)\n", http));
446
447 if (!http || !http->wused)
448 return (0);
449
450 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
451 bytes = http_write_chunk(http, http->wbuffer, http->wused);
452 else
453 bytes = http_write(http, http->wbuffer, http->wused);
454
455 http->wused = 0;
456
457 return (bytes);
458}
459
460
461/*
462 * 'httpGet()' - Send a GET request to the server.
463 */
464
465int /* O - Status of call (0 = success) */
466httpGet(http_t *http, /* I - HTTP data */
467 const char *uri) /* I - URI to get */
468{
469 return (http_send(http, HTTP_GET, uri));
470}
471
472
473/*
474 * 'httpGetSubField()' - Get a sub-field value.
475 *
476 * @deprecated@
477 */
478
479char * /* O - Value or NULL */
480httpGetSubField(http_t *http, /* I - HTTP data */
481 http_field_t field, /* I - Field index */
482 const char *name, /* I - Name of sub-field */
483 char *value) /* O - Value string */
484{
485 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
486}
487
488
489/*
490 * 'httpGetSubField2()' - Get a sub-field value.
491 *
492 * @since CUPS 1.2@
493 */
494
495char * /* O - Value or NULL */
496httpGetSubField2(http_t *http, /* I - HTTP data */
497 http_field_t field, /* I - Field index */
498 const char *name, /* I - Name of sub-field */
499 char *value, /* O - Value string */
500 int valuelen) /* I - Size of value buffer */
501{
502 const char *fptr; /* Pointer into field */
503 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
504 *ptr, /* Pointer into string buffer */
505 *end; /* End of value buffer */
506
507 DEBUG_printf(("httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, valuelen=%d)\n",
508 http, field, name, value, valuelen));
509
510 if (!http || !name || !value || valuelen < 2 ||
511 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
512 field > HTTP_FIELD_WWW_AUTHENTICATE)
513 return (NULL);
514
515 end = value + valuelen - 1;
516
517 for (fptr = http->fields[field]; *fptr;)
518 {
519 /*
520 * Skip leading whitespace...
521 */
522
523 while (isspace(*fptr & 255))
524 fptr ++;
525
526 if (*fptr == ',')
527 {
528 fptr ++;
529 continue;
530 }
531
532 /*
533 * Get the sub-field name...
534 */
535
536 for (ptr = temp;
537 *fptr && *fptr != '=' && !isspace(*fptr & 255) &&
538 ptr < (temp + sizeof(temp) - 1);
539 *ptr++ = *fptr++);
540
541 *ptr = '\0';
542
543 DEBUG_printf(("httpGetSubField: name=\"%s\"\n", temp));
544
545 /*
546 * Skip trailing chars up to the '='...
547 */
548
549 while (isspace(*fptr & 255))
550 fptr ++;
551
552 if (!*fptr)
553 break;
554
555 if (*fptr != '=')
556 continue;
557
558 /*
559 * Skip = and leading whitespace...
560 */
561
562 fptr ++;
563
564 while (isspace(*fptr & 255))
565 fptr ++;
566
567 if (*fptr == '\"')
568 {
569 /*
570 * Read quoted string...
571 */
572
573 for (ptr = value, fptr ++;
574 *fptr && *fptr != '\"' && ptr < end;
575 *ptr++ = *fptr++);
576
577 *ptr = '\0';
578
579 while (*fptr && *fptr != '\"')
580 fptr ++;
581
582 if (*fptr)
583 fptr ++;
584 }
585 else
586 {
587 /*
588 * Read unquoted string...
589 */
590
591 for (ptr = value;
592 *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < end;
593 *ptr++ = *fptr++);
594
595 *ptr = '\0';
596
597 while (*fptr && !isspace(*fptr & 255) && *fptr != ',')
598 fptr ++;
599 }
600
601 DEBUG_printf(("httpGetSubField: value=\"%s\"\n", value));
602
603 /*
604 * See if this is the one...
605 */
606
607 if (!strcmp(name, temp))
608 return (value);
609 }
610
611 value[0] = '\0';
612
613 return (NULL);
614}
615
616
617/*
618 * 'httpGetLength()' - Get the amount of data remaining from the
619 * content-length or transfer-encoding fields.
620 *
621 * This function is deprecated and will not return lengths larger than
622 * 2^31 - 1; use httpGetLength2() instead.
623 *
624 * @since CUPS 1.2@
625 */
626
627int /* O - Content length */
628httpGetLength(http_t *http) /* I - HTTP data */
629{
630 /*
631 * Get the read content length and return the 32-bit value.
632 */
633
634 httpGetLength2(http);
635
636 return (http->_data_remaining);
637}
638
639
640/*
641 * 'httpGetLength2()' - Get the amount of data remaining from the
642 * content-length or transfer-encoding fields.
643 *
644 * This function returns the complete content length, even for
645 * content larger than 2^31 - 1.
646 */
647
648off_t /* O - Content length */
649httpGetLength2(http_t *http) /* I - HTTP data */
650{
651 DEBUG_printf(("httpGetLength2(http=%p), state=%d\n", http, http->state));
652
653 if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
654 {
655 DEBUG_puts("httpGetLength2: chunked request!");
656
657 http->data_encoding = HTTP_ENCODE_CHUNKED;
658 http->data_remaining = 0;
659 }
660 else
661 {
662 http->data_encoding = HTTP_ENCODE_LENGTH;
663
664 /*
665 * The following is a hack for HTTP servers that don't send a
666 * content-length or transfer-encoding field...
667 *
668 * If there is no content-length then the connection must close
669 * after the transfer is complete...
670 */
671
672 if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
673 http->data_remaining = 2147483647;
674 else
675 http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
676 NULL, 10);
677
678 DEBUG_printf(("httpGetLength2: content_length=" CUPS_LLFMT "\n",
679 CUPS_LLCAST http->data_remaining));
680 }
681
682 if (http->data_remaining <= INT_MAX)
683 http->_data_remaining = (int)http->data_remaining;
684 else
685 http->_data_remaining = INT_MAX;
686
687 return (http->data_remaining);
688}
689
690
691/*
692 * 'httpGets()' - Get a line of text from a HTTP connection.
693 */
694
695char * /* O - Line or NULL */
696httpGets(char *line, /* I - Line to read into */
697 int length, /* I - Max length of buffer */
698 http_t *http) /* I - HTTP data */
699{
700 char *lineptr, /* Pointer into line */
701 *lineend, /* End of line */
702 *bufptr, /* Pointer into input buffer */
703 *bufend; /* Pointer to end of buffer */
704 int bytes, /* Number of bytes read */
705 eol; /* End-of-line? */
706
707
708 DEBUG_printf(("httpGets(line=%p, length=%d, http=%p)\n", line, length, http));
709
710 if (http == NULL || line == NULL)
711 return (NULL);
712
713 /*
714 * Read a line from the buffer...
715 */
716
717 lineptr = line;
718 lineend = line + length - 1;
719 eol = 0;
720
721 while (lineptr < lineend)
722 {
723 /*
724 * Pre-load the buffer as needed...
725 */
726
727#ifdef WIN32
728 WSASetLastError(0);
729#else
730 errno = 0;
731#endif /* WIN32 */
732
733 while (http->used == 0)
734 {
735 /*
736 * No newline; see if there is more data to be read...
737 */
738
739 if (!http->blocking && !http_wait(http, 1000))
740 return (NULL);
741
742#ifdef HAVE_SSL
743 if (http->tls)
744 bytes = http_read_ssl(http, http->buffer + http->used,
745 HTTP_MAX_BUFFER - http->used);
746 else
747#endif /* HAVE_SSL */
748 bytes = recv(http->fd, http->buffer + http->used,
749 HTTP_MAX_BUFFER - http->used, 0);
750
751 DEBUG_printf(("httpGets: read %d bytes...\n", bytes));
752
753 if (bytes < 0)
754 {
755 /*
756 * Nope, can't get a line this time...
757 */
758
759#ifdef WIN32
760 if (WSAGetLastError() != http->error)
761 {
762 http->error = WSAGetLastError();
763 continue;
764 }
765
766 DEBUG_printf(("httpGets: recv() error %d!\n", WSAGetLastError()));
767#else
768 DEBUG_printf(("httpGets: recv() error %d!\n", errno));
769
770 if (errno == EINTR)
771 continue;
772 else if (errno != http->error)
773 {
774 http->error = errno;
775 continue;
776 }
777#endif /* WIN32 */
778
779 return (NULL);
780 }
781 else if (bytes == 0)
782 {
783 http->error = EPIPE;
784
785 return (NULL);
786 }
787
788 /*
789 * Yup, update the amount used...
790 */
791
792 http->used += bytes;
793 }
794
795 /*
796 * Now copy as much of the current line as possible...
797 */
798
799 for (bufptr = http->buffer, bufend = http->buffer + http->used;
800 lineptr < lineend && bufptr < bufend;)
801 {
802 if (*bufptr == 0x0a)
803 {
804 eol = 1;
805 bufptr ++;
806 break;
807 }
808 else if (*bufptr == 0x0d)
809 bufptr ++;
810 else
811 *lineptr++ = *bufptr++;
812 }
813
814 http->used -= bufptr - http->buffer;
815 if (http->used > 0)
816 memmove(http->buffer, bufptr, http->used);
817
818 if (eol)
819 {
820 /*
821 * End of line...
822 */
823
824 http->activity = time(NULL);
825
826 *lineptr = '\0';
827
828 DEBUG_printf(("httpGets: Returning \"%s\"\n", line));
829
830 return (line);
831 }
832 }
833
834 DEBUG_puts("httpGets: No new line available!");
835
836 return (NULL);
837}
838
839
840/*
841 * 'httpHead()' - Send a HEAD request to the server.
842 */
843
844int /* O - Status of call (0 = success) */
845httpHead(http_t *http, /* I - HTTP data */
846 const char *uri) /* I - URI for head */
847{
848 return (http_send(http, HTTP_HEAD, uri));
849}
850
851
852/*
853 * 'httpInitialize()' - Initialize the HTTP interface library and set the
854 * default HTTP proxy (if any).
855 */
856
857void
858httpInitialize(void)
859{
860#ifdef HAVE_LIBSSL
861# ifndef WIN32
862 struct timeval curtime; /* Current time in microseconds */
863# endif /* !WIN32 */
864 int i; /* Looping var */
865 unsigned char data[1024]; /* Seed data */
866#endif /* HAVE_LIBSSL */
867
868#ifdef WIN32
869 WSADATA winsockdata; /* WinSock data */
870 static int initialized = 0; /* Has WinSock been initialized? */
871
872
873 if (!initialized)
874 WSAStartup(MAKEWORD(1,1), &winsockdata);
fa73b229 875#elif !defined(SO_NOSIGPIPE)
ef416fc2 876 /*
877 * Ignore SIGPIPE signals...
878 */
879
fa73b229 880# ifdef HAVE_SIGSET
881 sigset(SIGPIPE, SIG_IGN);
882# elif defined(HAVE_SIGACTION)
883 struct sigaction action; /* POSIX sigaction data */
884
885
ef416fc2 886 memset(&action, 0, sizeof(action));
887 action.sa_handler = SIG_IGN;
888 sigaction(SIGPIPE, &action, NULL);
fa73b229 889# else
ef416fc2 890 signal(SIGPIPE, SIG_IGN);
fa73b229 891# endif /* !SO_NOSIGPIPE */
ef416fc2 892#endif /* WIN32 */
893
894#ifdef HAVE_GNUTLS
895 gnutls_global_init();
896#endif /* HAVE_GNUTLS */
897
898#ifdef HAVE_LIBSSL
899 SSL_load_error_strings();
900 SSL_library_init();
901
902 /*
903 * Using the current time is a dubious random seed, but on some systems
904 * it is the best we can do (on others, this seed isn't even used...)
905 */
906
907#ifdef WIN32
908#else
909 gettimeofday(&curtime, NULL);
910 srand(curtime.tv_sec + curtime.tv_usec);
911#endif /* WIN32 */
912
913 for (i = 0; i < sizeof(data); i ++)
914 data[i] = rand(); /* Yes, this is a poor source of random data... */
915
916 RAND_seed(&data, sizeof(data));
917#endif /* HAVE_LIBSSL */
918}
919
920
921/*
922 * 'httpOptions()' - Send an OPTIONS request to the server.
923 */
924
925int /* O - Status of call (0 = success) */
926httpOptions(http_t *http, /* I - HTTP data */
927 const char *uri) /* I - URI for options */
928{
929 return (http_send(http, HTTP_OPTIONS, uri));
930}
931
932
933/*
934 * 'httpPost()' - Send a POST request to the server.
935 */
936
937int /* O - Status of call (0 = success) */
938httpPost(http_t *http, /* I - HTTP data */
939 const char *uri) /* I - URI for post */
940{
941 return (http_send(http, HTTP_POST, uri));
942}
943
944
945/*
946 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
947 */
948
949int /* O - Number of bytes written */
950httpPrintf(http_t *http, /* I - HTTP data */
951 const char *format, /* I - printf-style format string */
952 ...) /* I - Additional args as needed */
953{
954 int bytes; /* Number of bytes to write */
955 char buf[16384]; /* Buffer for formatted string */
956 va_list ap; /* Variable argument pointer */
957
958
959 DEBUG_printf(("httpPrintf(http=%p, format=\"%s\", ...)\n", http, format));
960
961 va_start(ap, format);
962 bytes = vsnprintf(buf, sizeof(buf), format, ap);
963 va_end(ap);
964
965 DEBUG_printf(("httpPrintf: %s", buf));
966
967 if (http->wused)
968 {
969 DEBUG_puts(" flushing existing data...");
970
971 if (httpFlushWrite(http) < 0)
972 return (-1);
973 }
974
975 return (http_write(http, buf, bytes));
976}
977
978
979/*
980 * 'httpPut()' - Send a PUT request to the server.
981 */
982
983int /* O - Status of call (0 = success) */
984httpPut(http_t *http, /* I - HTTP data */
985 const char *uri) /* I - URI to put */
986{
987 return (http_send(http, HTTP_PUT, uri));
988}
989
990
991/*
992 * 'httpRead()' - Read data from a HTTP connection.
a4d04587 993 *
994 * This function is deprecated. Use the httpRead2() function which can
995 * read more than 2GB of data.
996 *
997 * @deprecated@
ef416fc2 998 */
999
1000int /* O - Number of bytes read */
1001httpRead(http_t *http, /* I - HTTP data */
1002 char *buffer, /* I - Buffer for data */
1003 int length) /* I - Maximum number of bytes */
1004{
a4d04587 1005 return ((int)httpRead2(http, buffer, length));
1006}
1007
1008
1009/*
1010 * 'httpRead2()' - Read data from a HTTP connection.
1011 */
1012
1013ssize_t /* O - Number of bytes read */
1014httpRead2(http_t *http, /* I - HTTP data */
1015 char *buffer, /* I - Buffer for data */
1016 size_t length) /* I - Maximum number of bytes */
1017{
1018 ssize_t bytes; /* Bytes read */
ef416fc2 1019 char len[32]; /* Length string */
1020
1021
1022 DEBUG_printf(("httpRead(http=%p, buffer=%p, length=%d)\n",
1023 http, buffer, length));
1024
1025 if (http == NULL || buffer == NULL)
1026 return (-1);
1027
1028 http->activity = time(NULL);
1029
1030 if (length <= 0)
1031 return (0);
1032
1033 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1034 http->data_remaining <= 0)
1035 {
a4d04587 1036 DEBUG_puts("httpRead2: Getting chunk length...");
ef416fc2 1037
1038 if (httpGets(len, sizeof(len), http) == NULL)
1039 {
a4d04587 1040 DEBUG_puts("httpRead2: Could not get length!");
ef416fc2 1041 return (0);
1042 }
1043
1044 http->data_remaining = strtoll(len, NULL, 16);
1045 if (http->data_remaining < 0)
1046 {
a4d04587 1047 DEBUG_puts("httpRead2: Negative chunk length!");
ef416fc2 1048 return (0);
1049 }
1050 }
1051
a4d04587 1052 DEBUG_printf(("httpRead2: data_remaining=" CUPS_LLFMT "\n",
ef416fc2 1053 CUPS_LLCAST http->data_remaining));
1054
1055 if (http->data_remaining <= 0)
1056 {
1057 /*
1058 * A zero-length chunk ends a transfer; unless we are reading POST
1059 * data, go idle...
1060 */
1061
1062 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1063 httpGets(len, sizeof(len), http);
1064
1065 if (http->state == HTTP_POST_RECV)
1066 http->state ++;
1067 else
1068 http->state = HTTP_WAITING;
1069
1070 /*
1071 * Prevent future reads for this request...
1072 */
1073
1074 http->data_encoding = HTTP_ENCODE_LENGTH;
1075
1076 return (0);
1077 }
1078 else if (length > http->data_remaining)
1079 length = http->data_remaining;
1080
1081 if (http->used == 0 && length <= 256)
1082 {
1083 /*
1084 * Buffer small reads for better performance...
1085 */
1086
1087 if (!http->blocking && !httpWait(http, 1000))
1088 return (0);
1089
1090 if (http->data_remaining > sizeof(http->buffer))
1091 bytes = sizeof(http->buffer);
1092 else
1093 bytes = http->data_remaining;
1094
1095#ifdef HAVE_SSL
1096 if (http->tls)
1097 bytes = http_read_ssl(http, http->buffer, bytes);
1098 else
1099#endif /* HAVE_SSL */
1100 {
a4d04587 1101 DEBUG_printf(("httpRead2: reading %d bytes from socket into buffer...\n",
ef416fc2 1102 bytes));
1103
1104 bytes = recv(http->fd, http->buffer, bytes, 0);
1105
a4d04587 1106 DEBUG_printf(("httpRead2: read %d bytes from socket into buffer...\n",
ef416fc2 1107 bytes));
1108 }
1109
1110 if (bytes > 0)
1111 http->used = bytes;
1112 else if (bytes < 0)
1113 {
1114#ifdef WIN32
1115 http->error = WSAGetLastError();
1116 return (-1);
1117#else
1118 if (errno != EINTR)
1119 {
1120 http->error = errno;
1121 return (-1);
1122 }
1123#endif /* WIN32 */
1124 }
1125 else
1126 {
1127 http->error = EPIPE;
1128 return (0);
1129 }
1130 }
1131
1132 if (http->used > 0)
1133 {
1134 if (length > http->used)
1135 length = http->used;
1136
1137 bytes = length;
1138
a4d04587 1139 DEBUG_printf(("httpRead2: grabbing %d bytes from input buffer...\n", bytes));
ef416fc2 1140
1141 memcpy(buffer, http->buffer, length);
1142 http->used -= length;
1143
1144 if (http->used > 0)
1145 memmove(http->buffer, http->buffer + length, http->used);
1146 }
1147#ifdef HAVE_SSL
1148 else if (http->tls)
1149 {
1150 if (!http->blocking && !httpWait(http, 1000))
1151 return (0);
1152
1153 bytes = http_read_ssl(http, buffer, length);
1154 }
1155#endif /* HAVE_SSL */
1156 else
1157 {
1158 if (!http->blocking && !httpWait(http, 1000))
1159 return (0);
1160
a4d04587 1161 DEBUG_printf(("httpRead2: reading %d bytes from socket...\n", length));
ef416fc2 1162
1163 while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
1164 if (errno != EINTR)
1165 break;
1166
a4d04587 1167 DEBUG_printf(("httpRead2: read %d bytes from socket...\n", bytes));
ef416fc2 1168 }
1169
1170 if (bytes > 0)
1171 {
1172 http->data_remaining -= bytes;
1173
1174 if (http->data_remaining <= INT_MAX)
1175 http->_data_remaining = (int)http->data_remaining;
1176 else
1177 http->_data_remaining = INT_MAX;
1178 }
1179 else if (bytes < 0)
1180 {
1181#ifdef WIN32
1182 http->error = WSAGetLastError();
1183#else
1184 if (errno == EINTR)
1185 bytes = 0;
1186 else
1187 http->error = errno;
1188#endif /* WIN32 */
1189 }
1190 else
1191 {
1192 http->error = EPIPE;
1193 return (0);
1194 }
1195
1196 if (http->data_remaining == 0)
1197 {
1198 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1199 httpGets(len, sizeof(len), http);
1200
1201 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1202 {
1203 if (http->state == HTTP_POST_RECV)
1204 http->state ++;
1205 else
1206 http->state = HTTP_WAITING;
1207 }
1208 }
1209
1210#ifdef DEBUG
1211 {
1212 int i, j, ch;
a4d04587 1213 printf("httpRead2: Read %d bytes:\n", bytes);
ef416fc2 1214 for (i = 0; i < bytes; i += 16)
1215 {
1216 printf(" ");
1217
1218 for (j = 0; j < 16 && (i + j) < bytes; j ++)
1219 printf(" %02X", buffer[i + j] & 255);
1220
1221 while (j < 16)
1222 {
1223 printf(" ");
1224 j ++;
1225 }
1226
1227 printf(" ");
1228 for (j = 0; j < 16 && (i + j) < bytes; j ++)
1229 {
1230 ch = buffer[i + j] & 255;
1231
fa73b229 1232 if (ch < ' ' || ch >= 127)
ef416fc2 1233 ch = '.';
1234
1235 putchar(ch);
1236 }
1237 putchar('\n');
1238 }
1239 }
1240#endif /* DEBUG */
1241
1242 return (bytes);
1243}
1244
1245
1246#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
1247/*
1248 * '_httpReadCDSA()' - Read function for CDSA decryption code.
1249 */
1250
1251OSStatus /* O - -1 on error, 0 on success */
1252_httpReadCDSA(
1253 SSLConnectionRef connection, /* I - SSL/TLS connection */
1254 void *data, /* I - Data buffer */
1255 size_t *dataLength) /* IO - Number of bytes */
1256{
fa73b229 1257 OSStatus result; /* Return value */
ef416fc2 1258 ssize_t bytes; /* Number of bytes read */
1259
1260
fa73b229 1261 for (;;)
ef416fc2 1262 {
fa73b229 1263 bytes = recv((int)connection, data, *dataLength, 0);
1264
1265 if (bytes > 0)
1266 {
1267 result = (bytes == *dataLength);
1268 *dataLength = bytes;
1269
1270 return (result);
1271 }
1272
1273 if (bytes == 0)
1274 return (errSSLClosedAbort);
1275
1276 if (errno == EAGAIN)
1277 return (errSSLWouldBlock);
1278
1279 if (errno == EPIPE)
1280 return (errSSLClosedAbort);
1281
1282 if (errno != EINTR)
1283 return (errSSLInternal);
ef416fc2 1284 }
ef416fc2 1285}
1286#endif /* HAVE_SSL && HAVE_CDSASSL */
1287
1288
1289/*
1290 * 'httpReconnect()' - Reconnect to a HTTP server...
1291 */
1292
1293int /* O - 0 on success, non-zero on failure */
1294httpReconnect(http_t *http) /* I - HTTP data */
1295{
1296 http_addrlist_t *addr; /* Connected address */
1297
1298
1299 DEBUG_printf(("httpReconnect(http=%p)\n", http));
1300
1301 if (!http)
1302 return (-1);
1303
1304#ifdef HAVE_SSL
1305 if (http->tls)
1306 http_shutdown_ssl(http);
1307#endif /* HAVE_SSL */
1308
1309 /*
1310 * Close any previously open socket...
1311 */
1312
1313 if (http->fd >= 0)
bd7854cb 1314 {
ef416fc2 1315#ifdef WIN32
1316 closesocket(http->fd);
1317#else
1318 close(http->fd);
1319#endif /* WIN32 */
1320
bd7854cb 1321 http->fd = -1;
1322 }
1323
ef416fc2 1324 /*
1325 * Connect to the server...
1326 */
1327
1328 if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
1329 {
1330 /*
1331 * Unable to connect...
1332 */
1333
1334#ifdef WIN32
1335 http->error = WSAGetLastError();
1336#else
1337 http->error = errno;
1338#endif /* WIN32 */
1339 http->status = HTTP_ERROR;
1340
1341 return (-1);
1342 }
1343
1344 http->hostaddr = &(addr->addr);
1345 http->error = 0;
1346 http->status = HTTP_CONTINUE;
1347
1348#ifdef HAVE_SSL
1349 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
1350 {
1351 /*
1352 * Always do encryption via SSL.
1353 */
1354
1355 if (http_setup_ssl(http) != 0)
1356 {
1357#ifdef WIN32
1358 closesocket(http->fd);
1359#else
1360 close(http->fd);
1361#endif /* WIN32 */
1362
1363 return (-1);
1364 }
1365 }
1366 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
1367 return (http_upgrade(http));
1368#endif /* HAVE_SSL */
1369
1370 return (0);
1371}
1372
1373
1374/*
1375 * 'httpSetCookie()' - Set the cookie value(s)...
1376 *
1377 * @since CUPS 1.1.19@
1378 */
1379
1380void
1381httpSetCookie(http_t *http, /* I - Connection */
1382 const char *cookie) /* I - Cookie string */
1383{
1384 if (!http)
1385 return;
1386
1387 if (http->cookie)
1388 free(http->cookie);
1389
1390 if (cookie)
1391 http->cookie = strdup(cookie);
1392 else
1393 http->cookie = NULL;
1394}
1395
1396
1397/*
1398 * 'httpSetField()' - Set the value of an HTTP header.
1399 */
1400
1401void
1402httpSetField(http_t *http, /* I - HTTP data */
1403 http_field_t field, /* I - Field index */
1404 const char *value) /* I - Value */
1405{
1406 if (http == NULL ||
1407 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
1408 field > HTTP_FIELD_WWW_AUTHENTICATE ||
1409 value == NULL)
1410 return;
1411
1412 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
1413}
1414
1415
1416/*
1417 * 'httpSetLength()' - Set the content-length and content-encoding.
1418 *
1419 * @since CUPS 1.2@
1420 */
1421
1422void
1423httpSetLength(http_t *http, /* I - HTTP data */
1424 size_t length) /* I - Length (0 for chunked) */
1425{
1426 if (!http)
1427 return;
1428
1429 if (!length)
1430 {
1431 strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
1432 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
1433 }
1434 else
1435 {
1436 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
1437 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
1438 CUPS_LLFMT, CUPS_LLCAST length);
1439 }
1440}
1441
1442
1443/*
1444 * 'httpTrace()' - Send an TRACE request to the server.
1445 */
1446
1447int /* O - Status of call (0 = success) */
1448httpTrace(http_t *http, /* I - HTTP data */
1449 const char *uri) /* I - URI for trace */
1450{
1451 return (http_send(http, HTTP_TRACE, uri));
1452}
1453
1454
1455/*
1456 * 'httpUpdate()' - Update the current HTTP state for incoming data.
1457 */
1458
1459http_status_t /* O - HTTP status */
1460httpUpdate(http_t *http) /* I - HTTP data */
1461{
1462 char line[32768], /* Line from connection... */
1463 *value; /* Pointer to value on line */
1464 http_field_t field; /* Field index */
1465 int major, minor, /* HTTP version numbers */
1466 status; /* Request status */
1467
1468
1469 DEBUG_printf(("httpUpdate(http=%p), state=%d\n", http, http->state));
1470
1471 /*
1472 * Flush pending data, if any...
1473 */
1474
1475 if (http->wused)
1476 {
1477 DEBUG_puts(" flushing buffer...");
1478
1479 if (httpFlushWrite(http) < 0)
1480 return (HTTP_ERROR);
1481 }
1482
1483 /*
1484 * If we haven't issued any commands, then there is nothing to "update"...
1485 */
1486
1487 if (http->state == HTTP_WAITING)
1488 return (HTTP_CONTINUE);
1489
1490 /*
1491 * Grab all of the lines we can from the connection...
1492 */
1493
1494 while (httpGets(line, sizeof(line), http) != NULL)
1495 {
1496 DEBUG_printf(("httpUpdate: Got \"%s\"\n", line));
1497
1498 if (line[0] == '\0')
1499 {
1500 /*
1501 * Blank line means the start of the data section (if any). Return
1502 * the result code, too...
1503 *
1504 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
1505 * Instead, we just return HTTP_CONTINUE to the caller and keep on
1506 * tryin'...
1507 */
1508
1509 if (http->status == HTTP_CONTINUE)
1510 return (http->status);
1511
1512 if (http->status < HTTP_BAD_REQUEST)
1513 http->digest_tries = 0;
1514
1515#ifdef HAVE_SSL
1516 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
1517 {
1518 if (http_setup_ssl(http) != 0)
1519 {
1520# ifdef WIN32
1521 closesocket(http->fd);
1522# else
1523 close(http->fd);
1524# endif /* WIN32 */
1525
1526 return (HTTP_ERROR);
1527 }
1528
1529 return (HTTP_CONTINUE);
1530 }
1531#endif /* HAVE_SSL */
1532
1533 httpGetLength2(http);
1534
1535 switch (http->state)
1536 {
1537 case HTTP_GET :
1538 case HTTP_POST :
1539 case HTTP_POST_RECV :
1540 case HTTP_PUT :
1541 http->state ++;
1542 case HTTP_POST_SEND :
1543 break;
1544
1545 default :
1546 http->state = HTTP_WAITING;
1547 break;
1548 }
1549
1550 return (http->status);
1551 }
1552 else if (strncmp(line, "HTTP/", 5) == 0)
1553 {
1554 /*
1555 * Got the beginning of a response...
1556 */
1557
1558 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
1559 return (HTTP_ERROR);
1560
1561 http->version = (http_version_t)(major * 100 + minor);
1562 http->status = (http_status_t)status;
1563 }
1564 else if ((value = strchr(line, ':')) != NULL)
1565 {
1566 /*
1567 * Got a value...
1568 */
1569
1570 *value++ = '\0';
1571 while (isspace(*value & 255))
1572 value ++;
1573
1574 /*
1575 * Be tolerants of servers that send unknown attribute fields...
1576 */
1577
1578 if (!strcasecmp(line, "expect"))
1579 {
1580 /*
1581 * "Expect: 100-continue" or similar...
1582 */
1583
1584 http->expect = (http_status_t)atoi(value);
1585 }
1586 else if (!strcasecmp(line, "cookie"))
1587 {
1588 /*
1589 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
1590 */
1591
1592 httpSetCookie(http, value);
1593 }
1594 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
1595 {
1596 DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line));
1597 continue;
1598 }
1599 else
1600 httpSetField(http, field, value);
1601 }
1602 else
1603 {
1604 http->status = HTTP_ERROR;
1605 return (HTTP_ERROR);
1606 }
1607 }
1608
1609 /*
1610 * See if there was an error...
1611 */
1612
1613 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
1614 return (http->status);
1615
1616 if (http->error)
1617 {
1618 DEBUG_printf(("httpUpdate: socket error %d - %s\n", http->error,
1619 strerror(http->error)));
1620 http->status = HTTP_ERROR;
1621 return (HTTP_ERROR);
1622 }
1623
1624 /*
1625 * If we haven't already returned, then there is nothing new...
1626 */
1627
1628 return (HTTP_CONTINUE);
1629}
1630
1631
1632/*
1633 * 'httpWait()' - Wait for data available on a connection.
1634 *
1635 * @since CUPS 1.1.19@
1636 */
1637
1638int /* O - 1 if data is available, 0 otherwise */
1639httpWait(http_t *http, /* I - HTTP data */
1640 int msec) /* I - Milliseconds to wait */
1641{
1642 /*
1643 * First see if there is data in the buffer...
1644 */
1645
1646 if (http == NULL)
1647 return (0);
1648
1649 if (http->used)
1650 return (1);
1651
1652 /*
1653 * If not, check the SSL/TLS buffers and do a select() on the connection...
1654 */
1655
1656 return (http_wait(http, msec));
1657}
1658
1659
1660/*
1661 * 'httpWrite()' - Write data to a HTTP connection.
a4d04587 1662 *
1663 * This function is deprecated. Use the httpWrite2() function which can
1664 * write more than 2GB of data.
1665 *
1666 * @deprecated@
ef416fc2 1667 */
1668
1669int /* O - Number of bytes written */
1670httpWrite(http_t *http, /* I - HTTP data */
1671 const char *buffer, /* I - Buffer for data */
1672 int length) /* I - Number of bytes to write */
1673{
a4d04587 1674 return ((int)httpWrite2(http, buffer, length));
1675}
1676
1677
1678/*
1679 * 'httpWrite2()' - Write data to a HTTP connection.
1680 */
1681
1682ssize_t /* O - Number of bytes written */
1683httpWrite2(http_t *http, /* I - HTTP data */
1684 const char *buffer, /* I - Buffer for data */
1685 size_t length) /* I - Number of bytes to write */
1686{
1687 ssize_t bytes; /* Bytes written */
ef416fc2 1688
1689
1690 DEBUG_printf(("httpWrite(http=%p, buffer=%p, length=%d)\n", http,
1691 buffer, length));
1692
1693 /*
1694 * Range check input...
1695 */
1696
1697 if (http == NULL || buffer == NULL)
1698 return (-1);
1699
1700 /*
1701 * Mark activity on the connection...
1702 */
1703
1704 http->activity = time(NULL);
1705
1706 /*
1707 * Buffer small writes for better performance...
1708 */
1709
1710 if (length > 0)
1711 {
1712 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
1713 {
1714 DEBUG_printf((" flushing buffer (wused=%d, length=%d)\n",
1715 http->wused, length));
1716
1717 httpFlushWrite(http);
1718 }
1719
1720 if ((length + http->wused) <= sizeof(http->wbuffer))
1721 {
1722 /*
1723 * Write to buffer...
1724 */
1725
1726 DEBUG_printf((" copying %d bytes to wbuffer...\n", length));
1727
1728 memcpy(http->wbuffer + http->wused, buffer, length);
1729 http->wused += length;
1730 bytes = length;
1731 }
1732 else
1733 {
1734 /*
1735 * Otherwise write the data directly...
1736 */
1737
1738 DEBUG_printf((" writing %d bytes to socket...\n", length));
1739
1740 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1741 bytes = http_write_chunk(http, buffer, length);
1742 else
1743 bytes = http_write(http, buffer, length);
1744
1745 DEBUG_printf((" wrote %d bytes...\n", bytes));
1746 }
1747
1748 if (http->data_encoding == HTTP_ENCODE_LENGTH)
1749 http->data_remaining -= bytes;
1750 }
1751 else
1752 bytes = 0;
1753
1754 /*
1755 * Handle end-of-request processing...
1756 */
1757
1758 if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
1759 (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
1760 {
1761 /*
1762 * Finished with the transfer; unless we are sending POST or PUT
1763 * data, go idle...
1764 */
1765
1766 DEBUG_puts("httpWrite: changing states...");
1767
1768 if (http->wused)
1769 httpFlushWrite(http);
1770
1771 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1772 {
1773 /*
1774 * Send a 0-length chunk at the end of the request...
1775 */
1776
1777 http_write(http, "0\r\n\r\n", 5);
1778
1779 /*
1780 * Reset the data state...
1781 */
1782
1783 http->data_encoding = HTTP_ENCODE_LENGTH;
1784 http->data_remaining = 0;
1785 }
1786
1787 if (http->state == HTTP_POST_RECV)
1788 http->state ++;
1789 else if (http->state == HTTP_PUT_RECV)
1790 http->state = HTTP_STATUS;
1791 else
1792 http->state = HTTP_WAITING;
1793 }
1794
1795 return (bytes);
1796}
1797
1798
1799#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
1800/*
1801 * '_httpWriteCDSA()' - Write function for CDSA encryption code.
1802 */
1803
1804OSStatus /* O - -1 on error, 0 on success */
1805_httpWriteCDSA(
1806 SSLConnectionRef connection, /* I - SSL/TLS connection */
1807 const void *data, /* I - Data buffer */
1808 size_t *dataLength) /* IO - Number of bytes */
1809{
fa73b229 1810 OSStatus result; /* Return value */
1811 ssize_t bytes; /* Number of bytes read */
ef416fc2 1812
1813
fa73b229 1814 for (;;)
ef416fc2 1815 {
fa73b229 1816 bytes = write((int)connection, data, *dataLength);
1817
1818 if (bytes >= 0)
1819 {
1820 result = (bytes == *dataLength) ? 0 : errSSLWouldBlock;
1821 *dataLength = bytes;
1822
1823 return (result);
1824 }
1825
1826 if (errno == EAGAIN)
1827 return (errSSLWouldBlock);
1828
1829 if (errno == EPIPE)
1830 return (errSSLClosedAbort);
1831
1832 if (errno != EINTR)
1833 return (errSSLInternal);
ef416fc2 1834 }
ef416fc2 1835}
1836#endif /* HAVE_SSL && HAVE_CDSASSL */
1837
1838
1839/*
1840 * 'http_field()' - Return the field index for a field name.
1841 */
1842
1843static http_field_t /* O - Field index */
1844http_field(const char *name) /* I - String name */
1845{
1846 int i; /* Looping var */
1847
1848
1849 for (i = 0; i < HTTP_FIELD_MAX; i ++)
1850 if (strcasecmp(name, http_fields[i]) == 0)
1851 return ((http_field_t)i);
1852
1853 return (HTTP_FIELD_UNKNOWN);
1854}
1855
1856
1857#ifdef HAVE_SSL
1858/*
1859 * 'http_read_ssl()' - Read from a SSL/TLS connection.
1860 */
1861
1862static int /* O - Bytes read */
1863http_read_ssl(http_t *http, /* I - HTTP data */
1864 char *buf, /* I - Buffer to store data */
1865 int len) /* I - Length of buffer */
1866{
1867# if defined(HAVE_LIBSSL)
1868 return (SSL_read((SSL *)(http->tls), buf, len));
1869
1870# elif defined(HAVE_GNUTLS)
1871 return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
1872
1873# elif defined(HAVE_CDSASSL)
fa73b229 1874 int result; /* Return value */
ef416fc2 1875 OSStatus error; /* Error info */
1876 size_t processed; /* Number of bytes processed */
1877
1878
1879 error = SSLRead((SSLContextRef)http->tls, buf, len, &processed);
1880
fa73b229 1881 switch (error)
ef416fc2 1882 {
fa73b229 1883 case 0 :
1884 result = (int)processed;
1885 break;
1886 case errSSLClosedGraceful :
1887 result = 0;
1888 break;
1889 case errSSLWouldBlock :
1890 errno = EAGAIN;
1891 result = -1;
1892 break;
1893 default :
1894 errno = EPIPE;
1895 result = -1;
1896 break;
ef416fc2 1897 }
fa73b229 1898
1899 return (result);
ef416fc2 1900# endif /* HAVE_LIBSSL */
1901}
1902#endif /* HAVE_SSL */
1903
1904
1905/*
1906 * 'http_send()' - Send a request with all fields and the trailing blank line.
1907 */
1908
1909static int /* O - 0 on success, non-zero on error */
1910http_send(http_t *http, /* I - HTTP data */
1911 http_state_t request, /* I - Request code */
1912 const char *uri) /* I - URI */
1913{
1914 int i; /* Looping var */
1915 char *ptr, /* Pointer in buffer */
1916 buf[1024]; /* Encoded URI buffer */
1917 static const char * const codes[] =
1918 { /* Request code strings */
1919 NULL,
1920 "OPTIONS",
1921 "GET",
1922 NULL,
1923 "HEAD",
1924 "POST",
1925 NULL,
1926 NULL,
1927 "PUT",
1928 NULL,
1929 "DELETE",
1930 "TRACE",
1931 "CLOSE"
1932 };
1933 static const char hex[] = "0123456789ABCDEF";
1934 /* Hex digits */
1935
1936
1937 DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n",
1938 http, codes[request], uri));
1939
1940 if (http == NULL || uri == NULL)
1941 return (-1);
1942
1943 /*
1944 * Set the User-Agent field if it isn't already...
1945 */
1946
1947 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
1948 httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
1949
1950 /*
1951 * Encode the URI as needed...
1952 */
1953
1954 for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++)
1955 if (*uri <= ' ' || *uri >= 127)
1956 {
1957 if (ptr < (buf + sizeof(buf) - 1))
1958 *ptr ++ = '%';
1959 if (ptr < (buf + sizeof(buf) - 1))
1960 *ptr ++ = hex[(*uri >> 4) & 15];
1961 if (ptr < (buf + sizeof(buf) - 1))
1962 *ptr ++ = hex[*uri & 15];
1963 }
1964 else
1965 *ptr ++ = *uri;
1966
1967 *ptr = '\0';
1968
1969 /*
1970 * See if we had an error the last time around; if so, reconnect...
1971 */
1972
1973 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
fa73b229 1974 if (httpReconnect(http))
1975 return (-1);
ef416fc2 1976
1977 /*
1978 * Send the request header...
1979 */
1980
1981 http->state = request;
1982 if (request == HTTP_POST || request == HTTP_PUT)
1983 http->state ++;
1984
1985 http->status = HTTP_CONTINUE;
1986
1987#ifdef HAVE_SSL
1988 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
1989 {
1990 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
1991 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
1992 }
1993#endif /* HAVE_SSL */
1994
1995 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
1996 {
1997 http->status = HTTP_ERROR;
1998 return (-1);
1999 }
2000
2001 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2002 if (http->fields[i][0] != '\0')
2003 {
2004 DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i]));
2005
2006 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1)
2007 {
2008 http->status = HTTP_ERROR;
2009 return (-1);
2010 }
2011 }
2012
2013 if (http->cookie)
2014 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
2015 {
2016 http->status = HTTP_ERROR;
2017 return (-1);
2018 }
2019
2020 if (httpPrintf(http, "\r\n") < 1)
2021 {
2022 http->status = HTTP_ERROR;
2023 return (-1);
2024 }
2025
2026 httpGetLength2(http);
2027 httpClearFields(http);
2028
2029 return (0);
2030}
2031
2032
2033#ifdef HAVE_SSL
2034/*
2035 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
2036 */
2037
2038static int /* O - Status of connection */
2039http_setup_ssl(http_t *http) /* I - HTTP data */
2040{
2041# ifdef HAVE_LIBSSL
2042 SSL_CTX *context; /* Context for encryption */
2043 SSL *conn; /* Connection for encryption */
2044# elif defined(HAVE_GNUTLS)
2045 http_tls_t *conn; /* TLS session object */
2046 gnutls_certificate_client_credentials *credentials;
2047 /* TLS credentials */
2048# elif defined(HAVE_CDSASSL)
2049 SSLContextRef conn; /* Context for encryption */
2050 OSStatus error; /* Error info */
2051# endif /* HAVE_LIBSSL */
2052
2053
2054 DEBUG_printf(("http_setup_ssl(http=%p)\n", http));
2055
2056# ifdef HAVE_LIBSSL
2057 context = SSL_CTX_new(SSLv23_client_method());
2058
2059 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
2060
2061 conn = SSL_new(context);
2062
2063 SSL_set_fd(conn, http->fd);
2064 if (SSL_connect(conn) != 1)
2065 {
2066# ifdef DEBUG
2067 unsigned long error; /* Error code */
2068
2069 while ((error = ERR_get_error()) != 0)
2070 printf("http_setup_ssl: %s\n", ERR_error_string(error, NULL));
2071# endif /* DEBUG */
2072
2073 SSL_CTX_free(context);
2074 SSL_free(conn);
2075
2076# ifdef WIN32
2077 http->error = WSAGetLastError();
2078# else
2079 http->error = errno;
2080# endif /* WIN32 */
2081 http->status = HTTP_ERROR;
2082
2083 return (HTTP_ERROR);
2084 }
2085
2086# elif defined(HAVE_GNUTLS)
2087 conn = (http_tls_t *)malloc(sizeof(http_tls_t));
2088
2089 if (conn == NULL)
2090 {
2091 http->error = errno;
2092 http->status = HTTP_ERROR;
2093
2094 return (-1);
2095 }
2096
2097 credentials = (gnutls_certificate_client_credentials *)
2098 malloc(sizeof(gnutls_certificate_client_credentials));
2099 if (credentials == NULL)
2100 {
2101 free(conn);
2102
2103 http->error = errno;
2104 http->status = HTTP_ERROR;
2105
2106 return (-1);
2107 }
2108
2109 gnutls_certificate_allocate_credentials(credentials);
2110
2111 gnutls_init(&(conn->session), GNUTLS_CLIENT);
2112 gnutls_set_default_priority(conn->session);
2113 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
2114 gnutls_transport_set_ptr(conn->session, http->fd);
2115
2116 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
2117 {
2118 http->error = errno;
2119 http->status = HTTP_ERROR;
2120
2121 return (-1);
2122 }
2123
2124 conn->credentials = credentials;
2125
2126# elif defined(HAVE_CDSASSL)
2127 error = SSLNewContext(false, &conn);
2128
2129 if (!error)
2130 error = SSLSetIOFuncs(conn, _httpReadCDSA, _httpWriteCDSA);
2131
2132 if (!error)
2133 error = SSLSetConnection(conn, (SSLConnectionRef)http->fd);
2134
2135 if (!error)
2136 error = SSLSetAllowsExpiredCerts(conn, true);
2137
2138 if (!error)
2139 error = SSLSetAllowsAnyRoot(conn, true);
2140
2141 if (!error)
2142 error = SSLHandshake(conn);
2143
2144 if (error != 0)
2145 {
2146 http->error = error;
2147 http->status = HTTP_ERROR;
2148
2149 SSLDisposeContext(conn);
2150
2151 close(http->fd);
2152
2153 return (-1);
2154 }
2155# endif /* HAVE_CDSASSL */
2156
2157 http->tls = conn;
2158 return (0);
2159}
2160#endif /* HAVE_SSL */
2161
2162
2163#ifdef HAVE_SSL
2164/*
2165 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
2166 */
2167
2168static void
2169http_shutdown_ssl(http_t *http) /* I - HTTP data */
2170{
2171# ifdef HAVE_LIBSSL
2172 SSL_CTX *context; /* Context for encryption */
2173 SSL *conn; /* Connection for encryption */
2174
2175
2176 conn = (SSL *)(http->tls);
2177 context = SSL_get_SSL_CTX(conn);
2178
2179 SSL_shutdown(conn);
2180 SSL_CTX_free(context);
2181 SSL_free(conn);
2182
2183# elif defined(HAVE_GNUTLS)
2184 http_tls_t *conn; /* Encryption session */
2185 gnutls_certificate_client_credentials *credentials;
2186 /* TLS credentials */
2187
2188
2189 conn = (http_tls_t *)(http->tls);
2190 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
2191
2192 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
2193 gnutls_deinit(conn->session);
2194 gnutls_certificate_free_credentials(*credentials);
2195 free(credentials);
2196 free(conn);
2197
2198# elif defined(HAVE_CDSASSL)
2199 SSLClose((SSLContextRef)http->tls);
2200 SSLDisposeContext((SSLContextRef)http->tls);
2201# endif /* HAVE_LIBSSL */
2202
2203 http->tls = NULL;
2204}
2205#endif /* HAVE_SSL */
2206
2207
2208#ifdef HAVE_SSL
2209/*
2210 * 'http_upgrade()' - Force upgrade to TLS encryption.
2211 */
2212
2213static int /* O - Status of connection */
2214http_upgrade(http_t *http) /* I - HTTP data */
2215{
2216 int ret; /* Return value */
2217 http_t myhttp; /* Local copy of HTTP data */
2218
2219
2220 DEBUG_printf(("http_upgrade(%p)\n", http));
2221
2222 /*
2223 * Copy the HTTP data to a local variable so we can do the OPTIONS
2224 * request without interfering with the existing request data...
2225 */
2226
2227 memcpy(&myhttp, http, sizeof(myhttp));
2228
2229 /*
2230 * Send an OPTIONS request to the server, requiring SSL or TLS
2231 * encryption on the link...
2232 */
2233
2234 httpClearFields(&myhttp);
2235 httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade");
2236 httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
2237
2238 if ((ret = httpOptions(&myhttp, "*")) == 0)
2239 {
2240 /*
2241 * Wait for the secure connection...
2242 */
2243
2244 while (httpUpdate(&myhttp) == HTTP_CONTINUE);
2245 }
2246
2247 httpFlush(&myhttp);
2248
2249 /*
2250 * Copy the HTTP data back over, if any...
2251 */
2252
2253 http->fd = myhttp.fd;
2254 http->error = myhttp.error;
2255 http->activity = myhttp.activity;
2256 http->status = myhttp.status;
2257 http->version = myhttp.version;
2258 http->keep_alive = myhttp.keep_alive;
2259 http->used = myhttp.used;
2260
2261 if (http->used)
2262 memcpy(http->buffer, myhttp.buffer, http->used);
2263
2264 http->auth_type = myhttp.auth_type;
2265 http->nonce_count = myhttp.nonce_count;
2266
2267 memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce));
2268
2269 http->tls = myhttp.tls;
2270 http->encryption = myhttp.encryption;
2271
2272 /*
2273 * See if we actually went secure...
2274 */
2275
2276 if (!http->tls)
2277 {
2278 /*
2279 * Server does not support HTTP upgrade...
2280 */
2281
2282 DEBUG_puts("Server does not support HTTP upgrade!");
2283
2284# ifdef WIN32
2285 closesocket(http->fd);
2286# else
2287 close(http->fd);
2288# endif
2289
2290 http->fd = -1;
2291
2292 return (-1);
2293 }
2294 else
2295 return (ret);
2296}
2297#endif /* HAVE_SSL */
2298
2299
2300/*
2301 * 'http_wait()' - Wait for data available on a connection.
2302 */
2303
2304static int /* O - 1 if data is available, 0 otherwise */
2305http_wait(http_t *http, /* I - HTTP data */
2306 int msec) /* I - Milliseconds to wait */
2307{
2308#ifndef WIN32
2309 struct rlimit limit; /* Runtime limit */
2310 int set_size; /* Size of select set */
2311#endif /* !WIN32 */
2312 struct timeval timeout; /* Timeout */
2313 int nfds; /* Result from select() */
2314
2315
2316 DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
2317
fa73b229 2318 if (http->fd < 0)
2319 return (0);
2320
ef416fc2 2321 /*
2322 * Check the SSL/TLS buffers for data first...
2323 */
2324
2325#ifdef HAVE_SSL
2326 if (http->tls)
2327 {
2328# ifdef HAVE_LIBSSL
2329 if (SSL_pending((SSL *)(http->tls)))
2330 return (1);
2331# elif defined(HAVE_GNUTLS)
2332 if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
2333 return (1);
2334# elif defined(HAVE_CDSASSL)
2335 size_t bytes; /* Bytes that are available */
2336
2337 if (!SSLGetBufferedReadSize((SSLContextRef)http->tls, &bytes) && bytes > 0)
2338 return (1);
2339# endif /* HAVE_LIBSSL */
2340 }
2341#endif /* HAVE_SSL */
2342
2343 /*
2344 * Then try doing a select() to poll the socket...
2345 */
2346
2347 if (!http->input_set)
2348 {
2349#ifdef WIN32
2350 /*
2351 * Windows has a fixed-size select() structure, different (surprise,
2352 * surprise!) from all UNIX implementations. Just allocate this
2353 * fixed structure...
2354 */
2355
2356 http->input_set = calloc(1, sizeof(fd_set));
2357#else
2358 /*
2359 * Allocate the select() input set based upon the max number of file
2360 * descriptors available for this process...
2361 */
2362
2363 getrlimit(RLIMIT_NOFILE, &limit);
2364
2365 set_size = (limit.rlim_cur + 31) / 8 + 4;
2366 if (set_size < sizeof(fd_set))
2367 set_size = sizeof(fd_set);
2368
2369 http->input_set = calloc(1, set_size);
2370#endif /* WIN32 */
2371
2372 if (!http->input_set)
2373 return (0);
2374 }
2375
2376 do
2377 {
2378 FD_SET(http->fd, http->input_set);
2379
2380 if (msec >= 0)
2381 {
2382 timeout.tv_sec = msec / 1000;
2383 timeout.tv_usec = (msec % 1000) * 1000;
2384
2385 nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout);
2386 }
2387 else
2388 nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
2389 }
2390#ifdef WIN32
2391 while (nfds < 0 && WSAGetLastError() == WSAEINTR);
2392#else
2393 while (nfds < 0 && errno == EINTR);
2394#endif /* WIN32 */
2395
2396 FD_CLR(http->fd, http->input_set);
2397
2398 return (nfds > 0);
2399}
2400
2401
2402/*
2403 * 'http_write()' - Write a buffer to a HTTP connection.
2404 */
2405
2406static int /* O - Number of bytes written */
2407http_write(http_t *http, /* I - HTTP data */
2408 const char *buffer, /* I - Buffer for data */
2409 int length) /* I - Number of bytes to write */
2410{
2411 int tbytes, /* Total bytes sent */
2412 bytes; /* Bytes sent */
2413
2414
2415 tbytes = 0;
2416
2417 while (length > 0)
2418 {
2419#ifdef HAVE_SSL
2420 if (http->tls)
2421 bytes = http_write_ssl(http, buffer, length);
2422 else
2423#endif /* HAVE_SSL */
2424 bytes = send(http->fd, buffer, length, 0);
2425
2426 if (bytes < 0)
2427 {
2428#ifdef WIN32
2429 if (WSAGetLastError() != http->error)
2430 {
2431 http->error = WSAGetLastError();
2432 continue;
2433 }
2434#else
2435 if (errno == EINTR)
2436 continue;
2437 else if (errno != http->error && errno != ECONNRESET)
2438 {
2439 http->error = errno;
2440 continue;
2441 }
2442#endif /* WIN32 */
2443
2444 DEBUG_puts("http_write: error writing data...\n");
2445
2446 return (-1);
2447 }
2448
2449 buffer += bytes;
2450 tbytes += bytes;
2451 length -= bytes;
2452 }
2453
2454#ifdef DEBUG
2455 {
2456 int i, j, ch;
2457 printf("http_write: wrote %d bytes: \n", tbytes);
2458 for (i = 0, buffer -= tbytes; i < tbytes; i += 16)
2459 {
2460 printf(" ");
2461
2462 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
2463 printf(" %02X", buffer[i + j] & 255);
2464
2465 while (j < 16)
2466 {
2467 printf(" ");
2468 j ++;
2469 }
2470
2471 printf(" ");
2472 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
2473 {
2474 ch = buffer[i + j] & 255;
2475
2476 if (ch < ' ' || ch == 127)
2477 ch = '.';
2478
2479 putchar(ch);
2480 }
2481 putchar('\n');
2482 }
2483 }
2484#endif /* DEBUG */
2485
2486 return (tbytes);
2487}
2488
2489
2490/*
2491 * 'http_write_chunk()' - Write a chunked buffer.
2492 */
2493
2494static int /* O - Number bytes written */
2495http_write_chunk(http_t *http, /* I - HTTP data */
2496 const char *buffer, /* I - Buffer to write */
2497 int length) /* I - Length of buffer */
2498{
2499 char header[255]; /* Chunk header */
2500 int bytes; /* Bytes written */
2501
2502 DEBUG_printf(("http_write_chunk(http=%p, buffer=%p, length=%d)\n",
2503 http, buffer, length));
2504
2505 /*
2506 * Write the chunk header, data, and trailer.
2507 */
2508
2509 sprintf(header, "%x\r\n", length);
2510 if (http_write(http, header, strlen(header)) < 0)
2511 {
2512 DEBUG_puts(" http_write of length failed!");
2513 return (-1);
2514 }
2515
2516 if ((bytes = http_write(http, buffer, length)) < 0)
2517 {
2518 DEBUG_puts(" http_write of buffer failed!");
2519 return (-1);
2520 }
2521
2522 if (http_write(http, "\r\n", 2) < 0)
2523 {
2524 DEBUG_puts(" http_write of CR LF failed!");
2525 return (-1);
2526 }
2527
2528 return (bytes);
2529}
2530
2531
2532#ifdef HAVE_SSL
2533/*
2534 * 'http_write_ssl()' - Write to a SSL/TLS connection.
2535 */
2536
2537static int /* O - Bytes written */
2538http_write_ssl(http_t *http, /* I - HTTP data */
2539 const char *buf, /* I - Buffer holding data */
2540 int len) /* I - Length of buffer */
2541{
2542# if defined(HAVE_LIBSSL)
2543 return (SSL_write((SSL *)(http->tls), buf, len));
2544
2545# elif defined(HAVE_GNUTLS)
2546 return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
2547# elif defined(HAVE_CDSASSL)
fa73b229 2548 int result; /* Return value */
ef416fc2 2549 OSStatus error; /* Error info */
2550 size_t processed; /* Number of bytes processed */
2551
2552
2553 error = SSLWrite((SSLContextRef)http->tls, buf, len, &processed);
2554
fa73b229 2555 switch (error)
ef416fc2 2556 {
fa73b229 2557 case 0 :
2558 result = (int)processed;
2559 break;
2560 case errSSLClosedGraceful :
2561 result = 0;
2562 break;
2563 case errSSLWouldBlock :
2564 errno = EAGAIN;
2565 result = -1;
2566 break;
2567 default :
2568 errno = EPIPE;
2569 result = -1;
2570 break;
ef416fc2 2571 }
fa73b229 2572
2573 return (result);
ef416fc2 2574# endif /* HAVE_LIBSSL */
2575}
2576#endif /* HAVE_SSL */
2577
2578
2579/*
bd7854cb 2580 * End of "$Id: http.c 5103 2006-02-14 19:27:42Z mike $".
ef416fc2 2581 */