~ubuntu-branches/ubuntu/wily/libspiff/wily

« back to all changes in this revision

Viewing changes to win32/uriparser/UriCommon.c

  • Committer: Bazaar Package Importer
  • Author(s): Adeodato Simó
  • Date: 2007-10-11 14:44:38 UTC
  • Revision ID: james.westby@ubuntu.com-20071011144438-zpl4gtvl3bf2ocnx
Tags: upstream-0.8.2
Import upstream version 0.8.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * uriparser - RFC 3986 URI parsing library
 
3
 *
 
4
 * Copyright (C) 2007, Weijia Song <songweijia@gmail.com>
 
5
 * Copyright (C) 2007, Sebastian Pipping <webmaster@hartwork.org>
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution  and use in source and binary forms, with or without
 
9
 * modification,  are permitted provided that the following conditions
 
10
 * are met:
 
11
 *
 
12
 *     * Redistributions   of  source  code  must  retain  the   above
 
13
 *       copyright  notice, this list of conditions and the  following
 
14
 *       disclaimer.
 
15
 *
 
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.
 
20
 *
 
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
 
24
 *       permission.
 
25
 *
 
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.
 
38
 */
 
39
 
 
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"
 
46
# undef URI_PASS_ANSI
 
47
# define URI_PASS_UNICODE 1
 
48
# include "UriCommon.c"
 
49
# undef URI_PASS_UNICODE
 
50
#else
 
51
# ifdef URI_PASS_ANSI
 
52
#  include <uriparser/UriDefsAnsi.h>
 
53
# else
 
54
#  include <uriparser/UriDefsUnicode.h>
 
55
#  include <wchar.h>
 
56
# endif
 
57
 
 
58
 
 
59
 
 
60
#ifndef URI_DOXYGEN
 
61
# include <uriparser/Uri.h>
 
62
# include "UriCommon.h"
 
63
#endif
 
64
 
 
65
 
 
66
 
 
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("..");
 
70
 
 
71
 
 
72
 
 
73
void URI_FUNC(ResetUri)(URI_TYPE(Uri) * uri) {
 
74
        memset(uri, 0, sizeof(URI_TYPE(Uri)));
 
75
}
 
76
 
 
77
 
 
78
 
 
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)) {
 
83
                return URI_TRUE;
 
84
        }
 
85
 
 
86
        walker = uri->pathHead;
 
87
        walker->reserved = NULL; /* Prev pointer */
 
88
        do {
 
89
                int len = (int)(walker->text.afterLast - walker->text.first);
 
90
                switch (len) {
 
91
                case 1:
 
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;
 
96
 
 
97
                                /* Last segment? */
 
98
                                if (walker->next != NULL) {
 
99
                                        /* Not last segment */
 
100
                                        walker->next->reserved = prev;
 
101
 
 
102
                                        if (prev == NULL) {
 
103
                                                /* First but not last segment */
 
104
                                                uri->pathHead = walker->next;
 
105
                                        } else {
 
106
                                                /* Middle segment */
 
107
                                                prev->next = walker->next;
 
108
                                        }
 
109
 
 
110
                                        if (uri->owner) {
 
111
                                                free((URI_CHAR *)walker->text.first);
 
112
                                        }
 
113
                                        free(walker);
 
114
                                } else {
 
115
                                        /* Last segment */
 
116
                                        if (prev == NULL) {
 
117
                                                /* Last and first */
 
118
                                                if (uri->owner) {
 
119
                                                        free((URI_CHAR *)walker->text.first);
 
120
                                                }
 
121
                                                free(walker);
 
122
 
 
123
                                                uri->pathHead = NULL;
 
124
                                                uri->pathTail = NULL;
 
125
                                        } else {
 
126
                                                /* Last but not first, replace "." with empty segment to represent trailing slash */
 
127
                                                if (uri->owner) {
 
128
                                                        free((URI_CHAR *)walker->text.first);
 
129
                                                }
 
130
                                                walker->text.first = URI_FUNC(SafeToPointTo);
 
131
                                                walker->text.afterLast = URI_FUNC(SafeToPointTo);
 
132
                                        }
 
133
                                }
 
134
 
 
135
                                walker = nextBackup;
 
136
                        } else {
 
137
                                if (walker->next != NULL) {
 
138
                                        walker->next->reserved = walker;
 
139
                                } else {
 
140
                                        /* Last segment -> update tail */
 
141
                                        uri->pathTail = walker;
 
142
                                }
 
143
                                walker = walker->next;
 
144
                        }
 
145
                        break;
 
146
 
 
147
                case 2:
 
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;
 
154
                                if (prev != NULL) {
 
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;
 
162
                                                } else {
 
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) {
 
166
                                                                if (uri->owner) {
 
167
                                                                        free((URI_CHAR *)walker->text.first);
 
168
                                                                }
 
169
                                                                free(walker);
 
170
 
 
171
                                                                if (uri->owner) {
 
172
                                                                        free((URI_CHAR *)prev->text.first);
 
173
                                                                }
 
174
                                                                free(prev);
 
175
 
 
176
                                                                return URI_FALSE; /* Raises malloc error */
 
177
                                                        }
 
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;
 
183
                                                }
 
