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