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>