summaryrefslogtreecommitdiffstats
path: root/plugins/uriparser/UriRecompose.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/uriparser/UriRecompose.c')
-rw-r--r--plugins/uriparser/UriRecompose.c577
1 files changed, 577 insertions, 0 deletions
diff --git a/plugins/uriparser/UriRecompose.c b/plugins/uriparser/UriRecompose.c
new file mode 100644
index 0000000..09daee0
--- /dev/null
+++ b/plugins/uriparser/UriRecompose.c
@@ -0,0 +1,577 @@
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# ifdef URI_ENABLE_ANSI
45# define URI_PASS_ANSI 1
46# include "UriRecompose.c"
47# undef URI_PASS_ANSI
48# endif
49# ifdef URI_ENABLE_UNICODE
50# define URI_PASS_UNICODE 1
51# include "UriRecompose.c"
52# undef URI_PASS_UNICODE
53# endif
54#else
55# ifdef URI_PASS_ANSI
56# include <uriparser/UriDefsAnsi.h>
57# else
58# include <uriparser/UriDefsUnicode.h>
59# include <wchar.h>
60# endif
61
62
63
64#ifndef URI_DOXYGEN
65# include <uriparser/Uri.h>
66# include "UriCommon.h"
67#endif
68
69
70
71static int URI_FUNC(ToStringEngine)(URI_CHAR * dest, const URI_TYPE(Uri) * uri,
72 int maxChars, int * charsWritten, int * charsRequired);
73
74
75
76int URI_FUNC(ToStringCharsRequired)(const URI_TYPE(Uri) * uri,
77 int * charsRequired) {
78 const int MAX_CHARS = ((unsigned int)-1) >> 1;
79 return URI_FUNC(ToStringEngine)(NULL, uri, MAX_CHARS, NULL, charsRequired);
80}
81
82
83
84int URI_FUNC(ToString)(URI_CHAR * dest, const URI_TYPE(Uri) * uri,
85 int maxChars, int * charsWritten) {
86 return URI_FUNC(ToStringEngine)(dest, uri, maxChars, charsWritten, NULL);
87}
88
89
90
91static URI_INLINE int URI_FUNC(ToStringEngine)(URI_CHAR * dest,
92 const URI_TYPE(Uri) * uri, int maxChars, int * charsWritten,
93 int * charsRequired) {
94 int written = 0;
95 if ((uri == NULL) || ((dest == NULL) && (charsRequired == NULL))) {
96 if (charsWritten != NULL) {
97 *charsWritten = 0;
98 }
99 return URI_ERROR_NULL;
100 }
101
102 if (maxChars < 1) {
103 if (charsWritten != NULL) {
104 *charsWritten = 0;
105 }
106 return URI_ERROR_TOSTRING_TOO_LONG;
107 }
108 maxChars--; /* So we don't have to substract 1 for '\0' all the time */
109
110 /* [01/19] result = "" */
111 if (dest != NULL) {
112 dest[0] = _UT('\0');
113 } else {
114 (*charsRequired) = 0;
115 }
116 /* [02/19] if defined(scheme) then */
117 if (uri->scheme.first != NULL) {
118 /* [03/19] append scheme to result; */
119 const int charsToWrite
120 = (int)(uri->scheme.afterLast - uri->scheme.first);
121 if (dest != NULL) {
122 if (written + charsToWrite <= maxChars) {
123 memcpy(dest + written, uri->scheme.first,
124 charsToWrite * sizeof(URI_CHAR));
125 written += charsToWrite;
126 } else {
127 dest[0] = _UT('\0');
128 if (charsWritten != NULL) {
129 *charsWritten = 0;
130 }
131 return URI_ERROR_TOSTRING_TOO_LONG;
132 }
133 } else {
134 (*charsRequired) += charsToWrite;
135 }
136 /* [04/19] append ":" to result; */
137 if (dest != NULL) {
138 if (written + 1 <= maxChars) {
139 memcpy(dest + written, _UT(":"),
140 1 * sizeof(URI_CHAR));
141 written += 1;
142 } else {
143 dest[0] = _UT('\0');
144 if (charsWritten != NULL) {
145 *charsWritten = 0;
146 }
147 return URI_ERROR_TOSTRING_TOO_LONG;
148 }
149 } else {
150 (*charsRequired) += 1;
151 }
152 /* [05/19] endif; */
153 }
154 /* [06/19] if defined(authority) then */
155 if (URI_FUNC(IsHostSet)(uri)) {
156 /* [07/19] append "//" to result; */
157 if (dest != NULL) {
158 if (written + 2 <= maxChars) {
159 memcpy(dest + written, _UT("//"),
160 2 * sizeof(URI_CHAR));
161 written += 2;
162 } else {
163 dest[0] = _UT('\0');
164 if (charsWritten != NULL) {
165 *charsWritten = 0;
166 }
167 return URI_ERROR_TOSTRING_TOO_LONG;
168 }
169 } else {
170 (*charsRequired) += 2;
171 }
172 /* [08/19] append authority to result; */
173 /* UserInfo */
174 if (uri->userInfo.first != NULL) {
175 const int charsToWrite = (int)(uri->userInfo.afterLast - uri->userInfo.first);
176 if (dest != NULL) {
177 if (written + charsToWrite <= maxChars) {
178 memcpy(dest + written, uri->userInfo.first,
179 charsToWrite * sizeof(URI_CHAR));
180 written += charsToWrite;
181 } else {
182 dest[0] = _UT('\0');
183 if (charsWritten != NULL) {
184 *charsWritten = 0;
185 }
186 return URI_ERROR_TOSTRING_TOO_LONG;
187 }
188
189 if (written + 1 <= maxChars) {
190 memcpy(dest + written, _UT("@"),
191 1 * sizeof(URI_CHAR));
192 written += 1;
193 } else {
194 dest[0] = _UT('\0');
195 if (charsWritten != NULL) {
196 *charsWritten = 0;
197 }
198 return URI_ERROR_TOSTRING_TOO_LONG;
199 }
200 } else {
201 (*charsRequired) += charsToWrite + 1;
202 }
203 }
204
205 /* Host */
206 if (uri->hostData.ip4 != NULL) {
207 /* IPv4 */
208 int i = 0;
209 for (; i < 4; i++) {
210 const unsigned char value = uri->hostData.ip4->data[i];
211 const int charsToWrite = (value > 99) ? 3 : ((value > 9) ? 2 : 1);
212 if (dest != NULL) {
213 if (written + charsToWrite <= maxChars) {
214 URI_CHAR text[4];
215 if (value > 99) {
216 text[0] = _UT('0') + (value / 100);
217 text[1] = _UT('0') + ((value % 100) / 10);
218 text[2] = _UT('0') + (value % 10);
219 } else if (value > 9) {
220 text[0] = _UT('0') + (value / 10);
221 text[1] = _UT('0') + (value % 10);
222 } else {
223 text[0] = _UT('0') + value;
224 }
225 text[charsToWrite] = _UT('\0');
226 memcpy(dest + written, text, charsToWrite * sizeof(URI_CHAR));
227 written += charsToWrite;
228 } else {
229 dest[0] = _UT('\0');
230 if (charsWritten != NULL) {
231 *charsWritten = 0;
232 }
233 return URI_ERROR_TOSTRING_TOO_LONG;
234 }
235 if (i < 3) {
236 if (written + 1 <= maxChars) {
237 memcpy(dest + written, _UT("."),
238 1 * sizeof(URI_CHAR));
239 written += 1;
240 } else {
241 dest[0] = _UT('\0');
242 if (charsWritten != NULL) {
243 *charsWritten = 0;
244 }
245 return URI_ERROR_TOSTRING_TOO_LONG;
246 }
247 }
248 } else {
249 (*charsRequired) += charsToWrite + 1;
250 }
251 }
252 } else if (uri->hostData.ip6 != NULL) {
253 /* IPv6 */
254 int i = 0;
255 if (dest != NULL) {
256 if (written + 1 <= maxChars) {
257 memcpy(dest + written, _UT("["),
258 1 * sizeof(URI_CHAR));
259 written += 1;
260 } else {
261 dest[0] = _UT('\0');
262 if (charsWritten != NULL) {
263 *charsWritten = 0;
264 }
265 return URI_ERROR_TOSTRING_TOO_LONG;
266 }
267 } else {
268 (*charsRequired) += 1;
269 }
270
271 for (; i < 16; i++) {
272 const unsigned char value = uri->hostData.ip6->data[i];
273 if (dest != NULL) {
274 if (written + 2 <= maxChars) {
275 URI_CHAR text[3];
276 text[0] = URI_FUNC(HexToLetterEx)(value / 16, URI_FALSE);
277 text[1] = URI_FUNC(HexToLetterEx)(value % 16, URI_FALSE);
278 text[2] = _UT('\0');
279 memcpy(dest + written, text, 2 * sizeof(URI_CHAR));
280 written += 2;
281 } else {
282 dest[0] = _UT('\0');
283 if (charsWritten != NULL) {
284 *charsWritten = 0;
285 }
286 return URI_ERROR_TOSTRING_TOO_LONG;
287 }
288 } else {
289 (*charsRequired) += 2;
290 }
291 if (((i & 1) == 1) && (i < 15)) {
292 if (dest != NULL) {
293 if (written + 1 <= maxChars) {
294 memcpy(dest + written, _UT(":"),
295 1 * sizeof(URI_CHAR));
296 written += 1;
297 } else {
298 dest[0] = _UT('\0');
299 if (charsWritten != NULL) {
300 *charsWritten = 0;
301 }
302 return URI_ERROR_TOSTRING_TOO_LONG;
303 }
304 } else {
305 (*charsRequired) += 1;
306 }
307 }
308 }
309
310 if (dest != NULL) {
311 if (written + 1 <= maxChars) {
312 memcpy(dest + written, _UT("]"),
313 1 * sizeof(URI_CHAR));
314 written += 1;
315 } else {
316 dest[0] = _UT('\0');
317 if (charsWritten != NULL) {
318 *charsWritten = 0;
319 }
320 return URI_ERROR_TOSTRING_TOO_LONG;
321 }
322 } else {
323 (*charsRequired) += 1;
324 }
325 } else if (uri->hostData.ipFuture.first != NULL) {
326 /* IPvFuture */
327 const int charsToWrite = (int)(uri->hostData.ipFuture.afterLast
328 - uri->hostData.ipFuture.first);
329 if (dest != NULL) {
330 if (written + 1 <= maxChars) {
331 memcpy(dest + written, _UT("["),
332 1 * sizeof(URI_CHAR));
333 written += 1;
334 } else {
335 dest[0] = _UT('\0');
336 if (charsWritten != NULL) {
337 *charsWritten = 0;
338 }
339 return URI_ERROR_TOSTRING_TOO_LONG;
340 }
341
342 if (written + charsToWrite <= maxChars) {
343 memcpy(dest + written, uri->hostData.ipFuture.first, charsToWrite * sizeof(URI_CHAR));
344 written += charsToWrite;
345 } else {
346 dest[0] = _UT('\0');
347 if (charsWritten != NULL) {
348 *charsWritten = 0;
349 }
350 return URI_ERROR_TOSTRING_TOO_LONG;
351 }
352
353 if (written + 1 <= maxChars) {
354 memcpy(dest + written, _UT("]"),
355 1 * sizeof(URI_CHAR));
356 written += 1;
357 } else {
358 dest[0] = _UT('\0');
359 if (charsWritten != NULL) {
360 *charsWritten = 0;
361 }
362 return URI_ERROR_TOSTRING_TOO_LONG;
363 }
364 } else {
365 (*charsRequired) += 1 + charsToWrite + 1;
366 }
367 } else if (uri->hostText.first != NULL) {
368 /* Regname */
369 const int charsToWrite = (int)(uri->hostText.afterLast - uri->hostText.first);
370 if (dest != NULL) {
371 if (written + charsToWrite <= maxChars) {
372 memcpy(dest + written, uri->hostText.first,
373 charsToWrite * sizeof(URI_CHAR));
374 written += charsToWrite;
375 } else {
376 dest[0] = _UT('\0');
377 if (charsWritten != NULL) {
378 *charsWritten = 0;
379 }
380 return URI_ERROR_TOSTRING_TOO_LONG;
381 }
382 } else {
383 (*charsRequired) += charsToWrite;
384 }
385 }
386
387 /* Port */
388 if (uri->portText.first != NULL) {
389 const int charsToWrite = (int)(uri->portText.afterLast - uri->portText.first);
390 if (dest != NULL) {
391 /* Leading ':' */
392 if (written + 1 <= maxChars) {
393 memcpy(dest + written, _UT(":"),
394 1 * sizeof(URI_CHAR));
395 written += 1;
396 } else {
397 dest[0] = _UT('\0');
398 if (charsWritten != NULL) {
399 *charsWritten = 0;
400 }
401 return URI_ERROR_TOSTRING_TOO_LONG;
402 }
403
404 /* Port number */
405 if (written + charsToWrite <= maxChars) {
406 memcpy(dest + written, uri->portText.first,
407 charsToWrite * sizeof(URI_CHAR));
408 written += charsToWrite;
409 } else {
410 dest[0] = _UT('\0');
411 if (charsWritten != NULL) {
412 *charsWritten = 0;
413 }
414 return URI_ERROR_TOSTRING_TOO_LONG;
415 }
416 } else {
417 (*charsRequired) += 1 + charsToWrite;
418 }
419 }
420 /* [09/19] endif; */
421 }
422 /* [10/19] append path to result; */
423 /* Slash needed here? */
424 if (uri->absolutePath || ((uri->pathHead != NULL)
425 && URI_FUNC(IsHostSet)(uri))) {
426 if (dest != NULL) {
427 if (written + 1 <= maxChars) {
428 memcpy(dest + written, _UT("/"),
429 1 * sizeof(URI_CHAR));
430 written += 1;
431 } else {
432 dest[0] = _UT('\0');
433 if (charsWritten != NULL) {
434 *charsWritten = 0;
435 }
436 return URI_ERROR_TOSTRING_TOO_LONG;
437 }
438 } else {
439 (*charsRequired) += 1;
440 }
441 }
442
443 if (uri->pathHead != NULL) {
444 URI_TYPE(PathSegment) * walker = uri->pathHead;
445 do {
446 const int charsToWrite = (int)(walker->text.afterLast - walker->text.first);
447 if (dest != NULL) {
448 if (written + charsToWrite <= maxChars) {
449 memcpy(dest + written, walker->text.first,
450 charsToWrite * sizeof(URI_CHAR));
451 written += charsToWrite;
452 } else {
453 dest[0] = _UT('\0');
454 if (charsWritten != NULL) {
455 *charsWritten = 0;
456 }
457 return URI_ERROR_TOSTRING_TOO_LONG;
458 }
459 } else {
460 (*charsRequired) += charsToWrite;
461 }
462
463 /* Not last segment -> append slash */
464 if (walker->next != NULL) {
465 if (dest != NULL) {
466 if (written + 1 <= maxChars) {
467 memcpy(dest + written, _UT("/"),
468 1 * sizeof(URI_CHAR));
469 written += 1;
470 } else {
471 dest[0] = _UT('\0');
472 if (charsWritten != NULL) {
473 *charsWritten = 0;
474 }
475 return URI_ERROR_TOSTRING_TOO_LONG;
476 }
477 } else {
478 (*charsRequired) += 1;
479 }
480 }
481
482 walker = walker->next;
483 } while (walker != NULL);
484 }
485 /* [11/19] if defined(query) then */
486 if (uri->query.first != NULL) {
487 /* [12/19] append "?" to result; */
488 if (dest != NULL) {
489 if (written + 1 <= maxChars) {
490 memcpy(dest + written, _UT("?"),
491 1 * sizeof(URI_CHAR));
492 written += 1;
493 } else {
494 dest[0] = _UT('\0');
495 if (charsWritten != NULL) {
496 *charsWritten = 0;
497 }
498 return URI_ERROR_TOSTRING_TOO_LONG;
499 }
500 } else {
501 (*charsRequired) += 1;
502 }
503 /* [13/19] append query to result; */
504 {
505 const int charsToWrite
506 = (int)(uri->query.afterLast - uri->query.first);
507 if (dest != NULL) {
508 if (written + charsToWrite <= maxChars) {
509 memcpy(dest + written, uri->query.first,
510 charsToWrite * sizeof(URI_CHAR));
511 written += charsToWrite;
512 } else {
513 dest[0] = _UT('\0');
514 if (charsWritten != NULL) {
515 *charsWritten = 0;
516 }
517 return URI_ERROR_TOSTRING_TOO_LONG;
518 }
519 } else {
520 (*charsRequired) += charsToWrite;
521 }
522 }
523 /* [14/19] endif; */
524 }
525 /* [15/19] if defined(fragment) then */
526 if (uri->fragment.first != NULL) {
527 /* [16/19] append "#" to result; */
528 if (dest != NULL) {
529 if (written + 1 <= maxChars) {
530 memcpy(dest + written, _UT("#"),
531 1 * sizeof(URI_CHAR));
532 written += 1;
533 } else {
534 dest[0] = _UT('\0');
535 if (charsWritten != NULL) {
536 *charsWritten = 0;
537 }
538 return URI_ERROR_TOSTRING_TOO_LONG;
539 }
540 } else {
541 (*charsRequired) += 1;
542 }
543 /* [17/19] append fragment to result; */
544 {
545 const int charsToWrite
546 = (int)(uri->fragment.afterLast - uri->fragment.first);
547 if (dest != NULL) {
548 if (written + charsToWrite <= maxChars) {
549 memcpy(dest + written, uri->fragment.first,
550 charsToWrite * sizeof(URI_CHAR));
551 written += charsToWrite;
552 } else {
553 dest[0] = _UT('\0');
554 if (charsWritten != NULL) {
555 *charsWritten = 0;
556 }
557 return URI_ERROR_TOSTRING_TOO_LONG;
558 }
559 } else {
560 (*charsRequired) += charsToWrite;
561 }
562 }
563 /* [18/19] endif; */
564 }
565 /* [19/19] return result; */
566 if (dest != NULL) {
567 dest[written++] = _UT('\0');
568 if (charsWritten != NULL) {
569 *charsWritten = written;
570 }
571 }
572 return URI_SUCCESS;
573}
574
575
576
577#endif