]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/http.c
Merge changes from CUPS 1.5svn-r9105.
[thirdparty/cups.git] / cups / http.c
CommitLineData
ef416fc2 1/*
b19ccc9e 2 * "$Id: http.c 7850 2008-08-20 00:07:25Z mike $"
ef416fc2 3 *
71e16022 4 * HTTP routines for CUPS.
ef416fc2 5 *
71e16022 6 * Copyright 2007-2010 by Apple Inc.
b86bc4cf 7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
ef416fc2 8 *
f7deaa1a 9 * This file contains Kerberos support code, copyright 2006 by
10 * Jelmer Vernooij.
11 *
ef416fc2 12 * These coded instructions, statements, and computer programs are the
bc44d920 13 * property of Apple Inc. and are protected by Federal copyright
14 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
15 * which should have been included with this file. If this file is
16 * file is missing or damaged, see the license at "http://www.cups.org/".
ef416fc2 17 *
18 * This file is subject to the Apple OS-Developed Software exception.
19 *
20 * Contents:
21 *
411affcf 22 * _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP connections.
ecdc0628 23 * httpBlocking() - Set blocking/non-blocking behavior on a connection.
38e73f87
MS
24 * httpCheck() - Check to see if there is a pending response from the
25 * server.
ef416fc2 26 * httpClearCookie() - Clear the cookie value(s).
ecdc0628 27 * httpClearFields() - Clear HTTP request fields.
6d2f911b
MS
28 * httpClose() - Close an HTTP connection.
29 * httpConnect() - Connect to a HTTP server.
ef416fc2 30 * httpConnectEncrypt() - Connect to a HTTP server using encryption.
38e73f87 31 * _httpCreate() - Create an unconnected HTTP connection.
ef416fc2 32 * httpDelete() - Send a DELETE request to the server.
6d2f911b 33 * _httpDisconnect() - Disconnect a HTTP connection.
ef416fc2 34 * httpEncryption() - Set the required encryption on the link.
ecdc0628 35 * httpError() - Get the last error on a connection.
ef416fc2 36 * httpFlush() - Flush data from a HTTP connection.
37 * httpFlushWrite() - Flush data in write buffer.
38 * httpGet() - Send a GET request to the server.
355e94dc 39 * httpGetAuthString() - Get the current authorization string.
ecdc0628 40 * httpGetBlocking() - Get the blocking/non-block state of a connection.
41 * httpGetCookie() - Get any cookie data from the response.
42 * httpGetFd() - Get the file descriptor associated with a
43 * connection.
44 * httpGetField() - Get a field value from a request/response.
ef416fc2 45 * httpGetLength() - Get the amount of data remaining from the
46 * content-length or transfer-encoding fields.
47 * httpGetLength2() - Get the amount of data remaining from the
48 * content-length or transfer-encoding fields.
ecdc0628 49 * httpGetStatus() - Get the status of the last HTTP request.
ef416fc2 50 * httpGetSubField() - Get a sub-field value.
38e73f87 51 * httpGetSubField2() - Get a sub-field value.
ef416fc2 52 * httpGets() - Get a line of text from a HTTP connection.
53 * httpHead() - Send a HEAD request to the server.
54 * httpInitialize() - Initialize the HTTP interface library and set the
55 * default HTTP proxy (if any).
56 * httpOptions() - Send an OPTIONS request to the server.
6d2f911b 57 * _httpPeek() - Peek at data from a HTTP connection.
ef416fc2 58 * httpPost() - Send a POST request to the server.
59 * httpPrintf() - Print a formatted string to a HTTP connection.
60 * httpPut() - Send a PUT request to the server.
61 * httpRead() - Read data from a HTTP connection.
a4d04587 62 * httpRead2() - Read data from a HTTP connection.
411affcf 63 * _httpReadCDSA() - Read function for the CDSA library.
64 * _httpReadGNUTLS() - Read function for the GNU TLS library.
38e73f87 65 * httpReconnect() - Reconnect to a HTTP server.
355e94dc 66 * httpSetAuthString() - Set the current authorization string.
6d2f911b 67 * httpSetCookie() - Set the cookie value(s).
b423cd4c 68 * httpSetExpect() - Set the Expect: header in a request.
ef416fc2 69 * httpSetField() - Set the value of an HTTP header.
38e73f87 70 * httpSetLength() - Set the content-length and content-encoding.
ef416fc2 71 * httpTrace() - Send an TRACE request to the server.
72 * httpUpdate() - Update the current HTTP state for incoming data.
38e73f87 73 * _httpWait() - Wait for data available on a connection (no flush).
ef416fc2 74 * httpWait() - Wait for data available on a connection.
75 * httpWrite() - Write data to a HTTP connection.
a4d04587 76 * httpWrite2() - Write data to a HTTP connection.
411affcf 77 * _httpWriteCDSA() - Write function for the CDSA library.
78 * _httpWriteGNUTLS() - Write function for the GNU TLS library.
79 * http_bio_ctrl() - Control the HTTP connection.
80 * http_bio_free() - Free OpenSSL data.
81 * http_bio_new() - Initialize an OpenSSL BIO structure.
82 * http_bio_puts() - Send a string for OpenSSL.
83 * http_bio_read() - Read data for OpenSSL.
84 * http_bio_write() - Write data for OpenSSL.
ae71f5de 85 * http_debug_hex() - Do a hex dump of a buffer.
ef416fc2 86 * http_field() - Return the field index for a field name.
87 * http_read_ssl() - Read from a SSL/TLS connection.
6d2f911b 88 * http_locking_cb() - Lock/unlock a thread's mutex.
ef416fc2 89 * http_send() - Send a request with all fields and the trailing
90 * blank line.
38e73f87 91 * http_setup_ssl() - Set up SSL/TLS support on a connection.
ef416fc2 92 * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
6d2f911b 93 * http_threadid_cb() - Return the current thread ID.
ef416fc2 94 * http_upgrade() - Force upgrade to TLS encryption.
38e73f87
MS
95 * http_write() - Write a buffer to a HTTP connection.
96 * http_write_chunk() - Write a chunked buffer.
ef416fc2 97 * http_write_ssl() - Write to a SSL/TLS connection.
98 */
99
100/*
101 * Include necessary headers...
102 */
103
71e16022 104#include "cups-private.h"
ef416fc2 105#include <fcntl.h>
ef416fc2 106#ifndef WIN32
107# include <signal.h>
108# include <sys/time.h>
109# include <sys/resource.h>
110#endif /* !WIN32 */
f7deaa1a 111#ifdef HAVE_POLL
112# include <sys/poll.h>
113#endif /* HAVE_POLL */
ef416fc2 114
115
116/*
117 * Some operating systems have done away with the Fxxxx constants for
118 * the fcntl() call; this works around that "feature"...
119 */
120
121#ifndef FNONBLK
122# define FNONBLK O_NONBLOCK
123#endif /* !FNONBLK */
124
125
126/*
127 * Local functions...
128 */
129
ae71f5de
MS
130#ifdef DEBUG
131static void http_debug_hex(const char *prefix, const char *buffer,
132 int bytes);
133#endif /* DEBUG */
ef416fc2 134static http_field_t http_field(const char *name);
135static int http_send(http_t *http, http_state_t request,
136 const char *uri);
ef416fc2 137static int http_write(http_t *http, const char *buffer,
138 int length);
139static int http_write_chunk(http_t *http, const char *buffer,
140 int length);
141#ifdef HAVE_SSL
142static int http_read_ssl(http_t *http, char *buf, int len);
143static int http_setup_ssl(http_t *http);
144static void http_shutdown_ssl(http_t *http);
145static int http_upgrade(http_t *http);
146static int http_write_ssl(http_t *http, const char *buf, int len);
6d2f911b
MS
147
148# ifdef HAVE_GNUTLS
149# ifdef HAVE_PTHREAD_H
150GCRY_THREAD_OPTION_PTHREAD_IMPL;
151# endif /* HAVE_PTHREAD_H */
152
153# elif defined(HAVE_LIBSSL)
154static _cups_mutex_t *http_locks; /* OpenSSL lock mutexes */
155
156static void http_locking_cb(int mode, int type, const char *file,
157 int line);
158static unsigned long http_threadid_cb(void);
159# endif /* HAVE_GNUTLS */
ef416fc2 160#endif /* HAVE_SSL */
161
162
163/*
164 * Local globals...
165 */
166
167static const char * const http_fields[] =
168 {
169 "Accept-Language",
170 "Accept-Ranges",
171 "Authorization",
172 "Connection",
173 "Content-Encoding",
174 "Content-Language",
175 "Content-Length",
176 "Content-Location",
177 "Content-MD5",
178 "Content-Range",
179 "Content-Type",
180 "Content-Version",
181 "Date",
182 "Host",
183 "If-Modified-Since",
184 "If-Unmodified-since",
185 "Keep-Alive",
186 "Last-Modified",
187 "Link",
188 "Location",
189 "Range",
190 "Referer",
191 "Retry-After",
192 "Transfer-Encoding",
193 "Upgrade",
194 "User-Agent",
195 "WWW-Authenticate"
196 };
f11a948a
MS
197#ifdef DEBUG
198static const char * const http_states[] =
199 {
200 "HTTP_WAITING",
201 "HTTP_OPTIONS",
202 "HTTP_GET",
203 "HTTP_GET_SEND",
204 "HTTP_HEAD",
205 "HTTP_POST",
206 "HTTP_POST_RECV",
207 "HTTP_POST_SEND",
208 "HTTP_PUT",
209 "HTTP_PUT_RECV",
210 "HTTP_DELETE",
211 "HTTP_TRACE",
212 "HTTP_CLOSE",
213 "HTTP_STATUS"
214 };
215#endif /* DEBUG */
ef416fc2 216
217
411affcf 218#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
219/*
220 * BIO methods for OpenSSL...
221 */
222
223static int http_bio_write(BIO *h, const char *buf, int num);
224static int http_bio_read(BIO *h, char *buf, int size);
225static int http_bio_puts(BIO *h, const char *str);
226static long http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
227static int http_bio_new(BIO *h);
228static int http_bio_free(BIO *data);
229
230static BIO_METHOD http_bio_methods =
231 {
232 BIO_TYPE_SOCKET,
233 "http",
234 http_bio_write,
235 http_bio_read,
236 http_bio_puts,
237 NULL, /* http_bio_gets, */
238 http_bio_ctrl,
239 http_bio_new,
240 http_bio_free,
241 NULL,
242 };
243
244
245/*
246 * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
247 */
248
249BIO_METHOD * /* O - BIO methods for OpenSSL */
250_httpBIOMethods(void)
251{
252 return (&http_bio_methods);
253}
254#endif /* HAVE_SSL && HAVE_LIBSSL */
255
256
ecdc0628 257/*
258 * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
259 */
260
261void
568fa3fa 262httpBlocking(http_t *http, /* I - Connection to server */
ecdc0628 263 int b) /* I - 1 = blocking, 0 = non-blocking */
264{
265 if (http)
266 http->blocking = b;
267}
268
269
ef416fc2 270/*
271 * 'httpCheck()' - Check to see if there is a pending response from the server.
272 */
273
ecdc0628 274int /* O - 0 = no data, 1 = data available */
568fa3fa 275httpCheck(http_t *http) /* I - Connection to server */
ef416fc2 276{
277 return (httpWait(http, 0));
278}
279
280
281/*
282 * 'httpClearCookie()' - Clear the cookie value(s).
283 *
426c6a59 284 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 285 */
286
287void
568fa3fa 288httpClearCookie(http_t *http) /* I - Connection to server */
ef416fc2 289{
290 if (!http)
291 return;
292
293 if (http->cookie)
294 {
295 free(http->cookie);
296 http->cookie = NULL;
297 }
298}
299
300
ecdc0628 301/*
302 * 'httpClearFields()' - Clear HTTP request fields.
303 */
304
305void
568fa3fa 306httpClearFields(http_t *http) /* I - Connection to server */
ecdc0628 307{
308 if (http)
309 {
310 memset(http->fields, 0, sizeof(http->fields));
07725fee 311 if (http->hostname[0] == '/')
312 httpSetField(http, HTTP_FIELD_HOST, "localhost");
313 else
314 httpSetField(http, HTTP_FIELD_HOST, http->hostname);
b423cd4c 315
f7deaa1a 316 if (http->field_authorization)
317 {
318 free(http->field_authorization);
319 http->field_authorization = NULL;
320 }
321
b423cd4c 322 http->expect = (http_status_t)0;
ecdc0628 323 }
324}
325
326
ef416fc2 327/*
6d2f911b 328 * 'httpClose()' - Close an HTTP connection.
ef416fc2 329 */
330
331void
568fa3fa 332httpClose(http_t *http) /* I - Connection to server */
ef416fc2 333{
f7deaa1a 334#ifdef HAVE_GSSAPI
1f0275e3 335 OM_uint32 minor_status; /* Minor status code */
f7deaa1a 336#endif /* HAVE_GSSAPI */
337
338
e07d4801 339 DEBUG_printf(("httpClose(http=%p)", http));
ef416fc2 340
6d2f911b
MS
341 /*
342 * Range check input...
343 */
344
ef416fc2 345 if (!http)
346 return;
347
6d2f911b
MS
348 /*
349 * Close any open connection...
350 */
351
352 _httpDisconnect(http);
353
354 /*
355 * Free memory used...
356 */
357
ef416fc2 358 httpAddrFreeList(http->addrlist);
359
ef416fc2 360 if (http->cookie)
361 free(http->cookie);
362
f7deaa1a 363#ifdef HAVE_GSSAPI
364 if (http->gssctx != GSS_C_NO_CONTEXT)
1f0275e3 365 gss_delete_sec_context(&minor_status, &http->gssctx, GSS_C_NO_BUFFER);
f7deaa1a 366
367 if (http->gssname != GSS_C_NO_NAME)
1f0275e3 368 gss_release_name(&minor_status, &http->gssname);
f7deaa1a 369#endif /* HAVE_GSSAPI */
370
b94498cf 371#ifdef HAVE_AUTHORIZATION_H
372 if (http->auth_ref)
373 AuthorizationFree(http->auth_ref, kAuthorizationFlagDefaults);
374#endif /* HAVE_AUTHORIZATION_H */
375
f7deaa1a 376 httpClearFields(http);
377
378 if (http->authstring && http->authstring != http->_authstring)
379 free(http->authstring);
380
ef416fc2 381 free(http);
382}
383
384
385/*
386 * 'httpConnect()' - Connect to a HTTP server.
1ff0402e
MS
387 *
388 * This function is deprecated - use @link httpConnectEncrypt@ instead.
389 *
390 * @deprecated@
ef416fc2 391 */
392
393http_t * /* O - New HTTP connection */
394httpConnect(const char *host, /* I - Host to connect to */
395 int port) /* I - Port number */
396{
1ff0402e
MS
397 return (httpConnectEncrypt(host, port, HTTP_ENCRYPT_IF_REQUESTED));
398}
399
400
401/*
402 * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
403 */
404
405http_t * /* O - New HTTP connection */
406httpConnectEncrypt(
407 const char *host, /* I - Host to connect to */
408 int port, /* I - Port number */
409 http_encryption_t encryption) /* I - Type of encryption to use */
410{
411 http_t *http; /* New HTTP connection */
ef416fc2 412
413
e07d4801 414 DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)",
1ff0402e
MS
415 host, port, encryption));
416
ef416fc2 417 /*
1ff0402e 418 * Create the HTTP structure...
ef416fc2 419 */
420
1ff0402e
MS
421 if ((http = _httpCreate(host, port, encryption)) == NULL)
422 return (NULL);
ef416fc2 423
1ff0402e
MS
424 /*
425 * Connect to the remote system...
426 */
427
428 if (!httpReconnect(http))
429 return (http);
430
431 /*
432 * Could not connect to any known address - bail out!
433 */
434
435 httpAddrFreeList(http->addrlist);
436
437 free(http);
438
439 return (NULL);
ef416fc2 440}
441
442
443/*
1ff0402e 444 * '_httpCreate()' - Create an unconnected HTTP connection.
ef416fc2 445 */
446
1ff0402e
MS
447http_t * /* O - HTTP connection */
448_httpCreate(
449 const char *host, /* I - Hostname */
ef416fc2 450 int port, /* I - Port number */
1ff0402e 451 http_encryption_t encryption) /* I - Encryption to use */
ef416fc2 452{
453 http_t *http; /* New HTTP connection */
454 http_addrlist_t *addrlist; /* Host address data */
455 char service[255]; /* Service name */
456
457
e07d4801 458 DEBUG_printf(("4_httpCreate(host=\"%s\", port=%d, encryption=%d)",
1ff0402e 459 host, port, encryption));
ef416fc2 460
461 if (!host)
462 return (NULL);
463
464 httpInitialize();
465
466 /*
467 * Lookup the host...
468 */
469
470 sprintf(service, "%d", port);
471
472 if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
473 return (NULL);
474
475 /*
476 * Allocate memory for the structure...
477 */
478
91c84a35
MS
479 if ((http = calloc(sizeof(http_t), 1)) == NULL)
480 {
481 httpAddrFreeList(addrlist);
ef416fc2 482 return (NULL);
91c84a35 483 }
ef416fc2 484
1ff0402e
MS
485 /*
486 * Initialize the HTTP data...
487 */
488
ef416fc2 489 http->activity = time(NULL);
1ff0402e
MS
490 http->addrlist = addrlist;
491 http->blocking = 1;
ef416fc2 492 http->fd = -1;
f7deaa1a 493#ifdef HAVE_GSSAPI
1ff0402e
MS
494 http->gssctx = GSS_C_NO_CONTEXT;
495 http->gssname = GSS_C_NO_NAME;
f7deaa1a 496#endif /* HAVE_GSSAPI */
1ff0402e 497 http->version = HTTP_1_1;
f7deaa1a 498
1ff0402e 499 strlcpy(http->hostname, host, sizeof(http->hostname));
ef416fc2 500
501 if (port == 443) /* Always use encryption for https */
502 http->encryption = HTTP_ENCRYPT_ALWAYS;
503 else
504 http->encryption = encryption;
505
506 /*
1ff0402e 507 * Return the new structure...
ef416fc2 508 */
509
1ff0402e 510 return (http);
ef416fc2 511}
512
513
514/*
515 * 'httpDelete()' - Send a DELETE request to the server.
516 */
517
518int /* O - Status of call (0 = success) */
568fa3fa 519httpDelete(http_t *http, /* I - Connection to server */
ef416fc2 520 const char *uri) /* I - URI to delete */
521{
522 return (http_send(http, HTTP_DELETE, uri));
523}
524
525
6d2f911b
MS
526/*
527 * '_httpDisconnect()' - Disconnect a HTTP connection.
528 */
529
530void
531_httpDisconnect(http_t *http) /* I - Connection to server */
532{
533#ifdef HAVE_SSL
534 if (http->tls)
535 http_shutdown_ssl(http);
536#endif /* HAVE_SSL */
537
538#ifdef WIN32
539 closesocket(http->fd);
540#else
541 close(http->fd);
542#endif /* WIN32 */
543
544 http->fd = -1;
545}
546
547
ef416fc2 548/*
549 * 'httpEncryption()' - Set the required encryption on the link.
550 */
551
552int /* O - -1 on error, 0 on success */
568fa3fa 553httpEncryption(http_t *http, /* I - Connection to server */
ef416fc2 554 http_encryption_t e) /* I - New encryption preference */
555{
e07d4801 556 DEBUG_printf(("httpEncryption(http=%p, e=%d)", http, e));
ef416fc2 557
558#ifdef HAVE_SSL
559 if (!http)
560 return (0);
561
562 http->encryption = e;
563
564 if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
565 (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
566 return (httpReconnect(http));
567 else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
568 return (http_upgrade(http));
569 else
570 return (0);
571#else
572 if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
573 return (-1);
574 else
575 return (0);
576#endif /* HAVE_SSL */
577}
578
579
ecdc0628 580/*
581 * 'httpError()' - Get the last error on a connection.
582 */
583
584int /* O - Error code (errno) value */
568fa3fa 585httpError(http_t *http) /* I - Connection to server */
ecdc0628 586{
587 if (http)
588 return (http->error);
589 else
590 return (EINVAL);
591}
592
593
ef416fc2 594/*
595 * 'httpFlush()' - Flush data from a HTTP connection.
596 */
597
598void
568fa3fa 599httpFlush(http_t *http) /* I - Connection to server */
ef416fc2 600{
f8b3a85b
MS
601 char buffer[8192]; /* Junk buffer */
602 int blocking; /* To block or not to block */
603 http_state_t oldstate; /* Old state */
ef416fc2 604
605
f11a948a
MS
606 DEBUG_printf(("httpFlush(http=%p), state=%s", http,
607 http_states[http->state]));
ef416fc2 608
fa73b229 609 /*
610 * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
611 */
612
613 blocking = http->blocking;
614 http->blocking = 0;
615
616 /*
617 * Read any data we can...
618 */
619
f8b3a85b 620 oldstate = http->state;
a4d04587 621 while (httpRead2(http, buffer, sizeof(buffer)) > 0);
fa73b229 622
623 /*
624 * Restore blocking and reset the connection if we didn't get all of
625 * the remaining data...
626 */
627
628 http->blocking = blocking;
629
aaf19ab0 630 if (http->state == oldstate && http->state != HTTP_WAITING && http->fd >= 0)
fa73b229 631 {
632 /*
633 * Didn't get the data back, so close the current connection.
634 */
635
636 http->state = HTTP_WAITING;
637
638#ifdef HAVE_SSL
639 if (http->tls)
640 http_shutdown_ssl(http);
641#endif /* HAVE_SSL */
642
643#ifdef WIN32
644 closesocket(http->fd);
645#else
646 close(http->fd);
647#endif /* WIN32 */
648
649 http->fd = -1;
650 }
ef416fc2 651}
652
653
654/*
655 * 'httpFlushWrite()' - Flush data in write buffer.
656 *
426c6a59 657 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 658 */
659
660int /* O - Bytes written or -1 on error */
568fa3fa 661httpFlushWrite(http_t *http) /* I - Connection to server */
ef416fc2 662{
663 int bytes; /* Bytes written */
664
665
e07d4801 666 DEBUG_printf(("httpFlushWrite(http=%p)", http));
ef416fc2 667
668 if (!http || !http->wused)
f8b3a85b
MS
669 {
670 DEBUG_puts(http ? "1httpFlushWrite: Write buffer is empty." :
671 "1httpFlushWrite: No connection.");
ef416fc2 672 return (0);
f8b3a85b 673 }
ef416fc2 674
675 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
676 bytes = http_write_chunk(http, http->wbuffer, http->wused);
677 else
678 bytes = http_write(http, http->wbuffer, http->wused);
679
680 http->wused = 0;
681
f8b3a85b
MS
682 DEBUG_printf(("1httpFlushWrite: Returning %d.", bytes));
683
ef416fc2 684 return (bytes);
685}
686
687
688/*
689 * 'httpGet()' - Send a GET request to the server.
690 */
691
692int /* O - Status of call (0 = success) */
568fa3fa 693httpGet(http_t *http, /* I - Connection to server */
ef416fc2 694 const char *uri) /* I - URI to get */
695{
696 return (http_send(http, HTTP_GET, uri));
697}
698
699
355e94dc
MS
700/*
701 * 'httpGetAuthString()' - Get the current authorization string.
702 *
703 * The authorization string is set by cupsDoAuthentication() and
704 * httpSetAuthString(). Use httpGetAuthString() to retrieve the
705 * string to use with httpSetField() for the HTTP_FIELD_AUTHORIZATION
706 * value.
707 *
426c6a59 708 * @since CUPS 1.3/Mac OS X 10.5@
355e94dc
MS
709 */
710
711char * /* O - Authorization string */
568fa3fa 712httpGetAuthString(http_t *http) /* I - Connection to server */
355e94dc
MS
713{
714 if (http)
715 return (http->authstring);
716 else
717 return (NULL);
718}
719
720
ecdc0628 721/*
722 * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
723 *
426c6a59 724 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 725 */
726
727int /* O - 1 if blocking, 0 if non-blocking */
568fa3fa 728httpGetBlocking(http_t *http) /* I - Connection to server */
ecdc0628 729{
730 return (http ? http->blocking : 0);
731}
732
733
734/*
735 * 'httpGetCookie()' - Get any cookie data from the response.
757d2cad 736 *
426c6a59 737 * @since CUPS 1.1.19/Mac OS X 10.3@
ecdc0628 738 */
739
740const char * /* O - Cookie data or NULL */
741httpGetCookie(http_t *http) /* I - HTTP connecion */
742{
743 return (http ? http->cookie : NULL);
744}
745
746
747/*
748 * 'httpGetFd()' - Get the file descriptor associated with a connection.
749 *
426c6a59 750 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 751 */
752
753int /* O - File descriptor or -1 if none */
568fa3fa 754httpGetFd(http_t *http) /* I - Connection to server */
ecdc0628 755{
756 return (http ? http->fd : -1);
757}
758
759
760/*
761 * 'httpGetField()' - Get a field value from a request/response.
762 */
763
764const char * /* O - Field value */
568fa3fa 765httpGetField(http_t *http, /* I - Connection to server */
ecdc0628 766 http_field_t field) /* I - Field to get */
767{
768 if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
769 return (NULL);
ef55b745 770 else if (field == HTTP_FIELD_AUTHORIZATION &&
f7deaa1a 771 http->field_authorization)
772 {
773 /*
774 * Special case for WWW-Authenticate: as its contents can be
775 * longer than HTTP_MAX_VALUE...
776 */
777
778 return (http->field_authorization);
779 }
ecdc0628 780 else
781 return (http->fields[field]);
782}
783
784
785/*
786 * 'httpGetLength()' - Get the amount of data remaining from the
787 * content-length or transfer-encoding fields.
788 *
789 * This function is deprecated and will not return lengths larger than
790 * 2^31 - 1; use httpGetLength2() instead.
791 *
792 * @deprecated@
793 */
794
795int /* O - Content length */
568fa3fa 796httpGetLength(http_t *http) /* I - Connection to server */
ecdc0628 797{
798 /*
799 * Get the read content length and return the 32-bit value.
800 */
801
802 if (http)
803 {
804 httpGetLength2(http);
805
806 return (http->_data_remaining);
807 }
808 else
809 return (-1);
810}
811
812
813/*
814 * 'httpGetLength2()' - Get the amount of data remaining from the
815 * content-length or transfer-encoding fields.
816 *
817 * This function returns the complete content length, even for
818 * content larger than 2^31 - 1.
819 *
426c6a59 820 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 821 */
822
823off_t /* O - Content length */
568fa3fa 824httpGetLength2(http_t *http) /* I - Connection to server */
ecdc0628 825{
f11a948a
MS
826 DEBUG_printf(("2httpGetLength2(http=%p), state=%s", http,
827 http_states[http->state]));
ecdc0628 828
829 if (!http)
830 return (-1);
831
832 if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
833 {
e07d4801 834 DEBUG_puts("4httpGetLength2: chunked request!");
ecdc0628 835
836 http->data_encoding = HTTP_ENCODE_CHUNKED;
837 http->data_remaining = 0;
838 }
839 else
840 {
841 http->data_encoding = HTTP_ENCODE_LENGTH;
842
843 /*
844 * The following is a hack for HTTP servers that don't send a
845 * content-length or transfer-encoding field...
846 *
847 * If there is no content-length then the connection must close
848 * after the transfer is complete...
849 */
850
b86bc4cf 851 if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
852 {
853 /*
854 * Default content length is 0 for errors and 2^31-1 for other
855 * successful requests...
856 */
857
858 if (http->status >= HTTP_MULTIPLE_CHOICES)
859 http->data_remaining = 0;
860 else
861 http->data_remaining = 2147483647;
862 }
ecdc0628 863 else
864 http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
865 NULL, 10);
866
e07d4801 867 DEBUG_printf(("4httpGetLength2: content_length=" CUPS_LLFMT,
ecdc0628 868 CUPS_LLCAST http->data_remaining));
869 }
870
871 if (http->data_remaining <= INT_MAX)
872 http->_data_remaining = (int)http->data_remaining;
873 else
874 http->_data_remaining = INT_MAX;
875
876 return (http->data_remaining);
877}
878
879
880/*
881 * 'httpGetStatus()' - Get the status of the last HTTP request.
882 *
426c6a59 883 * @since CUPS 1.2/Mac OS X 10.5@
ecdc0628 884 */
885
886http_status_t /* O - HTTP status */
568fa3fa 887httpGetStatus(http_t *http) /* I - Connection to server */
ecdc0628 888{
889 return (http ? http->status : HTTP_ERROR);
890}
891
892
ef416fc2 893/*
894 * 'httpGetSubField()' - Get a sub-field value.
895 *
896 * @deprecated@
897 */
898
899char * /* O - Value or NULL */
568fa3fa 900httpGetSubField(http_t *http, /* I - Connection to server */
ef416fc2 901 http_field_t field, /* I - Field index */
902 const char *name, /* I - Name of sub-field */
903 char *value) /* O - Value string */
904{
905 return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
906}
907
908
909/*
910 * 'httpGetSubField2()' - Get a sub-field value.
911 *
426c6a59 912 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 913 */
914
915char * /* O - Value or NULL */
568fa3fa 916httpGetSubField2(http_t *http, /* I - Connection to server */
ef416fc2 917 http_field_t field, /* I - Field index */
918 const char *name, /* I - Name of sub-field */
919 char *value, /* O - Value string */
920 int valuelen) /* I - Size of value buffer */
921{
922 const char *fptr; /* Pointer into field */
923 char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
924 *ptr, /* Pointer into string buffer */
925 *end; /* End of value buffer */
926
e07d4801
MS
927 DEBUG_printf(("2httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, "
928 "valuelen=%d)", http, field, name, value, valuelen));
ef416fc2 929
930 if (!http || !name || !value || valuelen < 2 ||
ecdc0628 931 field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
ef416fc2 932 return (NULL);
933
934 end = value + valuelen - 1;
935
936 for (fptr = http->fields[field]; *fptr;)
937 {
938 /*
939 * Skip leading whitespace...
940 */
941
942 while (isspace(*fptr & 255))
943 fptr ++;
944
945 if (*fptr == ',')
946 {
947 fptr ++;
948 continue;
949 }
950
951 /*
952 * Get the sub-field name...
953 */
954
955 for (ptr = temp;
956 *fptr && *fptr != '=' && !isspace(*fptr & 255) &&
957 ptr < (temp + sizeof(temp) - 1);
958 *ptr++ = *fptr++);
959
960 *ptr = '\0';
961
e07d4801 962 DEBUG_printf(("4httpGetSubField2: name=\"%s\"", temp));
ef416fc2 963
964 /*
965 * Skip trailing chars up to the '='...
966 */
967
968 while (isspace(*fptr & 255))
969 fptr ++;
970
971 if (!*fptr)
972 break;
973
974 if (*fptr != '=')
975 continue;
976
977 /*
978 * Skip = and leading whitespace...
979 */
980
981 fptr ++;
982
983 while (isspace(*fptr & 255))
984 fptr ++;
985
986 if (*fptr == '\"')
987 {
988 /*
989 * Read quoted string...
990 */
991
992 for (ptr = value, fptr ++;
993 *fptr && *fptr != '\"' && ptr < end;
994 *ptr++ = *fptr++);
995
996 *ptr = '\0';
997
998 while (*fptr && *fptr != '\"')
999 fptr ++;
1000
1001 if (*fptr)
1002 fptr ++;
1003 }
1004 else
1005 {
1006 /*
1007 * Read unquoted string...
1008 */
1009
1010 for (ptr = value;
1011 *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < end;
1012 *ptr++ = *fptr++);
1013
1014 *ptr = '\0';
1015
1016 while (*fptr && !isspace(*fptr & 255) && *fptr != ',')
1017 fptr ++;
1018 }
1019
e07d4801 1020 DEBUG_printf(("4httpGetSubField2: value=\"%s\"", value));
ef416fc2 1021
1022 /*
1023 * See if this is the one...
1024 */
1025
1026 if (!strcmp(name, temp))
e07d4801
MS
1027 {
1028 DEBUG_printf(("3httpGetSubField2: Returning \"%s\"", value));
ef416fc2 1029 return (value);
e07d4801 1030 }
ef416fc2 1031 }
1032
1033 value[0] = '\0';
1034
e07d4801
MS
1035 DEBUG_puts("3httpGetSubField2: Returning NULL");
1036
ef416fc2 1037 return (NULL);
1038}
1039
1040
ef416fc2 1041/*
1042 * 'httpGets()' - Get a line of text from a HTTP connection.
1043 */
1044
1045char * /* O - Line or NULL */
1046httpGets(char *line, /* I - Line to read into */
1047 int length, /* I - Max length of buffer */
568fa3fa 1048 http_t *http) /* I - Connection to server */
ef416fc2 1049{
1050 char *lineptr, /* Pointer into line */
1051 *lineend, /* End of line */
1052 *bufptr, /* Pointer into input buffer */
1053 *bufend; /* Pointer to end of buffer */
1054 int bytes, /* Number of bytes read */
1055 eol; /* End-of-line? */
1056
1057
e07d4801 1058 DEBUG_printf(("2httpGets(line=%p, length=%d, http=%p)", line, length, http));
ef416fc2 1059
1060 if (http == NULL || line == NULL)
1061 return (NULL);
1062
1063 /*
1064 * Read a line from the buffer...
1065 */
f11a948a
MS
1066
1067 http->error = 0;
1068 lineptr = line;
1069 lineend = line + length - 1;
1070 eol = 0;
ef416fc2 1071
1072 while (lineptr < lineend)
1073 {
1074 /*
1075 * Pre-load the buffer as needed...
1076 */
1077
1078#ifdef WIN32
1079 WSASetLastError(0);
1080#else
1081 errno = 0;
1082#endif /* WIN32 */
1083
1084 while (http->used == 0)
1085 {
1086 /*
1087 * No newline; see if there is more data to be read...
1088 */
1089
38e73f87 1090 if (!http->blocking && !_httpWait(http, 10000, 1))
89d46774 1091 {
e07d4801 1092 DEBUG_puts("3httpGets: Timed out!");
b86bc4cf 1093#ifdef WIN32
1094 http->error = WSAETIMEDOUT;
1095#else
89d46774 1096 http->error = ETIMEDOUT;
b86bc4cf 1097#endif /* WIN32 */
ef416fc2 1098 return (NULL);
89d46774 1099 }
ef416fc2 1100
1101#ifdef HAVE_SSL
1102 if (http->tls)
1103 bytes = http_read_ssl(http, http->buffer + http->used,
1104 HTTP_MAX_BUFFER - http->used);
1105 else
1106#endif /* HAVE_SSL */
1107 bytes = recv(http->fd, http->buffer + http->used,
1108 HTTP_MAX_BUFFER - http->used, 0);
1109
e07d4801 1110 DEBUG_printf(("4httpGets: read %d bytes...", bytes));
ef416fc2 1111
1112 if (bytes < 0)
1113 {
1114 /*
1115 * Nope, can't get a line this time...
1116 */
1117
1118#ifdef WIN32
1119 if (WSAGetLastError() != http->error)
1120 {
1121 http->error = WSAGetLastError();
1122 continue;
1123 }
1124
e07d4801 1125 DEBUG_printf(("3httpGets: recv() error %d!", WSAGetLastError()));
ef416fc2 1126#else
e07d4801 1127 DEBUG_printf(("3httpGets: recv() error %d!", errno));
ef416fc2 1128
e07d4801 1129 if (errno == EINTR || errno == EAGAIN)
ef416fc2 1130 continue;
1131 else if (errno != http->error)
1132 {
1133 http->error = errno;
1134 continue;
1135 }
1136#endif /* WIN32 */
1137
1138 return (NULL);
1139 }
1140 else if (bytes == 0)
1141 {
1142 http->error = EPIPE;
1143
1144 return (NULL);
1145 }
1146
1147 /*
1148 * Yup, update the amount used...
1149 */
1150
1151 http->used += bytes;
1152 }
1153
1154 /*
1155 * Now copy as much of the current line as possible...
1156 */
1157
1158 for (bufptr = http->buffer, bufend = http->buffer + http->used;
1159 lineptr < lineend && bufptr < bufend;)
1160 {
1161 if (*bufptr == 0x0a)
1162 {
1163 eol = 1;
1164 bufptr ++;
1165 break;
1166 }
1167 else if (*bufptr == 0x0d)
1168 bufptr ++;
1169 else
1170 *lineptr++ = *bufptr++;
1171 }
1172
b86bc4cf 1173 http->used -= (int)(bufptr - http->buffer);
ef416fc2 1174 if (http->used > 0)
1175 memmove(http->buffer, bufptr, http->used);
1176
1177 if (eol)
1178 {
1179 /*
1180 * End of line...
1181 */
1182
1183 http->activity = time(NULL);
1184
1185 *lineptr = '\0';
ef55b745 1186
e07d4801 1187 DEBUG_printf(("3httpGets: Returning \"%s\"", line));
ef416fc2 1188
1189 return (line);
1190 }
1191 }
1192
e07d4801 1193 DEBUG_puts("3httpGets: No new line available!");
ef416fc2 1194
1195 return (NULL);
1196}
1197
1198
1199/*
1200 * 'httpHead()' - Send a HEAD request to the server.
1201 */
1202
1203int /* O - Status of call (0 = success) */
568fa3fa 1204httpHead(http_t *http, /* I - Connection to server */
ef416fc2 1205 const char *uri) /* I - URI for head */
1206{
e07d4801 1207 DEBUG_printf(("httpHead(http=%p, uri=\"%s\")", http, uri));
ef416fc2 1208 return (http_send(http, HTTP_HEAD, uri));
1209}
1210
1211
1212/*
1213 * 'httpInitialize()' - Initialize the HTTP interface library and set the
1214 * default HTTP proxy (if any).
1215 */
1216
1217void
1218httpInitialize(void)
1219{
6d2f911b
MS
1220 static int initialized = 0; /* Have we been called before? */
1221#ifdef WIN32
1222 WSADATA winsockdata; /* WinSock data */
1223#endif /* WIN32 */
ef416fc2 1224#ifdef HAVE_LIBSSL
6d2f911b
MS
1225 int i; /* Looping var */
1226 unsigned char data[1024]; /* Seed data */
ef416fc2 1227#endif /* HAVE_LIBSSL */
1228
ef416fc2 1229
6d2f911b
MS
1230 _cupsGlobalLock();
1231 if (initialized)
1232 {
1233 _cupsGlobalUnlock();
1234 return;
1235 }
1236
1237#ifdef WIN32
1238 WSAStartup(MAKEWORD(1,1), &winsockdata);
ef416fc2 1239
fa73b229 1240#elif !defined(SO_NOSIGPIPE)
ef416fc2 1241 /*
1242 * Ignore SIGPIPE signals...
1243 */
1244
fa73b229 1245# ifdef HAVE_SIGSET
1246 sigset(SIGPIPE, SIG_IGN);
6d2f911b 1247
fa73b229 1248# elif defined(HAVE_SIGACTION)
1249 struct sigaction action; /* POSIX sigaction data */
1250
1251
ef416fc2 1252 memset(&action, 0, sizeof(action));
1253 action.sa_handler = SIG_IGN;
1254 sigaction(SIGPIPE, &action, NULL);
6d2f911b 1255
fa73b229 1256# else
ef416fc2 1257 signal(SIGPIPE, SIG_IGN);
fa73b229 1258# endif /* !SO_NOSIGPIPE */
ef416fc2 1259#endif /* WIN32 */
1260
1261#ifdef HAVE_GNUTLS
6d2f911b
MS
1262 /*
1263 * Make sure we handle threading properly...
1264 */
1265
1266# ifdef HAVE_PTHREAD_H
1267 gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread);
1268# endif /* HAVE_PTHREAD_H */
1269
1270 /*
1271 * Initialize GNU TLS...
1272 */
1273
ef416fc2 1274 gnutls_global_init();
ef416fc2 1275
6d2f911b
MS
1276#elif defined(HAVE_LIBSSL)
1277 /*
1278 * Initialize OpenSSL...
1279 */
1280
ef416fc2 1281 SSL_load_error_strings();
1282 SSL_library_init();
1283
6d2f911b
MS
1284 /*
1285 * Set the threading callbacks...
1286 */
1287
1288 http_locks = calloc(CRYPTO_num_locks(), sizeof(_cups_mutex_t));
1289# ifdef HAVE_PTHREAD_H
1290 for (i = 0; i < CRYPTO_num_locks(); i ++)
1291 pthread_mutex_init(http_locks + i, NULL);
1292# endif /* HAVE_PTHREAD_H */
1293
1294 CRYPTO_set_id_callback(http_threadid_cb);
1295 CRYPTO_set_locking_callback(http_locking_cb);
1296
ef416fc2 1297 /*
1298 * Using the current time is a dubious random seed, but on some systems
1299 * it is the best we can do (on others, this seed isn't even used...)
1300 */
1301
6d2f911b 1302 CUPS_SRAND(time(NULL));
ef416fc2 1303
1304 for (i = 0; i < sizeof(data); i ++)
6d2f911b 1305 data[i] = CUPS_RAND();
ef416fc2 1306
dfd5680b 1307 RAND_seed(data, sizeof(data));
6d2f911b
MS
1308#endif /* HAVE_GNUTLS */
1309
1310 initialized = 1;
1311 _cupsGlobalUnlock();
ef416fc2 1312}
1313
1314
1315/*
1316 * 'httpOptions()' - Send an OPTIONS request to the server.
1317 */
1318
1319int /* O - Status of call (0 = success) */
568fa3fa 1320httpOptions(http_t *http, /* I - Connection to server */
ef416fc2 1321 const char *uri) /* I - URI for options */
1322{
1323 return (http_send(http, HTTP_OPTIONS, uri));
1324}
1325
1326
6d2f911b
MS
1327/*
1328 * '_httpPeek()' - Peek at data from a HTTP connection.
1329 *
1330 * This function copies available data from the given HTTP connection, reading
1331 * a buffer as needed. The data is still available for reading using
1332 * @link httpRead@ or @link httpRead2@.
1333 *
1334 * For non-blocking connections the usual timeouts apply.
1335 */
1336
1337ssize_t /* O - Number of bytes copied */
1338_httpPeek(http_t *http, /* I - Connection to server */
1339 char *buffer, /* I - Buffer for data */
1340 size_t length) /* I - Maximum number of bytes */
1341{
1342 ssize_t bytes; /* Bytes read */
1343 char len[32]; /* Length string */
1344
1345
1346 DEBUG_printf(("_httpPeek(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
1347 http, buffer, CUPS_LLCAST length));
1348
1349 if (http == NULL || buffer == NULL)
1350 return (-1);
1351
1352 http->activity = time(NULL);
1353 http->error = 0;
1354
1355 if (length <= 0)
1356 return (0);
1357
1358 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1359 http->data_remaining <= 0)
1360 {
1361 DEBUG_puts("2_httpPeek: Getting chunk length...");
1362
1363 if (httpGets(len, sizeof(len), http) == NULL)
1364 {
1365 DEBUG_puts("1_httpPeek: Could not get length!");
1366 return (0);
1367 }
1368
1369 http->data_remaining = strtoll(len, NULL, 16);
1370 if (http->data_remaining < 0)
1371 {
1372 DEBUG_puts("1_httpPeek: Negative chunk length!");
1373 return (0);
1374 }
1375 }
1376
1377 DEBUG_printf(("2_httpPeek: data_remaining=" CUPS_LLFMT,
1378 CUPS_LLCAST http->data_remaining));
1379
1380 if (http->data_remaining <= 0)
1381 {
1382 /*
1383 * A zero-length chunk ends a transfer; unless we are reading POST
1384 * data, go idle...
1385 */
1386
1387 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1388 httpGets(len, sizeof(len), http);
1389
1390 if (http->state == HTTP_POST_RECV)
1391 http->state ++;
1392 else
1393 http->state = HTTP_WAITING;
1394
1395 /*
1396 * Prevent future reads for this request...
1397 */
1398
1399 http->data_encoding = HTTP_ENCODE_LENGTH;
1400
1401 return (0);
1402 }
1403 else if (length > (size_t)http->data_remaining)
1404 length = (size_t)http->data_remaining;
1405
1406 if (http->used == 0)
1407 {
1408 /*
1409 * Buffer small reads for better performance...
1410 */
1411
1412 if (!http->blocking && !httpWait(http, 10000))
1413 return (0);
1414
1415 if (http->data_remaining > sizeof(http->buffer))
1416 bytes = sizeof(http->buffer);
1417 else
1418 bytes = http->data_remaining;
1419
1420#ifdef HAVE_SSL
1421 if (http->tls)
1422 bytes = http_read_ssl(http, http->buffer, bytes);
1423 else
1424#endif /* HAVE_SSL */
1425 {
1426 DEBUG_printf(("2_httpPeek: reading %d bytes from socket into buffer...",
1427 (int)bytes));
1428
1429 bytes = recv(http->fd, http->buffer, bytes, 0);
1430
1431 DEBUG_printf(("2_httpPeek: read %d bytes from socket into buffer...",
1432 (int)bytes));
1433 }
1434
1435 if (bytes > 0)
1436 http->used = bytes;
1437 else if (bytes < 0)
1438 {
1439#ifdef WIN32
1440 http->error = WSAGetLastError();
1441 return (-1);
1442#else
1443 if (errno != EINTR && errno != EAGAIN)
1444 {
1445 http->error = errno;
1446 return (-1);
1447 }
1448#endif /* WIN32 */
1449 }
1450 else
1451 {
1452 http->error = EPIPE;
1453 return (0);
1454 }
1455 }
1456
1457 if (http->used > 0)
1458 {
1459 if (length > (size_t)http->used)
1460 length = (size_t)http->used;
1461
1462 bytes = (ssize_t)length;
1463
1464 DEBUG_printf(("2_httpPeek: grabbing %d bytes from input buffer...",
1465 (int)bytes));
1466
1467 memcpy(buffer, http->buffer, length);
1468 }
1469 else
1470 bytes = 0;
1471
1472 if (bytes < 0)
1473 {
1474#ifdef WIN32
1475 http->error = WSAGetLastError();
1476#else
1477 if (errno == EINTR || errno == EAGAIN)
1478 bytes = 0;
1479 else
1480 http->error = errno;
1481#endif /* WIN32 */
1482 }
1483 else if (bytes == 0)
1484 {
1485 http->error = EPIPE;
1486 return (0);
1487 }
1488
1489#ifdef DEBUG
1490 http_debug_hex("_httpPeek", buffer, (int)bytes);
1491#endif /* DEBUG */
1492
1493 return (bytes);
1494}
1495
1496
ef416fc2 1497/*
1498 * 'httpPost()' - Send a POST request to the server.
1499 */
1500
1501int /* O - Status of call (0 = success) */
568fa3fa 1502httpPost(http_t *http, /* I - Connection to server */
ef416fc2 1503 const char *uri) /* I - URI for post */
1504{
1505 return (http_send(http, HTTP_POST, uri));
1506}
1507
1508
1509/*
1510 * 'httpPrintf()' - Print a formatted string to a HTTP connection.
ecdc0628 1511 *
1512 * @private@
ef416fc2 1513 */
1514
1515int /* O - Number of bytes written */
568fa3fa 1516httpPrintf(http_t *http, /* I - Connection to server */
ef416fc2 1517 const char *format, /* I - printf-style format string */
1518 ...) /* I - Additional args as needed */
1519{
1520 int bytes; /* Number of bytes to write */
1521 char buf[16384]; /* Buffer for formatted string */
1522 va_list ap; /* Variable argument pointer */
1523
1524
e07d4801 1525 DEBUG_printf(("2httpPrintf(http=%p, format=\"%s\", ...)", http, format));
ef416fc2 1526
1527 va_start(ap, format);
1528 bytes = vsnprintf(buf, sizeof(buf), format, ap);
1529 va_end(ap);
1530
e07d4801 1531 DEBUG_printf(("3httpPrintf: %s", buf));
ef416fc2 1532
d09495fa 1533 if (http->data_encoding == HTTP_ENCODE_FIELDS)
1534 return (httpWrite2(http, buf, bytes));
1535 else
ef416fc2 1536 {
d09495fa 1537 if (http->wused)
1538 {
e07d4801 1539 DEBUG_puts("4httpPrintf: flushing existing data...");
ef416fc2 1540
d09495fa 1541 if (httpFlushWrite(http) < 0)
1542 return (-1);
1543 }
ef416fc2 1544
d09495fa 1545 return (http_write(http, buf, bytes));
1546 }
ef416fc2 1547}
1548
1549
1550/*
1551 * 'httpPut()' - Send a PUT request to the server.
1552 */
1553
1554int /* O - Status of call (0 = success) */
568fa3fa 1555httpPut(http_t *http, /* I - Connection to server */
ef416fc2 1556 const char *uri) /* I - URI to put */
1557{
e07d4801 1558 DEBUG_printf(("httpPut(http=%p, uri=\"%s\")", http, uri));
ef416fc2 1559 return (http_send(http, HTTP_PUT, uri));
1560}
1561
1562
1563/*
1564 * 'httpRead()' - Read data from a HTTP connection.
a4d04587 1565 *
1566 * This function is deprecated. Use the httpRead2() function which can
1567 * read more than 2GB of data.
1568 *
1569 * @deprecated@
ef416fc2 1570 */
1571
1572int /* O - Number of bytes read */
568fa3fa 1573httpRead(http_t *http, /* I - Connection to server */
ef416fc2 1574 char *buffer, /* I - Buffer for data */
1575 int length) /* I - Maximum number of bytes */
1576{
a4d04587 1577 return ((int)httpRead2(http, buffer, length));
1578}
1579
1580
1581/*
1582 * 'httpRead2()' - Read data from a HTTP connection.
ecdc0628 1583 *
426c6a59 1584 * @since CUPS 1.2/Mac OS X 10.5@
a4d04587 1585 */
1586
1587ssize_t /* O - Number of bytes read */
568fa3fa 1588httpRead2(http_t *http, /* I - Connection to server */
a4d04587 1589 char *buffer, /* I - Buffer for data */
1590 size_t length) /* I - Maximum number of bytes */
1591{
1592 ssize_t bytes; /* Bytes read */
ef416fc2 1593 char len[32]; /* Length string */
1594
1595
e07d4801 1596 DEBUG_printf(("httpRead2(http=%p, buffer=%p, length=" CUPS_LLFMT ")",
a603edef 1597 http, buffer, CUPS_LLCAST length));
ef416fc2 1598
1599 if (http == NULL || buffer == NULL)
1600 return (-1);
1601
1602 http->activity = time(NULL);
f11a948a 1603 http->error = 0;
ef416fc2 1604
1605 if (length <= 0)
1606 return (0);
1607
1608 if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
1609 http->data_remaining <= 0)
1610 {
e07d4801 1611 DEBUG_puts("2httpRead2: Getting chunk length...");
ef416fc2 1612
1613 if (httpGets(len, sizeof(len), http) == NULL)
1614 {
e07d4801 1615 DEBUG_puts("1httpRead2: Could not get length!");
ef416fc2 1616 return (0);
1617 }
1618
1619 http->data_remaining = strtoll(len, NULL, 16);
1620 if (http->data_remaining < 0)
1621 {
e07d4801 1622 DEBUG_puts("1httpRead2: Negative chunk length!");
ef416fc2 1623 return (0);
1624 }
1625 }
1626
e07d4801 1627 DEBUG_printf(("2httpRead2: data_remaining=" CUPS_LLFMT,
ef416fc2 1628 CUPS_LLCAST http->data_remaining));
1629
1630 if (http->data_remaining <= 0)
1631 {
1632 /*
1633 * A zero-length chunk ends a transfer; unless we are reading POST
1634 * data, go idle...
1635 */
1636
1637 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1638 httpGets(len, sizeof(len), http);
1639
1640 if (http->state == HTTP_POST_RECV)
1641 http->state ++;
1642 else
1643 http->state = HTTP_WAITING;
1644
1645 /*
1646 * Prevent future reads for this request...
1647 */
1648
1649 http->data_encoding = HTTP_ENCODE_LENGTH;
1650
1651 return (0);
1652 }
b86bc4cf 1653 else if (length > (size_t)http->data_remaining)
1654 length = (size_t)http->data_remaining;
ef416fc2 1655
1656 if (http->used == 0 && length <= 256)
1657 {
1658 /*
1659 * Buffer small reads for better performance...
1660 */
1661
ed486911 1662 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1663 return (0);
1664
1665 if (http->data_remaining > sizeof(http->buffer))
1666 bytes = sizeof(http->buffer);
1667 else
1668 bytes = http->data_remaining;
1669
1670#ifdef HAVE_SSL
1671 if (http->tls)
1672 bytes = http_read_ssl(http, http->buffer, bytes);
1673 else
1674#endif /* HAVE_SSL */
1675 {
e07d4801 1676 DEBUG_printf(("2httpRead2: reading %d bytes from socket into buffer...",
a603edef 1677 (int)bytes));
ef416fc2 1678
1679 bytes = recv(http->fd, http->buffer, bytes, 0);
1680
e07d4801 1681 DEBUG_printf(("2httpRead2: read %d bytes from socket into buffer...",
a603edef 1682 (int)bytes));
ef416fc2 1683 }
1684
1685 if (bytes > 0)
1686 http->used = bytes;
1687 else if (bytes < 0)
1688 {
1689#ifdef WIN32
1690 http->error = WSAGetLastError();
1691 return (-1);
1692#else
e07d4801 1693 if (errno != EINTR && errno != EAGAIN)
ef416fc2 1694 {
1695 http->error = errno;
1696 return (-1);
1697 }
1698#endif /* WIN32 */
1699 }
1700 else
1701 {
1702 http->error = EPIPE;
1703 return (0);
1704 }
1705 }
1706
1707 if (http->used > 0)
1708 {
b86bc4cf 1709 if (length > (size_t)http->used)
1710 length = (size_t)http->used;
ef416fc2 1711
b86bc4cf 1712 bytes = (ssize_t)length;
ef416fc2 1713
e07d4801 1714 DEBUG_printf(("2httpRead2: grabbing %d bytes from input buffer...",
a603edef 1715 (int)bytes));
ef416fc2 1716
1717 memcpy(buffer, http->buffer, length);
b86bc4cf 1718 http->used -= (int)length;
ef416fc2 1719
1720 if (http->used > 0)
1721 memmove(http->buffer, http->buffer + length, http->used);
1722 }
1723#ifdef HAVE_SSL
1724 else if (http->tls)
1725 {
ed486911 1726 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1727 return (0);
1728
b86bc4cf 1729 bytes = (ssize_t)http_read_ssl(http, buffer, (int)length);
ef416fc2 1730 }
1731#endif /* HAVE_SSL */
1732 else
1733 {
ed486911 1734 if (!http->blocking && !httpWait(http, 10000))
ef416fc2 1735 return (0);
1736
e07d4801 1737 DEBUG_printf(("2httpRead2: reading " CUPS_LLFMT " bytes from socket...",
a603edef 1738 CUPS_LLCAST length));
ef416fc2 1739
b86bc4cf 1740#ifdef WIN32
1741 bytes = (ssize_t)recv(http->fd, buffer, (int)length, 0);
1742#else
ef416fc2 1743 while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
d1c13e16 1744 if (errno != EINTR && errno != EAGAIN)
ef416fc2 1745 break;
b86bc4cf 1746#endif /* WIN32 */
ef416fc2 1747
e07d4801 1748 DEBUG_printf(("2httpRead2: read " CUPS_LLFMT " bytes from socket...",
a603edef 1749 CUPS_LLCAST bytes));
ef416fc2 1750 }
1751
1752 if (bytes > 0)
1753 {
1754 http->data_remaining -= bytes;
1755
1756 if (http->data_remaining <= INT_MAX)
1757 http->_data_remaining = (int)http->data_remaining;
1758 else
1759 http->_data_remaining = INT_MAX;
1760 }
1761 else if (bytes < 0)
1762 {
1763#ifdef WIN32
1764 http->error = WSAGetLastError();
1765#else
d1c13e16 1766 if (errno == EINTR || errno == EAGAIN)
ef416fc2 1767 bytes = 0;
1768 else
1769 http->error = errno;
1770#endif /* WIN32 */
1771 }
1772 else
1773 {
1774 http->error = EPIPE;
1775 return (0);
1776 }
1777
1778 if (http->data_remaining == 0)
1779 {
1780 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
1781 httpGets(len, sizeof(len), http);
1782
1783 if (http->data_encoding != HTTP_ENCODE_CHUNKED)
1784 {
1785 if (http->state == HTTP_POST_RECV)
1786 http->state ++;
1787 else
1788 http->state = HTTP_WAITING;
1789 }
1790 }
1791
1792#ifdef DEBUG
ae71f5de 1793 http_debug_hex("httpRead2", buffer, (int)bytes);
ef416fc2 1794#endif /* DEBUG */
1795
1796 return (bytes);
1797}
1798
1799
1800#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
1801/*
411affcf 1802 * '_httpReadCDSA()' - Read function for the CDSA library.
ef416fc2 1803 */
1804
1805OSStatus /* O - -1 on error, 0 on success */
1806_httpReadCDSA(
1807 SSLConnectionRef connection, /* I - SSL/TLS connection */
1808 void *data, /* I - Data buffer */
1809 size_t *dataLength) /* IO - Number of bytes */
1810{
411affcf 1811 OSStatus result; /* Return value */
1812 ssize_t bytes; /* Number of bytes read */
1813 http_t *http; /* HTTP connection */
1814
1815
1816 http = (http_t *)connection;
e53920b9 1817
411affcf 1818 if (!http->blocking)
1819 {
1820 /*
1821 * Make sure we have data before we read...
1822 */
e53920b9 1823
38e73f87 1824 if (!_httpWait(http, 10000, 0))
411affcf 1825 {
1826 http->error = ETIMEDOUT;
1827 return (-1);
1828 }
1829 }
ef416fc2 1830
b423cd4c 1831 do
411affcf 1832 {
1833 bytes = recv(http->fd, data, *dataLength, 0);
1834 }
e07d4801 1835 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 1836
b423cd4c 1837 if (bytes == *dataLength)
411affcf 1838 {
b423cd4c 1839 result = 0;
411affcf 1840 }
b423cd4c 1841 else if (bytes > 0)
1842 {
1843 *dataLength = bytes;
1844 result = errSSLWouldBlock;
1845 }
1846 else
1847 {
1848 *dataLength = 0;
fa73b229 1849
1850 if (bytes == 0)
ed486911 1851 result = errSSLClosedGraceful;
b423cd4c 1852 else if (errno == EAGAIN)
1853 result = errSSLWouldBlock;
b423cd4c 1854 else
ed486911 1855 result = errSSLClosedAbort;
ef416fc2 1856 }
b423cd4c 1857
411affcf 1858 return (result);
ef416fc2 1859}
1860#endif /* HAVE_SSL && HAVE_CDSASSL */
1861
1862
411affcf 1863#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
1864/*
1865 * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
1866 */
1867
1868ssize_t /* O - Number of bytes read or -1 on error */
1869_httpReadGNUTLS(
568fa3fa 1870 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 1871 void *data, /* I - Buffer */
1872 size_t length) /* I - Number of bytes to read */
1873{
1874 http_t *http; /* HTTP connection */
1875
1876
1877 http = (http_t *)ptr;
1878
1879 if (!http->blocking)
1880 {
1881 /*
1882 * Make sure we have data before we read...
1883 */
1884
38e73f87 1885 if (!_httpWait(http, 10000, 0))
411affcf 1886 {
1887 http->error = ETIMEDOUT;
1888 return (-1);
1889 }
1890 }
1891
1892 return (recv(http->fd, data, length, 0));
1893}
1894#endif /* HAVE_SSL && HAVE_GNUTLS */
1895
1896
ef416fc2 1897/*
ecdc0628 1898 * 'httpReconnect()' - Reconnect to a HTTP server.
ef416fc2 1899 */
1900
1901int /* O - 0 on success, non-zero on failure */
568fa3fa 1902httpReconnect(http_t *http) /* I - Connection to server */
ef416fc2 1903{
1904 http_addrlist_t *addr; /* Connected address */
1ff0402e
MS
1905#ifdef DEBUG
1906 http_addrlist_t *current; /* Current address */
1907 char temp[256]; /* Temporary address string */
1908#endif /* DEBUG */
ef416fc2 1909
1910
e07d4801 1911 DEBUG_printf(("httpReconnect(http=%p)", http));
ef416fc2 1912
1913 if (!http)
1914 return (-1);
1915
1916#ifdef HAVE_SSL
1917 if (http->tls)
1ff0402e 1918 {
e07d4801 1919 DEBUG_puts("2httpReconnect: Shutting down SSL/TLS...");
ef416fc2 1920 http_shutdown_ssl(http);
1ff0402e 1921 }
ef416fc2 1922#endif /* HAVE_SSL */
1923
1924 /*
1925 * Close any previously open socket...
1926 */
1927
1928 if (http->fd >= 0)
bd7854cb 1929 {
e07d4801 1930 DEBUG_printf(("2httpReconnect: Closing socket %d...", http->fd));
1ff0402e 1931
ef416fc2 1932#ifdef WIN32
1933 closesocket(http->fd);
1934#else
1935 close(http->fd);
1936#endif /* WIN32 */
1937
bd7854cb 1938 http->fd = -1;
1939 }
1940
ef416fc2 1941 /*
1942 * Connect to the server...
1943 */
1944
1ff0402e
MS
1945#ifdef DEBUG
1946 for (current = http->addrlist; current; current = current->next)
e07d4801 1947 DEBUG_printf(("2httpReconnect: Address %s:%d",
1ff0402e
MS
1948 httpAddrString(&(current->addr), temp, sizeof(temp)),
1949 _httpAddrPort(&(current->addr))));
1950#endif /* DEBUG */
1951
ef416fc2 1952 if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
1953 {
1954 /*
1955 * Unable to connect...
1956 */
1957
1958#ifdef WIN32
1959 http->error = WSAGetLastError();
1960#else
1961 http->error = errno;
1962#endif /* WIN32 */
1963 http->status = HTTP_ERROR;
1964
e07d4801 1965 DEBUG_printf(("1httpReconnect: httpAddrConnect failed: %s",
1ff0402e
MS
1966 strerror(http->error)));
1967
ef416fc2 1968 return (-1);
1969 }
1970
e07d4801 1971 DEBUG_printf(("2httpReconnect: New socket=%d", http->fd));
1ff0402e 1972
ef416fc2 1973 http->hostaddr = &(addr->addr);
1974 http->error = 0;
1975 http->status = HTTP_CONTINUE;
1976
1977#ifdef HAVE_SSL
1978 if (http->encryption == HTTP_ENCRYPT_ALWAYS)
1979 {
1980 /*
1981 * Always do encryption via SSL.
1982 */
1983
1984 if (http_setup_ssl(http) != 0)
1985 {
f7deaa1a 1986# ifdef WIN32
ef416fc2 1987 closesocket(http->fd);
f7deaa1a 1988# else
ef416fc2 1989 close(http->fd);
f7deaa1a 1990# endif /* WIN32 */
ef416fc2 1991
1992 return (-1);
1993 }
1994 }
1995 else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
1996 return (http_upgrade(http));
1997#endif /* HAVE_SSL */
1998
e07d4801 1999 DEBUG_printf(("1httpReconnect: Connected to %s:%d...",
1ff0402e
MS
2000 httpAddrString(http->hostaddr, temp, sizeof(temp)),
2001 _httpAddrPort(http->hostaddr)));
2002
ef416fc2 2003 return (0);
2004}
2005
2006
355e94dc
MS
2007/*
2008 * 'httpSetAuthString()' - Set the current authorization string.
2009 *
2010 * This function just stores a copy of the current authorization string in
2011 * the HTTP connection object. You must still call httpSetField() to set
2012 * HTTP_FIELD_AUTHORIZATION prior to issuing a HTTP request using httpGet(),
2013 * httpHead(), httpOptions(), httpPost, or httpPut().
2014 *
426c6a59 2015 * @since CUPS 1.3/Mac OS X 10.5@
355e94dc
MS
2016 */
2017
2018void
568fa3fa 2019httpSetAuthString(http_t *http, /* I - Connection to server */
355e94dc
MS
2020 const char *scheme, /* I - Auth scheme (NULL to clear it) */
2021 const char *data) /* I - Auth data (NULL for none) */
2022{
2023 /*
2024 * Range check input...
2025 */
2026
2027 if (!http)
2028 return;
2029
2030 if (http->authstring && http->authstring != http->_authstring)
2031 free(http->authstring);
2032
2033 http->authstring = http->_authstring;
2034
2035 if (scheme)
2036 {
2037 /*
2038 * Set the current authorization string...
2039 */
2040
2041 int len = (int)strlen(scheme) + (data ? (int)strlen(data) + 1 : 0) + 1;
91c84a35 2042 char *temp;
355e94dc
MS
2043
2044 if (len > (int)sizeof(http->_authstring))
91c84a35
MS
2045 {
2046 if ((temp = malloc(len)) == NULL)
2047 len = sizeof(http->_authstring);
2048 else
2049 http->authstring = temp;
2050 }
355e94dc
MS
2051
2052 if (data)
2053 snprintf(http->authstring, len, "%s %s", scheme, data);
2054 else
2055 strlcpy(http->authstring, scheme, len);
2056 }
2057 else
2058 {
2059 /*
2060 * Clear the current authorization string...
2061 */
2062
2063 http->_authstring[0] = '\0';
2064 }
2065}
2066
2067
ef416fc2 2068/*
6d2f911b 2069 * 'httpSetCookie()' - Set the cookie value(s).
ef416fc2 2070 *
426c6a59 2071 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 2072 */
2073
2074void
2075httpSetCookie(http_t *http, /* I - Connection */
2076 const char *cookie) /* I - Cookie string */
2077{
2078 if (!http)
2079 return;
2080
2081 if (http->cookie)
2082 free(http->cookie);
2083
2084 if (cookie)
2085 http->cookie = strdup(cookie);
2086 else
2087 http->cookie = NULL;
2088}
2089
2090
b423cd4c 2091/*
2092 * 'httpSetExpect()' - Set the Expect: header in a request.
2093 *
2094 * Currently only HTTP_CONTINUE is supported for the "expect" argument.
2095 *
426c6a59 2096 * @since CUPS 1.2/Mac OS X 10.5@
b423cd4c 2097 */
2098
2099void
568fa3fa 2100httpSetExpect(http_t *http, /* I - Connection to server */
b423cd4c 2101 http_status_t expect) /* I - HTTP status to expect (HTTP_CONTINUE) */
2102{
2103 if (http)
2104 http->expect = expect;
2105}
2106
2107
ef416fc2 2108/*
2109 * 'httpSetField()' - Set the value of an HTTP header.
2110 */
2111
2112void
568fa3fa 2113httpSetField(http_t *http, /* I - Connection to server */
ef416fc2 2114 http_field_t field, /* I - Field index */
2115 const char *value) /* I - Value */
2116{
2117 if (http == NULL ||
2118 field < HTTP_FIELD_ACCEPT_LANGUAGE ||
2119 field > HTTP_FIELD_WWW_AUTHENTICATE ||
2120 value == NULL)
2121 return;
2122
2123 strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
f7deaa1a 2124
f7deaa1a 2125 if (field == HTTP_FIELD_AUTHORIZATION)
2126 {
e07d4801
MS
2127 /*
2128 * Special case for Authorization: as its contents can be
2129 * longer than HTTP_MAX_VALUE
2130 */
2131
f7deaa1a 2132 if (http->field_authorization)
2133 free(http->field_authorization);
2134
2135 http->field_authorization = strdup(value);
2136 }
e07d4801
MS
2137 else if (field == HTTP_FIELD_HOST)
2138 {
2139 /*
f11a948a
MS
2140 * Special-case for Host: as we don't want a trailing "." on the hostname and
2141 * need to bracket IPv6 numeric addresses.
e07d4801
MS
2142 */
2143
178cb736
MS
2144 char *ptr = strchr(value, ':');
2145
2146 if (value[0] != '[' && ptr && strchr(ptr + 1, ':'))
f11a948a
MS
2147 {
2148 /*
2149 * Bracket IPv6 numeric addresses...
2150 *
2151 * This is slightly inefficient (basically copying twice), but is an edge
2152 * case and not worth optimizing...
2153 */
e07d4801 2154
f11a948a
MS
2155 snprintf(http->fields[HTTP_FIELD_HOST],
2156 sizeof(http->fields[HTTP_FIELD_HOST]), "[%s]", value);
2157 }
2158 else
e07d4801 2159 {
f11a948a
MS
2160 /*
2161 * Check for a trailing dot on the hostname...
2162 */
2163
178cb736 2164 ptr = http->fields[HTTP_FIELD_HOST];
f11a948a
MS
2165
2166 if (*ptr)
2167 {
2168 ptr += strlen(ptr) - 1;
e07d4801 2169
f11a948a
MS
2170 if (*ptr == '.')
2171 *ptr = '\0';
2172 }
e07d4801
MS
2173 }
2174 }
ef416fc2 2175}
2176
2177
2178/*
2179 * 'httpSetLength()' - Set the content-length and content-encoding.
2180 *
426c6a59 2181 * @since CUPS 1.2/Mac OS X 10.5@
ef416fc2 2182 */
2183
2184void
568fa3fa 2185httpSetLength(http_t *http, /* I - Connection to server */
ef416fc2 2186 size_t length) /* I - Length (0 for chunked) */
2187{
2188 if (!http)
2189 return;
2190
2191 if (!length)
2192 {
2193 strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
2194 http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
2195 }
2196 else
2197 {
2198 http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
2199 snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
2200 CUPS_LLFMT, CUPS_LLCAST length);
2201 }
2202}
2203
2204
2205/*
2206 * 'httpTrace()' - Send an TRACE request to the server.
2207 */
2208
2209int /* O - Status of call (0 = success) */
568fa3fa 2210httpTrace(http_t *http, /* I - Connection to server */
ef416fc2 2211 const char *uri) /* I - URI for trace */
2212{
2213 return (http_send(http, HTTP_TRACE, uri));
2214}
2215
2216
2217/*
2218 * 'httpUpdate()' - Update the current HTTP state for incoming data.
2219 */
2220
2221http_status_t /* O - HTTP status */
568fa3fa 2222httpUpdate(http_t *http) /* I - Connection to server */
ef416fc2 2223{
2224 char line[32768], /* Line from connection... */
2225 *value; /* Pointer to value on line */
2226 http_field_t field; /* Field index */
2227 int major, minor, /* HTTP version numbers */
2228 status; /* Request status */
2229
2230
f11a948a
MS
2231 DEBUG_printf(("httpUpdate(http=%p), state=%s", http,
2232 http_states[http->state]));
ef416fc2 2233
2234 /*
2235 * Flush pending data, if any...
2236 */
2237
2238 if (http->wused)
2239 {
e07d4801 2240 DEBUG_puts("2httpUpdate: flushing buffer...");
ef416fc2 2241
2242 if (httpFlushWrite(http) < 0)
2243 return (HTTP_ERROR);
2244 }
2245
2246 /*
2247 * If we haven't issued any commands, then there is nothing to "update"...
2248 */
2249
2250 if (http->state == HTTP_WAITING)
2251 return (HTTP_CONTINUE);
2252
2253 /*
2254 * Grab all of the lines we can from the connection...
2255 */
2256
2257 while (httpGets(line, sizeof(line), http) != NULL)
2258 {
e07d4801 2259 DEBUG_printf(("2httpUpdate: Got \"%s\"", line));
ef416fc2 2260
2261 if (line[0] == '\0')
2262 {
2263 /*
2264 * Blank line means the start of the data section (if any). Return
2265 * the result code, too...
2266 *
2267 * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
2268 * Instead, we just return HTTP_CONTINUE to the caller and keep on
2269 * tryin'...
2270 */
2271
2272 if (http->status == HTTP_CONTINUE)
2273 return (http->status);
2274
2275 if (http->status < HTTP_BAD_REQUEST)
2276 http->digest_tries = 0;
2277
2278#ifdef HAVE_SSL
2279 if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
2280 {
2281 if (http_setup_ssl(http) != 0)
2282 {
2283# ifdef WIN32
2284 closesocket(http->fd);
2285# else
2286 close(http->fd);
2287# endif /* WIN32 */
2288
2289 return (HTTP_ERROR);
2290 }
2291
2292 return (HTTP_CONTINUE);
2293 }
2294#endif /* HAVE_SSL */
2295
2296 httpGetLength2(http);
2297
2298 switch (http->state)
2299 {
2300 case HTTP_GET :
2301 case HTTP_POST :
2302 case HTTP_POST_RECV :
2303 case HTTP_PUT :
2304 http->state ++;
2305 case HTTP_POST_SEND :
e1d6a774 2306 case HTTP_HEAD :
ef416fc2 2307 break;
2308
2309 default :
2310 http->state = HTTP_WAITING;
2311 break;
2312 }
2313
2314 return (http->status);
2315 }
e07d4801 2316 else if (!strncmp(line, "HTTP/", 5))
ef416fc2 2317 {
2318 /*
2319 * Got the beginning of a response...
2320 */
2321
2322 if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
2323 return (HTTP_ERROR);
2324
2325 http->version = (http_version_t)(major * 100 + minor);
2326 http->status = (http_status_t)status;
2327 }
2328 else if ((value = strchr(line, ':')) != NULL)
2329 {
2330 /*
2331 * Got a value...
2332 */
2333
2334 *value++ = '\0';
2335 while (isspace(*value & 255))
2336 value ++;
2337
2338 /*
2339 * Be tolerants of servers that send unknown attribute fields...
2340 */
2341
2342 if (!strcasecmp(line, "expect"))
2343 {
2344 /*
2345 * "Expect: 100-continue" or similar...
2346 */
2347
2348 http->expect = (http_status_t)atoi(value);
2349 }
2350 else if (!strcasecmp(line, "cookie"))
2351 {
2352 /*
2353 * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
2354 */
2355
2356 httpSetCookie(http, value);
2357 }
2358 else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
2359 {
e07d4801 2360 DEBUG_printf(("1httpUpdate: unknown field %s seen!", line));
ef416fc2 2361 continue;
2362 }
2363 else
2364 httpSetField(http, field, value);
2365 }
2366 else
2367 {
e07d4801 2368 DEBUG_printf(("1httpUpdate: Bad response line \"%s\"!", line));
ef416fc2 2369 http->status = HTTP_ERROR;
2370 return (HTTP_ERROR);
2371 }
2372 }
2373
2374 /*
2375 * See if there was an error...
2376 */
2377
2378 if (http->error == EPIPE && http->status > HTTP_CONTINUE)
e07d4801
MS
2379 {
2380 DEBUG_printf(("1httpUpdate: Returning status %d...", http->status));
ef416fc2 2381 return (http->status);
e07d4801 2382 }
ef416fc2 2383
2384 if (http->error)
2385 {
e07d4801 2386 DEBUG_printf(("1httpUpdate: socket error %d - %s", http->error,
ef416fc2 2387 strerror(http->error)));
2388 http->status = HTTP_ERROR;
2389 return (HTTP_ERROR);
2390 }
2391
2392 /*
2393 * If we haven't already returned, then there is nothing new...
2394 */
2395
2396 return (HTTP_CONTINUE);
2397}
2398
2399
38e73f87
MS
2400/*
2401 * '_httpWait()' - Wait for data available on a connection (no flush).
2402 */
2403
2404int /* O - 1 if data is available, 0 otherwise */
2405_httpWait(http_t *http, /* I - Connection to server */
2406 int msec, /* I - Milliseconds to wait */
2407 int usessl) /* I - Use SSL context? */
2408{
2409#ifdef HAVE_POLL
2410 struct pollfd pfd; /* Polled file descriptor */
2411#else
2412 fd_set input_set; /* select() input set */
2413 struct timeval timeout; /* Timeout */
2414#endif /* HAVE_POLL */
2415 int nfds; /* Result from select()/poll() */
2416
2417
e07d4801 2418 DEBUG_printf(("4_httpWait(http=%p, msec=%d, usessl=%d)", http, msec, usessl));
38e73f87
MS
2419
2420 if (http->fd < 0)
f8b3a85b
MS
2421 {
2422 DEBUG_printf(("5_httpWait: Returning 0 since fd=%d", http->fd));
38e73f87 2423 return (0);
f8b3a85b 2424 }
38e73f87
MS
2425
2426 /*
2427 * Check the SSL/TLS buffers for data first...
2428 */
2429
2430#ifdef HAVE_SSL
2431 if (http->tls && usessl)
2432 {
2433# ifdef HAVE_LIBSSL
2434 if (SSL_pending((SSL *)(http->tls)))
f8b3a85b
MS
2435 {
2436 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 2437 return (1);
f8b3a85b
MS
2438 }
2439
38e73f87
MS
2440# elif defined(HAVE_GNUTLS)
2441 if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
f8b3a85b
MS
2442 {
2443 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 2444 return (1);
f8b3a85b
MS
2445 }
2446
38e73f87
MS
2447# elif defined(HAVE_CDSASSL)
2448 size_t bytes; /* Bytes that are available */
2449
2450 if (!SSLGetBufferedReadSize(((http_tls_t *)(http->tls))->session, &bytes) &&
2451 bytes > 0)
f8b3a85b
MS
2452 {
2453 DEBUG_puts("5_httpWait: Return 1 since there is pending SSL data.");
38e73f87 2454 return (1);
f8b3a85b 2455 }
38e73f87
MS
2456# endif /* HAVE_LIBSSL */
2457 }
2458#endif /* HAVE_SSL */
2459
2460 /*
2461 * Then try doing a select() or poll() to poll the socket...
2462 */
2463
2464#ifdef HAVE_POLL
2465 pfd.fd = http->fd;
2466 pfd.events = POLLIN;
2467
e07d4801
MS
2468 while ((nfds = poll(&pfd, 1, msec)) < 0 &&
2469 (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2470
2471#else
2472 do
2473 {
2474 FD_ZERO(&input_set);
2475 FD_SET(http->fd, &input_set);
2476
e07d4801 2477 DEBUG_printf(("6_httpWait: msec=%d, http->fd=%d", msec, http->fd));
38e73f87
MS
2478
2479 if (msec >= 0)
2480 {
2481 timeout.tv_sec = msec / 1000;
2482 timeout.tv_usec = (msec % 1000) * 1000;
2483
2484 nfds = select(http->fd + 1, &input_set, NULL, NULL, &timeout);
2485 }
2486 else
2487 nfds = select(http->fd + 1, &input_set, NULL, NULL, NULL);
2488
e07d4801 2489 DEBUG_printf(("6_httpWait: select() returned %d...", nfds));
38e73f87
MS
2490 }
2491# ifdef WIN32
2492 while (nfds < 0 && WSAGetLastError() == WSAEINTR);
2493# else
e07d4801 2494 while (nfds < 0 && (errno == EINTR || errno == EAGAIN));
38e73f87
MS
2495# endif /* WIN32 */
2496#endif /* HAVE_POLL */
2497
f8b3a85b
MS
2498 DEBUG_printf(("5_httpWait: returning with nfds=%d, errno=%d...", nfds,
2499 errno));
38e73f87
MS
2500
2501 return (nfds > 0);
2502}
2503
2504
ef416fc2 2505/*
2506 * 'httpWait()' - Wait for data available on a connection.
2507 *
426c6a59 2508 * @since CUPS 1.1.19/Mac OS X 10.3@
ef416fc2 2509 */
2510
2511int /* O - 1 if data is available, 0 otherwise */
568fa3fa 2512httpWait(http_t *http, /* I - Connection to server */
ef416fc2 2513 int msec) /* I - Milliseconds to wait */
2514{
2515 /*
2516 * First see if there is data in the buffer...
2517 */
2518
2519 if (http == NULL)
2520 return (0);
2521
2522 if (http->used)
2523 return (1);
2524
8ca02f3c 2525 /*
2526 * Flush pending data, if any...
2527 */
2528
2529 if (http->wused)
2530 {
2531 if (httpFlushWrite(http) < 0)
2532 return (0);
2533 }
2534
ef416fc2 2535 /*
2536 * If not, check the SSL/TLS buffers and do a select() on the connection...
2537 */
2538
38e73f87 2539 return (_httpWait(http, msec, 1));
ef416fc2 2540}
2541
2542
2543/*
2544 * 'httpWrite()' - Write data to a HTTP connection.
a4d04587 2545 *
2546 * This function is deprecated. Use the httpWrite2() function which can
2547 * write more than 2GB of data.
2548 *
2549 * @deprecated@
ef416fc2 2550 */
ef55b745 2551
ef416fc2 2552int /* O - Number of bytes written */
568fa3fa 2553httpWrite(http_t *http, /* I - Connection to server */
ef416fc2 2554 const char *buffer, /* I - Buffer for data */
2555 int length) /* I - Number of bytes to write */
2556{
a4d04587 2557 return ((int)httpWrite2(http, buffer, length));
2558}
2559
2560
2561/*
2562 * 'httpWrite2()' - Write data to a HTTP connection.
ecdc0628 2563 *
426c6a59 2564 * @since CUPS 1.2/Mac OS X 10.5@
a4d04587 2565 */
ef55b745 2566
a4d04587 2567ssize_t /* O - Number of bytes written */
568fa3fa 2568httpWrite2(http_t *http, /* I - Connection to server */
a4d04587 2569 const char *buffer, /* I - Buffer for data */
2570 size_t length) /* I - Number of bytes to write */
2571{
2572 ssize_t bytes; /* Bytes written */
ef416fc2 2573
2574
e07d4801 2575 DEBUG_printf(("httpWrite2(http=%p, buffer=%p, length=" CUPS_LLFMT ")", http,
a603edef 2576 buffer, CUPS_LLCAST length));
ef416fc2 2577
2578 /*
2579 * Range check input...
2580 */
2581
2582 if (http == NULL || buffer == NULL)
2583 return (-1);
2584
2585 /*
2586 * Mark activity on the connection...
2587 */
2588
2589 http->activity = time(NULL);
2590
2591 /*
2592 * Buffer small writes for better performance...
2593 */
2594
2595 if (length > 0)
2596 {
2597 if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
2598 {
e07d4801
MS
2599 DEBUG_printf(("2httpWrite2: Flushing buffer (wused=%d, length="
2600 CUPS_LLFMT ")", http->wused, CUPS_LLCAST length));
ef416fc2 2601
2602 httpFlushWrite(http);
2603 }
2604
38e73f87
MS
2605 if ((length + http->wused) <= sizeof(http->wbuffer) &&
2606 length < sizeof(http->wbuffer))
ef416fc2 2607 {
2608 /*
2609 * Write to buffer...
2610 */
2611
e07d4801 2612 DEBUG_printf(("2httpWrite2: Copying " CUPS_LLFMT " bytes to wbuffer...",
a603edef 2613 CUPS_LLCAST length));
ef416fc2 2614
2615 memcpy(http->wbuffer + http->wused, buffer, length);
b86bc4cf 2616 http->wused += (int)length;
2617 bytes = (ssize_t)length;
ef416fc2 2618 }
2619 else
2620 {
2621 /*
2622 * Otherwise write the data directly...
2623 */
2624
e07d4801 2625 DEBUG_printf(("2httpWrite2: Writing " CUPS_LLFMT " bytes to socket...",
a603edef 2626 CUPS_LLCAST length));
ef416fc2 2627
2628 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
b86bc4cf 2629 bytes = (ssize_t)http_write_chunk(http, buffer, (int)length);
ef416fc2 2630 else
b86bc4cf 2631 bytes = (ssize_t)http_write(http, buffer, (int)length);
ef416fc2 2632
e07d4801 2633 DEBUG_printf(("2httpWrite2: Wrote " CUPS_LLFMT " bytes...",
ae71f5de 2634 CUPS_LLCAST bytes));
ef416fc2 2635 }
2636
2637 if (http->data_encoding == HTTP_ENCODE_LENGTH)
2638 http->data_remaining -= bytes;
2639 }
2640 else
2641 bytes = 0;
2642
2643 /*
2644 * Handle end-of-request processing...
2645 */
2646
2647 if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
2648 (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
2649 {
2650 /*
2651 * Finished with the transfer; unless we are sending POST or PUT
2652 * data, go idle...
2653 */
2654
e07d4801 2655 DEBUG_puts("2httpWrite: changing states...");
ef416fc2 2656
2657 if (http->wused)
2658 httpFlushWrite(http);
2659
2660 if (http->data_encoding == HTTP_ENCODE_CHUNKED)
2661 {
2662 /*
2663 * Send a 0-length chunk at the end of the request...
2664 */
2665
2666 http_write(http, "0\r\n\r\n", 5);
2667
2668 /*
2669 * Reset the data state...
2670 */
2671
2672 http->data_encoding = HTTP_ENCODE_LENGTH;
2673 http->data_remaining = 0;
2674 }
2675
2676 if (http->state == HTTP_POST_RECV)
2677 http->state ++;
2678 else if (http->state == HTTP_PUT_RECV)
2679 http->state = HTTP_STATUS;
2680 else
2681 http->state = HTTP_WAITING;
2682 }
2683
2684 return (bytes);
2685}
2686
2687
2688#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
2689/*
411affcf 2690 * '_httpWriteCDSA()' - Write function for the CDSA library.
ef416fc2 2691 */
2692
2693OSStatus /* O - -1 on error, 0 on success */
2694_httpWriteCDSA(
2695 SSLConnectionRef connection, /* I - SSL/TLS connection */
2696 const void *data, /* I - Data buffer */
2697 size_t *dataLength) /* IO - Number of bytes */
2698{
411affcf 2699 OSStatus result; /* Return value */
2700 ssize_t bytes; /* Number of bytes read */
2701 http_t *http; /* HTTP connection */
e53920b9 2702
2703
411affcf 2704 http = (http_t *)connection;
ef416fc2 2705
b423cd4c 2706 do
411affcf 2707 {
2708 bytes = write(http->fd, data, *dataLength);
2709 }
e07d4801 2710 while (bytes == -1 && (errno == EINTR || errno == EAGAIN));
fa73b229 2711
b423cd4c 2712 if (bytes == *dataLength)
411affcf 2713 {
b423cd4c 2714 result = 0;
411affcf 2715 }
b423cd4c 2716 else if (bytes >= 0)
2717 {
2718 *dataLength = bytes;
2719 result = errSSLWouldBlock;
2720 }
2721 else
2722 {
2723 *dataLength = 0;
ef55b745 2724
fa73b229 2725 if (errno == EAGAIN)
b423cd4c 2726 result = errSSLWouldBlock;
b423cd4c 2727 else
ed486911 2728 result = errSSLClosedAbort;
ef416fc2 2729 }
b423cd4c 2730
411affcf 2731 return (result);
ef416fc2 2732}
2733#endif /* HAVE_SSL && HAVE_CDSASSL */
2734
2735
411affcf 2736#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
2737/*
2738 * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
2739 */
2740
2741ssize_t /* O - Number of bytes written or -1 on error */
2742_httpWriteGNUTLS(
568fa3fa 2743 gnutls_transport_ptr ptr, /* I - Connection to server */
411affcf 2744 const void *data, /* I - Data buffer */
2745 size_t length) /* I - Number of bytes to write */
2746{
2747 return (send(((http_t *)ptr)->fd, data, length, 0));
2748}
2749#endif /* HAVE_SSL && HAVE_GNUTLS */
2750
2751
2752#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
2753/*
2754 * 'http_bio_ctrl()' - Control the HTTP connection.
2755 */
2756
2757static long /* O - Result/data */
2758http_bio_ctrl(BIO *h, /* I - BIO data */
2759 int cmd, /* I - Control command */
2760 long arg1, /* I - First argument */
2761 void *arg2) /* I - Second argument */
2762{
2763 switch (cmd)
2764 {
2765 default :
2766 return (0);
2767
2768 case BIO_CTRL_RESET :
2769 h->ptr = NULL;
2770 return (0);
2771
2772 case BIO_C_SET_FILE_PTR :
2773 h->ptr = arg2;
2774 h->init = 1;
2775 return (1);
2776
2777 case BIO_C_GET_FILE_PTR :
2778 if (arg2)
2779 {
2780 *((void **)arg2) = h->ptr;
2781 return (1);
2782 }
2783 else
2784 return (0);
ef55b745 2785
411affcf 2786 case BIO_CTRL_DUP :
2787 case BIO_CTRL_FLUSH :
2788 return (1);
2789 }
2790}
2791
2792
2793/*
2794 * 'http_bio_free()' - Free OpenSSL data.
2795 */
2796
2797static int /* O - 1 on success, 0 on failure */
2798http_bio_free(BIO *h) /* I - BIO data */
2799{
2800 if (!h)
2801 return (0);
2802
2803 if (h->shutdown)
2804 {
2805 h->init = 0;
2806 h->flags = 0;
2807 }
2808
2809 return (1);
2810}
2811
2812
2813/*
2814 * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
2815 */
2816
2817static int /* O - 1 on success, 0 on failure */
2818http_bio_new(BIO *h) /* I - BIO data */
2819{
2820 if (!h)
2821 return (0);
2822
2823 h->init = 0;
2824 h->num = 0;
2825 h->ptr = NULL;
2826 h->flags = 0;
2827
2828 return (1);
2829}
2830
2831
2832/*
2833 * 'http_bio_puts()' - Send a string for OpenSSL.
2834 */
2835
2836static int /* O - Bytes written */
2837http_bio_puts(BIO *h, /* I - BIO data */
2838 const char *str) /* I - String to write */
2839{
b86bc4cf 2840#ifdef WIN32
2841 return (send(((http_t *)h->ptr)->fd, str, (int)strlen(str), 0));
2842#else
411affcf 2843 return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
b86bc4cf 2844#endif /* WIN32 */
411affcf 2845}
2846
2847
2848/*
2849 * 'http_bio_read()' - Read data for OpenSSL.
2850 */
2851
2852static int /* O - Bytes read */
2853http_bio_read(BIO *h, /* I - BIO data */
2854 char *buf, /* I - Buffer */
2855 int size) /* I - Number of bytes to read */
2856{
2857 http_t *http; /* HTTP connection */
2858
2859
2860 http = (http_t *)h->ptr;
2861
2862 if (!http->blocking)
2863 {
2864 /*
2865 * Make sure we have data before we read...
2866 */
2867
38e73f87 2868 if (!_httpWait(http, 10000, 0))
411affcf 2869 {
b86bc4cf 2870#ifdef WIN32
2871 http->error = WSAETIMEDOUT;
2872#else
411affcf 2873 http->error = ETIMEDOUT;
b86bc4cf 2874#endif /* WIN32 */
2875
411affcf 2876 return (-1);
2877 }
2878 }
2879
2880 return (recv(http->fd, buf, size, 0));
2881}
2882
2883
2884/*
2885 * 'http_bio_write()' - Write data for OpenSSL.
2886 */
2887
2888static int /* O - Bytes written */
2889http_bio_write(BIO *h, /* I - BIO data */
2890 const char *buf, /* I - Buffer to write */
2891 int num) /* I - Number of bytes to write */
2892{
2893 return (send(((http_t *)h->ptr)->fd, buf, num, 0));
2894}
2895#endif /* HAVE_SSL && HAVE_LIBSSL */
2896
2897
ae71f5de
MS
2898#ifdef DEBUG
2899/*
2900 * 'http_debug_hex()' - Do a hex dump of a buffer.
2901 */
2902
2903static void
2904http_debug_hex(const char *prefix, /* I - Prefix for line */
2905 const char *buffer, /* I - Buffer to dump */
2906 int bytes) /* I - Bytes to dump */
2907{
2908 int i, j, /* Looping vars */
2909 ch; /* Current character */
2910 char line[255], /* Line buffer */
2911 *start, /* Start of line after prefix */
2912 *ptr; /* Pointer into line */
2913
2914
f11a948a 2915 if (_cups_debug_fd < 0 || _cups_debug_level < 6)
dd1abb6b
MS
2916 return;
2917
e07d4801 2918 DEBUG_printf(("6%s: %d bytes:\n", prefix, bytes));
ae71f5de 2919
f11a948a 2920 snprintf(line, sizeof(line), "6%s: ", prefix);
ae71f5de
MS
2921 start = line + strlen(line);
2922
2923 for (i = 0; i < bytes; i += 16)
2924 {
2925 for (j = 0, ptr = start; j < 16 && (i + j) < bytes; j ++, ptr += 2)
2926 sprintf(ptr, "%02X", buffer[i + j] & 255);
2927
2928 while (j < 16)
2929 {
2930 strcpy(ptr, " ");
2931 ptr += 2;
2932 j ++;
2933 }
2934
2935 strcpy(ptr, " ");
2936 ptr += 2;
2937
2938 for (j = 0; j < 16 && (i + j) < bytes; j ++)
2939 {
2940 ch = buffer[i + j] & 255;
2941
2942 if (ch < ' ' || ch >= 127)
2943 ch = '.';
2944
2945 *ptr++ = ch;
2946 }
2947
2948 *ptr = '\0';
2949 DEBUG_puts(line);
2950 }
2951}
2952#endif /* DEBUG */
2953
2954
ef416fc2 2955/*
2956 * 'http_field()' - Return the field index for a field name.
2957 */
2958
ae71f5de
MS
2959static http_field_t /* O - Field index */
2960http_field(const char *name) /* I - String name */
ef416fc2 2961{
ae71f5de 2962 int i; /* Looping var */
ef416fc2 2963
2964
2965 for (i = 0; i < HTTP_FIELD_MAX; i ++)
2966 if (strcasecmp(name, http_fields[i]) == 0)
2967 return ((http_field_t)i);
2968
2969 return (HTTP_FIELD_UNKNOWN);
2970}
2971
2972
2973#ifdef HAVE_SSL
2974/*
2975 * 'http_read_ssl()' - Read from a SSL/TLS connection.
2976 */
2977
2978static int /* O - Bytes read */
568fa3fa 2979http_read_ssl(http_t *http, /* I - Connection to server */
ef416fc2 2980 char *buf, /* I - Buffer to store data */
2981 int len) /* I - Length of buffer */
2982{
2983# if defined(HAVE_LIBSSL)
2984 return (SSL_read((SSL *)(http->tls), buf, len));
2985
2986# elif defined(HAVE_GNUTLS)
ef55b745
MS
2987 ssize_t result; /* Return value */
2988
2989
2990 result = gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len);
2991
2992 if (result < 0 && !errno)
2993 {
2994 /*
2995 * Convert GNU TLS error to errno value...
2996 */
2997
2998 switch (result)
2999 {
3000 case GNUTLS_E_INTERRUPTED :
3001 errno = EINTR;
3002 break;
3003
3004 case GNUTLS_E_AGAIN :
3005 errno = EAGAIN;
3006 break;
3007
3008 default :
3009 errno = EPIPE;
3010 break;
3011 }
3012
3013 result = -1;
3014 }
3015
3016 return ((int)result);
ef416fc2 3017
3018# elif defined(HAVE_CDSASSL)
fa73b229 3019 int result; /* Return value */
ef416fc2 3020 OSStatus error; /* Error info */
3021 size_t processed; /* Number of bytes processed */
3022
3023
89d46774 3024 error = SSLRead(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 3025
fa73b229 3026 switch (error)
ef416fc2 3027 {
fa73b229 3028 case 0 :
3029 result = (int)processed;
3030 break;
3031 case errSSLClosedGraceful :
3032 result = 0;
3033 break;
3034 case errSSLWouldBlock :
b423cd4c 3035 if (processed)
3036 result = (int)processed;
3037 else
3038 {
3039 result = -1;
3040 errno = EINTR;
3041 }
fa73b229 3042 break;
3043 default :
3044 errno = EPIPE;
3045 result = -1;
3046 break;
ef416fc2 3047 }
fa73b229 3048
3049 return (result);
ef416fc2 3050# endif /* HAVE_LIBSSL */
3051}
3052#endif /* HAVE_SSL */
3053
3054
6d2f911b
MS
3055#ifdef HAVE_LIBSSL
3056/*
3057 * 'http_locking_cb()' - Lock/unlock a thread's mutex.
3058 */
3059
3060static void
3061http_locking_cb(int mode, /* I - Lock mode */
3062 int type, /* I - Lock type */
3063 const char *file, /* I - Source file */
3064 int line) /* I - Line number */
3065{
3066 if (mode & CRYPTO_LOCK)
3067 _cupsMutexLock(http_locks + type);
3068 else
3069 _cupsMutexUnlock(http_locks + type);
3070}
3071#endif /* HAVE_LIBSSL */
3072
3073
ef416fc2 3074/*
3075 * 'http_send()' - Send a request with all fields and the trailing blank line.
3076 */
3077
3078static int /* O - 0 on success, non-zero on error */
568fa3fa 3079http_send(http_t *http, /* I - Connection to server */
ef416fc2 3080 http_state_t request, /* I - Request code */
3081 const char *uri) /* I - URI */
3082{
3083 int i; /* Looping var */
839a51c8 3084 char buf[1024]; /* Encoded URI buffer */
ef416fc2 3085 static const char * const codes[] =
3086 { /* Request code strings */
3087 NULL,
3088 "OPTIONS",
3089 "GET",
3090 NULL,
3091 "HEAD",
3092 "POST",
3093 NULL,
3094 NULL,
3095 "PUT",
3096 NULL,
3097 "DELETE",
3098 "TRACE",
3099 "CLOSE"
3100 };
ef416fc2 3101
3102
e07d4801 3103 DEBUG_printf(("7http_send(http=%p, request=HTTP_%s, uri=\"%s\")",
ef416fc2 3104 http, codes[request], uri));
3105
3106 if (http == NULL || uri == NULL)
3107 return (-1);
3108
3109 /*
3110 * Set the User-Agent field if it isn't already...
3111 */
3112
3113 if (!http->fields[HTTP_FIELD_USER_AGENT][0])
3114 httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
3115
3116 /*
3117 * Encode the URI as needed...
3118 */
3119
839a51c8 3120 _httpEncodeURI(buf, uri, sizeof(buf));
ef416fc2 3121
3122 /*
3123 * See if we had an error the last time around; if so, reconnect...
3124 */
3125
3126 if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
fa73b229 3127 if (httpReconnect(http))
3128 return (-1);
ef416fc2 3129
d09495fa 3130 /*
3131 * Flush any written data that is pending...
3132 */
3133
3134 if (http->wused)
536bc2c6
MS
3135 {
3136 if (httpFlushWrite(http) < 0)
3137 if (httpReconnect(http))
3138 return (-1);
3139 }
d09495fa 3140
ef416fc2 3141 /*
3142 * Send the request header...
3143 */
3144
d09495fa 3145 http->state = request;
3146 http->data_encoding = HTTP_ENCODE_FIELDS;
3147
ef416fc2 3148 if (request == HTTP_POST || request == HTTP_PUT)
3149 http->state ++;
3150
3151 http->status = HTTP_CONTINUE;
3152
3153#ifdef HAVE_SSL
3154 if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
3155 {
3156 httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
3157 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
3158 }
3159#endif /* HAVE_SSL */
3160
3161 if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
3162 {
3163 http->status = HTTP_ERROR;
3164 return (-1);
3165 }
3166
3167 for (i = 0; i < HTTP_FIELD_MAX; i ++)
3168 if (http->fields[i][0] != '\0')
3169 {
e07d4801 3170 DEBUG_printf(("9http_send: %s: %s", http_fields[i],
ae71f5de 3171 httpGetField(http, i)));
ef416fc2 3172
ef55b745 3173 if (httpPrintf(http, "%s: %s\r\n", http_fields[i],
f7deaa1a 3174 httpGetField(http, i)) < 1)
ef416fc2 3175 {
3176 http->status = HTTP_ERROR;
3177 return (-1);
3178 }
3179 }
3180
3181 if (http->cookie)
3182 if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
3183 {
3184 http->status = HTTP_ERROR;
3185 return (-1);
3186 }
3187
b423cd4c 3188 if (http->expect == HTTP_CONTINUE &&
3189 (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
3190 if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
3191 {
3192 http->status = HTTP_ERROR;
3193 return (-1);
3194 }
3195
ef416fc2 3196 if (httpPrintf(http, "\r\n") < 1)
3197 {
3198 http->status = HTTP_ERROR;
3199 return (-1);
3200 }
3201
536bc2c6
MS
3202 if (httpFlushWrite(http) < 0)
3203 return (-1);
3204
ef416fc2 3205 httpGetLength2(http);
3206 httpClearFields(http);
3207
f7deaa1a 3208 /*
b94498cf 3209 * The Kerberos and AuthRef authentication strings can only be used once...
f7deaa1a 3210 */
3211
ef55b745
MS
3212 if (http->field_authorization && http->authstring &&
3213 (!strncmp(http->authstring, "Negotiate", 9) ||
b94498cf 3214 !strncmp(http->authstring, "AuthRef", 7)))
f7deaa1a 3215 {
3216 http->_authstring[0] = '\0';
3217
3218 if (http->authstring != http->_authstring)
3219 free(http->authstring);
ef55b745 3220
f7deaa1a 3221 http->authstring = http->_authstring;
3222 }
3223
ef416fc2 3224 return (0);
3225}
3226
3227
3228#ifdef HAVE_SSL
3229/*
3230 * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
3231 */
3232
3233static int /* O - Status of connection */
568fa3fa 3234http_setup_ssl(http_t *http) /* I - Connection to server */
ef416fc2 3235{
3236# ifdef HAVE_LIBSSL
89d46774 3237 SSL_CTX *context; /* Context for encryption */
3238 SSL *conn; /* Connection for encryption */
411affcf 3239 BIO *bio; /* BIO data */
ef416fc2 3240# elif defined(HAVE_GNUTLS)
89d46774 3241 http_tls_t *conn; /* TLS session object */
ef416fc2 3242 gnutls_certificate_client_credentials *credentials;
89d46774 3243 /* TLS credentials */
ef416fc2 3244# elif defined(HAVE_CDSASSL)
89d46774 3245 OSStatus error; /* Error code */
3246 http_tls_t *conn; /* CDSA connection information */
ef416fc2 3247# endif /* HAVE_LIBSSL */
3248
3249
e07d4801 3250 DEBUG_printf(("7http_setup_ssl(http=%p)", http));
ef416fc2 3251
3252# ifdef HAVE_LIBSSL
3253 context = SSL_CTX_new(SSLv23_client_method());
3254
3255 SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
3256
411affcf 3257 bio = BIO_new(_httpBIOMethods());
3258 BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
3259
ef416fc2 3260 conn = SSL_new(context);
411affcf 3261 SSL_set_bio(conn, bio, bio);
ef416fc2 3262
ef416fc2 3263 if (SSL_connect(conn) != 1)
3264 {
3265# ifdef DEBUG
3266 unsigned long error; /* Error code */
3267
3268 while ((error = ERR_get_error()) != 0)
e07d4801 3269 DEBUG_printf(("8http_setup_ssl: %s", ERR_error_string(error, NULL)));
ef416fc2 3270# endif /* DEBUG */
3271
3272 SSL_CTX_free(context);
3273 SSL_free(conn);
3274
3275# ifdef WIN32
3276 http->error = WSAGetLastError();
3277# else
3278 http->error = errno;
3279# endif /* WIN32 */
3280 http->status = HTTP_ERROR;
3281
3282 return (HTTP_ERROR);
3283 }
3284
3285# elif defined(HAVE_GNUTLS)
89d46774 3286 if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
ef416fc2 3287 {
3288 http->error = errno;
3289 http->status = HTTP_ERROR;
3290
3291 return (-1);
3292 }
3293
3294 credentials = (gnutls_certificate_client_credentials *)
3295 malloc(sizeof(gnutls_certificate_client_credentials));
3296 if (credentials == NULL)
3297 {
3298 free(conn);
3299
3300 http->error = errno;
3301 http->status = HTTP_ERROR;
3302
3303 return (-1);
3304 }
3305
3306 gnutls_certificate_allocate_credentials(credentials);
3307
3308 gnutls_init(&(conn->session), GNUTLS_CLIENT);
3309 gnutls_set_default_priority(conn->session);
3310 gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
411affcf 3311 gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)http);
3312 gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
3313 gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
ef416fc2 3314
3315 if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
3316 {
3317 http->error = errno;
3318 http->status = HTTP_ERROR;
3319
85b5d1df
MS
3320 gnutls_deinit(conn->session);
3321 gnutls_certificate_free_credentials(*credentials);
3322 free(credentials);
3323 free(conn);
3324
ef416fc2 3325 return (-1);
3326 }
3327
3328 conn->credentials = credentials;
3329
3330# elif defined(HAVE_CDSASSL)
89d46774 3331 conn = (http_tls_t *)calloc(1, sizeof(http_tls_t));
e53920b9 3332
89d46774 3333 if (conn == NULL)
3334 return (-1);
e53920b9 3335
89d46774 3336 if ((error = SSLNewContext(false, &conn->session)))
e53920b9 3337 {
89d46774 3338 http->error = error;
3339 http->status = HTTP_ERROR;
e53920b9 3340
89d46774 3341 free(conn);
3342 return (-1);
e53920b9 3343 }
ef416fc2 3344
89d46774 3345 /*
3346 * Use a union to resolve warnings about int/pointer size mismatches...
3347 */
3348
411affcf 3349 error = SSLSetConnection(conn->session, http);
89d46774 3350
3351 if (!error)
3352 error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
3353
ef416fc2 3354 if (!error)
89d46774 3355 error = SSLSetAllowsExpiredCerts(conn->session, true);
ef416fc2 3356
3357 if (!error)
89d46774 3358 error = SSLSetAllowsAnyRoot(conn->session, true);
ef416fc2 3359
ed486911 3360 if (!error)
3361 error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
3362
ef416fc2 3363 if (!error)
b423cd4c 3364 {
89d46774 3365 while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
b423cd4c 3366 usleep(1000);
3367 }
ef416fc2 3368
89d46774 3369 if (error)
ef416fc2 3370 {
3371 http->error = error;
3372 http->status = HTTP_ERROR;
3373
89d46774 3374 SSLDisposeContext(conn->session);
ef416fc2 3375
89d46774 3376 free(conn);
ef416fc2 3377
3378 return (-1);
3379 }
3380# endif /* HAVE_CDSASSL */
3381
3382 http->tls = conn;
3383 return (0);
3384}
3385#endif /* HAVE_SSL */
3386
3387
3388#ifdef HAVE_SSL
3389/*
3390 * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
3391 */
3392
3393static void
568fa3fa 3394http_shutdown_ssl(http_t *http) /* I - Connection to server */
ef416fc2 3395{
3396# ifdef HAVE_LIBSSL
89d46774 3397 SSL_CTX *context; /* Context for encryption */
3398 SSL *conn; /* Connection for encryption */
ef416fc2 3399
3400
3401 conn = (SSL *)(http->tls);
3402 context = SSL_get_SSL_CTX(conn);
3403
3404 SSL_shutdown(conn);
3405 SSL_CTX_free(context);
3406 SSL_free(conn);
3407
3408# elif defined(HAVE_GNUTLS)
89d46774 3409 http_tls_t *conn; /* Encryption session */
ef416fc2 3410 gnutls_certificate_client_credentials *credentials;
89d46774 3411 /* TLS credentials */
ef416fc2 3412
3413
3414 conn = (http_tls_t *)(http->tls);
3415 credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
3416
3417 gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
3418 gnutls_deinit(conn->session);
3419 gnutls_certificate_free_credentials(*credentials);
3420 free(credentials);
3421 free(conn);
3422
3423# elif defined(HAVE_CDSASSL)
89d46774 3424 http_tls_t *conn; /* CDSA connection information */
3425
3426
3427 conn = (http_tls_t *)(http->tls);
3428
3429 while (SSLClose(conn->session) == errSSLWouldBlock)
b423cd4c 3430 usleep(1000);
3431
89d46774 3432 SSLDisposeContext(conn->session);
3433
3434 if (conn->certsArray)
3435 CFRelease(conn->certsArray);
3436
3437 free(conn);
ef416fc2 3438# endif /* HAVE_LIBSSL */
3439
3440 http->tls = NULL;
3441}
3442#endif /* HAVE_SSL */
3443
3444
6d2f911b
MS
3445#ifdef HAVE_LIBSSL
3446/*
3447 * 'http_threadid_cb()' - Return the current thread ID.
3448 */
3449
3450static unsigned long /* O - Thread ID */
3451http_threadid_cb(void)
3452{
3453# ifdef HAVE_PTHREAD_H
3454 return ((unsigned long)pthread_self());
3455# else
3456 return (0);
3457# endif /* HAVE_PTHREAD_H */
3458}
3459#endif /* HAVE_LIBSSL */
3460
3461
ef416fc2 3462#ifdef HAVE_SSL
3463/*
3464 * 'http_upgrade()' - Force upgrade to TLS encryption.
3465 */
3466
89d46774 3467static int /* O - Status of connection */
568fa3fa 3468http_upgrade(http_t *http) /* I - Connection to server */
ef416fc2 3469{
89d46774 3470 int ret; /* Return value */
3471 http_t myhttp; /* Local copy of HTTP data */
ef416fc2 3472
3473
e07d4801 3474 DEBUG_printf(("7http_upgrade(%p)", http));
ef416fc2 3475
85b5d1df
MS
3476 /*
3477 * Flush the connection to make sure any previous "Upgrade" message
3478 * has been read.
3479 */
3480
3481 httpFlush(http);
3482
ef416fc2 3483 /*
3484 * Copy the HTTP data to a local variable so we can do the OPTIONS
3485 * request without interfering with the existing request data...
3486 */
3487
3488 memcpy(&myhttp, http, sizeof(myhttp));
3489
3490 /*
3491 * Send an OPTIONS request to the server, requiring SSL or TLS
3492 * encryption on the link...
3493 */
3494
f7deaa1a 3495 http->field_authorization = NULL; /* Don't free the auth string */
3496
b86bc4cf 3497 httpClearFields(http);
3498 httpSetField(http, HTTP_FIELD_CONNECTION, "upgrade");
3499 httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
ef416fc2 3500
b86bc4cf 3501 if ((ret = httpOptions(http, "*")) == 0)
ef416fc2 3502 {
3503 /*
3504 * Wait for the secure connection...
3505 */
3506
b86bc4cf 3507 while (httpUpdate(http) == HTTP_CONTINUE);
ef416fc2 3508 }
3509
ef416fc2 3510 /*
b86bc4cf 3511 * Restore the HTTP request data...
ef416fc2 3512 */
3513
b86bc4cf 3514 memcpy(http->fields, myhttp.fields, sizeof(http->fields));
f7deaa1a 3515 http->data_encoding = myhttp.data_encoding;
3516 http->data_remaining = myhttp.data_remaining;
3517 http->_data_remaining = myhttp._data_remaining;
3518 http->expect = myhttp.expect;
3519 http->field_authorization = myhttp.field_authorization;
bc44d920 3520 http->digest_tries = myhttp.digest_tries;
ef416fc2 3521
3522 /*
3523 * See if we actually went secure...
3524 */
3525
3526 if (!http->tls)
3527 {
3528 /*
3529 * Server does not support HTTP upgrade...
3530 */
3531
e07d4801 3532 DEBUG_puts("8http_upgrade: Server does not support HTTP upgrade!");
ef416fc2 3533
3534# ifdef WIN32
3535 closesocket(http->fd);
3536# else
3537 close(http->fd);
3538# endif
3539
3540 http->fd = -1;
3541
3542 return (-1);
3543 }
3544 else
3545 return (ret);
3546}
3547#endif /* HAVE_SSL */
3548
3549
ef416fc2 3550/*
3551 * 'http_write()' - Write a buffer to a HTTP connection.
3552 */
ef55b745 3553
ef416fc2 3554static int /* O - Number of bytes written */
568fa3fa 3555http_write(http_t *http, /* I - Connection to server */
f11a948a
MS
3556 const char *buffer, /* I - Buffer for data */
3557 int length) /* I - Number of bytes to write */
ef416fc2 3558{
3559 int tbytes, /* Total bytes sent */
3560 bytes; /* Bytes sent */
3561
3562
f8b3a85b
MS
3563 DEBUG_printf(("2http_write(http=%p, buffer=%p, length=%d)", http, buffer,
3564 length));
f11a948a
MS
3565 http->error = 0;
3566 tbytes = 0;
ef416fc2 3567
3568 while (length > 0)
3569 {
3570#ifdef HAVE_SSL
3571 if (http->tls)
3572 bytes = http_write_ssl(http, buffer, length);
3573 else
3574#endif /* HAVE_SSL */
3575 bytes = send(http->fd, buffer, length, 0);
3576
3577 if (bytes < 0)
3578 {
3579#ifdef WIN32
3580 if (WSAGetLastError() != http->error)
3581 {
3582 http->error = WSAGetLastError();
3583 continue;
3584 }
3585#else
e07d4801 3586 if (errno == EINTR || errno == EAGAIN)
ef416fc2 3587 continue;
3588 else if (errno != http->error && errno != ECONNRESET)
3589 {
3590 http->error = errno;
3591 continue;
3592 }
3593#endif /* WIN32 */
3594
f8b3a85b
MS
3595 DEBUG_printf(("3http_write: error writing data (%s).",
3596 strerror(http->error)));
ef416fc2 3597
3598 return (-1);
3599 }
3600
3601 buffer += bytes;
3602 tbytes += bytes;
3603 length -= bytes;
3604 }
3605
3606#ifdef DEBUG
ae71f5de 3607 http_debug_hex("http_write", buffer - tbytes, tbytes);
ef416fc2 3608#endif /* DEBUG */
3609
f8b3a85b
MS
3610 DEBUG_printf(("3http_write: Returning %d.", tbytes));
3611
ef416fc2 3612 return (tbytes);
3613}
3614
3615
3616/*
3617 * 'http_write_chunk()' - Write a chunked buffer.
3618 */
3619
3620static int /* O - Number bytes written */
568fa3fa 3621http_write_chunk(http_t *http, /* I - Connection to server */
ef416fc2 3622 const char *buffer, /* I - Buffer to write */
3623 int length) /* I - Length of buffer */
3624{
3625 char header[255]; /* Chunk header */
3626 int bytes; /* Bytes written */
3627
f11a948a 3628
e07d4801 3629 DEBUG_printf(("7http_write_chunk(http=%p, buffer=%p, length=%d)",
ef416fc2 3630 http, buffer, length));
3631
3632 /*
3633 * Write the chunk header, data, and trailer.
3634 */
3635
3636 sprintf(header, "%x\r\n", length);
b86bc4cf 3637 if (http_write(http, header, (int)strlen(header)) < 0)
ef416fc2 3638 {
e07d4801 3639 DEBUG_puts("8http_write_chunk: http_write of length failed!");
ef416fc2 3640 return (-1);
3641 }
3642
3643 if ((bytes = http_write(http, buffer, length)) < 0)
3644 {
e07d4801 3645 DEBUG_puts("8http_write_chunk: http_write of buffer failed!");
ef416fc2 3646 return (-1);
3647 }
3648
3649 if (http_write(http, "\r\n", 2) < 0)
3650 {
e07d4801 3651 DEBUG_puts("8http_write_chunk: http_write of CR LF failed!");
ef416fc2 3652 return (-1);
3653 }
3654
3655 return (bytes);
3656}
3657
3658
3659#ifdef HAVE_SSL
3660/*
3661 * 'http_write_ssl()' - Write to a SSL/TLS connection.
3662 */
3663
3664static int /* O - Bytes written */
568fa3fa 3665http_write_ssl(http_t *http, /* I - Connection to server */
ef416fc2 3666 const char *buf, /* I - Buffer holding data */
3667 int len) /* I - Length of buffer */
3668{
f8b3a85b
MS
3669 ssize_t result; /* Return value */
3670
3671
3672 DEBUG_printf(("2http_write_ssl(http=%p, buf=%p, len=%d)", http, buf, len));
3673
ef416fc2 3674# if defined(HAVE_LIBSSL)
f8b3a85b 3675 result = SSL_write((SSL *)(http->tls), buf, len);
ef416fc2 3676
3677# elif defined(HAVE_GNUTLS)
ef55b745
MS
3678 result = gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len);
3679
3680 if (result < 0 && !errno)
3681 {
3682 /*
3683 * Convert GNU TLS error to errno value...
3684 */
3685
3686 switch (result)
3687 {
3688 case GNUTLS_E_INTERRUPTED :
3689 errno = EINTR;
3690 break;
3691
3692 case GNUTLS_E_AGAIN :
3693 errno = EAGAIN;
3694 break;
3695
3696 default :
3697 errno = EPIPE;
3698 break;
3699 }
3700
3701 result = -1;
3702 }
3703
ef416fc2 3704# elif defined(HAVE_CDSASSL)
3705 OSStatus error; /* Error info */
3706 size_t processed; /* Number of bytes processed */
3707
3708
89d46774 3709 error = SSLWrite(((http_tls_t *)http->tls)->session, buf, len, &processed);
ef416fc2 3710
fa73b229 3711 switch (error)
ef416fc2 3712 {
fa73b229 3713 case 0 :
3714 result = (int)processed;
3715 break;
3716 case errSSLClosedGraceful :
3717 result = 0;
3718 break;
3719 case errSSLWouldBlock :
b423cd4c 3720 if (processed)
3721 result = (int)processed;
3722 else
3723 {
3724 result = -1;
ef55b745 3725 errno = EINTR;
b423cd4c 3726 }
fa73b229 3727 break;
3728 default :
ef55b745 3729 errno = EPIPE;
fa73b229 3730 result = -1;
3731 break;
ef416fc2 3732 }
3733# endif /* HAVE_LIBSSL */
f8b3a85b
MS
3734
3735 DEBUG_printf(("3http_write_ssl: Returning %d.", (int)result));
3736
3737 return ((int)result);
ef416fc2 3738}
3739#endif /* HAVE_SSL */
3740
3741
3742/*
b19ccc9e 3743 * End of "$Id: http.c 7850 2008-08-20 00:07:25Z mike $".
ef416fc2 3744 */