escape.c
Go to the documentation of this file.
1 /***************************************************************************
2  * _ _ ____ _
3  * Project ___| | | | _ \| |
4  * / __| | | | |_) | |
5  * | (__| |_| | _ <| |___
6  * \___|\___/|_| \_\_____|
7  *
8  * Copyright (C) 1998 - 2017, 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 static 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  unsigned char in; /* we need to treat the characters unsigned */
86  size_t newlen;
87  size_t strindex = 0;
88  size_t length;
90 
91  if(inlength < 0)
92  return NULL;
93 
94  alloc = (inlength?(size_t)inlength:strlen(string)) + 1;
95  newlen = alloc;
96 
97  ns = malloc(alloc);
98  if(!ns)
99  return NULL;
100 
101  length = alloc-1;
102  while(length--) {
103  in = *string;
104 
105  if(Curl_isunreserved(in))
106  /* just copy this */
107  ns[strindex++] = in;
108  else {
109  /* encode it */
110  newlen += 2; /* the size grows with two, since this'll become a %XX */
111  if(newlen > alloc) {
112  alloc *= 2;
113  testing_ptr = Curl_saferealloc(ns, alloc);
114  if(!testing_ptr)
115  return NULL;
116  ns = testing_ptr;
117  }
118 
119  result = Curl_convert_to_network(data, (char *)&in, 1);
120  if(result) {
121  /* Curl_convert_to_network calls failf if unsuccessful */
122  free(ns);
123  return NULL;
124  }
125 
126  snprintf(&ns[strindex], 4, "%%%02X", in);
127 
128  strindex += 3;
129  }
130  string++;
131  }
132  ns[strindex] = 0; /* terminate it */
133  return ns;
134 }
135 
136 /*
137  * Curl_urldecode() URL decodes the given string.
138  *
139  * Optionally detects control characters (byte codes lower than 32) in the
140  * data and rejects such data.
141  *
142  * Returns a pointer to a malloced string in *ostring with length given in
143  * *olen. If length == 0, the length is assumed to be strlen(string).
144  *
145  */
147  const char *string, size_t length,
148  char **ostring, size_t *olen,
149  bool reject_ctrl)
150 {
151  size_t alloc = (length?length:strlen(string)) + 1;
152  char *ns = malloc(alloc);
153  unsigned char in;
154  size_t strindex = 0;
155  unsigned long hex;
157 
158  if(!ns)
159  return CURLE_OUT_OF_MEMORY;
160 
161  while(--alloc > 0) {
162  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  result = Curl_convert_from_network(data, (char *)&in, 1);
177  if(result) {
178  /* Curl_convert_from_network calls failf if unsuccessful */
179  free(ns);
180  return result;
181  }
182 
183  string += 2;
184  alloc -= 2;
185  }
186 
187  if(reject_ctrl && (in < 0x20)) {
188  free(ns);
189  return CURLE_URL_MALFORMAT;
190  }
191 
192  ns[strindex++] = in;
193  string++;
194  }
195  ns[strindex] = 0; /* terminate it */
196 
197  if(olen)
198  /* store output size */
199  *olen = strindex;
200 
201  /* store output string */
202  *ostring = ns;
203 
204  return CURLE_OK;
205 }
206 
207 /*
208  * Unescapes the given URL escaped string of given length. Returns a
209  * pointer to a malloced string with length given in *olen.
210  * If length == 0, the length is assumed to be strlen(string).
211  * If olen == NULL, no output length is stored.
212  */
213 char *curl_easy_unescape(struct Curl_easy *data, const char *string,
214  int length, int *olen)
215 {
216  char *str = NULL;
217  if(length >= 0) {
218  size_t inputlen = length;
219  size_t outputlen;
220  CURLcode res = Curl_urldecode(data, string, inputlen, &str, &outputlen,
221  FALSE);
222  if(res)
223  return NULL;
224 
225  if(olen) {
226  if(outputlen <= (size_t) INT_MAX)
227  *olen = curlx_uztosi(outputlen);
228  else
229  /* too large to return in an int, fail! */
230  Curl_safefree(str);
231  }
232  }
233  return str;
234 }
235 
236 /* For operating systems/environments that use different malloc/free
237  systems for the app and for this library, we provide a free that uses
238  the library's memory system */
239 void curl_free(void *p)
240 {
241  free(p);
242 }
#define free(ptr)
Definition: curl_memory.h:130
CURLcode Curl_urldecode(struct Curl_easy *data, const char *string, size_t length, char **ostring, size_t *olen, bool reject_ctrl)
Definition: escape.c:146
char * curl_escape(const char *string, int inlength)
Definition: escape.c:68
::std::string string
Definition: gtest-port.h:1129
unsigned char curlx_ultouc(unsigned long ulnum)
Definition: warnless.c:143
UNITTEST_START char * ptr
Definition: unit1330.c:38
CURLcode
Definition: curl.h:454
static bool Curl_isunreserved(unsigned char in)
Definition: escape.c:44
static int res
int curlx_uztosi(size_t uznum)
Definition: warnless.c:203
#define malloc(size)
Definition: curl_memory.h:124
UNITTEST_START int result
Definition: unit1304.c:49
const char ** p
Definition: unit1394.c:76
const char * str
Definition: unit1398.c:33
#define FALSE
curl_easy_setopt expects a curl_off_t argument for this option curl_easy_setopt expects a curl_write_callback argument for this option curl_easy_setopt expects a curl_ioctl_callback argument for this option curl_easy_setopt expects a curl_opensocket_callback argument for this option curl_easy_setopt expects a curl_debug_callback argument for this option curl_easy_setopt expects a curl_conv_callback argument for this option curl_easy_setopt expects a private data pointer as argument for this option curl_easy_setopt expects a FILE *argument for this option curl_easy_setopt expects a struct curl_httppost *argument for this option curl_easy_setopt expects a struct curl_slist *argument for this option curl_easy_getinfo expects a pointer to char *for this info curl_easy_getinfo expects a pointer to double for this info curl_easy_getinfo expects a pointer to struct curl_tlssessioninfo *for this info curl_easy_getinfo expects a pointer to curl_socket_t for this info size_t
void * Curl_saferealloc(void *ptr, size_t size)
Definition: strdup.c:93
#define Curl_convert_from_network(a, b, c)
Definition: non-ascii.h:57
char * curl_unescape(const char *string, int length)
Definition: escape.c:74
#define Curl_convert_to_network(a, b, c)
Definition: non-ascii.h:56
Definition: curl.h:455
char * curl_easy_escape(struct Curl_easy *data, const char *string, int inlength)
Definition: escape.c:79
#define Curl_safefree(ptr)
Definition: memdebug.h:170
void curl_free(void *p)
Definition: escape.c:239
#define ISXDIGIT(x)
TFSIMD_FORCE_INLINE tfScalar length(const Quaternion &q)
#define snprintf
Definition: curl_printf.h:42
#define TRUE
char * curl_easy_unescape(struct Curl_easy *data, const char *string, int length, int *olen)
Definition: escape.c:213
Definition: debug.c:29


rc_tagdetect_client
Author(s): Monika Florek-Jasinska , Raphael Schaller
autogenerated on Sat Feb 13 2021 03:42:09