2
* uriparser - RFC 3986 URI parsing library
4
* Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
5
* Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
12
* * Redistributions of source code must retain the above
13
* copyright notice, this list of conditions and the following
16
* * Redistributions in binary form must reproduce the above
17
* copyright notice, this list of conditions and the following
18
* disclaimer in the documentation and/or other materials
19
* provided with the distribution.
21
* * Neither the name of the <ORGANIZATION> nor the names of its
22
* contributors may be used to endorse or promote products
23
* derived from this software without specific prior written
26
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
32
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
33
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
35
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
36
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
37
* OF THE POSSIBILITY OF SUCH DAMAGE.
40
/* What encodings are enabled? */
41
#include <uriparser/UriDefsConfig.h>
42
#if (!defined(URI_PASS_ANSI) && !defined(URI_PASS_UNICODE))
43
/* Include SELF twice */
44
# define URI_PASS_ANSI 1
45
# include "UriCommon.c"
47
# define URI_PASS_UNICODE 1
48
# include "UriCommon.c"
49
# undef URI_PASS_UNICODE
52
# include <uriparser/UriDefsAnsi.h>
54
# include <uriparser/UriDefsUnicode.h>
61
# include <uriparser/Uri.h>
62
# include "UriCommon.h"
67
/*extern*/ const URI_CHAR * const URI_FUNC(SafeToPointTo) = _UT("X");
68
/*extern*/ const URI_CHAR * const URI_FUNC(ConstPwd) = _UT(".");
69
/*extern*/ const URI_CHAR * const URI_FUNC(ConstParent) = _UT("..");
73
void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) {
74
memset(uri, 0, sizeof(URI_TYPE(Uri)));
79
/* Properly removes "." and ".." path segments */
80
UriBool URI_FUNC(RemoveDotSegments)(URI_TYPE(Uri) * uri) {
81
URI_TYPE(PathSegment) * walker;
82
if ((uri == NULL) || (uri->pathHead == NULL)) {
86
walker = uri->pathHead;
87
walker->reserved = NULL; /* Prev pointer */
89
int len = (int)(walker->text.afterLast - walker->text.first);
92
if ((walker->text.first)[0] == _UT('.')) {
93
/* Path "." -> remove this segment */
94
URI_TYPE(PathSegment) * const prev = walker->reserved;
95
URI_TYPE(PathSegment) * const nextBackup = walker->next;
98
if (walker->next != NULL) {
99
/* Not last segment */
100
walker->next->reserved = prev;
103
/* First but not last segment */
104
uri->pathHead = walker->next;
107
prev->next = walker->next;
111
free((URI_CHAR *)walker->text.first);
119
free((URI_CHAR *)walker->text.first);
123
uri->pathHead = NULL;
124
uri->pathTail = NULL;
126
/* Last but not first, replace "." with empty segment to represent trailing slash */
128
free((URI_CHAR *)walker->text.first);
130
walker->text.first = URI_FUNC(SafeToPointTo);
131
walker->text.afterLast = URI_FUNC(SafeToPointTo);
137
if (walker->next != NULL) {
138
walker->next->reserved = walker;
140
/* Last segment -> update tail */
141
uri->pathTail = walker;
143
walker = walker->next;
148
if (((walker->text.first)[0] == _UT('.'))
149
&& ((walker->text.first)[1] == _UT('.'))) {
150
/* Path ".." -> remove this and the previous segment */
151
URI_TYPE(PathSegment) * const prev = walker->reserved;
152
URI_TYPE(PathSegment) * prevPrev;
153
URI_TYPE(PathSegment) * const nextBackup = walker->next;
155
/* Not first segment */
156
prevPrev = prev->reserved;
157
if (prevPrev != NULL) {
158
/* Not even prev is the first one */
159
prevPrev->next = walker->next;
160
if (walker->next != NULL) {
161
walker->next->reserved = prevPrev;
163
/* Last segment -> insert "" segment to represent trailing slash, update tail */
164
URI_TYPE(PathSegment) * const segment = malloc(1 * sizeof(URI_TYPE(PathSegment)));
165
if (segment == NULL) {
167
free((URI_CHAR *)walker->text.first);
172
free((URI_CHAR *)prev->text.first);
176
return URI_FALSE; /* Raises malloc error */
178
memset(segment, 0, sizeof(URI_TYPE(PathSegment)));
179
segment->text.first = URI_FUNC(SafeToPointTo);
180
segment->text.afterLast = URI_FUNC(SafeToPointTo);
181
prevPrev->next = segment;
182
uri->pathTail = segment;
186
free((URI_CHAR *)walker->text.first);
191
free((URI_CHAR *)prev->text.first);
197
/* Prev is the first segment */
198
uri->pathHead = walker->next;
199
if (walker->next != NULL) {
200
walker->next->reserved = NULL;
202
/* Last segment -> update tail */
203
uri->pathTail = NULL;
207
free((URI_CHAR *)walker->text.first);
212
free((URI_CHAR *)prev->text.first);
219
URI_TYPE(PathSegment) * const nextBackup = walker->next;
220
/* First segment -> update head pointer */
221
uri->pathHead = walker->next;
222
if (walker->next != NULL) {
223
walker->next->reserved = NULL;
225
/* Last segment -> update tail */
226
uri->pathTail = NULL;
230
free((URI_CHAR *)walker->text.first);
237
if (walker->next != NULL) {
238
walker->next->reserved = walker;
240
/* Last segment -> update tail */
241
uri->pathTail = walker;
243
walker = walker->next;
248
if (walker->next != NULL) {
249
walker->next->reserved = walker;
251
/* Last segment -> update tail */
252
uri->pathTail = walker;
254
walker = walker->next;
258
} while (walker != NULL);
260
/* Fix path if only one empty segment */
261
if ((uri->pathHead != NULL)
262
&& (uri->pathHead->next == NULL)
263
&& (uri->pathHead->text.first == uri->pathHead->text.afterLast)) {
265
uri->pathHead = NULL;
266
uri->pathTail = NULL;
274
unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig) {
286
return (unsigned char)(9 + hexdig - _UT('9'));
294
return (unsigned char)(15 + hexdig - _UT('f'));
302
return (unsigned char)(15 + hexdig - _UT('F'));
311
URI_CHAR URI_FUNC(HexToLetter)(unsigned int value) {
313
case 0: return _UT('0');
314
case 1: return _UT('1');
315
case 2: return _UT('2');
316
case 3: return _UT('3');
317
case 4: return _UT('4');
318
case 5: return _UT('5');
319
case 6: return _UT('6');
320
case 7: return _UT('7');
321
case 8: return _UT('8');
322
case 9: return _UT('9');
324
/* Uppercase recommended in section 2.1. of RFC 3986 *
325
* http://tools.ietf.org/html/rfc3986#section-2.1 */
326
case 10: return _UT('A');
327
case 11: return _UT('B');
328
case 12: return _UT('C');
329
case 13: return _UT('D');
330
case 14: return _UT('E');
331
default: return _UT('F');
337
/* Checks if a URI has the host component set. */
338
UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri) {
340
&& ((uri->hostText.first != NULL)
341
|| (uri->hostData.ip4 != NULL)
342
|| (uri->hostData.ip6 != NULL)
343
|| (uri->hostData.ipFuture.first != NULL)
349
/* Copies the path segment list from one URI to another. */
350
UriBool URI_FUNC(CopyPath)(URI_TYPE(Uri) * dest,
351
const URI_TYPE(Uri) * source) {
352
if (source->pathHead == NULL) {
353
/* No path component */
354
dest->pathHead = NULL;
355
dest->pathTail = NULL;
357
/* Copy list but not the text contained */
358
URI_TYPE(PathSegment) * sourceWalker = source->pathHead;
359
URI_TYPE(PathSegment) * destPrev = NULL;
361
URI_TYPE(PathSegment) * cur = malloc(sizeof(URI_TYPE(PathSegment)));
363
/* Fix broken list */
364
if (destPrev != NULL) {
365
destPrev->next = NULL;
367
return URI_FALSE; /* Raises malloc error */
370
/* From this functions usage we know that *
371
* the dest URI cannot be uri->owner */
372
cur->text = sourceWalker->text;
373
if (destPrev == NULL) {
374
/* First segment ever */
375
dest->pathHead = cur;
377
destPrev->next = cur;
380
sourceWalker = sourceWalker->next;
381
} while (sourceWalker != NULL);
382
dest->pathTail = destPrev;
383
dest->pathTail->next = NULL;
386
dest->absolutePath = source->absolutePath;
392
/* Copies the authority part of an URI over to another. */
393
UriBool URI_FUNC(CopyAuthority)(URI_TYPE(Uri) * dest,
394
const URI_TYPE(Uri) * source) {
395
/* From this functions usage we know that *
396
* the dest URI cannot be uri->owner */
399
dest->userInfo = source->userInfo;
402
dest->hostText = source->hostText;
405
if (source->hostData.ip4 != NULL) {
406
dest->hostData.ip4 = malloc(sizeof(UriIp4));
407
if (dest->hostData.ip4 == NULL) {
408
return URI_FALSE; /* Raises malloc error */
410
*(dest->hostData.ip4) = *(source->hostData.ip4);
411
dest->hostData.ip6 = NULL;
412
dest->hostData.ipFuture.first = NULL;
413
dest->hostData.ipFuture.afterLast = NULL;
414
} else if (source->hostData.ip6 != NULL) {
415
dest->hostData.ip4 = NULL;
416
dest->hostData.ip6 = malloc(sizeof(UriIp6));
417
if (dest->hostData.ip6 == NULL) {
418
return URI_FALSE; /* Raises malloc error */
420
*(dest->hostData.ip6) = *(source->hostData.ip6);
421
dest->hostData.ipFuture.first = NULL;
422
dest->hostData.ipFuture.afterLast = NULL;
424
dest->hostData.ip4 = NULL;
425
dest->hostData.ip6 = NULL;
426
dest->hostData.ipFuture = source->hostData.ipFuture;
430
dest->portText = source->portText;
437
UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri) {
438
URI_TYPE(PathSegment) * segment;
440
if ( /* Case 1: absolute path, empty first segment */
442
&& (uri->pathHead != NULL)
443
&& (uri->pathHead->text.afterLast == uri->pathHead->text.first))
445
/* Case 2: relative path, empty first and second segment */
446
|| (!uri->absolutePath
447
&& (uri->pathHead != NULL)
448
&& (uri->pathHead->next != NULL)
449
&& (uri->pathHead->text.afterLast == uri->pathHead->text.first)
450
&& (uri->pathHead->next->text.afterLast == uri->pathHead->next->text.first))) {
456
segment = malloc(1 * sizeof(URI_TYPE(PathSegment)));
457
if (segment == NULL) {
458
return URI_FALSE; /* Raises malloc error */
461
/* Insert "." segment in front */
462
segment->next = uri->pathHead;
463
segment->text.first = URI_FUNC(ConstPwd);
464
segment->text.afterLast = URI_FUNC(ConstPwd) + 1;
465
uri->pathHead = segment;