diff options
Diffstat (limited to 'Utilities/cmcurl/lib/escape.c')
-rw-r--r-- | Utilities/cmcurl/lib/escape.c | 154 |
1 files changed, 103 insertions, 51 deletions
diff --git a/Utilities/cmcurl/lib/escape.c b/Utilities/cmcurl/lib/escape.c index 9552b0f..d7f8a8f 100644 --- a/Utilities/cmcurl/lib/escape.c +++ b/Utilities/cmcurl/lib/escape.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2014, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -18,23 +18,20 @@ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY * KIND, either express or implied. * - * $Id$ ***************************************************************************/ /* Escape and unescape URL encoding in strings. The functions return a new * allocated string or NULL if an error occurred. */ -#include "setup.h" -#include <ctype.h> +#include "curl_setup.h" + #include <curl/curl.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include "memory.h" -/* urldata.h and easyif.h are included for Curl_convert_... prototypes */ +#include "curl_memory.h" #include "urldata.h" -#include "easyif.h" +#include "warnless.h" +#include "non-ascii.h" +#include "escape.h" #define _MPRINTF_REPLACE /* use our functions only */ #include <curl/mprintf.h> @@ -42,6 +39,33 @@ /* The last #include file should be: */ #include "memdebug.h" +/* Portable character check (remember EBCDIC). Do not use isalnum() because + its behavior is altered by the current locale. + See http://tools.ietf.org/html/rfc3986#section-2.3 +*/ +static bool Curl_isunreserved(unsigned char in) +{ + switch (in) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + case 'a': case 'b': case 'c': case 'd': case 'e': + case 'f': case 'g': case 'h': case 'i': case 'j': + case 'k': case 'l': case 'm': case 'n': case 'o': + case 'p': case 'q': case 'r': case 's': case 't': + case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': + case 'A': case 'B': case 'C': case 'D': case 'E': + case 'F': case 'G': case 'H': case 'I': case 'J': + case 'K': case 'L': case 'M': case 'N': case 'O': + case 'P': case 'Q': case 'R': case 'S': case 'T': + case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': + case '-': case '.': case '_': case '~': + return TRUE; + default: + break; + } + return FALSE; +} + /* for ABI-compatibility with previous versions */ char *curl_escape(const char *string, int inlength) { @@ -59,15 +83,12 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength) size_t alloc = (inlength?(size_t)inlength:strlen(string))+1; char *ns; char *testing_ptr = NULL; - unsigned char in; + unsigned char in; /* we need to treat the characters unsigned */ size_t newlen = alloc; - int strindex=0; + size_t strindex=0; size_t length; + CURLcode res; -#ifndef CURL_DOES_CONVERSIONS - /* avoid compiler warnings */ - (void)handle; -#endif ns = malloc(alloc); if(!ns) return NULL; @@ -75,9 +96,11 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength) length = alloc-1; while(length--) { in = *string; - if(!(in >= 'a' && in <= 'z') && - !(in >= 'A' && in <= 'Z') && - !(in >= '0' && in <= '9')) { + + if(Curl_isunreserved(in)) + /* just copy this */ + ns[strindex++]=in; + else { /* encode it */ newlen += 2; /* the size grows with two, since this'll become a %XX */ if(newlen > alloc) { @@ -92,49 +115,52 @@ char *curl_easy_escape(CURL *handle, const char *string, int inlength) } } -#ifdef CURL_DOES_CONVERSIONS -/* escape sequences are always in ASCII so convert them on non-ASCII hosts */ - if (!handle || - (Curl_convert_to_network(handle, &in, 1) != CURLE_OK)) { + res = Curl_convert_to_network(handle, &in, 1); + if(res) { /* Curl_convert_to_network calls failf if unsuccessful */ free(ns); return NULL; } -#endif /* CURL_DOES_CONVERSIONS */ snprintf(&ns[strindex], 4, "%%%02X", in); strindex+=3; } - else { - /* just copy this */ - ns[strindex++]=in; - } string++; } ns[strindex]=0; /* terminate it */ return ns; } -char *curl_easy_unescape(CURL *handle, const char *string, int length, - int *olen) +/* + * Curl_urldecode() URL decodes the given string. + * + * Optionally detects control characters (byte codes lower than 32) in the + * data and rejects such data. + * + * Returns a pointer to a malloced string in *ostring with length given in + * *olen. If length == 0, the length is assumed to be strlen(string). + * + */ +CURLcode Curl_urldecode(struct SessionHandle *data, + const char *string, size_t length, + char **ostring, size_t *olen, + bool reject_ctrl) { - int alloc = (length?length:(int)strlen(string))+1; + size_t alloc = (length?length:strlen(string))+1; char *ns = malloc(alloc); unsigned char in; - int strindex=0; - long hex; - -#ifndef CURL_DOES_CONVERSIONS - /* avoid compiler warnings */ - (void)handle; -#endif - if( !ns ) - return NULL; + size_t strindex=0; + unsigned long hex; + CURLcode res; + + if(!ns) + return CURLE_OUT_OF_MEMORY; while(--alloc > 0) { in = *string; - if(('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { + if(('%' == in) && (alloc > 2) && + ISXDIGIT(string[1]) && ISXDIGIT(string[2])) { /* this is two hexadecimal digits following a '%' */ char hexstr[3]; char *ptr; @@ -142,23 +168,24 @@ char *curl_easy_unescape(CURL *handle, const char *string, int length, hexstr[1] = string[2]; hexstr[2] = 0; - hex = strtol(hexstr, &ptr, 16); + hex = strtoul(hexstr, &ptr, 16); - in = (unsigned char)hex; /* this long is never bigger than 255 anyway */ + in = curlx_ultouc(hex); /* this long is never bigger than 255 anyway */ -#ifdef CURL_DOES_CONVERSIONS -/* escape sequences are always in ASCII so convert them on non-ASCII hosts */ - if (!handle || - (Curl_convert_from_network(handle, &in, 1) != CURLE_OK)) { + res = Curl_convert_from_network(data, &in, 1); + if(res) { /* Curl_convert_from_network calls failf if unsuccessful */ free(ns); - return NULL; + return res; } -#endif /* CURL_DOES_CONVERSIONS */ string+=2; alloc-=2; } + if(reject_ctrl && (in < 0x20)) { + free(ns); + return CURLE_URL_MALFORMAT; + } ns[strindex++] = in; string++; @@ -168,11 +195,36 @@ char *curl_easy_unescape(CURL *handle, const char *string, int length, if(olen) /* store output size */ *olen = strindex; - return ns; + + /* store output string */ + *ostring = ns; + + return CURLE_OK; +} + +/* + * Unescapes the given URL escaped string of given length. Returns a + * pointer to a malloced string with length given in *olen. + * If length == 0, the length is assumed to be strlen(string). + * If olen == NULL, no output length is stored. + */ +char *curl_easy_unescape(CURL *handle, const char *string, int length, + int *olen) +{ + char *str = NULL; + size_t inputlen = length; + size_t outputlen; + CURLcode res = Curl_urldecode(handle, string, inputlen, &str, &outputlen, + FALSE); + if(res) + return NULL; + if(olen) + *olen = curlx_uztosi(outputlen); + return str; } /* For operating systems/environments that use different malloc/free - ssystems for the app and for this library, we provide a free that uses + systems for the app and for this library, we provide a free that uses the library's memory system */ void curl_free(void *p) { |