Annotation of embedaddon/curl/lib/escape.c, revision 1.1

1.1     ! misho       1: /***************************************************************************
        !             2:  *                                  _   _ ____  _
        !             3:  *  Project                     ___| | | |  _ \| |
        !             4:  *                             / __| | | | |_) | |
        !             5:  *                            | (__| |_| |  _ <| |___
        !             6:  *                             \___|\___/|_| \_\_____|
        !             7:  *
        !             8:  * Copyright (C) 1998 - 2018, 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: /* Escape and unescape URL encoding in strings. The functions return a new
        !            24:  * allocated string or NULL if an error occurred.  */
        !            25: 
        !            26: #include "curl_setup.h"
        !            27: 
        !            28: #include <curl/curl.h>
        !            29: 
        !            30: #include "urldata.h"
        !            31: #include "warnless.h"
        !            32: #include "non-ascii.h"
        !            33: #include "escape.h"
        !            34: #include "strdup.h"
        !            35: /* The last 3 #include files should be in this order */
        !            36: #include "curl_printf.h"
        !            37: #include "curl_memory.h"
        !            38: #include "memdebug.h"
        !            39: 
        !            40: /* Portable character check (remember EBCDIC). Do not use isalnum() because
        !            41:    its behavior is altered by the current locale.
        !            42:    See https://tools.ietf.org/html/rfc3986#section-2.3
        !            43: */
        !            44: bool Curl_isunreserved(unsigned char in)
        !            45: {
        !            46:   switch(in) {
        !            47:     case '0': case '1': case '2': case '3': case '4':
        !            48:     case '5': case '6': case '7': case '8': case '9':
        !            49:     case 'a': case 'b': case 'c': case 'd': case 'e':
        !            50:     case 'f': case 'g': case 'h': case 'i': case 'j':
        !            51:     case 'k': case 'l': case 'm': case 'n': case 'o':
        !            52:     case 'p': case 'q': case 'r': case 's': case 't':
        !            53:     case 'u': case 'v': case 'w': case 'x': case 'y': case 'z':
        !            54:     case 'A': case 'B': case 'C': case 'D': case 'E':
        !            55:     case 'F': case 'G': case 'H': case 'I': case 'J':
        !            56:     case 'K': case 'L': case 'M': case 'N': case 'O':
        !            57:     case 'P': case 'Q': case 'R': case 'S': case 'T':
        !            58:     case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z':
        !            59:     case '-': case '.': case '_': case '~':
        !            60:       return TRUE;
        !            61:     default:
        !            62:       break;
        !            63:   }
        !            64:   return FALSE;
        !            65: }
        !            66: 
        !            67: /* for ABI-compatibility with previous versions */
        !            68: char *curl_escape(const char *string, int inlength)
        !            69: {
        !            70:   return curl_easy_escape(NULL, string, inlength);
        !            71: }
        !            72: 
        !            73: /* for ABI-compatibility with previous versions */
        !            74: char *curl_unescape(const char *string, int length)
        !            75: {
        !            76:   return curl_easy_unescape(NULL, string, length, NULL);
        !            77: }
        !            78: 
        !            79: char *curl_easy_escape(struct Curl_easy *data, const char *string,
        !            80:                        int inlength)
        !            81: {
        !            82:   size_t alloc;
        !            83:   char *ns;
        !            84:   char *testing_ptr = NULL;
        !            85:   size_t newlen;
        !            86:   size_t strindex = 0;
        !            87:   size_t length;
        !            88:   CURLcode result;
        !            89: 
        !            90:   if(inlength < 0)
        !            91:     return NULL;
        !            92: 
        !            93:   alloc = (inlength?(size_t)inlength:strlen(string)) + 1;
        !            94:   newlen = alloc;
        !            95: 
        !            96:   ns = malloc(alloc);
        !            97:   if(!ns)
        !            98:     return NULL;
        !            99: 
        !           100:   length = alloc-1;
        !           101:   while(length--) {
        !           102:     unsigned char in = *string; /* we need to treat the characters unsigned */
        !           103: 
        !           104:     if(Curl_isunreserved(in))
        !           105:       /* just copy this */
        !           106:       ns[strindex++] = in;
        !           107:     else {
        !           108:       /* encode it */
        !           109:       newlen += 2; /* the size grows with two, since this'll become a %XX */
        !           110:       if(newlen > alloc) {
        !           111:         alloc *= 2;
        !           112:         testing_ptr = Curl_saferealloc(ns, alloc);
        !           113:         if(!testing_ptr)
        !           114:           return NULL;
        !           115:         ns = testing_ptr;
        !           116:       }
        !           117: 
        !           118:       result = Curl_convert_to_network(data, (char *)&in, 1);
        !           119:       if(result) {
        !           120:         /* Curl_convert_to_network calls failf if unsuccessful */
        !           121:         free(ns);
        !           122:         return NULL;
        !           123:       }
        !           124: 
        !           125:       msnprintf(&ns[strindex], 4, "%%%02X", in);
        !           126: 
        !           127:       strindex += 3;
        !           128:     }
        !           129:     string++;
        !           130:   }
        !           131:   ns[strindex] = 0; /* terminate it */
        !           132:   return ns;
        !           133: }
        !           134: 
        !           135: /*
        !           136:  * Curl_urldecode() URL decodes the given string.
        !           137:  *
        !           138:  * Optionally detects control characters (byte codes lower than 32) in the
        !           139:  * data and rejects such data.
        !           140:  *
        !           141:  * Returns a pointer to a malloced string in *ostring with length given in
        !           142:  * *olen. If length == 0, the length is assumed to be strlen(string).
        !           143:  *
        !           144:  * 'data' can be set to NULL but then this function can't convert network
        !           145:  * data to host for non-ascii.
        !           146:  */
        !           147: CURLcode Curl_urldecode(struct Curl_easy *data,
        !           148:                         const char *string, size_t length,
        !           149:                         char **ostring, size_t *olen,
        !           150:                         bool reject_ctrl)
        !           151: {
        !           152:   size_t alloc = (length?length:strlen(string)) + 1;
        !           153:   char *ns = malloc(alloc);
        !           154:   size_t strindex = 0;
        !           155:   unsigned long hex;
        !           156:   CURLcode result = CURLE_OK;
        !           157: 
        !           158:   if(!ns)
        !           159:     return CURLE_OUT_OF_MEMORY;
        !           160: 
        !           161:   while(--alloc > 0) {
        !           162:     unsigned char in = *string;
        !           163:     if(('%' == in) && (alloc > 2) &&
        !           164:        ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
        !           165:       /* this is two hexadecimal digits following a '%' */
        !           166:       char hexstr[3];
        !           167:       char *ptr;
        !           168:       hexstr[0] = string[1];
        !           169:       hexstr[1] = string[2];
        !           170:       hexstr[2] = 0;
        !           171: 
        !           172:       hex = strtoul(hexstr, &ptr, 16);
        !           173: 
        !           174:       in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */
        !           175: 
        !           176:       if(data) {
        !           177:         result = Curl_convert_from_network(data, (char *)&in, 1);
        !           178:         if(result) {
        !           179:           /* Curl_convert_from_network calls failf if unsuccessful */
        !           180:           free(ns);
        !           181:           return result;
        !           182:         }
        !           183:       }
        !           184: 
        !           185:       string += 2;
        !           186:       alloc -= 2;
        !           187:     }
        !           188: 
        !           189:     if(reject_ctrl && (in < 0x20)) {
        !           190:       free(ns);
        !           191:       return CURLE_URL_MALFORMAT;
        !           192:     }
        !           193: 
        !           194:     ns[strindex++] = in;
        !           195:     string++;
        !           196:   }
        !           197:   ns[strindex] = 0; /* terminate it */
        !           198: 
        !           199:   if(olen)
        !           200:     /* store output size */
        !           201:     *olen = strindex;
        !           202: 
        !           203:   /* store output string */
        !           204:   *ostring = ns;
        !           205: 
        !           206:   return CURLE_OK;
        !           207: }
        !           208: 
        !           209: /*
        !           210:  * Unescapes the given URL escaped string of given length. Returns a
        !           211:  * pointer to a malloced string with length given in *olen.
        !           212:  * If length == 0, the length is assumed to be strlen(string).
        !           213:  * If olen == NULL, no output length is stored.
        !           214:  */
        !           215: char *curl_easy_unescape(struct Curl_easy *data, const char *string,
        !           216:                          int length, int *olen)
        !           217: {
        !           218:   char *str = NULL;
        !           219:   if(length >= 0) {
        !           220:     size_t inputlen = length;
        !           221:     size_t outputlen;
        !           222:     CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
        !           223:                                   FALSE);
        !           224:     if(res)
        !           225:       return NULL;
        !           226: 
        !           227:     if(olen) {
        !           228:       if(outputlen <= (size_t) INT_MAX)
        !           229:         *olen = curlx_uztosi(outputlen);
        !           230:       else
        !           231:         /* too large to return in an int, fail! */
        !           232:         Curl_safefree(str);
        !           233:     }
        !           234:   }
        !           235:   return str;
        !           236: }
        !           237: 
        !           238: /* For operating systems/environments that use different malloc/free
        !           239:    systems for the app and for this library, we provide a free that uses
        !           240:    the library's memory system */
        !           241: void curl_free(void *p)
        !           242: {
        !           243:   free(p);
        !           244: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>