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