]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/http.c
9180c8d70765cc6cced483e2def2002ce851966c
[thirdparty/cups.git] / cups / http.c
1 /*
2 * "$Id$"
3 *
4 * HTTP routines for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 1997-2005 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 USA
19 *
20 * Voice: (301) 373-9600
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 * httpCheck() - Check to see if there is a pending response from
29 * the server.
30 * httpClearCookie() - Clear the cookie value(s).
31 * httpClose() - Close an HTTP connection...
32 * httpConnect() - Connect to a HTTP server.
33 * httpConnectEncrypt() - Connect to a HTTP server using encryption.
34 * httpDecode64() - Base64-decode a string.
35 * httpDecode64_2() - Base64-decode a string.
36 * httpDelete() - Send a DELETE request to the server.
37 * httpEncode64() - Base64-encode a string.
38 * httpEncode64_2() - Base64-encode a string.
39 * httpEncryption() - Set the required encryption on the link.
40 * httpFlush() - Flush data from a HTTP connection.
41 * httpFlushWrite() - Flush data in write buffer.
42 * httpGet() - Send a GET request to the server.
43 * httpGetDateString() - Get a formatted date/time string from a time value.
44 * httpGetDateString2() - Get a formatted date/time string from a time value.
45 * httpGetDateTime() - Get a time value from a formatted date/time string.
46 * httpGetLength() - Get the amount of data remaining from the
47 * content-length or transfer-encoding fields.
48 * httpGetSubField() - Get a sub-field value.
49 * httpGets() - Get a line of text from a HTTP connection.
50 * httpHead() - Send a HEAD request to the server.
51 * httpInitialize() - Initialize the HTTP interface library and set the
52 * default HTTP proxy (if any).
53 * httpOptions() - Send an OPTIONS request to the server.
54 * httpPost() - Send a POST request to the server.
55 * httpPrintf() - Print a formatted string to a HTTP connection.
56 * httpPut() - Send a PUT request to the server.
57 * httpRead() - Read data from a HTTP connection.
58 * httpReconnect() - Reconnect to a HTTP server...
59 * httpSetCookie() - Set the cookie value(s)...
60 * httpSetField() - Set the value of an HTTP header.
61 * httpTrace() - Send an TRACE request to the server.
62 * httpUpdate() - Update the current HTTP state for incoming data.
63 * httpWait() - Wait for data available on a connection.
64 * httpWrite() - Write data to a HTTP connection.
65 * http_field() - Return the field index for a field name.
66 * http_read_ssl() - Read from a SSL/TLS connection.
67 * http_send() - Send a request with all fields and the trailing
68 * blank line.
69 * http_setup_ssl() - Set up SSL/TLS on a connection.
70 * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
71 * http_upgrade() - Force upgrade to TLS encryption.
72 * http_wait() - Wait for data available on a connection.
73 * http_write() - Write data to a connection.
74 * http_write_ssl() - Write to a SSL/TLS connection.
75 * http_read_cdsa() - Read function for CDSA decryption code.
76 * http_write_cdsa() - Write function for CDSA encryption code.
77 */
78
79 /*
80 * Include necessary headers...
81 */
82
83 #include "http-private.h"
84 #include "globals.h"
85 #include "debug.h"
86 #include <stdlib.h>
87 #include <fcntl.h>
88 #include <errno.h>
89 #ifndef WIN32
90 # include <signal.h>
91 # include <sys/time.h>
92 # include <sys/resource.h>
93 #endif /* !WIN32 */
94
95
96 /*
97 * Some operating systems have done away with the Fxxxx constants for
98 * the fcntl() call; this works around that "feature"...
99 */
100
101 #ifndef FNONBLK
102 # define FNONBLK O_NONBLOCK
103 #endif /* !FNONBLK */
104
105
106 /*
107 * Local functions...
108 */
109
110 static http_field_t http_field(const char *name);
111 static int http_send(http_t *http, http_state_t request,
112 const char *uri);
113 static int http_wait(http_t *http, int msec);
114 static int http_write(http_t *http, const char *buffer,
115 int length);
116 static int http_write_chunk(http_t *http, const char *buffer,
117 int length);
118 #ifdef HAVE_SSL
119 # ifdef HAVE_CDSASSL
120 static OSStatus http_read_cdsa(SSLConnectionRef connection, void *data, size_t *dataLength);
121 # endif /* HAVE_CDSASSL */
122 static int http_read_ssl(http_t *http, char *buf, int len);
123 static int http_setup_ssl(http_t *http);
124 static void http_shutdown_ssl(http_t *http);
125 static int http_upgrade(http_t *http);
126 # ifdef HAVE_CDSASSL
127 static OSStatus http_write_cdsa(SSLConnectionRef connection, const void *data, size_t *dataLength);
128 # endif /* HAVE_CDSASSL */
129 static int http_write_ssl(http_t *http, const char *buf, int len);
130 #endif /* HAVE_SSL */
131
132
133 /*
134 * Local globals...
135 */
136
137 static const char * const http_fields[] =
138 {
139 "Accept-Language",
140 "Accept-Ranges",
141 "Authorization",
142 "Connection",
143 "Content-Encoding",
144 "Content-Language",
145 "Content-Length",
146 "Content-Location",
147 "Content-MD5",
148 "Content-Range",
149 "Content-Type",
150 "Content-Version",
151 "Date",
152 "Host",
153 "If-Modified-Since",
154 "If-Unmodified-since",
155 "Keep-Alive",
156 "Last-Modified",
157 "Link",
158 "Location",
159 "Range",
160 "Referer",
161 "Retry-After",
162 "Transfer-Encoding",
163 "Upgrade",
164 "User-Agent",
165 "WWW-Authenticate"
166 };
167 static const char * const http_days[7] =
168 {
169 "Sun",
170 "Mon",
171 "Tue",
172 "Wed",
173 "Thu",
174 "Fri",
175 "Sat"
176 };
177 static const char * const http_months[12] =
178 {
179 "Jan",
180 "Feb",
181 "Mar",
182 "Apr",
183 "May",
184 "Jun",
185 "Jul",
186 "Aug",
187 "Sep",
188 "Oct",
189 "Nov",
190 "Dec"
191 };
192
193
194 /*
195 * 'httpCheck()' - Check to see if there is a pending response from the server.
196 */
197
198 int /* O - 0 = no data, 1 = data available */
199 httpCheck(http_t *http) /* I - HTTP connection */
200 {
201 return (httpWait(http, 0));
202 }
203
204
205 /*
206 * 'httpClearCookie()' - Clear the cookie value(s).
207 */
208
209 void
210 httpClearCookie(http_t *http) /* I - Connection */
211 {
212 if (!http)
213 return;
214
215 if (http->cookie)
216 {
217 free(http->cookie);
218 http->cookie = NULL;
219 }
220 }
221
222
223 /*
224 * 'httpClose()' - Close an HTTP connection...
225 */
226
227 void
228 httpClose(http_t *http) /* I - Connection to close */
229 {
230 DEBUG_printf(("httpClose(http=%p)\n", http));
231
232 if (!http)
233 return;
234
235 if (http->input_set)
236 free(http->input_set);
237
238 if (http->cookie)
239 free(http->cookie);
240
241 #ifdef HAVE_SSL
242 if (http->tls)
243 http_shutdown_ssl(http);
244 #endif /* HAVE_SSL */
245
246 #ifdef WIN32
247 closesocket(http->fd);
248 #else
249 close(http->fd);
250 #endif /* WIN32 */
251
252 free(http);
253 }
254
255
256 /*
257 * 'httpConnect()' - Connect to a HTTP server.
258 */
259
260 http_t * /* O - New HTTP connection */
261 httpConnect(const char *host, /* I - Host to connect to */
262 int port) /* I - Port number */
263 {
264 http_encryption_t encryption; /* Type of encryption to use */
265
266
267 /*
268 * Set the default encryption status...
269 */
270
271 if (port == 443)
272 encryption = HTTP_ENCRYPT_ALWAYS;
273 else
274 encryption = HTTP_ENCRYPT_IF_REQUESTED;
275
276 return (httpConnectEncrypt(host, port, encryption));
277 }
278
279
280 /*
281 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
282 */
283
284 http_t * /* O - New HTTP connection */
285 httpConnectEncrypt(
286 const char *host, /* I - Host to connect to */
287 int port, /* I - Port number */
288 http_encryption_t encryption) /* I - Type of encryption to use */
289 {
290 int i; /* Looping var */
291 http_t *http; /* New HTTP connection */
292 struct hostent *hostaddr; /* Host address data */
293
294
295 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encrypt=%d)\n",
296 host ? host : "(null)", port, encrypt));
297
298 if (!host)
299 return (NULL);
300
301 httpInitialize();
302
303 /*
304 * Lookup the host...
305 */
306
307 if ((hostaddr = httpGetHostByName(host)) == NULL)
308 {
309 /*
310 * This hack to make users that don't have a localhost entry in
311 * their hosts file or DNS happy...
312 */
313
314 if (strcasecmp(host, "localhost") != 0)
315 return (NULL);
316 else if ((hostaddr = httpGetHostByName("127.0.0.1")) == NULL)
317 return (NULL);
318 }
319
320 /*
321 * Verify that it is an IPv4, IPv6, or domain address...
322 */
323
324 if ((hostaddr->h_addrtype != AF_INET || hostaddr->h_length != 4)
325 #ifdef AF_INET6
326 && (hostaddr->h_addrtype != AF_INET6 || hostaddr->h_length != 16)
327 #endif /* AF_INET6 */
328 #ifdef AF_LOCAL
329 && (hostaddr->h_addrtype != AF_LOCAL)
330 #endif /* AF_LOCAL */
331 )
332 return (NULL);
333
334 /*
335 * Allocate memory for the structure...
336 */
337
338 http = calloc(sizeof(http_t), 1);
339 if (http == NULL)
340 return (NULL);
341
342 http->version = HTTP_1_1;
343 http->blocking = 1;
344 http->activity = time(NULL);
345 http->fd = -1;
346
347 /*
348 * Set the encryption status...
349 */
350
351 if (port == 443) /* Always use encryption for https */
352 http->encryption = HTTP_ENCRYPT_ALWAYS;
353 else
354 http->encryption = encryption;
355
356 /*
357 * Loop through the addresses we have until one of them connects...
358 */
359
360 strlcpy(http->hostname, host, sizeof(http->hostname));
361
362 for (i = 0; hostaddr->h_addr_list[i]; i ++)
363 {
364 /*
365 * Load the address...
366 */
367
368 httpAddrLoad(hostaddr, port, i, &(http->hostaddr));
369
370 /*
371 * Connect to the remote system...
372 */
373
374 if (!httpReconnect(http))
375 return (http);
376 }
377
378 /*
379 * Could not connect to any known address - bail out!
380 */
381
382 free(http);
383 return (NULL);
384 }
385
386
387 /*
388 * 'httpDecode64()' - Base64-decode a string.
389 */
390
391 char * /* O - Decoded string */
392 httpDecode64(char *out, /* I - String to write to */
393 const char *in) /* I - String to read from */
394 {
395 int outlen; /* Output buffer length */
396
397
398 /*
399 * Use the old maximum buffer size for binary compatibility...
400 */
401
402 outlen = 512;
403
404 return (httpDecode64_2(out, &outlen, in));
405 }
406
407
408 /*
409 * 'httpDecode64_2()' - Base64-decode a string.
410 */
411
412 char * /* O - Decoded string */
413 httpDecode64_2(char *out, /* I - String to write to */
414 int *outlen, /* IO - Size of output string */
415 const char *in) /* I - String to read from */
416 {
417 int pos, /* Bit position */
418 base64; /* Value of this character */
419 char *outptr, /* Output pointer */
420 *outend; /* End of output buffer */
421
422
423 /*
424 * Range check input...
425 */
426
427 if (!out || !outlen || *outlen < 1 || !in || !*in)
428 return (NULL);
429
430 /*
431 * Convert from base-64 to bytes...
432 */
433
434 for (outptr = out, outend = out + *outlen - 1, pos = 0; *in != '\0'; in ++)
435 {
436 /*
437 * Decode this character into a number from 0 to 63...
438 */
439
440 if (*in >= 'A' && *in <= 'Z')
441 base64 = *in - 'A';
442 else if (*in >= 'a' && *in <= 'z')
443 base64 = *in - 'a' + 26;
444 else if (*in >= '0' && *in <= '9')
445 base64 = *in - '0' + 52;
446 else if (*in == '+')
447 base64 = 62;
448 else if (*in == '/')
449 base64 = 63;
450 else if (*in == '=')
451 break;
452 else
453 continue;
454
455 /*
456 * Store the result in the appropriate chars...
457 */
458
459 switch (pos)
460 {
461 case 0 :
462 if (outptr < outend)
463 *outptr = base64 << 2;
464 pos ++;
465 break;
466 case 1 :
467 if (outptr < outend)
468 *outptr++ |= (base64 >> 4) & 3;
469 if (outptr < outend)
470 *outptr = (base64 << 4) & 255;
471 pos ++;
472 break;
473 case 2 :
474 if (outptr < outend)
475 *outptr++ |= (base64 >> 2) & 15;
476 if (outptr < outend)
477 *outptr = (base64 << 6) & 255;
478 pos ++;
479 break;
480 case 3 :
481 if (outptr < outend)
482 *outptr++ |= base64;
483 pos = 0;
484 break;
485 }
486 }
487
488 *outptr = '\0';
489
490 /*
491 * Return the decoded string and size...
492 */
493
494 *outlen = (int)(outptr - out);
495
496 return (out);
497 }
498
499
500 /*
501 * 'httpDelete()' - Send a DELETE request to the server.
502 */
503
504 int /* O - Status of call (0 = success) */
505 httpDelete(http_t *http, /* I - HTTP data */
506 const char *uri) /* I - URI to delete */
507 {
508 return (http_send(http, HTTP_DELETE, uri));
509 }
510
511
512 /*
513 * 'httpEncode64()' - Base64-encode a string.
514 */
515
516 char * /* O - Encoded string */
517 httpEncode64(char *out, /* I - String to write to */
518 const char *in) /* I - String to read from */
519 {
520 return (httpEncode64_2(out, 512, in, strlen(in)));
521 }
522
523
524 /*
525 * 'httpEncode64_2()' - Base64-encode a string.
526 */
527
528 char * /* O - Encoded string */
529 httpEncode64_2(char *out, /* I - String to write to */
530 int outlen, /* I - Size of output string */
531 const char *in, /* I - String to read from */
532 int inlen) /* I - Size of input string */
533 {
534 char *outptr, /* Output pointer */
535 *outend; /* End of output buffer */
536 static const char base64[] = /* Base64 characters... */
537 {
538 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
539 "abcdefghijklmnopqrstuvwxyz"
540 "0123456789"
541 "+/"
542 };
543
544
545 /*
546 * Range check input...
547 */
548
549 if (!out || outlen < 1 || !in || inlen < 1)
550 return (NULL);
551
552 /*
553 * Convert bytes to base-64...
554 */
555
556 for (outptr = out, outend = out + outlen - 1; inlen > 0; in ++, inlen --)
557 {
558 /*
559 * Encode the up to 3 characters as 4 Base64 numbers...
560 */
561
562 if (outptr < outend)
563 *outptr ++ = base64[(in[0] & 255) >> 2];
564 if (outptr < outend)
565 *outptr ++ = base64[(((in[0] & 255) << 4) | ((in[1] & 255) >> 4)) & 63];
566
567 in ++;
568 inlen --;
569 if (inlen <= 0)
570 {
571 if (outptr < outend)
572 *outptr ++ = '=';
573 if (outptr < outend)
574 *outptr ++ = '=';
575 break;
576 }
577
578 if (outptr < outend)
579 *outptr ++ = base64[(((in[0] & 255) << 2) | ((in[1] & 255) >> 6)) & 63];
580
581 in ++;
582 inlen --;
583 if (inlen <= 0)
584 {
585 if (outptr < outend)
586 *outptr ++ = '=';
587 break;
588 }
589
590 if (outptr < outend)
591 *outptr ++ = base64[in[0] & 63];
592 }
593
594 *outptr = '\0';
595
596 /*
597 * Return the encoded string...
598 */
599
600 return (out);
601 }
602
603
604 /*
605 * 'httpEncryption()' - Set the required encryption on the link.
606 */
607
608 int /* O - -1 on error, 0 on success */
609 httpEncryption(http_t *http, /* I - HTTP data */
610 http_encryption_t e) /* I - New encryption preference */
611 {
612 DEBUG_printf(("httpEncryption(http=%p, e=%d)\n", http, e));
613
614 #ifdef HAVE_SSL
615 if (!http)
616 return (0);
617
618 http->encryption = e;
619
620 if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
621 (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
622 return (httpReconnect(http));
623 else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
624 return (http_upgrade(http));
625 else
626 return (0);
627 #else
628 if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
629 return (-1);
630 else
631 return (0);
632 #endif /* HAVE_SSL */
633 }
634
635
636 /*
637 * 'httpFlush()' - Flush data from a HTTP connection.
638 */
639
640 void
641 httpFlush(http_t *http) /* I - HTTP data */
642 {
643 char buffer[8192]; /* Junk buffer */
644
645
646 DEBUG_printf(("httpFlush(http=%p), state=%d\n", http, http->state));
647
648 while (httpRead(http, buffer, sizeof(buffer)) > 0);
649 }
650
651
652 /*
653 * 'httpFlushWrite()' - Flush data in write buffer.
654 */
655
656 int /* O - Bytes written or -1 on error */
657 httpFlushWrite(http_t *http) /* I - HTTP data */
658 {
659 int bytes; /* Bytes written */
660
661
662 DEBUG_printf(("httpFlushWrite(http=%p)\n", http));
663
664 if (!http || !http->wused)
665 return (0);
666
667 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
668 bytes = http_write_chunk(http, http->wbuffer, http->wused);
669 else
670 bytes = http_write(http, http->wbuffer, http->wused);
671
672 http->wused = 0;
673
674 return (bytes);
675 }
676
677
678 /*
679 * 'httpGet()' - Send a GET request to the server.
680 */
681
682 int /* O - Status of call (0 = success) */
683 httpGet(http_t *http, /* I - HTTP data */
684 const char *uri) /* I - URI to get */
685 {
686 return (http_send(http, HTTP_GET, uri));
687 }
688
689
690 /*
691 * 'httpGetDateString()' - Get a formatted date/time string from a time value.
692 *
693 * @deprecated
694 */
695
696 const char * /* O - Date/time string */
697 httpGetDateString(time_t t) /* I - UNIX time */
698 {
699 _cups_globals_t *cg = _cupsGlobals(); /* Pointer to library globals */
700
701
702 return (httpGetDateString2(t, cg->http_date, sizeof(cg->http_date)));
703 }
704
705
706 /*
707 * 'httpGetDateString2()' - Get a formatted date/time string from a time value.
708 */
709
710 const char * /* O - Date/time string */
711 httpGetDateString2(time_t t, /* I - UNIX time */
712 char *s, /* I - String buffer */
713 int slen) /* I - Size of string buffer */
714 {
715 struct tm *tdate; /* UNIX date/time data */
716
717
718 tdate = gmtime(&t);
719 snprintf(s, slen, "%s, %02d %s %d %02d:%02d:%02d GMT",
720 http_days[tdate->tm_wday], tdate->tm_mday,
721 http_months[tdate->tm_mon], tdate->tm_year + 1900,
722 tdate->tm_hour, tdate->tm_min, tdate->tm_sec);
723
724 return (s);
725 }
726
727
728 /*
729 * 'httpGetDateTime()' - Get a time value from a formatted date/time string.
730 */
731
732 time_t /* O - UNIX time */
733 httpGetDateTime(const char *s) /* I - Date/time string */
734 {
735 int i; /* Looping var */
736 char mon[16]; /* Abbreviated month name */
737 int day, year; /* Day of month and year */
738 int hour, min, sec; /* Time */
739 int days; /* Number of days since 1970 */
740 static const int normal_days[] = /* Days to a month, normal years */
741 { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
742 static const int leap_days[] = /* Days to a month, leap years */
743 { 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
744
745
746 DEBUG_printf(("httpGetDateTime(s=\"%s\")\n", s));
747
748 /*
749 * Extract the date and time from the formatted string...
750 */
751
752 if (sscanf(s, "%*s%d%15s%d%d:%d:%d", &day, mon, &year, &hour, &min, &sec) < 6)
753 return (0);
754
755 DEBUG_printf((" day=%d, mon=\"%s\", year=%d, hour=%d, min=%d, sec=%d\n",
756 day, mon, year, hour, min, sec));
757
758 /*
759 * Convert the month name to a number from 0 to 11.
760 */
761
762 for (i = 0; i < 12; i ++)
763 if (!strcasecmp(mon, http_months[i]))
764 break;
765
766 if (i >= 12)
767 return (0);
768
769 DEBUG_printf((" i=%d\n", i));
770
771 /*
772 * Now convert the date and time to a UNIX time value in seconds since
773 * 1970. We can't use mktime() since the timezone may not be UTC but
774 * the date/time string *is* UTC.
775 */
776
777 if ((year & 3) == 0 && ((year % 100) != 0 || (year % 400) == 0))
778 days = leap_days[i] + day - 1;
779 else
780 days = normal_days[i] + day - 1;
781
782 DEBUG_printf((" days=%d\n", days));
783
784 days += (year - 1970) * 365 + /* 365 days per year (normally) */
785 ((year - 1) / 4 - 492) - /* + leap days */
786 ((year - 1) / 100 - 19) + /* - 100 year days */
787 ((year - 1) / 400 - 4); /* + 400 year days */
788
789 DEBUG_printf((" days=%d\n", days));
790
791 return (days * 86400 + hour * 3600 + min * 60 + sec);
792 }
793
794
795 /*
796 * 'httpGetSubField()' - Get a sub-field value.
797 */
798
799 char * /* O - Value or NULL */
800 httpGetSubField(http_t *http, /* I - HTTP data */
801 http_field_t field, /* I - Field index */
802 const char *name, /* I - Name of sub-field */
803 char *value) /* O - Value string */
804 {
805 const char *fptr; /* Pointer into field */
806 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
807 *ptr; /* Pointer into string buffer */
808
809
810 DEBUG_printf(("httpGetSubField(http=%p, field=%d, name=\"%s\", value=%p)\n",
811 http, field, name, value));
812
813 if (http == NULL ||
814 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
815 field > HTTP_FIELD_WWW_AUTHENTICATE ||
816 name == NULL || value == NULL)
817 return (NULL);
818
819 for (fptr = http->fields[field]; *fptr;)
820 {
821 /*
822 * Skip leading whitespace...
823 */
824
825 while (isspace(*fptr & 255))
826 fptr ++;
827
828 if (*fptr == ',')
829 {
830 fptr ++;
831 continue;
832 }
833
834 /*
835 * Get the sub-field name...
836 */
837
838 for (ptr = temp;
839 *fptr && *fptr != '=' && !isspace(*fptr & 255) && ptr < (temp + sizeof(temp) - 1);
840 *ptr++ = *fptr++);
841
842 *ptr = '\0';
843
844 DEBUG_printf(("httpGetSubField: name=\"%s\"\n", temp));
845
846 /*
847 * Skip trailing chars up to the '='...
848 */
849
850 while (isspace(*fptr & 255))
851 fptr ++;
852
853 if (!*fptr)
854 break;
855
856 if (*fptr != '=')
857 continue;
858
859 /*
860 * Skip = and leading whitespace...
861 */
862
863 fptr ++;
864
865 while (isspace(*fptr & 255))
866 fptr ++;
867
868 if (*fptr == '\"')
869 {
870 /*
871 * Read quoted string...
872 */
873
874 for (ptr = value, fptr ++;
875 *fptr && *fptr != '\"' && ptr < (value + HTTP_MAX_VALUE - 1);
876 *ptr++ = *fptr++);
877
878 *ptr = '\0';
879
880 while (*fptr && *fptr != '\"')
881 fptr ++;
882
883 if (*fptr)
884 fptr ++;
885 }
886 else
887 {
888 /*
889 * Read unquoted string...
890 */
891
892 for (ptr = value;
893 *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < (value + HTTP_MAX_VALUE - 1);
894 *ptr++ = *fptr++);
895
896 *ptr = '\0';
897
898 while (*fptr && !isspace(*fptr & 255) && *fptr != ',')
899 fptr ++;
900 }
901
902 DEBUG_printf(("httpGetSubField: value=\"%s\"\n", value));
903
904 /*
905 * See if this is the one...
906 */
907
908 if (strcmp(name, temp) == 0)
909 return (value);
910 }
911
912 value[0] = '\0';
913
914 return (NULL);
915 }
916
917
918 /*
919 * 'httpGetLength()' - Get the amount of data remaining from the
920 * content-length or transfer-encoding fields.
921 */
922
923 int /* O - Content length */
924 httpGetLength(http_t *http) /* I - HTTP data */
925 {
926 DEBUG_printf(("httpGetLength(http=%p), state=%d\n", http, http->state));
927
928 if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
929 {
930 DEBUG_puts("httpGetLength: chunked request!");
931
932 http->data_encoding = HTTP_ENCODE_CHUNKED;
933 http->data_remaining = 0;
934 }
935 else
936 {
937 http->data_encoding = HTTP_ENCODE_LENGTH;
938
939 /*
940 * The following is a hack for HTTP servers that don't send a
941 * content-length or transfer-encoding field...
942 *
943 * If there is no content-length then the connection must close
944 * after the transfer is complete...
945 */
946
947 if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
948 http->data_remaining = 2147483647;
949 else
950 http->data_remaining = atoi(http->fields[HTTP_FIELD_CONTENT_LENGTH]);
951
952 DEBUG_printf(("httpGetLength: content_length=%d\n", http->data_remaining));
953 }
954
955 return (http->data_remaining);
956 }
957
958
959 /*
960 * 'httpGets()' - Get a line of text from a HTTP connection.
961 */
962
963 char * /* O - Line or NULL */
964 httpGets(char *line, /* I - Line to read into */
965 int length, /* I - Max length of buffer */
966 http_t *http) /* I - HTTP data */
967 {
968 char *lineptr, /* Pointer into line */
969 *bufptr, /* Pointer into input buffer */
970 *bufend; /* Pointer to end of buffer */
971 int bytes; /* Number of bytes read */
972
973
974 DEBUG_printf(("httpGets(line=%p, length=%d, http=%p)\n", line, length, http));
975
976 if (http == NULL || line == NULL)
977 return (NULL);
978
979 /*
980 * Pre-scan the buffer and see if there is a newline in there...
981 */
982
983 #ifdef WIN32
984 WSASetLastError(0);
985 #else
986 errno = 0;
987 #endif /* WIN32 */
988
989 do
990 {
991 bufptr = http->buffer;
992 bufend = http->buffer + http->used;
993
994 while (bufptr < bufend)
995 if (*bufptr == 0x0a)
996 break;
997 else
998 bufptr ++;
999
1000 if (bufptr >= bufend && http->used < HTTP_MAX_BUFFER)
1001 {
1002 /*
1003 * No newline; see if there is more data to be read...
1004 */
1005
1006 if (!http->blocking && !http_wait(http, 1000))
1007 return (NULL);
1008
1009 #ifdef HAVE_SSL
1010 if (http->tls)
1011 bytes = http_read_ssl(http, bufend, HTTP_MAX_BUFFER - http->used);
1012 else
1013 #endif /* HAVE_SSL */
1014 bytes = recv(http->fd, bufend, HTTP_MAX_BUFFER - http->used, 0);
1015
1016 DEBUG_printf(("httpGets: read %d bytes...\n", bytes));
1017
1018 if (bytes < 0)
1019 {
1020 /*
1021 * Nope, can't get a line this time...
1022 */
1023
1024 #ifdef WIN32
1025 if (WSAGetLastError() != http->error)
1026 {
1027 http->error = WSAGetLastError();
1028 continue;
1029 }
1030
1031 DEBUG_printf(("httpGets: recv() error %d!\n", WSAGetLastError()));
1032 #else
1033 DEBUG_printf(("httpGets: recv() error %d!\n", errno));
1034
1035 if (errno == EINTR)
1036 continue;
1037 else if (errno != http->error)
1038 {
1039 http->error = errno;
1040 continue;
1041 }
1042 #endif /* WIN32 */
1043
1044 return (NULL);
1045 }
1046 else if (bytes == 0)
1047 {
1048 http->error = EPIPE;
1049
1050 return (NULL);
1051 }
1052
1053 /*
1054 * Yup, update the amount used and the end pointer...
1055 */
1056
1057 http->used += bytes;
1058 bufend += bytes;
1059 bufptr = bufend;
1060 }
1061 }
1062 while (bufptr >= bufend && http->used < HTTP_MAX_BUFFER);
1063
1064 http->activity = time(NULL);
1065
1066 /*
1067 * Read a line from the buffer...
1068 */
1069
1070 lineptr = line;
1071 bufptr = http->buffer;
1072 bytes = 0;
1073 length --;
1074
1075 while (bufptr < bufend && bytes < length)
1076 {
1077 bytes ++;
1078
1079 if (*bufptr == 0x0a)
1080 {
1081 bufptr ++;
1082 break;
1083 }
1084 else if (*bufptr == 0x0d)
1085 bufptr ++;
1086 else
1087 *lineptr++ = *bufptr++;
1088 }
1089
1090 if (bytes > 0)
1091 {
1092 *lineptr = '\0';
1093
1094 http->used -= bytes;
1095 if (http->used > 0)
1096 memmove(http->buffer, bufptr, http->used);
1097
1098 DEBUG_printf(("httpGets: Returning \"%s\"\n", line));
1099 return (line);
1100 }
1101
1102 DEBUG_puts("httpGets: No new line available!");
1103
1104 return (NULL);
1105 }
1106
1107
1108 /*
1109 * 'httpHead()' - Send a HEAD request to the server.
1110 */
1111
1112 int /* O - Status of call (0 = success) */
1113 httpHead(http_t *http, /* I - HTTP data */
1114 const char *uri) /* I - URI for head */
1115 {
1116 return (http_send(http, HTTP_HEAD, uri));
1117 }
1118
1119
1120 /*
1121 * 'httpInitialize()' - Initialize the HTTP interface library and set the
1122 * default HTTP proxy (if any).
1123 */
1124
1125 void
1126 httpInitialize(void)
1127 {
1128 #ifdef HAVE_LIBSSL
1129 # ifndef WIN32
1130 struct timeval curtime; /* Current time in microseconds */
1131 # endif /* !WIN32 */
1132 int i; /* Looping var */
1133 unsigned char data[1024]; /* Seed data */
1134 #endif /* HAVE_LIBSSL */
1135
1136 #ifdef WIN32
1137 WSADATA winsockdata; /* WinSock data */
1138 static int initialized = 0; /* Has WinSock been initialized? */
1139
1140
1141 if (!initialized)
1142 WSAStartup(MAKEWORD(1,1), &winsockdata);
1143 #elif defined(HAVE_SIGSET)
1144 sigset(SIGPIPE, SIG_IGN);
1145 #elif defined(HAVE_SIGACTION)
1146 struct sigaction action; /* POSIX sigaction data */
1147
1148
1149 /*
1150 * Ignore SIGPIPE signals...
1151 */
1152
1153 memset(&action, 0, sizeof(action));
1154 action.sa_handler = SIG_IGN;
1155 sigaction(SIGPIPE, &action, NULL);
1156 #else
1157 signal(SIGPIPE, SIG_IGN);
1158 #endif /* WIN32 */
1159
1160 #ifdef HAVE_GNUTLS
1161 gnutls_global_init();
1162 #endif /* HAVE_GNUTLS */
1163
1164 #ifdef HAVE_LIBSSL
1165 SSL_load_error_strings();
1166 SSL_library_init();
1167
1168 /*
1169 * Using the current time is a dubious random seed, but on some systems
1170 * it is the best we can do (on others, this seed isn't even used...)
1171 */
1172
1173 #ifdef WIN32
1174 #else
1175 gettimeofday(&curtime, NULL);
1176 srand(curtime.tv_sec + curtime.tv_usec);
1177 #endif /* WIN32 */
1178
1179 for (i = 0; i < sizeof(data); i ++)
1180 data[i] = rand(); /* Yes, this is a poor source of random data... */
1181
1182 RAND_seed(&data, sizeof(data));
1183 #endif /* HAVE_LIBSSL */
1184 }
1185
1186
1187 /*
1188 * 'httpOptions()' - Send an OPTIONS request to the server.
1189 */
1190
1191 int /* O - Status of call (0 = success) */
1192 httpOptions(http_t *http, /* I - HTTP data */
1193 const char *uri) /* I - URI for options */
1194 {
1195 return (http_send(http, HTTP_OPTIONS, uri));
1196 }
1197
1198
1199 /*
1200 * 'httpPost()' - Send a POST request to the server.
1201 */
1202
1203 int /* O - Status of call (0 = success) */
1204 httpPost(http_t *http, /* I - HTTP data */
1205 const char *uri) /* I - URI for post */
1206 {
1207 return (http_send(http, HTTP_POST, uri));
1208 }
1209
1210
1211 /*
1212 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
1213 */
1214
1215 int /* O - Number of bytes written */
1216 httpPrintf(http_t *http, /* I - HTTP data */
1217 const char *format, /* I - printf-style format string */
1218 ...) /* I - Additional args as needed */
1219 {
1220 int bytes; /* Number of bytes to write */
1221 char buf[16384]; /* Buffer for formatted string */
1222 va_list ap; /* Variable argument pointer */
1223
1224
1225 DEBUG_printf(("httpPrintf(http=%p, format=\"%s\", ...)\n", http, format));
1226
1227 va_start(ap, format);
1228 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1229 va_end(ap);
1230
1231 DEBUG_printf(("httpPrintf: %s", buf));
1232
1233 if (http->wused)
1234 httpFlushWrite(http);
1235
1236 return (http_write(http, buf, bytes));
1237 }
1238
1239
1240 /*
1241 * 'httpPut()' - Send a PUT request to the server.
1242 */
1243
1244 int /* O - Status of call (0 = success) */
1245 httpPut(http_t *http, /* I - HTTP data */
1246 const char *uri) /* I - URI to put */
1247 {
1248 return (http_send(http, HTTP_PUT, uri));
1249 }
1250
1251
1252 /*
1253 * 'httpRead()' - Read data from a HTTP connection.
1254 */
1255
1256 int /* O - Number of bytes read */
1257 httpRead(http_t *http, /* I - HTTP data */
1258 char *buffer, /* I - Buffer for data */
1259 int length) /* I - Maximum number of bytes */
1260 {
1261 int bytes; /* Bytes read */
1262 char len[32]; /* Length string */
1263
1264
1265 DEBUG_printf(("httpRead(http=%p, buffer=%p, length=%d)\n",
1266 http, buffer, length));
1267
1268 if (http == NULL || buffer == NULL)
1269 return (-1);
1270
1271 http->activity = time(NULL);
1272
1273 if (length <= 0)
1274 return (0);
1275
1276 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1277 http->data_remaining <= 0)
1278 {
1279 DEBUG_puts("httpRead: Getting chunk length...");
1280
1281 if (httpGets(len, sizeof(len), http) == NULL)
1282 {
1283 DEBUG_puts("httpRead: Could not get length!");
1284 return (0);
1285 }
1286
1287 http->data_remaining = strtol(len, NULL, 16);
1288 if (http->data_remaining < 0)
1289 {
1290 DEBUG_puts("httpRead: Negative chunk length!");
1291 return (0);
1292 }
1293 }
1294
1295 DEBUG_printf(("httpRead: data_remaining=%d\n", http->data_remaining));
1296
1297 if (http->data_remaining <= 0)
1298 {
1299 /*
1300 * A zero-length chunk ends a transfer; unless we are reading POST
1301 * data, go idle...
1302 */
1303
1304 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1305 httpGets(len, sizeof(len), http);
1306
1307 if (http->state == HTTP_POST_RECV)
1308 http->state ++;
1309 else
1310 http->state = HTTP_WAITING;
1311
1312 /*
1313 * Prevent future reads for this request...
1314 */
1315
1316 http->data_encoding = HTTP_ENCODE_LENGTH;
1317
1318 return (0);
1319 }
1320 else if (length > http->data_remaining)
1321 length = http->data_remaining;
1322
1323 if (http->used == 0 && length <= 256)
1324 {
1325 /*
1326 * Buffer small reads for better performance...
1327 */
1328
1329 if (!http->blocking && !httpWait(http, 1000))
1330 return (0);
1331
1332 if (http->data_remaining > sizeof(http->buffer))
1333 bytes = sizeof(http->buffer);
1334 else
1335 bytes = http->data_remaining;
1336
1337 #ifdef HAVE_SSL
1338 if (http->tls)
1339 bytes = http_read_ssl(http, http->buffer, bytes);
1340 else
1341 #endif /* HAVE_SSL */
1342 {
1343 DEBUG_printf(("httpRead: reading %d bytes from socket into buffer...\n",
1344 bytes));
1345
1346 bytes = recv(http->fd, http->buffer, bytes, 0);
1347
1348 DEBUG_printf(("httpRead: read %d bytes from socket into buffer...\n",
1349 bytes));
1350 }
1351
1352 if (bytes > 0)
1353 http->used = bytes;
1354 else if (bytes < 0)
1355 {
1356 #ifdef WIN32
1357 http->error = WSAGetLastError();
1358 return (-1);
1359 #else
1360 if (errno != EINTR)
1361 {
1362 http->error = errno;
1363 return (-1);
1364 }
1365 #endif /* WIN32 */
1366 }
1367 else
1368 {
1369 http->error = EPIPE;
1370 return (0);
1371 }
1372 }
1373
1374 if (http->used > 0)
1375 {
1376 if (length > http->used)
1377 length = http->used;
1378
1379 bytes = length;
1380
1381 DEBUG_printf(("httpRead: grabbing %d bytes from input buffer...\n", bytes));
1382
1383 memcpy(buffer, http->buffer, length);
1384 http->used -= length;
1385
1386 if (http->used > 0)
1387 memmove(http->buffer, http->buffer + length, http->used);
1388 }
1389 #ifdef HAVE_SSL
1390 else if (http->tls)
1391 {
1392 if (!http->blocking && !httpWait(http, 1000))
1393 return (0);
1394
1395 bytes = http_read_ssl(http, buffer, length);
1396 }
1397 #endif /* HAVE_SSL */
1398 else
1399 {
1400 if (!http->blocking && !httpWait(http, 1000))
1401 return (0);
1402
1403 DEBUG_printf(("httpRead: reading %d bytes from socket...\n", length));
1404
1405 while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
1406 if (errno != EINTR)
1407 break;
1408
1409 DEBUG_printf(("httpRead: read %d bytes from socket...\n", bytes));
1410 }
1411
1412 if (bytes > 0)
1413 http->data_remaining -= bytes;
1414 else if (bytes < 0)
1415 {
1416 #ifdef WIN32
1417 http->error = WSAGetLastError();
1418 #else
1419 if (errno == EINTR)
1420 bytes = 0;
1421 else
1422 http->error = errno;
1423 #endif /* WIN32 */
1424 }
1425 else
1426 {
1427 http->error = EPIPE;
1428 return (0);
1429 }
1430
1431 if (http->data_remaining == 0)
1432 {
1433 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1434 httpGets(len, sizeof(len), http);
1435
1436 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1437 {
1438 if (http->state == HTTP_POST_RECV)
1439 http->state ++;
1440 else
1441 http->state = HTTP_WAITING;
1442 }
1443 }
1444
1445 #ifdef DEBUG
1446 {
1447 int i, j, ch;
1448 printf("httpRead: Read %d bytes:\n", bytes);
1449 for (i = 0; i < bytes; i += 16)
1450 {
1451 printf(" ");
1452
1453 for (j = 0; j < 16 && (i + j) < bytes; j ++)
1454 printf(" %02X", buffer[i + j] & 255);
1455
1456 while (j < 16)
1457 {
1458 printf(" ");
1459 j ++;
1460 }
1461
1462 printf(" ");
1463 for (j = 0; j < 16 && (i + j) < bytes; j ++)
1464 {
1465 ch = buffer[i + j] & 255;
1466
1467 if (ch < ' ' || ch == 127)
1468 ch = '.';
1469
1470 putchar(ch);
1471 }
1472 putchar('\n');
1473 }
1474 }
1475 #endif /* DEBUG */
1476
1477 return (bytes);
1478 }
1479
1480
1481 /*
1482 * 'httpReconnect()' - Reconnect to a HTTP server...
1483 */
1484
1485 int /* O - 0 on success, non-zero on failure */
1486 httpReconnect(http_t *http) /* I - HTTP data */
1487 {
1488 int val; /* Socket option value */
1489 int status; /* Connect status */
1490
1491
1492 DEBUG_printf(("httpReconnect(http=%p)\n", http));
1493
1494 if (!http)
1495 return (-1);
1496
1497 #ifdef HAVE_SSL
1498 if (http->tls)
1499 http_shutdown_ssl(http);
1500 #endif /* HAVE_SSL */
1501
1502 /*
1503 * Close any previously open socket...
1504 */
1505
1506 if (http->fd >= 0)
1507 #ifdef WIN32
1508 closesocket(http->fd);
1509 #else
1510 close(http->fd);
1511 #endif /* WIN32 */
1512
1513 /*
1514 * Create the socket and set options to allow reuse.
1515 */
1516
1517 if ((http->fd = socket(http->hostaddr.addr.sa_family, SOCK_STREAM, 0)) < 0)
1518 {
1519 #ifdef WIN32
1520 http->error = WSAGetLastError();
1521 #else
1522 http->error = errno;
1523 #endif /* WIN32 */
1524 http->status = HTTP_ERROR;
1525 return (-1);
1526 }
1527
1528 #ifdef FD_CLOEXEC
1529 fcntl(http->fd, F_SETFD, FD_CLOEXEC); /* Close this socket when starting *
1530 * other processes... */
1531 #endif /* FD_CLOEXEC */
1532
1533 val = 1;
1534 setsockopt(http->fd, SOL_SOCKET, SO_REUSEADDR, (char *)&val, sizeof(val));
1535
1536 #ifdef SO_REUSEPORT
1537 val = 1;
1538 setsockopt(http->fd, SOL_SOCKET, SO_REUSEPORT, &val, sizeof(val));
1539 #endif /* SO_REUSEPORT */
1540
1541 /*
1542 * Using TCP_NODELAY improves responsiveness, especially on systems
1543 * with a slow loopback interface... Since we write large buffers
1544 * when sending print files and requests, there shouldn't be any
1545 * performance penalty for this...
1546 */
1547
1548 val = 1;
1549 #ifdef WIN32
1550 setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, (char *)&val, sizeof(val));
1551 #else
1552 setsockopt(http->fd, IPPROTO_TCP, TCP_NODELAY, &val, sizeof(val));
1553 #endif /* WIN32 */
1554
1555 /*
1556 * Connect to the server...
1557 */
1558
1559 #ifdef AF_INET6
1560 if (http->hostaddr.addr.sa_family == AF_INET6)
1561 status = connect(http->fd, (struct sockaddr *)&(http->hostaddr),
1562 sizeof(http->hostaddr.ipv6));
1563 else
1564 #endif /* AF_INET6 */
1565 #ifdef AF_LOCAL
1566 if (http->hostaddr.addr.sa_family == AF_LOCAL)
1567 status = connect(http->fd, (struct sockaddr *)&(http->hostaddr),
1568 SUN_LEN(&(http->hostaddr.un)));
1569 else
1570 #endif /* AF_LOCAL */
1571 status = connect(http->fd, (struct sockaddr *)&(http->hostaddr),
1572 sizeof(http->hostaddr.ipv4));
1573
1574 if (status < 0)
1575 {
1576 #ifdef WIN32
1577 http->error = WSAGetLastError();
1578 #else
1579 http->error = errno;
1580 #endif /* WIN32 */
1581 http->status = HTTP_ERROR;
1582
1583 #ifdef WIN32
1584 closesocket(http->fd);
1585 #else
1586 close(http->fd);
1587 #endif
1588
1589 http->fd = -1;
1590
1591 return (-1);
1592 }
1593
1594 http->error = 0;
1595 http->status = HTTP_CONTINUE;
1596
1597 #ifdef HAVE_SSL
1598 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
1599 {
1600 /*
1601 * Always do encryption via SSL.
1602 */
1603
1604 if (http_setup_ssl(http) != 0)
1605 {
1606 #ifdef WIN32
1607 closesocket(http->fd);
1608 #else
1609 close(http->fd);
1610 #endif /* WIN32 */
1611
1612 return (-1);
1613 }
1614 }
1615 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
1616 return (http_upgrade(http));
1617 #endif /* HAVE_SSL */
1618
1619 return (0);
1620 }
1621
1622
1623 /*
1624 * 'httpSetCookie()' - Set the cookie value(s)...
1625 */
1626
1627 void
1628 httpSetCookie(http_t *http, /* I - Connection */
1629 const char *cookie) /* I - Cookie string */
1630 {
1631 if (!http)
1632 return;
1633
1634 if (http->cookie)
1635 free(http->cookie);
1636
1637 if (cookie)
1638 http->cookie = strdup(cookie);
1639 else
1640 http->cookie = NULL;
1641 }
1642
1643
1644 /*
1645 * 'httpSetField()' - Set the value of an HTTP header.
1646 */
1647
1648 void
1649 httpSetField(http_t *http, /* I - HTTP data */
1650 http_field_t field, /* I - Field index */
1651 const char *value) /* I - Value */
1652 {
1653 if (http == NULL ||
1654 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
1655 field > HTTP_FIELD_WWW_AUTHENTICATE ||
1656 value == NULL)
1657 return;
1658
1659 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
1660 }
1661
1662
1663 /*
1664 * 'httpTrace()' - Send an TRACE request to the server.
1665 */
1666
1667 int /* O - Status of call (0 = success) */
1668 httpTrace(http_t *http, /* I - HTTP data */
1669 const char *uri) /* I - URI for trace */
1670 {
1671 return (http_send(http, HTTP_TRACE, uri));
1672 }
1673
1674
1675 /*
1676 * 'httpUpdate()' - Update the current HTTP state for incoming data.
1677 */
1678
1679 http_status_t /* O - HTTP status */
1680 httpUpdate(http_t *http) /* I - HTTP data */
1681 {
1682 char line[16384], /* Line from connection... */
1683 *value; /* Pointer to value on line */
1684 http_field_t field; /* Field index */
1685 int major, minor, /* HTTP version numbers */
1686 status; /* Request status */
1687
1688
1689 DEBUG_printf(("httpUpdate(http=%p), state=%d\n", http, http->state));
1690
1691 /*
1692 * Flush pending data, if any...
1693 */
1694
1695 if (http->wused)
1696 httpFlushWrite(http);
1697
1698 /*
1699 * If we haven't issued any commands, then there is nothing to "update"...
1700 */
1701
1702 if (http->state == HTTP_WAITING)
1703 return (HTTP_CONTINUE);
1704
1705 /*
1706 * Grab all of the lines we can from the connection...
1707 */
1708
1709 while (httpGets(line, sizeof(line), http) != NULL)
1710 {
1711 DEBUG_printf(("httpUpdate: Got \"%s\"\n", line));
1712
1713 if (line[0] == '\0')
1714 {
1715 /*
1716 * Blank line means the start of the data section (if any). Return
1717 * the result code, too...
1718 *
1719 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
1720 * Instead, we just return HTTP_CONTINUE to the caller and keep on
1721 * tryin'...
1722 */
1723
1724 if (http->status == HTTP_CONTINUE)
1725 return (http->status);
1726
1727 if (http->status < HTTP_BAD_REQUEST)
1728 http->digest_tries = 0;
1729
1730 #ifdef HAVE_SSL
1731 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
1732 {
1733 if (http_setup_ssl(http) != 0)
1734 {
1735 # ifdef WIN32
1736 closesocket(http->fd);
1737 # else
1738 close(http->fd);
1739 # endif /* WIN32 */
1740
1741 return (HTTP_ERROR);
1742 }
1743
1744 return (HTTP_CONTINUE);
1745 }
1746 #endif /* HAVE_SSL */
1747
1748 httpGetLength(http);
1749
1750 switch (http->state)
1751 {
1752 case HTTP_GET :
1753 case HTTP_POST :
1754 case HTTP_POST_RECV :
1755 case HTTP_PUT :
1756 http->state ++;
1757 case HTTP_POST_SEND :
1758 break;
1759
1760 default :
1761 http->state = HTTP_WAITING;
1762 break;
1763 }
1764
1765 return (http->status);
1766 }
1767 else if (strncmp(line, "HTTP/", 5) == 0)
1768 {
1769 /*
1770 * Got the beginning of a response...
1771 */
1772
1773 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
1774 return (HTTP_ERROR);
1775
1776 http->version = (http_version_t)(major * 100 + minor);
1777 http->status = (http_status_t)status;
1778 }
1779 else if ((value = strchr(line, ':')) != NULL)
1780 {
1781 /*
1782 * Got a value...
1783 */
1784
1785 *value++ = '\0';
1786 while (isspace(*value & 255))
1787 value ++;
1788
1789 /*
1790 * Be tolerants of servers that send unknown attribute fields...
1791 */
1792
1793 if (!strcasecmp(line, "expect"))
1794 {
1795 /*
1796 * "Expect: 100-continue" or similar...
1797 */
1798
1799 http->expect = (http_status_t)atoi(value);
1800 }
1801 else if (!strcasecmp(line, "cookie"))
1802 {
1803 /*
1804 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
1805 */
1806
1807 httpSetCookie(http, value);
1808 }
1809 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
1810 {
1811 DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line));
1812 continue;
1813 }
1814 else
1815 httpSetField(http, field, value);
1816 }
1817 else
1818 {
1819 http->status = HTTP_ERROR;
1820 return (HTTP_ERROR);
1821 }
1822 }
1823
1824 /*
1825 * See if there was an error...
1826 */
1827
1828 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
1829 return (http->status);
1830
1831 if (http->error)
1832 {
1833 DEBUG_printf(("httpUpdate: socket error %d - %s\n", http->error,
1834 strerror(http->error)));
1835 http->status = HTTP_ERROR;
1836 return (HTTP_ERROR);
1837 }
1838
1839 /*
1840 * If we haven't already returned, then there is nothing new...
1841 */
1842
1843 return (HTTP_CONTINUE);
1844 }
1845
1846
1847 /*
1848 * 'httpWait()' - Wait for data available on a connection.
1849 */
1850
1851 int /* O - 1 if data is available, 0 otherwise */
1852 httpWait(http_t *http, /* I - HTTP data */
1853 int msec) /* I - Milliseconds to wait */
1854 {
1855 /*
1856 * First see if there is data in the buffer...
1857 */
1858
1859 if (http == NULL)
1860 return (0);
1861
1862 if (http->used)
1863 return (1);
1864
1865 /*
1866 * If not, check the SSL/TLS buffers and do a select() on the connection...
1867 */
1868
1869 return (http_wait(http, msec));
1870 }
1871
1872
1873 /*
1874 * 'httpWrite()' - Write data to a HTTP connection.
1875 */
1876
1877 int /* O - Number of bytes written */
1878 httpWrite(http_t *http, /* I - HTTP data */
1879 const char *buffer, /* I - Buffer for data */
1880 int length) /* I - Number of bytes to write */
1881 {
1882 int bytes; /* Bytes written */
1883
1884
1885 /*
1886 * Range check input...
1887 */
1888
1889 if (http == NULL || buffer == NULL)
1890 return (-1);
1891
1892 /*
1893 * Mark activity on the connection...
1894 */
1895
1896 http->activity = time(NULL);
1897
1898 /*
1899 * Buffer small writes for better performance...
1900 */
1901
1902 if (length > 0)
1903 {
1904 if ((length + http->wused) > sizeof(http->wbuffer))
1905 httpFlushWrite(http);
1906
1907 if ((length + http->wused) <= sizeof(http->wbuffer))
1908 {
1909 /*
1910 * Write to buffer...
1911 */
1912
1913 memcpy(http->wbuffer + http->wused, buffer, length);
1914 http->wused += length;
1915 bytes = length;
1916 }
1917 else
1918 {
1919 /*
1920 * Otherwise write the data directly...
1921 */
1922
1923 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1924 length = http_write_chunk(http, buffer, length);
1925 else
1926 length = http_write(http, buffer, length);
1927 }
1928
1929 if (http->data_encoding == HTTP_ENCODE_LENGTH)
1930 http->data_remaining -= bytes;
1931 }
1932
1933 /*
1934 * Handle end-of-request processing...
1935 */
1936
1937 if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
1938 (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
1939 {
1940 /*
1941 * Finished with the transfer; unless we are sending POST or PUT
1942 * data, go idle...
1943 */
1944
1945 DEBUG_puts("httpWrite: changing states...");
1946
1947 if (http->wused)
1948 httpFlushWrite(http);
1949
1950 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1951 {
1952 /*
1953 * Send a 0-length chunk at the end of the request...
1954 */
1955
1956 http_write(http, "0\r\n\r\n", 5);
1957
1958 /*
1959 * Reset the data state...
1960 */
1961
1962 http->data_encoding = HTTP_ENCODE_LENGTH;
1963 http->data_remaining = 0;
1964 }
1965
1966 if (http->state == HTTP_POST_RECV)
1967 http->state ++;
1968 else if (http->state == HTTP_PUT_RECV)
1969 http->state = HTTP_STATUS;
1970 else
1971 http->state = HTTP_WAITING;
1972 }
1973
1974 return (bytes);
1975 }
1976
1977
1978 /*
1979 * 'http_field()' - Return the field index for a field name.
1980 */
1981
1982 static http_field_t /* O - Field index */
1983 http_field(const char *name) /* I - String name */
1984 {
1985 int i; /* Looping var */
1986
1987
1988 for (i = 0; i < HTTP_FIELD_MAX; i ++)
1989 if (strcasecmp(name, http_fields[i]) == 0)
1990 return ((http_field_t)i);
1991
1992 return (HTTP_FIELD_UNKNOWN);
1993 }
1994
1995
1996 #if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
1997 /*
1998 * 'http_read_cdsa()' - Read function for CDSA decryption code.
1999 */
2000
2001 static OSStatus /* O - -1 on error, 0 on success */
2002 http_read_cdsa(
2003 SSLConnectionRef connection, /* I - SSL/TLS connection */
2004 void *data, /* I - Data buffer */
2005 size_t *dataLength) /* IO - Number of bytes */
2006 {
2007 ssize_t bytes; /* Number of bytes read */
2008
2009
2010 bytes = recv((int)connection, data, *dataLength, 0);
2011 if (bytes >= 0)
2012 {
2013 *dataLength = bytes;
2014 return (0);
2015 }
2016 else
2017 return (-1);
2018 }
2019 #endif /* HAVE_SSL && HAVE_CDSASSL */
2020
2021
2022 #ifdef HAVE_SSL
2023 /*
2024 * 'http_read_ssl()' - Read from a SSL/TLS connection.
2025 */
2026
2027 static int /* O - Bytes read */
2028 http_read_ssl(http_t *http, /* I - HTTP data */
2029 char *buf, /* I - Buffer to store data */
2030 int len) /* I - Length of buffer */
2031 {
2032 # if defined(HAVE_LIBSSL)
2033 return (SSL_read((SSL *)(http->tls), buf, len));
2034
2035 # elif defined(HAVE_GNUTLS)
2036 return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
2037
2038 # elif defined(HAVE_CDSASSL)
2039 OSStatus error; /* Error info */
2040 size_t processed; /* Number of bytes processed */
2041
2042
2043 error = SSLRead((SSLContextRef)http->tls, buf, len, &processed);
2044
2045 if (error == 0)
2046 return (processed);
2047 else
2048 {
2049 http->error = error;
2050
2051 return (-1);
2052 }
2053 # endif /* HAVE_LIBSSL */
2054 }
2055 #endif /* HAVE_SSL */
2056
2057
2058 /*
2059 * 'http_send()' - Send a request with all fields and the trailing blank line.
2060 */
2061
2062 static int /* O - 0 on success, non-zero on error */
2063 http_send(http_t *http, /* I - HTTP data */
2064 http_state_t request, /* I - Request code */
2065 const char *uri) /* I - URI */
2066 {
2067 int i; /* Looping var */
2068 char *ptr, /* Pointer in buffer */
2069 buf[1024]; /* Encoded URI buffer */
2070 static const char * const codes[] =
2071 { /* Request code strings */
2072 NULL,
2073 "OPTIONS",
2074 "GET",
2075 NULL,
2076 "HEAD",
2077 "POST",
2078 NULL,
2079 NULL,
2080 "PUT",
2081 NULL,
2082 "DELETE",
2083 "TRACE",
2084 "CLOSE"
2085 };
2086 static const char hex[] = "0123456789ABCDEF";
2087 /* Hex digits */
2088
2089
2090 DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n",
2091 http, codes[request], uri));
2092
2093 if (http == NULL || uri == NULL)
2094 return (-1);
2095
2096 /*
2097 * Encode the URI as needed...
2098 */
2099
2100 for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++)
2101 if (*uri <= ' ' || *uri >= 127)
2102 {
2103 if (ptr < (buf + sizeof(buf) - 1))
2104 *ptr ++ = '%';
2105 if (ptr < (buf + sizeof(buf) - 1))
2106 *ptr ++ = hex[(*uri >> 4) & 15];
2107 if (ptr < (buf + sizeof(buf) - 1))
2108 *ptr ++ = hex[*uri & 15];
2109 }
2110 else
2111 *ptr ++ = *uri;
2112
2113 *ptr = '\0';
2114
2115 /*
2116 * See if we had an error the last time around; if so, reconnect...
2117 */
2118
2119 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
2120 httpReconnect(http);
2121
2122 /*
2123 * Send the request header...
2124 */
2125
2126 http->state = request;
2127 if (request == HTTP_POST || request == HTTP_PUT)
2128 http->state ++;
2129
2130 http->status = HTTP_CONTINUE;
2131
2132 #ifdef HAVE_SSL
2133 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
2134 {
2135 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
2136 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
2137 }
2138 #endif /* HAVE_SSL */
2139
2140 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
2141 {
2142 http->status = HTTP_ERROR;
2143 return (-1);
2144 }
2145
2146 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2147 if (http->fields[i][0] != '\0')
2148 {
2149 DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i]));
2150
2151 if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1)
2152 {
2153 http->status = HTTP_ERROR;
2154 return (-1);
2155 }
2156 }
2157
2158 if (httpPrintf(http, "\r\n") < 1)
2159 {
2160 http->status = HTTP_ERROR;
2161 return (-1);
2162 }
2163
2164 httpGetLength(http);
2165 httpClearFields(http);
2166
2167 return (0);
2168 }
2169
2170
2171 #ifdef HAVE_SSL
2172 /*
2173 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
2174 */
2175
2176 static int /* O - Status of connection */
2177 http_setup_ssl(http_t *http) /* I - HTTP data */
2178 {
2179 # ifdef HAVE_LIBSSL
2180 SSL_CTX *context; /* Context for encryption */
2181 SSL *conn; /* Connection for encryption */
2182 # elif defined(HAVE_GNUTLS)
2183 http_tls_t *conn; /* TLS session object */
2184 gnutls_certificate_client_credentials *credentials;
2185 /* TLS credentials */
2186 # elif defined(HAVE_CDSASSL)
2187 SSLContextRef conn; /* Context for encryption */
2188 OSStatus error; /* Error info */
2189 # endif /* HAVE_LIBSSL */
2190
2191
2192 DEBUG_printf(("http_setup_ssl(http=%p)\n", http));
2193
2194 # ifdef HAVE_LIBSSL
2195 context = SSL_CTX_new(SSLv23_client_method());
2196
2197 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
2198
2199 conn = SSL_new(context);
2200
2201 SSL_set_fd(conn, http->fd);
2202 if (SSL_connect(conn) != 1)
2203 {
2204 # ifdef DEBUG
2205 unsigned long error; /* Error code */
2206
2207 while ((error = ERR_get_error()) != 0)
2208 printf("http_setup_ssl: %s\n", ERR_error_string(error, NULL));
2209 # endif /* DEBUG */
2210
2211 SSL_CTX_free(context);
2212 SSL_free(conn);
2213
2214 # ifdef WIN32
2215 http->error = WSAGetLastError();
2216 # else
2217 http->error = errno;
2218 # endif /* WIN32 */
2219 http->status = HTTP_ERROR;
2220
2221 return (HTTP_ERROR);
2222 }
2223
2224 # elif defined(HAVE_GNUTLS)
2225 conn = (http_tls_t *)malloc(sizeof(http_tls_t));
2226
2227 if (conn == NULL)
2228 {
2229 http->error = errno;
2230 http->status = HTTP_ERROR;
2231
2232 return (-1);
2233 }
2234
2235 credentials = (gnutls_certificate_client_credentials *)
2236 malloc(sizeof(gnutls_certificate_client_credentials));
2237 if (credentials == NULL)
2238 {
2239 free(conn);
2240
2241 http->error = errno;
2242 http->status = HTTP_ERROR;
2243
2244 return (-1);
2245 }
2246
2247 gnutls_certificate_allocate_credentials(credentials);
2248
2249 gnutls_init(&(conn->session), GNUTLS_CLIENT);
2250 gnutls_set_default_priority(conn->session);
2251 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
2252 gnutls_transport_set_ptr(conn->session, http->fd);
2253
2254 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
2255 {
2256 http->error = errno;
2257 http->status = HTTP_ERROR;
2258
2259 return (-1);
2260 }
2261
2262 conn->credentials = credentials;
2263
2264 # elif defined(HAVE_CDSASSL)
2265 error = SSLNewContext(false, &conn);
2266
2267 if (!error)
2268 error = SSLSetIOFuncs(conn, http_read_cdsa, http_write_cdsa);
2269
2270 if (!error)
2271 error = SSLSetConnection(conn, (SSLConnectionRef)http->fd);
2272
2273 if (!error)
2274 error = SSLSetAllowsExpiredCerts(conn, true);
2275
2276 if (!error)
2277 error = SSLSetAllowsAnyRoot(conn, true);
2278
2279 if (!error)
2280 error = SSLHandshake(conn);
2281
2282 if (error != 0)
2283 {
2284 http->error = error;
2285 http->status = HTTP_ERROR;
2286
2287 SSLDisposeContext(conn);
2288
2289 close(http->fd);
2290
2291 return (-1);
2292 }
2293 # endif /* HAVE_CDSASSL */
2294
2295 http->tls = conn;
2296 return (0);
2297 }
2298 #endif /* HAVE_SSL */
2299
2300
2301 #ifdef HAVE_SSL
2302 /*
2303 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
2304 */
2305
2306 static void
2307 http_shutdown_ssl(http_t *http) /* I - HTTP data */
2308 {
2309 # ifdef HAVE_LIBSSL
2310 SSL_CTX *context; /* Context for encryption */
2311 SSL *conn; /* Connection for encryption */
2312
2313
2314 conn = (SSL *)(http->tls);
2315 context = SSL_get_SSL_CTX(conn);
2316
2317 SSL_shutdown(conn);
2318 SSL_CTX_free(context);
2319 SSL_free(conn);
2320
2321 # elif defined(HAVE_GNUTLS)
2322 http_tls_t *conn; /* Encryption session */
2323 gnutls_certificate_client_credentials *credentials;
2324 /* TLS credentials */
2325
2326
2327 conn = (http_tls_t *)(http->tls);
2328 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
2329
2330 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
2331 gnutls_deinit(conn->session);
2332 gnutls_certificate_free_credentials(*credentials);
2333 free(credentials);
2334 free(conn);
2335
2336 # elif defined(HAVE_CDSASSL)
2337 SSLClose((SSLContextRef)http->tls);
2338 SSLDisposeContext((SSLContextRef)http->tls);
2339 # endif /* HAVE_LIBSSL */
2340
2341 http->tls = NULL;
2342 }
2343 #endif /* HAVE_SSL */
2344
2345
2346 #ifdef HAVE_SSL
2347 /*
2348 * 'http_upgrade()' - Force upgrade to TLS encryption.
2349 */
2350
2351 static int /* O - Status of connection */
2352 http_upgrade(http_t *http) /* I - HTTP data */
2353 {
2354 int ret; /* Return value */
2355 http_t myhttp; /* Local copy of HTTP data */
2356
2357
2358 DEBUG_printf(("http_upgrade(%p)\n", http));
2359
2360 /*
2361 * Copy the HTTP data to a local variable so we can do the OPTIONS
2362 * request without interfering with the existing request data...
2363 */
2364
2365 memcpy(&myhttp, http, sizeof(myhttp));
2366
2367 /*
2368 * Send an OPTIONS request to the server, requiring SSL or TLS
2369 * encryption on the link...
2370 */
2371
2372 httpClearFields(&myhttp);
2373 httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade");
2374 httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
2375
2376 if ((ret = httpOptions(&myhttp, "*")) == 0)
2377 {
2378 /*
2379 * Wait for the secure connection...
2380 */
2381
2382 while (httpUpdate(&myhttp) == HTTP_CONTINUE);
2383 }
2384
2385 httpFlush(&myhttp);
2386
2387 /*
2388 * Copy the HTTP data back over, if any...
2389 */
2390
2391 http->fd = myhttp.fd;
2392 http->error = myhttp.error;
2393 http->activity = myhttp.activity;
2394 http->status = myhttp.status;
2395 http->version = myhttp.version;
2396 http->keep_alive = myhttp.keep_alive;
2397 http->used = myhttp.used;
2398
2399 if (http->used)
2400 memcpy(http->buffer, myhttp.buffer, http->used);
2401
2402 http->auth_type = myhttp.auth_type;
2403 http->nonce_count = myhttp.nonce_count;
2404
2405 memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce));
2406
2407 http->tls = myhttp.tls;
2408 http->encryption = myhttp.encryption;
2409
2410 /*
2411 * See if we actually went secure...
2412 */
2413
2414 if (!http->tls)
2415 {
2416 /*
2417 * Server does not support HTTP upgrade...
2418 */
2419
2420 DEBUG_puts("Server does not support HTTP upgrade!");
2421
2422 # ifdef WIN32
2423 closesocket(http->fd);
2424 # else
2425 close(http->fd);
2426 # endif
2427
2428 http->fd = -1;
2429
2430 return (-1);
2431 }
2432 else
2433 return (ret);
2434 }
2435 #endif /* HAVE_SSL */
2436
2437
2438 /*
2439 * 'http_wait()' - Wait for data available on a connection.
2440 */
2441
2442 static int /* O - 1 if data is available, 0 otherwise */
2443 http_wait(http_t *http, /* I - HTTP data */
2444 int msec) /* I - Milliseconds to wait */
2445 {
2446 #ifndef WIN32
2447 struct rlimit limit; /* Runtime limit */
2448 #endif /* !WIN32 */
2449 struct timeval timeout; /* Timeout */
2450 int nfds; /* Result from select() */
2451 int set_size; /* Size of select set */
2452
2453
2454 DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
2455
2456 /*
2457 * Check the SSL/TLS buffers for data first...
2458 */
2459
2460 #ifdef HAVE_SSL
2461 if (http->tls)
2462 {
2463 # ifdef HAVE_LIBSSL
2464 if (SSL_pending((SSL *)(http->tls)))
2465 return (1);
2466 # elif defined(HAVE_GNUTLS)
2467 if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
2468 return (1);
2469 # elif defined(HAVE_CDSASSL)
2470 size_t bytes; /* Bytes that are available */
2471
2472 if (!SSLGetBufferedReadSize((SSLContextRef)http->tls, &bytes) && bytes > 0)
2473 return (1);
2474 # endif /* HAVE_LIBSSL */
2475 }
2476 #endif /* HAVE_SSL */
2477
2478 /*
2479 * Then try doing a select() to poll the socket...
2480 */
2481
2482 if (!http->input_set)
2483 {
2484 #ifdef WIN32
2485 /*
2486 * Windows has a fixed-size select() structure, different (surprise,
2487 * surprise!) from all UNIX implementations. Just allocate this
2488 * fixed structure...
2489 */
2490
2491 http->input_set = calloc(1, sizeof(fd_set));
2492 #else
2493 /*
2494 * Allocate the select() input set based upon the max number of file
2495 * descriptors available for this process...
2496 */
2497
2498 getrlimit(RLIMIT_NOFILE, &limit);
2499
2500 set_size = (limit.rlim_cur + 31) / 8 + 4;
2501 if (set_size < sizeof(fd_set))
2502 set_size = sizeof(fd_set);
2503
2504 http->input_set = calloc(1, set_size);
2505 #endif /* WIN32 */
2506
2507 if (!http->input_set)
2508 return (0);
2509 }
2510
2511 do
2512 {
2513 FD_SET(http->fd, http->input_set);
2514
2515 if (msec >= 0)
2516 {
2517 timeout.tv_sec = msec / 1000;
2518 timeout.tv_usec = (msec % 1000) * 1000;
2519
2520 nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout);
2521 }
2522 else
2523 nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
2524 }
2525 #ifdef WIN32
2526 while (nfds < 0 && WSAGetLastError() == WSAEINTR);
2527 #else
2528 while (nfds < 0 && errno == EINTR);
2529 #endif /* WIN32 */
2530
2531 FD_CLR(http->fd, http->input_set);
2532
2533 return (nfds > 0);
2534 }
2535
2536
2537 /*
2538 * 'http_write()' - Write a buffer to a HTTP connection.
2539 */
2540
2541 static int /* O - Number of bytes written */
2542 http_write(http_t *http, /* I - HTTP data */
2543 const char *buffer, /* I - Buffer for data */
2544 int length) /* I - Number of bytes to write */
2545 {
2546 int tbytes, /* Total bytes sent */
2547 bytes; /* Bytes sent */
2548
2549
2550 tbytes = 0;
2551
2552 while (length > 0)
2553 {
2554 #ifdef HAVE_SSL
2555 if (http->tls)
2556 bytes = http_write_ssl(http, buffer, length);
2557 else
2558 #endif /* HAVE_SSL */
2559 bytes = send(http->fd, buffer, length, 0);
2560
2561 if (bytes < 0)
2562 {
2563 #ifdef WIN32
2564 if (WSAGetLastError() != http->error)
2565 {
2566 http->error = WSAGetLastError();
2567 continue;
2568 }
2569 #else
2570 if (errno == EINTR)
2571 continue;
2572 else if (errno != http->error && errno != ECONNRESET)
2573 {
2574 http->error = errno;
2575 continue;
2576 }
2577 #endif /* WIN32 */
2578
2579 DEBUG_puts("http_write: error writing data...\n");
2580
2581 return (-1);
2582 }
2583
2584 buffer += bytes;
2585 tbytes += bytes;
2586 length -= bytes;
2587 }
2588
2589 #ifdef DEBUG
2590 {
2591 int i, j, ch;
2592 printf("http_write: wrote %d bytes: \n", tbytes);
2593 for (i = 0, buffer -= tbytes; i < tbytes; i += 16)
2594 {
2595 printf(" ");
2596
2597 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
2598 printf(" %02X", buffer[i + j] & 255);
2599
2600 while (j < 16)
2601 {
2602 printf(" ");
2603 j ++;
2604 }
2605
2606 printf(" ");
2607 for (j = 0; j < 16 && (i + j) < tbytes; j ++)
2608 {
2609 ch = buffer[i + j] & 255;
2610
2611 if (ch < ' ' || ch == 127)
2612 ch = '.';
2613
2614 putchar(ch);
2615 }
2616 putchar('\n');
2617 }
2618 }
2619 #endif /* DEBUG */
2620
2621 return (tbytes);
2622 }
2623
2624
2625 #if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2626 /*
2627 * 'http_write_cdsa()' - Write function for CDSA encryption code.
2628 */
2629
2630 static OSStatus /* O - -1 on error, 0 on success */
2631 http_write_cdsa(
2632 SSLConnectionRef connection, /* I - SSL/TLS connection */
2633 const void *data, /* I - Data buffer */
2634 size_t *dataLength) /* IO - Number of bytes */
2635 {
2636 ssize_t bytes; /* Number of write written */
2637
2638
2639 bytes = write((int)connection, data, *dataLength);
2640 if (bytes >= 0)
2641 {
2642 *dataLength = bytes;
2643 return (0);
2644 }
2645 else
2646 return (-1);
2647 }
2648 #endif /* HAVE_SSL && HAVE_CDSASSL */
2649
2650
2651 /*
2652 * 'http_write_chunk()' - Write a chunked buffer.
2653 */
2654
2655 static int /* O - Number bytes written */
2656 http_write_chunk(http_t *http, /* I - HTTP data */
2657 const char *buffer, /* I - Buffer to write */
2658 int length) /* I - Length of buffer */
2659 {
2660 char header[255]; /* Chunk header */
2661 int bytes; /* Bytes written */
2662
2663 DEBUG_printf(("http_write_chunk(http=%p, buffer=%p, length=%d)\n",
2664 http, buffer, length));
2665
2666 /*
2667 * Write the chunk header, data, and trailer.
2668 */
2669
2670 sprintf(header, "%x\r\n", length);
2671 if (http_write(http, header, strlen(header)) < 0)
2672 return (-1);
2673
2674 if ((bytes = http_write(http, buffer, length)) < 0)
2675 return (-1);
2676
2677 if (http_write(http, "\r\n", 2) < 0)
2678 return (-1);
2679
2680 return (bytes);
2681 }
2682
2683
2684 #ifdef HAVE_SSL
2685 /*
2686 * 'http_write_ssl()' - Write to a SSL/TLS connection.
2687 */
2688
2689 static int /* O - Bytes written */
2690 http_write_ssl(http_t *http, /* I - HTTP data */
2691 const char *buf, /* I - Buffer holding data */
2692 int len) /* I - Length of buffer */
2693 {
2694 # if defined(HAVE_LIBSSL)
2695 return (SSL_write((SSL *)(http->tls), buf, len));
2696
2697 # elif defined(HAVE_GNUTLS)
2698 return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
2699 # elif defined(HAVE_CDSASSL)
2700 OSStatus error; /* Error info */
2701 size_t processed; /* Number of bytes processed */
2702
2703
2704 error = SSLWrite((SSLContextRef)http->tls, buf, len, &processed);
2705
2706 if (error == 0)
2707 return (processed);
2708 else
2709 {
2710 http->error = error;
2711 return (-1);
2712 }
2713 # endif /* HAVE_LIBSSL */
2714 }
2715 #endif /* HAVE_SSL */
2716
2717
2718 /*
2719 * End of "$Id$".
2720 */