184
 
 
185
                                                if (uri->owner) {
 
186
                                                        free((URI_CHAR *)walker->text.first);
 
187
                                                }
 
188
                                                free(walker);
 
189
 
 
190
                                                if (uri->owner) {
 
191
                                                        free((URI_CHAR *)prev->text.first);
 
192
                                                }
 
193
                                                free(prev);
 
194
 
 
195
                                                walker = nextBackup;
 
196
                                        } else {
 
197
                                                /* Prev is the first segment */
 
198
                                                uri->pathHead = walker->next;
 
199
                                                if (walker->next != NULL) {
 
200
                                                        walker->next->reserved = NULL;
 
201
                                                } else {
 
202
                                                        /* Last segment -> update tail */
 
203
                                                        uri->pathTail = NULL;
 
204
                                                }
 
205
 
 
206
                                                if (uri->owner) {
 
207
                                                        free((URI_CHAR *)walker->text.first);
 
208
                                                }
 
209
                                                free(walker);
 
210
 
 
211
                                                if (uri->owner) {
 
212
                                                        free((URI_CHAR *)prev->text.first);
 
213
                                                }
 
214
                                                free(prev);
 
215
 
 
216
                                                walker = nextBackup;
 
217
                                        }
 
218
                                } else {
 
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;
 
224
                                        } else {
 
225
                                                /* Last segment -> update tail */
 
226
                                                uri->pathTail = NULL;
 
227
                                        }
 
228
 
 
229
                                        if (uri->owner) {
 
230
                                                free((URI_CHAR *)walker->text.first);
 
231
                                        }
 
232
                                        free(walker);
 
233
 
 
234
                                        walker = nextBackup;
 
235
                                }
 
236
                        } else {
 
237
                                if (walker->next != NULL) {
 
238
                                        walker->next->reserved = walker;
 
239
                                } else {
 
240
                                        /* Last segment -> update tail */
 
241
                                        uri->pathTail = walker;
 
242
                                }
 
243
                                walker = walker->next;
 
244
                        }
 
245
                        break;
 
246
 
 
247
                default:
 
248
                        if (walker->next != NULL) {
 
249
                                walker->next->reserved = walker;
 
250
                        } else {
 
251
                                /* Last segment -> update tail */
 
252
                                uri->pathTail = walker;
 
253
                        }
 
254
                        walker = walker->next;
 
255
                        break;
 
256
 
 
257
                }
 
258
        } while (walker != NULL);
 
259
 
 
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)) {
 
264
                free(uri->pathHead);
 
265
                uri->pathHead = NULL;
 
266
                uri->pathTail = NULL;
 
267
        }
 
268
 
 
269
        return URI_TRUE;
 
270
}
 
271
 
 
272
 
 
273
 
 
274
unsigned char URI_FUNC(HexdigToInt)(URI_CHAR hexdig) {
 
275
        switch (hexdig) {
 
276
        case _UT('0'):
 
277
        case _UT('1'):
 
278
        case _UT('2'):
 
279
        case _UT('3'):
 
280
        case _UT('4'):
 
281
        case _UT('5'):
 
282
        case _UT('6'):
 
283
        case _UT('7'):
 
284
        case _UT('8'):
 
285
        case _UT('9'):
 
286
                return (unsigned char)(9 + hexdig - _UT('9'));
 
287
 
 
288
        case _UT('a'):
 
289
        case _UT('b'):
 
290
        case _UT('c'):
 
291
        case _UT('d'):
 
292
        case _UT('e'):
 
293
        case _UT('f'):
 
294
                return (unsigned char)(15 + hexdig - _UT('f'));
 
295
 
 
296
        case _UT('A'):
 
297
        case _UT('B'):
 
298
        case _UT('C'):
 
299
        case _UT('D'):
 
300
        case _UT('E'):
 
301
        case _UT('F'):
 
302
                return (unsigned char)(15 + hexdig - _UT('F'));
 
303
 
 
304
        default:
 
305
                return 0;
 
306
        }
 
307
}
 
