13473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * uri.c: set of generic URI related routines
33473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
4d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Reference: RFCs 3986, 2732 and 2373
53473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
63473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * See Copyright for the status of this software.
73473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
8c5d64345cf19bfd72418eb0a837869b0462e9130Daniel Veillard * daniel@veillard.com
93473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1134ce8bece2f22cc99d25221b77315cd008f4866bDaniel Veillard#define IN_LIBXML
1270a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese#include "libxml.h"
1370a9da54eb200cd5c5ceafb72aff72c39021c94cBjorn Reese
143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <string.h>
153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlmemory.h>
173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/uri.h>
18d0463560300f1d8b3e41d70c3728ed84fdc8dd30Daniel Veillard#include <libxml/globals.h>
193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#include <libxml/xmlerror.h>
203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard/**
2257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * MAX_URI_LENGTH:
2357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard *
2457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * The definition of the URI regexp in the above RFC has no size limit
2557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * In practice they are usually relativey short except for the
2657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * data URI scheme as defined in RFC 2397. Even for data URI the usual
2757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * maximum size before hitting random practical limits is around 64 KB
2857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * and 4KB is usually a maximum admitted limit for proper operations.
2957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * The value below is more a security limit than anything else and
3057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * really should never be hit by 'normal' operations
3157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * Set to 1 MByte in 2012, this is only enforced on output
3257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard */
3357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard#define MAX_URI_LENGTH 1024 * 1024
3457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard
3557560386503be0fd023f3b7537fd496784f3be18Daniel Veillardstatic void
3657560386503be0fd023f3b7537fd496784f3be18Daniel VeillardxmlURIErrMemory(const char *extra)
3757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard{
3857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    if (extra)
3957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        __xmlRaiseError(NULL, NULL, NULL,
4057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        NULL, NULL, XML_FROM_URI,
4157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
4257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        extra, NULL, NULL, 0, 0,
4357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        "Memory allocation failed : %s\n", extra);
4457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    else
4557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        __xmlRaiseError(NULL, NULL, NULL,
4657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        NULL, NULL, XML_FROM_URI,
4757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
4857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        NULL, NULL, NULL, 0, 0,
4957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        "Memory allocation failed\n");
5057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard}
5157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard
52d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic void xmlCleanURI(xmlURIPtr uri);
533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
55d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Old rule from 2396 used in legacy handling code
563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * alpha    = lowalpha | upalpha
573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x))
593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *            "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *            "u" | "v" | "w" | "x" | "y" | "z"
653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z'))
683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" |
713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" |
723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *           "U" | "V" | "W" | "X" | "Y" | "Z"
733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z'))
753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
76be3eb2088e3e27b897b57855382f80a737f974ceDaniel Veillard#ifdef IS_DIGIT
77be3eb2088e3e27b897b57855382f80a737f974ceDaniel Veillard#undef IS_DIGIT
78be3eb2088e3e27b897b57855382f80a737f974ceDaniel Veillard#endif
793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9'))
833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * alphanum = alpha | digit
863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x))
893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
94d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') ||     \
95d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') ||    \
963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    ((x) == '(') || ((x) == ')'))
973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
98d7af555327843a9938a913205ac703c13c225603Daniel Veillard/*
99d7af555327843a9938a913205ac703c13c225603Daniel Veillard * unwise = "{" | "}" | "|" | "\" | "^" | "`"
100d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
1013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
102d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define IS_UNWISE(p)                                                    \
103d7af555327843a9938a913205ac703c13c225603Daniel Veillard      (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) ||         \
104d7af555327843a9938a913205ac703c13c225603Daniel Veillard       ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) ||        \
105d7af555327843a9938a913205ac703c13c225603Daniel Veillard       ((*(p) == ']')) || ((*(p) == '`')))
1063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
107015ccb2c747fb73561e2fe72d6214585dd9985e8William M. Brack * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," |
108d7af555327843a9938a913205ac703c13c225603Daniel Veillard *            "[" | "]"
1093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
111d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \
112d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \
113d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \
114d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ((x) == ']'))
1153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
1173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * unreserved = alphanum | mark
1183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x))
1213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
123d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Skip to next pointer char, handle escaped sequences
1243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
126d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define NEXT(p) ((*p == '%')? p += 3 : p++)
1273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
129d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Productions from the spec.
130d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
131d7af555327843a9938a913205ac703c13c225603Daniel Veillard *    authority     = server | reg_name
132d7af555327843a9938a913205ac703c13c225603Daniel Veillard *    reg_name      = 1*( unreserved | escaped | "$" | "," |
133d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                        ";" | ":" | "@" | "&" | "=" | "+" )
134d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
135d7af555327843a9938a913205ac703c13c225603Daniel Veillard * path          = [ abs_path | opaque_part ]
1363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
137d7af555327843a9938a913205ac703c13c225603Daniel Veillard
138d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n))
139d7af555327843a9938a913205ac703c13c225603Daniel Veillard
140d7af555327843a9938a913205ac703c13c225603Daniel Veillard/************************************************************************
141d7af555327843a9938a913205ac703c13c225603Daniel Veillard *									*
142d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                         RFC 3986 parser				*
143d7af555327843a9938a913205ac703c13c225603Daniel Veillard *									*
144d7af555327843a9938a913205ac703c13c225603Daniel Veillard ************************************************************************/
145d7af555327843a9938a913205ac703c13c225603Daniel Veillard
146d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9'))
147d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) ||		\
148d7af555327843a9938a913205ac703c13c225603Daniel Veillard                      ((*(p) >= 'A') && (*(p) <= 'Z')))
149d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define ISA_HEXDIG(p)							\
150d7af555327843a9938a913205ac703c13c225603Daniel Veillard       (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) ||		\
151d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ((*(p) >= 'A') && (*(p) <= 'F')))
1523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
154d7af555327843a9938a913205ac703c13c225603Daniel Veillard *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
155d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                     / "*" / "+" / "," / ";" / "="
1563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
157d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define ISA_SUB_DELIM(p)						\
158d7af555327843a9938a913205ac703c13c225603Daniel Veillard      (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) ||		\
159d7af555327843a9938a913205ac703c13c225603Daniel Veillard       ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) ||		\
160d7af555327843a9938a913205ac703c13c225603Daniel Veillard       ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) ||		\
1612ee91eb6587191de876dbcf147d99bc9b8c7799dDaniel Veillard       ((*(p) == '=')) || ((*(p) == '\'')))
1623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
164d7af555327843a9938a913205ac703c13c225603Daniel Veillard *    gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
1653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
166d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define ISA_GEN_DELIM(p)						\
167d7af555327843a9938a913205ac703c13c225603Daniel Veillard      (((*(p) == ':')) || ((*(p) == '/')) || ((*(p) == '?')) ||         \
168d7af555327843a9938a913205ac703c13c225603Daniel Veillard       ((*(p) == '#')) || ((*(p) == '[')) || ((*(p) == ']')) ||         \
169d7af555327843a9938a913205ac703c13c225603Daniel Veillard       ((*(p) == '@')))
1703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
172d7af555327843a9938a913205ac703c13c225603Daniel Veillard *    reserved      = gen-delims / sub-delims
1733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
174d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define ISA_RESERVED(p) (ISA_GEN_DELIM(p) || (ISA_SUB_DELIM(p)))
1753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
177d7af555327843a9938a913205ac703c13c225603Daniel Veillard *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
1783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
179d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define ISA_UNRESERVED(p)						\
180d7af555327843a9938a913205ac703c13c225603Daniel Veillard      ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) ||		\
181d7af555327843a9938a913205ac703c13c225603Daniel Veillard       ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~')))
1823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
184d7af555327843a9938a913205ac703c13c225603Daniel Veillard *    pct-encoded   = "%" HEXDIG HEXDIG
1853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
186d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define ISA_PCT_ENCODED(p)						\
187d7af555327843a9938a913205ac703c13c225603Daniel Veillard     ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2)))
1883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/*
190d7af555327843a9938a913205ac703c13c225603Daniel Veillard *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
1913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
192d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define ISA_PCHAR(p)							\
193d7af555327843a9938a913205ac703c13c225603Daniel Veillard     (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) ||	\
194d7af555327843a9938a913205ac703c13c225603Daniel Veillard      ((*(p) == ':')) || ((*(p) == '@')))
1953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
196d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
197d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986Scheme:
198d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
199d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  pointer to the string to analyze
200d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
201d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an URI scheme
202d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
203d7af555327843a9938a913205ac703c13c225603Daniel Veillard * ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
204d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
205d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
206d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
207d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
208d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986Scheme(xmlURIPtr uri, const char **str) {
209d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
2103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
211d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (str == NULL)
212d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(-1);
213bb6808ea16b16055727ceb73d45a7f748b14ccfdDaniel Veillard
214d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
215d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (!ISA_ALPHA(cur))
216d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(2);
217d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur++;
218d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (ISA_ALPHA(cur) || ISA_DIGIT(cur) ||
219d7af555327843a9938a913205ac703c13c225603Daniel Veillard           (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++;
220d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
221d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->scheme != NULL) xmlFree(uri->scheme);
222d7af555327843a9938a913205ac703c13c225603Daniel Veillard	uri->scheme = STRNDUP(*str, cur - *str);
223d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
224d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
225d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(0);
226d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
227bb6808ea16b16055727ceb73d45a7f748b14ccfdDaniel Veillard
228d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
229d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986Fragment:
230d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
231d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  pointer to the string to analyze
232d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
233d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse the query part of an URI
234d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
23584c45df8d88f2b44f9c16474795fa2d30265bc21Daniel Veillard * fragment      = *( pchar / "/" / "?" )
23684c45df8d88f2b44f9c16474795fa2d30265bc21Daniel Veillard * NOTE: the strict syntax as defined by 3986 does not allow '[' and ']'
23784c45df8d88f2b44f9c16474795fa2d30265bc21Daniel Veillard *       in the fragment identifier but this is used very broadly for
23884c45df8d88f2b44f9c16474795fa2d30265bc21Daniel Veillard *       xpointer scheme selection, so we are allowing it here to not break
23984c45df8d88f2b44f9c16474795fa2d30265bc21Daniel Veillard *       for example all the DocBook processing chains.
240d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
241d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
2423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
243d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
244d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986Fragment(xmlURIPtr uri, const char **str)
245d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
246d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
2473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
248d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (str == NULL)
249d7af555327843a9938a913205ac703c13c225603Daniel Veillard        return (-1);
2503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
251d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
252d7af555327843a9938a913205ac703c13c225603Daniel Veillard
253d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
25484c45df8d88f2b44f9c16474795fa2d30265bc21Daniel Veillard           (*cur == '[') || (*cur == ']') ||
255d7af555327843a9938a913205ac703c13c225603Daniel Veillard           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
256d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NEXT(cur);
257d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
258d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (uri->fragment != NULL)
259d7af555327843a9938a913205ac703c13c225603Daniel Veillard            xmlFree(uri->fragment);
260d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->cleanup & 2)
261d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    uri->fragment = STRNDUP(*str, cur - *str);
262d7af555327843a9938a913205ac703c13c225603Daniel Veillard	else
263d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL);
264d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
265d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
266d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return (0);
267d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
268d7af555327843a9938a913205ac703c13c225603Daniel Veillard
269d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
270d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986Query:
271d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
272d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  pointer to the string to analyze
2733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
274d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse the query part of an URI
2753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
276d7af555327843a9938a913205ac703c13c225603Daniel Veillard * query = *uric
277d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
278d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
2793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
280d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
281d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986Query(xmlURIPtr uri, const char **str)
282d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
283d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
2843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
285d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (str == NULL)
286d7af555327843a9938a913205ac703c13c225603Daniel Veillard        return (-1);
287336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard
288d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
289d7af555327843a9938a913205ac703c13c225603Daniel Veillard
290d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
291d7af555327843a9938a913205ac703c13c225603Daniel Veillard           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
292d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NEXT(cur);
293d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
294d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (uri->query != NULL)
295d7af555327843a9938a913205ac703c13c225603Daniel Veillard            xmlFree(uri->query);
296d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->cleanup & 2)
297d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    uri->query = STRNDUP(*str, cur - *str);
298d7af555327843a9938a913205ac703c13c225603Daniel Veillard	else
299d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    uri->query = xmlURIUnescapeString(*str, cur - *str, NULL);
300d7af555327843a9938a913205ac703c13c225603Daniel Veillard
301d7af555327843a9938a913205ac703c13c225603Daniel Veillard	/* Save the raw bytes of the query as well.
302d7af555327843a9938a913205ac703c13c225603Daniel Veillard	 * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114
303d7af555327843a9938a913205ac703c13c225603Daniel Veillard	 */
304d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->query_raw != NULL)
305d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    xmlFree (uri->query_raw);
306d7af555327843a9938a913205ac703c13c225603Daniel Veillard	uri->query_raw = STRNDUP (*str, cur - *str);
307d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
308d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
309d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return (0);
310d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
3113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
313d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986Port:
314d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
315d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
3163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
317d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse a port  part and fills in the appropriate fields
318d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
3193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
320d7af555327843a9938a913205ac703c13c225603Daniel Veillard * port          = *DIGIT
321d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
322d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
3233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
324d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
325d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986Port(xmlURIPtr uri, const char **str)
326d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
327d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur = *str;
3283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
329d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ISA_DIGIT(cur)) {
330d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri != NULL)
331d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    uri->port = 0;
332d7af555327843a9938a913205ac703c13c225603Daniel Veillard	while (ISA_DIGIT(cur)) {
333d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (uri != NULL)
334d7af555327843a9938a913205ac703c13c225603Daniel Veillard		uri->port = uri->port * 10 + (*cur - '0');
335d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    cur++;
336d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
337d7af555327843a9938a913205ac703c13c225603Daniel Veillard	*str = cur;
338d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(0);
3393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
340d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(1);
3413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
3423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
3433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
344d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986Userinfo:
345d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
346d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
3473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
348d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an user informations part and fills in the appropriate fields
349d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
3503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
351d7af555327843a9938a913205ac703c13c225603Daniel Veillard * userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
352d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
353d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
3543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
355d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
356d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986Userinfo(xmlURIPtr uri, const char **str)
357d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
358d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
3593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
360d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
361d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) ||
362d7af555327843a9938a913205ac703c13c225603Daniel Veillard           ISA_SUB_DELIM(cur) || (*cur == ':'))
363d7af555327843a9938a913205ac703c13c225603Daniel Veillard	NEXT(cur);
364d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*cur == '@') {
365d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri != NULL) {
366d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (uri->user != NULL) xmlFree(uri->user);
367d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (uri->cleanup & 2)
368d7af555327843a9938a913205ac703c13c225603Daniel Veillard		uri->user = STRNDUP(*str, cur - *str);
369d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else
370d7af555327843a9938a913205ac703c13c225603Daniel Veillard		uri->user = xmlURIUnescapeString(*str, cur - *str, NULL);
371d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
372d7af555327843a9938a913205ac703c13c225603Daniel Veillard	*str = cur;
373d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(0);
374d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
375d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(1);
376d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
3773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
378d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
379d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986DecOctet:
380d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
381d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
382d7af555327843a9938a913205ac703c13c225603Daniel Veillard *    dec-octet     = DIGIT                 ; 0-9
383d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                  / %x31-39 DIGIT         ; 10-99
384d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                  / "1" 2DIGIT            ; 100-199
385d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                  / "2" %x30-34 DIGIT     ; 200-249
386d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                  / "25" %x30-35          ; 250-255
387d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
388d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Skip a dec-octet.
389d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
390d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 if found and skipped, 1 otherwise
391d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
392d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
393d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986DecOctet(const char **str) {
394d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur = *str;
3953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
396d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (!(ISA_DIGIT(cur)))
397d7af555327843a9938a913205ac703c13c225603Daniel Veillard        return(1);
398d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (!ISA_DIGIT(cur+1))
399d7af555327843a9938a913205ac703c13c225603Daniel Veillard	cur++;
400d7af555327843a9938a913205ac703c13c225603Daniel Veillard    else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur+2)))
401d7af555327843a9938a913205ac703c13c225603Daniel Veillard	cur += 2;
402d7af555327843a9938a913205ac703c13c225603Daniel Veillard    else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2)))
403d7af555327843a9938a913205ac703c13c225603Daniel Veillard	cur += 3;
404d7af555327843a9938a913205ac703c13c225603Daniel Veillard    else if ((*cur == '2') && (*(cur + 1) >= '0') &&
405d7af555327843a9938a913205ac703c13c225603Daniel Veillard	     (*(cur + 1) <= '4') && (ISA_DIGIT(cur + 2)))
406d7af555327843a9938a913205ac703c13c225603Daniel Veillard	cur += 3;
407d7af555327843a9938a913205ac703c13c225603Daniel Veillard    else if ((*cur == '2') && (*(cur + 1) == '5') &&
408d7af555327843a9938a913205ac703c13c225603Daniel Veillard	     (*(cur + 2) >= '0') && (*(cur + 1) <= '5'))
409d7af555327843a9938a913205ac703c13c225603Daniel Veillard	cur += 3;
410d7af555327843a9938a913205ac703c13c225603Daniel Veillard    else
411d7af555327843a9938a913205ac703c13c225603Daniel Veillard        return(1);
412d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
413d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(0);
414d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
415d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
416d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986Host:
417d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
418d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
419d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
420d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an host part and fills in the appropriate fields
421d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
422d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
423d7af555327843a9938a913205ac703c13c225603Daniel Veillard * host          = IP-literal / IPv4address / reg-name
424d7af555327843a9938a913205ac703c13c225603Daniel Veillard * IP-literal    = "[" ( IPv6address / IPvFuture  ) "]"
425d7af555327843a9938a913205ac703c13c225603Daniel Veillard * IPv4address   = dec-octet "." dec-octet "." dec-octet "." dec-octet
426d7af555327843a9938a913205ac703c13c225603Daniel Veillard * reg-name      = *( unreserved / pct-encoded / sub-delims )
427d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
428d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
429d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
430d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
431d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986Host(xmlURIPtr uri, const char **str)
432d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
433d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur = *str;
434d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *host;
4353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
436d7af555327843a9938a913205ac703c13c225603Daniel Veillard    host = cur;
437d7af555327843a9938a913205ac703c13c225603Daniel Veillard    /*
438d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * IPv6 and future adressing scheme are enclosed between brackets
439d7af555327843a9938a913205ac703c13c225603Daniel Veillard     */
440d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*cur == '[') {
441d7af555327843a9938a913205ac703c13c225603Daniel Veillard        cur++;
442d7af555327843a9938a913205ac703c13c225603Daniel Veillard	while ((*cur != ']') && (*cur != 0))
443d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    cur++;
444d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (*cur != ']')
445d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    return(1);
446d7af555327843a9938a913205ac703c13c225603Daniel Veillard	cur++;
447d7af555327843a9938a913205ac703c13c225603Daniel Veillard	goto found;
4483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
449d7af555327843a9938a913205ac703c13c225603Daniel Veillard    /*
450d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * try to parse an IPv4
451d7af555327843a9938a913205ac703c13c225603Daniel Veillard     */
452d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ISA_DIGIT(cur)) {
453d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (xmlParse3986DecOctet(&cur) != 0)
454d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    goto not_ipv4;
455d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (*cur != '.')
456d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    goto not_ipv4;
457d7af555327843a9938a913205ac703c13c225603Daniel Veillard	cur++;
458d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (xmlParse3986DecOctet(&cur) != 0)
459d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    goto not_ipv4;
460d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (*cur != '.')
461d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    goto not_ipv4;
462d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (xmlParse3986DecOctet(&cur) != 0)
463d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    goto not_ipv4;
464d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (*cur != '.')
465d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    goto not_ipv4;
466d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (xmlParse3986DecOctet(&cur) != 0)
467d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    goto not_ipv4;
468d7af555327843a9938a913205ac703c13c225603Daniel Veillard	goto found;
469d7af555327843a9938a913205ac703c13c225603Daniel Veillardnot_ipv4:
470d7af555327843a9938a913205ac703c13c225603Daniel Veillard        cur = *str;
471d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
472d7af555327843a9938a913205ac703c13c225603Daniel Veillard    /*
473d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * then this should be a hostname which can be empty
474d7af555327843a9938a913205ac703c13c225603Daniel Veillard     */
475d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur))
476d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NEXT(cur);
477d7af555327843a9938a913205ac703c13c225603Daniel Veillardfound:
478d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
479d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->authority != NULL) xmlFree(uri->authority);
480d7af555327843a9938a913205ac703c13c225603Daniel Veillard	uri->authority = NULL;
481d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->server != NULL) xmlFree(uri->server);
482d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (cur != host) {
483d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (uri->cleanup & 2)
484d7af555327843a9938a913205ac703c13c225603Daniel Veillard		uri->server = STRNDUP(host, cur - host);
485d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else
486d7af555327843a9938a913205ac703c13c225603Daniel Veillard		uri->server = xmlURIUnescapeString(host, cur - host, NULL);
487d7af555327843a9938a913205ac703c13c225603Daniel Veillard	} else
488d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    uri->server = NULL;
489d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
490d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
491d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(0);
492d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
493d7af555327843a9938a913205ac703c13c225603Daniel Veillard
494d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
495d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986Authority:
496d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
497d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
498d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
499d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an authority part and fills in the appropriate fields
500d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
501d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
502d7af555327843a9938a913205ac703c13c225603Daniel Veillard * authority     = [ userinfo "@" ] host [ ":" port ]
503d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
504d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
505d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
506d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
507d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986Authority(xmlURIPtr uri, const char **str)
508d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
509d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
510d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
511d7af555327843a9938a913205ac703c13c225603Daniel Veillard
512d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
513d7af555327843a9938a913205ac703c13c225603Daniel Veillard    /*
514d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * try to parse an userinfo and check for the trailing @
515d7af555327843a9938a913205ac703c13c225603Daniel Veillard     */
516d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = xmlParse3986Userinfo(uri, &cur);
517d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if ((ret != 0) || (*cur != '@'))
518d7af555327843a9938a913205ac703c13c225603Daniel Veillard        cur = *str;
519d7af555327843a9938a913205ac703c13c225603Daniel Veillard    else
520d7af555327843a9938a913205ac703c13c225603Daniel Veillard        cur++;
521d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = xmlParse3986Host(uri, &cur);
522d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret != 0) return(ret);
523d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*cur == ':') {
524f582d14fbcba1cd1e6598d556d8838ea6f4788baDaniel Veillard        cur++;
525d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlParse3986Port(uri, &cur);
526d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
527d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
528d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
529d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(0);
530d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
531d7af555327843a9938a913205ac703c13c225603Daniel Veillard
532d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
533d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986Segment:
534d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
535d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @forbid: an optional forbidden character
536d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @empty: allow an empty segment
537d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
538d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse a segment and fills in the appropriate fields
539d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
540d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
541d7af555327843a9938a913205ac703c13c225603Daniel Veillard * segment       = *pchar
542d7af555327843a9938a913205ac703c13c225603Daniel Veillard * segment-nz    = 1*pchar
543d7af555327843a9938a913205ac703c13c225603Daniel Veillard * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
544d7af555327843a9938a913205ac703c13c225603Daniel Veillard *               ; non-zero-length segment without any colon ":"
545d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
546d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
547d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
548d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
549d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986Segment(const char **str, char forbid, int empty)
550d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
551d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
552d7af555327843a9938a913205ac703c13c225603Daniel Veillard
553d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
554d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (!ISA_PCHAR(cur)) {
555d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (empty)
556d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    return(0);
557d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(1);
558fdd27d2718b9d6ef234092fb6cddfd7e9916feb6Daniel Veillard    }
559d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (ISA_PCHAR(cur) && (*cur != forbid))
560d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NEXT(cur);
561d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
562d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return (0);
563d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
564d7af555327843a9938a913205ac703c13c225603Daniel Veillard
565d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
566d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986PathAbEmpty:
567d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
568d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
569d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
570d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an path absolute or empty and fills in the appropriate fields
571d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
572d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
573d7af555327843a9938a913205ac703c13c225603Daniel Veillard * path-abempty  = *( "/" segment )
574d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
575d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
576d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
577d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
578d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986PathAbEmpty(xmlURIPtr uri, const char **str)
579d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
580d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
581d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
582d7af555327843a9938a913205ac703c13c225603Daniel Veillard
583d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
584d7af555327843a9938a913205ac703c13c225603Daniel Veillard
585d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (*cur == '/') {
586d7af555327843a9938a913205ac703c13c225603Daniel Veillard        cur++;
587d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986Segment(&cur, 0, 1);
588d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
589d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
590d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
591d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->path != NULL) xmlFree(uri->path);
5921358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        if (*str != cur) {
5931358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            if (uri->cleanup & 2)
5941358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard                uri->path = STRNDUP(*str, cur - *str);
5951358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            else
5961358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
5971358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        } else {
5981358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            uri->path = NULL;
5991358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        }
600d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
601d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
602d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return (0);
603d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
604d7af555327843a9938a913205ac703c13c225603Daniel Veillard
605d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
606d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986PathAbsolute:
607d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
608d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
609d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
610d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an path absolute and fills in the appropriate fields
611d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
612d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
613d7af555327843a9938a913205ac703c13c225603Daniel Veillard * path-absolute = "/" [ segment-nz *( "/" segment ) ]
614d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
615d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
616d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
617d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
618d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986PathAbsolute(xmlURIPtr uri, const char **str)
619d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
620d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
621d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
622d7af555327843a9938a913205ac703c13c225603Daniel Veillard
623d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
624d7af555327843a9938a913205ac703c13c225603Daniel Veillard
625d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*cur != '/')
626d7af555327843a9938a913205ac703c13c225603Daniel Veillard        return(1);
627d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur++;
628d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = xmlParse3986Segment(&cur, 0, 0);
629d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret == 0) {
630d7af555327843a9938a913205ac703c13c225603Daniel Veillard	while (*cur == '/') {
631d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    cur++;
632d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret = xmlParse3986Segment(&cur, 0, 1);
633d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (ret != 0) return(ret);
6343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
635fdd27d2718b9d6ef234092fb6cddfd7e9916feb6Daniel Veillard    }
636d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
637d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->path != NULL) xmlFree(uri->path);
6381358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        if (cur != *str) {
6391358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            if (uri->cleanup & 2)
6401358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard                uri->path = STRNDUP(*str, cur - *str);
6411358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            else
6421358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
6431358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        } else {
6441358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            uri->path = NULL;
6451358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        }
6463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
647d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
648d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return (0);
6493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
6503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
652d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986PathRootless:
653d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
654d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
6553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
656d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an path without root and fills in the appropriate fields
657d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
658d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
659d7af555327843a9938a913205ac703c13c225603Daniel Veillard * path-rootless = segment-nz *( "/" segment )
660d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
661d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
6623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
663d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
664d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986PathRootless(xmlURIPtr uri, const char **str)
665d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
666d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
667d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
6683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
669d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
670d7af555327843a9938a913205ac703c13c225603Daniel Veillard
671d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = xmlParse3986Segment(&cur, 0, 0);
672d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret != 0) return(ret);
673d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (*cur == '/') {
674d7af555327843a9938a913205ac703c13c225603Daniel Veillard        cur++;
675d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986Segment(&cur, 0, 1);
676d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
677d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
678d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
679d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->path != NULL) xmlFree(uri->path);
6801358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        if (cur != *str) {
6811358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            if (uri->cleanup & 2)
6821358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard                uri->path = STRNDUP(*str, cur - *str);
6831358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            else
6841358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
6851358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        } else {
6861358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            uri->path = NULL;
6871358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        }
6883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
689d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
690d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return (0);
6913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
6923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
6933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
694d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986PathNoScheme:
695d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
696d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
6973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
698d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an path which is not a scheme and fills in the appropriate fields
699d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
700d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
701d7af555327843a9938a913205ac703c13c225603Daniel Veillard * path-noscheme = segment-nz-nc *( "/" segment )
702d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
703d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
7043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
705d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
706d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986PathNoScheme(xmlURIPtr uri, const char **str)
707d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
708d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
709d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
7103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
711d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
712d7af555327843a9938a913205ac703c13c225603Daniel Veillard
713d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = xmlParse3986Segment(&cur, ':', 0);
714d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret != 0) return(ret);
715d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (*cur == '/') {
716d7af555327843a9938a913205ac703c13c225603Daniel Veillard        cur++;
717d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986Segment(&cur, 0, 1);
718d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
719d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
720d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
721d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->path != NULL) xmlFree(uri->path);
7221358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        if (cur != *str) {
7231358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            if (uri->cleanup & 2)
7241358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard                uri->path = STRNDUP(*str, cur - *str);
7251358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            else
7261358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
7271358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        } else {
7281358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard            uri->path = NULL;
7291358fef9aa2c3fea5ed3d6ee50c7eb4d6f92b247Daniel Veillard        }
730d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
731d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
732d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return (0);
733d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
734d7af555327843a9938a913205ac703c13c225603Daniel Veillard
735d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
736d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986HierPart:
737d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
738d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
739d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
740d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an hierarchical part and fills in the appropriate fields
741d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
742d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
743d7af555327843a9938a913205ac703c13c225603Daniel Veillard * hier-part     = "//" authority path-abempty
744d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                / path-absolute
745d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                / path-rootless
746d7af555327843a9938a913205ac703c13c225603Daniel Veillard *                / path-empty
747d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
748d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
749d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
750d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
751d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986HierPart(xmlURIPtr uri, const char **str)
752d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
753d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *cur;
754d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
755d7af555327843a9938a913205ac703c13c225603Daniel Veillard
756d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = *str;
757d7af555327843a9938a913205ac703c13c225603Daniel Veillard
758d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if ((*cur == '/') && (*(cur + 1) == '/')) {
759d7af555327843a9938a913205ac703c13c225603Daniel Veillard        cur += 2;
760d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986Authority(uri, &cur);
761d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
762beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard	if (uri->server == NULL)
763beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard	    uri->port = -1;
764d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986PathAbEmpty(uri, &cur);
765d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
766d7af555327843a9938a913205ac703c13c225603Daniel Veillard	*str = cur;
767d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(0);
768d7af555327843a9938a913205ac703c13c225603Daniel Veillard    } else if (*cur == '/') {
769d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlParse3986PathAbsolute(uri, &cur);
770d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
771d7af555327843a9938a913205ac703c13c225603Daniel Veillard    } else if (ISA_PCHAR(cur)) {
772d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlParse3986PathRootless(uri, &cur);
773d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
774d7af555327843a9938a913205ac703c13c225603Daniel Veillard    } else {
775d7af555327843a9938a913205ac703c13c225603Daniel Veillard	/* path-empty is effectively empty */
776d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri != NULL) {
777d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (uri->path != NULL) xmlFree(uri->path);
778d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    uri->path = NULL;
779d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
780d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
781d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *str = cur;
782d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return (0);
783d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
784d7af555327843a9938a913205ac703c13c225603Daniel Veillard
785d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
786d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986RelativeRef:
787d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
788d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
789d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
790d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an URI string and fills in the appropriate fields
791d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
792d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
793d7af555327843a9938a913205ac703c13c225603Daniel Veillard * relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
794d7af555327843a9938a913205ac703c13c225603Daniel Veillard * relative-part = "//" authority path-abempty
795d7af555327843a9938a913205ac703c13c225603Daniel Veillard *               / path-absolute
796d7af555327843a9938a913205ac703c13c225603Daniel Veillard *               / path-noscheme
797d7af555327843a9938a913205ac703c13c225603Daniel Veillard *               / path-empty
798d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
799d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
800d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
801d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
802d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986RelativeRef(xmlURIPtr uri, const char *str) {
803d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
804d7af555327843a9938a913205ac703c13c225603Daniel Veillard
805d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if ((*str == '/') && (*(str + 1) == '/')) {
806d7af555327843a9938a913205ac703c13c225603Daniel Veillard        str += 2;
807d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986Authority(uri, &str);
808d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
809d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986PathAbEmpty(uri, &str);
810d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
811d7af555327843a9938a913205ac703c13c225603Daniel Veillard    } else if (*str == '/') {
812d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986PathAbsolute(uri, &str);
813d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
814d7af555327843a9938a913205ac703c13c225603Daniel Veillard    } else if (ISA_PCHAR(str)) {
815d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlParse3986PathNoScheme(uri, &str);
816d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
817d7af555327843a9938a913205ac703c13c225603Daniel Veillard    } else {
818d7af555327843a9938a913205ac703c13c225603Daniel Veillard	/* path-empty is effectively empty */
819d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri != NULL) {
820d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (uri->path != NULL) xmlFree(uri->path);
821d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    uri->path = NULL;
822d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
823d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
824d7af555327843a9938a913205ac703c13c225603Daniel Veillard
825d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*str == '?') {
826d7af555327843a9938a913205ac703c13c225603Daniel Veillard	str++;
827d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986Query(uri, &str);
828d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
829d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
830d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*str == '#') {
831d7af555327843a9938a913205ac703c13c225603Daniel Veillard	str++;
832d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986Fragment(uri, &str);
833d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
834d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
835d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*str != 0) {
836d7af555327843a9938a913205ac703c13c225603Daniel Veillard	xmlCleanURI(uri);
837d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(1);
838d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
839d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(0);
8403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
8413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
842d7af555327843a9938a913205ac703c13c225603Daniel Veillard
8433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
844d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986URI:
845d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
846d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
8473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
848d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an URI string and fills in the appropriate fields
849d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
850d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
851d7af555327843a9938a913205ac703c13c225603Daniel Veillard * scheme ":" hier-part [ "?" query ] [ "#" fragment ]
852d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
853d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
8543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
855d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
856d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986URI(xmlURIPtr uri, const char *str) {
857d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
8583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
859d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = xmlParse3986Scheme(uri, &str);
860d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret != 0) return(ret);
861d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*str != ':') {
862d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(1);
863d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
864d7af555327843a9938a913205ac703c13c225603Daniel Veillard    str++;
865d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = xmlParse3986HierPart(uri, &str);
866d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret != 0) return(ret);
867d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*str == '?') {
868d7af555327843a9938a913205ac703c13c225603Daniel Veillard	str++;
869d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986Query(uri, &str);
870d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
871d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
872d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*str == '#') {
873d7af555327843a9938a913205ac703c13c225603Daniel Veillard	str++;
874d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986Fragment(uri, &str);
875d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) return(ret);
876d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
877d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (*str != 0) {
878d7af555327843a9938a913205ac703c13c225603Daniel Veillard	xmlCleanURI(uri);
879d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(1);
880d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
881d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(0);
8823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
8833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
8843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
885d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParse3986URIReference:
886d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
887d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
8883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
889d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an URI reference string and fills in the appropriate fields
890d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of the @uri structure
8913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
892d7af555327843a9938a913205ac703c13c225603Daniel Veillard * URI-reference = URI / relative-ref
8933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
894d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
8953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
896d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int
897d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParse3986URIReference(xmlURIPtr uri, const char *str) {
898d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
8993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
900d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (str == NULL)
9013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
902d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlCleanURI(uri);
9033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
9043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
905d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * Try first to parse absolute refs, then fallback to relative if
906d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * it fails.
9073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
908d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = xmlParse3986URI(uri, str);
909d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret != 0) {
910d7af555327843a9938a913205ac703c13c225603Daniel Veillard	xmlCleanURI(uri);
911d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlParse3986RelativeRef(uri, str);
912d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret != 0) {
913d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    xmlCleanURI(uri);
914d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    return(ret);
9153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
9163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
917d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(0);
918d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
9193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
920d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
921d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParseURI:
922d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the URI string to analyze
923d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
924d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an URI based on RFC 3986
925d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
926d7af555327843a9938a913205ac703c13c225603Daniel Veillard * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
927d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
928d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns a newly built xmlURIPtr or NULL in case of error
929d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
930d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlURIPtr
931d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParseURI(const char *str) {
932d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlURIPtr uri;
933d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
9343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
935d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (str == NULL)
936d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(NULL);
937d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri = xmlCreateURI();
938d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
939d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParse3986URIReference(uri, str);
940d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (ret) {
941d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    xmlFreeURI(uri);
942d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    return(NULL);
943d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
9443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
945d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(uri);
946d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
9473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
948d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
949d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParseURIReference:
950d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an URI structure
951d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to analyze
952d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
953d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an URI reference string based on RFC 3986 and fills in the
954d7af555327843a9938a913205ac703c13c225603Daniel Veillard * appropriate fields of the @uri structure
955d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
956d7af555327843a9938a913205ac703c13c225603Daniel Veillard * URI-reference = URI / relative-ref
957d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
958d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or the error code
959d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
960d7af555327843a9938a913205ac703c13c225603Daniel Veillardint
961d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParseURIReference(xmlURIPtr uri, const char *str) {
962d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(xmlParse3986URIReference(uri, str));
963d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
9643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
965d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
966d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlParseURIRaw:
967d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the URI string to analyze
968d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @raw:  if 1 unescaping of URI pieces are disabled
969d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
970d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Parse an URI but allows to keep intact the original fragments.
971d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
972d7af555327843a9938a913205ac703c13c225603Daniel Veillard * URI-reference = URI / relative-ref
973d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
974d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns a newly built xmlURIPtr or NULL in case of error
975d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
976d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlURIPtr
977d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlParseURIRaw(const char *str, int raw) {
978d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlURIPtr uri;
979d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret;
9803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
981d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (str == NULL)
982d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(NULL);
983d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri = xmlCreateURI();
984d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri != NULL) {
985d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (raw) {
986d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    uri->cleanup |= 2;
987d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
988d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = xmlParseURIReference(uri, str);
989d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (ret) {
990d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    xmlFreeURI(uri);
991d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    return(NULL);
992d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
993d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
994d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(uri);
9953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
9963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
997d7af555327843a9938a913205ac703c13c225603Daniel Veillard/************************************************************************
998d7af555327843a9938a913205ac703c13c225603Daniel Veillard *									*
999d7af555327843a9938a913205ac703c13c225603Daniel Veillard *			Generic URI structure functions			*
1000d7af555327843a9938a913205ac703c13c225603Daniel Veillard *									*
1001d7af555327843a9938a913205ac703c13c225603Daniel Veillard ************************************************************************/
1002d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1003d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
1004d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlCreateURI:
1005d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
1006d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Simply creates an empty xmlURI
1007d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
1008d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns the new structure or NULL in case of error
1009d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
1010d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlURIPtr
1011d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlCreateURI(void) {
1012d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlURIPtr ret;
1013d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1014d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI));
1015d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret == NULL) {
101657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        xmlURIErrMemory("creating URI structure\n");
1017d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(NULL);
1018d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1019d7af555327843a9938a913205ac703c13c225603Daniel Veillard    memset(ret, 0, sizeof(xmlURI));
1020d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(ret);
1021966a31e222f478b8ab3174617794808aa90f20c0Daniel Veillard}
1022966a31e222f478b8ab3174617794808aa90f20c0Daniel Veillard
10233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
102457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * xmlSaveUriRealloc:
102557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard *
102657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * Function to handle properly a reallocation when saving an URI
102757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * Also imposes some limit on the length of an URI string output
102857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard */
102957560386503be0fd023f3b7537fd496784f3be18Daniel Veillardstatic xmlChar *
103057560386503be0fd023f3b7537fd496784f3be18Daniel VeillardxmlSaveUriRealloc(xmlChar *ret, int *max) {
103157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    xmlChar *temp;
103257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    int tmp;
103357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard
103457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    if (*max > MAX_URI_LENGTH) {
103557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        xmlURIErrMemory("reaching arbitrary MAX_URI_LENGTH limit\n");
103657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        return(NULL);
103757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    }
103857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    tmp = *max * 2;
103957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    temp = (xmlChar *) xmlRealloc(ret, (tmp + 1));
104057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    if (temp == NULL) {
104157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        xmlURIErrMemory("saving URI\n");
104257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        return(NULL);
104357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    }
104457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    *max = tmp;
104557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    return(temp);
104657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard}
104757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard
104857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard/**
1049d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlSaveUri:
1050d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an xmlURI
10513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1052d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Save the URI as an escaped string
10533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1054d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns a new string (to be deallocated by caller)
10553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1056d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlChar *
1057d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlSaveUri(xmlURIPtr uri) {
1058d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlChar *ret = NULL;
1059d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlChar *temp;
1060d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *p;
1061d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int len;
1062d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int max;
10633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1064d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri == NULL) return(NULL);
1065d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1066d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1067d7af555327843a9938a913205ac703c13c225603Daniel Veillard    max = 80;
1068d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar));
1069d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret == NULL) {
107057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        xmlURIErrMemory("saving URI\n");
10713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(NULL);
1072d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1073d7af555327843a9938a913205ac703c13c225603Daniel Veillard    len = 0;
10743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1075d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->scheme != NULL) {
1076d7af555327843a9938a913205ac703c13c225603Daniel Veillard	p = uri->scheme;
1077d7af555327843a9938a913205ac703c13c225603Daniel Veillard	while (*p != 0) {
1078d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (len >= max) {
107957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                temp = xmlSaveUriRealloc(ret, &max);
108057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                if (temp == NULL) goto mem_error;
1081d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret = temp;
1082d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1083d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret[len++] = *p++;
10843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
1085d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (len >= max) {
108657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard            temp = xmlSaveUriRealloc(ret, &max);
108757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard            if (temp == NULL) goto mem_error;
108857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard            ret = temp;
1089d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
1090d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret[len++] = ':';
1091d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1092d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->opaque != NULL) {
1093d7af555327843a9938a913205ac703c13c225603Daniel Veillard	p = uri->opaque;
1094d7af555327843a9938a913205ac703c13c225603Daniel Veillard	while (*p != 0) {
1095d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (len + 3 >= max) {
109657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                temp = xmlSaveUriRealloc(ret, &max);
109757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                if (temp == NULL) goto mem_error;
109857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                ret = temp;
1099d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1100d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p)))
1101d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = *p++;
1102d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else {
1103d7af555327843a9938a913205ac703c13c225603Daniel Veillard		int val = *(unsigned char *)p++;
1104d7af555327843a9938a913205ac703c13c225603Daniel Veillard		int hi = val / 0x10, lo = val % 0x10;
1105d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = '%';
1106d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1107d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1108d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1109d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
1110d7af555327843a9938a913205ac703c13c225603Daniel Veillard    } else {
1111beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard	if ((uri->server != NULL) || (uri->port == -1)) {
1112d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (len + 3 >= max) {
111357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                temp = xmlSaveUriRealloc(ret, &max);
111457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                if (temp == NULL) goto mem_error;
111557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                ret = temp;
1116d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1117d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret[len++] = '/';
1118d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret[len++] = '/';
1119d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (uri->user != NULL) {
1120d7af555327843a9938a913205ac703c13c225603Daniel Veillard		p = uri->user;
1121d7af555327843a9938a913205ac703c13c225603Daniel Veillard		while (*p != 0) {
1122d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    if (len + 3 >= max) {
112357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        temp = xmlSaveUriRealloc(ret, &max);
112457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        if (temp == NULL) goto mem_error;
112557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                        ret = temp;
1126d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    }
1127d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    if ((IS_UNRESERVED(*(p))) ||
1128d7af555327843a9938a913205ac703c13c225603Daniel Veillard			((*(p) == ';')) || ((*(p) == ':')) ||
1129d7af555327843a9938a913205ac703c13c225603Daniel Veillard			((*(p) == '&')) || ((*(p) == '=')) ||
1130d7af555327843a9938a913205ac703c13c225603Daniel Veillard			((*(p) == '+')) || ((*(p) == '$')) ||
1131d7af555327843a9938a913205ac703c13c225603Daniel Veillard			((*(p) == ',')))
1132d7af555327843a9938a913205ac703c13c225603Daniel Veillard			ret[len++] = *p++;
1133d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    else {
1134d7af555327843a9938a913205ac703c13c225603Daniel Veillard			int val = *(unsigned char *)p++;
1135d7af555327843a9938a913205ac703c13c225603Daniel Veillard			int hi = val / 0x10, lo = val % 0x10;
1136d7af555327843a9938a913205ac703c13c225603Daniel Veillard			ret[len++] = '%';
1137d7af555327843a9938a913205ac703c13c225603Daniel Veillard			ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1138d7af555327843a9938a913205ac703c13c225603Daniel Veillard			ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1139d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    }
1140d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1141d7af555327843a9938a913205ac703c13c225603Daniel Veillard		if (len + 3 >= max) {
114257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    temp = xmlSaveUriRealloc(ret, &max);
114357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    if (temp == NULL) goto mem_error;
114457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    ret = temp;
1145d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1146d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = '@';
1147d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1148beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard	    if (uri->server != NULL) {
1149beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard		p = uri->server;
1150beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard		while (*p != 0) {
1151beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard		    if (len >= max) {
1152beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard			temp = xmlSaveUriRealloc(ret, &max);
1153beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard			if (temp == NULL) goto mem_error;
1154beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard			ret = temp;
1155beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard		    }
1156beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard		    ret[len++] = *p++;
1157d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1158beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard		if (uri->port > 0) {
1159beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard		    if (len + 10 >= max) {
1160beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard			temp = xmlSaveUriRealloc(ret, &max);
1161beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard			if (temp == NULL) goto mem_error;
1162beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard			ret = temp;
1163beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard		    }
1164beb7281055dbf0ed4d041022a67c6c5cfd126f25Daniel Veillard		    len += snprintf((char *) &ret[len], max - len, ":%d", uri->port);
1165d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1166d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1167d7af555327843a9938a913205ac703c13c225603Daniel Veillard	} else if (uri->authority != NULL) {
1168d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (len + 3 >= max) {
116957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                temp = xmlSaveUriRealloc(ret, &max);
117057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                if (temp == NULL) goto mem_error;
117157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                ret = temp;
1172d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1173d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret[len++] = '/';
1174d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret[len++] = '/';
1175d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    p = uri->authority;
1176d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    while (*p != 0) {
1177d7af555327843a9938a913205ac703c13c225603Daniel Veillard		if (len + 3 >= max) {
117857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    temp = xmlSaveUriRealloc(ret, &max);
117957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    if (temp == NULL) goto mem_error;
118057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    ret = temp;
1181d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1182d7af555327843a9938a913205ac703c13c225603Daniel Veillard		if ((IS_UNRESERVED(*(p))) ||
1183d7af555327843a9938a913205ac703c13c225603Daniel Veillard                    ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) ||
1184d7af555327843a9938a913205ac703c13c225603Daniel Veillard                    ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||
1185d7af555327843a9938a913205ac703c13c225603Daniel Veillard                    ((*(p) == '=')) || ((*(p) == '+')))
1186d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = *p++;
1187d7af555327843a9938a913205ac703c13c225603Daniel Veillard		else {
1188d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    int val = *(unsigned char *)p++;
1189d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    int hi = val / 0x10, lo = val % 0x10;
1190d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = '%';
1191d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1192d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1193d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1194d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1195d7af555327843a9938a913205ac703c13c225603Daniel Veillard	} else if (uri->scheme != NULL) {
1196d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (len + 3 >= max) {
119757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                temp = xmlSaveUriRealloc(ret, &max);
119857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                if (temp == NULL) goto mem_error;
119957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                ret = temp;
1200d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
12013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
1202d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->path != NULL) {
1203d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    p = uri->path;
1204d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    /*
1205d7af555327843a9938a913205ac703c13c225603Daniel Veillard	     * the colon in file:///d: should not be escaped or
1206d7af555327843a9938a913205ac703c13c225603Daniel Veillard	     * Windows accesses fail later.
1207d7af555327843a9938a913205ac703c13c225603Daniel Veillard	     */
1208d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if ((uri->scheme != NULL) &&
1209d7af555327843a9938a913205ac703c13c225603Daniel Veillard		(p[0] == '/') &&
1210d7af555327843a9938a913205ac703c13c225603Daniel Veillard		(((p[1] >= 'a') && (p[1] <= 'z')) ||
1211d7af555327843a9938a913205ac703c13c225603Daniel Veillard		 ((p[1] >= 'A') && (p[1] <= 'Z'))) &&
1212d7af555327843a9938a913205ac703c13c225603Daniel Veillard		(p[2] == ':') &&
1213d7af555327843a9938a913205ac703c13c225603Daniel Veillard	        (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
1214d7af555327843a9938a913205ac703c13c225603Daniel Veillard		if (len + 3 >= max) {
121557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    temp = xmlSaveUriRealloc(ret, &max);
121657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    if (temp == NULL) goto mem_error;
121757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    ret = temp;
1218d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1219d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = *p++;
1220d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = *p++;
1221d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = *p++;
1222d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1223d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    while (*p != 0) {
1224d7af555327843a9938a913205ac703c13c225603Daniel Veillard		if (len + 3 >= max) {
122557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    temp = xmlSaveUriRealloc(ret, &max);
122657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    if (temp == NULL) goto mem_error;
122757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    ret = temp;
1228d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1229d7af555327843a9938a913205ac703c13c225603Daniel Veillard		if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) ||
1230d7af555327843a9938a913205ac703c13c225603Daniel Veillard                    ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) ||
1231d7af555327843a9938a913205ac703c13c225603Daniel Veillard	            ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||
1232d7af555327843a9938a913205ac703c13c225603Daniel Veillard	            ((*(p) == ',')))
1233d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = *p++;
1234d7af555327843a9938a913205ac703c13c225603Daniel Veillard		else {
1235d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    int val = *(unsigned char *)p++;
1236d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    int hi = val / 0x10, lo = val % 0x10;
1237d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = '%';
1238d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1239d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1240d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
12413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
12423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
1243d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (uri->query_raw != NULL) {
1244d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (len + 1 >= max) {
124557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                temp = xmlSaveUriRealloc(ret, &max);
124657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                if (temp == NULL) goto mem_error;
124757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                ret = temp;
1248d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1249d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret[len++] = '?';
1250d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    p = uri->query_raw;
1251d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    while (*p != 0) {
1252d7af555327843a9938a913205ac703c13c225603Daniel Veillard		if (len + 1 >= max) {
125357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    temp = xmlSaveUriRealloc(ret, &max);
125457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    if (temp == NULL) goto mem_error;
125557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    ret = temp;
1256d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1257d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = *p++;
1258d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1259d7af555327843a9938a913205ac703c13c225603Daniel Veillard	} else if (uri->query != NULL) {
1260d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (len + 3 >= max) {
126157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                temp = xmlSaveUriRealloc(ret, &max);
126257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                if (temp == NULL) goto mem_error;
126357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                ret = temp;
1264d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1265d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret[len++] = '?';
1266d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    p = uri->query;
1267d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    while (*p != 0) {
1268d7af555327843a9938a913205ac703c13c225603Daniel Veillard		if (len + 3 >= max) {
126957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    temp = xmlSaveUriRealloc(ret, &max);
127057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    if (temp == NULL) goto mem_error;
127157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                    ret = temp;
1272d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
127357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard		if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
1274d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = *p++;
1275d7af555327843a9938a913205ac703c13c225603Daniel Veillard		else {
1276d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    int val = *(unsigned char *)p++;
1277d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    int hi = val / 0x10, lo = val % 0x10;
1278d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = '%';
1279d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1280d7af555327843a9938a913205ac703c13c225603Daniel Veillard		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1281d7af555327843a9938a913205ac703c13c225603Daniel Veillard		}
1282d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
12833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
12844def3bd94c4c34ad0b7b2848f7f43a62c9ea067cDaniel Veillard    }
1285d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->fragment != NULL) {
1286d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (len + 3 >= max) {
128757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard            temp = xmlSaveUriRealloc(ret, &max);
128857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard            if (temp == NULL) goto mem_error;
128957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard            ret = temp;
1290d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
1291d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret[len++] = '#';
1292d7af555327843a9938a913205ac703c13c225603Daniel Veillard	p = uri->fragment;
1293d7af555327843a9938a913205ac703c13c225603Daniel Veillard	while (*p != 0) {
1294d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (len + 3 >= max) {
129557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                temp = xmlSaveUriRealloc(ret, &max);
129657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                if (temp == NULL) goto mem_error;
129757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                ret = temp;
1298d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
129957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard	    if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
1300d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = *p++;
1301d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else {
1302d7af555327843a9938a913205ac703c13c225603Daniel Veillard		int val = *(unsigned char *)p++;
1303d7af555327843a9938a913205ac703c13c225603Daniel Veillard		int hi = val / 0x10, lo = val % 0x10;
1304d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = '%';
1305d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1306d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1307d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1308d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
13093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1310d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (len >= max) {
131157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        temp = xmlSaveUriRealloc(ret, &max);
131257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        if (temp == NULL) goto mem_error;
131357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        ret = temp;
13143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
131513cee4e37ba9f2a401f976e069539514ebfce7bcDaniel Veillard    ret[len] = 0;
1316d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(ret);
131757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard
131857560386503be0fd023f3b7537fd496784f3be18Daniel Veillardmem_error:
131957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    xmlFree(ret);
132057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    return(NULL);
13213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
13223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1324d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlPrintURI:
1325d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @stream:  a FILE* for the output
1326d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an xmlURI
13273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1328d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Prints the URI in the stream @stream.
13293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1330d7af555327843a9938a913205ac703c13c225603Daniel Veillardvoid
1331d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlPrintURI(FILE *stream, xmlURIPtr uri) {
1332d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlChar *out;
13333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1334d7af555327843a9938a913205ac703c13c225603Daniel Veillard    out = xmlSaveUri(uri);
1335d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (out != NULL) {
1336d7af555327843a9938a913205ac703c13c225603Daniel Veillard	fprintf(stream, "%s", (char *) out);
1337d7af555327843a9938a913205ac703c13c225603Daniel Veillard	xmlFree(out);
13383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
13393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
13403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
13413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1342d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlCleanURI:
1343d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an xmlURI
13443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1345d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Make sure the xmlURI struct is free of content
13463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1347d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic void
1348d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlCleanURI(xmlURIPtr uri) {
1349d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri == NULL) return;
13503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1351d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->scheme != NULL) xmlFree(uri->scheme);
1352d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri->scheme = NULL;
1353d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->server != NULL) xmlFree(uri->server);
1354d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri->server = NULL;
1355d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->user != NULL) xmlFree(uri->user);
1356d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri->user = NULL;
1357d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->path != NULL) xmlFree(uri->path);
1358d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri->path = NULL;
1359d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->fragment != NULL) xmlFree(uri->fragment);
1360d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri->fragment = NULL;
1361d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->opaque != NULL) xmlFree(uri->opaque);
1362d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri->opaque = NULL;
1363d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->authority != NULL) xmlFree(uri->authority);
1364d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri->authority = NULL;
1365d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->query != NULL) xmlFree(uri->query);
1366d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri->query = NULL;
1367d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->query_raw != NULL) xmlFree(uri->query_raw);
1368d7af555327843a9938a913205ac703c13c225603Daniel Veillard    uri->query_raw = NULL;
1369d7af555327843a9938a913205ac703c13c225603Daniel Veillard}
13704def3bd94c4c34ad0b7b2848f7f43a62c9ea067cDaniel Veillard
1371d7af555327843a9938a913205ac703c13c225603Daniel Veillard/**
1372d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlFreeURI:
1373d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @uri:  pointer to an xmlURI
1374d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
1375d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Free up the xmlURI struct
1376d7af555327843a9938a913205ac703c13c225603Daniel Veillard */
1377d7af555327843a9938a913205ac703c13c225603Daniel Veillardvoid
1378d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlFreeURI(xmlURIPtr uri) {
1379d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri == NULL) return;
1380d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1381d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->scheme != NULL) xmlFree(uri->scheme);
1382d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->server != NULL) xmlFree(uri->server);
1383d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->user != NULL) xmlFree(uri->user);
1384d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->path != NULL) xmlFree(uri->path);
1385d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->fragment != NULL) xmlFree(uri->fragment);
1386d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->opaque != NULL) xmlFree(uri->opaque);
1387d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->authority != NULL) xmlFree(uri->authority);
1388d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->query != NULL) xmlFree(uri->query);
1389d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->query_raw != NULL) xmlFree(uri->query_raw);
1390d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlFree(uri);
13913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
13923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1393d7af555327843a9938a913205ac703c13c225603Daniel Veillard/************************************************************************
1394d7af555327843a9938a913205ac703c13c225603Daniel Veillard *									*
1395d7af555327843a9938a913205ac703c13c225603Daniel Veillard *			Helper functions				*
1396d7af555327843a9938a913205ac703c13c225603Daniel Veillard *									*
1397d7af555327843a9938a913205ac703c13c225603Daniel Veillard ************************************************************************/
1398d7af555327843a9938a913205ac703c13c225603Daniel Veillard
13993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1400d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlNormalizeURIPath:
1401d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @path:  pointer to the path string
14023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1403d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Applies the 5 normalization steps to a path string--that is, RFC 2396
1404d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Section 5.2, steps 6.c through 6.g.
14053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1406d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Normalization occurs directly on the string, no new allocation is done
1407d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
1408d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns 0 or an error code
14093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1410d7af555327843a9938a913205ac703c13c225603Daniel Veillardint
1411d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlNormalizeURIPath(char *path) {
1412d7af555327843a9938a913205ac703c13c225603Daniel Veillard    char *cur, *out;
14133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1414d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (path == NULL)
14153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(-1);
14163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1417d7af555327843a9938a913205ac703c13c225603Daniel Veillard    /* Skip all initial "/" chars.  We want to get to the beginning of the
1418d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * first non-empty segment.
14193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
1420d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = path;
1421d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (cur[0] == '/')
1422d7af555327843a9938a913205ac703c13c225603Daniel Veillard      ++cur;
1423d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (cur[0] == '\0')
1424d7af555327843a9938a913205ac703c13c225603Daniel Veillard      return(0);
1425d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1426d7af555327843a9938a913205ac703c13c225603Daniel Veillard    /* Keep everything we've seen so far.  */
1427d7af555327843a9938a913205ac703c13c225603Daniel Veillard    out = cur;
1428d7af555327843a9938a913205ac703c13c225603Daniel Veillard
14293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
1430d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * Analyze each segment in sequence for cases (c) and (d).
14313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
1432d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (cur[0] != '\0') {
1433015ccb2c747fb73561e2fe72d6214585dd9985e8William M. Brack	/*
1434d7af555327843a9938a913205ac703c13c225603Daniel Veillard	 * c) All occurrences of "./", where "." is a complete path segment,
1435d7af555327843a9938a913205ac703c13c225603Daniel Veillard	 *    are removed from the buffer string.
1436015ccb2c747fb73561e2fe72d6214585dd9985e8William M. Brack	 */
1437d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if ((cur[0] == '.') && (cur[1] == '/')) {
1438d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    cur += 2;
1439d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    /* '//' normalization should be done at this point too */
1440d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    while (cur[0] == '/')
14413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		cur++;
1442d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    continue;
14433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
14443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1445d7af555327843a9938a913205ac703c13c225603Daniel Veillard	/*
1446d7af555327843a9938a913205ac703c13c225603Daniel Veillard	 * d) If the buffer string ends with "." as a complete path segment,
1447d7af555327843a9938a913205ac703c13c225603Daniel Veillard	 *    that "." is removed.
1448d7af555327843a9938a913205ac703c13c225603Daniel Veillard	 */
1449d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if ((cur[0] == '.') && (cur[1] == '\0'))
1450d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    break;
14513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1452d7af555327843a9938a913205ac703c13c225603Daniel Veillard	/* Otherwise keep the segment.  */
1453d7af555327843a9938a913205ac703c13c225603Daniel Veillard	while (cur[0] != '/') {
1454d7af555327843a9938a913205ac703c13c225603Daniel Veillard            if (cur[0] == '\0')
1455d7af555327843a9938a913205ac703c13c225603Daniel Veillard              goto done_cd;
1456d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    (out++)[0] = (cur++)[0];
1457d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
1458d7af555327843a9938a913205ac703c13c225603Daniel Veillard	/* nomalize // */
1459d7af555327843a9938a913205ac703c13c225603Daniel Veillard	while ((cur[0] == '/') && (cur[1] == '/'))
1460d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    cur++;
14614def3bd94c4c34ad0b7b2848f7f43a62c9ea067cDaniel Veillard
1462d7af555327843a9938a913205ac703c13c225603Daniel Veillard        (out++)[0] = (cur++)[0];
14633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1464d7af555327843a9938a913205ac703c13c225603Daniel Veillard done_cd:
1465d7af555327843a9938a913205ac703c13c225603Daniel Veillard    out[0] = '\0';
1466d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1467d7af555327843a9938a913205ac703c13c225603Daniel Veillard    /* Reset to the beginning of the first segment for the next sequence.  */
1468d7af555327843a9938a913205ac703c13c225603Daniel Veillard    cur = path;
1469d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (cur[0] == '/')
1470d7af555327843a9938a913205ac703c13c225603Daniel Veillard      ++cur;
1471d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (cur[0] == '\0')
1472d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(0);
1473d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1474d7af555327843a9938a913205ac703c13c225603Daniel Veillard    /*
1475d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * Analyze each segment in sequence for cases (e) and (f).
1476d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *
1477d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * e) All occurrences of "<segment>/../", where <segment> is a
1478d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    complete path segment not equal to "..", are removed from the
1479d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    buffer string.  Removal of these path segments is performed
1480d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    iteratively, removing the leftmost matching pattern on each
1481d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    iteration, until no matching pattern remains.
1482d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *
1483d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * f) If the buffer string ends with "<segment>/..", where <segment>
1484d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    is a complete path segment not equal to "..", that
1485d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    "<segment>/.." is removed.
1486d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *
1487d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * To satisfy the "iterative" clause in (e), we need to collapse the
1488d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * string every time we find something that needs to be removed.  Thus,
1489d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * we don't need to keep two pointers into the string: we only need a
1490d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * "current position" pointer.
1491d7af555327843a9938a913205ac703c13c225603Daniel Veillard     */
1492d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while (1) {
1493d7af555327843a9938a913205ac703c13c225603Daniel Veillard        char *segp, *tmp;
14943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1495d7af555327843a9938a913205ac703c13c225603Daniel Veillard        /* At the beginning of each iteration of this loop, "cur" points to
1496d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * the first character of the segment we want to examine.
1497d7af555327843a9938a913205ac703c13c225603Daniel Veillard         */
14983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1499d7af555327843a9938a913205ac703c13c225603Daniel Veillard        /* Find the end of the current segment.  */
1500d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segp = cur;
1501d7af555327843a9938a913205ac703c13c225603Daniel Veillard        while ((segp[0] != '/') && (segp[0] != '\0'))
1502d7af555327843a9938a913205ac703c13c225603Daniel Veillard          ++segp;
15034def3bd94c4c34ad0b7b2848f7f43a62c9ea067cDaniel Veillard
1504d7af555327843a9938a913205ac703c13c225603Daniel Veillard        /* If this is the last segment, we're done (we need at least two
1505d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * segments to meet the criteria for the (e) and (f) cases).
1506d7af555327843a9938a913205ac703c13c225603Daniel Veillard         */
1507d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (segp[0] == '\0')
1508d7af555327843a9938a913205ac703c13c225603Daniel Veillard          break;
15093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1510d7af555327843a9938a913205ac703c13c225603Daniel Veillard        /* If the first segment is "..", or if the next segment _isn't_ "..",
1511d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * keep this segment and try the next one.
1512d7af555327843a9938a913205ac703c13c225603Daniel Veillard         */
1513d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ++segp;
1514d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (((cur[0] == '.') && (cur[1] == '.') && (segp == cur+3))
1515d7af555327843a9938a913205ac703c13c225603Daniel Veillard            || ((segp[0] != '.') || (segp[1] != '.')
1516d7af555327843a9938a913205ac703c13c225603Daniel Veillard                || ((segp[2] != '/') && (segp[2] != '\0')))) {
1517d7af555327843a9938a913205ac703c13c225603Daniel Veillard          cur = segp;
1518d7af555327843a9938a913205ac703c13c225603Daniel Veillard          continue;
15194def3bd94c4c34ad0b7b2848f7f43a62c9ea067cDaniel Veillard        }
15203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1521d7af555327843a9938a913205ac703c13c225603Daniel Veillard        /* If we get here, remove this segment and the next one and back up
1522d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * to the previous segment (if there is one), to implement the
1523d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * "iteratively" clause.  It's pretty much impossible to back up
1524d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * while maintaining two pointers into the buffer, so just compact
1525d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * the whole buffer now.
15264def3bd94c4c34ad0b7b2848f7f43a62c9ea067cDaniel Veillard         */
15273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1528d7af555327843a9938a913205ac703c13c225603Daniel Veillard        /* If this is the end of the buffer, we're done.  */
1529d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (segp[2] == '\0') {
1530d7af555327843a9938a913205ac703c13c225603Daniel Veillard          cur[0] = '\0';
1531d7af555327843a9938a913205ac703c13c225603Daniel Veillard          break;
15324def3bd94c4c34ad0b7b2848f7f43a62c9ea067cDaniel Veillard        }
1533d7af555327843a9938a913205ac703c13c225603Daniel Veillard        /* Valgrind complained, strcpy(cur, segp + 3); */
1534cedf84d35ab127dd24f9bcbf8b8339518d0e8928Nico Weber        /* string will overlap, do not use strcpy */
1535cedf84d35ab127dd24f9bcbf8b8339518d0e8928Nico Weber        tmp = cur;
1536cedf84d35ab127dd24f9bcbf8b8339518d0e8928Nico Weber        segp += 3;
1537cedf84d35ab127dd24f9bcbf8b8339518d0e8928Nico Weber        while ((*tmp++ = *segp++) != 0)
1538cedf84d35ab127dd24f9bcbf8b8339518d0e8928Nico Weber          ;
15393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1540d7af555327843a9938a913205ac703c13c225603Daniel Veillard        /* If there are no previous segments, then keep going from here.  */
1541d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segp = cur;
1542d7af555327843a9938a913205ac703c13c225603Daniel Veillard        while ((segp > path) && ((--segp)[0] == '/'))
1543d7af555327843a9938a913205ac703c13c225603Daniel Veillard          ;
1544d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (segp == path)
1545d7af555327843a9938a913205ac703c13c225603Daniel Veillard          continue;
15463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1547d7af555327843a9938a913205ac703c13c225603Daniel Veillard        /* "segp" is pointing to the end of a previous segment; find it's
1548d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * start.  We need to back up to the previous segment and start
1549d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * over with that to handle things like "foo/bar/../..".  If we
1550d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * don't do this, then on the first pass we'll remove the "bar/..",
1551d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * but be pointing at the second ".." so we won't realize we can also
1552d7af555327843a9938a913205ac703c13c225603Daniel Veillard         * remove the "foo/..".
1553d7af555327843a9938a913205ac703c13c225603Daniel Veillard         */
1554d7af555327843a9938a913205ac703c13c225603Daniel Veillard        cur = segp;
1555d7af555327843a9938a913205ac703c13c225603Daniel Veillard        while ((cur > path) && (cur[-1] != '/'))
1556d7af555327843a9938a913205ac703c13c225603Daniel Veillard          --cur;
1557d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1558d7af555327843a9938a913205ac703c13c225603Daniel Veillard    out[0] = '\0';
15593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
1561d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * g) If the resulting buffer string still begins with one or more
1562d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    complete path segments of "..", then the reference is
1563d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    considered to be in error. Implementations may handle this
1564d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    error by retaining these components in the resolved path (i.e.,
1565d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    treating them as part of the final URI), by removing them from
1566d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    the resolved path (i.e., discarding relative levels above the
1567d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *    root), or by avoiding traversal of the reference.
1568d7af555327843a9938a913205ac703c13c225603Daniel Veillard     *
1569d7af555327843a9938a913205ac703c13c225603Daniel Veillard     * We discard them from the final path.
15703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
1571d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (path[0] == '/') {
1572d7af555327843a9938a913205ac703c13c225603Daniel Veillard      cur = path;
1573d7af555327843a9938a913205ac703c13c225603Daniel Veillard      while ((cur[0] == '/') && (cur[1] == '.') && (cur[2] == '.')
1574d7af555327843a9938a913205ac703c13c225603Daniel Veillard             && ((cur[3] == '/') || (cur[3] == '\0')))
1575d7af555327843a9938a913205ac703c13c225603Daniel Veillard	cur += 3;
15763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1577d7af555327843a9938a913205ac703c13c225603Daniel Veillard      if (cur != path) {
1578d7af555327843a9938a913205ac703c13c225603Daniel Veillard	out = path;
1579d7af555327843a9938a913205ac703c13c225603Daniel Veillard	while (cur[0] != '\0')
1580d7af555327843a9938a913205ac703c13c225603Daniel Veillard          (out++)[0] = (cur++)[0];
1581d7af555327843a9938a913205ac703c13c225603Daniel Veillard	out[0] = 0;
1582d7af555327843a9938a913205ac703c13c225603Daniel Veillard      }
15833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
15843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(0);
15863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
15873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1588d7af555327843a9938a913205ac703c13c225603Daniel Veillardstatic int is_hex(char c) {
1589d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (((c >= '0') && (c <= '9')) ||
1590d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ((c >= 'a') && (c <= 'f')) ||
1591d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ((c >= 'A') && (c <= 'F')))
15923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	return(1);
1593d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(0);
15943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
15953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
15963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1597d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlURIUnescapeString:
1598d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string to unescape
1599d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @len:   the length in bytes to unescape (or <= 0 to indicate full string)
1600d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @target:  optional destination buffer
16013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1602d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Unescaping routine, but does not check that the string is an URI. The
1603d7af555327843a9938a913205ac703c13c225603Daniel Veillard * output is a direct unsigned char translation of %XX values (no encoding)
1604d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Note that the length of the result can only be smaller or same size as
1605d7af555327843a9938a913205ac703c13c225603Daniel Veillard * the input string.
16063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1607d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns a copy of the string, but unescaped, will return NULL only in case
1608d7af555327843a9938a913205ac703c13c225603Daniel Veillard * of error
16093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1610d7af555327843a9938a913205ac703c13c225603Daniel Veillardchar *
1611d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlURIUnescapeString(const char *str, int len, char *target) {
1612d7af555327843a9938a913205ac703c13c225603Daniel Veillard    char *ret, *out;
1613d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const char *in;
16143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (str == NULL)
1616d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(NULL);
1617d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (len <= 0) len = strlen(str);
1618d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (len < 0) return(NULL);
1619d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1620d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (target == NULL) {
1621d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = (char *) xmlMallocAtomic(len + 1);
1622d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (ret == NULL) {
162357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard            xmlURIErrMemory("unescaping URI value\n");
1624d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    return(NULL);
16253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
1626d7af555327843a9938a913205ac703c13c225603Daniel Veillard    } else
1627d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ret = target;
1628d7af555327843a9938a913205ac703c13c225603Daniel Veillard    in = str;
1629d7af555327843a9938a913205ac703c13c225603Daniel Veillard    out = ret;
1630d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while(len > 0) {
1631d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) {
1632d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    in++;
163357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard	    if ((*in >= '0') && (*in <= '9'))
1634d7af555327843a9938a913205ac703c13c225603Daniel Veillard	        *out = (*in - '0');
1635d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else if ((*in >= 'a') && (*in <= 'f'))
1636d7af555327843a9938a913205ac703c13c225603Daniel Veillard	        *out = (*in - 'a') + 10;
1637d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else if ((*in >= 'A') && (*in <= 'F'))
1638d7af555327843a9938a913205ac703c13c225603Daniel Veillard	        *out = (*in - 'A') + 10;
1639d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    in++;
164057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard	    if ((*in >= '0') && (*in <= '9'))
1641d7af555327843a9938a913205ac703c13c225603Daniel Veillard	        *out = *out * 16 + (*in - '0');
1642d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else if ((*in >= 'a') && (*in <= 'f'))
1643d7af555327843a9938a913205ac703c13c225603Daniel Veillard	        *out = *out * 16 + (*in - 'a') + 10;
1644d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else if ((*in >= 'A') && (*in <= 'F'))
1645d7af555327843a9938a913205ac703c13c225603Daniel Veillard	        *out = *out * 16 + (*in - 'A') + 10;
1646d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    in++;
1647d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    len -= 3;
1648d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    out++;
1649d7af555327843a9938a913205ac703c13c225603Daniel Veillard	} else {
1650d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    *out++ = *in++;
1651d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    len--;
16523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
16533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1654d7af555327843a9938a913205ac703c13c225603Daniel Veillard    *out = 0;
16553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(ret);
16563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
16573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1659d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlURIEscapeStr:
1660d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  string to escape
1661d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @list: exception list string of chars not to escape
16623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1663d7af555327843a9938a913205ac703c13c225603Daniel Veillard * This routine escapes a string to hex, ignoring reserved characters (a-z)
1664d7af555327843a9938a913205ac703c13c225603Daniel Veillard * and the characters in the exception list.
16653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1666d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns a new escaped string or NULL in case of error.
16673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1668d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlChar *
1669d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlURIEscapeStr(const xmlChar *str, const xmlChar *list) {
1670d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlChar *ret, ch;
1671d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlChar *temp;
1672d7af555327843a9938a913205ac703c13c225603Daniel Veillard    const xmlChar *in;
167357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    int len, out;
16743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
16753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (str == NULL)
1676d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(NULL);
1677d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (str[0] == 0)
1678d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(xmlStrdup(str));
1679d7af555327843a9938a913205ac703c13c225603Daniel Veillard    len = xmlStrlen(str);
1680d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (!(len > 0)) return(NULL);
16813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1682d7af555327843a9938a913205ac703c13c225603Daniel Veillard    len += 20;
1683d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = (xmlChar *) xmlMallocAtomic(len);
1684d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (ret == NULL) {
168557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        xmlURIErrMemory("escaping URI value\n");
1686d7af555327843a9938a913205ac703c13c225603Daniel Veillard	return(NULL);
16873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1688d7af555327843a9938a913205ac703c13c225603Daniel Veillard    in = (const xmlChar *) str;
1689d7af555327843a9938a913205ac703c13c225603Daniel Veillard    out = 0;
1690d7af555327843a9938a913205ac703c13c225603Daniel Veillard    while(*in != 0) {
1691d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if (len - out <= 3) {
169257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard            temp = xmlSaveUriRealloc(ret, &len);
1693d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (temp == NULL) {
169457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard                xmlURIErrMemory("escaping URI value\n");
1695d7af555327843a9938a913205ac703c13c225603Daniel Veillard		xmlFree(ret);
1696d7af555327843a9938a913205ac703c13c225603Daniel Veillard		return(NULL);
1697d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    }
1698d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret = temp;
1699d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
1700d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1701d7af555327843a9938a913205ac703c13c225603Daniel Veillard	ch = *in;
1702d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1703d7af555327843a9938a913205ac703c13c225603Daniel Veillard	if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!xmlStrchr(list, ch))) {
1704d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    unsigned char val;
1705d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret[out++] = '%';
1706d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    val = ch >> 4;
1707d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (val <= 9)
1708d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[out++] = '0' + val;
1709d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else
1710d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[out++] = 'A' + val - 0xA;
1711d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    val = ch & 0xF;
1712d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    if (val <= 9)
1713d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[out++] = '0' + val;
1714d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    else
1715d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret[out++] = 'A' + val - 0xA;
1716d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    in++;
1717d7af555327843a9938a913205ac703c13c225603Daniel Veillard	} else {
1718d7af555327843a9938a913205ac703c13c225603Daniel Veillard	    ret[out++] = *in++;
1719d7af555327843a9938a913205ac703c13c225603Daniel Veillard	}
17203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
1722d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret[out] = 0;
1723d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return(ret);
17243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
17253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
1727d7af555327843a9938a913205ac703c13c225603Daniel Veillard * xmlURIEscape:
1728d7af555327843a9938a913205ac703c13c225603Daniel Veillard * @str:  the string of the URI to escape
17293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1730d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Escaping routine, does not do validity checks !
1731d7af555327843a9938a913205ac703c13c225603Daniel Veillard * It will try to escape the chars needing this, but this is heuristic
1732d7af555327843a9938a913205ac703c13c225603Daniel Veillard * based it's impossible to be sure.
17333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
1734d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Returns an copy of the string, but escaped
1735d7af555327843a9938a913205ac703c13c225603Daniel Veillard *
1736d7af555327843a9938a913205ac703c13c225603Daniel Veillard * 25 May 2001
1737d7af555327843a9938a913205ac703c13c225603Daniel Veillard * Uses xmlParseURI and xmlURIEscapeStr to try to escape correctly
1738d7af555327843a9938a913205ac703c13c225603Daniel Veillard * according to RFC2396.
1739d7af555327843a9938a913205ac703c13c225603Daniel Veillard *   - Carl Douglas
17403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
1741d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlChar *
1742d7af555327843a9938a913205ac703c13c225603Daniel VeillardxmlURIEscape(const xmlChar * str)
1743d7af555327843a9938a913205ac703c13c225603Daniel Veillard{
1744d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlChar *ret, *segment = NULL;
17453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlURIPtr uri;
1746d7af555327843a9938a913205ac703c13c225603Daniel Veillard    int ret2;
1747d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1748d7af555327843a9938a913205ac703c13c225603Daniel Veillard#define NULLCHK(p) if(!p) { \
174957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard         xmlURIErrMemory("escaping URI value\n"); \
175057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard         xmlFreeURI(uri); \
175157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard         return NULL; } \
17523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
17533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (str == NULL)
1754d7af555327843a9938a913205ac703c13c225603Daniel Veillard        return (NULL);
1755d7af555327843a9938a913205ac703c13c225603Daniel Veillard
17563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    uri = xmlCreateURI();
17573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (uri != NULL) {
1758d7af555327843a9938a913205ac703c13c225603Daniel Veillard	/*
1759d7af555327843a9938a913205ac703c13c225603Daniel Veillard	 * Allow escaping errors in the unescaped form
1760d7af555327843a9938a913205ac703c13c225603Daniel Veillard	 */
1761d7af555327843a9938a913205ac703c13c225603Daniel Veillard        uri->cleanup = 1;
1762d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret2 = xmlParseURIReference(uri, (const char *)str);
1763d7af555327843a9938a913205ac703c13c225603Daniel Veillard        if (ret2) {
1764d7af555327843a9938a913205ac703c13c225603Daniel Veillard            xmlFreeURI(uri);
1765d7af555327843a9938a913205ac703c13c225603Daniel Veillard            return (NULL);
1766d7af555327843a9938a913205ac703c13c225603Daniel Veillard        }
17673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
17683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
1769d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (!uri)
1770d7af555327843a9938a913205ac703c13c225603Daniel Veillard        return NULL;
1771336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard
1772d7af555327843a9938a913205ac703c13c225603Daniel Veillard    ret = NULL;
1773d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1774d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->scheme) {
1775d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segment = xmlURIEscapeStr(BAD_CAST uri->scheme, BAD_CAST "+-.");
1776d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NULLCHK(segment)
1777d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, segment);
1778d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, BAD_CAST ":");
1779d7af555327843a9938a913205ac703c13c225603Daniel Veillard        xmlFree(segment);
1780336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard    }
1781d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1782d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->authority) {
1783d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segment =
1784d7af555327843a9938a913205ac703c13c225603Daniel Veillard            xmlURIEscapeStr(BAD_CAST uri->authority, BAD_CAST "/?;:@");
1785d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NULLCHK(segment)
1786d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, BAD_CAST "//");
1787d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, segment);
1788d7af555327843a9938a913205ac703c13c225603Daniel Veillard        xmlFree(segment);
1789d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1790d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1791d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->user) {
1792d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segment = xmlURIEscapeStr(BAD_CAST uri->user, BAD_CAST ";:&=+$,");
1793d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NULLCHK(segment)
179457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard		ret = xmlStrcat(ret,BAD_CAST "//");
1795d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, segment);
1796d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, BAD_CAST "@");
1797d7af555327843a9938a913205ac703c13c225603Daniel Veillard        xmlFree(segment);
1798d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1799d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1800d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->server) {
1801d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@");
1802d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NULLCHK(segment)
1803d7af555327843a9938a913205ac703c13c225603Daniel Veillard		if (uri->user == NULL)
1804d7af555327843a9938a913205ac703c13c225603Daniel Veillard		ret = xmlStrcat(ret, BAD_CAST "//");
1805d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, segment);
1806d7af555327843a9938a913205ac703c13c225603Daniel Veillard        xmlFree(segment);
1807d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1808d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1809d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->port) {
1810d7af555327843a9938a913205ac703c13c225603Daniel Veillard        xmlChar port[10];
1811d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1812d7af555327843a9938a913205ac703c13c225603Daniel Veillard        snprintf((char *) port, 10, "%d", uri->port);
1813d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, BAD_CAST ":");
1814d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, port);
1815d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1816d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1817d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->path) {
1818d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segment =
1819d7af555327843a9938a913205ac703c13c225603Daniel Veillard            xmlURIEscapeStr(BAD_CAST uri->path, BAD_CAST ":@&=+$,/?;");
1820d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NULLCHK(segment)
1821d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, segment);
1822d7af555327843a9938a913205ac703c13c225603Daniel Veillard        xmlFree(segment);
1823d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1824d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1825d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->query_raw) {
1826d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, BAD_CAST "?");
1827d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, BAD_CAST uri->query_raw);
1828d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1829d7af555327843a9938a913205ac703c13c225603Daniel Veillard    else if (uri->query) {
1830d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segment =
1831d7af555327843a9938a913205ac703c13c225603Daniel Veillard            xmlURIEscapeStr(BAD_CAST uri->query, BAD_CAST ";/?:@&=+,$");
1832d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NULLCHK(segment)
1833d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, BAD_CAST "?");
1834d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, segment);
1835d7af555327843a9938a913205ac703c13c225603Daniel Veillard        xmlFree(segment);
1836d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1837d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1838d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->opaque) {
1839d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segment = xmlURIEscapeStr(BAD_CAST uri->opaque, BAD_CAST "");
1840d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NULLCHK(segment)
1841d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, segment);
1842d7af555327843a9938a913205ac703c13c225603Daniel Veillard        xmlFree(segment);
1843d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1844d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1845d7af555327843a9938a913205ac703c13c225603Daniel Veillard    if (uri->fragment) {
1846d7af555327843a9938a913205ac703c13c225603Daniel Veillard        segment = xmlURIEscapeStr(BAD_CAST uri->fragment, BAD_CAST "#");
1847d7af555327843a9938a913205ac703c13c225603Daniel Veillard        NULLCHK(segment)
1848d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, BAD_CAST "#");
1849d7af555327843a9938a913205ac703c13c225603Daniel Veillard        ret = xmlStrcat(ret, segment);
1850d7af555327843a9938a913205ac703c13c225603Daniel Veillard        xmlFree(segment);
1851d7af555327843a9938a913205ac703c13c225603Daniel Veillard    }
1852d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1853d7af555327843a9938a913205ac703c13c225603Daniel Veillard    xmlFreeURI(uri);
1854d7af555327843a9938a913205ac703c13c225603Daniel Veillard#undef NULLCHK
1855d7af555327843a9938a913205ac703c13c225603Daniel Veillard
1856d7af555327843a9938a913205ac703c13c225603Daniel Veillard    return (ret);
1857336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard}
1858336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard
18593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/************************************************************************
18603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
18613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *			Public functions				*
18623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *									*
18633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor ************************************************************************/
18643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor/**
18663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * xmlBuildURI:
18673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @URI:  the URI instance found in the document
18683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * @base:  the base value
18693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
18703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Computes he final URI of the reference done by checking that
18713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * the given URI is valid, and building the final URI using the
187257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * base URI. This is processed according to section 5.2 of the
18733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * RFC 2396
18743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
18753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * 5.2. Resolving Relative References to Absolute Form
18763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *
18773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor * Returns a new URI string (to be freed by the caller) or NULL in case
18783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor *         of error.
18793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor */
18803473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlChar *
18813473f88a7abdf4e585e267288fb77e898c580d2bOwen TaylorxmlBuildURI(const xmlChar *URI, const xmlChar *base) {
18823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlChar *val = NULL;
188356a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard    int ret, len, indx, cur, out;
18843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlURIPtr ref = NULL;
18853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlURIPtr bas = NULL;
18863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlURIPtr res = NULL;
18873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
18883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
18893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * 1) The URI reference is parsed into the potential four components and
18903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    fragment identifier, as described in Section 4.3.
18913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *
18923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    NOTE that a completely empty URI is treated by modern browsers
18933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    as a reference to "." rather than as a synonym for the current
18943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    URI.  Should we do that here?
18953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
189657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    if (URI == NULL)
18973473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = -1;
18983473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
18993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (*URI) {
19003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ref = xmlCreateURI();
19013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (ref == NULL)
19023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		goto done;
19033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = xmlParseURIReference(ref, (const char *) URI);
19043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
19053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else
19063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    ret = 0;
19073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
19083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret != 0)
19093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	goto done;
19107b4b2f9d8fc712c49beaf75985161a130c77d13aDaniel Veillard    if ((ref != NULL) && (ref->scheme != NULL)) {
19117b4b2f9d8fc712c49beaf75985161a130c77d13aDaniel Veillard	/*
19127b4b2f9d8fc712c49beaf75985161a130c77d13aDaniel Veillard	 * The URI is absolute don't modify.
19137b4b2f9d8fc712c49beaf75985161a130c77d13aDaniel Veillard	 */
19147b4b2f9d8fc712c49beaf75985161a130c77d13aDaniel Veillard	val = xmlStrdup(URI);
19157b4b2f9d8fc712c49beaf75985161a130c77d13aDaniel Veillard	goto done;
19167b4b2f9d8fc712c49beaf75985161a130c77d13aDaniel Veillard    }
19173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (base == NULL)
19183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = -1;
19193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else {
19203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	bas = xmlCreateURI();
19213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (bas == NULL)
19223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    goto done;
19233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	ret = xmlParseURIReference(bas, (const char *) base);
19243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
19253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ret != 0) {
19263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ref)
19273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    val = xmlSaveUri(ref);
19283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	goto done;
19293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
19303473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ref == NULL) {
19313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
19323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * the base fragment must be ignored
19333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
19343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (bas->fragment != NULL) {
19353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    xmlFree(bas->fragment);
19363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    bas->fragment = NULL;
19373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
19383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	val = xmlSaveUri(bas);
19393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	goto done;
19403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
19413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
19433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * 2) If the path component is empty and the scheme, authority, and
19443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    query components are undefined, then it is a reference to the
19453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    current document and we are done.  Otherwise, the reference URI's
19463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    query and fragment components are defined as found (or not found)
19473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    within the URI reference and not inherited from the base URI.
19483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *
19493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    NOTE that in modern browsers, the parsing differs from the above
19503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    in the following aspect:  the query component is allowed to be
19513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    defined while still treating this as a reference to the current
19523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    document.
19533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
19543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    res = xmlCreateURI();
19553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (res == NULL)
19563473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	goto done;
19573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ref->scheme == NULL) && (ref->path == NULL) &&
19583473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	((ref->authority == NULL) && (ref->server == NULL))) {
19593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (bas->scheme != NULL)
19603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->scheme = xmlMemStrdup(bas->scheme);
19613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (bas->authority != NULL)
19623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->authority = xmlMemStrdup(bas->authority);
19633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (bas->server != NULL) {
19643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->server = xmlMemStrdup(bas->server);
19653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (bas->user != NULL)
19663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		res->user = xmlMemStrdup(bas->user);
196757560386503be0fd023f3b7537fd496784f3be18Daniel Veillard	    res->port = bas->port;
19683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
19693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (bas->path != NULL)
19703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->path = xmlMemStrdup(bas->path);
1971a1413b84f7163d57c6251d5f4251186368efd859Daniel Veillard	if (ref->query_raw != NULL)
1972a1413b84f7163d57c6251d5f4251186368efd859Daniel Veillard	    res->query_raw = xmlMemStrdup (ref->query_raw);
1973a1413b84f7163d57c6251d5f4251186368efd859Daniel Veillard	else if (ref->query != NULL)
19743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->query = xmlMemStrdup(ref->query);
1975a1413b84f7163d57c6251d5f4251186368efd859Daniel Veillard	else if (bas->query_raw != NULL)
1976a1413b84f7163d57c6251d5f4251186368efd859Daniel Veillard	    res->query_raw = xmlMemStrdup(bas->query_raw);
19773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else if (bas->query != NULL)
19783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->query = xmlMemStrdup(bas->query);
19793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ref->fragment != NULL)
19803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->fragment = xmlMemStrdup(ref->fragment);
19813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	goto step_7;
19823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
19833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
19843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
19853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * 3) If the scheme component is defined, indicating that the reference
19863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    starts with a scheme name, then the reference is interpreted as an
19873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    absolute URI and we are done.  Otherwise, the reference URI's
19883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    scheme is inherited from the base URI's scheme component.
19893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
19903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ref->scheme != NULL) {
19913473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	val = xmlSaveUri(ref);
19923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	goto done;
19933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
19943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (bas->scheme != NULL)
19953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res->scheme = xmlMemStrdup(bas->scheme);
199657560386503be0fd023f3b7537fd496784f3be18Daniel Veillard
1997a1413b84f7163d57c6251d5f4251186368efd859Daniel Veillard    if (ref->query_raw != NULL)
1998a1413b84f7163d57c6251d5f4251186368efd859Daniel Veillard	res->query_raw = xmlMemStrdup(ref->query_raw);
1999a1413b84f7163d57c6251d5f4251186368efd859Daniel Veillard    else if (ref->query != NULL)
20009231ff9250af7e22104cc5e9406f0dd43e86aec0Daniel Veillard	res->query = xmlMemStrdup(ref->query);
20019231ff9250af7e22104cc5e9406f0dd43e86aec0Daniel Veillard    if (ref->fragment != NULL)
20029231ff9250af7e22104cc5e9406f0dd43e86aec0Daniel Veillard	res->fragment = xmlMemStrdup(ref->fragment);
20033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
20053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * 4) If the authority component is defined, then the reference is a
20063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    network-path and we skip to step 7.  Otherwise, the reference
20073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    URI's authority is inherited from the base URI's authority
20083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    component, which will also be undefined if the URI scheme does not
20093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    use an authority component.
20103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
20113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ref->authority != NULL) || (ref->server != NULL)) {
20123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ref->authority != NULL)
20133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->authority = xmlMemStrdup(ref->authority);
20143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	else {
20153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->server = xmlMemStrdup(ref->server);
20163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (ref->user != NULL)
20173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		res->user = xmlMemStrdup(ref->user);
201857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard            res->port = ref->port;
20193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
20203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (ref->path != NULL)
20213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->path = xmlMemStrdup(ref->path);
20223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	goto step_7;
20233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (bas->authority != NULL)
20253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res->authority = xmlMemStrdup(bas->authority);
20263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    else if (bas->server != NULL) {
20273473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res->server = xmlMemStrdup(bas->server);
20283473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if (bas->user != NULL)
20293473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->user = xmlMemStrdup(bas->user);
203057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard	res->port = bas->port;
20313473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20323473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20333473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
20343473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * 5) If the path component begins with a slash character ("/"), then
20353473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    the reference is an absolute-path and we skip to step 7.
20363473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
20373473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if ((ref->path != NULL) && (ref->path[0] == '/')) {
20383473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	res->path = xmlMemStrdup(ref->path);
20393473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	goto step_7;
20403473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20413473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20423473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20433473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
20443473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * 6) If this step is reached, then we are resolving a relative-path
20453473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    reference.  The relative path needs to be merged with the base
20463473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    URI's path.  Although there are many ways to do this, we will
20473473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    describe a simple method using a separate string buffer.
20483473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *
20493473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Allocate a buffer large enough for the result string.
20503473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
20513473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    len = 2; /* extra / and 0 */
20523473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ref->path != NULL)
20533473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	len += strlen(ref->path);
20543473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (bas->path != NULL)
20553473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	len += strlen(bas->path);
20563c908dca479ed50dca24b8593bca90e40dbde6b8Daniel Veillard    res->path = (char *) xmlMallocAtomic(len);
20573473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (res->path == NULL) {
205857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        xmlURIErrMemory("resolving URI against base\n");
20593473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	goto done;
20603473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20613473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    res->path[0] = 0;
20623473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20633473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
20643473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * a) All but the last segment of the base URI's path component is
20653473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    copied to the buffer.  In other words, any characters after the
20663473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    last (right-most) slash character, if any, are excluded.
20673473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
20683473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    cur = 0;
20693473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    out = 0;
20703473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (bas->path != NULL) {
20713473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	while (bas->path[cur] != 0) {
20723473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while ((bas->path[cur] != 0) && (bas->path[cur] != '/'))
20733473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		cur++;
20743473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    if (bas->path[cur] == 0)
20753473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		break;
20763473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20773473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    cur++;
20783473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    while (out < cur) {
20793473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		res->path[out] = bas->path[out];
20803473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor		out++;
20813473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    }
20823473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
20833473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
20843473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    res->path[out] = 0;
20853473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
20863473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
20873473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * b) The reference's path component is appended to the buffer
20883473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    string.
20893473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
20903473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ref->path != NULL && ref->path[0] != 0) {
209156a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	indx = 0;
20923473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	/*
20933473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 * Ensure the path includes a '/'
20943473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	 */
20953473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	if ((out == 0) && (bas->server != NULL))
20963473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	    res->path[out++] = '/';
209756a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	while (ref->path[indx] != 0) {
209856a4cb8c4d3eab4ab3295a61c87e8e92483922c6Daniel Veillard	    res->path[out++] = ref->path[indx++];
20993473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	}
21003473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    }
21013473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    res->path[out] = 0;
21023473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21033473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
21043473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * Steps c) to h) are really path normalization steps
21053473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
21063473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    xmlNormalizeURIPath(res->path);
21073473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21083473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylorstep_7:
21093473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21103473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    /*
21113473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     * 7) The resulting URI components, including any inherited from the
21123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    base URI, are recombined to give the absolute form of the URI
21133473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     *    reference.
21143473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor     */
21153473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    val = xmlSaveUri(res);
21163473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
21173473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylordone:
21183473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (ref != NULL)
21193473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFreeURI(ref);
21203473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (bas != NULL)
21213473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFreeURI(bas);
21223473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    if (res != NULL)
21233473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor	xmlFreeURI(res);
21243473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor    return(val);
21253473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor}
21263473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2127f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic/**
2128f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack * xmlBuildRelativeURI:
2129f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack * @URI:  the URI reference under consideration
2130f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack * @base:  the base value
2131f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *
2132f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack * Expresses the URI of the reference in terms relative to the
2133f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack * base.  Some examples of this operation include:
2134f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     base = "http://site1.com/docs/book1.html"
2135f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *        URI input                        URI returned
2136f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     docs/pic1.gif                    pic1.gif
2137f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     docs/img/pic1.gif                img/pic1.gif
2138f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     img/pic1.gif                     ../img/pic1.gif
2139f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     http://site1.com/docs/pic1.gif   pic1.gif
2140f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     http://site2.com/docs/pic1.gif   http://site2.com/docs/pic1.gif
2141f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *
2142f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     base = "docs/book1.html"
2143f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *        URI input                        URI returned
2144f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     docs/pic1.gif                    pic1.gif
2145f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     docs/img/pic1.gif                img/pic1.gif
2146f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     img/pic1.gif                     ../img/pic1.gif
2147f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *     http://site1.com/docs/pic1.gif   http://site1.com/docs/pic1.gif
2148f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *
2149f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *
2150f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack * Note: if the URI reference is really wierd or complicated, it may be
2151f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *       worthwhile to first convert it into a "nice" one by calling
2152f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *       xmlBuildURI (using 'base') before calling this routine,
2153f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *       since this routine (for reasonable efficiency) assumes URI has
2154f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *       already been through some validation.
2155f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack *
2156f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack * Returns a new URI string (to be freed by the caller) or NULL in case
2157f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack * error.
2158f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack */
2159f7789b13c59ef9d9e73047543c704c6ab21a6212William M. BrackxmlChar *
2160f7789b13c59ef9d9e73047543c704c6ab21a6212William M. BrackxmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
2161f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack{
2162f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    xmlChar *val = NULL;
2163f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    int ret;
2164f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    int ix;
2165f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    int pos = 0;
2166f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    int nbslash = 0;
2167820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack    int len;
2168f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    xmlURIPtr ref = NULL;
2169f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    xmlURIPtr bas = NULL;
2170f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    xmlChar *bptr, *uptr, *vptr;
21710f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    int remove_path = 0;
2172f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2173f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    if ((URI == NULL) || (*URI == 0))
2174f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	return NULL;
2175f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2176f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    /*
2177f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * First parse URI into a standard form
2178f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     */
2179f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    ref = xmlCreateURI ();
2180f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    if (ref == NULL)
2181f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	return NULL;
218238c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack    /* If URI not already in "relative" form */
218338c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack    if (URI[0] != '.') {
218438c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack	ret = xmlParseURIReference (ref, (const char *) URI);
218538c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack	if (ret != 0)
218638c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack	    goto done;		/* Error in URI, return NULL */
218738c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack    } else
218838c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack	ref->path = (char *)xmlStrdup(URI);
2189f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2190f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    /*
2191f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * Next parse base into the same standard form
2192f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     */
2193f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    if ((base == NULL) || (*base == 0)) {
2194f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	val = xmlStrdup (URI);
2195f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	goto done;
2196f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    }
2197f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    bas = xmlCreateURI ();
2198f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    if (bas == NULL)
2199f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	goto done;
220038c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack    if (base[0] != '.') {
220138c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack	ret = xmlParseURIReference (bas, (const char *) base);
220238c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack	if (ret != 0)
220338c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack	    goto done;		/* Error in base, return NULL */
220438c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack    } else
220538c4b332c4ec2f0db5ee601abaa9b46ec2e272e2William M. Brack	bas->path = (char *)xmlStrdup(base);
2206f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2207f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    /*
2208f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * If the scheme / server on the URI differs from the base,
2209f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * just return the URI
2210f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     */
2211f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    if ((ref->scheme != NULL) &&
22120f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	((bas->scheme == NULL) ||
22130f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	 (xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) ||
22140f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	 (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)))) {
2215f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	val = xmlStrdup (URI);
2216f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	goto done;
2217f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    }
22180f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) {
22190f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	val = xmlStrdup(BAD_CAST "");
22200f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	goto done;
22210f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    }
22220f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    if (bas->path == NULL) {
22230f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	val = xmlStrdup((xmlChar *)ref->path);
22240f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	goto done;
22250f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    }
22260f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    if (ref->path == NULL) {
22270f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard        ref->path = (char *) "/";
22280f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	remove_path = 1;
22290f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    }
2230f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2231f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    /*
2232f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * At this point (at last!) we can compare the two paths
2233f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     *
2234820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack     * First we take care of the special case where either of the
2235820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack     * two path components may be missing (bug 316224)
2236f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     */
2237820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack    if (bas->path == NULL) {
2238820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	if (ref->path != NULL) {
22390f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	    uptr = (xmlChar *) ref->path;
2240820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    if (*uptr == '/')
2241820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack		uptr++;
2242504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack	    /* exception characters from xmlSaveUri */
2243504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack	    val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,");
2244820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	}
2245820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	goto done;
2246f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    }
2247820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack    bptr = (xmlChar *)bas->path;
2248820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack    if (ref->path == NULL) {
2249820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	for (ix = 0; bptr[ix] != 0; ix++) {
2250820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    if (bptr[ix] == '/')
2251820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack		nbslash++;
2252820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	}
2253820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	uptr = NULL;
2254820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	len = 1;	/* this is for a string terminator only */
2255f2a657aa599bf9e9a1cbf4082ba885d177f05697William M. Brack    } else {
2256f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    /*
2257820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack     * Next we compare the two strings and find where they first differ
2258f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     */
2259820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/'))
2260820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack            pos += 2;
2261820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	if ((*bptr == '.') && (bptr[1] == '/'))
2262820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack            bptr += 2;
2263820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	else if ((*bptr == '/') && (ref->path[pos] != '/'))
2264820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    bptr++;
2265820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0))
2266820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    pos++;
2267820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack
2268820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	if (bptr[pos] == ref->path[pos]) {
22690f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	    val = xmlStrdup(BAD_CAST "");
2270820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    goto done;		/* (I can't imagine why anyone would do this) */
2271820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	}
2272820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack
2273820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	/*
2274820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	 * In URI, "back up" to the last '/' encountered.  This will be the
2275820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	 * beginning of the "unique" suffix of URI
2276820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	 */
2277820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	ix = pos;
2278820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	if ((ref->path[ix] == '/') && (ix > 0))
2279820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    ix--;
22800f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/'))
22810f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	    ix -= 2;
2282820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	for (; ix > 0; ix--) {
2283820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    if (ref->path[ix] == '/')
2284820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack		break;
2285820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	}
2286820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	if (ix == 0) {
2287820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    uptr = (xmlChar *)ref->path;
2288820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	} else {
2289820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    ix++;
2290820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    uptr = (xmlChar *)&ref->path[ix];
2291f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	}
2292f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2293820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	/*
2294820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	 * In base, count the number of '/' from the differing point
2295820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	 */
2296820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	if (bptr[pos] != ref->path[pos]) {/* check for trivial URI == base */
2297820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    for (; bptr[ix] != 0; ix++) {
2298820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack		if (bptr[ix] == '/')
2299820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack		    nbslash++;
2300820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	    }
2301820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	}
2302820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	len = xmlStrlen (uptr) + 1;
2303820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack    }
230457560386503be0fd023f3b7537fd496784f3be18Daniel Veillard
2305f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    if (nbslash == 0) {
2306820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	if (uptr != NULL)
2307504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack	    /* exception characters from xmlSaveUri */
2308504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack	    val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,");
2309f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	goto done;
2310f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    }
2311f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2312f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    /*
2313f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * Allocate just enough space for the returned string -
2314f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * length of the remainder of the URI, plus enough space
2315f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * for the "../" groups, plus one for the terminator
2316f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     */
2317820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack    val = (xmlChar *) xmlMalloc (len + 3 * nbslash);
2318f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    if (val == NULL) {
231957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard        xmlURIErrMemory("building relative URI\n");
2320f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	goto done;
2321f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    }
2322f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    vptr = val;
2323f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    /*
2324f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * Put in as many "../" as needed
2325f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     */
2326f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    for (; nbslash>0; nbslash--) {
2327f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	*vptr++ = '.';
2328f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	*vptr++ = '.';
2329f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	*vptr++ = '/';
2330f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    }
2331f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    /*
2332f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * Finish up with the end of the URI
2333f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     */
23340f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    if (uptr != NULL) {
23350f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard        if ((vptr > val) && (len > 0) &&
23360f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	    (uptr[0] == '/') && (vptr[-1] == '/')) {
23370f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	    memcpy (vptr, uptr + 1, len - 1);
23380f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	    vptr[len - 2] = 0;
23390f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	} else {
23400f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	    memcpy (vptr, uptr, len);
23410f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	    vptr[len - 1] = 0;
23420f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard	}
23430f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    } else {
2344820d5ed74771a2efc2a7b42386b9710d4f129e48William M. Brack	vptr[len - 1] = 0;
23450f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    }
2346f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2347504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack    /* escape the freshly-built path */
2348504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack    vptr = val;
2349504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack	/* exception characters from xmlSaveUri */
2350504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack    val = xmlURIEscapeStr(vptr, BAD_CAST "/;&=+$,");
2351504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack    xmlFree(vptr);
2352504201966dbcc76b0d3c60d85e36133188620f6cWilliam M. Brack
23530f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillarddone:
2354f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    /*
2355f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     * Free the working variables
2356f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack     */
23570f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard    if (remove_path != 0)
23580f7b33101b1850f671e81b15f3aecc7a332c813fDaniel Veillard        ref->path = NULL;
2359f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    if (ref != NULL)
2360f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	xmlFreeURI (ref);
2361f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    if (bas != NULL)
2362f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack	xmlFreeURI (bas);
2363f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2364f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack    return val;
2365f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack}
2366f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack
2367f7789b13c59ef9d9e73047543c704c6ab21a6212William M. Brack/**
2368f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic * xmlCanonicPath:
2369f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic * @path:  the resource locator in a filesystem notation
2370f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic *
237157560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * Constructs a canonic path from the specified path.
2372f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic *
237357560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * Returns a new canonic path, or a duplicate of the path parameter if the
2374f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic * construction fails. The caller is responsible for freeing the memory occupied
237557560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * by the returned string. If there is insufficient memory available, or the
2376f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic * argument is NULL, the function returns NULL.
2377f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic */
237857560386503be0fd023f3b7537fd496784f3be18Daniel Veillard#define IS_WINDOWS_PATH(p)					\
2379f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic	((p != NULL) &&						\
2380f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic	 (((p[0] >= 'a') && (p[0] <= 'z')) ||			\
2381f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic	  ((p[0] >= 'A') && (p[0] <= 'Z'))) &&			\
2382f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic	 (p[1] == ':') && ((p[2] == '/') || (p[2] == '\\')))
2383b8efdda0a31947d5291fcb9221040fdab88dc549Daniel VeillardxmlChar *
2384f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor ZlatkovicxmlCanonicPath(const xmlChar *path)
2385f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic{
23862224227818b8196ea9250235038e069f6bc03a55William M. Brack/*
23872224227818b8196ea9250235038e069f6bc03a55William M. Brack * For Windows implementations, additional work needs to be done to
23882224227818b8196ea9250235038e069f6bc03a55William M. Brack * replace backslashes in pathnames with "forward slashes"
23892224227818b8196ea9250235038e069f6bc03a55William M. Brack */
239057560386503be0fd023f3b7537fd496784f3be18Daniel Veillard#if defined(_WIN32) && !defined(__CYGWIN__)
2391ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic    int len = 0;
2392ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic    int i = 0;
2393ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic    xmlChar *p = NULL;
2394c64b8e984c13a0d989dea436c13128b289a4d4d6Daniel Veillard#endif
2395f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic    xmlURIPtr uri;
2396336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard    xmlChar *ret;
2397336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard    const xmlChar *absuri;
2398f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic
2399f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic    if (path == NULL)
2400f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic	return(NULL);
240169f8a13e52d4d4afd34e7642ce99c9cd0fcd8f03Daniel Veillard
240255b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl#if defined(_WIN32)
240355b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl    /*
240455b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl     * We must not change the backslashes to slashes if the the path
240555b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl     * starts with \\?\
240655b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl     * Those paths can be up to 32k characters long.
240755b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl     * Was added specifically for OpenOffice, those paths can't be converted
240855b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl     * to URIs anyway.
240955b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl     */
241055b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl    if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
241155b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl        (path[3] == '\\') )
241255b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl	return xmlStrdup((const xmlChar *) path);
241355b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl#endif
241455b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl
241555b899a23acfa2e1bb36026b50a8f7cb36dc4fdaMichael Stahl	/* sanitize filename starting with // so it can be used as URI */
241669f8a13e52d4d4afd34e7642ce99c9cd0fcd8f03Daniel Veillard    if ((path[0] == '/') && (path[1] == '/') && (path[2] != '/'))
241769f8a13e52d4d4afd34e7642ce99c9cd0fcd8f03Daniel Veillard        path++;
241869f8a13e52d4d4afd34e7642ce99c9cd0fcd8f03Daniel Veillard
2419c64b8e984c13a0d989dea436c13128b289a4d4d6Daniel Veillard    if ((uri = xmlParseURI((const char *) path)) != NULL) {
2420f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic	xmlFreeURI(uri);
2421f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic	return xmlStrdup(path);
2422f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic    }
2423f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic
24242224227818b8196ea9250235038e069f6bc03a55William M. Brack    /* Check if this is an "absolute uri" */
2425336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard    absuri = xmlStrstr(path, BAD_CAST "://");
2426336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard    if (absuri != NULL) {
2427336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard        int l, j;
2428336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	unsigned char c;
2429336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	xmlChar *escURI;
2430336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard
2431336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard        /*
2432336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	 * this looks like an URI where some parts have not been
24332224227818b8196ea9250235038e069f6bc03a55William M. Brack	 * escaped leading to a parsing problem.  Check that the first
2434336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	 * part matches a protocol.
2435336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	 */
2436336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	l = absuri - path;
24372224227818b8196ea9250235038e069f6bc03a55William M. Brack	/* Bypass if first part (part before the '://') is > 20 chars */
2438336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	if ((l <= 0) || (l > 20))
2439336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	    goto path_processing;
24402224227818b8196ea9250235038e069f6bc03a55William M. Brack	/* Bypass if any non-alpha characters are present in first part */
2441336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	for (j = 0;j < l;j++) {
2442336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	    c = path[j];
2443336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	    if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))))
2444336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	        goto path_processing;
2445336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	}
2446336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard
24472224227818b8196ea9250235038e069f6bc03a55William M. Brack	/* Escape all except the characters specified in the supplied path */
2448336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard        escURI = xmlURIEscapeStr(path, BAD_CAST ":/?_.#&;=");
2449336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	if (escURI != NULL) {
24502224227818b8196ea9250235038e069f6bc03a55William M. Brack	    /* Try parsing the escaped path */
2451336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	    uri = xmlParseURI((const char *) escURI);
24522224227818b8196ea9250235038e069f6bc03a55William M. Brack	    /* If successful, return the escaped string */
2453336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	    if (uri != NULL) {
2454336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	        xmlFreeURI(uri);
2455336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard		return escURI;
2456336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	    }
2457336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard	}
2458336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard    }
2459336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard
2460336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillardpath_processing:
24612224227818b8196ea9250235038e069f6bc03a55William M. Brack/* For Windows implementations, replace backslashes with 'forward slashes' */
246257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard#if defined(_WIN32) && !defined(__CYGWIN__)
2463336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard    /*
24642224227818b8196ea9250235038e069f6bc03a55William M. Brack     * Create a URI structure
2465336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard     */
2466f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic    uri = xmlCreateURI();
24672224227818b8196ea9250235038e069f6bc03a55William M. Brack    if (uri == NULL) {		/* Guard against 'out of memory' */
2468a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard        return(NULL);
2469a76fe5ca11ebf9e9322dfcf7728dc55077086d43Daniel Veillard    }
2470f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic
2471f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic    len = xmlStrlen(path);
2472f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic    if ((len > 2) && IS_WINDOWS_PATH(path)) {
24732224227818b8196ea9250235038e069f6bc03a55William M. Brack        /* make the scheme 'file' */
2474f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic	uri->scheme = xmlStrdup(BAD_CAST "file");
24752224227818b8196ea9250235038e069f6bc03a55William M. Brack	/* allocate space for leading '/' + path + string terminator */
2476b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	uri->path = xmlMallocAtomic(len + 2);
2477b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	if (uri->path == NULL) {
24782224227818b8196ea9250235038e069f6bc03a55William M. Brack	    xmlFreeURI(uri);	/* Guard agains 'out of memory' */
2479b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	    return(NULL);
2480b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	}
24812224227818b8196ea9250235038e069f6bc03a55William M. Brack	/* Put in leading '/' plus path */
2482f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic	uri->path[0] = '/';
2483ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic	p = uri->path + 1;
2484ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic	strncpy(p, path, len + 1);
2485ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic    } else {
2486b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	uri->path = xmlStrdup(path);
2487b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	if (uri->path == NULL) {
2488b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	    xmlFreeURI(uri);
2489b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	    return(NULL);
2490b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	}
2491ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic	p = uri->path;
2492ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic    }
24932224227818b8196ea9250235038e069f6bc03a55William M. Brack    /* Now change all occurences of '\' to '/' */
2494ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic    while (*p != '\0') {
2495ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic	if (*p == '\\')
2496ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic	    *p = '/';
2497ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic	p++;
2498ce07616c089bf22653e31e2f7286cfdd8462857fIgor Zlatkovic    }
24998f3392ef69ec36d34a389336c4df66bcce26969bDaniel Veillard
2500b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    if (uri->scheme == NULL) {
25012224227818b8196ea9250235038e069f6bc03a55William M. Brack	ret = xmlStrdup((const xmlChar *) uri->path);
2502b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    } else {
2503b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	ret = xmlSaveUri(uri);
2504b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    }
25058f3392ef69ec36d34a389336c4df66bcce26969bDaniel Veillard
2506f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic    xmlFreeURI(uri);
2507336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard#else
2508336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard    ret = xmlStrdup((const xmlChar *) path);
2509336a8e13bf013d6cf260c8b78a1129cef1e3662cDaniel Veillard#endif
2510f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic    return(ret);
2511f2238e6e553f0fa039ed084c436b38dbb33a0c86Igor Zlatkovic}
25123473f88a7abdf4e585e267288fb77e898c580d2bOwen Taylor
2513b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard/**
2514b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard * xmlPathToURI:
2515b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard * @path:  the resource locator in a filesystem notation
2516b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard *
2517b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard * Constructs an URI expressing the existing path
2518b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard *
251957560386503be0fd023f3b7537fd496784f3be18Daniel Veillard * Returns a new URI, or a duplicate of the path parameter if the
2520b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard * construction fails. The caller is responsible for freeing the memory
2521b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard * occupied by the returned string. If there is insufficient memory available,
2522b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard * or the argument is NULL, the function returns NULL.
2523b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard */
2524b8efdda0a31947d5291fcb9221040fdab88dc549Daniel VeillardxmlChar *
2525b8efdda0a31947d5291fcb9221040fdab88dc549Daniel VeillardxmlPathToURI(const xmlChar *path)
2526b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard{
2527b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    xmlURIPtr uri;
2528b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    xmlURI temp;
2529b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    xmlChar *ret, *cal;
2530b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard
2531b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    if (path == NULL)
2532b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard        return(NULL);
2533b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard
2534b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    if ((uri = xmlParseURI((const char *) path)) != NULL) {
2535b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	xmlFreeURI(uri);
2536b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard	return xmlStrdup(path);
2537b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    }
2538b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    cal = xmlCanonicPath(path);
2539b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    if (cal == NULL)
2540b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard        return(NULL);
2541481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard#if defined(_WIN32) && !defined(__CYGWIN__)
254257560386503be0fd023f3b7537fd496784f3be18Daniel Veillard    /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?)
2543481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard       If 'cal' is a valid URI allready then we are done here, as continuing would make
2544481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard       it invalid. */
2545481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard    if ((uri = xmlParseURI((const char *) cal)) != NULL) {
2546481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard	xmlFreeURI(uri);
2547481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard	return cal;
2548481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard    }
2549481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard    /* 'cal' can contain a relative path with backslashes. If that is processed
2550481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard       by xmlSaveURI, they will be escaped and the external entity loader machinery
2551481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard       will fail. So convert them to slashes. Misuse 'ret' for walking. */
2552481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard    ret = cal;
2553481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard    while (*ret != '\0') {
2554481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard	if (*ret == '\\')
2555481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard	    *ret = '/';
2556481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard	ret++;
2557481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard    }
2558481dcfcff3945620a05b8cdbc2f3c7aa5de7a470Daniel Veillard#endif
2559b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    memset(&temp, 0, sizeof(temp));
2560b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    temp.path = (char *) cal;
2561b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    ret = xmlSaveUri(&temp);
2562b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    xmlFree(cal);
2563b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard    return(ret);
2564b8efdda0a31947d5291fcb9221040fdab88dc549Daniel Veillard}
25655d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#define bottom_uri
25665d4644ef6e38479a648615eca758c5e962a141d5Daniel Veillard#include "elfgcchack.h"
2567