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