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