]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/http.c
Fix httpGets() bug caused by the line and newline(s) being sent in separate
[thirdparty/cups.git] / cups / http.c
1 /*
2 * "$Id: http.c,v 1.105 2002/10/30 20:04:56 mike Exp $"
3 *
4 * HTTP routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2002 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 }
900
901 DEBUG_printf(("httpRead: data_remaining = %d\n", http->data_remaining));
902
903 if (http->data_remaining == 0)
904 {
905 /*
906 * A zero-length chunk ends a transfer; unless we are reading POST
907 * data, go idle...
908 */
909
910 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
911 httpGets(len, sizeof(len), http);
912
913 if (http->state == HTTP_POST_RECV)
914 http->state ++;
915 else
916 http->state = HTTP_WAITING;
917
918 return (0);
919 }
920 else if (length > http->data_remaining)
921 length = http->data_remaining;
922
923 if (http->used == 0 && length <= 256)
924 {
925 /*
926 * Buffer small reads for better performance...
927 */
928
929 if (http->data_remaining > sizeof(http->buffer))
930 bytes = sizeof(http->buffer);
931 else
932 bytes = http->data_remaining;
933
934 #ifdef HAVE_LIBSSL
935 if (http->tls)
936 bytes = SSL_read((SSL *)(http->tls), http->buffer, bytes);
937 else
938 #endif /* HAVE_LIBSSL */
939 {
940 DEBUG_printf(("httpRead: reading %d bytes from socket into buffer...\n",
941 bytes));
942
943 bytes = recv(http->fd, http->buffer, bytes, 0);
944
945 DEBUG_printf(("httpRead: read %d bytes from socket into buffer...\n",
946 bytes));
947 }
948
949 if (bytes > 0)
950 http->used = bytes;
951 else if (bytes < 0)
952 {
953 #ifdef WIN32
954 http->error = WSAGetLastError();
955 return (-1);
956 #else
957 if (errno != EINTR)
958 {
959 http->error = errno;
960 return (-1);
961 }
962 #endif /* WIN32 */
963 }
964 else
965 return (0);
966 }
967
968 if (http->used > 0)
969 {
970 if (length > http->used)
971 length = http->used;
972
973 bytes = length;
974
975 DEBUG_printf(("httpRead: grabbing %d bytes from input buffer...\n", bytes));
976
977 memcpy(buffer, http->buffer, length);
978 http->used -= length;
979
980 if (http->used > 0)
981 memmove(http->buffer, http->buffer + length, http->used);
982 }
983 #ifdef HAVE_LIBSSL
984 else if (http->tls)
985 bytes = SSL_read((SSL *)(http->tls), buffer, length);
986 #endif /* HAVE_LIBSSL */
987 else
988 {
989 DEBUG_printf(("httpRead: reading %d bytes from socket...\n", length));
990 bytes = recv(http->fd, buffer, length, 0);
991 DEBUG_printf(("httpRead: read %d bytes from socket...\n", bytes));
992 }
993
994 if (bytes > 0)
995 http->data_remaining -= bytes;
996 else if (bytes < 0)
997 {
998 #ifdef WIN32
999 http->error = WSAGetLastError();
1000 #else
1001 if (errno == EINTR)
1002 bytes = 0;
1003 else
1004 http->error = errno;
1005 #endif /* WIN32 */
1006 }
1007
1008 if (http->data_remaining == 0)
1009 {
1010 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1011 httpGets(len, sizeof(len), http);
1012
1013 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1014 {
1015 if (http->state == HTTP_POST_RECV)
1016 http->state ++;
1017 else
1018 http->state = HTTP_WAITING;
1019 }
1020 }
1021
1022 #ifdef DEBUG
1023 {
1024 int i, j, ch;
1025 printf("httpRead: Read %d bytes:\n", bytes);
1026 for (i = 0; i < bytes; i += 16)
1027 {
1028 printf(" ");
1029
1030 for (j = 0; j < 16 && (i + j) < bytes; j ++)
1031 printf(" %02X", buffer[i + j] & 255);
1032
1033 while (j < 16)
1034 {
1035 printf(" ");
1036 j ++;
1037 }
1038
1039 printf(" ");
1040 for (j = 0; j < 16 && (i + j) < bytes; j ++)
1041 {
1042 ch = buffer[i + j] & 255;
1043
1044 if (ch < ' ' || ch == 127)
1045 ch = '.';
1046
1047 putchar(ch);
1048 }
1049 putchar('\n');
1050 }
1051 }
1052 #endif /* DEBUG */
1053
1054 return (bytes);
1055 }
1056
1057
1058 /*
1059 * 'httpWrite()' - Write data to a HTTP connection.
1060 */
1061
1062 int /* O - Number of bytes written */
1063 httpWrite(http_t *http, /* I - HTTP data */
1064 const char *buffer, /* I - Buffer for data */
1065 int length) /* I - Number of bytes to write */
1066 {
1067 int tbytes, /* Total bytes sent */
1068 bytes; /* Bytes sent */
1069
1070
1071 if (http == NULL || buffer == NULL)
1072 return (-1);
1073
1074 http->activity = time(NULL);
1075
1076 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1077 {
1078 if (httpPrintf(http, "%x\r\n", length) < 0)
1079 return (-1);
1080
1081 if (length == 0)
1082 {
1083 /*
1084 * A zero-length chunk ends a transfer; unless we are sending POST
1085 * data, go idle...
1086 */
1087
1088 DEBUG_puts("httpWrite: changing states...");
1089
1090 if (http->state == HTTP_POST_RECV)
1091 http->state ++;
1092 else if (http->state == HTTP_PUT_RECV)
1093 http->state = HTTP_STATUS;
1094 else
1095 http->state = HTTP_WAITING;
1096
1097 if (httpPrintf(http, "\r\n") < 0)
1098 return (-1);
1099
1100 return (0);
1101 }
1102 }
1103
1104 tbytes = 0;
1105
1106 while (length > 0)
1107 {
1108 #ifdef HAVE_LIBSSL
1109 if (http->tls)
1110 bytes = SSL_write((SSL *)(http->tls), buffer, length);
1111 else
1112 #endif /* HAVE_LIBSSL */
1113 bytes = send(http->fd, buffer, length, 0);
1114
1115 if (bytes < 0)
1116 {
1117 #ifdef WIN32
1118 if (WSAGetLastError() != http->error)
1119 {
1120 http->error = WSAGetLastError();
1121 continue;
1122 }
1123 #else
1124 if (errno == EINTR)
1125 continue;
1126 else if (errno != http->error)
1127 {
1128 http->error = errno;
1129 continue;
1130 }
1131 #endif /* WIN32 */
1132
1133 DEBUG_puts("httpWrite: error writing data...\n");
1134
1135 return (-1);
1136 }
1137
1138 buffer += bytes;
1139 tbytes += bytes;
1140 length -= bytes;
1141 if (http->data_encoding == HTTP_ENCODE_LENGTH)
1142 http->data_remaining -= bytes;
1143 }
1144
1145 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1146 if (httpPrintf(http, "\r\n") < 0)
1147 return (-1);
1148
1149 if (http->data_remaining == 0 && http->data_encoding == HTTP_ENCODE_LENGTH)
1150 {
1151 /*
1152 * Finished with the transfer; unless we are sending POST data, go idle...
1153 */
1154
1155 DEBUG_puts("httpWrite: changing states...");
1156
1157 if (http->state == HTTP_POST_RECV)
1158 http->state ++;
1159 else
1160 http->state = HTTP_WAITING;
1161 }
1162
1163 #ifdef DEBUG
1164 {
1165 int i, j, ch;
1166 printf("httpWrite: wrote %d bytes: \n", tbytes);
1167 for (i = 0, buffer -= tbytes; i < tbytes; i += 16)
1168 {
1169 printf(" ");
1170
1171 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
1172 printf(" %02X", buffer[i + j] & 255);
1173
1174 while (j < 16)
1175 {
1176 printf(" ");
1177 j ++;
1178 }
1179
1180 printf(" ");
1181 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
1182 {
1183 ch = buffer[i + j] & 255;
1184
1185 if (ch < ' ' || ch == 127)
1186 ch = '.';
1187
1188 putchar(ch);
1189 }
1190 putchar('\n');
1191 }
1192 }
1193 #endif /* DEBUG */
1194 return (tbytes);
1195 }
1196
1197
1198 /*
1199 * 'httpGets()' - Get a line of text from a HTTP connection.
1200 */
1201
1202 char * /* O - Line or NULL */
1203 httpGets(char *line, /* I - Line to read into */
1204 int length, /* I - Max length of buffer */
1205 http_t *http) /* I - HTTP data */
1206 {
1207 char *lineptr, /* Pointer into line */
1208 *bufptr, /* Pointer into input buffer */
1209 *bufend; /* Pointer to end of buffer */
1210 int bytes; /* Number of bytes read */
1211
1212
1213 DEBUG_printf(("httpGets(%p, %d, %p)\n", line, length, http));
1214
1215 if (http == NULL || line == NULL)
1216 return (NULL);
1217
1218 /*
1219 * Pre-scan the buffer and see if there is a newline in there...
1220 */
1221
1222 #ifdef WIN32
1223 WSASetLastError(0);
1224 #else
1225 errno = 0;
1226 #endif /* WIN32 */
1227
1228 do
1229 {
1230 bufptr = http->buffer;
1231 bufend = http->buffer + http->used;
1232
1233 while (bufptr < bufend)
1234 if (*bufptr == 0x0a)
1235 break;
1236 else
1237 bufptr ++;
1238
1239 if (bufptr >= bufend && http->used < HTTP_MAX_BUFFER)
1240 {
1241 /*
1242 * No newline; see if there is more data to be read...
1243 */
1244
1245 #ifdef HAVE_LIBSSL
1246 if (http->tls)
1247 bytes = SSL_read((SSL *)(http->tls), bufend,
1248 HTTP_MAX_BUFFER - http->used);
1249 else
1250 #endif /* HAVE_LIBSSL */
1251 bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0);
1252
1253 if (bytes < 0)
1254 {
1255 /*
1256 * Nope, can't get a line this time...
1257 */
1258
1259 #ifdef WIN32
1260 if (WSAGetLastError() != http->error)
1261 {
1262 http->error = WSAGetLastError();
1263 continue;
1264 }
1265
1266 DEBUG_printf(("httpGets(): recv() error %d!\n", WSAGetLastError()));
1267 #else
1268 if (errno == EINTR)
1269 continue;
1270 else if (errno != http->error)
1271 {
1272 http->error = errno;
1273 continue;
1274 }
1275
1276 DEBUG_printf(("httpGets(): recv() error %d!\n", errno));
1277 #endif /* WIN32 */
1278
1279 return (NULL);
1280 }
1281 else if (bytes == 0)
1282 {
1283 if (http->blocking)
1284 http->error = EPIPE;
1285
1286 return (NULL);
1287 }
1288
1289 /*
1290 * Yup, update the amount used and the end pointer...
1291 */
1292
1293 http->used += bytes;
1294 bufend += bytes;
1295 bufptr = bufend;
1296 }
1297 }
1298 while (bufptr >= bufend && http->used < HTTP_MAX_BUFFER);
1299
1300 http->activity = time(NULL);
1301
1302 /*
1303 * Read a line from the buffer...
1304 */
1305
1306 lineptr = line;
1307 bufptr = http->buffer;
1308 bytes = 0;
1309 length --;
1310
1311 while (bufptr < bufend && bytes < length)
1312 {
1313 bytes ++;
1314
1315 if (*bufptr == 0x0a)
1316 {
1317 bufptr ++;
1318 break;
1319 }
1320 else if (*bufptr == 0x0d)
1321 bufptr ++;
1322 else
1323 *lineptr++ = *bufptr++;
1324 }
1325
1326 if (bytes > 0)
1327 {
1328 *lineptr = '\0';
1329
1330 http->used -= bytes;
1331 if (http->used > 0)
1332 memmove(http->buffer, bufptr, http->used);
1333
1334 DEBUG_printf(("httpGets(): Returning \"%s\"\n", line));
1335 return (line);
1336 }
1337
1338 DEBUG_puts("httpGets(): No new line available!");
1339
1340 return (NULL);
1341 }
1342
1343
1344 /*
1345 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
1346 */
1347
1348 int /* O - Number of bytes written */
1349 httpPrintf(http_t *http, /* I - HTTP data */
1350 const char *format, /* I - printf-style format string */
1351 ...) /* I - Additional args as needed */
1352 {
1353 int bytes, /* Number of bytes to write */
1354 nbytes, /* Number of bytes written */
1355 tbytes; /* Number of bytes all together */
1356 char buf[HTTP_MAX_BUFFER], /* Buffer for formatted string */
1357 *bufptr; /* Pointer into buffer */
1358 va_list ap; /* Variable argument pointer */
1359
1360
1361 va_start(ap, format);
1362 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1363 va_end(ap);
1364
1365 DEBUG_printf(("httpPrintf: %s", buf));
1366
1367 for (tbytes = 0, bufptr = buf; tbytes < bytes; tbytes += nbytes, bufptr += nbytes)
1368 {
1369 #ifdef HAVE_LIBSSL
1370 if (http->tls)
1371 nbytes = SSL_write((SSL *)(http->tls), bufptr, bytes - tbytes);
1372 else
1373 #endif /* HAVE_LIBSSL */
1374 nbytes = send(http->fd, bufptr, bytes - tbytes, 0);
1375
1376 if (nbytes < 0)
1377 {
1378 nbytes = 0;
1379
1380 #ifdef WIN32
1381 if (WSAGetLastError() != http->error)
1382 {
1383 http->error = WSAGetLastError();
1384 continue;
1385 }
1386 #else
1387 if (errno == EINTR)
1388 continue;
1389 else if (errno != http->error)
1390 {
1391 http->error = errno;
1392 continue;
1393 }
1394 #endif /* WIN32 */
1395
1396 return (-1);
1397 }
1398 }
1399
1400 return (bytes);
1401 }
1402
1403
1404 /*
1405 * 'httpGetDateString()' - Get a formatted date/time string from a time value.
1406 */
1407
1408 const char * /* O - Date/time string */
1409 httpGetDateString(time_t t) /* I - UNIX time */
1410 {
1411 struct tm *tdate;
1412 static char datetime[256];
1413
1414
1415 tdate = gmtime(&t);
1416 snprintf(datetime, sizeof(datetime), "%s, %02d %s %d %02d:%02d:%02d GMT",
1417 days[tdate->tm_wday], tdate->tm_mday, months[tdate->tm_mon],
1418 tdate->tm_year + 1900, tdate->tm_hour, tdate->tm_min, tdate->tm_sec);
1419
1420 return (datetime);
1421 }
1422
1423
1424 /*
1425 * 'httpGetDateTime()' - Get a time value from a formatted date/time string.
1426 */
1427
1428 time_t /* O - UNIX time */
1429 httpGetDateTime(const char *s) /* I - Date/time string */
1430 {
1431 int i; /* Looping var */
1432 struct tm tdate; /* Time/date structure */
1433 char mon[16]; /* Abbreviated month name */
1434 int day, year; /* Day of month and year */
1435 int hour, min, sec; /* Time */
1436
1437
1438 if (sscanf(s, "%*s%d%15s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6)
1439 return (0);
1440
1441 for (i = 0; i < 12; i ++)
1442 if (strcasecmp(mon, months[i]) == 0)
1443 break;
1444
1445 if (i >= 12)
1446 return (0);
1447
1448 tdate.tm_mon = i;
1449 tdate.tm_mday = day;
1450 tdate.tm_year = year - 1900;
1451 tdate.tm_hour = hour;
1452 tdate.tm_min = min;
1453 tdate.tm_sec = sec;
1454 tdate.tm_isdst = 0;
1455
1456 return (mktime(&tdate));
1457 }
1458
1459
1460 /*
1461 * 'httpUpdate()' - Update the current HTTP state for incoming data.
1462 */
1463
1464 http_status_t /* O - HTTP status */
1465 httpUpdate(http_t *http) /* I - HTTP data */
1466 {
1467 char line[1024], /* Line from connection... */
1468 *value; /* Pointer to value on line */
1469 http_field_t field; /* Field index */
1470 int major, minor; /* HTTP version numbers */
1471 http_status_t status; /* Authorization status */
1472 #ifdef HAVE_LIBSSL
1473 SSL_CTX *context; /* Context for encryption */
1474 SSL *conn; /* Connection for encryption */
1475 #endif /* HAVE_LIBSSL */
1476
1477
1478 DEBUG_printf(("httpUpdate(%p)\n", http));
1479
1480 /*
1481 * If we haven't issued any commands, then there is nothing to "update"...
1482 */
1483
1484 if (http->state == HTTP_WAITING)
1485 return (HTTP_CONTINUE);
1486
1487 /*
1488 * Grab all of the lines we can from the connection...
1489 */
1490
1491 while (httpGets(line, sizeof(line), http) != NULL)
1492 {
1493 DEBUG_puts(line);
1494
1495 if (line[0] == '\0')
1496 {
1497 /*
1498 * Blank line means the start of the data section (if any). Return
1499 * the result code, too...
1500 *
1501 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
1502 * Instead, we just return HTTP_CONTINUE to the caller and keep on
1503 * tryin'...
1504 */
1505
1506 if (http->status == HTTP_CONTINUE)
1507 return (http->status);
1508
1509 #ifdef HAVE_LIBSSL
1510 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
1511 {
1512 context = SSL_CTX_new(SSLv23_method());
1513 conn = SSL_new(context);
1514
1515 SSL_set_fd(conn, http->fd);
1516 if (SSL_connect(conn) != 1)
1517 {
1518 SSL_CTX_free(context);
1519 SSL_free(conn);
1520
1521 #ifdef WIN32
1522 http->error = WSAGetLastError();
1523 #else
1524 http->error = errno;
1525 #endif /* WIN32 */
1526 http->status = HTTP_ERROR;
1527
1528 #ifdef WIN32
1529 closesocket(http->fd);
1530 #else
1531 close(http->fd);
1532 #endif
1533
1534 return (HTTP_ERROR);
1535 }
1536
1537 http->tls = conn;
1538
1539 return (HTTP_CONTINUE);
1540 }
1541 #endif /* HAVE_LIBSSL */
1542
1543 httpGetLength(http);
1544
1545 switch (http->state)
1546 {
1547 case HTTP_GET :
1548 case HTTP_POST :
1549 case HTTP_POST_RECV :
1550 case HTTP_PUT :
1551 http->state ++;
1552 break;
1553
1554 default :
1555 http->state = HTTP_WAITING;
1556 break;
1557 }
1558
1559 return (http->status);
1560 }
1561 else if (strncmp(line, "HTTP/", 5) == 0)
1562 {
1563 /*
1564 * Got the beginning of a response...
1565 */
1566
1567 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, (int *)&status) != 3)
1568 return (HTTP_ERROR);
1569
1570 http->version = (http_version_t)(major * 100 + minor);
1571 http->status = status;
1572 }
1573 else if ((value = strchr(line, ':')) != NULL)
1574 {
1575 /*
1576 * Got a value...
1577 */
1578
1579 *value++ = '\0';
1580 while (isspace(*value))
1581 value ++;
1582
1583 /*
1584 * Be tolerants of servers that send unknown attribute fields...
1585 */
1586
1587 if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
1588 {
1589 DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line));
1590 continue;
1591 }
1592
1593 httpSetField(http, field, value);
1594 }
1595 else
1596 {
1597 http->status = HTTP_ERROR;
1598 return (HTTP_ERROR);
1599 }
1600 }
1601
1602 /*
1603 * See if there was an error...
1604 */
1605
1606 if (http->error)
1607 {
1608 http->status = HTTP_ERROR;
1609 return (HTTP_ERROR);
1610 }
1611
1612 /*
1613 * If we haven't already returned, then there is nothing new...
1614 */
1615
1616 return (HTTP_CONTINUE);
1617 }
1618
1619
1620 /*
1621 * 'httpDecode64()' - Base64-decode a string.
1622 */
1623
1624 char * /* O - Decoded string */
1625 httpDecode64(char *out, /* I - String to write to */
1626 const char *in) /* I - String to read from */
1627 {
1628 int pos, /* Bit position */
1629 base64; /* Value of this character */
1630 char *outptr; /* Output pointer */
1631
1632
1633 for (outptr = out, pos = 0; *in != '\0'; in ++)
1634 {
1635 /*
1636 * Decode this character into a number from 0 to 63...
1637 */
1638
1639 if (*in >= 'A' && *in <= 'Z')
1640 base64 = *in - 'A';
1641 else if (*in >= 'a' && *in <= 'z')
1642 base64 = *in - 'a' + 26;
1643 else if (*in >= '0' && *in <= '9')
1644 base64 = *in - '0' + 52;
1645 else if (*in == '+')
1646 base64 = 62;
1647 else if (*in == '/')
1648 base64 = 63;
1649 else if (*in == '=')
1650 break;
1651 else
1652 continue;
1653
1654 /*
1655 * Store the result in the appropriate chars...
1656 */
1657
1658 switch (pos)
1659 {
1660 case 0 :
1661 *outptr = base64 << 2;
1662 pos ++;
1663 break;
1664 case 1 :
1665 *outptr++ |= (base64 >> 4) & 3;
1666 *outptr = (base64 << 4) & 255;
1667 pos ++;
1668 break;
1669 case 2 :
1670 *outptr++ |= (base64 >> 2) & 15;
1671 *outptr = (base64 << 6) & 255;
1672 pos ++;
1673 break;
1674 case 3 :
1675 *outptr++ |= base64;
1676 pos = 0;
1677 break;
1678 }
1679 }
1680
1681 *outptr = '\0';
1682
1683 /*
1684 * Return the decoded string...
1685 */
1686
1687 return (out);
1688 }
1689
1690
1691 /*
1692 * 'httpEncode64()' - Base64-encode a string.
1693 */
1694
1695 char * /* O - Encoded string */
1696 httpEncode64(char *out, /* I - String to write to */
1697 const char *in) /* I - String to read from */
1698 {
1699 char *outptr; /* Output pointer */
1700 static char base64[] = /* Base64 characters... */
1701 {
1702 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1703 "abcdefghijklmnopqrstuvwxyz"
1704 "0123456789"
1705 "+/"
1706 };
1707
1708
1709 for (outptr = out; *in != '\0'; in ++)
1710 {
1711 /*
1712 * Encode the up to 3 characters as 4 Base64 numbers...
1713 */
1714
1715 *outptr ++ = base64[in[0] >> 2];
1716 *outptr ++ = base64[((in[0] << 4) | (in[1] >> 4)) & 63];
1717
1718 in ++;
1719 if (*in == '\0')
1720 {
1721 *outptr ++ = '=';
1722 break;
1723 }
1724
1725 *outptr ++ = base64[((in[0] << 2) | (in[1] >> 6)) & 63];
1726
1727 in ++;
1728 if (*in == '\0')
1729 break;
1730
1731 *outptr ++ = base64[in[0] & 63];
1732 }
1733
1734 *outptr ++ = '=';
1735 *outptr = '\0';
1736
1737 /*
1738 * Return the encoded string...
1739 */
1740
1741 return (out);
1742 }
1743
1744
1745 /*
1746 * 'httpGetLength()' - Get the amount of data remaining from the
1747 * content-length or transfer-encoding fields.
1748 */
1749
1750 int /* O - Content length */
1751 httpGetLength(http_t *http) /* I - HTTP data */
1752 {
1753 DEBUG_printf(("httpGetLength(%p)\n", http));
1754
1755 if (strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked") == 0)
1756 {
1757 DEBUG_puts("httpGetLength: chunked request!");
1758
1759 http->data_encoding = HTTP_ENCODE_CHUNKED;
1760 http->data_remaining = 0;
1761 }
1762 else
1763 {
1764 http->data_encoding = HTTP_ENCODE_LENGTH;
1765
1766 /*
1767 * The following is a hack for HTTP servers that don't send a
1768 * content-length or transfer-encoding field...
1769 *
1770 * If there is no content-length then the connection must close
1771 * after the transfer is complete...
1772 */
1773
1774 if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
1775 http->data_remaining = 2147483647;
1776 else
1777 http->data_remaining = atoi(http->fields[HTTP_FIELD_CONTENT_LENGTH]);
1778
1779 DEBUG_printf(("httpGetLength: content_length = %d\n", http->data_remaining));
1780 }
1781
1782 return (http->data_remaining);
1783 }
1784
1785
1786 /*
1787 * 'http_field()' - Return the field index for a field name.
1788 */
1789
1790 static http_field_t /* O - Field index */
1791 http_field(const char *name) /* I - String name */
1792 {
1793 int i; /* Looping var */
1794
1795
1796 for (i = 0; i < HTTP_FIELD_MAX; i ++)
1797 if (strcasecmp(name, http_fields[i]) == 0)
1798 return ((http_field_t)i);
1799
1800 return (HTTP_FIELD_UNKNOWN);
1801 }
1802
1803
1804 /*
1805 * 'http_send()' - Send a request with all fields and the trailing blank line.
1806 */
1807
1808 static int /* O - 0 on success, non-zero on error */
1809 http_send(http_t *http, /* I - HTTP data */
1810 http_state_t request, /* I - Request code */
1811 const char *uri) /* I - URI */
1812 {
1813 int i; /* Looping var */
1814 char *ptr, /* Pointer in buffer */
1815 buf[1024]; /* Encoded URI buffer */
1816 static const char *codes[] = /* Request code strings */
1817 {
1818 NULL,
1819 "OPTIONS",
1820 "GET",
1821 NULL,
1822 "HEAD",
1823 "POST",
1824 NULL,
1825 NULL,
1826 "PUT",
1827 NULL,
1828 "DELETE",
1829 "TRACE",
1830 "CLOSE"
1831 };
1832 static const char *hex = "0123456789ABCDEF";
1833 /* Hex digits */
1834
1835
1836 if (http == NULL || uri == NULL)
1837 return (-1);
1838
1839 /*
1840 * Encode the URI as needed...
1841 */
1842
1843 for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++)
1844 if (*uri <= ' ' || *uri >= 127)
1845 {
1846 if (ptr < (buf + sizeof(buf) - 1))
1847 *ptr ++ = '%';
1848 if (ptr < (buf + sizeof(buf) - 1))
1849 *ptr ++ = hex[(*uri >> 4) & 15];
1850 if (ptr < (buf + sizeof(buf) - 1))
1851 *ptr ++ = hex[*uri & 15];
1852 }
1853 else
1854 *ptr ++ = *uri;
1855
1856 *ptr = '\0';
1857
1858 /*
1859 * See if we had an error the last time around; if so, reconnect...
1860 */
1861
1862 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
1863 httpReconnect(http);
1864
1865 /*
1866 * Send the request header...
1867 */
1868
1869 http->state = request;
1870 if (request == HTTP_POST || request == HTTP_PUT)
1871 http->state ++;
1872
1873 http->status = HTTP_CONTINUE;
1874
1875 #ifdef HAVE_LIBSSL
1876 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
1877 {
1878 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
1879 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
1880 }
1881 #endif /* HAVE_LIBSSL */
1882
1883 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
1884 {
1885 http->status = HTTP_ERROR;
1886 return (-1);
1887 }
1888
1889 for (i = 0; i < HTTP_FIELD_MAX; i ++)
1890 if (http->fields[i][0] != '\0')
1891 {
1892 DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i]));
1893
1894 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1)
1895 {
1896 http->status = HTTP_ERROR;
1897 return (-1);
1898 }
1899 }
1900
1901 if (httpPrintf(http, "\r\n") < 1)
1902 {
1903 http->status = HTTP_ERROR;
1904 return (-1);
1905 }
1906
1907 httpClearFields(http);
1908
1909 return (0);
1910 }
1911
1912
1913 #ifdef HAVE_LIBSSL
1914 /*
1915 * 'http_upgrade()' - Force upgrade to TLS encryption.
1916 */
1917
1918 static int /* O - Status of connection */
1919 http_upgrade(http_t *http) /* I - HTTP data */
1920 {
1921 int ret; /* Return value */
1922 http_t myhttp; /* Local copy of HTTP data */
1923
1924
1925 DEBUG_printf(("http_upgrade(%p)\n", http));
1926
1927 /*
1928 * Copy the HTTP data to a local variable so we can do the OPTIONS
1929 * request without interfering with the existing request data...
1930 */
1931
1932 memcpy(&myhttp, http, sizeof(myhttp));
1933
1934 /*
1935 * Send an OPTIONS request to the server, requiring SSL or TLS
1936 * encryption on the link...
1937 */
1938
1939 httpClearFields(&myhttp);
1940 httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade");
1941 httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
1942
1943 if ((ret = httpOptions(&myhttp, "*")) == 0)
1944 {
1945 /*
1946 * Wait for the secure connection...
1947 */
1948
1949 while (httpUpdate(&myhttp) == HTTP_CONTINUE);
1950 }
1951
1952 httpFlush(&myhttp);
1953
1954 /*
1955 * Copy the HTTP data back over, if any...
1956 */
1957
1958 http->fd = myhttp.fd;
1959 http->error = myhttp.error;
1960 http->activity = myhttp.activity;
1961 http->status = myhttp.status;
1962 http->version = myhttp.version;
1963 http->keep_alive = myhttp.keep_alive;
1964 http->used = myhttp.used;
1965
1966 if (http->used)
1967 memcpy(http->buffer, myhttp.buffer, http->used);
1968
1969 http->auth_type = myhttp.auth_type;
1970 http->nonce_count = myhttp.nonce_count;
1971
1972 memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce));
1973
1974 http->tls = myhttp.tls;
1975 http->encryption = myhttp.encryption;
1976
1977 /*
1978 * See if we actually went secure...
1979 */
1980
1981 if (!http->tls)
1982 {
1983 /*
1984 * Server does not support HTTP upgrade...
1985 */
1986
1987 DEBUG_puts("Server does not support HTTP upgrade!");
1988
1989 #ifdef WIN32
1990 closesocket(http->fd);
1991 #else
1992 close(http->fd);
1993 #endif
1994
1995 http->fd = -1;
1996
1997 return (-1);
1998 }
1999 else
2000 return (ret);
2001 }
2002 #endif /* HAVE_LIBSSL */
2003
2004
2005 /*
2006 * End of "$Id: http.c,v 1.105 2002/10/30 20:04:56 mike Exp $".
2007 */