File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / curl / lib / non-ascii.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 10:01:15 2020 UTC (4 years, 1 month ago) by misho
Branches: curl, MAIN
CVS tags: v7_70_0p4, HEAD
curl

    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>