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_FALSE;
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 register 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
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317 NSAPI_PUBLIC char* util_uri_strip_params(
char *uri)
318 {
319
320
321 char* out;
322 if((out = strchr(uri,
';'))) {
323 char* in = out;
324 while (*in) {
325 if (*in ==
';') {
326
327 do in++;
while (*in && *in !=
'/');
328 }
else {
329
330 *out++ = *in++;
331 }
332 }
333 *out =
0;
334 }
335 return uri;
336 }
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 NSAPI_PUBLIC char* util_canonicalize_uri(
pool_handle_t *pool,
const char *uri,
int len,
int *pcanonlen)
355 {
356 PRBool success =
PR_TRUE;
357 const char *in_ptr = uri;
358 int in =
0;
359 int in_len = len;
360
361
362
363 char* canonPath = (
char *)pool_malloc(pool, in_len+
1);
364 char* out_ptr = canonPath;
365
366 if (!canonPath) {
367 success =
PR_FALSE;
368 goto done;
369 }
370
371
372
373
374
375 while (in < in_len) {
376
377
378 if (in_ptr[
0] !=
'/') {
379 *out_ptr++ = *in_ptr++;
380 in++;
381 continue;
382 }
383
384
385 if (in+
1 >= in_len) {
386 *out_ptr++ = *in_ptr++;
387 in++;
388 break;
389 }
390
391
392 switch(in_ptr[
1]) {
393 case '/':
394
395 in_ptr++;
396 in++;
397 break;
398
399 case '.':
400
401 if (in+
2 >= in_len) {
402
403
404
405 *out_ptr++ = *in_ptr++;
406 goto done;
407 }
408
409
410 if (in_ptr[
2] ==
'/') {
411
412 in_ptr +=
2;
413 in +=
2;
414 break;
415 }
416
417 if (in_ptr[
2] !=
'.') {
418
419 *out_ptr++ = *in_ptr++;
420 in++;
421 break;
422 }
423
424
425
426
427 if (in+
3 < in_len && in_ptr[
3] !=
'/' && in_ptr[
3] !=
';') {
428
429 *out_ptr++ = *in_ptr++;
430 in++;
431 }
432 else {
433
434 if (out_ptr == canonPath) {
435
436 success =
PR_FALSE;
437 goto done;
438 }
439
440
441 for (out_ptr--;
442 out_ptr != canonPath && out_ptr[
0] !=
'/';
443 out_ptr--);
444
445
446
447
448 if(in+
3 == in_len)
449 out_ptr++;
450
451
452 in_ptr +=
3;
453 in +=
3;
454 }
455 break;
456
457 default:
458
459 if (out_ptr == canonPath || *(out_ptr-
1) !=
'/')
460 *out_ptr++ = *in_ptr;
461 in_ptr++; in++;
462 break;
463 }
464 }
465
466 done:
467 int canonLen =
0;
468
469 if (success) {
470
471 canonLen = out_ptr - canonPath;
472 canonPath[canonLen] =
'\0';
473 }
else {
474
475 pool_free(pool, canonPath);
476 canonPath =
NULL;
477 }
478
479 if (pcanonlen)
480 *pcanonlen = canonLen;
481
482 return canonPath;
483 }
484
485
486
487
488 NSAPI_PUBLIC char* util_canonicalize_redirect(
pool_handle_t *pool,
const char *baseUri,
const char *newUri)
489 {
490
491
492 if (*newUri ==
'/')
493 return util_canonicalize_uri(pool, newUri, strlen(newUri),
NULL);
494
495 int bLen = strlen(baseUri);
496 if (bLen >
0 && baseUri[bLen -
1] !=
'/') {
497 while (bLen >
0 && baseUri[bLen -
1] !=
'/')
498 bLen--;
499 }
500
501 int pLen = strlen(newUri) + bLen +
1;
502 char *pUri = (
char *)pool_malloc(pool, pLen +
1);
503 if (!pUri)
504 return PR_FALSE;
505
506 memcpy(pUri, baseUri, bLen);
507 pUri[bLen] =
'/';
508 strcpy(pUri + bLen +
1, newUri);
509
510 char *rval = util_canonicalize_uri(pool, pUri, pLen,
NULL);
511 pool_free(pool, pUri);
512
513 return rval;
514 }
515
516
517
518
519 NSAPI_PUBLIC char *util_host_port_suffix(
char *h)
520 {
521 return (
char *)util_host_port_suffix((
const char *)h);
522 }
523
524 const char *util_host_port_suffix(
const char *h)
525 {
526
527
528
529
530
531
532
533
534 if (h ==
NULL)
535 return h;
536
537 for (;;) {
538
539 for (;;) {
540 register char c = *h;
541
542 if (c ==
'\0')
543 return NULL;
544
545 if (c ==
'/')
546 return NULL;
547
548 if (c ==
':')
549 return h;
550
551 if (c ==
'[')
552 break;
553
554 h++;
555 }
556
557
558 while (*h !=
'\0' && *h !=
']')
559 h++;
560 }
561 }
562