1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 #ifdef XP_WIN32
35 #define _MBCS
36 #include <windows.h>
37 #include <mbctype.h>
38 #endif
39
40 #include "util.h"
41 #include "pool.h"
42
43
44
45 #ifdef XP_WIN32
46 static PRBool _getfullpathname = -
1;
47 #endif
48
49
50
51 static inline
int allow_dbcs_uri()
52 {
53
54
55
56
57
58
59
60 return PR_TRUE;
61 }
62
63 #ifdef XP_WIN32
64 void set_fullpathname(PRBool b)
65 {
66 _getfullpathname = b;
67 }
68 #endif
69
70 NSAPI_PUBLIC int util_uri_is_evil_internal(
const char *t,
int allow_tilde,
int allow_dot_dir)
71 {
72 #ifdef XP_WIN32
73 int flagDbcsUri = allow_dbcs_uri();
74 #endif
75 PRBool flagEmptySegment =
PR_FALSE;
76 int x;
77
78 for (x =
0; t[x]; ++x) {
79 if (t[x] ==
'/') {
80 if (flagEmptySegment)
81 return 1;
82 #ifdef XP_WIN32
83 if (t[x+
1] ==
'/' && x !=
0)
84 #else
85 if (t[x+
1] ==
'/')
86 #endif
87 return 1;
88 if (t[x+
1] ==
';')
89 flagEmptySegment =
PR_TRUE;
90 if (t[x+
1] ==
'.') {
91
92 if (t[x+
2] ==
'\0')
93 return 1;
94
95
96 if (!allow_dot_dir && (t[x+
2] ==
'/' || t[x+
2] ==
';'))
97 return 1;
98
99
100 if (t[x+
2] ==
'.' && (t[x+
3] ==
'/' || t[x+
3] ==
';' || t[x+
3] ==
'\0'))
101 return 1;
102 }
103 }
104 #ifdef XP_WIN32
105
106
107
108 if (!allow_tilde && (t[x] ==
'~')) {
109 return 1;
110 }
111
112
113
114
115 if ((t[x] ==
':') && x >
1) {
116 return 1;
117 }
118
119
120
121
122
123
124
125
126 if (((t[x] ==
'.') || (t[x] ==
' ')) &&
127 ((t[x+
1] ==
';') || (t[x+
1] ==
'/') || (t[x+
1] ==
'\0')))
128 {
129 return 1;
130 }
131
132
133 if (flagDbcsUri && t[x+
1] && IsDBCSLeadByte(t[x])) x++;
134 #endif
135 }
136 return 0;
137 }
138
139 NSAPI_PUBLIC int util_uri_is_evil(
const char *t)
140 {
141 return util_uri_is_evil_internal(t,
0,
0);
142 }
143
144
145
146
147 #ifdef XP_WIN32
148
149
150
151
152 NSAPI_PUBLIC
153 int util_uri_unescape_and_normalize(
pool_handle_t *pool,
char *s,
char *unnormalized)
154 {
155 if(!(util_uri_unescape_strict(s)))
156 return 0;
157
158 if (unnormalized) strcpy(unnormalized, s);
159
160 if (_getfullpathname == -
1)
161 _getfullpathname = (_getmbcp() !=
0);
162
163
164 if(_getfullpathname && strcmp(s,
"*") && (*s ==
'/' ) ) {
165 char *pzAbsPath =
NULL;
166 int pathlen =
0;
167 int len =
0;
168 int ret =
0;
169 if(!(pzAbsPath = util_canonicalize_uri(pool, s, strlen(s),
NULL))) {
170
171 return 0;
172 }
173 char *pzPath = (
char *)
MALLOC(
MAX_PATH +
1);
174 char *pzFilename =
NULL;
175
176
177 if(!(ret = GetFullPathName(pzAbsPath,
MAX_PATH, pzPath, &pzFilename)) || ( ret >
MAX_PATH)){
178 FREE(pzAbsPath);
179 FREE(pzPath);
180 return 0;
181 }
182 len = strlen(pzAbsPath);
183 pathlen = strlen( pzPath );
184
185
186
187
188
189
190 if ( pzAbsPath[len-
1] ==
'/' && pzPath[pathlen-
1] !=
'\\')
191 strcat( pzPath,
"\\");
192 FREE(pzAbsPath);
193 pzFilename = strchr(pzPath,
'\\');
194 if(!pzFilename) {
195 FREE(pzPath);
196 return 0;
197 }
198 strcpy(s, pzFilename);
199 FREE(pzPath);
200 }
201
202 util_uri_normalize_slashes(s);
203
204 return 1;
205 }
206 #endif
207
208
209
210
211 void util_uri_normalize_slashes(
char *s)
212 {
213 #ifdef XP_WIN32
214 int flagDbcsUri = allow_dbcs_uri();
215
216 while (*s) {
217 if (*s ==
'\\') {
218
219 *s =
'/';
220 }
else if (flagDbcsUri && s[
1] && IsDBCSLeadByte(s[
0])) {
221
222 s++;
223 }
224 s++;
225 }
226 #endif
227 }
228
229
230
231 NSAPI_PUBLIC char *util_uri_escape(
char *od,
const char *s)
232 {
233 int flagDbcsUri = allow_dbcs_uri();
234 char *d;
235
236 if (!od)
237 od = (
char *)
MALLOC((strlen(s)*
3) +
1);
238 d = od;
239
240 while (*s) {
241 if (strchr(
"% ?#:+&*\"''<>\r\n", *s)) {
242 util_sprintf(d,
"%%%02x", (
unsigned char)*s);
243 ++s; d +=
3;
244 }
245 #ifdef XP_WIN32
246 else if (flagDbcsUri && s[
1] && IsDBCSLeadByte(s[
0]))
247 #else
248
249 else if (flagDbcsUri && s[
1] && (s[
0] & 0x80))
250 #endif
251 {
252
253
254
255
256 util_sprintf(d,
"%%%02x%%%02x", (
unsigned char)s[
0], (
unsigned char)s[
1]);
257 s +=
2; d +=
6;
258 }
259 else if (0x80 & *s) {
260 util_sprintf(d,
"%%%02x", (
unsigned char)*s);
261 ++s; d +=
3;
262 }
else {
263 *d++ = *s++;
264 }
265 }
266 *d =
'\0';
267 return od;
268 }
269
270
271
272
273 NSAPI_PUBLIC char *util_url_escape(
char *od,
const char *s)
274 {
275 int flagDbcsUri = allow_dbcs_uri();
276 char *d;
277
278 if (!od)
279 od = (
char *)
MALLOC((strlen(s)*
3) +
1);
280 d = od;
281
282 while (*s) {
283 if (strchr(
"% +*\"''<>\r\n", *s)) {
284 util_sprintf(d,
"%%%02x", (
unsigned char)*s);
285 ++s; d +=
3;
286 }
287 #ifdef XP_WIN32
288 else if (flagDbcsUri && s[
1] && IsDBCSLeadByte(s[
0]))
289 #else
290
291 else if (flagDbcsUri && s[
1] && (s[
0] & 0x80))
292 #endif
293 {
294
295
296
297
298 util_sprintf(d,
"%%%02x%%%02x", (
unsigned char)s[
0], (
unsigned char)s[
1]);
299 s +=
2; d +=
6;
300 }
301 else if (0x80 & *s) {
302 util_sprintf(d,
"%%%02x", (
unsigned char)*s);
303 ++s; d +=
3;
304 }
else {
305 *d++ = *s++;
306 }
307 }
308 *d =
'\0';
309 return od;
310 }
311
312
313
314
315 NSAPI_PUBLIC char* util_uri_strip_params(
char *uri)
316 {
317
318
319 char* out;
320 if((out = strchr(uri,
';'))) {
321 char* in = out;
322 while (*in) {
323 if (*in ==
';') {
324
325 do in++;
while (*in && *in !=
'/');
326 }
else {
327
328 *out++ = *in++;
329 }
330 }
331 *out =
0;
332 }
333 return uri;
334 }
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352 NSAPI_PUBLIC char* util_canonicalize_uri(
pool_handle_t *pool,
const char *uri,
int len,
int *pcanonlen)
353 {
354 PRBool success =
PR_TRUE;
355 const char *in_ptr = uri;
356 int in =
0;
357 int in_len = len;
358
359
360
361 char* canonPath = (
char *)pool_malloc(pool, in_len+
1);
362 char* out_ptr = canonPath;
363
364 if (!canonPath) {
365 success =
PR_FALSE;
366 goto done;
367 }
368
369
370
371
372
373 while (in < in_len) {
374
375
376 if (in_ptr[
0] !=
'/') {
377 *out_ptr++ = *in_ptr++;
378 in++;
379 continue;
380 }
381
382
383 if (in+
1 >= in_len) {
384 *out_ptr++ = *in_ptr++;
385 in++;
386 break;
387 }
388
389
390 switch(in_ptr[
1]) {
391 case '/':
392
393 in_ptr++;
394 in++;
395 break;
396
397 case '.':
398
399 if (in+
2 >= in_len) {
400
401
402
403 *out_ptr++ = *in_ptr++;
404 goto done;
405 }
406
407
408 if (in_ptr[
2] ==
'/') {
409
410 in_ptr +=
2;
411 in +=
2;
412 break;
413 }
414
415 if (in_ptr[
2] !=
'.') {
416
417 *out_ptr++ = *in_ptr++;
418 in++;
419 break;
420 }
421
422
423
424
425 if (in+
3 < in_len && in_ptr[
3] !=
'/' && in_ptr[
3] !=
';') {
426
427 *out_ptr++ = *in_ptr++;
428 in++;
429 }
430 else {
431
432 if (out_ptr == canonPath) {
433
434 success =
PR_FALSE;
435 goto done;
436 }
437
438
439 for (out_ptr--;
440 out_ptr != canonPath && out_ptr[
0] !=
'/';
441 out_ptr--);
442
443
444
445
446 if(in+
3 == in_len)
447 out_ptr++;
448
449
450 in_ptr +=
3;
451 in +=
3;
452 }
453 break;
454
455 default:
456
457 if (out_ptr == canonPath || *(out_ptr-
1) !=
'/')
458 *out_ptr++ = *in_ptr;
459 in_ptr++; in++;
460 break;
461 }
462 }
463
464 done:
465
466 if (success) {
467
468 unsigned canonLen = (
unsigned) (out_ptr - canonPath);
469 canonPath[canonLen] =
'\0';
470 if (pcanonlen) *pcanonlen = (
int) canonLen;
471 }
else {
472
473 pool_free(pool, canonPath);
474 canonPath =
NULL;
475 if (pcanonlen) *pcanonlen =
0;
476 }
477
478 return canonPath;
479 }
480
481
482
483
484 NSAPI_PUBLIC char* util_canonicalize_redirect(
pool_handle_t *pool,
const char *baseUri,
const char *newUri)
485 {
486
487
488 if (*newUri ==
'/')
489 return util_canonicalize_uri(pool, newUri, strlen(newUri),
NULL);
490
491 int bLen = strlen(baseUri);
492 if (bLen >
0 && baseUri[bLen -
1] !=
'/') {
493 while (bLen >
0 && baseUri[bLen -
1] !=
'/')
494 bLen--;
495 }
496
497 int pLen = strlen(newUri) + bLen +
1;
498 char *pUri = (
char *)pool_malloc(pool, pLen +
1);
499 if (!pUri)
500 return PR_FALSE;
501
502 memcpy(pUri, baseUri, bLen);
503 pUri[bLen] =
'/';
504 strcpy(pUri + bLen +
1, newUri);
505
506 char *rval = util_canonicalize_uri(pool, pUri, pLen,
NULL);
507 pool_free(pool, pUri);
508
509 return rval;
510 }
511
512
513
514
515 NSAPI_PUBLIC const char *util_host_port_suffix(
const char *h)
516 {
517
518
519
520
521
522
523
524
525 if (h ==
NULL)
526 return h;
527
528 for (;;) {
529
530 for (;;) {
531 char c = *h;
532
533 if (c ==
'\0')
534 return NULL;
535
536 if (c ==
'/')
537 return NULL;
538
539 if (c ==
':')
540 return h;
541
542 if (c ==
'[')
543 break;
544
545 h++;
546 }
547
548
549 while (*h !=
'\0' && *h !=
']')
550 h++;
551 }
552 }
553