8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / lib / print / libhttp-core / common / http.c
blobb32b1eb3bc1803af3bb83f0c6e0606a71f8b590c
1 /*
2 * "$Id: http.c 148 2006-04-25 16:54:17Z njacobs $"
4 * HTTP routines for the Common UNIX Printing System (CUPS).
6 * Copyright 1997-2005 by Easy Software Products, all rights reserved.
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:
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
24 * This file is subject to the Apple OS-Developed Software exception.
26 * Contents:
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.
76 #pragma ident "%Z%%M% %I% %E% SMI"
79 * Include necessary headers...
82 #include "http-private.h"
84 #include <stdio.h>
85 #include <stdlib.h>
86 #include <stdarg.h>
87 #include <ctype.h>
88 #include "string.h"
89 #include <fcntl.h>
90 #include <errno.h>
92 #include "http.h"
93 #include "debug.h"
95 #ifndef WIN32
96 # include <signal.h>
97 # include <sys/time.h>
98 # include <sys/resource.h>
99 #endif /* !WIN32 */
103 * Some operating systems have done away with the Fxxxx constants for
104 * the fcntl() call; this works around that "feature"...
107 #ifndef FNONBLK
108 # define FNONBLK O_NONBLOCK
109 #endif /* !FNONBLK */
113 * Local functions...
116 static http_field_t http_field(const char *name);
117 static int http_send(http_t *http, http_state_t request,
118 const char *uri);
119 static int http_wait(http_t *http, int msec);
120 #ifdef HAVE_SSL
121 static int http_upgrade(http_t *http);
122 static int http_setup_ssl(http_t *http);
123 static void http_shutdown_ssl(http_t *http);
124 static int http_read_ssl(http_t *http, char *buf, int len);
125 static int http_write_ssl(http_t *http, const char *buf, int len);
126 # ifdef HAVE_CDSASSL
127 static OSStatus CDSAReadFunc(SSLConnectionRef connection, void *data, size_t *dataLength);
128 static OSStatus CDSAWriteFunc(SSLConnectionRef connection, const void *data, size_t *dataLength);
129 # endif /* HAVE_CDSASSL */
130 #endif /* HAVE_SSL */
134 * Local globals...
137 static const char * const http_fields[] =
139 "Accept-Language",
140 "Accept-Ranges",
141 "Authorization",
142 "Connection",
143 "Content-Encoding",
144 "Content-Language",
145 "Content-Length",
146 "Content-Location",
147 "Content-MD5",
148 "Content-Range",
149 "Content-Type",
150 "Content-Version",
151 "Date",
152 "Host",
153 "If-Modified-Since",
154 "If-Unmodified-since",
155 "Keep-Alive",
156 "Last-Modified",
157 "Link",
158 "Location",
159 "Range",
160 "Referer",
161 "Retry-After",
162 "Transfer-Encoding",
163 "Upgrade",
164 "User-Agent",
165 "WWW-Authenticate"
167 static const char * const days[7] =
169 "Sun",
170 "Mon",
171 "Tue",
172 "Wed",
173 "Thu",
174 "Fri",
175 "Sat"
177 static const char * const months[12] =
179 "Jan",
180 "Feb",
181 "Mar",
182 "Apr",
183 "May",
184 "Jun",
185 "Jul",
186 "Aug",
187 "Sep",
188 "Oct",
189 "Nov",
190 "Dec"
193 void
194 httpDumpData(FILE *fp, const char *tag, const char *buffer, int bytes)
196 int i, j, ch;
198 fprintf(fp, "%s %d(0x%x) bytes...\n", tag, bytes, bytes);
199 for (i = 0; i < bytes; i += 16) {
200 fprintf(fp, "%s ", (tag ? tag : ""));
202 for (j = 0; j < 16 && (i + j) < bytes; j ++)
203 fprintf(fp, " %02X", buffer[i + j] & 255);
205 while (j < 16) {
206 fprintf(fp, " ");
207 j++;
210 fprintf(fp, " ");
211 for (j = 0; j < 16 && (i + j) < bytes; j ++) {
212 ch = buffer[i + j] & 255;
213 if (ch < ' ' || ch == 127)
214 ch = '.';
215 putc(ch, fp);
217 putc('\n', fp);
223 * 'httpInitialize()' - Initialize the HTTP interface library and set the
224 * default HTTP proxy (if any).
227 void
228 httpInitialize(void)
230 #ifdef HAVE_LIBSSL
231 # ifndef WIN32
232 struct timeval curtime; /* Current time in microseconds */
233 # endif /* !WIN32 */
234 int i; /* Looping var */
235 unsigned char data[1024]; /* Seed data */
236 #endif /* HAVE_LIBSSL */
238 #ifdef WIN32
239 WSADATA winsockdata; /* WinSock data */
240 static int initialized = 0; /* Has WinSock been initialized? */
243 if (!initialized)
244 WSAStartup(MAKEWORD(1,1), &winsockdata);
245 #elif defined(HAVE_SIGSET)
246 sigset(SIGPIPE, SIG_IGN);
247 #elif defined(HAVE_SIGACTION)
248 struct sigaction action; /* POSIX sigaction data */
252 * Ignore SIGPIPE signals...
255 memset(&action, 0, sizeof(action));
256 action.sa_handler = SIG_IGN;
257 sigaction(SIGPIPE, &action, NULL);
258 #else
259 signal(SIGPIPE, SIG_IGN);
260 #endif /* WIN32 */
262 #ifdef HAVE_GNUTLS
263 gnutls_global_init();
264 #endif /* HAVE_GNUTLS */
266 #ifdef HAVE_LIBSSL
267 SSL_load_error_strings();
268 SSL_library_init();
271 * Using the current time is a dubious random seed, but on some systems
272 * it is the best we can do (on others, this seed isn't even used...)
275 #ifdef WIN32
276 #else
277 gettimeofday(&curtime, NULL);
278 srand(curtime.tv_sec + curtime.tv_usec);
279 #endif /* WIN32 */
281 for (i = 0; i < sizeof(data); i ++)
282 data[i] = rand(); /* Yes, this is a poor source of random data... */
284 RAND_seed(&data, sizeof(data));
285 #endif /* HAVE_LIBSSL */
290 * 'httpCheck()' - Check to see if there is a pending response from the server.
293 int /* O - 0 = no data, 1 = data available */
294 httpCheck(http_t *http) /* I - HTTP connection */
296 return (httpWait(http, 0));
301 * 'httpClearCookie()' - Clear the cookie value(s).
304 void
305 httpClearCookie(http_t *http) /* I - Connection */
307 if (!http)
308 return;
310 if (http->cookie)
312 free(http->cookie);
313 http->cookie = NULL;
319 * 'httpClose()' - Close an HTTP connection...
322 void
323 httpClose(http_t *http) /* I - Connection to close */
325 DEBUG_printf(("httpClose(http=%p)\n", http));
327 if (!http)
328 return;
330 if (http->input_set)
331 free(http->input_set);
333 if (http->cookie)
334 free(http->cookie);
336 #ifdef HAVE_SSL
337 if (http->tls)
338 http_shutdown_ssl(http);
339 #endif /* HAVE_SSL */
341 #ifdef WIN32
342 closesocket(http->fd);
343 #else
344 close(http->fd);
345 #endif /* WIN32 */
347 free(http);
352 * 'httpConnect()' - Connect to a HTTP server.
355 http_t * /* O - New HTTP connection */
356 httpConnect(const char *host, /* I - Host to connect to */
357 int port) /* I - Port number */
359 http_encryption_t encrypt; /* Type of encryption to use */
363 * Set the default encryption status...
366 if (port == 443)
367 encrypt = HTTP_ENCRYPT_ALWAYS;
368 else
369 encrypt = HTTP_ENCRYPT_IF_REQUESTED;
371 return (httpConnectEncrypt(host, port, encrypt));
376 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
379 http_t * /* O - New HTTP connection */
380 httpConnectEncrypt(const char *host, /* I - Host to connect to */
381 int port, /* I - Port number */
382 http_encryption_t encrypt)
383 /* I - Type of encryption to use */
385 int i; /* Looping var */
386 http_t *http; /* New HTTP connection */
387 struct hostent *hostaddr; /* Host address data */
390 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encrypt=%d)\n",
391 host ? host : "(null)", port, encrypt));
393 if (!host)
394 return (NULL);
396 httpInitialize();
399 * Lookup the host...
402 if ((hostaddr = httpGetHostByName(host)) == NULL)
405 * This hack to make users that don't have a localhost entry in
406 * their hosts file or DNS happy...
409 if (strcasecmp(host, "localhost") != 0)
410 return (NULL);
411 else if ((hostaddr = httpGetHostByName("127.0.0.1")) == NULL)
412 return (NULL);
416 * Verify that it is an IPv4, IPv6, or domain address...
419 if ((hostaddr->h_addrtype != AF_INET || hostaddr->h_length != 4)
420 #ifdef AF_INET6
421 && (hostaddr->h_addrtype != AF_INET6 || hostaddr->h_length != 16)
422 #endif /* AF_INET6 */
423 #ifdef AF_LOCAL
424 && (hostaddr->h_addrtype != AF_LOCAL)
425 #endif /* AF_LOCAL */
427 return (NULL);
430 * Allocate memory for the structure...
433 http = calloc(sizeof(http_t), 1);
434 if (http == NULL)
435 return (NULL);
437 http->version = HTTP_1_1;
438 http->blocking = 1;
439 http->activity = time(NULL);
440 http->fd = -1;
443 * Set the encryption status...
446 if (port == 443) /* Always use encryption for https */
447 http->encryption = HTTP_ENCRYPT_ALWAYS;
448 else
449 http->encryption = encrypt;
452 * Loop through the addresses we have until one of them connects...
455 strlcpy(http->hostname, host, sizeof(http->hostname));
457 for (i = 0; hostaddr->h_addr_list[i]; i ++)
460 * Load the address...
463 httpAddrLoad(hostaddr, port, i, &(http->hostaddr));
466 * Connect to the remote system...
469 if (!httpReconnect(http))
470 return (http);
474 * Could not connect to any known address - bail out!
477 free(http);
478 return (NULL);
483 * 'httpEncryption()' - Set the required encryption on the link.
486 int /* O - -1 on error, 0 on success */
487 httpEncryption(http_t *http, /* I - HTTP data */
488 http_encryption_t e) /* I - New encryption preference */
490 DEBUG_printf(("httpEncryption(http=%p, e=%d)\n", http, e));
492 #ifdef HAVE_SSL
493 if (!http)
494 return (0);
496 http->encryption = e;
498 if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
499 (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
500 return (httpReconnect(http));
501 else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
502 return (http_upgrade(http));
503 else
504 return (0);
505 #else
506 if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
507 return (-1);
508 else
509 return (0);
510 #endif /* HAVE_SSL */
515 * 'httpReconnect()' - Reconnect to a HTTP server...
518 int /* O - 0 on success, non-zero on failure */
519 httpReconnect(http_t *http) /* I - HTTP data */
521 int val; /* Socket option value */
522 int status; /* Connect status */
525 DEBUG_printf(("httpReconnect(http=%p)\n", http));
527 if (!http)
528 return (-1);
530 #ifdef HAVE_SSL
531 if (http->tls)
532 http_shutdown_ssl(http);
533 #endif /* HAVE_SSL */
536 * Close any previously open socket...
539 if (http->fd >= 0)
540 #ifdef WIN32
541 closesocket(http->fd);
542 #else
543 close(http->fd);
544 #endif /* WIN32 */
547 * Create the socket and set options to allow reuse.
550 if ((http->fd = socket(http->hostaddr.addr.sa_family, SOCK_STREAM, 0)) < 0)
552 #ifdef WIN32
553 http->error = WSAGetLastError();
554 #else
555 http->error = errno;
556 #endif /* WIN32 */
557 http->status = HTTP_ERROR;
558 return (-1);
561 #ifdef FD_CLOEXEC
562 fcntl(http->fd, F_SETFD, FD_CLOEXEC); /* Close this socket when starting *
563 * other processes... */
564 #endif /* FD_CLOEXEC */
566 val = 1;
567 setsockopt(http->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
569 #ifdef SO_REUSEPORT
570 val = 1;
571 setsockopt(http->fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
572 #endif /* SO_REUSEPORT */
575 * Using TCP_NODELAY improves responsiveness, especially on systems
576 * with a slow loopback interface... Since we write large buffers
577 * when sending print files and requests, there shouldn't be any
578 * performance penalty for this...
581 val = 1;
582 #ifdef WIN32
583 setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
584 #else
585 setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
586 #endif /* WIN32 */
589 * Connect to the server...
592 #ifdef AF_INET6
593 if (http->hostaddr.addr.sa_family == AF_INET6)
594 status = connect(http->fd, (struct sockaddr *)&(http->hostaddr),
595 sizeof(http->hostaddr.ipv6));
596 else
597 #endif /* AF_INET6 */
598 #ifdef AF_LOCAL
599 if (http->hostaddr.addr.sa_family == AF_LOCAL)
600 status = connect(http->fd, (struct sockaddr *)&(http->hostaddr),
601 SUN_LEN(&(http->hostaddr.un)));
602 else
603 #endif /* AF_LOCAL */
604 status = connect(http->fd, (struct sockaddr *)&(http->hostaddr),
605 sizeof(http->hostaddr.ipv4));
607 if (status < 0)
609 #ifdef WIN32
610 http->error = WSAGetLastError();
611 #else
612 http->error = errno;
613 #endif /* WIN32 */
614 http->status = HTTP_ERROR;
616 #ifdef WIN32
617 closesocket(http->fd);
618 #else
619 close(http->fd);
620 #endif
622 http->fd = -1;
624 return (-1);
627 http->error = 0;
628 http->status = HTTP_CONTINUE;
630 #ifdef HAVE_SSL
631 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
634 * Always do encryption via SSL.
637 if (http_setup_ssl(http) != 0)
639 #ifdef WIN32
640 closesocket(http->fd);
641 #else
642 close(http->fd);
643 #endif /* WIN32 */
645 return (-1);
648 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
649 return (http_upgrade(http));
650 #endif /* HAVE_SSL */
652 return (0);
657 * 'httpGetSubField()' - Get a sub-field value.
660 char * /* O - Value or NULL */
661 httpGetSubField(http_t *http, /* I - HTTP data */
662 http_field_t field, /* I - Field index */
663 const char *name, /* I - Name of sub-field */
664 char *value) /* O - Value string */
666 const char *fptr; /* Pointer into field */
667 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
668 *ptr; /* Pointer into string buffer */
671 DEBUG_printf(("httpGetSubField(http=%p, field=%d, name=\"%s\", value=%p)\n",
672 http, field, name, value));
674 if (http == NULL ||
675 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
676 field > HTTP_FIELD_WWW_AUTHENTICATE ||
677 name == NULL || value == NULL)
678 return (NULL);
680 for (fptr = http->fields[field]; *fptr;)
683 * Skip leading whitespace...
686 while (isspace(*fptr & 255))
687 fptr ++;
689 if (*fptr == ',')
691 fptr ++;
692 continue;
696 * Get the sub-field name...
699 for (ptr = temp;
700 *fptr && *fptr != '=' && !isspace(*fptr & 255) && ptr < (temp + sizeof(temp) - 1);
701 *ptr++ = *fptr++);
703 *ptr = '\0';
705 DEBUG_printf(("httpGetSubField: name=\"%s\"\n", temp));
708 * Skip trailing chars up to the '='...
711 while (isspace(*fptr & 255))
712 fptr ++;
714 if (!*fptr)
715 break;
717 if (*fptr != '=')
718 continue;
721 * Skip = and leading whitespace...
724 fptr ++;
726 while (isspace(*fptr & 255))
727 fptr ++;
729 if (*fptr == '\"')
732 * Read quoted string...
735 for (ptr = value, fptr ++;
736 *fptr && *fptr != '\"' && ptr < (value + HTTP_MAX_VALUE - 1);
737 *ptr++ = *fptr++);
739 *ptr = '\0';
741 while (*fptr && *fptr != '\"')
742 fptr ++;
744 if (*fptr)
745 fptr ++;
747 else
750 * Read unquoted string...
753 for (ptr = value;
754 *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < (value + HTTP_MAX_VALUE - 1);
755 *ptr++ = *fptr++);
757 *ptr = '\0';
759 while (*fptr && !isspace(*fptr & 255) && *fptr != ',')
760 fptr ++;
763 DEBUG_printf(("httpGetSubField: value=\"%s\"\n", value));
766 * See if this is the one...
769 if (strcmp(name, temp) == 0)
770 return (value);
773 value[0] = '\0';
775 return (NULL);
780 * 'httpSetField()' - Set the value of an HTTP header.
783 void
784 httpSetField(http_t *http, /* I - HTTP data */
785 http_field_t field, /* I - Field index */
786 const char *value) /* I - Value */
788 if (http == NULL ||
789 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
790 field > HTTP_FIELD_WWW_AUTHENTICATE ||
791 value == NULL)
792 return;
794 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
799 * 'httpDelete()' - Send a DELETE request to the server.
802 int /* O - Status of call (0 = success) */
803 httpDelete(http_t *http, /* I - HTTP data */
804 const char *uri) /* I - URI to delete */
806 return (http_send(http, HTTP_DELETE, uri));
811 * 'httpGet()' - Send a GET request to the server.
814 int /* O - Status of call (0 = success) */
815 httpGet(http_t *http, /* I - HTTP data */
816 const char *uri) /* I - URI to get */
818 return (http_send(http, HTTP_GET, uri));
823 * 'httpHead()' - Send a HEAD request to the server.
826 int /* O - Status of call (0 = success) */
827 httpHead(http_t *http, /* I - HTTP data */
828 const char *uri) /* I - URI for head */
830 return (http_send(http, HTTP_HEAD, uri));
835 * 'httpOptions()' - Send an OPTIONS request to the server.
838 int /* O - Status of call (0 = success) */
839 httpOptions(http_t *http, /* I - HTTP data */
840 const char *uri) /* I - URI for options */
842 return (http_send(http, HTTP_OPTIONS, uri));
847 * 'httpPost()' - Send a POST request to the server.
850 int /* O - Status of call (0 = success) */
851 httpPost(http_t *http, /* I - HTTP data */
852 const char *uri) /* I - URI for post */
854 httpGetLength(http);
856 return (http_send(http, HTTP_POST, uri));
861 * 'httpPut()' - Send a PUT request to the server.
864 int /* O - Status of call (0 = success) */
865 httpPut(http_t *http, /* I - HTTP data */
866 const char *uri) /* I - URI to put */
868 httpGetLength(http);
870 return (http_send(http, HTTP_PUT, uri));
875 * 'httpTrace()' - Send an TRACE request to the server.
878 int /* O - Status of call (0 = success) */
879 httpTrace(http_t *http, /* I - HTTP data */
880 const char *uri) /* I - URI for trace */
882 return (http_send(http, HTTP_TRACE, uri));
887 * 'httpFlush()' - Flush data from a HTTP connection.
890 void
891 httpFlush(http_t *http) /* I - HTTP data */
893 char buffer[8192]; /* Junk buffer */
896 DEBUG_printf(("httpFlush(http=%p), state=%d\n", http, http->state));
898 while (httpRead(http, buffer, sizeof(buffer)) > 0);
903 * 'httpRead()' - Read data from a HTTP connection.
906 int /* O - Number of bytes read */
907 httpRead(http_t *http, /* I - HTTP data */
908 char *buffer, /* I - Buffer for data */
909 int length) /* I - Maximum number of bytes */
911 int bytes; /* Bytes read */
912 char len[32]; /* Length string */
915 DEBUG_printf(("httpRead(http=%p, buffer=%p, length=%d)\n",
916 http, buffer, length));
918 if (http == NULL || buffer == NULL)
919 return (-1);
921 http->activity = time(NULL);
923 if (length <= 0)
924 return (0);
926 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
927 http->data_remaining <= 0)
929 DEBUG_puts("httpRead: Getting chunk length...");
931 if (httpGets(len, sizeof(len), http) == NULL)
933 DEBUG_puts("httpRead: Could not get length!");
934 return (0);
937 http->data_remaining = strtol(len, NULL, 16);
938 if (http->data_remaining < 0)
940 DEBUG_puts("httpRead: Negative chunk length!");
941 return (0);
945 DEBUG_printf(("httpRead: data_remaining=%d\n", http->data_remaining));
947 if (http->data_remaining <= 0)
950 * A zero-length chunk ends a transfer; unless we are reading POST
951 * data, go idle...
954 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
955 httpGets(len, sizeof(len), http);
957 if (http->state == HTTP_POST_RECV)
958 http->state ++;
959 else
960 http->state = HTTP_WAITING;
963 * Prevent future reads for this request...
966 http->data_encoding = HTTP_ENCODE_LENGTH;
968 return (0);
970 else if (length > http->data_remaining)
971 length = http->data_remaining;
973 if (http->used == 0 && length <= 256)
976 * Buffer small reads for better performance...
979 if (!http->blocking && !httpWait(http, 1000))
980 return (0);
982 if (http->data_remaining > sizeof(http->buffer))
983 bytes = sizeof(http->buffer);
984 else
985 bytes = http->data_remaining;
987 #ifdef HAVE_SSL
988 if (http->tls)
989 bytes = http_read_ssl(http, http->buffer, bytes);
990 else
991 #endif /* HAVE_SSL */
993 DEBUG_printf(("httpRead: reading %d bytes from socket into buffer...\n",
994 bytes));
996 bytes = recv(http->fd, http->buffer, bytes, 0);
998 DEBUG_printf(("httpRead: read %d bytes from socket into buffer...\n",
999 bytes));
1000 #ifdef DEBUG_HTTP
1001 httpDumpData(stdout, "httpRead:", http->buffer, bytes);
1002 #endif
1005 if (bytes > 0)
1006 http->used = bytes;
1007 else if (bytes < 0)
1009 #ifdef WIN32
1010 http->error = WSAGetLastError();
1011 return (-1);
1012 #else
1013 if (errno != EINTR)
1015 http->error = errno;
1016 return (-1);
1018 #endif /* WIN32 */
1020 else
1022 http->error = EPIPE;
1023 return (0);
1027 if (http->used > 0)
1029 if (length > http->used)
1030 length = http->used;
1032 bytes = length;
1034 DEBUG_printf(("httpRead: grabbing %d bytes from input buffer...\n", bytes));
1036 memcpy(buffer, http->buffer, length);
1037 http->used -= length;
1039 if (http->used > 0)
1040 memmove(http->buffer, http->buffer + length, http->used);
1042 #ifdef HAVE_SSL
1043 else if (http->tls)
1045 if (!http->blocking && !httpWait(http, 1000))
1046 return (0);
1048 bytes = http_read_ssl(http, buffer, length);
1050 #endif /* HAVE_SSL */
1051 else
1053 if (!http->blocking && !httpWait(http, 1000))
1054 return (0);
1056 DEBUG_printf(("httpRead: reading %d bytes from socket...\n", length));
1058 while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
1059 if (errno != EINTR)
1060 break;
1061 DEBUG_printf(("httpRead: read %d bytes from socket...\n", bytes));
1063 #ifdef DEBUG_HTTP
1064 httpDumpData(stdout, "httpRead:", buffer, bytes);
1065 #endif
1067 if (bytes > 0)
1068 http->data_remaining -= bytes;
1069 else if (bytes < 0)
1071 #ifdef WIN32
1072 http->error = WSAGetLastError();
1073 #else
1074 if (errno == EINTR)
1075 bytes = 0;
1076 else
1077 http->error = errno;
1078 #endif /* WIN32 */
1080 else
1082 http->error = EPIPE;
1083 return (0);
1086 if (http->data_remaining == 0)
1088 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1089 httpGets(len, sizeof(len), http);
1091 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1093 if (http->state == HTTP_POST_RECV)
1094 http->state ++;
1095 else
1096 http->state = HTTP_WAITING;
1100 return (bytes);
1105 * 'httpSetCookie()' - Set the cookie value(s)...
1108 void
1109 httpSetCookie(http_t *http, /* I - Connection */
1110 const char *cookie) /* I - Cookie string */
1112 if (!http)
1113 return;
1115 if (http->cookie)
1116 free(http->cookie);
1118 if (cookie)
1119 http->cookie = strdup(cookie);
1120 else
1121 http->cookie = NULL;
1126 * 'httpWait()' - Wait for data available on a connection.
1129 int /* O - 1 if data is available, 0 otherwise */
1130 httpWait(http_t *http, /* I - HTTP data */
1131 int msec) /* I - Milliseconds to wait */
1134 * First see if there is data in the buffer...
1137 if (http == NULL)
1138 return (0);
1140 if (http->used)
1141 return (1);
1144 * If not, check the SSL/TLS buffers and do a select() on the connection...
1147 return (http_wait(http, msec));
1152 * 'httpWrite()' - Write data to a HTTP connection.
1155 int /* O - Number of bytes written */
1156 httpWrite(http_t *http, /* I - HTTP data */
1157 const char *buffer, /* I - Buffer for data */
1158 int length) /* I - Number of bytes to write */
1160 int tbytes, /* Total bytes sent */
1161 bytes; /* Bytes sent */
1164 if (http == NULL || buffer == NULL)
1165 return (-1);
1167 http->activity = time(NULL);
1169 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1171 if (httpPrintf(http, "%x\r\n", length) < 0)
1172 return (-1);
1174 if (length == 0)
1177 * A zero-length chunk ends a transfer; unless we are sending POST
1178 * or PUT data, go idle...
1181 DEBUG_printf(("httpWrite: changing states from %d", http->state));
1183 if (http->state == HTTP_POST_RECV)
1184 http->state ++;
1185 else if (http->state == HTTP_PUT_RECV)
1186 http->state = HTTP_STATUS;
1187 else
1188 http->state = HTTP_WAITING;
1189 DEBUG_printf((" to %d\n", http->state));
1191 if (httpPrintf(http, "\r\n") < 0)
1192 return (-1);
1194 return (0);
1198 tbytes = 0;
1200 while (length > 0)
1202 #ifdef HAVE_SSL
1203 if (http->tls)
1204 bytes = http_write_ssl(http, buffer, length);
1205 else
1206 #endif /* HAVE_SSL */
1207 bytes = send(http->fd, buffer, length, 0);
1209 #ifdef DEBUG_HTTP
1210 if (bytes >= 0)
1211 httpDumpData(stdout, "httpWrite:", buffer, bytes);
1212 #endif /* DEBUG */
1215 if (bytes < 0)
1217 #ifdef WIN32
1218 if (WSAGetLastError() != http->error)
1220 http->error = WSAGetLastError();
1221 continue;
1223 #else
1224 if (errno == EINTR)
1225 continue;
1226 else if (errno != http->error && errno != ECONNRESET)
1228 http->error = errno;
1229 continue;
1231 #endif /* WIN32 */
1233 DEBUG_puts("httpWrite: error writing data...\n");
1235 return (-1);
1238 buffer += bytes;
1239 tbytes += bytes;
1240 length -= bytes;
1241 if (http->data_encoding == HTTP_ENCODE_LENGTH)
1242 http->data_remaining -= bytes;
1245 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1246 if (httpPrintf(http, "\r\n") < 0)
1247 return (-1);
1249 if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODE_LENGTH)
1252 * Finished with the transfer; unless we are sending POST or PUT
1253 * data, go idle...
1256 DEBUG_printf(("httpWrite: changing states from %d", http->state));
1258 if (http->state == HTTP_POST_RECV)
1259 http->state ++;
1260 else if (http->state == HTTP_PUT_RECV)
1261 http->state = HTTP_STATUS;
1262 else
1263 http->state = HTTP_WAITING;
1265 DEBUG_printf((" to %d\n", http->state));
1268 return (tbytes);
1273 * 'httpGets()' - Get a line of text from a HTTP connection.
1276 char * /* O - Line or NULL */
1277 httpGets(char *line, /* I - Line to read into */
1278 int length, /* I - Max length of buffer */
1279 http_t *http) /* I - HTTP data */
1281 char *lineptr, /* Pointer into line */
1282 *bufptr, /* Pointer into input buffer */
1283 *bufend; /* Pointer to end of buffer */
1284 int bytes; /* Number of bytes read */
1287 DEBUG_printf(("httpGets(line=%p, length=%d, http=%p)\n", line, length, http));
1289 if (http == NULL || line == NULL)
1290 return (NULL);
1293 * Pre-scan the buffer and see if there is a newline in there...
1296 #ifdef WIN32
1297 WSASetLastError(0);
1298 #else
1299 errno = 0;
1300 #endif /* WIN32 */
1304 bufptr = http->buffer;
1305 bufend = http->buffer + http->used;
1307 while (bufptr < bufend)
1308 if (*bufptr == 0x0a)
1309 break;
1310 else
1311 bufptr ++;
1313 if (bufptr >= bufend && http->used < HTTP_MAX_BUFFER)
1316 * No newline; see if there is more data to be read...
1319 if (!http->blocking && !http_wait(http, 1000))
1320 return (NULL);
1322 #ifdef HAVE_SSL
1323 if (http->tls)
1324 bytes = http_read_ssl(http, bufend, HTTP_MAX_BUFFER - http->used);
1325 else
1326 #endif /* HAVE_SSL */
1327 bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0);
1329 DEBUG_printf(("httpGets: read %d bytes...\n", bytes));
1330 #ifdef DEBUG_HTTP
1331 httpDumpData(stdout, "httpGets:", bufend, bytes);
1332 #endif
1334 if (bytes < 0)
1337 * Nope, can't get a line this time...
1340 #ifdef WIN32
1341 if (WSAGetLastError() != http->error)
1343 http->error = WSAGetLastError();
1344 continue;
1347 DEBUG_printf(("httpGets: recv() error %d!\n", WSAGetLastError()));
1348 #else
1349 DEBUG_printf(("httpGets: recv() error %d!\n", errno));
1351 if (errno == EINTR)
1352 continue;
1353 else if (errno != http->error)
1355 http->error = errno;
1356 continue;
1358 #endif /* WIN32 */
1360 return (NULL);
1362 else if (bytes == 0)
1364 http->error = EPIPE;
1366 return (NULL);
1370 * Yup, update the amount used and the end pointer...
1373 http->used += bytes;
1374 bufend += bytes;
1375 bufptr = bufend;
1378 while (bufptr >= bufend && http->used < HTTP_MAX_BUFFER);
1380 http->activity = time(NULL);
1383 * Read a line from the buffer...
1386 lineptr = line;
1387 bufptr = http->buffer;
1388 bytes = 0;
1389 length --;
1391 while (bufptr < bufend && bytes < length)
1393 bytes ++;
1395 if (*bufptr == 0x0a)
1397 bufptr ++;
1398 break;
1400 else if (*bufptr == 0x0d)
1401 bufptr ++;
1402 else
1403 *lineptr++ = *bufptr++;
1406 if (bytes > 0)
1408 *lineptr = '\0';
1410 http->used -= bytes;
1411 if (http->used > 0)
1412 memmove(http->buffer, bufptr, http->used);
1414 DEBUG_printf(("httpGets: Returning \"%s\"\n", line));
1415 return (line);
1418 DEBUG_puts("httpGets: No new line available!");
1420 return (NULL);
1425 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
1428 int /* O - Number of bytes written */
1429 httpPrintf(http_t *http, /* I - HTTP data */
1430 const char *format, /* I - printf-style format string */
1431 ...) /* I - Additional args as needed */
1433 int bytes, /* Number of bytes to write */
1434 nbytes, /* Number of bytes written */
1435 tbytes; /* Number of bytes all together */
1436 char buf[HTTP_MAX_BUFFER], /* Buffer for formatted string */
1437 *bufptr; /* Pointer into buffer */
1438 va_list ap; /* Variable argument pointer */
1441 DEBUG_printf(("httpPrintf: httpPrintf(http=%p, format=\"%s\", ...)\n", http, format));
1443 va_start(ap, format);
1444 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1445 va_end(ap);
1447 DEBUG_printf(("httpPrintf: %s", buf));
1449 for (tbytes = 0, bufptr = buf; tbytes < bytes; tbytes += nbytes, bufptr += nbytes)
1451 #ifdef HAVE_SSL
1452 if (http->tls)
1453 nbytes = http_write_ssl(http, bufptr, bytes - tbytes);
1454 else
1455 #endif /* HAVE_SSL */
1456 nbytes = send(http->fd, bufptr, bytes - tbytes, 0);
1458 #ifdef DEBUG_HTTP
1459 if (nbytes >= 0)
1460 httpDumpData(stdout, "httpPrintf:", bufptr, nbytes);
1461 #endif
1463 if (nbytes < 0)
1465 nbytes = 0;
1467 #ifdef WIN32
1468 if (WSAGetLastError() != http->error)
1470 http->error = WSAGetLastError();
1471 continue;
1473 #else
1474 if (errno == EINTR)
1475 continue;
1476 else if (errno != http->error)
1478 http->error = errno;
1479 continue;
1481 #endif /* WIN32 */
1483 return (-1);
1487 return (bytes);
1492 * 'httpGetDateString()' - Get a formatted date/time string from a time value.
1495 const char * /* O - Date/time string */
1496 httpGetDateString(time_t t) /* I - UNIX time */
1498 struct tm *tdate;
1499 static char datetime[256];
1502 tdate = gmtime(&t);
1503 snprintf(datetime, sizeof(datetime), "%s, %02d %s %d %02d:%02d:%02d GMT",
1504 days[tdate->tm_wday], tdate->tm_mday, months[tdate->tm_mon],
1505 tdate->tm_year + 1900, tdate->tm_hour, tdate->tm_min, tdate->tm_sec);
1507 return (datetime);
1512 * 'httpGetDateTime()' - Get a time value from a formatted date/time string.
1515 time_t /* O - UNIX time */
1516 httpGetDateTime(const char *s) /* I - Date/time string */
1518 int i; /* Looping var */
1519 struct tm tdate; /* Time/date structure */
1520 char mon[16]; /* Abbreviated month name */
1521 int day, year; /* Day of month and year */
1522 int hour, min, sec; /* Time */
1525 if (sscanf(s, "%*s%d%15s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6)
1526 return (0);
1528 for (i = 0; i < 12; i ++)
1529 if (strcasecmp(mon, months[i]) == 0)
1530 break;
1532 if (i >= 12)
1533 return (0);
1535 tdate.tm_mon = i;
1536 tdate.tm_mday = day;
1537 tdate.tm_year = year - 1900;
1538 tdate.tm_hour = hour;
1539 tdate.tm_min = min;
1540 tdate.tm_sec = sec;
1541 tdate.tm_isdst = 0;
1543 return (mktime(&tdate));
1548 * 'httpUpdate()' - Update the current HTTP state for incoming data.
1551 http_status_t /* O - HTTP status */
1552 httpUpdate(http_t *http) /* I - HTTP data */
1554 char line[1024], /* Line from connection... */
1555 *value; /* Pointer to value on line */
1556 http_field_t field; /* Field index */
1557 int major, minor, /* HTTP version numbers */
1558 status; /* Request status */
1561 DEBUG_printf(("httpUpdate(http=%p), state=%d\n", http, http->state));
1564 * If we haven't issued any commands, then there is nothing to "update"...
1567 if (http->state == HTTP_WAITING)
1568 return (HTTP_CONTINUE);
1571 * Grab all of the lines we can from the connection...
1574 line[0] = '\0';
1575 while (httpGets(line, sizeof(line), http) != NULL)
1577 DEBUG_printf(("httpUpdate: Got \"%s\"\n", line));
1579 if (line[0] == '\0')
1582 * Blank line means the start of the data section (if any). Return
1583 * the result code, too...
1585 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
1586 * Instead, we just return HTTP_CONTINUE to the caller and keep on
1587 * tryin'...
1590 if (http->status == HTTP_CONTINUE)
1591 return (http->status);
1593 if (http->status < HTTP_BAD_REQUEST)
1594 http->digest_tries = 0;
1596 #ifdef HAVE_SSL
1597 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
1599 if (http_setup_ssl(http) != 0)
1601 # ifdef WIN32
1602 closesocket(http->fd);
1603 # else
1604 close(http->fd);
1605 # endif /* WIN32 */
1607 return (HTTP_ERROR);
1610 return (HTTP_CONTINUE);
1612 #endif /* HAVE_SSL */
1614 httpGetLength(http);
1616 switch (http->state)
1618 case HTTP_GET :
1619 case HTTP_POST :
1620 case HTTP_POST_RECV :
1621 case HTTP_PUT :
1622 http->state ++;
1623 case HTTP_POST_SEND :
1624 break;
1626 default :
1627 http->state = HTTP_WAITING;
1628 break;
1631 return (http->status);
1633 else if (strncmp(line, "HTTP/", 5) == 0)
1636 * Got the beginning of a response...
1639 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
1640 return (HTTP_ERROR);
1642 http->version = (http_version_t)(major * 100 + minor);
1643 http->status = (http_status_t)status;
1645 else if ((value = strchr(line, ':')) != NULL)
1648 * Got a value...
1651 *value++ = '\0';
1652 while (isspace(*value & 255))
1653 value ++;
1656 * Be tolerants of servers that send unknown attribute fields...
1659 if (!strcasecmp(line, "expect"))
1662 * "Expect: 100-continue" or similar...
1665 http->expect = (http_status_t)atoi(value);
1667 else if (!strcasecmp(line, "cookie"))
1670 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
1673 httpSetCookie(http, value);
1675 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
1677 DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line));
1678 continue;
1680 else
1681 httpSetField(http, field, value);
1683 else
1685 http->status = HTTP_ERROR;
1686 return (HTTP_ERROR);
1691 * See if there was an error...
1694 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
1695 return (http->status);
1697 if (http->error)
1699 DEBUG_printf(("httpUpdate: socket error %d - %s\n", http->error,
1700 strerror(http->error)));
1701 http->status = HTTP_ERROR;
1702 return (HTTP_ERROR);
1706 * If we haven't already returned, then there is nothing new...
1709 return (HTTP_CONTINUE);
1714 * 'httpDecode64()' - Base64-decode a string.
1717 char * /* O - Decoded string */
1718 httpDecode64(char *out, /* I - String to write to */
1719 const char *in) /* I - String to read from */
1721 int outlen; /* Output buffer length */
1725 * Use the old maximum buffer size for binary compatibility...
1728 outlen = 512;
1730 return (httpDecode64_2(out, &outlen, in));
1735 * 'httpDecode64_2()' - Base64-decode a string.
1738 char * /* O - Decoded string */
1739 httpDecode64_2(char *out, /* I - String to write to */
1740 int *outlen, /* IO - Size of output string */
1741 const char *in) /* I - String to read from */
1743 int pos, /* Bit position */
1744 base64; /* Value of this character */
1745 char *outptr, /* Output pointer */
1746 *outend; /* End of output buffer */
1750 * Range check input...
1753 if (!out || !outlen || *outlen < 1 || !in || !*in)
1754 return (NULL);
1757 * Convert from base-64 to bytes...
1760 for (outptr = out, outend = out + *outlen - 1, pos = 0; *in != '\0'; in ++)
1763 * Decode this character into a number from 0 to 63...
1766 if (*in >= 'A' && *in <= 'Z')
1767 base64 = *in - 'A';
1768 else if (*in >= 'a' && *in <= 'z')
1769 base64 = *in - 'a' + 26;
1770 else if (*in >= '0' && *in <= '9')
1771 base64 = *in - '0' + 52;
1772 else if (*in == '+')
1773 base64 = 62;
1774 else if (*in == '/')
1775 base64 = 63;
1776 else if (*in == '=')
1777 break;
1778 else
1779 continue;
1782 * Store the result in the appropriate chars...
1785 switch (pos)
1787 case 0 :
1788 if (outptr < outend)
1789 *outptr = base64 << 2;
1790 pos ++;
1791 break;
1792 case 1 :
1793 if (outptr < outend)
1794 *outptr++ |= (base64 >> 4) & 3;
1795 if (outptr < outend)
1796 *outptr = (base64 << 4) & 255;
1797 pos ++;
1798 break;
1799 case 2 :
1800 if (outptr < outend)
1801 *outptr++ |= (base64 >> 2) & 15;
1802 if (outptr < outend)
1803 *outptr = (base64 << 6) & 255;
1804 pos ++;
1805 break;
1806 case 3 :
1807 if (outptr < outend)
1808 *outptr++ |= base64;
1809 pos = 0;
1810 break;
1814 *outptr = '\0';
1817 * Return the decoded string and size...
1820 *outlen = (int)(outptr - out);
1822 return (out);
1827 * 'httpEncode64()' - Base64-encode a string.
1830 char * /* O - Encoded string */
1831 httpEncode64(char *out, /* I - String to write to */
1832 const char *in) /* I - String to read from */
1834 return (httpEncode64_2(out, 512, in, strlen(in)));
1839 * 'httpEncode64_2()' - Base64-encode a string.
1842 char * /* O - Encoded string */
1843 httpEncode64_2(char *out, /* I - String to write to */
1844 int outlen, /* I - Size of output string */
1845 const char *in, /* I - String to read from */
1846 int inlen) /* I - Size of input string */
1848 char *outptr, /* Output pointer */
1849 *outend; /* End of output buffer */
1850 static const char base64[] = /* Base64 characters... */
1852 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1853 "abcdefghijklmnopqrstuvwxyz"
1854 "0123456789"
1855 "+/"
1860 * Range check input...
1863 if (!out || outlen < 1 || !in || inlen < 1)
1864 return (NULL);
1867 * Convert bytes to base-64...
1870 for (outptr = out, outend = out + outlen - 1; inlen > 0; in ++, inlen --)
1873 * Encode the up to 3 characters as 4 Base64 numbers...
1876 if (outptr < outend)
1877 *outptr ++ = base64[(in[0] & 255) >> 2];
1878 if (outptr < outend)
1879 *outptr ++ = base64[(((in[0] & 255) << 4) | ((in[1] & 255) >> 4)) & 63];
1881 in ++;
1882 inlen --;
1883 if (inlen <= 0)
1885 if (outptr < outend)
1886 *outptr ++ = '=';
1887 if (outptr < outend)
1888 *outptr ++ = '=';
1889 break;
1892 if (outptr < outend)
1893 *outptr ++ = base64[(((in[0] & 255) << 2) | ((in[1] & 255) >> 6)) & 63];
1895 in ++;
1896 inlen --;
1897 if (inlen <= 0)
1899 if (outptr < outend)
1900 *outptr ++ = '=';
1901 break;
1904 if (outptr < outend)
1905 *outptr ++ = base64[in[0] & 63];
1908 *outptr = '\0';
1911 * Return the encoded string...
1914 return (out);
1919 * 'httpGetLength()' - Get the amount of data remaining from the
1920 * content-length or transfer-encoding fields.
1923 int /* O - Content length */
1924 httpGetLength(http_t *http) /* I - HTTP data */
1926 DEBUG_printf(("httpGetLength(http=%p), state=%d\n", http, http->state));
1928 if (strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked") == 0)
1930 DEBUG_puts("httpGetLength: chunked request!");
1932 http->data_encoding = HTTP_ENCODE_CHUNKED;
1933 http->data_remaining = 0;
1935 else
1937 http->data_encoding = HTTP_ENCODE_LENGTH;
1940 * The following is a hack for HTTP servers that don't send a
1941 * content-length or transfer-encoding field...
1943 * If there is no content-length then the connection must close
1944 * after the transfer is complete...
1947 if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
1948 http->data_remaining = 2147483647;
1949 else
1950 http->data_remaining = atoi(http->fields[HTTP_FIELD_CONTENT_LENGTH]);
1952 DEBUG_printf(("httpGetLength: content_length=%d\n", http->data_remaining));
1955 return (http->data_remaining);
1960 * 'http_field()' - Return the field index for a field name.
1963 static http_field_t /* O - Field index */
1964 http_field(const char *name) /* I - String name */
1966 int i; /* Looping var */
1969 for (i = 0; i < HTTP_FIELD_MAX; i ++)
1970 if (strcasecmp(name, http_fields[i]) == 0)
1971 return ((http_field_t)i);
1973 return (HTTP_FIELD_UNKNOWN);
1978 * 'http_send()' - Send a request with all fields and the trailing blank line.
1981 static int /* O - 0 on success, non-zero on error */
1982 http_send(http_t *http, /* I - HTTP data */
1983 http_state_t request, /* I - Request code */
1984 const char *uri) /* I - URI */
1986 int i; /* Looping var */
1987 char *ptr, /* Pointer in buffer */
1988 buf[1024]; /* Encoded URI buffer */
1989 static const char * const codes[] =
1990 { /* Request code strings */
1991 NULL,
1992 "OPTIONS",
1993 "GET",
1994 NULL,
1995 "HEAD",
1996 "POST",
1997 NULL,
1998 NULL,
1999 "PUT",
2000 NULL,
2001 "DELETE",
2002 "TRACE",
2003 "CLOSE"
2005 static const char hex[] = "0123456789ABCDEF";
2006 /* Hex digits */
2009 DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n",
2010 http, codes[request], uri));
2012 if (http == NULL || uri == NULL)
2013 return (-1);
2016 * Encode the URI as needed...
2019 for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++)
2020 if (*uri <= ' ' || *uri >= 127)
2022 if (ptr < (buf + sizeof(buf) - 1))
2023 *ptr ++ = '%';
2024 if (ptr < (buf + sizeof(buf) - 1))
2025 *ptr ++ = hex[(*uri >> 4) & 15];
2026 if (ptr < (buf + sizeof(buf) - 1))
2027 *ptr ++ = hex[*uri & 15];
2029 else
2030 *ptr ++ = *uri;
2032 *ptr = '\0';
2035 * See if we had an error the last time around; if so, reconnect...
2038 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
2039 httpReconnect(http);
2042 * Send the request header...
2045 http->state = request;
2046 if (request == HTTP_POST || request == HTTP_PUT)
2047 http->state ++;
2049 http->status = HTTP_CONTINUE;
2051 #ifdef HAVE_SSL
2052 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
2054 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
2055 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
2057 #endif /* HAVE_SSL */
2059 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
2061 http->status = HTTP_ERROR;
2062 return (-1);
2065 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2066 if (http->fields[i][0] != '\0')
2068 DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i]));
2070 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1)
2072 http->status = HTTP_ERROR;
2073 return (-1);
2077 if (httpPrintf(http, "\r\n") < 1)
2079 http->status = HTTP_ERROR;
2080 return (-1);
2083 httpClearFields(http);
2085 return (0);
2090 * 'http_wait()' - Wait for data available on a connection.
2093 static int /* O - 1 if data is available, 0 otherwise */
2094 http_wait(http_t *http, /* I - HTTP data */
2095 int msec) /* I - Milliseconds to wait */
2097 #ifndef WIN32
2098 struct rlimit limit; /* Runtime limit */
2099 #endif /* !WIN32 */
2100 struct timeval timeout; /* Timeout */
2101 int nfds; /* Result from select() */
2102 int set_size; /* Size of select set */
2105 DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
2108 * Check the SSL/TLS buffers for data first...
2111 #ifdef HAVE_SSL
2112 if (http->tls)
2114 # ifdef HAVE_LIBSSL
2115 if (SSL_pending((SSL *)(http->tls)))
2116 return (1);
2117 # elif defined(HAVE_GNUTLS)
2118 if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
2119 return (1);
2120 # elif defined(HAVE_CDSASSL)
2121 size_t bytes; /* Bytes that are available */
2123 if (!SSLGetBufferedReadSize((SSLContextRef)http->tls, &bytes) && bytes > 0)
2124 return;
2125 # endif /* HAVE_LIBSSL */
2127 #endif /* HAVE_SSL */
2130 * Then try doing a select() to poll the socket...
2133 if (!http->input_set)
2135 #ifdef WIN32
2137 * Windows has a fixed-size select() structure, different (surprise,
2138 * surprise!) from all UNIX implementations. Just allocate this
2139 * fixed structure...
2142 http->input_set = calloc(1, sizeof(fd_set));
2143 #else
2145 * Allocate the select() input set based upon the max number of file
2146 * descriptors available for this process...
2149 getrlimit(RLIMIT_NOFILE, &limit);
2151 set_size = (limit.rlim_cur + 31) / 8 + 4;
2152 if (set_size < sizeof(fd_set))
2153 set_size = sizeof(fd_set);
2155 http->input_set = calloc(1, set_size);
2156 #endif /* WIN32 */
2158 if (!http->input_set)
2159 return (0);
2164 FD_SET(http->fd, http->input_set);
2166 if (msec >= 0)
2168 timeout.tv_sec = msec / 1000;
2169 timeout.tv_usec = (msec % 1000) * 1000;
2171 nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout);
2173 else
2174 nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
2176 #ifdef WIN32
2177 while (nfds < 0 && WSAGetLastError() == WSAEINTR);
2178 #else
2179 while (nfds < 0 && errno == EINTR);
2180 #endif /* WIN32 */
2182 FD_CLR(http->fd, http->input_set);
2184 return (nfds > 0);
2188 #ifdef HAVE_SSL
2190 * 'http_upgrade()' - Force upgrade to TLS encryption.
2193 static int /* O - Status of connection */
2194 http_upgrade(http_t *http) /* I - HTTP data */
2196 int ret; /* Return value */
2197 http_t myhttp; /* Local copy of HTTP data */
2200 DEBUG_printf(("http_upgrade(%p)\n", http));
2203 * Copy the HTTP data to a local variable so we can do the OPTIONS
2204 * request without interfering with the existing request data...
2207 memcpy(&myhttp, http, sizeof(myhttp));
2210 * Send an OPTIONS request to the server, requiring SSL or TLS
2211 * encryption on the link...
2214 httpClearFields(&myhttp);
2215 httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade");
2216 httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
2218 if ((ret = httpOptions(&myhttp, "*")) == 0)
2221 * Wait for the secure connection...
2224 while (httpUpdate(&myhttp) == HTTP_CONTINUE);
2227 httpFlush(&myhttp);
2230 * Copy the HTTP data back over, if any...
2233 http->fd = myhttp.fd;
2234 http->error = myhttp.error;
2235 http->activity = myhttp.activity;
2236 http->status = myhttp.status;
2237 http->version = myhttp.version;
2238 http->keep_alive = myhttp.keep_alive;
2239 http->used = myhttp.used;
2241 if (http->used)
2242 memcpy(http->buffer, myhttp.buffer, http->used);
2244 http->auth_type = myhttp.auth_type;
2245 http->nonce_count = myhttp.nonce_count;
2247 memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce));
2249 http->tls = myhttp.tls;
2250 http->encryption = myhttp.encryption;
2253 * See if we actually went secure...
2256 if (!http->tls)
2259 * Server does not support HTTP upgrade...
2262 DEBUG_puts("Server does not support HTTP upgrade!");
2264 # ifdef WIN32
2265 closesocket(http->fd);
2266 # else
2267 close(http->fd);
2268 # endif
2270 http->fd = -1;
2272 return (-1);
2274 else
2275 return (ret);
2280 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
2283 static int /* O - Status of connection */
2284 http_setup_ssl(http_t *http) /* I - HTTP data */
2286 # ifdef HAVE_LIBSSL
2287 SSL_CTX *context; /* Context for encryption */
2288 SSL *conn; /* Connection for encryption */
2289 # elif defined(HAVE_GNUTLS)
2290 http_tls_t *conn; /* TLS session object */
2291 gnutls_certificate_client_credentials *credentials;
2292 /* TLS credentials */
2293 # elif defined(HAVE_CDSASSL)
2294 SSLContextRef conn; /* Context for encryption */
2295 OSStatus error; /* Error info */
2296 # endif /* HAVE_LIBSSL */
2299 DEBUG_printf(("http_setup_ssl(http=%p)\n", http));
2301 # ifdef HAVE_LIBSSL
2302 context = SSL_CTX_new(SSLv23_client_method());
2304 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
2306 conn = SSL_new(context);
2308 SSL_set_fd(conn, http->fd);
2309 if (SSL_connect(conn) != 1)
2311 # ifdef DEBUG
2312 unsigned long error; /* Error code */
2314 while ((error = ERR_get_error()) != 0)
2315 printf("http_setup_ssl: %s\n", ERR_error_string(error, NULL));
2316 # endif /* DEBUG */
2318 SSL_CTX_free(context);
2319 SSL_free(conn);
2321 # ifdef WIN32
2322 http->error = WSAGetLastError();
2323 # else
2324 http->error = errno;
2325 # endif /* WIN32 */
2326 http->status = HTTP_ERROR;
2328 return (HTTP_ERROR);
2331 # elif defined(HAVE_GNUTLS)
2332 conn = (http_tls_t *)malloc(sizeof(http_tls_t));
2334 if (conn == NULL)
2336 http->error = errno;
2337 http->status = HTTP_ERROR;
2339 return (-1);
2342 credentials = (gnutls_certificate_client_credentials *)
2343 malloc(sizeof(gnutls_certificate_client_credentials));
2344 if (credentials == NULL)
2346 free(conn);
2348 http->error = errno;
2349 http->status = HTTP_ERROR;
2351 return (-1);
2354 gnutls_certificate_allocate_credentials(credentials);
2356 gnutls_init(&(conn->session), GNUTLS_CLIENT);
2357 gnutls_set_default_priority(conn->session);
2358 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
2359 gnutls_transport_set_ptr(conn->session, http->fd);
2361 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
2363 http->error = errno;
2364 http->status = HTTP_ERROR;
2366 return (-1);
2369 conn->credentials = credentials;
2371 # elif defined(HAVE_CDSASSL)
2372 error = SSLNewContext(false, &conn);
2374 if (!error)
2375 error = SSLSetIOFuncs(conn, CDSAReadFunc, CDSAWriteFunc);
2377 if (!error)
2378 error = SSLSetConnection(conn, (SSLConnectionRef)http->fd);
2380 if (!error)
2381 error = SSLSetAllowsExpiredCerts(conn, true);
2383 if (!error)
2384 error = SSLSetAllowsAnyRoot(conn, true);
2386 if (!error)
2387 error = SSLHandshake(conn);
2389 if (error != 0)
2391 http->error = error;
2392 http->status = HTTP_ERROR;
2394 SSLDisposeContext(conn);
2396 close(http->fd);
2398 return (-1);
2400 # endif /* HAVE_CDSASSL */
2402 http->tls = conn;
2403 return (0);
2408 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
2411 static void
2412 http_shutdown_ssl(http_t *http) /* I - HTTP data */
2414 # ifdef HAVE_LIBSSL
2415 SSL_CTX *context; /* Context for encryption */
2416 SSL *conn; /* Connection for encryption */
2419 conn = (SSL *)(http->tls);
2420 context = SSL_get_SSL_CTX(conn);
2422 SSL_shutdown(conn);
2423 SSL_CTX_free(context);
2424 SSL_free(conn);
2426 # elif defined(HAVE_GNUTLS)
2427 http_tls_t *conn; /* Encryption session */
2428 gnutls_certificate_client_credentials *credentials;
2429 /* TLS credentials */
2432 conn = (http_tls_t *)(http->tls);
2433 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
2435 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
2436 gnutls_deinit(conn->session);
2437 gnutls_certificate_free_credentials(*credentials);
2438 free(credentials);
2439 free(conn);
2441 # elif defined(HAVE_CDSASSL)
2442 SSLClose((SSLContextRef)http->tls);
2443 SSLDisposeContext((SSLContextRef)http->tls);
2444 # endif /* HAVE_LIBSSL */
2446 http->tls = NULL;
2451 * 'http_read_ssl()' - Read from a SSL/TLS connection.
2454 static int /* O - Bytes read */
2455 http_read_ssl(http_t *http, /* I - HTTP data */
2456 char *buf, /* I - Buffer to store data */
2457 int len) /* I - Length of buffer */
2459 # if defined(HAVE_LIBSSL)
2460 return (SSL_read((SSL *)(http->tls), buf, len));
2462 # elif defined(HAVE_GNUTLS)
2463 return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
2465 # elif defined(HAVE_CDSASSL)
2466 OSStatus error; /* Error info */
2467 size_t processed; /* Number of bytes processed */
2470 error = SSLRead((SSLContextRef)http->tls, buf, len, &processed);
2472 if (error == 0)
2473 return (processed);
2474 else
2476 http->error = error;
2478 return (-1);
2480 # endif /* HAVE_LIBSSL */
2485 * 'http_write_ssl()' - Write to a SSL/TLS connection.
2488 static int /* O - Bytes written */
2489 http_write_ssl(http_t *http, /* I - HTTP data */
2490 const char *buf, /* I - Buffer holding data */
2491 int len) /* I - Length of buffer */
2493 # if defined(HAVE_LIBSSL)
2494 return (SSL_write((SSL *)(http->tls), buf, len));
2496 # elif defined(HAVE_GNUTLS)
2497 return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
2498 # elif defined(HAVE_CDSASSL)
2499 OSStatus error; /* Error info */
2500 size_t processed; /* Number of bytes processed */
2503 error = SSLWrite((SSLContextRef)http->tls, buf, len, &processed);
2505 if (error == 0)
2506 return (processed);
2507 else
2509 http->error = error;
2510 return (-1);
2512 # endif /* HAVE_LIBSSL */
2516 # if defined(HAVE_CDSASSL)
2518 * 'CDSAReadFunc()' - Read function for CDSA decryption code.
2521 static OSStatus /* O - -1 on error, 0 on success */
2522 CDSAReadFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */
2523 void *data, /* I - Data buffer */
2524 size_t *dataLength) /* IO - Number of bytes */
2526 ssize_t bytes; /* Number of bytes read */
2528 #ifdef DEBUG_HTTP
2529 httpDumpData(stdout, "CDSAReadFunc:", data, *dataLength);
2530 #endif
2531 bytes = recv((int)connection, data, *dataLength, 0);
2532 if (bytes >= 0)
2534 *dataLength = bytes;
2535 return (0);
2537 else
2538 return (-1);
2543 * 'CDSAWriteFunc()' - Write function for CDSA encryption code.
2546 static OSStatus /* O - -1 on error, 0 on success */
2547 CDSAWriteFunc(SSLConnectionRef connection, /* I - SSL/TLS connection */
2548 const void *data, /* I - Data buffer */
2549 size_t *dataLength) /* IO - Number of bytes */
2551 ssize_t bytes;
2554 bytes = write((int)connection, data, *dataLength);
2555 if (bytes >= 0)
2557 *dataLength = bytes;
2558 return (0);
2560 else
2561 return (-1);
2563 # endif /* HAVE_CDSASSL */
2564 #endif /* HAVE_SSL */
2568 * End of "$Id: http.c 148 2006-04-25 16:54:17Z njacobs $"