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