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