00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "setup.h"
00025
00026
00027 #include <stdio.h>
00028 #include <string.h>
00029 #include <stdarg.h>
00030 #include <stdlib.h>
00031 #include <ctype.h>
00032 #include <errno.h>
00033
00034 #include "strequal.h"
00035
00036 #ifdef WIN32
00037 #include <time.h>
00038 #include <io.h>
00039 #else
00040 #ifdef HAVE_SYS_SOCKET_H
00041 #include <sys/socket.h>
00042 #endif
00043 #ifdef HAVE_NETINET_IN_H
00044 #include <netinet/in.h>
00045 #endif
00046 #ifdef HAVE_SYS_TIME_H
00047 #include <sys/time.h>
00048 #endif
00049 #ifdef HAVE_UNISTD_H
00050 #include <unistd.h>
00051 #endif
00052 #ifdef HAVE_NETDB_H
00053 #include <netdb.h>
00054 #endif
00055 #ifdef HAVE_ARPA_INET_H
00056 #include <arpa/inet.h>
00057 #endif
00058 #ifdef HAVE_NET_IF_H
00059 #include <net/if.h>
00060 #endif
00061 #ifdef HAVE_SYS_IOCTL_H
00062 #include <sys/ioctl.h>
00063 #endif
00064 #include <signal.h>
00065
00066 #ifdef HAVE_SYS_PARAM_H
00067 #include <sys/param.h>
00068 #endif
00069
00070 #endif
00071
00072 #include "urldata.h"
00073 #include <curl/curl.h>
00074 #include "transfer.h"
00075 #include "sslgen.h"
00076 #include "url.h"
00077 #include "getinfo.h"
00078 #include "hostip.h"
00079 #include "share.h"
00080 #include "strdup.h"
00081 #include "memory.h"
00082 #include "progress.h"
00083 #include "easyif.h"
00084 #include "select.h"
00085 #include "sendf.h"
00086 #include "ca-bundle.h"
00087
00088 #define _MPRINTF_REPLACE
00089 #include <curl/mprintf.h>
00090
00091 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
00092 #include <iconv.h>
00093
00094 #ifndef CURL_ICONV_CODESET_OF_NETWORK
00095 #define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
00096 #endif
00097 #ifndef CURL_ICONV_CODESET_FOR_UTF8
00098 #define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
00099 #endif
00100 #define ICONV_ERROR (size_t)-1
00101 #endif
00102
00103
00104 #include "memdebug.h"
00105
00106 #ifdef USE_WINSOCK
00107
00108
00109 static void win32_cleanup(void)
00110 {
00111 WSACleanup();
00112 }
00113
00114
00115
00116 static CURLcode win32_init(void)
00117 {
00118 WORD wVersionRequested;
00119 WSADATA wsaData;
00120 int err;
00121
00122 #if defined(ENABLE_IPV6) && (USE_WINSOCK < 2)
00123 Error IPV6_requires_winsock2
00124 #endif
00125
00126 wVersionRequested = MAKEWORD(USE_WINSOCK, USE_WINSOCK);
00127
00128 err = WSAStartup(wVersionRequested, &wsaData);
00129
00130 if (err != 0)
00131
00132
00133 return CURLE_FAILED_INIT;
00134
00135
00136
00137
00138
00139
00140
00141 if ( LOBYTE( wsaData.wVersion ) != LOBYTE(wVersionRequested) ||
00142 HIBYTE( wsaData.wVersion ) != HIBYTE(wVersionRequested) ) {
00143
00144
00145
00146 WSACleanup();
00147 return CURLE_FAILED_INIT;
00148 }
00149
00150 return CURLE_OK;
00151 }
00152
00153 #else
00154
00155 static CURLcode win32_init(void) { return CURLE_OK; }
00156 static void win32_cleanup(void) { }
00157 #endif
00158
00159 #ifdef USE_LIBIDN
00160
00161
00162
00163
00164
00165 static void idna_init (void)
00166 {
00167 #ifdef WIN32
00168 char buf[60];
00169 UINT cp = GetACP();
00170
00171 if (!getenv("CHARSET") && cp > 0) {
00172 snprintf(buf, sizeof(buf), "CHARSET=cp%u", cp);
00173 putenv(buf);
00174 }
00175 #else
00176
00177 #endif
00178 }
00179 #endif
00180
00181
00182 static unsigned int initialized;
00183 static long init_flags;
00184
00185
00186
00187
00188
00189
00190 #if defined(_WIN32_WCE)
00191 #define system_strdup _strdup
00192 #elif !defined(HAVE_STRDUP)
00193 #define system_strdup curlx_strdup
00194 #else
00195 #define system_strdup strdup
00196 #endif
00197
00198
00199
00200
00201
00202
00203 curl_malloc_callback Curl_cmalloc = (curl_malloc_callback)malloc;
00204 curl_free_callback Curl_cfree = (curl_free_callback)free;
00205 curl_realloc_callback Curl_crealloc = (curl_realloc_callback)realloc;
00206 curl_strdup_callback Curl_cstrdup = (curl_strdup_callback)system_strdup;
00207 curl_calloc_callback Curl_ccalloc = (curl_calloc_callback)calloc;
00208
00213 CURLcode curl_global_init(long flags)
00214 {
00215 if (initialized++)
00216 return CURLE_OK;
00217
00218
00219 Curl_cmalloc = (curl_malloc_callback)malloc;
00220 Curl_cfree = (curl_free_callback)free;
00221 Curl_crealloc = (curl_realloc_callback)realloc;
00222 Curl_cstrdup = (curl_strdup_callback)system_strdup;
00223 Curl_ccalloc = (curl_calloc_callback)calloc;
00224
00225 if (flags & CURL_GLOBAL_SSL)
00226 if (!Curl_ssl_init()) {
00227 DEBUGF(fprintf(stderr, "Error: Curl_ssl_init failed\n"));
00228 return CURLE_FAILED_INIT;
00229 }
00230
00231 if (flags & CURL_GLOBAL_WIN32)
00232 if (win32_init() != CURLE_OK) {
00233 DEBUGF(fprintf(stderr, "Error: win32_init failed\n"));
00234 return CURLE_FAILED_INIT;
00235 }
00236
00237 #ifdef __AMIGA__
00238 if(!amiga_init()) {
00239 DEBUGF(fprintf(stderr, "Error: amiga_init failed\n"));
00240 return CURLE_FAILED_INIT;
00241 }
00242 #endif
00243
00244 #ifdef USE_LIBIDN
00245 idna_init();
00246 #endif
00247
00248 init_flags = flags;
00249
00250 return CURLE_OK;
00251 }
00252
00253
00254
00255
00256
00257 CURLcode curl_global_init_mem(long flags, curl_malloc_callback m,
00258 curl_free_callback f, curl_realloc_callback r,
00259 curl_strdup_callback s, curl_calloc_callback c)
00260 {
00261 CURLcode code = CURLE_OK;
00262
00263
00264 if (!m || !f || !r || !s || !c)
00265 return CURLE_FAILED_INIT;
00266
00267
00268 if ( initialized )
00269 return CURLE_OK;
00270
00271
00272 code = curl_global_init(flags);
00273 if (code == CURLE_OK) {
00274 Curl_cmalloc = m;
00275 Curl_cfree = f;
00276 Curl_cstrdup = s;
00277 Curl_crealloc = r;
00278 Curl_ccalloc = c;
00279 }
00280
00281 return code;
00282 }
00283
00288 void curl_global_cleanup(void)
00289 {
00290 if (!initialized)
00291 return;
00292
00293 if (--initialized)
00294 return;
00295
00296 Curl_global_host_cache_dtor();
00297
00298 if (init_flags & CURL_GLOBAL_SSL)
00299 Curl_ssl_cleanup();
00300
00301 if (init_flags & CURL_GLOBAL_WIN32)
00302 win32_cleanup();
00303
00304 #ifdef __AMIGA__
00305 amiga_cleanup();
00306 #endif
00307
00308 init_flags = 0;
00309 }
00310
00311
00312
00313
00314
00315 CURL *curl_easy_init(void)
00316 {
00317 CURLcode res;
00318 struct SessionHandle *data;
00319
00320
00321 if (!initialized) {
00322 res = curl_global_init(CURL_GLOBAL_DEFAULT);
00323 if(res) {
00324
00325 DEBUGF(fprintf(stderr, "Error: curl_global_init failed\n"));
00326 return NULL;
00327 }
00328 }
00329
00330
00331 res = Curl_open(&data);
00332 if(res != CURLE_OK) {
00333 DEBUGF(fprintf(stderr, "Error: Curl_open failed\n"));
00334 return NULL;
00335 }
00336
00337 return data;
00338 }
00339
00340
00341
00342
00343
00344
00345 CURLcode curl_easy_setopt(CURL *curl, CURLoption tag, ...)
00346 {
00347 va_list arg;
00348 struct SessionHandle *data = curl;
00349 CURLcode ret;
00350
00351 if(!curl)
00352 return CURLE_BAD_FUNCTION_ARGUMENT;
00353
00354 va_start(arg, tag);
00355
00356 ret = Curl_setopt(data, tag, arg);
00357
00358 va_end(arg);
00359 return ret;
00360 }
00361
00362 #ifdef CURL_MULTIEASY
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376 CURLcode curl_easy_perform(CURL *easy)
00377 {
00378 CURLM *multi;
00379 CURLMcode mcode;
00380 CURLcode code = CURLE_OK;
00381 int still_running;
00382 struct timeval timeout;
00383 int rc;
00384 CURLMsg *msg;
00385 fd_set fdread;
00386 fd_set fdwrite;
00387 fd_set fdexcep;
00388 int maxfd;
00389
00390 if(!easy)
00391 return CURLE_BAD_FUNCTION_ARGUMENT;
00392
00393 multi = curl_multi_init();
00394 if(!multi)
00395 return CURLE_OUT_OF_MEMORY;
00396
00397 mcode = curl_multi_add_handle(multi, easy);
00398 if(mcode) {
00399 curl_multi_cleanup(multi);
00400 if(mcode == CURLM_OUT_OF_MEMORY)
00401 return CURLE_OUT_OF_MEMORY;
00402 else
00403 return CURLE_FAILED_INIT;
00404 }
00405
00406
00407
00408 do {
00409 while(CURLM_CALL_MULTI_PERFORM ==
00410 curl_multi_perform(multi, &still_running));
00411
00412 if(!still_running)
00413 break;
00414
00415 FD_ZERO(&fdread);
00416 FD_ZERO(&fdwrite);
00417 FD_ZERO(&fdexcep);
00418
00419
00420 timeout.tv_sec = 1;
00421 timeout.tv_usec = 0;
00422
00423
00424 curl_multi_fdset(multi, &fdread, &fdwrite, &fdexcep, &maxfd);
00425 rc = Curl_select(maxfd+1, &fdread, &fdwrite, &fdexcep, &timeout);
00426
00427
00428
00429
00430
00431 if(rc == -1)
00432
00433 break;
00434
00435
00436 } while(still_running);
00437
00438 msg = curl_multi_info_read(multi, &rc);
00439 if(msg)
00440 code = msg->data.result;
00441
00442 mcode = curl_multi_remove_handle(multi, easy);
00443
00444
00445 mcode = curl_multi_cleanup(multi);
00446
00447
00448 return code;
00449 }
00450 #else
00451
00452
00453
00454
00455 CURLcode curl_easy_perform(CURL *curl)
00456 {
00457 struct SessionHandle *data = (struct SessionHandle *)curl;
00458
00459 if(!data)
00460 return CURLE_BAD_FUNCTION_ARGUMENT;
00461
00462 if ( ! (data->share && data->share->hostcache) ) {
00463
00464 if (Curl_global_host_cache_use(data) &&
00465 (data->dns.hostcachetype != HCACHE_GLOBAL)) {
00466 if (data->dns.hostcachetype == HCACHE_PRIVATE)
00467 Curl_hash_destroy(data->dns.hostcache);
00468 data->dns.hostcache = Curl_global_host_cache_get();
00469 data->dns.hostcachetype = HCACHE_GLOBAL;
00470 }
00471
00472 if (!data->dns.hostcache) {
00473 data->dns.hostcachetype = HCACHE_PRIVATE;
00474 data->dns.hostcache = Curl_mk_dnscache();
00475
00476 if(!data->dns.hostcache)
00477
00478
00479
00480 return CURLE_OUT_OF_MEMORY;
00481 }
00482
00483 }
00484
00485 if(!data->state.connc) {
00486
00487 data->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1);
00488 if(!data->state.connc)
00489 return CURLE_OUT_OF_MEMORY;
00490 }
00491
00492 return Curl_perform(data);
00493 }
00494 #endif
00495
00496
00497
00498
00499
00500 void curl_easy_cleanup(CURL *curl)
00501 {
00502 struct SessionHandle *data = (struct SessionHandle *)curl;
00503
00504 if(!data)
00505 return;
00506
00507 Curl_close(data);
00508 }
00509
00510
00511
00512
00513 void Curl_easy_addmulti(struct SessionHandle *data,
00514 void *multi)
00515 {
00516 data->multi = multi;
00517 if (multi == NULL)
00518
00519
00520 data->state.used_interface = Curl_if_none;
00521 }
00522
00523 void Curl_easy_initHandleData(struct SessionHandle *data)
00524 {
00525 memset(&data->reqdata, 0, sizeof(struct HandleData));
00526
00527 data->reqdata.maxdownload = -1;
00528 }
00529
00530
00531
00532
00533
00534 CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...)
00535 {
00536 va_list arg;
00537 void *paramp;
00538 struct SessionHandle *data = (struct SessionHandle *)curl;
00539
00540 va_start(arg, info);
00541 paramp = va_arg(arg, void *);
00542
00543 return Curl_getinfo(data, info, paramp);
00544 }
00545
00546
00547
00548
00549
00550
00551 CURL *curl_easy_duphandle(CURL *incurl)
00552 {
00553 bool fail = TRUE;
00554 struct SessionHandle *data=(struct SessionHandle *)incurl;
00555
00556 struct SessionHandle *outcurl = (struct SessionHandle *)
00557 calloc(sizeof(struct SessionHandle), 1);
00558
00559 if(NULL == outcurl)
00560 return NULL;
00561
00562 do {
00563
00564
00565
00566
00567
00568
00569 outcurl->state.headerbuff=(char*)malloc(HEADERSIZE);
00570 if(!outcurl->state.headerbuff) {
00571 break;
00572 }
00573 outcurl->state.headersize=HEADERSIZE;
00574
00575
00576 outcurl->set = data->set;
00577
00578 if(data->state.used_interface == Curl_if_multi)
00579 outcurl->state.connc = data->state.connc;
00580 else
00581 outcurl->state.connc = Curl_mk_connc(CONNCACHE_PRIVATE, -1);
00582
00583 if(!outcurl->state.connc)
00584 break;
00585
00586 outcurl->state.lastconnect = -1;
00587
00588 outcurl->progress.flags = data->progress.flags;
00589 outcurl->progress.callback = data->progress.callback;
00590
00591 #if !defined(CURL_DISABLE_HTTP) && !defined(CURL_DISABLE_COOKIES)
00592 if(data->cookies) {
00593
00594
00595 outcurl->cookies = Curl_cookie_init(data,
00596 data->cookies->filename,
00597 outcurl->cookies,
00598 data->set.cookiesession);
00599 if(!outcurl->cookies) {
00600 break;
00601 }
00602 }
00603 #endif
00604
00605
00606
00607 if(data->change.url) {
00608 outcurl->change.url = strdup(data->change.url);
00609 if(!outcurl->change.url)
00610 break;
00611 outcurl->change.url_alloc = TRUE;
00612 }
00613
00614 if(data->change.referer) {
00615 outcurl->change.referer = strdup(data->change.referer);
00616 if(!outcurl->change.referer)
00617 break;
00618 outcurl->change.referer_alloc = TRUE;
00619 }
00620
00621 #ifdef USE_ARES
00622
00623 if(ARES_SUCCESS != ares_init(&outcurl->state.areschannel))
00624 break;
00625 #endif
00626
00627 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
00628 outcurl->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
00629 CURL_ICONV_CODESET_OF_NETWORK);
00630 outcurl->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
00631 CURL_ICONV_CODESET_OF_HOST);
00632 outcurl->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
00633 CURL_ICONV_CODESET_FOR_UTF8);
00634 #endif
00635
00636 Curl_easy_initHandleData(outcurl);
00637
00638 outcurl->magic = CURLEASY_MAGIC_NUMBER;
00639
00640 fail = FALSE;
00641
00642 } while(0);
00643
00644 if(fail) {
00645 if(outcurl) {
00646 if(outcurl->state.connc &&
00647 (outcurl->state.connc->type == CONNCACHE_PRIVATE))
00648 Curl_rm_connc(outcurl->state.connc);
00649 if(outcurl->state.headerbuff)
00650 free(outcurl->state.headerbuff);
00651 if(outcurl->change.url)
00652 free(outcurl->change.url);
00653 if(outcurl->change.referer)
00654 free(outcurl->change.referer);
00655 free(outcurl);
00656 outcurl = NULL;
00657 }
00658 }
00659
00660 return outcurl;
00661 }
00662
00663
00664
00665
00666
00667 void curl_easy_reset(CURL *curl)
00668 {
00669 struct SessionHandle *data = (struct SessionHandle *)curl;
00670
00671 Curl_safefree(data->reqdata.pathbuffer);
00672 data->reqdata.pathbuffer=NULL;
00673
00674 Curl_safefree(data->reqdata.proto.generic);
00675 data->reqdata.proto.generic=NULL;
00676
00677
00678 memset(&data->set, 0, sizeof(struct UserDefined));
00679
00680
00681 memset(&data->progress, 0, sizeof(struct Progress));
00682
00683
00684 Curl_easy_initHandleData(data);
00685
00686
00687
00688 data->set.out = stdout;
00689 data->set.in = stdin;
00690 data->set.err = stderr;
00691
00692
00693 data->set.fwrite = (curl_write_callback)fwrite;
00694
00695
00696 data->set.fread = (curl_read_callback)fread;
00697
00698 data->set.infilesize = -1;
00699 data->set.postfieldsize = -1;
00700
00701 data->state.current_speed = -1;
00702
00703 data->set.httpreq = HTTPREQ_GET;
00704 data->set.ftp_use_epsv = TRUE;
00705 data->set.ftp_use_eprt = TRUE;
00706
00707 data->set.dns_cache_timeout = 60;
00708
00709
00710 data->set.hide_progress = TRUE;
00711 data->progress.flags |= PGRS_HIDE;
00712
00713
00714 data->set.ssl.numsessions = 5;
00715
00716 data->set.proxyport = 1080;
00717 data->set.proxytype = CURLPROXY_HTTP;
00718 data->set.httpauth = CURLAUTH_BASIC;
00719 data->set.proxyauth = CURLAUTH_BASIC;
00720
00721
00722
00723
00724
00725 data->set.ssl.verifypeer = TRUE;
00726 data->set.ssl.verifyhost = 2;
00727 #ifdef CURL_CA_BUNDLE
00728
00729 data->set.ssl.CAfile = (char *)CURL_CA_BUNDLE;
00730 #endif
00731
00732 data->set.ssh_auth_types = CURLSSH_AUTH_DEFAULT;
00733
00734 data->set.new_file_perms = 0644;
00735 data->set.new_directory_perms = 0755;
00736 }
00737
00738 #ifdef CURL_DOES_CONVERSIONS
00739
00740
00741
00742
00743 CURLcode Curl_convert_to_network(struct SessionHandle *data,
00744 char *buffer, size_t length)
00745 {
00746 CURLcode rc;
00747
00748 if(data->set.convtonetwork) {
00749
00750 rc = data->set.convtonetwork(buffer, length);
00751 if(rc != CURLE_OK) {
00752 failf(data,
00753 "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %i: %s",
00754 rc, curl_easy_strerror(rc));
00755 }
00756 return(rc);
00757 } else {
00758 #ifdef HAVE_ICONV
00759
00760 char *input_ptr, *output_ptr;
00761 size_t in_bytes, out_bytes, rc;
00762 int error;
00763
00764
00765 if(data->outbound_cd == (iconv_t)-1) {
00766 data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
00767 CURL_ICONV_CODESET_OF_HOST);
00768 if(data->outbound_cd == (iconv_t)-1) {
00769 error = ERRNO;
00770 failf(data,
00771 "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
00772 CURL_ICONV_CODESET_OF_NETWORK,
00773 CURL_ICONV_CODESET_OF_HOST,
00774 error, strerror(error));
00775 return CURLE_CONV_FAILED;
00776 }
00777 }
00778
00779 input_ptr = output_ptr = buffer;
00780 in_bytes = out_bytes = length;
00781 rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
00782 &output_ptr, &out_bytes);
00783 if ((rc == ICONV_ERROR) || (in_bytes != 0)) {
00784 error = ERRNO;
00785 failf(data,
00786 "The Curl_convert_to_network iconv call failed with errno %i: %s",
00787 error, strerror(error));
00788 return CURLE_CONV_FAILED;
00789 }
00790 #else
00791 failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
00792 return CURLE_CONV_REQD;
00793 #endif
00794 }
00795
00796 return CURLE_OK;
00797 }
00798
00799
00800
00801
00802
00803 CURLcode Curl_convert_from_network(struct SessionHandle *data,
00804 char *buffer, size_t length)
00805 {
00806 CURLcode rc;
00807
00808 if(data->set.convfromnetwork) {
00809
00810 rc = data->set.convfromnetwork(buffer, length);
00811 if(rc != CURLE_OK) {
00812 failf(data,
00813 "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %i: %s",
00814 rc, curl_easy_strerror(rc));
00815 }
00816 return(rc);
00817 } else {
00818 #ifdef HAVE_ICONV
00819
00820 char *input_ptr, *output_ptr;
00821 size_t in_bytes, out_bytes, rc;
00822 int error;
00823
00824
00825 if(data->inbound_cd == (iconv_t)-1) {
00826 data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
00827 CURL_ICONV_CODESET_OF_NETWORK);
00828 if(data->inbound_cd == (iconv_t)-1) {
00829 error = ERRNO;
00830 failf(data,
00831 "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
00832 CURL_ICONV_CODESET_OF_HOST,
00833 CURL_ICONV_CODESET_OF_NETWORK,
00834 error, strerror(error));
00835 return CURLE_CONV_FAILED;
00836 }
00837 }
00838
00839 input_ptr = output_ptr = buffer;
00840 in_bytes = out_bytes = length;
00841 rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
00842 &output_ptr, &out_bytes);
00843 if ((rc == ICONV_ERROR) || (in_bytes != 0)) {
00844 error = ERRNO;
00845 failf(data,
00846 "The Curl_convert_from_network iconv call failed with errno %i: %s",
00847 error, strerror(error));
00848 return CURLE_CONV_FAILED;
00849 }
00850 #else
00851 failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
00852 return CURLE_CONV_REQD;
00853 #endif
00854 }
00855
00856 return CURLE_OK;
00857 }
00858
00859
00860
00861
00862
00863 CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
00864 char *buffer, size_t length)
00865 {
00866 CURLcode rc;
00867
00868 if(data->set.convfromutf8) {
00869
00870 rc = data->set.convfromutf8(buffer, length);
00871 if(rc != CURLE_OK) {
00872 failf(data,
00873 "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %i: %s",
00874 rc, curl_easy_strerror(rc));
00875 }
00876 return(rc);
00877 } else {
00878 #ifdef HAVE_ICONV
00879
00880 char *input_ptr, *output_ptr;
00881 size_t in_bytes, out_bytes, rc;
00882 int error;
00883
00884
00885 if(data->utf8_cd == (iconv_t)-1) {
00886 data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
00887 CURL_ICONV_CODESET_FOR_UTF8);
00888 if(data->utf8_cd == (iconv_t)-1) {
00889 error = ERRNO;
00890 failf(data,
00891 "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
00892 CURL_ICONV_CODESET_OF_HOST,
00893 CURL_ICONV_CODESET_FOR_UTF8,
00894 error, strerror(error));
00895 return CURLE_CONV_FAILED;
00896 }
00897 }
00898
00899 input_ptr = output_ptr = buffer;
00900 in_bytes = out_bytes = length;
00901 rc = iconv(data->utf8_cd, (const char**)&input_ptr, &in_bytes,
00902 &output_ptr, &out_bytes);
00903 if ((rc == ICONV_ERROR) || (in_bytes != 0)) {
00904 error = ERRNO;
00905 failf(data,
00906 "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
00907 error, strerror(error));
00908 return CURLE_CONV_FAILED;
00909 }
00910 if (output_ptr < input_ptr) {
00911
00912 *output_ptr = 0x00;
00913 }
00914 #else
00915 failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
00916 return CURLE_CONV_REQD;
00917 #endif
00918 }
00919
00920 return CURLE_OK;
00921 }
00922
00923 #endif