Replaced use of standard C library rand()/srand() by our own pseudo-random number...
[platform/upstream/curl.git] / lib / easy.c
1 /***************************************************************************
2  *                                  _   _ ____  _
3  *  Project                     ___| | | |  _ \| |
4  *                             / __| | | | |_) | |
5  *                            | (__| |_| |  _ <| |___
6  *                             \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
9  *
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.
13  *
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.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  * $Id$
22  ***************************************************************************/
23
24 #include "setup.h"
25
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>
33
34 #include "strequal.h"
35
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
65 #ifdef HAVE_SYS_PARAM_H
66 #include <sys/param.h>
67 #endif
68
69 #endif  /* WIN32 ... */
70
71 #include "urldata.h"
72 #include <curl/curl.h>
73 #include "transfer.h"
74 #include "sslgen.h"
75 #include "url.h"
76 #include "getinfo.h"
77 #include "hostip.h"
78 #include "share.h"
79 #include "strdup.h"
80 #include "curl_memory.h"
81 #include "progress.h"
82 #include "easyif.h"
83 #include "select.h"
84 #include "sendf.h" /* for failf function prototype */
85 #include "http_ntlm.h"
86 #include "connect.h" /* for Curl_getconnectinfo */
87 #include "slist.h"
88 #include "formdata.h"   /* For Curl_srand(). */
89
90 #define _MPRINTF_REPLACE /* use our functions only */
91 #include <curl/mprintf.h>
92
93 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
94 #include <iconv.h>
95 /* set default codesets for iconv */
96 #ifndef CURL_ICONV_CODESET_OF_NETWORK
97 #define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
98 #endif
99 #ifndef CURL_ICONV_CODESET_FOR_UTF8
100 #define CURL_ICONV_CODESET_FOR_UTF8   "UTF-8"
101 #endif
102 #define ICONV_ERROR  (size_t)-1
103 #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
104
105 /* The last #include file should be: */
106 #include "memdebug.h"
107
108 /* win32_cleanup() is for win32 socket cleanup functionality, the opposite
109    of win32_init() */
110 static void win32_cleanup(void)
111 {
112 #ifdef USE_WINSOCK
113   WSACleanup();
114 #endif
115 #ifdef USE_WINDOWS_SSPI
116   Curl_sspi_global_cleanup();
117 #endif
118 }
119
120 /* win32_init() performs win32 socket initialization to properly setup the
121    stack to allow networking */
122 static CURLcode win32_init(void)
123 {
124 #ifdef USE_WINSOCK
125   WORD wVersionRequested;
126   WSADATA wsaData;
127   int res;
128
129 #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
130   Error IPV6_requires_winsock2
131 #endif
132
133   wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
134
135   res = WSAStartup(wVersionRequested, &wsaData);
136
137   if(res != 0)
138     /* Tell the user that we couldn't find a useable */
139     /* winsock.dll.     */
140     return CURLE_FAILED_INIT;
141
142   /* Confirm that the Windows Sockets DLL supports what we need.*/
143   /* Note that if the DLL supports versions greater */
144   /* than wVersionRequested, it will still return */
145   /* wVersionRequested in wVersion. wHighVersion contains the */
146   /* highest supported version. */
147
148   if( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
149        HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
150     /* Tell the user that we couldn't find a useable */
151
152     /* winsock.dll. */
153     WSACleanup();
154     return CURLE_FAILED_INIT;
155   }
156   /* The Windows Sockets DLL is acceptable. Proceed. */
157 #endif
158
159 #ifdef USE_WINDOWS_SSPI
160   {
161     CURLcode err = Curl_sspi_global_init();
162     if (err != CURLE_OK)
163       return err;
164   }
165 #endif
166
167   return CURLE_OK;
168 }
169
170 #ifdef USE_LIBIDN
171 /*
172  * Initialise use of IDNA library.
173  * It falls back to ASCII if $CHARSET isn't defined. This doesn't work for
174  * idna_to_ascii_lz().
175  */
176 static void idna_init (void)
177 {
178 #ifdef WIN32
179   char buf[60];
180   UINT cp = GetACP();
181
182   if(!getenv("CHARSET") && cp > 0) {
183     snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
184     putenv(buf);
185   }
186 #else
187   /* to do? */
188 #endif
189 }
190 #endif  /* USE_LIBIDN */
191
192 /* true globals -- for curl_global_init() and curl_global_cleanup() */
193 static unsigned int  initialized;
194 static long          init_flags;
195
196 /*
197  * strdup (and other memory functions) is redefined in complicated
198  * ways, but at this point it must be defined as the system-supplied strdup
199  * so the callback pointer is initialized correctly.
200  */
201 #if defined(_WIN32_WCE)
202 #define system_strdup _strdup
203 #elif !defined(HAVE_STRDUP)
204 #define system_strdup curlx_strdup
205 #else
206 #define system_strdup strdup
207 #endif
208
209 #if defined(_MSC_VER) && defined(_DLL)
210 #  pragma warning(disable:4232) /* MSVC extension, dllimport identity */
211 #endif
212
213 #ifndef __SYMBIAN32__
214 /*
215  * If a memory-using function (like curl_getenv) is used before
216  * curl_global_init() is called, we need to have these pointers set already.
217  */
218 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
219 curl_free_callback Curl_cfree = (curl_free_callback)free;
220 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
221 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
222 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
223 #else
224 /*
225  * Symbian OS doesn't support initialization to code in writeable static data.
226  * Initialization will occur in the curl_global_init() call.
227  */
228 curl_malloc_callback Curl_cmalloc;
229 curl_free_callback Curl_cfree;
230 curl_realloc_callback Curl_crealloc;
231 curl_strdup_callback Curl_cstrdup;
232 curl_calloc_callback Curl_ccalloc;
233 #endif
234
235 #if defined(_MSC_VER) && defined(_DLL)
236 #  pragma warning(default:4232) /* MSVC extension, dllimport identity */
237 #endif
238
239 /**
240  * curl_global_init() globally initializes cURL given a bitwise set of the
241  * different features of what to initialize.
242  */
243 CURLcode curl_global_init(long flags)
244 {
245   if(initialized++)
246     return CURLE_OK;
247
248   /* Setup the default memory functions here (again) */
249   Curl_cmalloc = (curl_malloc_callback)malloc;
250   Curl_cfree = (curl_free_callback)free;
251   Curl_crealloc = (curl_realloc_callback)realloc;
252   Curl_cstrdup = (curl_strdup_callback)system_strdup;
253   Curl_ccalloc = (curl_calloc_callback)calloc;
254
255   if(flags & CURL_GLOBAL_SSL)
256     if(!Curl_ssl_init()) {
257       DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
258       return CURLE_FAILED_INIT;
259     }
260
261   if(flags & CURL_GLOBAL_WIN32)
262     if(win32_init() != CURLE_OK) {
263       DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
264       return CURLE_FAILED_INIT;
265     }
266
267 #ifdef __AMIGA__
268   if(!amiga_init()) {
269     DEBUGF(fprintf(stderr, "Error: amiga_init failed\n"));
270     return CURLE_FAILED_INIT;
271   }
272 #endif
273
274 #ifdef NETWARE
275   if(netware_init()) {
276     DEBUGF(fprintf(stderr, "Warning: LONG namespace not available\n"));
277   }
278 #endif
279
280 #ifdef USE_LIBIDN
281   idna_init();
282 #endif
283
284 #ifdef CARES_HAVE_ARES_LIBRARY_INIT
285   if(ares_library_init(ARES_LIB_INIT_ALL)) {
286     DEBUGF(fprintf(stderr, "Error: ares_library_init failed\n"));
287     return CURLE_FAILED_INIT;
288   }
289 #endif
290
291   init_flags  = flags;
292
293   /* Preset pseudo-random number sequence. */
294
295   Curl_srand();
296
297   return CURLE_OK;
298 }
299
300 /*
301  * curl_global_init_mem() globally initializes cURL and also registers the
302  * user provided callback routines.
303  */
304 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
305                               curl_free_callback f, curl_realloc_callback r,
306                               curl_strdup_callback s, curl_calloc_callback c)
307 {
308   CURLcode code = CURLE_OK;
309
310   /* Invalid input, return immediately */
311   if(!m || !f || !r || !s || !c)
312     return CURLE_FAILED_INIT;
313
314   /* Already initialized, don't do it again */
315   if( initialized )
316     return CURLE_OK;
317
318   /* Call the actual init function first */
319   code = curl_global_init(flags);
320   if(code == CURLE_OK) {
321     Curl_cmalloc = m;
322     Curl_cfree = f;
323     Curl_cstrdup = s;
324     Curl_crealloc = r;
325     Curl_ccalloc = c;
326   }
327
328   return code;
329 }
330
331 /**
332  * curl_global_cleanup() globally cleanups cURL, uses the value of
333  * "init_flags" to determine what needs to be cleaned up and what doesn't.
334  */
335 void curl_global_cleanup(void)
336 {
337   if(!initialized)
338     return;
339
340   if(--initialized)
341     return;
342
343   Curl_global_host_cache_dtor();
344
345   if(init_flags & CURL_GLOBAL_SSL)
346     Curl_ssl_cleanup();
347
348 #ifdef CARES_HAVE_ARES_LIBRARY_CLEANUP
349   ares_library_cleanup();
350 #endif
351
352   if(init_flags & CURL_GLOBAL_WIN32)
353     win32_cleanup();
354
355 #ifdef __AMIGA__
356   amiga_cleanup();
357 #endif
358
359   init_flags  = 0;
360 }
361
362 /*
363  * curl_easy_init() is the external interface to alloc, setup and init an
364  * easy handle that is returned. If anything goes wrong, NULL is returned.
365  */
366 CURL *curl_easy_init(void)
367 {
368   CURLcode res;
369   struct SessionHandle *data;
370
371   /* Make sure we inited the global SSL stuff */
372   if(!initialized) {
373     res = curl_global_init(CURL_GLOBAL_DEFAULT);
374     if(res) {
375       /* something in the global init failed, return nothing */
376       DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
377       return NULL;
378     }
379   }
380
381   /* We use curl_open() with undefined URL so far */
382   res = Curl_open(&data);
383   if(res != CURLE_OK) {
384     DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
385     return NULL;
386   }
387
388   return data;
389 }
390
391 /*
392  * curl_easy_setopt() is the external interface for setting options on an
393  * easy handle.
394  */
395
396 #undef curl_easy_setopt
397 CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
398 {
399   va_list arg;
400   struct SessionHandle *data = curl;
401   CURLcode ret;
402
403   if(!curl)
404     return CURLE_BAD_FUNCTION_ARGUMENT;
405
406   va_start(arg, tag);
407
408   ret = Curl_setopt(data, tag, arg);
409
410   va_end(arg);
411   return ret;
412 }
413
414 #ifdef CURL_MULTIEASY
415 /***************************************************************************
416  * This function is still only for testing purposes. It makes a great way
417  * to run the full test suite on the multi interface instead of the easy one.
418  ***************************************************************************
419  *
420  * The *new* curl_easy_perform() is the external interface that performs a
421  * transfer previously setup.
422  *
423  * Wrapper-function that: creates a multi handle, adds the easy handle to it,
424  * runs curl_multi_perform() until the transfer is done, then detaches the
425  * easy handle, destroys the multi handle and returns the easy handle's return
426  * code. This will make everything internally use and assume multi interface.
427  */
428 CURLcode curl_easy_perform(CURL *easy)
429 {
430   CURLM *multi;
431   CURLMcode mcode;
432   CURLcode code = CURLE_OK;
433   int still_running;
434   struct timeval timeout;
435   int rc;
436   CURLMsg *msg;
437   fd_set fdread;
438   fd_set fdwrite;
439   fd_set fdexcep;
440   int maxfd;
441
442   if(!easy)
443     return CURLE_BAD_FUNCTION_ARGUMENT;
444
445   multi = curl_multi_init();
446   if(!multi)
447     return CURLE_OUT_OF_MEMORY;
448
449   mcode = curl_multi_add_handle(multi, easy);
450   if(mcode) {
451     curl_multi_cleanup(multi);
452     if(mcode == CURLM_OUT_OF_MEMORY)
453       return CURLE_OUT_OF_MEMORY;
454     else
455       return CURLE_FAILED_INIT;
456   }
457
458   /* we start some action by calling perform right away */
459
460   do {
461     while(CURLM_CALL_MULTI_PERFORM ==
462           curl_multi_perform(multi, &still_running));
463
464     if(!still_running)
465       break;
466
467     FD_ZERO(&fdread);
468     FD_ZERO(&fdwrite);
469     FD_ZERO(&fdexcep);
470
471     /* timeout once per second */
472     timeout.tv_sec = 1;
473     timeout.tv_usec = 0;
474
475     /* Old deprecated style: get file descriptors from the transfers */
476     curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
477     rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
478
479     /* The way is to extract the sockets and wait for them without using
480        select. This whole alternative version should probably rather use the
481        curl_multi_socket() approach. */
482
483     if(rc == -1)
484       /* select error */
485       break;
486
487     /* timeout or data to send/receive => loop! */
488   } while(still_running);
489
490   msg = curl_multi_info_read(multi, &rc);
491   if(msg)
492     code = msg->data.result;
493
494   mcode = curl_multi_remove_handle(multi, easy);
495   /* what to do if it fails? */
496
497   mcode = curl_multi_cleanup(multi);
498   /* what to do if it fails? */
499
500   return code;
501 }
502 #else
503 /*
504  * curl_easy_perform() is the external interface that performs a transfer
505  * previously setup.
506  */
507 CURLcode curl_easy_perform(CURL *curl)
508 {
509   struct SessionHandle *data = (struct SessionHandle *)curl;
510
511   if(!data)
512     return CURLE_BAD_FUNCTION_ARGUMENT;
513
514   if( ! (data->share && data->share->hostcache) ) {
515     /* this handle is not using a shared dns cache */
516
517     if(data->set.global_dns_cache &&
518        (data->dns.hostcachetype != HCACHE_GLOBAL)) {
519       /* global dns cache was requested but still isn't */
520       struct curl_hash *ptr;
521
522       if(data->dns.hostcachetype == HCACHE_PRIVATE) {
523         /* if the current cache is private, kill it first */
524         Curl_hash_destroy(data->dns.hostcache);
525         data->dns.hostcachetype = HCACHE_NONE;
526         data->dns.hostcache = NULL;
527       }
528
529       ptr = Curl_global_host_cache_init();
530       if(ptr) {
531         /* only do this if the global cache init works */
532         data->dns.hostcache = ptr;
533         data->dns.hostcachetype = HCACHE_GLOBAL;
534       }
535     }
536
537     if(!data->dns.hostcache) {
538       data->dns.hostcachetype = HCACHE_PRIVATE;
539       data->dns.hostcache = Curl_mk_dnscache();
540
541       if(!data->dns.hostcache)
542         /* While we possibly could survive and do good without a host cache,
543            the fact that creating it failed indicates that things are truly
544            screwed up and we should bail out! */
545         return CURLE_OUT_OF_MEMORY;
546     }
547
548   }
549
550   if(!data->state.connc) {
551     /* oops, no connection cache, make one up */
552     data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1L);
553     if(!data->state.connc)
554       return CURLE_OUT_OF_MEMORY;
555   }
556
557   return Curl_perform(data);
558 }
559 #endif
560
561 /*
562  * curl_easy_cleanup() is the external interface to cleaning/freeing the given
563  * easy handle.
564  */
565 void curl_easy_cleanup(CURL *curl)
566 {
567   struct SessionHandle *data = (struct SessionHandle *)curl;
568
569   if(!data)
570     return;
571
572   Curl_close(data);
573 }
574
575 /*
576  * Store a pointed to the multi handle within the easy handle's data struct.
577  */
578 void Curl_easy_addmulti(struct SessionHandle *data,
579                         void *multi)
580 {
581   data->multi = multi;
582   if(multi == NULL)
583     /* the association is cleared, mark the easy handle as not used by an
584        interface */
585     data->state.used_interface = Curl_if_none;
586 }
587
588 void Curl_easy_initHandleData(struct SessionHandle *data)
589 {
590     memset(&data->req, 0, sizeof(struct SingleRequest));
591
592     data->req.maxdownload = -1;
593 }
594
595 /*
596  * curl_easy_getinfo() is an external interface that allows an app to retrieve
597  * information from a performed transfer and similar.
598  */
599 #undef curl_easy_getinfo
600 CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
601 {
602   va_list arg;
603   void *paramp;
604   struct SessionHandle *data = (struct SessionHandle *)curl;
605
606   va_start(arg, info);
607   paramp = va_arg(arg, void *);
608
609   return Curl_getinfo(data, info, paramp);
610 }
611
612 /*
613  * curl_easy_duphandle() is an external interface to allow duplication of a
614  * given input easy handle. The returned handle will be a new working handle
615  * with all options set exactly as the input source handle.
616  */
617 CURL *curl_easy_duphandle(CURL *incurl)
618 {
619   bool fail = TRUE;
620   struct SessionHandle *data=(struct SessionHandle *)incurl;
621
622   struct SessionHandle *outcurl = calloc(sizeof(struct SessionHandle), 1);
623
624   if(NULL == outcurl)
625     return NULL; /* failure */
626
627   do {
628
629     /*
630      * We setup a few buffers we need. We should probably make them
631      * get setup on-demand in the code, as that would probably decrease
632      * the likeliness of us forgetting to init a buffer here in the future.
633      */
634     outcurl->state.headerbuff = malloc(HEADERSIZE);
635     if(!outcurl->state.headerbuff) {
636       break;
637     }
638     outcurl->state.headersize=HEADERSIZE;
639
640     /* copy all userdefined values */
641     if(Curl_dupset(outcurl, data) != CURLE_OK)
642       break;
643
644     /* the connection cache is setup on demand */
645     outcurl->state.connc = NULL;
646
647     outcurl->state.lastconnect = -1;
648
649     outcurl->progress.flags    = data->progress.flags;
650     outcurl->progress.callback = data->progress.callback;
651
652 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
653     if(data->cookies) {
654       /* If cookies are enabled in the parent handle, we enable them
655          in the clone as well! */
656       outcurl->cookies = Curl_cookie_init(data,
657                                           data->cookies->filename,
658                                           outcurl->cookies,
659                                           data->set.cookiesession);
660       if(!outcurl->cookies) {
661         break;
662       }
663     }
664 #endif   /* CURL_DISABLE_HTTP */
665
666     /* duplicate all values in 'change' */
667
668 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
669     if(data->change.cookielist) {
670       outcurl->change.cookielist =
671         Curl_slist_duplicate(data->change.cookielist);
672
673       if (!outcurl->change.cookielist)
674         break;
675     }
676 #endif   /* CURL_DISABLE_HTTP */
677
678     if(data->change.url) {
679       outcurl->change.url = strdup(data->change.url);
680       if(!outcurl->change.url)
681         break;
682       outcurl->change.url_alloc = TRUE;
683     }
684
685     if(data->change.referer) {
686       outcurl->change.referer = strdup(data->change.referer);
687       if(!outcurl->change.referer)
688         break;
689       outcurl->change.referer_alloc = TRUE;
690     }
691
692 #ifdef USE_ARES
693     /* If we use ares, we setup a new ares channel for the new handle */
694     if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel))
695       break;
696 #endif
697
698 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
699     outcurl->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
700                                      CURL_ICONV_CODESET_OF_NETWORK);
701     outcurl->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
702                                       CURL_ICONV_CODESET_OF_HOST);
703     outcurl->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
704                                   CURL_ICONV_CODESET_FOR_UTF8);
705 #endif
706
707     Curl_easy_initHandleData(outcurl);
708
709     outcurl->magic = CURLEASY_MAGIC_NUMBER;
710
711     fail = FALSE; /* we reach this point and thus we are OK */
712
713   } while(0);
714
715   if(fail) {
716     if(outcurl) {
717       if(outcurl->state.connc &&
718          (outcurl->state.connc->type == CONNCACHE_PRIVATE))
719         Curl_rm_connc(outcurl->state.connc);
720       if(outcurl->state.headerbuff)
721         free(outcurl->state.headerbuff);
722 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
723       if(outcurl->change.cookielist)
724         curl_slist_free_all(outcurl->change.cookielist);
725 #endif
726       if(outcurl->change.url)
727         free(outcurl->change.url);
728       if(outcurl->change.referer)
729         free(outcurl->change.referer);
730       Curl_freeset(outcurl);
731       free(outcurl); /* free the memory again */
732       outcurl = NULL;
733     }
734   }
735
736   return outcurl;
737 }
738
739 /*
740  * curl_easy_reset() is an external interface that allows an app to re-
741  * initialize a session handle to the default values.
742  */
743 void curl_easy_reset(CURL *curl)
744 {
745   struct SessionHandle *data = (struct SessionHandle *)curl;
746
747   Curl_safefree(data->state.pathbuffer);
748   data->state.pathbuffer=NULL;
749
750   Curl_safefree(data->state.proto.generic);
751   data->state.proto.generic=NULL;
752
753   /* zero out UserDefined data: */
754   Curl_freeset(data);
755   memset(&data->set, 0, sizeof(struct UserDefined));
756   (void)Curl_init_userdefined(&data->set);
757
758   /* zero out Progress data: */
759   memset(&data->progress, 0, sizeof(struct Progress));
760
761   /* init Handle data */
762   Curl_easy_initHandleData(data);
763
764   data->progress.flags |= PGRS_HIDE;
765   data->state.current_speed = -1; /* init to negative == impossible */
766 }
767
768 /*
769  * curl_easy_pause() allows an application to pause or unpause a specific
770  * transfer and direction. This function sets the full new state for the
771  * current connection this easy handle operates on.
772  *
773  * NOTE: if you have the receiving paused and you call this function to remove
774  * the pausing, you may get your write callback called at this point.
775  *
776  * Action is a bitmask consisting of CURLPAUSE_* bits in curl/curl.h
777  */
778 CURLcode curl_easy_pause(CURL *curl, int action)
779 {
780   struct SessionHandle *data = (struct SessionHandle *)curl;
781   struct SingleRequest *k = &data->req;
782   CURLcode result = CURLE_OK;
783
784   /* first switch off both pause bits */
785   int newstate = k->keepon &~ (KEEP_RECV_PAUSE| KEEP_SEND_PAUSE);
786
787   /* set the new desired pause bits */
788   newstate |= ((action & CURLPAUSE_RECV)?KEEP_RECV_PAUSE:0) |
789     ((action & CURLPAUSE_SEND)?KEEP_SEND_PAUSE:0);
790
791   /* put it back in the keepon */
792   k->keepon = newstate;
793
794   if(!(newstate & KEEP_RECV_PAUSE) && data->state.tempwrite) {
795     /* we have a buffer for sending that we now seem to be able to deliver since
796        the receive pausing is lifted! */
797
798     /* get the pointer, type and length in local copies since the function may
799        return PAUSE again and then we'll get a new copy allocted and stored in
800        the tempwrite variables */
801     char *tempwrite = data->state.tempwrite;
802     char *freewrite = tempwrite; /* store this pointer to free it later */
803     size_t tempsize = data->state.tempwritesize;
804     int temptype = data->state.tempwritetype;
805     size_t chunklen;
806
807     /* clear tempwrite here just to make sure it gets cleared if there's no
808        further use of it, and make sure we don't clear it after the function
809        invoke as it may have been set to a new value by then */
810     data->state.tempwrite = NULL;
811
812     /* since the write callback API is define to never exceed
813        CURL_MAX_WRITE_SIZE bytes in a single call, and since we may in fact
814        have more data than that in our buffer here, we must loop sending the
815        data in multiple calls until there's no data left or we get another
816        pause returned.
817
818        A tricky part is that the function we call will "buffer" the data
819        itself when it pauses on a particular buffer, so we may need to do some
820        extra trickery if we get a pause return here.
821     */
822     do {
823       chunklen = (tempsize > CURL_MAX_WRITE_SIZE)?CURL_MAX_WRITE_SIZE:tempsize;
824
825       result = Curl_client_write(data->state.current_conn,
826                                  temptype, tempwrite, chunklen);
827       if(result)
828         /* failures abort the loop at once */
829         break;
830
831       if(data->state.tempwrite && (tempsize - chunklen)) {
832         /* Ouch, the reading is again paused and the block we send is now
833            "cached". If this is the final chunk we can leave it like this, but
834            if we have more chunks that are cached after this, we need to free
835            the newly cached one and put back a version that is truly the entire
836            contents that is saved for later
837         */
838         char *newptr;
839
840         /* note that tempsize is still the size as before the callback was
841            used, and thus the whole piece of data to keep */
842         newptr = realloc(data->state.tempwrite, tempsize);
843
844         if(!newptr) {
845           free(data->state.tempwrite); /* free old area */
846           data->state.tempwrite = NULL;
847           result = CURLE_OUT_OF_MEMORY;
848           /* tempwrite will be freed further down */
849           break;
850         }
851         data->state.tempwrite = newptr; /* store new pointer */
852         memcpy(newptr, tempwrite, tempsize);
853         data->state.tempwritesize = tempsize; /* store new size */
854         /* tempwrite will be freed further down */
855         break; /* go back to pausing until further notice */
856       }
857       else {
858         tempsize -= chunklen;  /* left after the call above */
859         tempwrite += chunklen; /* advance the pointer */
860       }
861
862     } while((result == CURLE_OK) && tempsize);
863
864     free(freewrite); /* this is unconditionally no longer used */
865   }
866
867   return result;
868 }
869
870 #ifdef CURL_DOES_CONVERSIONS
871 /*
872  * Curl_convert_to_network() is an internal function
873  * for performing ASCII conversions on non-ASCII platforms.
874  */
875 CURLcode Curl_convert_to_network(struct SessionHandle *data,
876                                  char *buffer, size_t length)
877 {
878   CURLcode rc;
879
880   if(data->set.convtonetwork) {
881     /* use translation callback */
882     rc = data->set.convtonetwork(buffer, length);
883     if(rc != CURLE_OK) {
884       failf(data,
885             "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %i: %s",
886             rc, curl_easy_strerror(rc));
887     }
888     return(rc);
889   } else {
890 #ifdef HAVE_ICONV
891     /* do the translation ourselves */
892     char *input_ptr, *output_ptr;
893     size_t in_bytes, out_bytes, rc;
894     int error;
895
896     /* open an iconv conversion descriptor if necessary */
897     if(data->outbound_cd == (iconv_t)-1) {
898       data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
899                                      CURL_ICONV_CODESET_OF_HOST);
900       if(data->outbound_cd == (iconv_t)-1) {
901         error = ERRNO;
902         failf(data,
903               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
904                CURL_ICONV_CODESET_OF_NETWORK,
905                CURL_ICONV_CODESET_OF_HOST,
906                error, strerror(error));
907         return CURLE_CONV_FAILED;
908       }
909     }
910     /* call iconv */
911     input_ptr = output_ptr = buffer;
912     in_bytes = out_bytes = length;
913     rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
914                &output_ptr, &out_bytes);
915     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
916       error = ERRNO;
917       failf(data,
918         "The Curl_convert_to_network iconv call failed with errno %i: %s",
919              error, strerror(error));
920       return CURLE_CONV_FAILED;
921     }
922 #else
923     failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
924     return CURLE_CONV_REQD;
925 #endif /* HAVE_ICONV */
926   }
927
928   return CURLE_OK;
929 }
930
931 /*
932  * Curl_convert_from_network() is an internal function
933  * for performing ASCII conversions on non-ASCII platforms.
934  */
935 CURLcode Curl_convert_from_network(struct SessionHandle *data,
936                                       char *buffer, size_t length)
937 {
938   CURLcode rc;
939
940   if(data->set.convfromnetwork) {
941     /* use translation callback */
942     rc = data->set.convfromnetwork(buffer, length);
943     if(rc != CURLE_OK) {
944       failf(data,
945             "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %i: %s",
946             rc, curl_easy_strerror(rc));
947     }
948     return(rc);
949   }
950   else {
951 #ifdef HAVE_ICONV
952     /* do the translation ourselves */
953     char *input_ptr, *output_ptr;
954     size_t in_bytes, out_bytes, rc;
955     int error;
956
957     /* open an iconv conversion descriptor if necessary */
958     if(data->inbound_cd == (iconv_t)-1) {
959       data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
960                                     CURL_ICONV_CODESET_OF_NETWORK);
961       if(data->inbound_cd == (iconv_t)-1) {
962         error = ERRNO;
963         failf(data,
964               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
965               CURL_ICONV_CODESET_OF_HOST,
966               CURL_ICONV_CODESET_OF_NETWORK,
967               error, strerror(error));
968         return CURLE_CONV_FAILED;
969       }
970     }
971     /* call iconv */
972     input_ptr = output_ptr = buffer;
973     in_bytes = out_bytes = length;
974     rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
975                &output_ptr, &out_bytes);
976     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
977       error = ERRNO;
978       failf(data,
979             "The Curl_convert_from_network iconv call failed with errno %i: %s",
980             error, strerror(error));
981       return CURLE_CONV_FAILED;
982     }
983 #else
984     failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
985     return CURLE_CONV_REQD;
986 #endif /* HAVE_ICONV */
987   }
988
989   return CURLE_OK;
990 }
991
992 /*
993  * Curl_convert_from_utf8() is an internal function
994  * for performing UTF-8 conversions on non-ASCII platforms.
995  */
996 CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
997                                      char *buffer, size_t length)
998 {
999   CURLcode rc;
1000
1001   if(data->set.convfromutf8) {
1002     /* use translation callback */
1003     rc = data->set.convfromutf8(buffer, length);
1004     if(rc != CURLE_OK) {
1005       failf(data,
1006             "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %i: %s",
1007             rc, curl_easy_strerror(rc));
1008     }
1009     return(rc);
1010   } else {
1011 #ifdef HAVE_ICONV
1012     /* do the translation ourselves */
1013     const char *input_ptr;
1014     char *output_ptr;
1015     size_t in_bytes, out_bytes, rc;
1016     int error;
1017
1018     /* open an iconv conversion descriptor if necessary */
1019     if(data->utf8_cd == (iconv_t)-1) {
1020       data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
1021                                  CURL_ICONV_CODESET_FOR_UTF8);
1022       if(data->utf8_cd == (iconv_t)-1) {
1023         error = ERRNO;
1024         failf(data,
1025               "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
1026               CURL_ICONV_CODESET_OF_HOST,
1027               CURL_ICONV_CODESET_FOR_UTF8,
1028               error, strerror(error));
1029         return CURLE_CONV_FAILED;
1030       }
1031     }
1032     /* call iconv */
1033     input_ptr = output_ptr = buffer;
1034     in_bytes = out_bytes = length;
1035     rc = iconv(data->utf8_cd, &input_ptr, &in_bytes,
1036                &output_ptr, &out_bytes);
1037     if((rc == ICONV_ERROR) || (in_bytes != 0)) {
1038       error = ERRNO;
1039       failf(data,
1040             "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
1041             error, strerror(error));
1042       return CURLE_CONV_FAILED;
1043     }
1044     if(output_ptr < input_ptr) {
1045       /* null terminate the now shorter output string */
1046       *output_ptr = 0x00;
1047     }
1048 #else
1049     failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
1050     return CURLE_CONV_REQD;
1051 #endif /* HAVE_ICONV */
1052   }
1053
1054   return CURLE_OK;
1055 }
1056
1057 #endif /* CURL_DOES_CONVERSIONS */
1058
1059 static CURLcode easy_connection(struct SessionHandle *data,
1060                                 curl_socket_t *sfd,
1061                                 struct connectdata **connp)
1062 {
1063   CURLcode ret;
1064   long sockfd;
1065
1066   if(data == NULL)
1067     return CURLE_BAD_FUNCTION_ARGUMENT;
1068
1069   /* only allow these to be called on handles with CURLOPT_CONNECT_ONLY */
1070   if(!data->set.connect_only) {
1071     failf(data, "CONNECT_ONLY is required!");
1072     return CURLE_UNSUPPORTED_PROTOCOL;
1073   }
1074
1075   ret = Curl_getconnectinfo(data, &sockfd, connp);
1076   if(ret != CURLE_OK)
1077     return ret;
1078
1079   if(sockfd == -1) {
1080     failf(data, "Failed to get recent socket");
1081     return CURLE_UNSUPPORTED_PROTOCOL;
1082   }
1083
1084   *sfd = (curl_socket_t)sockfd; /* we know that this is actually a socket
1085                                    descriptor so the typecast is fine here */
1086
1087   return CURLE_OK;
1088 }
1089
1090 /*
1091  * Receives data from the connected socket. Use after successful
1092  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1093  * Returns CURLE_OK on success, error code on error.
1094  */
1095 CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen, size_t *n)
1096 {
1097   curl_socket_t sfd;
1098   CURLcode ret;
1099   int ret1;
1100   ssize_t n1;
1101   struct connectdata *c;
1102   struct SessionHandle *data = (struct SessionHandle *)curl;
1103
1104   ret = easy_connection(data, &sfd, &c);
1105   if(ret)
1106     return ret;
1107
1108   *n = 0;
1109   ret1 = Curl_read(c, sfd, buffer, buflen, &n1);
1110
1111   if(ret1 == -1)
1112     return CURLE_AGAIN;
1113
1114   if(ret1 != CURLE_OK)
1115     return (CURLcode)ret1;
1116
1117   *n = (size_t)n1;
1118
1119   return CURLE_OK;
1120 }
1121
1122 /*
1123  * Sends data over the connected socket. Use after successful
1124  * curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
1125  */
1126 CURLcode curl_easy_send(CURL *curl, const void *buffer, size_t buflen,
1127                         size_t *n)
1128 {
1129   curl_socket_t sfd;
1130   CURLcode ret;
1131   ssize_t n1;
1132   struct connectdata *c = NULL;
1133   struct SessionHandle *data = (struct SessionHandle *)curl;
1134
1135   ret = easy_connection(data, &sfd, &c);
1136   if(ret)
1137     return ret;
1138
1139   *n = 0;
1140   ret = Curl_write(c, sfd, buffer, buflen, &n1);
1141
1142   if(n1 == -1)
1143     return CURLE_SEND_ERROR;
1144
1145   /* detect EAGAIN */
1146   if((CURLE_OK == ret) && (0 == n1))
1147     return CURLE_AGAIN;
1148
1149   *n = (size_t)n1;
1150
1151   return ret;
1152 }