123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332 |
- /***************************************************************************
- * _ _ ____ _
- * Project ___| | | | _ \| |
- * / __| | | | |_) | |
- * | (__| |_| | _ <| |___
- * \___|\___/|_| \_\_____|
- *
- * Copyright (C) 1998 - 2019, Daniel Stenberg, <daniel@haxx.se>, et al.
- *
- * This software is licensed as described in the file COPYING, which
- * you should have received as part of this distribution. The terms
- * are also available at https://curl.haxx.se/docs/copyright.html.
- *
- * You may opt to use, copy, modify, merge, publish, distribute and/or sell
- * copies of the Software, and permit persons to whom the Software is
- * furnished to do so, under the terms of the COPYING file.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ***************************************************************************/
- #include "curl_setup.h"
- #ifdef CURL_DOES_CONVERSIONS
- #include <curl/curl.h>
- #include "non-ascii.h"
- #include "formdata.h"
- #include "sendf.h"
- #include "urldata.h"
- #include "multiif.h"
- #include "curl_memory.h"
- /* The last #include file should be: */
- #include "memdebug.h"
- #ifdef HAVE_ICONV
- #include <iconv.h>
- /* set default codesets for iconv */
- #ifndef CURL_ICONV_CODESET_OF_NETWORK
- #define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
- #endif
- #ifndef CURL_ICONV_CODESET_FOR_UTF8
- #define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
- #endif
- #define ICONV_ERROR (size_t)-1
- #endif /* HAVE_ICONV */
- /*
- * Curl_convert_clone() returns a malloced copy of the source string (if
- * returning CURLE_OK), with the data converted to network format.
- */
- CURLcode Curl_convert_clone(struct Curl_easy *data,
- const char *indata,
- size_t insize,
- char **outbuf)
- {
- char *convbuf;
- CURLcode result;
- convbuf = malloc(insize);
- if(!convbuf)
- return CURLE_OUT_OF_MEMORY;
- memcpy(convbuf, indata, insize);
- result = Curl_convert_to_network(data, convbuf, insize);
- if(result) {
- free(convbuf);
- return result;
- }
- *outbuf = convbuf; /* return the converted buffer */
- return CURLE_OK;
- }
- /*
- * Curl_convert_to_network() is an internal function for performing ASCII
- * conversions on non-ASCII platforms. It converts the buffer _in place_.
- */
- CURLcode Curl_convert_to_network(struct Curl_easy *data,
- char *buffer, size_t length)
- {
- if(data && data->set.convtonetwork) {
- /* use translation callback */
- CURLcode result;
- Curl_set_in_callback(data, true);
- result = data->set.convtonetwork(buffer, length);
- Curl_set_in_callback(data, false);
- if(result) {
- failf(data,
- "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
- (int)result, curl_easy_strerror(result));
- }
- return result;
- }
- else {
- #ifdef HAVE_ICONV
- /* do the translation ourselves */
- iconv_t tmpcd = (iconv_t) -1;
- iconv_t *cd = &tmpcd;
- char *input_ptr, *output_ptr;
- size_t in_bytes, out_bytes, rc;
- /* open an iconv conversion descriptor if necessary */
- if(data)
- cd = &data->outbound_cd;
- if(*cd == (iconv_t)-1) {
- *cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
- CURL_ICONV_CODESET_OF_HOST);
- if(*cd == (iconv_t)-1) {
- failf(data,
- "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
- CURL_ICONV_CODESET_OF_NETWORK,
- CURL_ICONV_CODESET_OF_HOST,
- errno, strerror(errno));
- return CURLE_CONV_FAILED;
- }
- }
- /* call iconv */
- input_ptr = output_ptr = buffer;
- in_bytes = out_bytes = length;
- rc = iconv(*cd, &input_ptr, &in_bytes,
- &output_ptr, &out_bytes);
- if(!data)
- iconv_close(tmpcd);
- if((rc == ICONV_ERROR) || (in_bytes != 0)) {
- failf(data,
- "The Curl_convert_to_network iconv call failed with errno %i: %s",
- errno, strerror(errno));
- return CURLE_CONV_FAILED;
- }
- #else
- failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
- return CURLE_CONV_REQD;
- #endif /* HAVE_ICONV */
- }
- return CURLE_OK;
- }
- /*
- * Curl_convert_from_network() is an internal function for performing ASCII
- * conversions on non-ASCII platforms. It converts the buffer _in place_.
- */
- CURLcode Curl_convert_from_network(struct Curl_easy *data,
- char *buffer, size_t length)
- {
- if(data && data->set.convfromnetwork) {
- /* use translation callback */
- CURLcode result;
- Curl_set_in_callback(data, true);
- result = data->set.convfromnetwork(buffer, length);
- Curl_set_in_callback(data, false);
- if(result) {
- failf(data,
- "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
- (int)result, curl_easy_strerror(result));
- }
- return result;
- }
- else {
- #ifdef HAVE_ICONV
- /* do the translation ourselves */
- iconv_t tmpcd = (iconv_t) -1;
- iconv_t *cd = &tmpcd;
- char *input_ptr, *output_ptr;
- size_t in_bytes, out_bytes, rc;
- /* open an iconv conversion descriptor if necessary */
- if(data)
- cd = &data->inbound_cd;
- if(*cd == (iconv_t)-1) {
- *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
- CURL_ICONV_CODESET_OF_NETWORK);
- if(*cd == (iconv_t)-1) {
- failf(data,
- "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
- CURL_ICONV_CODESET_OF_HOST,
- CURL_ICONV_CODESET_OF_NETWORK,
- errno, strerror(errno));
- return CURLE_CONV_FAILED;
- }
- }
- /* call iconv */
- input_ptr = output_ptr = buffer;
- in_bytes = out_bytes = length;
- rc = iconv(*cd, &input_ptr, &in_bytes,
- &output_ptr, &out_bytes);
- if(!data)
- iconv_close(tmpcd);
- if((rc == ICONV_ERROR) || (in_bytes != 0)) {
- failf(data,
- "Curl_convert_from_network iconv call failed with errno %i: %s",
- errno, strerror(errno));
- return CURLE_CONV_FAILED;
- }
- #else
- failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
- return CURLE_CONV_REQD;
- #endif /* HAVE_ICONV */
- }
- return CURLE_OK;
- }
- /*
- * Curl_convert_from_utf8() is an internal function for performing UTF-8
- * conversions on non-ASCII platforms.
- */
- CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
- char *buffer, size_t length)
- {
- if(data && data->set.convfromutf8) {
- /* use translation callback */
- CURLcode result;
- Curl_set_in_callback(data, true);
- result = data->set.convfromutf8(buffer, length);
- Curl_set_in_callback(data, false);
- if(result) {
- failf(data,
- "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
- (int)result, curl_easy_strerror(result));
- }
- return result;
- }
- else {
- #ifdef HAVE_ICONV
- /* do the translation ourselves */
- iconv_t tmpcd = (iconv_t) -1;
- iconv_t *cd = &tmpcd;
- char *input_ptr;
- char *output_ptr;
- size_t in_bytes, out_bytes, rc;
- /* open an iconv conversion descriptor if necessary */
- if(data)
- cd = &data->utf8_cd;
- if(*cd == (iconv_t)-1) {
- *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
- CURL_ICONV_CODESET_FOR_UTF8);
- if(*cd == (iconv_t)-1) {
- failf(data,
- "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
- CURL_ICONV_CODESET_OF_HOST,
- CURL_ICONV_CODESET_FOR_UTF8,
- errno, strerror(errno));
- return CURLE_CONV_FAILED;
- }
- }
- /* call iconv */
- input_ptr = output_ptr = buffer;
- in_bytes = out_bytes = length;
- rc = iconv(*cd, &input_ptr, &in_bytes,
- &output_ptr, &out_bytes);
- if(!data)
- iconv_close(tmpcd);
- if((rc == ICONV_ERROR) || (in_bytes != 0)) {
- failf(data,
- "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
- errno, strerror(errno));
- return CURLE_CONV_FAILED;
- }
- if(output_ptr < input_ptr) {
- /* null terminate the now shorter output string */
- *output_ptr = 0x00;
- }
- #else
- failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
- return CURLE_CONV_REQD;
- #endif /* HAVE_ICONV */
- }
- return CURLE_OK;
- }
- /*
- * Init conversion stuff for a Curl_easy
- */
- void Curl_convert_init(struct Curl_easy *data)
- {
- #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
- /* conversion descriptors for iconv calls */
- data->outbound_cd = (iconv_t)-1;
- data->inbound_cd = (iconv_t)-1;
- data->utf8_cd = (iconv_t)-1;
- #else
- (void)data;
- #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
- }
- /*
- * Setup conversion stuff for a Curl_easy
- */
- void Curl_convert_setup(struct Curl_easy *data)
- {
- data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
- CURL_ICONV_CODESET_OF_NETWORK);
- data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
- CURL_ICONV_CODESET_OF_HOST);
- data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
- CURL_ICONV_CODESET_FOR_UTF8);
- }
- /*
- * Close conversion stuff for a Curl_easy
- */
- void Curl_convert_close(struct Curl_easy *data)
- {
- #ifdef HAVE_ICONV
- /* close iconv conversion descriptors */
- if(data->inbound_cd != (iconv_t)-1) {
- iconv_close(data->inbound_cd);
- }
- if(data->outbound_cd != (iconv_t)-1) {
- iconv_close(data->outbound_cd);
- }
- if(data->utf8_cd != (iconv_t)-1) {
- iconv_close(data->utf8_cd);
- }
- #else
- (void)data;
- #endif /* HAVE_ICONV */
- }
- #endif /* CURL_DOES_CONVERSIONS */
|