Skip to content
Snippets Groups Projects
escape.c 5.47 KiB
Newer Older
  • Learn to ignore specific revisions
  • /***************************************************************************
    
     *                                  _   _ ____  _
     *  Project                     ___| | | |  _ \| |
     *                             / __| | | | |_) | |
     *                            | (__| |_| |  _ <| |___
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *                             \___|\___/|_| \_\_____|
     *
    
     * Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
     * This software is licensed as described in the file COPYING, which
     * you should have received as part of this distribution. The terms
     * are also available at http://curl.haxx.se/docs/copyright.html.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * You may opt to use, copy, modify, merge, publish, distribute and/or sell
     * copies of the Software, and permit persons to whom the Software is
    
     * furnished to do so, under the terms of the COPYING file.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
     * KIND, either express or implied.
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     *
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
     * $Id$
    
     ***************************************************************************/
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    /* Escape and unescape URL encoding in strings. The functions return a new
     * allocated string or NULL if an error occurred.  */
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /* urldata.h and easyif.h are included for Curl_convert_... prototypes */
    #include "urldata.h"
    #include "easyif.h"
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
    #define _MPRINTF_REPLACE /* use our functions only */
    #include <curl/mprintf.h>
    
    
    /* The last #include file should be: */
    #include "memdebug.h"
    
    
    /* for ABI-compatibility with previous versions */
    
    char *curl_escape(const char *string, int inlength)
    
    {
      return curl_easy_escape(NULL, string, inlength);
    }
    
    /* for ABI-compatibility with previous versions */
    char *curl_unescape(const char *string, int length)
    {
      return curl_easy_unescape(NULL, string, length, NULL);
    }
    
    char *curl_easy_escape(CURL *handle, const char *string, int inlength)
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    {
    
      size_t alloc = (inlength?(size_t)inlength:strlen(string))+1;
    
      char *ns;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      size_t newlen = alloc;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    
    
    #ifndef CURL_DOES_CONVERSIONS
      /* avoid compiler warnings */
      (void)handle;
    #endif
    
      ns = malloc(alloc);
      if(!ns)
        return NULL;
    
    
      length = alloc-1;
    
      while(length--) {
        in = *string;
    
    
        /* Portable character check (remember EBCDIC). Do not use isalnum() because
           its behavior is altered by the current locale. */
    
        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':
          /* just copy this */
          ns[strindex++]=in;
          break;
        default:
    
          /* encode it */
    
          newlen += 2; /* the size grows with two, since this'll become a %XX */
          if(newlen > alloc) {
            alloc *= 2;
    
            testing_ptr = realloc(ns, alloc);
            if(!testing_ptr) {
              free( ns );
    
    
    #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)) {
            /* Curl_convert_to_network calls failf if unsuccessful */
            free(ns);
            return NULL;
          }
    #endif /* CURL_DOES_CONVERSIONS */
    
    
          snprintf(&ns[strindex], 4, "%%%02X", in);
    
    char *curl_easy_unescape(CURL *handle, const char *string, int length,
                             int *olen)
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    {
    
      int alloc = (length?length:(int)strlen(string))+1;
    
      char *ns = malloc(alloc);
      unsigned char in;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
      long hex;
    
    #ifndef CURL_DOES_CONVERSIONS
      /* avoid compiler warnings */
      (void)handle;
    #endif
    
      if( !ns )
    
      while(--alloc > 0) {
        in = *string;
    
        if(('%' == in) && ISXDIGIT(string[1]) && ISXDIGIT(string[2])) {
    
          /* this is two hexadecimal digits following a '%' */
          char hexstr[3];
          char *ptr;
          hexstr[0] = string[1];
          hexstr[1] = string[2];
          hexstr[2] = 0;
    
          hex = strtol(hexstr, &ptr, 16);
    
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
          in = (unsigned char)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)) {
            /* Curl_convert_from_network calls failf if unsuccessful */
            free(ns);
            return NULL;
          }
    #endif /* CURL_DOES_CONVERSIONS */
    
    
    
      if(olen)
        /* store output size */
        *olen = strindex;
    
    Daniel Stenberg's avatar
    Daniel Stenberg committed
    }
    
    /* For operating systems/environments that use different malloc/free
       ssystems for the app and for this library, we provide a free that uses
       the library's memory system */
    
    void curl_free(void *p)
    {