74d8deea82d68c2c4f7807da71bb5f6c6cb36be6
[platform/upstream/curl.git] / lib / escape.c
1 /*****************************************************************************
2  *                                  _   _ ____  _     
3  *  Project                     ___| | | |  _ \| |    
4  *                             / __| | | | |_) | |    
5  *                            | (__| |_| |  _ <| |___ 
6  *                             \___|\___/|_| \_\_____|
7  *
8  *  The contents of this file are subject to the Mozilla Public License
9  *  Version 1.0 (the "License"); you may not use this file except in
10  *  compliance with the License. You may obtain a copy of the License at
11  *  http://www.mozilla.org/MPL/
12  *
13  *  Software distributed under the License is distributed on an "AS IS"
14  *  basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
15  *  License for the specific language governing rights and limitations
16  *  under the License.
17  *
18  *  The Original Code is Curl.
19  *
20  *  The Initial Developer of the Original Code is Daniel Stenberg.
21  *
22  *  Portions created by the Initial Developer are Copyright (C) 1998.
23  *  All Rights Reserved.
24  *
25  * ------------------------------------------------------------
26  * Main author:
27  * - Daniel Stenberg <daniel@haxx.se>
28  *
29  *      http://curl.haxx.se
30  *
31  * $Source$
32  * $Revision$
33  * $Date$
34  * $Author$
35  * $State$
36  * $Locker$
37  *
38  * ------------------------------------------------------------
39  ****************************************************************************/
40
41 /* Escape and unescape URL encoding in strings. The functions return a new
42  * allocated string or NULL if an error occurred.  */
43
44 #include "setup.h"
45 #include <curl/curl.h>
46
47 #include <stdio.h>
48 #include <stdlib.h>
49 #include <string.h>
50
51 /* The last #include file should be: */
52 #ifdef MALLOCDEBUG
53 #include "memdebug.h"
54 #endif
55
56 char *curl_escape(char *string)
57 {
58    int alloc=strlen(string)+1;
59    char *ns = malloc(alloc);
60    unsigned char in;
61    int newlen = alloc;
62    int index=0;
63
64    while(*string) {
65       in = *string;
66       if(' ' == in)
67          ns[index++] = '+';
68       else if(!(in >= 'a' && in <= 'z') &&
69               !(in >= 'A' && in <= 'Z') &&
70               !(in >= '0' && in <= '9')) {
71          /* encode it */
72          newlen += 2; /* the size grows with two, since this'll become a %XX */
73          if(newlen > alloc) {
74             alloc *= 2;
75             ns = realloc(ns, alloc);
76             if(!ns)
77                return NULL;
78          }
79          sprintf(&ns[index], "%%%02X", in);
80          index+=3;
81       }
82       else {
83          /* just copy this */
84          ns[index++]=in;
85       }
86       string++;
87    }
88    ns[index]=0; /* terminate it */
89    return ns;
90 }
91
92 char *curl_unescape(char *string, int length)
93 {
94    int alloc = (length?length:strlen(string))+1;
95    char *ns = malloc(alloc);
96    unsigned char in;
97    int index=0;
98    int hex;
99    char querypart=FALSE; /* everything to the right of a '?' letter is
100                             the "query part" where '+' should become ' '.
101                             RFC 2316, section 3.10 */
102   
103    while(--alloc > 0) {
104       in = *string;
105       if(querypart && ('+' == in))
106          in = ' ';
107       else if(!querypart && ('?' == in)) {
108         /* we have "walked in" to the query part */
109         querypart=TRUE;
110       }
111       else if('%' == in) {
112         /* encoded part */
113         if(sscanf(string+1, "%02X", &hex)) {
114           in = hex;
115           string+=2;
116           alloc-=2;
117         }
118       }
119
120       ns[index++] = in;
121       string++;
122    }
123    ns[index]=0; /* terminate it */
124    return ns;
125   
126 }