blob: 88f62a903043cd008ce073d180b4531a023fb2e9 [file] [log] [blame]
Daniel Veillard3dd82e72000-03-20 11:48:04 +00001/**
2 * uri.c: set of generic URI related routines
3 *
4 * Reference: RFC 2396
5 *
6 * See Copyright for the status of this software.
7 *
8 * Daniel.Veillard@w3.org
9 */
10
11#ifdef WIN32
12#define INCLUDE_WINSOCK
13#include "win32config.h"
14#else
15#include "config.h"
16#endif
17
18#include <stdio.h>
19#include <string.h>
20
21#include "xmlmemory.h"
22#include "uri.h"
23
24/**
25 * alpha = lowalpha | upalpha
26 */
27#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x))
28
29
30/**
31 * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
32 * "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
33 * "u" | "v" | "w" | "x" | "y" | "z"
34 */
35
36#define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z'))
37
38/**
39 * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" |
40 * "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" |
41 * "U" | "V" | "W" | "X" | "Y" | "Z"
42 */
43#define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z'))
44
45/**
46 * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
47 */
48
49#define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9'))
50
51/**
52 * alphanum = alpha | digit
53 */
54
55#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x))
56
57/**
58 * he(x) = digit | "A" | "B" | "C" | "D" | "E" | "F" |
59 * "a" | "b" | "c" | "d" | "e" | "f"
60 */
61
62#define IS_HEX(x) ((IS_DIGIT(x)) || (((x) >= 'a') && ((x) <= 'f')) || \
63 (((x) >= 'A') && ((x) <= 'F')))
64
65/**
66 * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
67 */
68
69#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') || \
70 ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') || \
71 ((x) == '(') || ((x) == ')'))
72
73
74/**
75 * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | ","
76 */
77
78#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \
79 ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \
80 ((x) == '+') || ((x) == '$') || ((x) == ','))
81
82/**
83 * unreserved = alphanum | mark
84 */
85
86#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x))
87
88/**
89 * escaped = "%" hex hex
90 */
91
92#define IS_ESCAPED(p) ((*(p) == '%') && (IS_HEX((p)[1])) && \
93 (IS_HEX((p)[2])))
94
95/**
96 * uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" |
97 * "&" | "=" | "+" | "$" | ","
98 */
99#define IS_URIC_NO_SLASH(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) ||\
100 ((*(p) == ';')) || ((*(p) == '?')) || ((*(p) == ':')) ||\
101 ((*(p) == '@')) || ((*(p) == '&')) || ((*(p) == '=')) ||\
102 ((*(p) == '+')) || ((*(p) == '$')) || ((*(p) == ',')))
103
104/**
105 * pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | ","
106 */
107#define IS_PCHAR(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
108 ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||\
109 ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||\
110 ((*(p) == ',')))
111
112/**
113 * rel_segment = 1*( unreserved | escaped |
114 * ";" | "@" | "&" | "=" | "+" | "$" | "," )
115 */
116
117#define IS_SEGMENT(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
118 ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || \
119 ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \
120 ((*(p) == ',')))
121
122/**
123 * scheme = alpha *( alpha | digit | "+" | "-" | "." )
124 */
125
126#define IS_SCHEME(x) ((IS_ALPHA(x)) || (IS_DIGIT(x)) || \
127 ((x) == '+') || ((x) == '-') || ((x) == '.'))
128
129/**
130 * reg_name = 1*( unreserved | escaped | "$" | "," |
131 * ";" | ":" | "@" | "&" | "=" | "+" )
132 */
133
134#define IS_REG_NAME(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
135 ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || \
136 ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || \
137 ((*(p) == '=')) || ((*(p) == '+')))
138
139/**
140 * userinfo = *( unreserved | escaped | ";" | ":" | "&" | "=" |
141 * "+" | "$" | "," )
142 */
143#define IS_USERINFO(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
144 ((*(p) == ';')) || ((*(p) == ':')) || ((*(p) == '&')) || \
145 ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \
146 ((*(p) == ',')))
147
148/**
149 * uric = reserved | unreserved | escaped
150 */
151
152#define IS_URIC(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \
153 (IS_RESERVED(*(p))))
154
155/**
156 * Skip to next pointer char, handle escaped sequences
157 */
158
159#define NEXT(p) ((*p == '%')? p += 3 : p++)
160
161/**
162 *
163
164 *
165 authority = server | reg_name
166 server = [ [ userinfo "@" ] hostport ]
167
168 * reg_name = 1*( unreserved | escaped | "$" | "," |
169 * ";" | ":" | "@" | "&" | "=" | "+" )
170
171 * userinfo = *( unreserved | escaped |
172 * ";" | ":" | "&" | "=" | "+" | "$" | "," )
173
174 hostport = host [ ":" port ]
175 host = hostname | IPv4address
176 hostname = *( domainlabel "." ) toplabel [ "." ]
177 domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
178 toplabel = alpha | alpha *( alphanum | "-" ) alphanum
179 IPv4address = 1*digit "." 1*digit "." 1*digit "." 1*digit
180 port = *digit
181
182 path = [ abs_path | opaque_part ]
183
184
185 */
186
187/**
188 * xmlCreateURI:
189 *
190 * Simply creates an empty xmlURI
191 *
192 * Returns the new structure or NULL in case of error
193 */
194xmlURIPtr
195xmlCreateURI(void) {
196 xmlURIPtr ret;
197
198 ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI));
199 if (ret == NULL) {
200 fprintf(stderr, "xmlCreateURI: out of memory\n");
201 return(NULL);
202 }
203 memset(ret, 0, sizeof(xmlURI));
204 return(ret);
205}
206
207/**
208 * xmlPrintURI:
209 * @stream: a FILE* for the output
210 * @uri: pointer to an xmlURI
211 *
212 * Prints the URI in the stream @steam.
213 */
214void
215xmlPrintURI(FILE *stream, xmlURIPtr uri) {
216 if (uri == NULL) return;
217
218 /* TODO !!! URI encoding ... improper ! */
219 if (uri->scheme != NULL)
220 fprintf(stderr, "%s:", uri->scheme);
221 if (uri->opaque != NULL) {
222 fprintf(stderr, "%s", uri->opaque);
223 } else {
224 if (uri->authority != NULL)
225 fprintf(stderr, "//%s", uri->authority);
226
227 /* TODO !!!
228 if (uri->server != NULL) xmlFree(uri->server);
229 */
230
231 if (uri->path != NULL)
232 fprintf(stderr, "%s", uri->path);
233
234 if (uri->query != NULL)
235 fprintf(stderr, "?%s", uri->query);
236 if (uri->fragment != NULL)
237 fprintf(stderr, "#%s", uri->fragment);
238 }
239}
240
241/**
242 * xmlCleanURI:
243 * @uri: pointer to an xmlURI
244 *
245 * Make sure the xmlURI struct is free of content
246 */
247void
248xmlCleanURI(xmlURIPtr uri) {
249 if (uri == NULL) return;
250
251 if (uri->scheme != NULL) xmlFree(uri->scheme);
252 uri->scheme = NULL;
253 if (uri->server != NULL) xmlFree(uri->server);
254 uri->server = NULL;
255 if (uri->path != NULL) xmlFree(uri->path);
256 uri->path = NULL;
257 if (uri->fragment != NULL) xmlFree(uri->fragment);
258 uri->fragment = NULL;
259 if (uri->opaque != NULL) xmlFree(uri->opaque);
260 uri->opaque = NULL;
261 if (uri->authority != NULL) xmlFree(uri->authority);
262 uri->authority = NULL;
263 if (uri->query != NULL) xmlFree(uri->query);
264 uri->query = NULL;
265}
266
267/**
268 * xmlFreeURI:
269 * @uri: pointer to an xmlURI
270 *
271 * Free up the xmlURI struct
272 */
273void
274xmlFreeURI(xmlURIPtr uri) {
275 if (uri == NULL) return;
276
277 if (uri->scheme != NULL) xmlFree(uri->scheme);
278 if (uri->server != NULL) xmlFree(uri->server);
279 if (uri->path != NULL) xmlFree(uri->path);
280 if (uri->fragment != NULL) xmlFree(uri->fragment);
281 if (uri->opaque != NULL) xmlFree(uri->opaque);
282 if (uri->authority != NULL) xmlFree(uri->authority);
283 if (uri->query != NULL) xmlFree(uri->query);
284 memset(uri, -1, sizeof(xmlURI));
285 xmlFree(uri);
286}
287
288/**
289 * xmlURIUnescape:
290 * @str: the string to unescape
291 * @len: the lenght in bytes to unescape (or <= 0 to indicate full string)
292 * @target: optionnal destination buffer
293 *
294 * Unescaping routine, does not do validity checks !
295 *
296 * Returns an copy of the string, but unescaped
297 */
298char *
299xmlURIUnescape(const char *str, int len, char *target) {
300 char *ret, *out;
301 const char *in;
302
303 if (str == NULL)
304 return(NULL);
305 if (len <= 0) len = strlen(str);
306 if (len <= 0) return(NULL);
307
308 if (target == NULL) {
309 ret = (char *) xmlMalloc(len + 1);
310 if (ret == NULL) {
311 fprintf(stderr, "xmlURIUnescape: out of memory\n");
312 return(NULL);
313 }
314 } else
315 ret = target;
316 in = str;
317 out = ret;
318 while(len > 0) {
319 if (*in == '%') {
320 in++;
321 if ((*in >= '0') && (*in <= '9'))
322 *out = (*in - '0');
323 else if ((*in >= 'a') && (*in <= 'f'))
324 *out = (*in - 'a') + 10;
325 else if ((*in >= 'A') && (*in <= 'F'))
326 *out = (*in - 'A') + 10;
327 in++;
328 if ((*in >= '0') && (*in <= '9'))
329 *out = *out * 16 + (*in - '0');
330 else if ((*in >= 'a') && (*in <= 'f'))
331 *out = *out * 16 + (*in - 'a') + 10;
332 else if ((*in >= 'A') && (*in <= 'F'))
333 *out = *out * 16 + (*in - 'A') + 10;
334 in++;
335 len -= 3;
336 } else {
337 *out++ = *in++;
338 len--;
339 }
340 }
341 *out = 0;
342 return(ret);
343}
344
345
346/**
347 * xmlParseURIFragment:
348 * @uri: pointer to an URI structure
349 * @str: pointer to the string to analyze
350 *
351 * Parse an URI fragment string and fills in the appropriate fields
352 * of the @uri structure.
353 *
354 * fragment = *uric
355 *
356 * Returns 0 or the error code
357 */
358int
359xmlParseURIFragment(xmlURIPtr uri, const char **str) {
360 const char *cur = *str;
361
362 if (str == NULL) return(-1);
363
364 while (IS_URIC(cur)) NEXT(cur);
365 if (uri != NULL) {
366 if (uri->fragment != NULL) xmlFree(uri->fragment);
367 uri->fragment = xmlURIUnescape(*str, cur - *str, NULL);
368 }
369 *str = cur;
370 return(0);
371}
372
373/**
374 * xmlParseURIQuery:
375 * @uri: pointer to an URI structure
376 * @str: pointer to the string to analyze
377 *
378 * Parse the query part of an URI
379 *
380 * query = *uric
381 *
382 * Returns 0 or the error code
383 */
384int
385xmlParseURIQuery(xmlURIPtr uri, const char **str) {
386 const char *cur = *str;
387
388 if (str == NULL) return(-1);
389
390 while (IS_URIC(cur)) NEXT(cur);
391 if (uri != NULL) {
392 if (uri->query != NULL) xmlFree(uri->query);
393 uri->query = xmlURIUnescape(*str, cur - *str, NULL);
394 }
395 *str = cur;
396 return(0);
397}
398
399/**
400 * xmlParseURIScheme:
401 * @uri: pointer to an URI structure
402 * @str: pointer to the string to analyze
403 *
404 * Parse an URI scheme
405 *
406 * scheme = alpha *( alpha | digit | "+" | "-" | "." )
407 *
408 * Returns 0 or the error code
409 */
410int
411xmlParseURIScheme(xmlURIPtr uri, const char **str) {
412 const char *cur;
413
414 if (str == NULL)
415 return(-1);
416
417 cur = *str;
418 if (!IS_ALPHA(*cur))
419 return(2);
420 cur++;
421 while (IS_SCHEME(*cur)) cur++;
422 if (uri != NULL) {
423 if (uri->scheme != NULL) xmlFree(uri->scheme);
424 uri->scheme = xmlURIUnescape(*str, cur - *str, NULL); /* !!! strndup */
425 }
426 *str = cur;
427 return(0);
428}
429
430/**
431 * xmlParseURIOpaquePart:
432 * @uri: pointer to an URI structure
433 * @str: pointer to the string to analyze
434 *
435 * Parse an URI opaque part
436 *
437 * opaque_part = uric_no_slash *uric
438 *
439 * Returns 0 or the error code
440 */
441int
442xmlParseURIOpaquePart(xmlURIPtr uri, const char **str) {
443 const char *cur;
444
445 if (str == NULL)
446 return(-1);
447
448 cur = *str;
449 if (!IS_URIC_NO_SLASH(cur)) {
450 return(3);
451 }
452 NEXT(cur);
453 while (IS_URIC(cur)) NEXT(cur);
454 if (uri != NULL) {
455 if (uri->opaque != NULL) xmlFree(uri->opaque);
456 uri->opaque = xmlURIUnescape(*str, cur - *str, NULL);
457 }
458 *str = cur;
459 return(0);
460}
461
462/**
463 * xmlParseURIRelSegment:
464 * @uri: pointer to an URI structure
465 * @str: pointer to the string to analyze
466 *
467 * Parse an URI relative segment
468 *
469 * rel_segment = 1*( unreserved | escaped | ";" | "@" | "&" | "=" |
470 * "+" | "$" | "," )
471 *
472 * Returns 0 or the error code
473 */
474int
475xmlParseURIRelSegment(xmlURIPtr uri, const char **str) {
476 const char *cur;
477
478 if (str == NULL)
479 return(-1);
480
481 cur = *str;
482 if (!IS_SEGMENT(cur)) {
483 return(3);
484 }
485 NEXT(cur);
486 while (IS_SEGMENT(cur)) NEXT(cur);
487 if (uri != NULL) {
488 if (uri->path != NULL) xmlFree(uri->path);
489 uri->path = xmlURIUnescape(*str, cur - *str, NULL);
490 }
491 *str = cur;
492 return(0);
493}
494
495/**
496 * xmlParseURIPathSegments:
497 * @uri: pointer to an URI structure
498 * @str: pointer to the string to analyze
499 * @slash: should we add a leading slash
500 *
501 * Parse an URI set of path segments
502 *
503 * path_segments = segment *( "/" segment )
504 * segment = *pchar *( ";" param )
505 * param = *pchar
506 *
507 * Returns 0 or the error code
508 */
509int
510xmlParseURIPathSegments(xmlURIPtr uri, const char **str, int slash) {
511 const char *cur;
512
513 if (str == NULL)
514 return(-1);
515
516 cur = *str;
517
518 do {
519 while (IS_PCHAR(cur)) NEXT(cur);
520 if (*cur == ';') {
521 cur++;
522 while (IS_PCHAR(cur)) NEXT(cur);
523 }
524 if (*cur != '/') break;
525 cur++;
526 } while (1);
527 if (uri != NULL) {
528 int len, len2 = 0;
529 char *path;
530
531 /*
532 * Concat the set of path segments to the current path
533 */
534 len = cur - *str;
535 if (slash)
536 len++;
537
538 if (uri->path != NULL) {
539 len2 = strlen(uri->path);
540 len += len2;
541 }
542 path = (char *) xmlMalloc(len + 1);
543 if (path == NULL) {
544 fprintf(stderr, "xmlParseURIPathSegments: out of memory\n");
545 *str = cur;
546 return(-1);
547 }
548 if (uri->path != NULL)
549 memcpy(path, uri->path, len2);
550 if (slash) {
551 path[len2] = '/';
552 len2++;
553 }
554 xmlURIUnescape(*str, cur - *str, &path[len2]);
555 if (uri->path != NULL)
556 xmlFree(uri->path);
557 uri->path = path;
558 }
559 *str = cur;
560 return(0);
561}
562
563/**
564 * xmlParseURIAuthority:
565 * @uri: pointer to an URI structure
566 * @str: pointer to the string to analyze
567 *
568 * Parse the authority part of an URI.
569 *
570 * authority = server | reg_name
571 * server = [ [ userinfo "@" ] hostport ]
572 * reg_name = 1*( unreserved | escaped | "$" | "," | ";" | ":" |
573 * "@" | "&" | "=" | "+" )
574 *
575 * Note : this is completely ambiguous since reg_name is allowed to
576 * use the full set of chars in use by server:
577 *
578 * 3.2.1. Registry-based Naming Authority
579 *
580 * The structure of a registry-based naming authority is specific
581 * to the URI scheme, but constrained to the allowed characters
582 * for an authority component.
583 *
584 * Returns 0 or the error code
585 */
586int
587xmlParseURIAuthority(xmlURIPtr uri, const char **str) {
588 const char *cur;
589
590 if (str == NULL)
591 return(-1);
592
593 cur = *str;
594 if (!IS_REG_NAME(cur)) {
595 return(5);
596 }
597 NEXT(cur);
598 while (IS_REG_NAME(cur)) NEXT(cur);
599 if (uri != NULL) {
600 if (uri->authority != NULL) xmlFree(uri->authority);
601 uri->authority = xmlURIUnescape(*str, cur - *str, NULL);
602
603 /* @@ Parse the authority to try to extract server infos !!! */
604 }
605 *str = cur;
606 return(0);
607}
608
609/**
610 * xmlParseURIHierPart:
611 * @uri: pointer to an URI structure
612 * @str: pointer to the string to analyze
613 *
614 * Parse an URI hirarchical part
615 *
616 * hier_part = ( net_path | abs_path ) [ "?" query ]
617 * abs_path = "/" path_segments
618 * net_path = "//" authority [ abs_path ]
619 *
620 * Returns 0 or the error code
621 */
622int
623xmlParseURIHierPart(xmlURIPtr uri, const char **str) {
624 int ret;
625 const char *cur;
626
627 if (str == NULL)
628 return(-1);
629
630 cur = *str;
631
632 if ((cur[0] == '/') && (cur[1] == '/')) {
633 cur += 2;
634 ret = xmlParseURIAuthority(uri, &cur);
635 if (ret != 0)
636 return(ret);
637 if (cur[0] == '/') {
638 cur++;
639 ret = xmlParseURIPathSegments(uri, &cur, 1);
640 }
641 } else if (cur[0] == '/') {
642 cur++;
643 ret = xmlParseURIPathSegments(uri, &cur, 1);
644 } else {
645 return(4);
646 }
647 if (ret != 0)
648 return(ret);
649 if (*cur == '?') {
650 cur++;
651 ret = xmlParseURIQuery(uri, &cur);
652 if (ret != 0)
653 return(ret);
654 }
655 *str = cur;
656 return(0);
657}
658
659/**
660 * xmlParseAbsoluteURI:
661 * @uri: pointer to an URI structure
662 * @str: pointer to the string to analyze
663 *
664 * Parse an URI reference string and fills in the appropriate fields
665 * of the @uri structure
666 *
667 * absoluteURI = scheme ":" ( hier_part | opaque_part )
668 *
669 * Returns 0 or the error code
670 */
671int
672xmlParseAbsoluteURI(xmlURIPtr uri, const char **str) {
673 int ret;
674
675 if (str == NULL)
676 return(-1);
677
678 ret = xmlParseURIScheme(uri, str);
679 if (ret != 0) return(ret);
680 if (**str != ':')
681 return(1);
682 (*str)++;
683 if (**str == '/')
684 return(xmlParseURIHierPart(uri, str));
685 return(xmlParseURIOpaquePart(uri, str));
686}
687
688/**
689 * xmlParseRelativeURI:
690 * @uri: pointer to an URI structure
691 * @str: pointer to the string to analyze
692 *
693 * Parse an relative URI string and fills in the appropriate fields
694 * of the @uri structure
695 *
696 * relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ]
697 * abs_path = "/" path_segments
698 * net_path = "//" authority [ abs_path ]
699 * rel_path = rel_segment [ abs_path ]
700 *
701 * Returns 0 or the error code
702 */
703int
704xmlParseRelativeURI(xmlURIPtr uri, const char **str) {
705 int ret = 0;
706 const char *cur;
707
708 if (str == NULL)
709 return(-1);
710
711 cur = *str;
712 if ((cur[0] == '/') && (cur[1] == '/')) {
713 cur += 2;
714 ret = xmlParseURIAuthority(uri, &cur);
715 if (ret != 0)
716 return(ret);
717 if (cur[0] == '/') {
718 cur++;
719 ret = xmlParseURIPathSegments(uri, &cur, 1);
720 }
721 } else if (cur[0] == '/') {
722 cur++;
723 ret = xmlParseURIPathSegments(uri, &cur, 1);
724 } else {
725 ret = xmlParseURIRelSegment(uri, &cur);
726 if (ret != 0)
727 return(ret);
728 if (cur[0] == '/') {
729 cur++;
730 ret = xmlParseURIPathSegments(uri, &cur, 1);
731 }
732 }
733 if (ret != 0)
734 return(ret);
735 if (*cur == '?') {
736 cur++;
737 ret = xmlParseURIQuery(uri, &cur);
738 if (ret != 0)
739 return(ret);
740 }
741 *str = cur;
742 return(ret);
743}
744
745/**
746 * xmlParseURIReference:
747 * @uri: pointer to an URI structure
748 * @str: the string to analyze
749 *
750 * Parse an URI reference string and fills in the appropriate fields
751 * of the @uri structure
752 *
753 * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
754 *
755 * Returns 0 or the error code
756 */
757int
758xmlParseURIReference(xmlURIPtr uri, const char *str) {
759 int ret;
760 const char *tmp = str;
761
762 if (str == NULL)
763 return(-1);
764 xmlCleanURI(uri);
765
766 /*
767 * Try first to parse aboslute refs, then fallback to relative if
768 * it fails.
769 */
770 ret = xmlParseAbsoluteURI(uri, &str);
771 if (ret != 0) {
772 xmlCleanURI(uri);
773 str = tmp;
774 ret = xmlParseRelativeURI(uri, &str);
775 }
776 if (ret != 0) {
777 xmlCleanURI(uri);
778 return(ret);
779 }
780
781 if (*str == '#') {
782 str++;
783 ret = xmlParseURIFragment(uri, &str);
784 if (ret != 0) return(ret);
785 }
786 if (*str != 0) {
787 xmlCleanURI(uri);
788 return(1);
789 }
790 return(0);
791}
792
793/**
794 * xmlBuildURI:
795 * @URI: the URI instance found in the document
796 * @base: the base value
797 *
798 * Computes he final URI of the reference done by checking that
799 * the given URI is valid, and building the final URI using the
800 * base URI. This is processed according to section 5.2 of the
801 * RFC 2396
802 *
803 * 5.2. Resolving Relative References to Absolute Form
804 *
805 * Returns a new URI string (to be freed by the caller)
806 */
807xmlChar *
808xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
809 /* TODO */
810 return(NULL);
811}
812
813
814#ifdef STANDALONE
815int main(int argc, char **argv) {
816 int i, ret;
817 xmlURIPtr uri;
818
819 uri = xmlCreateURI();
820 if (argc <= 1) {
821 char str[1024];
822
823 while (1) {
824 /*
825 * read one line in string buffer.
826 */
827 if (fgets (&str[0], sizeof (str) - 1, stdin) == NULL)
828 break;
829
830 /*
831 * remove the ending spaces
832 */
833 i = strlen(str);
834 while ((i > 0) &&
835 ((str[i - 1] == '\n') || (str[i - 1] == '\r') ||
836 (str[i - 1] == ' ') || (str[i - 1] == '\t'))) {
837 i--;
838 str[i] = 0;
839 }
840 if (i <= 0)
841 continue;
842
843 ret = xmlParseURIReference(uri, str);
844 if (ret != 0)
845 printf("%s : error %d\n", str, ret);
846 else {
847 xmlPrintURI(stdout, uri);
848 printf("\n");
849 }
850
851 }
852 } else {
853 for (i = 1;i < argc;i++) {
854 ret = xmlParseURIReference(uri, argv[i]);
855 if (ret != 0)
856 printf("%s : error %d\n", argv[i], ret);
857 else {
858 xmlPrintURI(stdout, uri);
859 printf("\n");
860 }
861 }
862 }
863 xmlFreeURI(uri);
864 exit(0);
865}
866#endif