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