Annotation of embedaddon/curl/lib/non-ascii.c, revision 1.1.1.1
1.1 misho 1: /***************************************************************************
2: * _ _ ____ _
3: * Project ___| | | | _ \| |
4: * / __| | | | |_) | |
5: * | (__| |_| | _ <| |___
6: * \___|\___/|_| \_\_____|
7: *
8: * Copyright (C) 1998 - 2019, 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 https://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: ***************************************************************************/
22:
23: #include "curl_setup.h"
24:
25: #ifdef CURL_DOES_CONVERSIONS
26:
27: #include <curl/curl.h>
28:
29: #include "non-ascii.h"
30: #include "formdata.h"
31: #include "sendf.h"
32: #include "urldata.h"
33: #include "multiif.h"
34:
35: #include "curl_memory.h"
36: /* The last #include file should be: */
37: #include "memdebug.h"
38:
39: #ifdef HAVE_ICONV
40: #include <iconv.h>
41: /* set default codesets for iconv */
42: #ifndef CURL_ICONV_CODESET_OF_NETWORK
43: #define CURL_ICONV_CODESET_OF_NETWORK "ISO8859-1"
44: #endif
45: #ifndef CURL_ICONV_CODESET_FOR_UTF8
46: #define CURL_ICONV_CODESET_FOR_UTF8 "UTF-8"
47: #endif
48: #define ICONV_ERROR (size_t)-1
49: #endif /* HAVE_ICONV */
50:
51: /*
52: * Curl_convert_clone() returns a malloced copy of the source string (if
53: * returning CURLE_OK), with the data converted to network format.
54: */
55: CURLcode Curl_convert_clone(struct Curl_easy *data,
56: const char *indata,
57: size_t insize,
58: char **outbuf)
59: {
60: char *convbuf;
61: CURLcode result;
62:
63: convbuf = malloc(insize);
64: if(!convbuf)
65: return CURLE_OUT_OF_MEMORY;
66:
67: memcpy(convbuf, indata, insize);
68: result = Curl_convert_to_network(data, convbuf, insize);
69: if(result) {
70: free(convbuf);
71: return result;
72: }
73:
74: *outbuf = convbuf; /* return the converted buffer */
75:
76: return CURLE_OK;
77: }
78:
79: /*
80: * Curl_convert_to_network() is an internal function for performing ASCII
81: * conversions on non-ASCII platforms. It converts the buffer _in place_.
82: */
83: CURLcode Curl_convert_to_network(struct Curl_easy *data,
84: char *buffer, size_t length)
85: {
86: if(data && data->set.convtonetwork) {
87: /* use translation callback */
88: CURLcode result;
89: Curl_set_in_callback(data, true);
90: result = data->set.convtonetwork(buffer, length);
91: Curl_set_in_callback(data, false);
92: if(result) {
93: failf(data,
94: "CURLOPT_CONV_TO_NETWORK_FUNCTION callback returned %d: %s",
95: (int)result, curl_easy_strerror(result));
96: }
97:
98: return result;
99: }
100: else {
101: #ifdef HAVE_ICONV
102: /* do the translation ourselves */
103: iconv_t tmpcd = (iconv_t) -1;
104: iconv_t *cd = &tmpcd;
105: char *input_ptr, *output_ptr;
106: size_t in_bytes, out_bytes, rc;
107:
108: /* open an iconv conversion descriptor if necessary */
109: if(data)
110: cd = &data->outbound_cd;
111: if(*cd == (iconv_t)-1) {
112: *cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
113: CURL_ICONV_CODESET_OF_HOST);
114: if(*cd == (iconv_t)-1) {
115: failf(data,
116: "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
117: CURL_ICONV_CODESET_OF_NETWORK,
118: CURL_ICONV_CODESET_OF_HOST,
119: errno, strerror(errno));
120: return CURLE_CONV_FAILED;
121: }
122: }
123: /* call iconv */
124: input_ptr = output_ptr = buffer;
125: in_bytes = out_bytes = length;
126: rc = iconv(*cd, &input_ptr, &in_bytes,
127: &output_ptr, &out_bytes);
128: if(!data)
129: iconv_close(tmpcd);
130: if((rc == ICONV_ERROR) || (in_bytes != 0)) {
131: failf(data,
132: "The Curl_convert_to_network iconv call failed with errno %i: %s",
133: errno, strerror(errno));
134: return CURLE_CONV_FAILED;
135: }
136: #else
137: failf(data, "CURLOPT_CONV_TO_NETWORK_FUNCTION callback required");
138: return CURLE_CONV_REQD;
139: #endif /* HAVE_ICONV */
140: }
141:
142: return CURLE_OK;
143: }
144:
145: /*
146: * Curl_convert_from_network() is an internal function for performing ASCII
147: * conversions on non-ASCII platforms. It converts the buffer _in place_.
148: */
149: CURLcode Curl_convert_from_network(struct Curl_easy *data,
150: char *buffer, size_t length)
151: {
152: if(data && data->set.convfromnetwork) {
153: /* use translation callback */
154: CURLcode result;
155: Curl_set_in_callback(data, true);
156: result = data->set.convfromnetwork(buffer, length);
157: Curl_set_in_callback(data, false);
158: if(result) {
159: failf(data,
160: "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback returned %d: %s",
161: (int)result, curl_easy_strerror(result));
162: }
163:
164: return result;
165: }
166: else {
167: #ifdef HAVE_ICONV
168: /* do the translation ourselves */
169: iconv_t tmpcd = (iconv_t) -1;
170: iconv_t *cd = &tmpcd;
171: char *input_ptr, *output_ptr;
172: size_t in_bytes, out_bytes, rc;
173:
174: /* open an iconv conversion descriptor if necessary */
175: if(data)
176: cd = &data->inbound_cd;
177: if(*cd == (iconv_t)-1) {
178: *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
179: CURL_ICONV_CODESET_OF_NETWORK);
180: if(*cd == (iconv_t)-1) {
181: failf(data,
182: "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
183: CURL_ICONV_CODESET_OF_HOST,
184: CURL_ICONV_CODESET_OF_NETWORK,
185: errno, strerror(errno));
186: return CURLE_CONV_FAILED;
187: }
188: }
189: /* call iconv */
190: input_ptr = output_ptr = buffer;
191: in_bytes = out_bytes = length;
192: rc = iconv(*cd, &input_ptr, &in_bytes,
193: &output_ptr, &out_bytes);
194: if(!data)
195: iconv_close(tmpcd);
196: if((rc == ICONV_ERROR) || (in_bytes != 0)) {
197: failf(data,
198: "Curl_convert_from_network iconv call failed with errno %i: %s",
199: errno, strerror(errno));
200: return CURLE_CONV_FAILED;
201: }
202: #else
203: failf(data, "CURLOPT_CONV_FROM_NETWORK_FUNCTION callback required");
204: return CURLE_CONV_REQD;
205: #endif /* HAVE_ICONV */
206: }
207:
208: return CURLE_OK;
209: }
210:
211: /*
212: * Curl_convert_from_utf8() is an internal function for performing UTF-8
213: * conversions on non-ASCII platforms.
214: */
215: CURLcode Curl_convert_from_utf8(struct Curl_easy *data,
216: char *buffer, size_t length)
217: {
218: if(data && data->set.convfromutf8) {
219: /* use translation callback */
220: CURLcode result;
221: Curl_set_in_callback(data, true);
222: result = data->set.convfromutf8(buffer, length);
223: Curl_set_in_callback(data, false);
224: if(result) {
225: failf(data,
226: "CURLOPT_CONV_FROM_UTF8_FUNCTION callback returned %d: %s",
227: (int)result, curl_easy_strerror(result));
228: }
229:
230: return result;
231: }
232: else {
233: #ifdef HAVE_ICONV
234: /* do the translation ourselves */
235: iconv_t tmpcd = (iconv_t) -1;
236: iconv_t *cd = &tmpcd;
237: char *input_ptr;
238: char *output_ptr;
239: size_t in_bytes, out_bytes, rc;
240:
241: /* open an iconv conversion descriptor if necessary */
242: if(data)
243: cd = &data->utf8_cd;
244: if(*cd == (iconv_t)-1) {
245: *cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
246: CURL_ICONV_CODESET_FOR_UTF8);
247: if(*cd == (iconv_t)-1) {
248: failf(data,
249: "The iconv_open(\"%s\", \"%s\") call failed with errno %i: %s",
250: CURL_ICONV_CODESET_OF_HOST,
251: CURL_ICONV_CODESET_FOR_UTF8,
252: errno, strerror(errno));
253: return CURLE_CONV_FAILED;
254: }
255: }
256: /* call iconv */
257: input_ptr = output_ptr = buffer;
258: in_bytes = out_bytes = length;
259: rc = iconv(*cd, &input_ptr, &in_bytes,
260: &output_ptr, &out_bytes);
261: if(!data)
262: iconv_close(tmpcd);
263: if((rc == ICONV_ERROR) || (in_bytes != 0)) {
264: failf(data,
265: "The Curl_convert_from_utf8 iconv call failed with errno %i: %s",
266: errno, strerror(errno));
267: return CURLE_CONV_FAILED;
268: }
269: if(output_ptr < input_ptr) {
270: /* null terminate the now shorter output string */
271: *output_ptr = 0x00;
272: }
273: #else
274: failf(data, "CURLOPT_CONV_FROM_UTF8_FUNCTION callback required");
275: return CURLE_CONV_REQD;
276: #endif /* HAVE_ICONV */
277: }
278:
279: return CURLE_OK;
280: }
281:
282: /*
283: * Init conversion stuff for a Curl_easy
284: */
285: void Curl_convert_init(struct Curl_easy *data)
286: {
287: #if defined(CURL_DOES_CONVERSIONS) && defined(HAVE_ICONV)
288: /* conversion descriptors for iconv calls */
289: data->outbound_cd = (iconv_t)-1;
290: data->inbound_cd = (iconv_t)-1;
291: data->utf8_cd = (iconv_t)-1;
292: #else
293: (void)data;
294: #endif /* CURL_DOES_CONVERSIONS && HAVE_ICONV */
295: }
296:
297: /*
298: * Setup conversion stuff for a Curl_easy
299: */
300: void Curl_convert_setup(struct Curl_easy *data)
301: {
302: data->inbound_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
303: CURL_ICONV_CODESET_OF_NETWORK);
304: data->outbound_cd = iconv_open(CURL_ICONV_CODESET_OF_NETWORK,
305: CURL_ICONV_CODESET_OF_HOST);
306: data->utf8_cd = iconv_open(CURL_ICONV_CODESET_OF_HOST,
307: CURL_ICONV_CODESET_FOR_UTF8);
308: }
309:
310: /*
311: * Close conversion stuff for a Curl_easy
312: */
313:
314: void Curl_convert_close(struct Curl_easy *data)
315: {
316: #ifdef HAVE_ICONV
317: /* close iconv conversion descriptors */
318: if(data->inbound_cd != (iconv_t)-1) {
319: iconv_close(data->inbound_cd);
320: }
321: if(data->outbound_cd != (iconv_t)-1) {
322: iconv_close(data->outbound_cd);
323: }
324: if(data->utf8_cd != (iconv_t)-1) {
325: iconv_close(data->utf8_cd);
326: }
327: #else
328: (void)data;
329: #endif /* HAVE_ICONV */
330: }
331:
332: #endif /* CURL_DOES_CONVERSIONS */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>