1 /***************************************************************************
3 * Project ___| | | | _ \| |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
8 * Copyright (C) 1998 - 2012, 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 ***************************************************************************/
23 #include "curl_setup.h"
25 #ifdef CURL_DOES_CONVERSIONS
27 #include <curl/curl.h>
29 #include "curl_non-ascii.h"
30 #include "curl_formdata.h"
31 #include "curl_sendf.h"
32 #include "curl_urldata.h"
34 #include "curl_memory.h"
35 /* The last #include file should be: */
36 #include "curl_memdebug.h"
40 /* set default codesets for iconv */
41 #ifndef CURL_ICONV_CODESET_OF_NETWORK
42 #define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
44 #ifndef CURL_ICONV_CODESET_FOR_UTF8
45 #define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
47 #define ICONV_ERROR (size_t)-1
48 #endif /* HAVE_ICONV */
51 * Curl_convert_clone() returns a malloced copy of the source string (if
52 * returning CURLE_OK), with the data converted to network format.
54 CURLcode Curl_convert_clone(struct SessionHandle *data,
62 convbuf = malloc(insize);
64 return CURLE_OUT_OF_MEMORY;
66 memcpy(convbuf, indata, insize);
67 result = Curl_convert_to_network(data, convbuf, insize);
73 *outbuf = convbuf; /* return the converted buffer */
79 * Curl_convert_to_network() is an internal function for performing ASCII
80 * conversions on non-ASCII platforms. It convers the buffer _in place_.
82 CURLcode Curl_convert_to_network(struct SessionHandle *data,
83 char *buffer, size_t length)
87 if(data->set.convtonetwork) {
88 /* use translation callback */
89 rc = data->set.convtonetwork(buffer, length);
92 "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
93 (int)rc, curl_easy_strerror(rc));
99 /* do the translation ourselves */
100 char *input_ptr, *output_ptr;
101 size_t in_bytes, out_bytes, rc;
104 /* open an iconv conversion descriptor if necessary */
105 if(data->outbound_cd == (iconv_t)-1) {
106 data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
107 CURL_ICONV_CODESET_OF_HOST);
108 if(data->outbound_cd == (iconv_t)-1) {
111 "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
112 CURL_ICONV_CODESET_OF_NETWORK,
113 CURL_ICONV_CODESET_OF_HOST,
114 error, strerror(error));
115 return CURLE_CONV_FAILED;
119 input_ptr = output_ptr = buffer;
120 in_bytes = out_bytes = length;
121 rc = iconv(data->outbound_cd, (const char**)&input_ptr, &in_bytes,
122 &output_ptr, &out_bytes);
123 if((rc == ICONV_ERROR) || (in_bytes != 0)) {
126 "The Curl_convert_to_network iconv call failed with errno %i: %s",
127 error, strerror(error));
128 return CURLE_CONV_FAILED;
131 failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
132 return CURLE_CONV_REQD;
133 #endif /* HAVE_ICONV */
140 * Curl_convert_from_network() is an internal function for performing ASCII
141 * conversions on non-ASCII platforms. It convers the buffer _in place_.
143 CURLcode Curl_convert_from_network(struct SessionHandle *data,
144 char *buffer, size_t length)
148 if(data->set.convfromnetwork) {
149 /* use translation callback */
150 rc = data->set.convfromnetwork(buffer, length);
153 "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
154 (int)rc, curl_easy_strerror(rc));
160 /* do the translation ourselves */
161 char *input_ptr, *output_ptr;
162 size_t in_bytes, out_bytes, rc;
165 /* open an iconv conversion descriptor if necessary */
166 if(data->inbound_cd == (iconv_t)-1) {
167 data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
168 CURL_ICONV_CODESET_OF_NETWORK);
169 if(data->inbound_cd == (iconv_t)-1) {
172 "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
173 CURL_ICONV_CODESET_OF_HOST,
174 CURL_ICONV_CODESET_OF_NETWORK,
175 error, strerror(error));
176 return CURLE_CONV_FAILED;
180 input_ptr = output_ptr = buffer;
181 in_bytes = out_bytes = length;
182 rc = iconv(data->inbound_cd, (const char **)&input_ptr, &in_bytes,
183 &output_ptr, &out_bytes);
184 if((rc == ICONV_ERROR) || (in_bytes != 0)) {
187 "Curl_convert_from_network iconv call failed with errno %i: %s",
188 error, strerror(error));
189 return CURLE_CONV_FAILED;
192 failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
193 return CURLE_CONV_REQD;
194 #endif /* HAVE_ICONV */
201 * Curl_convert_from_utf8() is an internal function for performing UTF-8
202 * conversions on non-ASCII platforms.
204 CURLcode Curl_convert_from_utf8(struct SessionHandle *data,
205 char *buffer, size_t length)
209 if(data->set.convfromutf8) {
210 /* use translation callback */
211 rc = data->set.convfromutf8(buffer, length);
214 "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
215 (int)rc, curl_easy_strerror(rc));
221 /* do the translation ourselves */
222 const char *input_ptr;
224 size_t in_bytes, out_bytes, rc;
227 /* open an iconv conversion descriptor if necessary */
228 if(data->utf8_cd == (iconv_t)-1) {
229 data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
230 CURL_ICONV_CODESET_FOR_UTF8);
231 if(data->utf8_cd == (iconv_t)-1) {
234 "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
235 CURL_ICONV_CODESET_OF_HOST,
236 CURL_ICONV_CODESET_FOR_UTF8,
237 error, strerror(error));
238 return CURLE_CONV_FAILED;
242 input_ptr = output_ptr = buffer;
243 in_bytes = out_bytes = length;
244 rc = iconv(data->utf8_cd, &input_ptr, &in_bytes,
245 &output_ptr, &out_bytes);
246 if((rc == ICONV_ERROR) || (in_bytes != 0)) {
249 "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
250 error, strerror(error));
251 return CURLE_CONV_FAILED;
253 if(output_ptr < input_ptr) {
254 /* null terminate the now shorter output string */
258 failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
259 return CURLE_CONV_REQD;
260 #endif /* HAVE_ICONV */
267 * Init conversion stuff for a SessionHandle
269 void Curl_convert_init(struct SessionHandle *data)
271 #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
272 /* conversion descriptors for iconv calls */
273 data->outbound_cd = (iconv_t)-1;
274 data->inbound_cd = (iconv_t)-1;
275 data->utf8_cd = (iconv_t)-1;
278 #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
282 * Setup conversion stuff for a SessionHandle
284 void Curl_convert_setup(struct SessionHandle *data)
286 data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
287 CURL_ICONV_CODESET_OF_NETWORK);
288 data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
289 CURL_ICONV_CODESET_OF_HOST);
290 data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
291 CURL_ICONV_CODESET_FOR_UTF8);
295 * Close conversion stuff for a SessionHandle
298 void Curl_convert_close(struct SessionHandle *data)
301 /* close iconv conversion descriptors */
302 if(data->inbound_cd != (iconv_t)-1) {
303 iconv_close(data->inbound_cd);
305 if(data->outbound_cd != (iconv_t)-1) {
306 iconv_close(data->outbound_cd);
308 if(data->utf8_cd != (iconv_t)-1) {
309 iconv_close(data->utf8_cd);
313 #endif /* HAVE_ICONV */
317 * Curl_convert_form() is used from http.c, this converts any form items that
318 need to be sent in the network encoding. Returns CURLE_OK on success.
320 CURLcode Curl_convert_form(struct SessionHandle *data, struct FormData *form)
322 struct FormData *next;
329 return CURLE_BAD_FUNCTION_ARGUMENT;
332 next=form->next; /* the following form line */
333 if(form->type == FORM_DATA) {
334 rc = Curl_convert_to_network(data, form->line, form->length);
335 /* Curl_convert_to_network calls failf if unsuccessful */
339 } while((form = next) != NULL); /* continue */
343 #endif /* CURL_DOES_CONVERSIONS */