308
 
 
309
 
 
310
 
 
311
URI_CHAR URI_FUNC(HexToLetter)(unsigned int value) {
 
312
        switch (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');
 
323
 
 
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');
 
332
        }
 
333
}
 
334
 
 
335
 
 
336
 
 
337
/* Checks if a URI has the host component set. */
 
338
UriBool URI_FUNC(IsHostSet)(const URI_TYPE(Uri) * uri) {
 
339
        return (uri != NULL)
 
340
                        && ((uri->hostText.first != NULL)
 
341
                                || (uri->hostData.ip4 != NULL)
 
342
                                || (uri->hostData.ip6 != NULL)
 
343
                                || (uri->hostData.ipFuture.first != NULL)
 
344
                        );
 
345
}
 
346
 
 
347
 
 
348
 
 
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;
 
356
        } else {
 
357
                /* Copy list but not the text contained */
 
358
                URI_TYPE(PathSegment) * sourceWalker = source->pathHead;
 
359
                URI_TYPE(PathSegment) * destPrev = NULL;
 
360
                do {
 
361
                        URI_TYPE(PathSegment) * cur = malloc(sizeof(URI_TYPE(PathSegment)));
 
362
                        if (cur == NULL) {
 
363
                                /* Fix broken list */
 
364
                                if (destPrev != NULL) {
 
365
                                        destPrev->next = NULL;
 
366
                                }
 
367
                                return URI_FALSE; /* Raises malloc error */
 
368
                        }
 
369
 
 
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;
 
376
                        } else {
 
377
                                destPrev->next = cur;
 
378
                        }
 
379
                        destPrev = cur;
 
380
                        sourceWalker = sourceWalker->next;
 
381
                } while (sourceWalker != NULL);
 
382
                dest->pathTail = destPrev;
 
383
                dest->pathTail->next = NULL;
 
384
        }
 
385
 
 
386
        dest->absolutePath = source->absolutePath;
 
387
        return URI_TRUE;
 
388
}
 
389
 
 
390
 
 
391
 
 
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      */
 
397
 
 
398
        /* Copy userInfo */
 
399
        dest->userInfo = source->userInfo;
 
400
 
 
401
        /* Copy hostText */
 
402
        dest->hostText = source->hostText;
 
403
 
 
404
        /* Copy hostData */
 
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 */
 
409
                }
 
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 */
 
419
                }
 
420
                *(dest->hostData.ip6) = *(source->hostData.ip6);
 
421
                dest->hostData.ipFuture.first = NULL;
 
422
                dest->hostData.ipFuture.afterLast = NULL;
 
423
        } else {
 
424
                dest->hostData.ip4 = NULL;
 
425
                dest->hostData.ip6 = NULL;
 
426
                dest->hostData.ipFuture = source->hostData.ipFuture;
 
427
        }
 
428
 
 
429
        /* Copy portText */
 
430
        dest->portText = source->portText;
 
431
 
 
432
        return URI_TRUE;
 
433
}
 
434
 
 
435
 
 
436
 
 
437
UriBool URI_FUNC(FixAmbiguity)(URI_TYPE(Uri) * uri) {
 
438
        URI_TYPE(PathSegment) * segment;
 
439
 
 
440
        if (    /* Case 1: absolute path, empty first segment */
 
441
                        (uri->absolutePath
 
442
                        && (uri->pathHead != NULL)
 
443
                        && (uri->pathHead->text.afterLast == uri->pathHead->text.first))
 
444
 
 
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))) {
 
451
                /* NOOP */
 
452
        } else {
 
453
                return URI_TRUE;
 
454
        }
 
455
 
 
456
        segment = malloc(1 * sizeof(URI_TYPE(PathSegment)));
 
457
        if (segment == NULL) {
 
458
                return URI_FALSE; /* Raises malloc error */
 
459
        }
 
460
 
 
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;
 
466
        return URI_TRUE;
 
467
}
 
468
 
 
469
 
 
470
 
 
471
#endif