Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Utilities / cmcurl-7.19.0 / lib / easy.c
blobc719f2f965dde9e03dbc890765fbcdda7caf57b9
1 /***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
10 * This software is licensed as described in the file COPYING, which
11 * you should have received as part of this distribution. The terms
12 * are also available at http://curl.haxx.se/docs/copyright.html.
14 * You may opt to use, copy, modify, merge, publish, distribute and/or sell
15 * copies of the Software, and permit persons to whom the Software is
16 * furnished to do so, under the terms of the COPYING file.
18 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19 * KIND, either express or implied.
21 * $Id: easy.c,v 1.1.1.1 2008-09-23 16:32:05 hoffman Exp $
22 ***************************************************************************/
24 #include "setup.h"
26 /* -- WIN32 approved -- */
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <ctype.h>
32 #include <errno.h>
34 #include "strequal.h"
36 #ifdef WIN32
37 #include <time.h>
38 #include <io.h>
39 #else
40 #ifdef HAVE_SYS_SOCKET_H
41 #include <sys/socket.h>
42 #endif
43 #ifdef HAVE_NETINET_IN_H
44 #include <netinet/in.h>
45 #endif
46 #ifdef HAVE_SYS_TIME_H
47 #include <sys/time.h>
48 #endif
49 #ifdef HAVE_UNISTD_H
50 #include <unistd.h>
51 #endif
52 #ifdef HAVE_NETDB_H
53 #include <netdb.h>
54 #endif
55 #ifdef HAVE_ARPA_INET_H
56 #include <arpa/inet.h>
57 #endif
58 #ifdef HAVE_NET_IF_H
59 #include <net/if.h>
60 #endif
61 #ifdef HAVE_SYS_IOCTL_H
62 #include <sys/ioctl.h>
63 #endif
64 #include <signal.h>
66 #ifdef HAVE_SYS_PARAM_H
67 #include <sys/param.h>
68 #endif
70 #endif /* WIN32 ... */
72 #include "urldata.h"
73 #include <curl/curl.h>
74 #include "transfer.h"
75 #include "sslgen.h"
76 #include "url.h"
77 #include "getinfo.h"
78 #include "hostip.h"
79 #include "share.h"
80 #include "strdup.h"
81 #include "memory.h"
82 #include "progress.h"
83 #include "easyif.h"
84 #include "select.h"
85 #include "sendf.h" /* for failf function prototype */
86 #include "http_ntlm.h"
87 #include "connect.h" /* for Curl_getconnectinfo */
89 #define _MPRINTF_REPLACE /* use our functions only */
90 #include <curl/mprintf.h>
92 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
93 #include <iconv.h>
94 /* set default codesets for iconv */
95 #ifndef CURL_ICONV_CODESET_OF_NETWORK
96 #define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
97 #endif
98 #ifndef CURL_ICONV_CODESET_FOR_UTF8
99 #define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
100 #endif
101 #define ICONV_ERROR (size_t)-1
102 #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
104 /* The last #include file should be: */
105 #include "memdebug.h"
107 /* win32_cleanup() is for win32 socket cleanup functionality, the opposite
108 of win32_init() */
109 static void win32_cleanup(void)
111 #ifdef USE_WINSOCK
112 WSACleanup();
113 #endif
114 #ifdef USE_WINDOWS_SSPI
115 Curl_ntlm_global_cleanup();
116 #endif
119 /* win32_init() performs win32 socket initialization to properly setup the
120 stack to allow networking */
121 static CURLcode win32_init(void)
123 #ifdef USE_WINSOCK
124 WORD wVersionRequested;
125 WSADATA wsaData;
126 int err;
128 #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
129 Error IPV6_requires_winsock2
130 #endif
132 wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
134 err = WSAStartup(wVersionRequested, &wsaData);
136 if(err != 0)
137 /* Tell the user that we couldn't find a useable */
138 /* winsock.dll. */
139 return CURLE_FAILED_INIT;
141 /* Confirm that the Windows Sockets DLL supports what we need.*/
142 /* Note that if the DLL supports versions greater */
143 /* than wVersionRequested, it will still return */
144 /* wVersionRequested in wVersion. wHighVersion contains the */
145 /* highest supported version. */
147 if( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
148 HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
149 /* Tell the user that we couldn't find a useable */
151 /* winsock.dll. */
152 WSACleanup();
153 return CURLE_FAILED_INIT;
155 /* The Windows Sockets DLL is acceptable. Proceed. */
156 #endif
158 #ifdef USE_WINDOWS_SSPI
160 CURLcode err = Curl_ntlm_global_init();
161 if (err != CURLE_OK)
162 return err;
164 #endif
166 return CURLE_OK;
169 #ifdef USE_LIBIDN
171 * Initialise use of IDNA library.
172 * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
173 * idna_to_ascii_lz().
175 static void idna_init (void)
177 #ifdef WIN32
178 char buf[60];
179 UINT cp = GetACP();
181 if(!getenv("CHARSET") && cp > 0) {
182 snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
183 putenv(buf);
185 #else
186 /* to do? */
187 #endif
189 #endif /* USE_LIBIDN */
191 /* true globals -- for curl_global_init() and curl_global_cleanup() */
192 static unsigned int initialized;
193 static long init_flags;
196 * strdup (and other memory functions) is redefined in complicated
197 * ways, but at this point it must be defined as the system-supplied strdup
198 * so the callback pointer is initialized correctly.
200 #if defined(_WIN32_WCE)
201 #define system_strdup _strdup
202 #elif !defined(HAVE_STRDUP)
203 #define system_strdup curlx_strdup
204 #else
205 #define system_strdup strdup
206 #endif
208 #if defined(_MSC_VER) && defined(_DLL)
209 # pragma warning(disable:4232) /* MSVC extension, dllimport identity */
210 #endif
212 #ifndef __SYMBIAN32__
214 * If a memory-using function (like curl_getenv) is used before
215 * curl_global_init() is called, we need to have these pointers set already.
217 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
218 curl_free_callback Curl_cfree = (curl_free_callback)free;
219 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
220 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
221 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
222 #else
224 * Symbian OS doesn't support initialization to code in writeable static data.
225 * Initialization will occur in the curl_global_init() call.
227 curl_malloc_callback Curl_cmalloc;
228 curl_free_callback Curl_cfree;
229 curl_realloc_callback Curl_crealloc;
230 curl_strdup_callback Curl_cstrdup;
231 curl_calloc_callback Curl_ccalloc;
232 #endif
234 #if defined(_MSC_VER) && defined(_DLL)
235 # pragma warning(default:4232) /* MSVC extension, dllimport identity */
236 #endif
239 * curl_global_init() globally initializes cURL given a bitwise set of the
240 * different features of what to initialize.
242 CURLcode curl_global_init(long flags)
244 if(initialized++)
245 return CURLE_OK;
247 /* Setup the default memory functions here (again) */
248 Curl_cmalloc = (curl_malloc_callback)malloc;
249 Curl_cfree = (curl_free_callback)free;
250 Curl_crealloc = (curl_realloc_callback)realloc;
251 Curl_cstrdup = (curl_strdup_callback)system_strdup;
252 Curl_ccalloc = (curl_calloc_callback)calloc;
254 if(flags & CURL_GLOBAL_SSL)
255 if(!Curl_ssl_init()) {
256 DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
257 return CURLE_FAILED_INIT;
260 if(flags & CURL_GLOBAL_WIN32)
261 if(win32_init() != CURLE_OK) {
262 DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
263 return CURLE_FAILED_INIT;
266 #ifdef __AMIGA__
267 if(!amiga_init()) {
268 DEBUGF(fprintf(stderr, "Error: amiga_init failed\n"));
269 return CURLE_FAILED_INIT;
271 #endif
273 #ifdef NETWARE
274 if(netware_init()) {
275 DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
277 #endif
279 #ifdef USE_LIBIDN
280 idna_init();
281 #endif
283 init_flags = flags;
285 return CURLE_OK;
289 * curl_global_init_mem() globally initializes cURL and also registers the
290 * user provided callback routines.
292 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
293 curl_free_callback f, curl_realloc_callback r,
294 curl_strdup_callback s, curl_calloc_callback c)
296 CURLcode code = CURLE_OK;
298 /* Invalid input, return immediately */
299 if(!m || !f || !r || !s || !c)
300 return CURLE_FAILED_INIT;
302 /* Already initialized, don't do it again */
303 if( initialized )
304 return CURLE_OK;
306 /* Call the actual init function first */
307 code = curl_global_init(flags);
308 if(code == CURLE_OK) {
309 Curl_cmalloc = m;
310 Curl_cfree = f;
311 Curl_cstrdup = s;
312 Curl_crealloc = r;
313 Curl_ccalloc = c;
316 return code;
320 * curl_global_cleanup() globally cleanups cURL, uses the value of
321 * "init_flags" to determine what needs to be cleaned up and what doesn't.
323 void curl_global_cleanup(void)
325 if(!initialized)
326 return;
328 if(--initialized)
329 return;
331 Curl_global_host_cache_dtor();
333 if(init_flags & CURL_GLOBAL_SSL)
334 Curl_ssl_cleanup();
336 if(init_flags & CURL_GLOBAL_WIN32)
337 win32_cleanup();
339 #ifdef __AMIGA__
340 amiga_cleanup();
341 #endif
343 init_flags = 0;
347 * curl_easy_init() is the external interface to alloc, setup and init an
348 * easy handle that is returned. If anything goes wrong, NULL is returned.
350 CURL *curl_easy_init(void)
352 CURLcode res;
353 struct SessionHandle *data;
355 /* Make sure we inited the global SSL stuff */
356 if(!initialized) {
357 res = curl_global_init(CURL_GLOBAL_DEFAULT);
358 if(res) {
359 /* something in the global init failed, return nothing */
360 DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
361 return NULL;
365 /* We use curl_open() with undefined URL so far */
366 res = Curl_open(&data);
367 if(res != CURLE_OK) {
368 DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
369 return NULL;
372 return data;
376 * curl_easy_setopt() is the external interface for setting options on an
377 * easy handle.
380 #undef curl_easy_setopt
381 CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
383 va_list arg;
384 struct SessionHandle *data = curl;
385 CURLcode ret;
387 if(!curl)
388 return CURLE_BAD_FUNCTION_ARGUMENT;
390 va_start(arg, tag);
392 ret = Curl_setopt(data, tag, arg);
394 va_end(arg);
395 return ret;
398 #ifdef CURL_MULTIEASY
399 /***************************************************************************
400 * This function is still only for testing purposes. It makes a great way
401 * to run the full test suite on the multi interface instead of the easy one.
402 ***************************************************************************
404 * The *new* curl_easy_perform() is the external interface that performs a
405 * transfer previously setup.
407 * Wrapper-function that: creates a multi handle, adds the easy handle to it,
408 * runs curl_multi_perform() until the transfer is done, then detaches the
409 * easy handle, destroys the multi handle and returns the easy handle's return
410 * code. This will make everything internally use and assume multi interface.
412 CURLcode curl_easy_perform(CURL *easy)
414 CURLM *multi;
415 CURLMcode mcode;
416 CURLcode code = CURLE_OK;
417 int still_running;
418 struct timeval timeout;
419 int rc;
420 CURLMsg *msg;
421 fd_set fdread;
422 fd_set fdwrite;
423 fd_set fdexcep;
424 int maxfd;
426 if(!easy)
427 return CURLE_BAD_FUNCTION_ARGUMENT;
429 multi = curl_multi_init();
430 if(!multi)
431 return CURLE_OUT_OF_MEMORY;
433 mcode = curl_multi_add_handle(multi, easy);
434 if(mcode) {
435 curl_multi_cleanup(multi);
436 if(mcode == CURLM_OUT_OF_MEMORY)
437 return CURLE_OUT_OF_MEMORY;
438 else
439 return CURLE_FAILED_INIT;
442 /* we start some action by calling perform right away */
444 do {
445 while(CURLM_CALL_MULTI_PERFORM ==
446 curl_multi_perform(multi, &still_running));
448 if(!still_running)
449 break;
451 FD_ZERO(&fdread);
452 FD_ZERO(&fdwrite);
453 FD_ZERO(&fdexcep);
455 /* timeout once per second */
456 timeout.tv_sec = 1;
457 timeout.tv_usec = 0;
459 /* Old deprecated style: get file descriptors from the transfers */
460 curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
461 rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
463 /* The way is to extract the sockets and wait for them without using
464 select. This whole alternative version should probably rather use the
465 curl_multi_socket() approach. */
467 if(rc == -1)
468 /* select error */
469 break;
471 /* timeout or data to send/receive => loop! */
472 } while(still_running);
474 msg = curl_multi_info_read(multi, &rc);
475 if(msg)
476 code = msg->data.result;
478 mcode = curl_multi_remove_handle(multi, easy);
479 /* what to do if it fails? */
481 mcode = curl_multi_cleanup(multi);
482 /* what to do if it fails? */
484 return code;
486 #else
488 * curl_easy_perform() is the external interface that performs a transfer
489 * previously setup.
491 CURLcode curl_easy_perform(CURL *curl)
493 struct SessionHandle *data = (struct SessionHandle *)curl;
495 if(!data)
496 return CURLE_BAD_FUNCTION_ARGUMENT;
498 if( ! (data->share && data->share->hostcache) ) {
499 /* this handle is not using a shared dns cache */
501 if(data->set.global_dns_cache &&
502 (data->dns.hostcachetype != HCACHE_GLOBAL)) {
503 /* global dns cache was requested but still isn't */
504 struct curl_hash *ptr;
506 if(data->dns.hostcachetype == HCACHE_PRIVATE)
507 /* if the current cache is private, kill it first */
508 Curl_hash_destroy(data->dns.hostcache);
510 ptr = Curl_global_host_cache_init();
511 if(ptr) {
512 /* only do this if the global cache init works */
513 data->dns.hostcache = ptr;
514 data->dns.hostcachetype = HCACHE_GLOBAL;
518 if(!data->dns.hostcache) {
519 data->dns.hostcachetype = HCACHE_PRIVATE;
520 data->dns.hostcache = Curl_mk_dnscache();
522 if(!data->dns.hostcache)
523 /* While we possibly could survive and do good without a host cache,
524 the fact that creating it failed indicates that things are truly
525 screwed up and we should bail out! */
526 return CURLE_OUT_OF_MEMORY;
531 if(!data->state.connc) {
532 /* oops, no connection cache, make one up */
533 data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1);
534 if(!data->state.connc)
535 return CURLE_OUT_OF_MEMORY;
538 return Curl_perform(data);
540 #endif
543 * curl_easy_cleanup() is the external interface to cleaning/freeing the given
544 * easy handle.
546 void curl_easy_cleanup(CURL *curl)
548 struct SessionHandle *data = (struct SessionHandle *)curl;
550 if(!data)
551 return;
553 Curl_close(data);
557 * Store a pointed to the multi handle within the easy handle's data struct.
559 void Curl_easy_addmulti(struct SessionHandle *data,
560 void *multi)
562 data->multi = multi;
563 if(multi == NULL)
564 /* the association is cleared, mark the easy handle as not used by an
565 interface */
566 data->state.used_interface = Curl_if_none;
569 void Curl_easy_initHandleData(struct SessionHandle *data)
571 memset(&data->req, 0, sizeof(struct SingleRequest));
573 data->req.maxdownload = -1;
577 * curl_easy_getinfo() is an external interface that allows an app to retrieve
578 * information from a performed transfer and similar.
580 #undef curl_easy_getinfo
581 CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
583 va_list arg;
584 void *paramp;
585 struct SessionHandle *data = (struct SessionHandle *)curl;
587 va_start(arg, info);
588 paramp = va_arg(arg, void *);
590 return Curl_getinfo(data, info, paramp);
594 * curl_easy_duphandle() is an external interface to allow duplication of a
595 * given input easy handle. The returned handle will be a new working handle
596 * with all options set exactly as the input source handle.
598 CURL *curl_easy_duphandle(CURL *incurl)
600 bool fail = TRUE;
601 struct SessionHandle *data=(struct SessionHandle *)incurl;
603 struct SessionHandle *outcurl = (struct SessionHandle *)
604 calloc(sizeof(struct SessionHandle), 1);
606 if(NULL == outcurl)
607 return NULL; /* failure */
609 do {
612 * We setup a few buffers we need. We should probably make them
613 * get setup on-demand in the code, as that would probably decrease
614 * the likeliness of us forgetting to init a buffer here in the future.
616 outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
617 if(!outcurl->state.headerbuff) {
618 break;
620 outcurl->state.headersize=HEADERSIZE;
622 /* copy all userdefined values */
623 if(Curl_dupset(outcurl, data) != CURLE_OK)
624 break;
626 if(data->state.used_interface == Curl_if_multi)
627 outcurl->state.connc = data->state.connc;
628 else
629 outcurl->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1);
631 if(!outcurl->state.connc)
632 break;
634 outcurl->state.lastconnect = -1;
636 outcurl->progress.flags = data->progress.flags;
637 outcurl->progress.callback = data->progress.callback;
639 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
640 if(data->cookies) {
641 /* If cookies are enabled in the parent handle, we enable them
642 in the clone as well! */
643 outcurl->cookies = Curl_cookie_init(data,
644 data->cookies->filename,
645 outcurl->cookies,
646 data->set.cookiesession);
647 if(!outcurl->cookies) {
648 break;
651 #endif /* CURL_DISABLE_HTTP */
653 /* duplicate all values in 'change' */
655 if(data->change.url) {
656 outcurl->change.url = strdup(data->change.url);
657 if(!outcurl->change.url)
658 break;
659 outcurl->change.url_alloc = TRUE;
662 if(data->change.referer) {
663 outcurl->change.referer = strdup(data->change.referer);
664 if(!outcurl->change.referer)
665 break;
666 outcurl->change.referer_alloc = TRUE;
669 #ifdef USE_ARES
670 /* If we use ares, we setup a new ares channel for the new handle */
671 if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel))
672 break;
673 #endif
675 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
676 outcurl->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
677 CURL_ICONV_CODESET_OF_NETWORK);
678 outcurl->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
679 CURL_ICONV_CODESET_OF_HOST);
680 outcurl->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
681 CURL_ICONV_CODESET_FOR_UTF8);
682 #endif
684 Curl_easy_initHandleData(outcurl);
686 outcurl->magic = CURLEASY_MAGIC_NUMBER;
688 fail = FALSE; /* we reach this point and thus we are OK */
690 } while(0);
692 if(fail) {
693 if(outcurl) {
694 if(outcurl->state.connc &&
695 (outcurl->state.connc->type == CONNCACHE_PRIVATE))
696 Curl_rm_connc(outcurl->state.connc);
697 if(outcurl->state.headerbuff)
698 free(outcurl->state.headerbuff);
699 if(outcurl->change.url)
700 free(outcurl->change.url);
701 if(outcurl->change.referer)
702 free(outcurl->change.referer);
703 Curl_freeset(outcurl);
704 free(outcurl); /* free the memory again */
705 outcurl = NULL;
709 return outcurl;
713 * curl_easy_reset() is an external interface that allows an app to re-
714 * initialize a session handle to the default values.
716 void curl_easy_reset(CURL *curl)
718 struct SessionHandle *data = (struct SessionHandle *)curl;
720 Curl_safefree(data->state.pathbuffer);
721 data->state.pathbuffer=NULL;
723 Curl_safefree(data->state.proto.generic);
724 data->state.proto.generic=NULL;
726 /* zero out UserDefined data: */
727 Curl_freeset(data);
728 memset(&data->set, 0, sizeof(struct UserDefined));
730 /* zero out Progress data: */
731 memset(&data->progress, 0, sizeof(struct Progress));
733 /* init Handle data */
734 Curl_easy_initHandleData(data);
736 /* The remainder of these calls have been taken from Curl_open() */
738 data->set.out = stdout; /* default output to stdout */
739 data->set.in = stdin; /* default input from stdin */
740 data->set.err = stderr; /* default stderr to stderr */
742 /* use fwrite as default function to store output */
743 data->set.fwrite_func = (curl_write_callback)fwrite;
745 /* use fread as default function to read input */
746 data->set.fread_func = (curl_read_callback)fread;
748 data->set.infilesize = -1; /* we don't know any size */
749 data->set.postfieldsize = -1; /* unknown size */
750 data->set.maxredirs = -1; /* allow any amount by default */
751 data->state.current_speed = -1; /* init to negative == impossible */
753 data->set.httpreq = HTTPREQ_GET; /* Default HTTP request */
754 data->set.ftp_use_epsv = TRUE; /* FTP defaults to EPSV operations */
755 data->set.ftp_use_eprt = TRUE; /* FTP defaults to EPRT operations */
757 data->set.dns_cache_timeout = 60; /* Timeout every 60 seconds by default */
759 /* make libcurl quiet by default: */
760 data->set.hide_progress = TRUE; /* CURLOPT_NOPROGRESS changes these */
761 data->progress.flags |= PGRS_HIDE;
763 /* Set the default size of the SSL session ID cache */
764 data->set.ssl.numsessions = 5;
766 data->set.proxyport = CURL_DEFAULT_PROXY_PORT; /* from url.h */
767 data->set.proxytype = CURLPROXY_HTTP; /* defaults to HTTP proxy */
768 data->set.httpauth = CURLAUTH_BASIC; /* defaults to basic */
769 data->set.proxyauth = CURLAUTH_BASIC; /* defaults to basic */
772 * libcurl 7.10 introduced SSL verification *by default*! This needs to be
773 * switched off unless wanted.
775 data->set.ssl.verifypeer = TRUE;
776 data->set.ssl.verifyhost = 2;
777 /* This is our prefered CA cert bundle/path since install time */
778 #if defined(CURL_CA_BUNDLE)
779 (void) curl_easy_setopt(curl, CURLOPT_CAINFO, (char *) CURL_CA_BUNDLE);
780 #elif defined(CURL_CA_PATH)
781 (void) curl_easy_setopt(curl, CURLOPT_CAPATH, (char *) CURL_CA_PATH);
782 #endif
784 data->set.ssh_auth_types = CURLSSH_AUTH_DEFAULT; /* defaults to any auth
785 type */
786 data->set.new_file_perms = 0644; /* Default permissions */
787 data->set.new_directory_perms = 0755; /* Default permissions */
791 * curl_easy_pause() allows an application to pause or unpause a specific
792 * transfer and direction. This function sets the full new state for the
793 * current connection this easy handle operates on.
795 * NOTE: if you have the receiving paused and you call this function to remove
796 * the pausing, you may get your write callback called at this point.
798 * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
800 CURLcode curl_easy_pause(CURL *curl, int action)
802 struct SessionHandle *data = (struct SessionHandle *)curl;
803 struct SingleRequest *k = &data->req;
804 CURLcode result = CURLE_OK;
806 /* first switch off both pause bits */
807 int newstate = k->keepon &~ (KEEP_READ_PAUSE| KEEP_WRITE_PAUSE);
809 /* set the new desired pause bits */
810 newstate |= ((action & CURLPAUSE_RECV)?KEEP_READ_PAUSE:0) |
811 ((action & CURLPAUSE_SEND)?KEEP_WRITE_PAUSE:0);
813 /* put it back in the keepon */
814 k->keepon = newstate;
816 if(!(newstate & KEEP_READ_PAUSE) && data->state.tempwrite) {
817 /* we have a buffer for writing that we now seem to be able to deliver since
818 the receive pausing is lifted! */
820 /* get the pointer, type and length in local copies since the function may
821 return PAUSE again and then we'll get a new copy allocted and stored in
822 the tempwrite variables */
823 char *tempwrite = data->state.tempwrite;
824 size_t tempsize = data->state.tempwritesize;
825 int temptype = data->state.tempwritetype;
826 size_t chunklen;
828 /* clear tempwrite here just to make sure it gets cleared if there's no
829 further use of it, and make sure we don't clear it after the function
830 invoke as it may have been set to a new value by then */
831 data->state.tempwrite = NULL;
833 /* since the write callback API is define to never exceed
834 CURL_MAX_WRITE_SIZE bytes in a single call, and since we may in fact
835 have more data than that in our buffer here, we must loop sending the
836 data in multiple calls until there's no data left or we get another
837 pause returned.
839 A tricky part is that the function we call will "buffer" the data
840 itself when it pauses on a particular buffer, so we may need to do some
841 extra trickery if we get a pause return here.
843 do {
844 chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize;
846 result = Curl_client_write(data->state.current_conn,
847 temptype, tempwrite, chunklen);
848 if(!result)
849 /* failures abort the loop at once */
850 break;
852 if(data->state.tempwrite && (tempsize - chunklen)) {
853 /* Ouch, the reading is again paused and the block we send is now
854 "cached". If this is the final chunk we can leave it like this, but
855 if we have more chunks that is cached after this, we need to free
856 the newly cached one and put back a version that is truly the entire
857 contents that is saved for later
859 char *newptr;
861 free(data->state.tempwrite); /* free the one just cached as it isn't
862 enough */
864 /* note that tempsize is still the size as before the callback was
865 used, and thus the whole piece of data to keep */
866 newptr = malloc(tempsize);
867 if(!newptr) {
868 result = CURLE_OUT_OF_MEMORY;
869 /* tempwrite will be freed further down */
870 break;
872 data->state.tempwrite = newptr; /* store new pointer */
873 memcpy(newptr, tempwrite, tempsize);
874 data->state.tempwritesize = tempsize; /* store new size */
875 /* tempwrite will be freed further down */
876 break; /* go back to pausing until further notice */
878 else {
879 tempsize -= chunklen; /* left after the call above */
880 tempwrite += chunklen; /* advance the pointer */
883 } while((result == CURLE_OK) && tempsize);
885 free(tempwrite); /* this is unconditionally no longer used */
888 return result;
891 #ifdef CURL_DOES_CONVERSIONS
893 * Curl_convert_to_network() is an internal function
894 * for performing ASCII conversions on non-ASCII platforms.
896 CURLcode Curl_convert_to_network(struct SessionHandle *data,
897 char *buffer, size_t length)
899 CURLcode rc;
901 if(data->set.convtonetwork) {
902 /* use translation callback */
903 rc = data->set.convtonetwork(buffer, length);
904 if(rc != CURLE_OK) {
905 failf(data,
906 "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %i: %s",
907 rc, curl_easy_strerror(rc));
909 return(rc);
910 } else {
911 #ifdef HAVE_ICONV
912 /* do the translation ourselves */
913 char *input_ptr, *output_ptr;
914 size_t in_bytes, out_bytes, rc;
915 int error;
917 /* open an iconv conversion descriptor if necessary */
918 if(data->outbound_cd == (iconv_t)-1) {
919 data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
920 CURL_ICONV_CODESET_OF_HOST);
921 if(data->outbound_cd == (iconv_t)-1) {
922 error = ERRNO;
923 failf(data,
924 "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
925 CURL_ICONV_CODESET_OF_NETWORK,
926 CURL_ICONV_CODESET_OF_HOST,
927 error, strerror(error));
928 return CURLE_CONV_FAILED;
931 /* call iconv */
932 input_ptr = output_ptr = buffer;
933 in_bytes = out_bytes = length;
934 rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
935 &output_ptr, &out_bytes);
936 if((rc == ICONV_ERROR) || (in_bytes != 0)) {
937 error = ERRNO;
938 failf(data,
939 "The Curl_convert_to_network iconv call failed with errno %i: %s",
940 error, strerror(error));
941 return CURLE_CONV_FAILED;
943 #else
944 failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
945 return CURLE_CONV_REQD;
946 #endif /* HAVE_ICONV */
949 return CURLE_OK;
953 * Curl_convert_from_network() is an internal function
954 * for performing ASCII conversions on non-ASCII platforms.
956 CURLcode Curl_convert_from_network(struct SessionHandle *data,
957 char *buffer, size_t length)
959 CURLcode rc;
961 if(data->set.convfromnetwork) {
962 /* use translation callback */
963 rc = data->set.convfromnetwork(buffer, length);
964 if(rc != CURLE_OK) {
965 failf(data,
966 "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %i: %s",
967 rc, curl_easy_strerror(rc));
969 return(rc);
971 else {
972 #ifdef HAVE_ICONV
973 /* do the translation ourselves */
974 char *input_ptr, *output_ptr;
975 size_t in_bytes, out_bytes, rc;
976 int error;
978 /* open an iconv conversion descriptor if necessary */
979 if(data->inbound_cd == (iconv_t)-1) {
980 data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
981 CURL_ICONV_CODESET_OF_NETWORK);
982 if(data->inbound_cd == (iconv_t)-1) {
983 error = ERRNO;
984 failf(data,
985 "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
986 CURL_ICONV_CODESET_OF_HOST,
987 CURL_ICONV_CODESET_OF_NETWORK,
988 error, strerror(error));
989 return CURLE_CONV_FAILED;
992 /* call iconv */
993 input_ptr = output_ptr = buffer;
994 in_bytes = out_bytes = length;
995 rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
996 &output_ptr, &out_bytes);
997 if((rc == ICONV_ERROR) || (in_bytes != 0)) {
998 error = ERRNO;
999 failf(data,
1000 "The Curl_convert_from_network iconv call failed with errno %i: %s",
1001 error, strerror(error));
1002 return CURLE_CONV_FAILED;
1004 #else
1005 failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
1006 return CURLE_CONV_REQD;
1007 #endif /* HAVE_ICONV */
1010 return CURLE_OK;
1014 * Curl_convert_from_utf8() is an internal function
1015 * for performing UTF-8 conversions on non-ASCII platforms.
1017 CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
1018 char *buffer, size_t length)
1020 CURLcode rc;
1022 if(data->set.convfromutf8) {
1023 /* use translation callback */
1024 rc = data->set.convfromutf8(buffer, length);
1025 if(rc != CURLE_OK) {
1026 failf(data,
1027 "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %i: %s",
1028 rc, curl_easy_strerror(rc));
1030 return(rc);
1031 } else {
1032 #ifdef HAVE_ICONV
1033 /* do the translation ourselves */
1034 const char *input_ptr;
1035 char *output_ptr;
1036 size_t in_bytes, out_bytes, rc;
1037 int error;
1039 /* open an iconv conversion descriptor if necessary */
1040 if(data->utf8_cd == (iconv_t)-1) {
1041 data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
1042 CURL_ICONV_CODESET_FOR_UTF8);
1043 if(data->utf8_cd == (iconv_t)-1) {
1044 error = ERRNO;
1045 failf(data,
1046 "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
1047 CURL_ICONV_CODESET_OF_HOST,
1048 CURL_ICONV_CODESET_FOR_UTF8,
1049 error, strerror(error));
1050 return CURLE_CONV_FAILED;
1053 /* call iconv */
1054 input_ptr = output_ptr = buffer;
1055 in_bytes = out_bytes = length;
1056 rc = iconv(data->utf8_cd, &input_ptr, &in_bytes,
1057 &output_ptr, &out_bytes);
1058 if((rc == ICONV_ERROR) || (in_bytes != 0)) {
1059 error = ERRNO;
1060 failf(data,
1061 "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
1062 error, strerror(error));
1063 return CURLE_CONV_FAILED;
1065 if(output_ptr < input_ptr) {
1066 /* null terminate the now shorter output string */
1067 *output_ptr = 0x00;
1069 #else
1070 failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
1071 return CURLE_CONV_REQD;
1072 #endif /* HAVE_ICONV */
1075 return CURLE_OK;
1078 #endif /* CURL_DOES_CONVERSIONS */
1080 static CURLcode easy_connection(struct SessionHandle *data,
1081 curl_socket_t *sfd,
1082 struct connectdata **connp)
1084 CURLcode ret;
1085 long sockfd;
1087 if(data == NULL)
1088 return CURLE_BAD_FUNCTION_ARGUMENT;
1090 /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
1091 if(!data->set.connect_only) {
1092 failf(data, "CONNECT_ONLY is required!");
1093 return CURLE_UNSUPPORTED_PROTOCOL;
1096 ret = Curl_getconnectinfo(data, &sockfd, connp);
1097 if(ret != CURLE_OK)
1098 return ret;
1100 if(sockfd == -1) {
1101 failf(data, "Failed to get recent socket");
1102 return CURLE_UNSUPPORTED_PROTOCOL;
1105 *sfd = (curl_socket_t)sockfd; /* we know that this is actually a socket
1106 descriptor so the typecast is fine here */
1108 return CURLE_OK;
1112 * Receives data from the connected socket. Use after successful
1113 * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1114 * Returns CURLE_OK on success, error code on error.
1116 CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
1118 curl_socket_t sfd;
1119 CURLcode ret;
1120 int ret1;
1121 ssize_t n1;
1122 struct connectdata *c;
1123 struct SessionHandle *data = (struct SessionHandle *)curl;
1125 ret = easy_connection(data, &sfd, &c);
1126 if(ret)
1127 return ret;
1129 *n = 0;
1130 ret1 = Curl_read(c, sfd, buffer, buflen, &n1);
1132 if(ret1 == -1)
1133 return CURLE_AGAIN;
1135 if(n1 == -1)
1136 return CURLE_RECV_ERROR;
1138 *n = (size_t)n1;
1140 return CURLE_OK;
1144 * Sends data over the connected socket. Use after successful
1145 * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1147 CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen,
1148 size_t *n)
1150 curl_socket_t sfd;
1151 CURLcode ret;
1152 ssize_t n1;
1153 struct connectdata *c = NULL;
1154 struct SessionHandle *data = (struct SessionHandle *)curl;
1156 ret = easy_connection(data, &sfd, &c);
1157 if(ret)
1158 return ret;
1160 *n = 0;
1161 ret = Curl_write(c, sfd, buffer, buflen, &n1);
1163 if(n1 == -1)
1164 return CURLE_SEND_ERROR;
1166 /* detect EAGAIN */
1167 if((CURLE_OK == ret) && (0 == n1))
1168 return CURLE_AGAIN;
1170 *n = (size_t)n1;
1172 return ret;