Annotation of embedaddon/curl/lib/non-ascii.c, revision 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>