xref: /aosp_15_r20/external/cronet/third_party/libxml/src/uri.c (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker /**
2*6777b538SAndroid Build Coastguard Worker  * uri.c: set of generic URI related routines
3*6777b538SAndroid Build Coastguard Worker  *
4*6777b538SAndroid Build Coastguard Worker  * Reference: RFCs 3986, 2732 and 2373
5*6777b538SAndroid Build Coastguard Worker  *
6*6777b538SAndroid Build Coastguard Worker  * See Copyright for the status of this software.
7*6777b538SAndroid Build Coastguard Worker  *
8*6777b538SAndroid Build Coastguard Worker  * [email protected]
9*6777b538SAndroid Build Coastguard Worker  */
10*6777b538SAndroid Build Coastguard Worker 
11*6777b538SAndroid Build Coastguard Worker #define IN_LIBXML
12*6777b538SAndroid Build Coastguard Worker #include "libxml.h"
13*6777b538SAndroid Build Coastguard Worker 
14*6777b538SAndroid Build Coastguard Worker #include <limits.h>
15*6777b538SAndroid Build Coastguard Worker #include <string.h>
16*6777b538SAndroid Build Coastguard Worker 
17*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlmemory.h>
18*6777b538SAndroid Build Coastguard Worker #include <libxml/uri.h>
19*6777b538SAndroid Build Coastguard Worker #include <libxml/xmlerror.h>
20*6777b538SAndroid Build Coastguard Worker 
21*6777b538SAndroid Build Coastguard Worker #include "private/error.h"
22*6777b538SAndroid Build Coastguard Worker 
23*6777b538SAndroid Build Coastguard Worker /**
24*6777b538SAndroid Build Coastguard Worker  * MAX_URI_LENGTH:
25*6777b538SAndroid Build Coastguard Worker  *
26*6777b538SAndroid Build Coastguard Worker  * The definition of the URI regexp in the above RFC has no size limit
27*6777b538SAndroid Build Coastguard Worker  * In practice they are usually relatively short except for the
28*6777b538SAndroid Build Coastguard Worker  * data URI scheme as defined in RFC 2397. Even for data URI the usual
29*6777b538SAndroid Build Coastguard Worker  * maximum size before hitting random practical limits is around 64 KB
30*6777b538SAndroid Build Coastguard Worker  * and 4KB is usually a maximum admitted limit for proper operations.
31*6777b538SAndroid Build Coastguard Worker  * The value below is more a security limit than anything else and
32*6777b538SAndroid Build Coastguard Worker  * really should never be hit by 'normal' operations
33*6777b538SAndroid Build Coastguard Worker  * Set to 1 MByte in 2012, this is only enforced on output
34*6777b538SAndroid Build Coastguard Worker  */
35*6777b538SAndroid Build Coastguard Worker #define MAX_URI_LENGTH 1024 * 1024
36*6777b538SAndroid Build Coastguard Worker 
37*6777b538SAndroid Build Coastguard Worker #define PORT_EMPTY           0
38*6777b538SAndroid Build Coastguard Worker #define PORT_EMPTY_SERVER   -1
39*6777b538SAndroid Build Coastguard Worker 
40*6777b538SAndroid Build Coastguard Worker static void xmlCleanURI(xmlURIPtr uri);
41*6777b538SAndroid Build Coastguard Worker 
42*6777b538SAndroid Build Coastguard Worker /*
43*6777b538SAndroid Build Coastguard Worker  * Old rule from 2396 used in legacy handling code
44*6777b538SAndroid Build Coastguard Worker  * alpha    = lowalpha | upalpha
45*6777b538SAndroid Build Coastguard Worker  */
46*6777b538SAndroid Build Coastguard Worker #define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x))
47*6777b538SAndroid Build Coastguard Worker 
48*6777b538SAndroid Build Coastguard Worker 
49*6777b538SAndroid Build Coastguard Worker /*
50*6777b538SAndroid Build Coastguard Worker  * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
51*6777b538SAndroid Build Coastguard Worker  *            "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
52*6777b538SAndroid Build Coastguard Worker  *            "u" | "v" | "w" | "x" | "y" | "z"
53*6777b538SAndroid Build Coastguard Worker  */
54*6777b538SAndroid Build Coastguard Worker #define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z'))
55*6777b538SAndroid Build Coastguard Worker 
56*6777b538SAndroid Build Coastguard Worker /*
57*6777b538SAndroid Build Coastguard Worker  * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" |
58*6777b538SAndroid Build Coastguard Worker  *           "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" |
59*6777b538SAndroid Build Coastguard Worker  *           "U" | "V" | "W" | "X" | "Y" | "Z"
60*6777b538SAndroid Build Coastguard Worker  */
61*6777b538SAndroid Build Coastguard Worker #define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z'))
62*6777b538SAndroid Build Coastguard Worker 
63*6777b538SAndroid Build Coastguard Worker #ifdef IS_DIGIT
64*6777b538SAndroid Build Coastguard Worker #undef IS_DIGIT
65*6777b538SAndroid Build Coastguard Worker #endif
66*6777b538SAndroid Build Coastguard Worker /*
67*6777b538SAndroid Build Coastguard Worker  * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
68*6777b538SAndroid Build Coastguard Worker  */
69*6777b538SAndroid Build Coastguard Worker #define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9'))
70*6777b538SAndroid Build Coastguard Worker 
71*6777b538SAndroid Build Coastguard Worker /*
72*6777b538SAndroid Build Coastguard Worker  * alphanum = alpha | digit
73*6777b538SAndroid Build Coastguard Worker  */
74*6777b538SAndroid Build Coastguard Worker #define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x))
75*6777b538SAndroid Build Coastguard Worker 
76*6777b538SAndroid Build Coastguard Worker /*
77*6777b538SAndroid Build Coastguard Worker  * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
78*6777b538SAndroid Build Coastguard Worker  */
79*6777b538SAndroid Build Coastguard Worker 
80*6777b538SAndroid Build Coastguard Worker #define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') ||     \
81*6777b538SAndroid Build Coastguard Worker     ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') ||    \
82*6777b538SAndroid Build Coastguard Worker     ((x) == '(') || ((x) == ')'))
83*6777b538SAndroid Build Coastguard Worker 
84*6777b538SAndroid Build Coastguard Worker /*
85*6777b538SAndroid Build Coastguard Worker  * unwise = "{" | "}" | "|" | "\" | "^" | "`"
86*6777b538SAndroid Build Coastguard Worker  */
87*6777b538SAndroid Build Coastguard Worker #define IS_UNWISE(p)                                                    \
88*6777b538SAndroid Build Coastguard Worker       (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) ||         \
89*6777b538SAndroid Build Coastguard Worker        ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) ||        \
90*6777b538SAndroid Build Coastguard Worker        ((*(p) == ']')) || ((*(p) == '`')))
91*6777b538SAndroid Build Coastguard Worker 
92*6777b538SAndroid Build Coastguard Worker /*
93*6777b538SAndroid Build Coastguard Worker  * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," |
94*6777b538SAndroid Build Coastguard Worker  *            "[" | "]"
95*6777b538SAndroid Build Coastguard Worker  */
96*6777b538SAndroid Build Coastguard Worker #define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \
97*6777b538SAndroid Build Coastguard Worker         ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \
98*6777b538SAndroid Build Coastguard Worker         ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \
99*6777b538SAndroid Build Coastguard Worker         ((x) == ']'))
100*6777b538SAndroid Build Coastguard Worker 
101*6777b538SAndroid Build Coastguard Worker /*
102*6777b538SAndroid Build Coastguard Worker  * unreserved = alphanum | mark
103*6777b538SAndroid Build Coastguard Worker  */
104*6777b538SAndroid Build Coastguard Worker #define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x))
105*6777b538SAndroid Build Coastguard Worker 
106*6777b538SAndroid Build Coastguard Worker /*
107*6777b538SAndroid Build Coastguard Worker  * Skip to next pointer char, handle escaped sequences
108*6777b538SAndroid Build Coastguard Worker  */
109*6777b538SAndroid Build Coastguard Worker #define NEXT(p) ((*p == '%')? p += 3 : p++)
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker /*
112*6777b538SAndroid Build Coastguard Worker  * Productions from the spec.
113*6777b538SAndroid Build Coastguard Worker  *
114*6777b538SAndroid Build Coastguard Worker  *    authority     = server | reg_name
115*6777b538SAndroid Build Coastguard Worker  *    reg_name      = 1*( unreserved | escaped | "$" | "," |
116*6777b538SAndroid Build Coastguard Worker  *                        ";" | ":" | "@" | "&" | "=" | "+" )
117*6777b538SAndroid Build Coastguard Worker  *
118*6777b538SAndroid Build Coastguard Worker  * path          = [ abs_path | opaque_part ]
119*6777b538SAndroid Build Coastguard Worker  */
120*6777b538SAndroid Build Coastguard Worker #define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n))
121*6777b538SAndroid Build Coastguard Worker 
122*6777b538SAndroid Build Coastguard Worker /************************************************************************
123*6777b538SAndroid Build Coastguard Worker  *									*
124*6777b538SAndroid Build Coastguard Worker  *                         RFC 3986 parser				*
125*6777b538SAndroid Build Coastguard Worker  *									*
126*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
127*6777b538SAndroid Build Coastguard Worker 
128*6777b538SAndroid Build Coastguard Worker #define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9'))
129*6777b538SAndroid Build Coastguard Worker #define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) ||		\
130*6777b538SAndroid Build Coastguard Worker                       ((*(p) >= 'A') && (*(p) <= 'Z')))
131*6777b538SAndroid Build Coastguard Worker #define ISA_HEXDIG(p)							\
132*6777b538SAndroid Build Coastguard Worker        (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) ||		\
133*6777b538SAndroid Build Coastguard Worker         ((*(p) >= 'A') && (*(p) <= 'F')))
134*6777b538SAndroid Build Coastguard Worker 
135*6777b538SAndroid Build Coastguard Worker /*
136*6777b538SAndroid Build Coastguard Worker  *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
137*6777b538SAndroid Build Coastguard Worker  *                     / "*" / "+" / "," / ";" / "="
138*6777b538SAndroid Build Coastguard Worker  */
139*6777b538SAndroid Build Coastguard Worker #define ISA_SUB_DELIM(p)						\
140*6777b538SAndroid Build Coastguard Worker       (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) ||		\
141*6777b538SAndroid Build Coastguard Worker        ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) ||		\
142*6777b538SAndroid Build Coastguard Worker        ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) ||		\
143*6777b538SAndroid Build Coastguard Worker        ((*(p) == '=')) || ((*(p) == '\'')))
144*6777b538SAndroid Build Coastguard Worker 
145*6777b538SAndroid Build Coastguard Worker /*
146*6777b538SAndroid Build Coastguard Worker  *    gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
147*6777b538SAndroid Build Coastguard Worker  */
148*6777b538SAndroid Build Coastguard Worker #define ISA_GEN_DELIM(p)						\
149*6777b538SAndroid Build Coastguard Worker       (((*(p) == ':')) || ((*(p) == '/')) || ((*(p) == '?')) ||         \
150*6777b538SAndroid Build Coastguard Worker        ((*(p) == '#')) || ((*(p) == '[')) || ((*(p) == ']')) ||         \
151*6777b538SAndroid Build Coastguard Worker        ((*(p) == '@')))
152*6777b538SAndroid Build Coastguard Worker 
153*6777b538SAndroid Build Coastguard Worker /*
154*6777b538SAndroid Build Coastguard Worker  *    reserved      = gen-delims / sub-delims
155*6777b538SAndroid Build Coastguard Worker  */
156*6777b538SAndroid Build Coastguard Worker #define ISA_RESERVED(p) (ISA_GEN_DELIM(p) || (ISA_SUB_DELIM(p)))
157*6777b538SAndroid Build Coastguard Worker 
158*6777b538SAndroid Build Coastguard Worker /*
159*6777b538SAndroid Build Coastguard Worker  *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
160*6777b538SAndroid Build Coastguard Worker  */
161*6777b538SAndroid Build Coastguard Worker #define ISA_STRICTLY_UNRESERVED(p)					\
162*6777b538SAndroid Build Coastguard Worker       ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) ||		\
163*6777b538SAndroid Build Coastguard Worker        ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~')))
164*6777b538SAndroid Build Coastguard Worker 
165*6777b538SAndroid Build Coastguard Worker /*
166*6777b538SAndroid Build Coastguard Worker  *    pct-encoded   = "%" HEXDIG HEXDIG
167*6777b538SAndroid Build Coastguard Worker  */
168*6777b538SAndroid Build Coastguard Worker #define ISA_PCT_ENCODED(p)						\
169*6777b538SAndroid Build Coastguard Worker      ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2)))
170*6777b538SAndroid Build Coastguard Worker 
171*6777b538SAndroid Build Coastguard Worker /*
172*6777b538SAndroid Build Coastguard Worker  *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
173*6777b538SAndroid Build Coastguard Worker  */
174*6777b538SAndroid Build Coastguard Worker #define ISA_PCHAR(u, p)							\
175*6777b538SAndroid Build Coastguard Worker      (ISA_UNRESERVED(u, p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) ||	\
176*6777b538SAndroid Build Coastguard Worker       ((*(p) == ':')) || ((*(p) == '@')))
177*6777b538SAndroid Build Coastguard Worker 
178*6777b538SAndroid Build Coastguard Worker /*
179*6777b538SAndroid Build Coastguard Worker  * From https://www.w3.org/TR/leiri/
180*6777b538SAndroid Build Coastguard Worker  *
181*6777b538SAndroid Build Coastguard Worker  * " " / "<" / ">" / '"' / "{" / "}" / "|"
182*6777b538SAndroid Build Coastguard Worker  * / "\" / "^" / "`" / %x0-1F / %x7F-D7FF
183*6777b538SAndroid Build Coastguard Worker  * / %xE000-FFFD / %x10000-10FFFF
184*6777b538SAndroid Build Coastguard Worker  */
185*6777b538SAndroid Build Coastguard Worker #define ISA_UCSCHAR(p) \
186*6777b538SAndroid Build Coastguard Worker     ((*(p) <= 0x20) || (*(p) >= 0x7F) || (*(p) == '<') || (*(p) == '>') || \
187*6777b538SAndroid Build Coastguard Worker      (*(p) == '"')  || (*(p) == '{')  || (*(p) == '}') || (*(p) == '|') || \
188*6777b538SAndroid Build Coastguard Worker      (*(p) == '\\') || (*(p) == '^')  || (*(p) == '`'))
189*6777b538SAndroid Build Coastguard Worker 
190*6777b538SAndroid Build Coastguard Worker #define ISA_UNRESERVED(u, p) (xmlIsUnreserved(u, p))
191*6777b538SAndroid Build Coastguard Worker 
192*6777b538SAndroid Build Coastguard Worker #define XML_URI_ALLOW_UNWISE    1
193*6777b538SAndroid Build Coastguard Worker #define XML_URI_NO_UNESCAPE     2
194*6777b538SAndroid Build Coastguard Worker #define XML_URI_ALLOW_UCSCHAR   4
195*6777b538SAndroid Build Coastguard Worker 
196*6777b538SAndroid Build Coastguard Worker static int
xmlIsUnreserved(xmlURIPtr uri,const char * cur)197*6777b538SAndroid Build Coastguard Worker xmlIsUnreserved(xmlURIPtr uri, const char *cur) {
198*6777b538SAndroid Build Coastguard Worker     if (uri == NULL)
199*6777b538SAndroid Build Coastguard Worker         return(0);
200*6777b538SAndroid Build Coastguard Worker 
201*6777b538SAndroid Build Coastguard Worker     if (ISA_STRICTLY_UNRESERVED(cur))
202*6777b538SAndroid Build Coastguard Worker         return(1);
203*6777b538SAndroid Build Coastguard Worker 
204*6777b538SAndroid Build Coastguard Worker     if (uri->cleanup & XML_URI_ALLOW_UNWISE) {
205*6777b538SAndroid Build Coastguard Worker         if (IS_UNWISE(cur))
206*6777b538SAndroid Build Coastguard Worker             return(1);
207*6777b538SAndroid Build Coastguard Worker     } else if (uri->cleanup & XML_URI_ALLOW_UCSCHAR) {
208*6777b538SAndroid Build Coastguard Worker         if (ISA_UCSCHAR(cur))
209*6777b538SAndroid Build Coastguard Worker             return(1);
210*6777b538SAndroid Build Coastguard Worker     }
211*6777b538SAndroid Build Coastguard Worker 
212*6777b538SAndroid Build Coastguard Worker     return(0);
213*6777b538SAndroid Build Coastguard Worker }
214*6777b538SAndroid Build Coastguard Worker 
215*6777b538SAndroid Build Coastguard Worker /**
216*6777b538SAndroid Build Coastguard Worker  * xmlParse3986Scheme:
217*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
218*6777b538SAndroid Build Coastguard Worker  * @str:  pointer to the string to analyze
219*6777b538SAndroid Build Coastguard Worker  *
220*6777b538SAndroid Build Coastguard Worker  * Parse an URI scheme
221*6777b538SAndroid Build Coastguard Worker  *
222*6777b538SAndroid Build Coastguard Worker  * ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
223*6777b538SAndroid Build Coastguard Worker  *
224*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
225*6777b538SAndroid Build Coastguard Worker  */
226*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986Scheme(xmlURIPtr uri,const char ** str)227*6777b538SAndroid Build Coastguard Worker xmlParse3986Scheme(xmlURIPtr uri, const char **str) {
228*6777b538SAndroid Build Coastguard Worker     const char *cur;
229*6777b538SAndroid Build Coastguard Worker 
230*6777b538SAndroid Build Coastguard Worker     cur = *str;
231*6777b538SAndroid Build Coastguard Worker     if (!ISA_ALPHA(cur))
232*6777b538SAndroid Build Coastguard Worker 	return(1);
233*6777b538SAndroid Build Coastguard Worker     cur++;
234*6777b538SAndroid Build Coastguard Worker     while (ISA_ALPHA(cur) || ISA_DIGIT(cur) ||
235*6777b538SAndroid Build Coastguard Worker            (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++;
236*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
237*6777b538SAndroid Build Coastguard Worker 	if (uri->scheme != NULL) xmlFree(uri->scheme);
238*6777b538SAndroid Build Coastguard Worker 	uri->scheme = STRNDUP(*str, cur - *str);
239*6777b538SAndroid Build Coastguard Worker         if (uri->scheme == NULL)
240*6777b538SAndroid Build Coastguard Worker             return(-1);
241*6777b538SAndroid Build Coastguard Worker     }
242*6777b538SAndroid Build Coastguard Worker     *str = cur;
243*6777b538SAndroid Build Coastguard Worker     return(0);
244*6777b538SAndroid Build Coastguard Worker }
245*6777b538SAndroid Build Coastguard Worker 
246*6777b538SAndroid Build Coastguard Worker /**
247*6777b538SAndroid Build Coastguard Worker  * xmlParse3986Fragment:
248*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
249*6777b538SAndroid Build Coastguard Worker  * @str:  pointer to the string to analyze
250*6777b538SAndroid Build Coastguard Worker  *
251*6777b538SAndroid Build Coastguard Worker  * Parse the query part of an URI
252*6777b538SAndroid Build Coastguard Worker  *
253*6777b538SAndroid Build Coastguard Worker  * fragment      = *( pchar / "/" / "?" )
254*6777b538SAndroid Build Coastguard Worker  * NOTE: the strict syntax as defined by 3986 does not allow '[' and ']'
255*6777b538SAndroid Build Coastguard Worker  *       in the fragment identifier but this is used very broadly for
256*6777b538SAndroid Build Coastguard Worker  *       xpointer scheme selection, so we are allowing it here to not break
257*6777b538SAndroid Build Coastguard Worker  *       for example all the DocBook processing chains.
258*6777b538SAndroid Build Coastguard Worker  *
259*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
260*6777b538SAndroid Build Coastguard Worker  */
261*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986Fragment(xmlURIPtr uri,const char ** str)262*6777b538SAndroid Build Coastguard Worker xmlParse3986Fragment(xmlURIPtr uri, const char **str)
263*6777b538SAndroid Build Coastguard Worker {
264*6777b538SAndroid Build Coastguard Worker     const char *cur;
265*6777b538SAndroid Build Coastguard Worker 
266*6777b538SAndroid Build Coastguard Worker     cur = *str;
267*6777b538SAndroid Build Coastguard Worker 
268*6777b538SAndroid Build Coastguard Worker     while ((ISA_PCHAR(uri, cur)) || (*cur == '/') || (*cur == '?') ||
269*6777b538SAndroid Build Coastguard Worker            (*cur == '[') || (*cur == ']'))
270*6777b538SAndroid Build Coastguard Worker         NEXT(cur);
271*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
272*6777b538SAndroid Build Coastguard Worker         if (uri->fragment != NULL)
273*6777b538SAndroid Build Coastguard Worker             xmlFree(uri->fragment);
274*6777b538SAndroid Build Coastguard Worker 	if (uri->cleanup & XML_URI_NO_UNESCAPE)
275*6777b538SAndroid Build Coastguard Worker 	    uri->fragment = STRNDUP(*str, cur - *str);
276*6777b538SAndroid Build Coastguard Worker 	else
277*6777b538SAndroid Build Coastguard Worker 	    uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL);
278*6777b538SAndroid Build Coastguard Worker         if (uri->fragment == NULL)
279*6777b538SAndroid Build Coastguard Worker             return (-1);
280*6777b538SAndroid Build Coastguard Worker     }
281*6777b538SAndroid Build Coastguard Worker     *str = cur;
282*6777b538SAndroid Build Coastguard Worker     return (0);
283*6777b538SAndroid Build Coastguard Worker }
284*6777b538SAndroid Build Coastguard Worker 
285*6777b538SAndroid Build Coastguard Worker /**
286*6777b538SAndroid Build Coastguard Worker  * xmlParse3986Query:
287*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
288*6777b538SAndroid Build Coastguard Worker  * @str:  pointer to the string to analyze
289*6777b538SAndroid Build Coastguard Worker  *
290*6777b538SAndroid Build Coastguard Worker  * Parse the query part of an URI
291*6777b538SAndroid Build Coastguard Worker  *
292*6777b538SAndroid Build Coastguard Worker  * query = *uric
293*6777b538SAndroid Build Coastguard Worker  *
294*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
295*6777b538SAndroid Build Coastguard Worker  */
296*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986Query(xmlURIPtr uri,const char ** str)297*6777b538SAndroid Build Coastguard Worker xmlParse3986Query(xmlURIPtr uri, const char **str)
298*6777b538SAndroid Build Coastguard Worker {
299*6777b538SAndroid Build Coastguard Worker     const char *cur;
300*6777b538SAndroid Build Coastguard Worker 
301*6777b538SAndroid Build Coastguard Worker     cur = *str;
302*6777b538SAndroid Build Coastguard Worker 
303*6777b538SAndroid Build Coastguard Worker     while ((ISA_PCHAR(uri, cur)) || (*cur == '/') || (*cur == '?'))
304*6777b538SAndroid Build Coastguard Worker         NEXT(cur);
305*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
306*6777b538SAndroid Build Coastguard Worker         if (uri->query != NULL)
307*6777b538SAndroid Build Coastguard Worker             xmlFree(uri->query);
308*6777b538SAndroid Build Coastguard Worker 	if (uri->cleanup & XML_URI_NO_UNESCAPE)
309*6777b538SAndroid Build Coastguard Worker 	    uri->query = STRNDUP(*str, cur - *str);
310*6777b538SAndroid Build Coastguard Worker 	else
311*6777b538SAndroid Build Coastguard Worker 	    uri->query = xmlURIUnescapeString(*str, cur - *str, NULL);
312*6777b538SAndroid Build Coastguard Worker         if (uri->query == NULL)
313*6777b538SAndroid Build Coastguard Worker             return (-1);
314*6777b538SAndroid Build Coastguard Worker 
315*6777b538SAndroid Build Coastguard Worker 	/* Save the raw bytes of the query as well.
316*6777b538SAndroid Build Coastguard Worker 	 * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114
317*6777b538SAndroid Build Coastguard Worker 	 */
318*6777b538SAndroid Build Coastguard Worker 	if (uri->query_raw != NULL)
319*6777b538SAndroid Build Coastguard Worker 	    xmlFree (uri->query_raw);
320*6777b538SAndroid Build Coastguard Worker 	uri->query_raw = STRNDUP (*str, cur - *str);
321*6777b538SAndroid Build Coastguard Worker         if (uri->query_raw == NULL)
322*6777b538SAndroid Build Coastguard Worker             return (-1);
323*6777b538SAndroid Build Coastguard Worker     }
324*6777b538SAndroid Build Coastguard Worker     *str = cur;
325*6777b538SAndroid Build Coastguard Worker     return (0);
326*6777b538SAndroid Build Coastguard Worker }
327*6777b538SAndroid Build Coastguard Worker 
328*6777b538SAndroid Build Coastguard Worker /**
329*6777b538SAndroid Build Coastguard Worker  * xmlParse3986Port:
330*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
331*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
332*6777b538SAndroid Build Coastguard Worker  *
333*6777b538SAndroid Build Coastguard Worker  * Parse a port part and fills in the appropriate fields
334*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
335*6777b538SAndroid Build Coastguard Worker  *
336*6777b538SAndroid Build Coastguard Worker  * port          = *DIGIT
337*6777b538SAndroid Build Coastguard Worker  *
338*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
339*6777b538SAndroid Build Coastguard Worker  */
340*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986Port(xmlURIPtr uri,const char ** str)341*6777b538SAndroid Build Coastguard Worker xmlParse3986Port(xmlURIPtr uri, const char **str)
342*6777b538SAndroid Build Coastguard Worker {
343*6777b538SAndroid Build Coastguard Worker     const char *cur = *str;
344*6777b538SAndroid Build Coastguard Worker     int port = 0;
345*6777b538SAndroid Build Coastguard Worker 
346*6777b538SAndroid Build Coastguard Worker     if (ISA_DIGIT(cur)) {
347*6777b538SAndroid Build Coastguard Worker 	while (ISA_DIGIT(cur)) {
348*6777b538SAndroid Build Coastguard Worker             int digit = *cur - '0';
349*6777b538SAndroid Build Coastguard Worker 
350*6777b538SAndroid Build Coastguard Worker             if (port > INT_MAX / 10)
351*6777b538SAndroid Build Coastguard Worker                 return(1);
352*6777b538SAndroid Build Coastguard Worker             port *= 10;
353*6777b538SAndroid Build Coastguard Worker             if (port > INT_MAX - digit)
354*6777b538SAndroid Build Coastguard Worker                 return(1);
355*6777b538SAndroid Build Coastguard Worker 	    port += digit;
356*6777b538SAndroid Build Coastguard Worker 
357*6777b538SAndroid Build Coastguard Worker 	    cur++;
358*6777b538SAndroid Build Coastguard Worker 	}
359*6777b538SAndroid Build Coastguard Worker 	if (uri != NULL)
360*6777b538SAndroid Build Coastguard Worker 	    uri->port = port;
361*6777b538SAndroid Build Coastguard Worker 	*str = cur;
362*6777b538SAndroid Build Coastguard Worker 	return(0);
363*6777b538SAndroid Build Coastguard Worker     }
364*6777b538SAndroid Build Coastguard Worker     return(1);
365*6777b538SAndroid Build Coastguard Worker }
366*6777b538SAndroid Build Coastguard Worker 
367*6777b538SAndroid Build Coastguard Worker /**
368*6777b538SAndroid Build Coastguard Worker  * xmlParse3986Userinfo:
369*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
370*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
371*6777b538SAndroid Build Coastguard Worker  *
372*6777b538SAndroid Build Coastguard Worker  * Parse an user information part and fills in the appropriate fields
373*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
374*6777b538SAndroid Build Coastguard Worker  *
375*6777b538SAndroid Build Coastguard Worker  * userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
376*6777b538SAndroid Build Coastguard Worker  *
377*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
378*6777b538SAndroid Build Coastguard Worker  */
379*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986Userinfo(xmlURIPtr uri,const char ** str)380*6777b538SAndroid Build Coastguard Worker xmlParse3986Userinfo(xmlURIPtr uri, const char **str)
381*6777b538SAndroid Build Coastguard Worker {
382*6777b538SAndroid Build Coastguard Worker     const char *cur;
383*6777b538SAndroid Build Coastguard Worker 
384*6777b538SAndroid Build Coastguard Worker     cur = *str;
385*6777b538SAndroid Build Coastguard Worker     while (ISA_UNRESERVED(uri, cur) || ISA_PCT_ENCODED(cur) ||
386*6777b538SAndroid Build Coastguard Worker            ISA_SUB_DELIM(cur) || (*cur == ':'))
387*6777b538SAndroid Build Coastguard Worker 	NEXT(cur);
388*6777b538SAndroid Build Coastguard Worker     if (*cur == '@') {
389*6777b538SAndroid Build Coastguard Worker 	if (uri != NULL) {
390*6777b538SAndroid Build Coastguard Worker 	    if (uri->user != NULL) xmlFree(uri->user);
391*6777b538SAndroid Build Coastguard Worker 	    if (uri->cleanup & XML_URI_NO_UNESCAPE)
392*6777b538SAndroid Build Coastguard Worker 		uri->user = STRNDUP(*str, cur - *str);
393*6777b538SAndroid Build Coastguard Worker 	    else
394*6777b538SAndroid Build Coastguard Worker 		uri->user = xmlURIUnescapeString(*str, cur - *str, NULL);
395*6777b538SAndroid Build Coastguard Worker             if (uri->user == NULL)
396*6777b538SAndroid Build Coastguard Worker                 return(-1);
397*6777b538SAndroid Build Coastguard Worker 	}
398*6777b538SAndroid Build Coastguard Worker 	*str = cur;
399*6777b538SAndroid Build Coastguard Worker 	return(0);
400*6777b538SAndroid Build Coastguard Worker     }
401*6777b538SAndroid Build Coastguard Worker     return(1);
402*6777b538SAndroid Build Coastguard Worker }
403*6777b538SAndroid Build Coastguard Worker 
404*6777b538SAndroid Build Coastguard Worker /**
405*6777b538SAndroid Build Coastguard Worker  * xmlParse3986DecOctet:
406*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
407*6777b538SAndroid Build Coastguard Worker  *
408*6777b538SAndroid Build Coastguard Worker  *    dec-octet     = DIGIT                 ; 0-9
409*6777b538SAndroid Build Coastguard Worker  *                  / %x31-39 DIGIT         ; 10-99
410*6777b538SAndroid Build Coastguard Worker  *                  / "1" 2DIGIT            ; 100-199
411*6777b538SAndroid Build Coastguard Worker  *                  / "2" %x30-34 DIGIT     ; 200-249
412*6777b538SAndroid Build Coastguard Worker  *                  / "25" %x30-35          ; 250-255
413*6777b538SAndroid Build Coastguard Worker  *
414*6777b538SAndroid Build Coastguard Worker  * Skip a dec-octet.
415*6777b538SAndroid Build Coastguard Worker  *
416*6777b538SAndroid Build Coastguard Worker  * Returns 0 if found and skipped, 1 otherwise
417*6777b538SAndroid Build Coastguard Worker  */
418*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986DecOctet(const char ** str)419*6777b538SAndroid Build Coastguard Worker xmlParse3986DecOctet(const char **str) {
420*6777b538SAndroid Build Coastguard Worker     const char *cur = *str;
421*6777b538SAndroid Build Coastguard Worker 
422*6777b538SAndroid Build Coastguard Worker     if (!(ISA_DIGIT(cur)))
423*6777b538SAndroid Build Coastguard Worker         return(1);
424*6777b538SAndroid Build Coastguard Worker     if (!ISA_DIGIT(cur+1))
425*6777b538SAndroid Build Coastguard Worker 	cur++;
426*6777b538SAndroid Build Coastguard Worker     else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur+2)))
427*6777b538SAndroid Build Coastguard Worker 	cur += 2;
428*6777b538SAndroid Build Coastguard Worker     else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2)))
429*6777b538SAndroid Build Coastguard Worker 	cur += 3;
430*6777b538SAndroid Build Coastguard Worker     else if ((*cur == '2') && (*(cur + 1) >= '0') &&
431*6777b538SAndroid Build Coastguard Worker 	     (*(cur + 1) <= '4') && (ISA_DIGIT(cur + 2)))
432*6777b538SAndroid Build Coastguard Worker 	cur += 3;
433*6777b538SAndroid Build Coastguard Worker     else if ((*cur == '2') && (*(cur + 1) == '5') &&
434*6777b538SAndroid Build Coastguard Worker 	     (*(cur + 2) >= '0') && (*(cur + 1) <= '5'))
435*6777b538SAndroid Build Coastguard Worker 	cur += 3;
436*6777b538SAndroid Build Coastguard Worker     else
437*6777b538SAndroid Build Coastguard Worker         return(1);
438*6777b538SAndroid Build Coastguard Worker     *str = cur;
439*6777b538SAndroid Build Coastguard Worker     return(0);
440*6777b538SAndroid Build Coastguard Worker }
441*6777b538SAndroid Build Coastguard Worker /**
442*6777b538SAndroid Build Coastguard Worker  * xmlParse3986Host:
443*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
444*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
445*6777b538SAndroid Build Coastguard Worker  *
446*6777b538SAndroid Build Coastguard Worker  * Parse an host part and fills in the appropriate fields
447*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
448*6777b538SAndroid Build Coastguard Worker  *
449*6777b538SAndroid Build Coastguard Worker  * host          = IP-literal / IPv4address / reg-name
450*6777b538SAndroid Build Coastguard Worker  * IP-literal    = "[" ( IPv6address / IPvFuture  ) "]"
451*6777b538SAndroid Build Coastguard Worker  * IPv4address   = dec-octet "." dec-octet "." dec-octet "." dec-octet
452*6777b538SAndroid Build Coastguard Worker  * reg-name      = *( unreserved / pct-encoded / sub-delims )
453*6777b538SAndroid Build Coastguard Worker  *
454*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
455*6777b538SAndroid Build Coastguard Worker  */
456*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986Host(xmlURIPtr uri,const char ** str)457*6777b538SAndroid Build Coastguard Worker xmlParse3986Host(xmlURIPtr uri, const char **str)
458*6777b538SAndroid Build Coastguard Worker {
459*6777b538SAndroid Build Coastguard Worker     const char *cur = *str;
460*6777b538SAndroid Build Coastguard Worker     const char *host;
461*6777b538SAndroid Build Coastguard Worker 
462*6777b538SAndroid Build Coastguard Worker     host = cur;
463*6777b538SAndroid Build Coastguard Worker     /*
464*6777b538SAndroid Build Coastguard Worker      * IPv6 and future addressing scheme are enclosed between brackets
465*6777b538SAndroid Build Coastguard Worker      */
466*6777b538SAndroid Build Coastguard Worker     if (*cur == '[') {
467*6777b538SAndroid Build Coastguard Worker         cur++;
468*6777b538SAndroid Build Coastguard Worker 	while ((*cur != ']') && (*cur != 0))
469*6777b538SAndroid Build Coastguard Worker 	    cur++;
470*6777b538SAndroid Build Coastguard Worker 	if (*cur != ']')
471*6777b538SAndroid Build Coastguard Worker 	    return(1);
472*6777b538SAndroid Build Coastguard Worker 	cur++;
473*6777b538SAndroid Build Coastguard Worker 	goto found;
474*6777b538SAndroid Build Coastguard Worker     }
475*6777b538SAndroid Build Coastguard Worker     /*
476*6777b538SAndroid Build Coastguard Worker      * try to parse an IPv4
477*6777b538SAndroid Build Coastguard Worker      */
478*6777b538SAndroid Build Coastguard Worker     if (ISA_DIGIT(cur)) {
479*6777b538SAndroid Build Coastguard Worker         if (xmlParse3986DecOctet(&cur) != 0)
480*6777b538SAndroid Build Coastguard Worker 	    goto not_ipv4;
481*6777b538SAndroid Build Coastguard Worker 	if (*cur != '.')
482*6777b538SAndroid Build Coastguard Worker 	    goto not_ipv4;
483*6777b538SAndroid Build Coastguard Worker 	cur++;
484*6777b538SAndroid Build Coastguard Worker         if (xmlParse3986DecOctet(&cur) != 0)
485*6777b538SAndroid Build Coastguard Worker 	    goto not_ipv4;
486*6777b538SAndroid Build Coastguard Worker 	if (*cur != '.')
487*6777b538SAndroid Build Coastguard Worker 	    goto not_ipv4;
488*6777b538SAndroid Build Coastguard Worker         if (xmlParse3986DecOctet(&cur) != 0)
489*6777b538SAndroid Build Coastguard Worker 	    goto not_ipv4;
490*6777b538SAndroid Build Coastguard Worker 	if (*cur != '.')
491*6777b538SAndroid Build Coastguard Worker 	    goto not_ipv4;
492*6777b538SAndroid Build Coastguard Worker         if (xmlParse3986DecOctet(&cur) != 0)
493*6777b538SAndroid Build Coastguard Worker 	    goto not_ipv4;
494*6777b538SAndroid Build Coastguard Worker 	goto found;
495*6777b538SAndroid Build Coastguard Worker not_ipv4:
496*6777b538SAndroid Build Coastguard Worker         cur = *str;
497*6777b538SAndroid Build Coastguard Worker     }
498*6777b538SAndroid Build Coastguard Worker     /*
499*6777b538SAndroid Build Coastguard Worker      * then this should be a hostname which can be empty
500*6777b538SAndroid Build Coastguard Worker      */
501*6777b538SAndroid Build Coastguard Worker     while (ISA_UNRESERVED(uri, cur) ||
502*6777b538SAndroid Build Coastguard Worker            ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur))
503*6777b538SAndroid Build Coastguard Worker         NEXT(cur);
504*6777b538SAndroid Build Coastguard Worker found:
505*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
506*6777b538SAndroid Build Coastguard Worker 	if (uri->authority != NULL) xmlFree(uri->authority);
507*6777b538SAndroid Build Coastguard Worker 	uri->authority = NULL;
508*6777b538SAndroid Build Coastguard Worker 	if (uri->server != NULL) xmlFree(uri->server);
509*6777b538SAndroid Build Coastguard Worker 	if (cur != host) {
510*6777b538SAndroid Build Coastguard Worker 	    if (uri->cleanup & XML_URI_NO_UNESCAPE)
511*6777b538SAndroid Build Coastguard Worker 		uri->server = STRNDUP(host, cur - host);
512*6777b538SAndroid Build Coastguard Worker 	    else
513*6777b538SAndroid Build Coastguard Worker 		uri->server = xmlURIUnescapeString(host, cur - host, NULL);
514*6777b538SAndroid Build Coastguard Worker             if (uri->server == NULL)
515*6777b538SAndroid Build Coastguard Worker                 return(-1);
516*6777b538SAndroid Build Coastguard Worker 	} else
517*6777b538SAndroid Build Coastguard Worker 	    uri->server = NULL;
518*6777b538SAndroid Build Coastguard Worker     }
519*6777b538SAndroid Build Coastguard Worker     *str = cur;
520*6777b538SAndroid Build Coastguard Worker     return(0);
521*6777b538SAndroid Build Coastguard Worker }
522*6777b538SAndroid Build Coastguard Worker 
523*6777b538SAndroid Build Coastguard Worker /**
524*6777b538SAndroid Build Coastguard Worker  * xmlParse3986Authority:
525*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
526*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
527*6777b538SAndroid Build Coastguard Worker  *
528*6777b538SAndroid Build Coastguard Worker  * Parse an authority part and fills in the appropriate fields
529*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
530*6777b538SAndroid Build Coastguard Worker  *
531*6777b538SAndroid Build Coastguard Worker  * authority     = [ userinfo "@" ] host [ ":" port ]
532*6777b538SAndroid Build Coastguard Worker  *
533*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
534*6777b538SAndroid Build Coastguard Worker  */
535*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986Authority(xmlURIPtr uri,const char ** str)536*6777b538SAndroid Build Coastguard Worker xmlParse3986Authority(xmlURIPtr uri, const char **str)
537*6777b538SAndroid Build Coastguard Worker {
538*6777b538SAndroid Build Coastguard Worker     const char *cur;
539*6777b538SAndroid Build Coastguard Worker     int ret;
540*6777b538SAndroid Build Coastguard Worker 
541*6777b538SAndroid Build Coastguard Worker     cur = *str;
542*6777b538SAndroid Build Coastguard Worker     /*
543*6777b538SAndroid Build Coastguard Worker      * try to parse an userinfo and check for the trailing @
544*6777b538SAndroid Build Coastguard Worker      */
545*6777b538SAndroid Build Coastguard Worker     ret = xmlParse3986Userinfo(uri, &cur);
546*6777b538SAndroid Build Coastguard Worker     if (ret < 0)
547*6777b538SAndroid Build Coastguard Worker         return(ret);
548*6777b538SAndroid Build Coastguard Worker     if ((ret != 0) || (*cur != '@'))
549*6777b538SAndroid Build Coastguard Worker         cur = *str;
550*6777b538SAndroid Build Coastguard Worker     else
551*6777b538SAndroid Build Coastguard Worker         cur++;
552*6777b538SAndroid Build Coastguard Worker     ret = xmlParse3986Host(uri, &cur);
553*6777b538SAndroid Build Coastguard Worker     if (ret != 0) return(ret);
554*6777b538SAndroid Build Coastguard Worker     if (*cur == ':') {
555*6777b538SAndroid Build Coastguard Worker         cur++;
556*6777b538SAndroid Build Coastguard Worker         ret = xmlParse3986Port(uri, &cur);
557*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
558*6777b538SAndroid Build Coastguard Worker     }
559*6777b538SAndroid Build Coastguard Worker     *str = cur;
560*6777b538SAndroid Build Coastguard Worker     return(0);
561*6777b538SAndroid Build Coastguard Worker }
562*6777b538SAndroid Build Coastguard Worker 
563*6777b538SAndroid Build Coastguard Worker /**
564*6777b538SAndroid Build Coastguard Worker  * xmlParse3986Segment:
565*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
566*6777b538SAndroid Build Coastguard Worker  * @forbid: an optional forbidden character
567*6777b538SAndroid Build Coastguard Worker  * @empty: allow an empty segment
568*6777b538SAndroid Build Coastguard Worker  *
569*6777b538SAndroid Build Coastguard Worker  * Parse a segment and fills in the appropriate fields
570*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
571*6777b538SAndroid Build Coastguard Worker  *
572*6777b538SAndroid Build Coastguard Worker  * segment       = *pchar
573*6777b538SAndroid Build Coastguard Worker  * segment-nz    = 1*pchar
574*6777b538SAndroid Build Coastguard Worker  * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
575*6777b538SAndroid Build Coastguard Worker  *               ; non-zero-length segment without any colon ":"
576*6777b538SAndroid Build Coastguard Worker  *
577*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
578*6777b538SAndroid Build Coastguard Worker  */
579*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986Segment(xmlURIPtr uri,const char ** str,char forbid,int empty)580*6777b538SAndroid Build Coastguard Worker xmlParse3986Segment(xmlURIPtr uri, const char **str, char forbid, int empty)
581*6777b538SAndroid Build Coastguard Worker {
582*6777b538SAndroid Build Coastguard Worker     const char *cur;
583*6777b538SAndroid Build Coastguard Worker 
584*6777b538SAndroid Build Coastguard Worker     cur = *str;
585*6777b538SAndroid Build Coastguard Worker     if (!ISA_PCHAR(uri, cur)) {
586*6777b538SAndroid Build Coastguard Worker         if (empty)
587*6777b538SAndroid Build Coastguard Worker 	    return(0);
588*6777b538SAndroid Build Coastguard Worker 	return(1);
589*6777b538SAndroid Build Coastguard Worker     }
590*6777b538SAndroid Build Coastguard Worker     while (ISA_PCHAR(uri, cur) && (*cur != forbid))
591*6777b538SAndroid Build Coastguard Worker         NEXT(cur);
592*6777b538SAndroid Build Coastguard Worker     *str = cur;
593*6777b538SAndroid Build Coastguard Worker     return (0);
594*6777b538SAndroid Build Coastguard Worker }
595*6777b538SAndroid Build Coastguard Worker 
596*6777b538SAndroid Build Coastguard Worker /**
597*6777b538SAndroid Build Coastguard Worker  * xmlParse3986PathAbEmpty:
598*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
599*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
600*6777b538SAndroid Build Coastguard Worker  *
601*6777b538SAndroid Build Coastguard Worker  * Parse an path absolute or empty and fills in the appropriate fields
602*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
603*6777b538SAndroid Build Coastguard Worker  *
604*6777b538SAndroid Build Coastguard Worker  * path-abempty  = *( "/" segment )
605*6777b538SAndroid Build Coastguard Worker  *
606*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
607*6777b538SAndroid Build Coastguard Worker  */
608*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986PathAbEmpty(xmlURIPtr uri,const char ** str)609*6777b538SAndroid Build Coastguard Worker xmlParse3986PathAbEmpty(xmlURIPtr uri, const char **str)
610*6777b538SAndroid Build Coastguard Worker {
611*6777b538SAndroid Build Coastguard Worker     const char *cur;
612*6777b538SAndroid Build Coastguard Worker     int ret;
613*6777b538SAndroid Build Coastguard Worker 
614*6777b538SAndroid Build Coastguard Worker     cur = *str;
615*6777b538SAndroid Build Coastguard Worker 
616*6777b538SAndroid Build Coastguard Worker     while (*cur == '/') {
617*6777b538SAndroid Build Coastguard Worker         cur++;
618*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986Segment(uri, &cur, 0, 1);
619*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
620*6777b538SAndroid Build Coastguard Worker     }
621*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
622*6777b538SAndroid Build Coastguard Worker 	if (uri->path != NULL) xmlFree(uri->path);
623*6777b538SAndroid Build Coastguard Worker         if (*str != cur) {
624*6777b538SAndroid Build Coastguard Worker             if (uri->cleanup & XML_URI_NO_UNESCAPE)
625*6777b538SAndroid Build Coastguard Worker                 uri->path = STRNDUP(*str, cur - *str);
626*6777b538SAndroid Build Coastguard Worker             else
627*6777b538SAndroid Build Coastguard Worker                 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
628*6777b538SAndroid Build Coastguard Worker             if (uri->path == NULL)
629*6777b538SAndroid Build Coastguard Worker                 return (-1);
630*6777b538SAndroid Build Coastguard Worker         } else {
631*6777b538SAndroid Build Coastguard Worker             uri->path = NULL;
632*6777b538SAndroid Build Coastguard Worker         }
633*6777b538SAndroid Build Coastguard Worker     }
634*6777b538SAndroid Build Coastguard Worker     *str = cur;
635*6777b538SAndroid Build Coastguard Worker     return (0);
636*6777b538SAndroid Build Coastguard Worker }
637*6777b538SAndroid Build Coastguard Worker 
638*6777b538SAndroid Build Coastguard Worker /**
639*6777b538SAndroid Build Coastguard Worker  * xmlParse3986PathAbsolute:
640*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
641*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
642*6777b538SAndroid Build Coastguard Worker  *
643*6777b538SAndroid Build Coastguard Worker  * Parse an path absolute and fills in the appropriate fields
644*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
645*6777b538SAndroid Build Coastguard Worker  *
646*6777b538SAndroid Build Coastguard Worker  * path-absolute = "/" [ segment-nz *( "/" segment ) ]
647*6777b538SAndroid Build Coastguard Worker  *
648*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
649*6777b538SAndroid Build Coastguard Worker  */
650*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986PathAbsolute(xmlURIPtr uri,const char ** str)651*6777b538SAndroid Build Coastguard Worker xmlParse3986PathAbsolute(xmlURIPtr uri, const char **str)
652*6777b538SAndroid Build Coastguard Worker {
653*6777b538SAndroid Build Coastguard Worker     const char *cur;
654*6777b538SAndroid Build Coastguard Worker     int ret;
655*6777b538SAndroid Build Coastguard Worker 
656*6777b538SAndroid Build Coastguard Worker     cur = *str;
657*6777b538SAndroid Build Coastguard Worker 
658*6777b538SAndroid Build Coastguard Worker     if (*cur != '/')
659*6777b538SAndroid Build Coastguard Worker         return(1);
660*6777b538SAndroid Build Coastguard Worker     cur++;
661*6777b538SAndroid Build Coastguard Worker     ret = xmlParse3986Segment(uri, &cur, 0, 0);
662*6777b538SAndroid Build Coastguard Worker     if (ret == 0) {
663*6777b538SAndroid Build Coastguard Worker 	while (*cur == '/') {
664*6777b538SAndroid Build Coastguard Worker 	    cur++;
665*6777b538SAndroid Build Coastguard Worker 	    ret = xmlParse3986Segment(uri, &cur, 0, 1);
666*6777b538SAndroid Build Coastguard Worker 	    if (ret != 0) return(ret);
667*6777b538SAndroid Build Coastguard Worker 	}
668*6777b538SAndroid Build Coastguard Worker     }
669*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
670*6777b538SAndroid Build Coastguard Worker 	if (uri->path != NULL) xmlFree(uri->path);
671*6777b538SAndroid Build Coastguard Worker         if (cur != *str) {
672*6777b538SAndroid Build Coastguard Worker             if (uri->cleanup & XML_URI_NO_UNESCAPE)
673*6777b538SAndroid Build Coastguard Worker                 uri->path = STRNDUP(*str, cur - *str);
674*6777b538SAndroid Build Coastguard Worker             else
675*6777b538SAndroid Build Coastguard Worker                 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
676*6777b538SAndroid Build Coastguard Worker             if (uri->path == NULL)
677*6777b538SAndroid Build Coastguard Worker                 return (-1);
678*6777b538SAndroid Build Coastguard Worker         } else {
679*6777b538SAndroid Build Coastguard Worker             uri->path = NULL;
680*6777b538SAndroid Build Coastguard Worker         }
681*6777b538SAndroid Build Coastguard Worker     }
682*6777b538SAndroid Build Coastguard Worker     *str = cur;
683*6777b538SAndroid Build Coastguard Worker     return (0);
684*6777b538SAndroid Build Coastguard Worker }
685*6777b538SAndroid Build Coastguard Worker 
686*6777b538SAndroid Build Coastguard Worker /**
687*6777b538SAndroid Build Coastguard Worker  * xmlParse3986PathRootless:
688*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
689*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
690*6777b538SAndroid Build Coastguard Worker  *
691*6777b538SAndroid Build Coastguard Worker  * Parse an path without root and fills in the appropriate fields
692*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
693*6777b538SAndroid Build Coastguard Worker  *
694*6777b538SAndroid Build Coastguard Worker  * path-rootless = segment-nz *( "/" segment )
695*6777b538SAndroid Build Coastguard Worker  *
696*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
697*6777b538SAndroid Build Coastguard Worker  */
698*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986PathRootless(xmlURIPtr uri,const char ** str)699*6777b538SAndroid Build Coastguard Worker xmlParse3986PathRootless(xmlURIPtr uri, const char **str)
700*6777b538SAndroid Build Coastguard Worker {
701*6777b538SAndroid Build Coastguard Worker     const char *cur;
702*6777b538SAndroid Build Coastguard Worker     int ret;
703*6777b538SAndroid Build Coastguard Worker 
704*6777b538SAndroid Build Coastguard Worker     cur = *str;
705*6777b538SAndroid Build Coastguard Worker 
706*6777b538SAndroid Build Coastguard Worker     ret = xmlParse3986Segment(uri, &cur, 0, 0);
707*6777b538SAndroid Build Coastguard Worker     if (ret != 0) return(ret);
708*6777b538SAndroid Build Coastguard Worker     while (*cur == '/') {
709*6777b538SAndroid Build Coastguard Worker         cur++;
710*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986Segment(uri, &cur, 0, 1);
711*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
712*6777b538SAndroid Build Coastguard Worker     }
713*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
714*6777b538SAndroid Build Coastguard Worker 	if (uri->path != NULL) xmlFree(uri->path);
715*6777b538SAndroid Build Coastguard Worker         if (cur != *str) {
716*6777b538SAndroid Build Coastguard Worker             if (uri->cleanup & XML_URI_NO_UNESCAPE)
717*6777b538SAndroid Build Coastguard Worker                 uri->path = STRNDUP(*str, cur - *str);
718*6777b538SAndroid Build Coastguard Worker             else
719*6777b538SAndroid Build Coastguard Worker                 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
720*6777b538SAndroid Build Coastguard Worker             if (uri->path == NULL)
721*6777b538SAndroid Build Coastguard Worker                 return (-1);
722*6777b538SAndroid Build Coastguard Worker         } else {
723*6777b538SAndroid Build Coastguard Worker             uri->path = NULL;
724*6777b538SAndroid Build Coastguard Worker         }
725*6777b538SAndroid Build Coastguard Worker     }
726*6777b538SAndroid Build Coastguard Worker     *str = cur;
727*6777b538SAndroid Build Coastguard Worker     return (0);
728*6777b538SAndroid Build Coastguard Worker }
729*6777b538SAndroid Build Coastguard Worker 
730*6777b538SAndroid Build Coastguard Worker /**
731*6777b538SAndroid Build Coastguard Worker  * xmlParse3986PathNoScheme:
732*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
733*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
734*6777b538SAndroid Build Coastguard Worker  *
735*6777b538SAndroid Build Coastguard Worker  * Parse an path which is not a scheme and fills in the appropriate fields
736*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
737*6777b538SAndroid Build Coastguard Worker  *
738*6777b538SAndroid Build Coastguard Worker  * path-noscheme = segment-nz-nc *( "/" segment )
739*6777b538SAndroid Build Coastguard Worker  *
740*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
741*6777b538SAndroid Build Coastguard Worker  */
742*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986PathNoScheme(xmlURIPtr uri,const char ** str)743*6777b538SAndroid Build Coastguard Worker xmlParse3986PathNoScheme(xmlURIPtr uri, const char **str)
744*6777b538SAndroid Build Coastguard Worker {
745*6777b538SAndroid Build Coastguard Worker     const char *cur;
746*6777b538SAndroid Build Coastguard Worker     int ret;
747*6777b538SAndroid Build Coastguard Worker 
748*6777b538SAndroid Build Coastguard Worker     cur = *str;
749*6777b538SAndroid Build Coastguard Worker 
750*6777b538SAndroid Build Coastguard Worker     ret = xmlParse3986Segment(uri, &cur, ':', 0);
751*6777b538SAndroid Build Coastguard Worker     if (ret != 0) return(ret);
752*6777b538SAndroid Build Coastguard Worker     while (*cur == '/') {
753*6777b538SAndroid Build Coastguard Worker         cur++;
754*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986Segment(uri, &cur, 0, 1);
755*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
756*6777b538SAndroid Build Coastguard Worker     }
757*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
758*6777b538SAndroid Build Coastguard Worker 	if (uri->path != NULL) xmlFree(uri->path);
759*6777b538SAndroid Build Coastguard Worker         if (cur != *str) {
760*6777b538SAndroid Build Coastguard Worker             if (uri->cleanup & XML_URI_NO_UNESCAPE)
761*6777b538SAndroid Build Coastguard Worker                 uri->path = STRNDUP(*str, cur - *str);
762*6777b538SAndroid Build Coastguard Worker             else
763*6777b538SAndroid Build Coastguard Worker                 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
764*6777b538SAndroid Build Coastguard Worker             if (uri->path == NULL)
765*6777b538SAndroid Build Coastguard Worker                 return (-1);
766*6777b538SAndroid Build Coastguard Worker         } else {
767*6777b538SAndroid Build Coastguard Worker             uri->path = NULL;
768*6777b538SAndroid Build Coastguard Worker         }
769*6777b538SAndroid Build Coastguard Worker     }
770*6777b538SAndroid Build Coastguard Worker     *str = cur;
771*6777b538SAndroid Build Coastguard Worker     return (0);
772*6777b538SAndroid Build Coastguard Worker }
773*6777b538SAndroid Build Coastguard Worker 
774*6777b538SAndroid Build Coastguard Worker /**
775*6777b538SAndroid Build Coastguard Worker  * xmlParse3986HierPart:
776*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
777*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
778*6777b538SAndroid Build Coastguard Worker  *
779*6777b538SAndroid Build Coastguard Worker  * Parse an hierarchical part and fills in the appropriate fields
780*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
781*6777b538SAndroid Build Coastguard Worker  *
782*6777b538SAndroid Build Coastguard Worker  * hier-part     = "//" authority path-abempty
783*6777b538SAndroid Build Coastguard Worker  *                / path-absolute
784*6777b538SAndroid Build Coastguard Worker  *                / path-rootless
785*6777b538SAndroid Build Coastguard Worker  *                / path-empty
786*6777b538SAndroid Build Coastguard Worker  *
787*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
788*6777b538SAndroid Build Coastguard Worker  */
789*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986HierPart(xmlURIPtr uri,const char ** str)790*6777b538SAndroid Build Coastguard Worker xmlParse3986HierPart(xmlURIPtr uri, const char **str)
791*6777b538SAndroid Build Coastguard Worker {
792*6777b538SAndroid Build Coastguard Worker     const char *cur;
793*6777b538SAndroid Build Coastguard Worker     int ret;
794*6777b538SAndroid Build Coastguard Worker 
795*6777b538SAndroid Build Coastguard Worker     cur = *str;
796*6777b538SAndroid Build Coastguard Worker 
797*6777b538SAndroid Build Coastguard Worker     if ((*cur == '/') && (*(cur + 1) == '/')) {
798*6777b538SAndroid Build Coastguard Worker         cur += 2;
799*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986Authority(uri, &cur);
800*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
801*6777b538SAndroid Build Coastguard Worker         /*
802*6777b538SAndroid Build Coastguard Worker          * An empty server is marked with a special URI value.
803*6777b538SAndroid Build Coastguard Worker          */
804*6777b538SAndroid Build Coastguard Worker 	if ((uri->server == NULL) && (uri->port == PORT_EMPTY))
805*6777b538SAndroid Build Coastguard Worker 	    uri->port = PORT_EMPTY_SERVER;
806*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986PathAbEmpty(uri, &cur);
807*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
808*6777b538SAndroid Build Coastguard Worker 	*str = cur;
809*6777b538SAndroid Build Coastguard Worker 	return(0);
810*6777b538SAndroid Build Coastguard Worker     } else if (*cur == '/') {
811*6777b538SAndroid Build Coastguard Worker         ret = xmlParse3986PathAbsolute(uri, &cur);
812*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
813*6777b538SAndroid Build Coastguard Worker     } else if (ISA_PCHAR(uri, cur)) {
814*6777b538SAndroid Build Coastguard Worker         ret = xmlParse3986PathRootless(uri, &cur);
815*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
816*6777b538SAndroid Build Coastguard Worker     } else {
817*6777b538SAndroid Build Coastguard Worker 	/* path-empty is effectively empty */
818*6777b538SAndroid Build Coastguard Worker 	if (uri != NULL) {
819*6777b538SAndroid Build Coastguard Worker 	    if (uri->path != NULL) xmlFree(uri->path);
820*6777b538SAndroid Build Coastguard Worker 	    uri->path = NULL;
821*6777b538SAndroid Build Coastguard Worker 	}
822*6777b538SAndroid Build Coastguard Worker     }
823*6777b538SAndroid Build Coastguard Worker     *str = cur;
824*6777b538SAndroid Build Coastguard Worker     return (0);
825*6777b538SAndroid Build Coastguard Worker }
826*6777b538SAndroid Build Coastguard Worker 
827*6777b538SAndroid Build Coastguard Worker /**
828*6777b538SAndroid Build Coastguard Worker  * xmlParse3986RelativeRef:
829*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
830*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
831*6777b538SAndroid Build Coastguard Worker  *
832*6777b538SAndroid Build Coastguard Worker  * Parse an URI string and fills in the appropriate fields
833*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
834*6777b538SAndroid Build Coastguard Worker  *
835*6777b538SAndroid Build Coastguard Worker  * relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
836*6777b538SAndroid Build Coastguard Worker  * relative-part = "//" authority path-abempty
837*6777b538SAndroid Build Coastguard Worker  *               / path-absolute
838*6777b538SAndroid Build Coastguard Worker  *               / path-noscheme
839*6777b538SAndroid Build Coastguard Worker  *               / path-empty
840*6777b538SAndroid Build Coastguard Worker  *
841*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
842*6777b538SAndroid Build Coastguard Worker  */
843*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986RelativeRef(xmlURIPtr uri,const char * str)844*6777b538SAndroid Build Coastguard Worker xmlParse3986RelativeRef(xmlURIPtr uri, const char *str) {
845*6777b538SAndroid Build Coastguard Worker     int ret;
846*6777b538SAndroid Build Coastguard Worker 
847*6777b538SAndroid Build Coastguard Worker     if ((*str == '/') && (*(str + 1) == '/')) {
848*6777b538SAndroid Build Coastguard Worker         str += 2;
849*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986Authority(uri, &str);
850*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
851*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986PathAbEmpty(uri, &str);
852*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
853*6777b538SAndroid Build Coastguard Worker     } else if (*str == '/') {
854*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986PathAbsolute(uri, &str);
855*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
856*6777b538SAndroid Build Coastguard Worker     } else if (ISA_PCHAR(uri, str)) {
857*6777b538SAndroid Build Coastguard Worker         ret = xmlParse3986PathNoScheme(uri, &str);
858*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
859*6777b538SAndroid Build Coastguard Worker     } else {
860*6777b538SAndroid Build Coastguard Worker 	/* path-empty is effectively empty */
861*6777b538SAndroid Build Coastguard Worker 	if (uri != NULL) {
862*6777b538SAndroid Build Coastguard Worker 	    if (uri->path != NULL) xmlFree(uri->path);
863*6777b538SAndroid Build Coastguard Worker 	    uri->path = NULL;
864*6777b538SAndroid Build Coastguard Worker 	}
865*6777b538SAndroid Build Coastguard Worker     }
866*6777b538SAndroid Build Coastguard Worker 
867*6777b538SAndroid Build Coastguard Worker     if (*str == '?') {
868*6777b538SAndroid Build Coastguard Worker 	str++;
869*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986Query(uri, &str);
870*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
871*6777b538SAndroid Build Coastguard Worker     }
872*6777b538SAndroid Build Coastguard Worker     if (*str == '#') {
873*6777b538SAndroid Build Coastguard Worker 	str++;
874*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986Fragment(uri, &str);
875*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
876*6777b538SAndroid Build Coastguard Worker     }
877*6777b538SAndroid Build Coastguard Worker     if (*str != 0) {
878*6777b538SAndroid Build Coastguard Worker 	xmlCleanURI(uri);
879*6777b538SAndroid Build Coastguard Worker 	return(1);
880*6777b538SAndroid Build Coastguard Worker     }
881*6777b538SAndroid Build Coastguard Worker     return(0);
882*6777b538SAndroid Build Coastguard Worker }
883*6777b538SAndroid Build Coastguard Worker 
884*6777b538SAndroid Build Coastguard Worker 
885*6777b538SAndroid Build Coastguard Worker /**
886*6777b538SAndroid Build Coastguard Worker  * xmlParse3986URI:
887*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
888*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
889*6777b538SAndroid Build Coastguard Worker  *
890*6777b538SAndroid Build Coastguard Worker  * Parse an URI string and fills in the appropriate fields
891*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
892*6777b538SAndroid Build Coastguard Worker  *
893*6777b538SAndroid Build Coastguard Worker  * scheme ":" hier-part [ "?" query ] [ "#" fragment ]
894*6777b538SAndroid Build Coastguard Worker  *
895*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
896*6777b538SAndroid Build Coastguard Worker  */
897*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986URI(xmlURIPtr uri,const char * str)898*6777b538SAndroid Build Coastguard Worker xmlParse3986URI(xmlURIPtr uri, const char *str) {
899*6777b538SAndroid Build Coastguard Worker     int ret;
900*6777b538SAndroid Build Coastguard Worker 
901*6777b538SAndroid Build Coastguard Worker     ret = xmlParse3986Scheme(uri, &str);
902*6777b538SAndroid Build Coastguard Worker     if (ret != 0) return(ret);
903*6777b538SAndroid Build Coastguard Worker     if (*str != ':') {
904*6777b538SAndroid Build Coastguard Worker 	return(1);
905*6777b538SAndroid Build Coastguard Worker     }
906*6777b538SAndroid Build Coastguard Worker     str++;
907*6777b538SAndroid Build Coastguard Worker     ret = xmlParse3986HierPart(uri, &str);
908*6777b538SAndroid Build Coastguard Worker     if (ret != 0) return(ret);
909*6777b538SAndroid Build Coastguard Worker     if (*str == '?') {
910*6777b538SAndroid Build Coastguard Worker 	str++;
911*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986Query(uri, &str);
912*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
913*6777b538SAndroid Build Coastguard Worker     }
914*6777b538SAndroid Build Coastguard Worker     if (*str == '#') {
915*6777b538SAndroid Build Coastguard Worker 	str++;
916*6777b538SAndroid Build Coastguard Worker 	ret = xmlParse3986Fragment(uri, &str);
917*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) return(ret);
918*6777b538SAndroid Build Coastguard Worker     }
919*6777b538SAndroid Build Coastguard Worker     if (*str != 0) {
920*6777b538SAndroid Build Coastguard Worker 	xmlCleanURI(uri);
921*6777b538SAndroid Build Coastguard Worker 	return(1);
922*6777b538SAndroid Build Coastguard Worker     }
923*6777b538SAndroid Build Coastguard Worker     return(0);
924*6777b538SAndroid Build Coastguard Worker }
925*6777b538SAndroid Build Coastguard Worker 
926*6777b538SAndroid Build Coastguard Worker /**
927*6777b538SAndroid Build Coastguard Worker  * xmlParse3986URIReference:
928*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
929*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
930*6777b538SAndroid Build Coastguard Worker  *
931*6777b538SAndroid Build Coastguard Worker  * Parse an URI reference string and fills in the appropriate fields
932*6777b538SAndroid Build Coastguard Worker  * of the @uri structure
933*6777b538SAndroid Build Coastguard Worker  *
934*6777b538SAndroid Build Coastguard Worker  * URI-reference = URI / relative-ref
935*6777b538SAndroid Build Coastguard Worker  *
936*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
937*6777b538SAndroid Build Coastguard Worker  */
938*6777b538SAndroid Build Coastguard Worker static int
xmlParse3986URIReference(xmlURIPtr uri,const char * str)939*6777b538SAndroid Build Coastguard Worker xmlParse3986URIReference(xmlURIPtr uri, const char *str) {
940*6777b538SAndroid Build Coastguard Worker     int ret;
941*6777b538SAndroid Build Coastguard Worker 
942*6777b538SAndroid Build Coastguard Worker     if (str == NULL)
943*6777b538SAndroid Build Coastguard Worker 	return(-1);
944*6777b538SAndroid Build Coastguard Worker     xmlCleanURI(uri);
945*6777b538SAndroid Build Coastguard Worker 
946*6777b538SAndroid Build Coastguard Worker     /*
947*6777b538SAndroid Build Coastguard Worker      * Try first to parse absolute refs, then fallback to relative if
948*6777b538SAndroid Build Coastguard Worker      * it fails.
949*6777b538SAndroid Build Coastguard Worker      */
950*6777b538SAndroid Build Coastguard Worker     ret = xmlParse3986URI(uri, str);
951*6777b538SAndroid Build Coastguard Worker     if (ret < 0)
952*6777b538SAndroid Build Coastguard Worker         return(ret);
953*6777b538SAndroid Build Coastguard Worker     if (ret != 0) {
954*6777b538SAndroid Build Coastguard Worker 	xmlCleanURI(uri);
955*6777b538SAndroid Build Coastguard Worker         ret = xmlParse3986RelativeRef(uri, str);
956*6777b538SAndroid Build Coastguard Worker 	if (ret != 0) {
957*6777b538SAndroid Build Coastguard Worker 	    xmlCleanURI(uri);
958*6777b538SAndroid Build Coastguard Worker 	    return(ret);
959*6777b538SAndroid Build Coastguard Worker 	}
960*6777b538SAndroid Build Coastguard Worker     }
961*6777b538SAndroid Build Coastguard Worker     return(0);
962*6777b538SAndroid Build Coastguard Worker }
963*6777b538SAndroid Build Coastguard Worker 
964*6777b538SAndroid Build Coastguard Worker /**
965*6777b538SAndroid Build Coastguard Worker  * xmlParseURISafe:
966*6777b538SAndroid Build Coastguard Worker  * @str:  the URI string to analyze
967*6777b538SAndroid Build Coastguard Worker  * @uriOut:  optional pointer to parsed URI
968*6777b538SAndroid Build Coastguard Worker  *
969*6777b538SAndroid Build Coastguard Worker  * Parse an URI based on RFC 3986
970*6777b538SAndroid Build Coastguard Worker  *
971*6777b538SAndroid Build Coastguard Worker  * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
972*6777b538SAndroid Build Coastguard Worker  *
973*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success, an error code (typically 1) if the URI is invalid
974*6777b538SAndroid Build Coastguard Worker  * or -1 if a memory allocation failed.
975*6777b538SAndroid Build Coastguard Worker  */
976*6777b538SAndroid Build Coastguard Worker int
xmlParseURISafe(const char * str,xmlURIPtr * uriOut)977*6777b538SAndroid Build Coastguard Worker xmlParseURISafe(const char *str, xmlURIPtr *uriOut) {
978*6777b538SAndroid Build Coastguard Worker     xmlURIPtr uri;
979*6777b538SAndroid Build Coastguard Worker     int ret;
980*6777b538SAndroid Build Coastguard Worker 
981*6777b538SAndroid Build Coastguard Worker     if (uriOut != NULL)
982*6777b538SAndroid Build Coastguard Worker         *uriOut = NULL;
983*6777b538SAndroid Build Coastguard Worker     if (str == NULL)
984*6777b538SAndroid Build Coastguard Worker 	return(1);
985*6777b538SAndroid Build Coastguard Worker 
986*6777b538SAndroid Build Coastguard Worker     uri = xmlCreateURI();
987*6777b538SAndroid Build Coastguard Worker     if (uri == NULL)
988*6777b538SAndroid Build Coastguard Worker         return(-1);
989*6777b538SAndroid Build Coastguard Worker 
990*6777b538SAndroid Build Coastguard Worker     ret = xmlParse3986URIReference(uri, str);
991*6777b538SAndroid Build Coastguard Worker     if (ret) {
992*6777b538SAndroid Build Coastguard Worker         xmlFreeURI(uri);
993*6777b538SAndroid Build Coastguard Worker         return(ret);
994*6777b538SAndroid Build Coastguard Worker     }
995*6777b538SAndroid Build Coastguard Worker 
996*6777b538SAndroid Build Coastguard Worker     if (uriOut != NULL)
997*6777b538SAndroid Build Coastguard Worker         *uriOut = uri;
998*6777b538SAndroid Build Coastguard Worker     return(0);
999*6777b538SAndroid Build Coastguard Worker }
1000*6777b538SAndroid Build Coastguard Worker 
1001*6777b538SAndroid Build Coastguard Worker /**
1002*6777b538SAndroid Build Coastguard Worker  * xmlParseURI:
1003*6777b538SAndroid Build Coastguard Worker  * @str:  the URI string to analyze
1004*6777b538SAndroid Build Coastguard Worker  *
1005*6777b538SAndroid Build Coastguard Worker  * Parse an URI based on RFC 3986
1006*6777b538SAndroid Build Coastguard Worker  *
1007*6777b538SAndroid Build Coastguard Worker  * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
1008*6777b538SAndroid Build Coastguard Worker  *
1009*6777b538SAndroid Build Coastguard Worker  * Returns a newly built xmlURIPtr or NULL in case of error
1010*6777b538SAndroid Build Coastguard Worker  */
1011*6777b538SAndroid Build Coastguard Worker xmlURIPtr
xmlParseURI(const char * str)1012*6777b538SAndroid Build Coastguard Worker xmlParseURI(const char *str) {
1013*6777b538SAndroid Build Coastguard Worker     xmlURIPtr uri;
1014*6777b538SAndroid Build Coastguard Worker     xmlParseURISafe(str, &uri);
1015*6777b538SAndroid Build Coastguard Worker     return(uri);
1016*6777b538SAndroid Build Coastguard Worker }
1017*6777b538SAndroid Build Coastguard Worker 
1018*6777b538SAndroid Build Coastguard Worker /**
1019*6777b538SAndroid Build Coastguard Worker  * xmlParseURIReference:
1020*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an URI structure
1021*6777b538SAndroid Build Coastguard Worker  * @str:  the string to analyze
1022*6777b538SAndroid Build Coastguard Worker  *
1023*6777b538SAndroid Build Coastguard Worker  * Parse an URI reference string based on RFC 3986 and fills in the
1024*6777b538SAndroid Build Coastguard Worker  * appropriate fields of the @uri structure
1025*6777b538SAndroid Build Coastguard Worker  *
1026*6777b538SAndroid Build Coastguard Worker  * URI-reference = URI / relative-ref
1027*6777b538SAndroid Build Coastguard Worker  *
1028*6777b538SAndroid Build Coastguard Worker  * Returns 0 or the error code
1029*6777b538SAndroid Build Coastguard Worker  */
1030*6777b538SAndroid Build Coastguard Worker int
xmlParseURIReference(xmlURIPtr uri,const char * str)1031*6777b538SAndroid Build Coastguard Worker xmlParseURIReference(xmlURIPtr uri, const char *str) {
1032*6777b538SAndroid Build Coastguard Worker     return(xmlParse3986URIReference(uri, str));
1033*6777b538SAndroid Build Coastguard Worker }
1034*6777b538SAndroid Build Coastguard Worker 
1035*6777b538SAndroid Build Coastguard Worker /**
1036*6777b538SAndroid Build Coastguard Worker  * xmlParseURIRaw:
1037*6777b538SAndroid Build Coastguard Worker  * @str:  the URI string to analyze
1038*6777b538SAndroid Build Coastguard Worker  * @raw:  if 1 unescaping of URI pieces are disabled
1039*6777b538SAndroid Build Coastguard Worker  *
1040*6777b538SAndroid Build Coastguard Worker  * Parse an URI but allows to keep intact the original fragments.
1041*6777b538SAndroid Build Coastguard Worker  *
1042*6777b538SAndroid Build Coastguard Worker  * URI-reference = URI / relative-ref
1043*6777b538SAndroid Build Coastguard Worker  *
1044*6777b538SAndroid Build Coastguard Worker  * Returns a newly built xmlURIPtr or NULL in case of error
1045*6777b538SAndroid Build Coastguard Worker  */
1046*6777b538SAndroid Build Coastguard Worker xmlURIPtr
xmlParseURIRaw(const char * str,int raw)1047*6777b538SAndroid Build Coastguard Worker xmlParseURIRaw(const char *str, int raw) {
1048*6777b538SAndroid Build Coastguard Worker     xmlURIPtr uri;
1049*6777b538SAndroid Build Coastguard Worker     int ret;
1050*6777b538SAndroid Build Coastguard Worker 
1051*6777b538SAndroid Build Coastguard Worker     if (str == NULL)
1052*6777b538SAndroid Build Coastguard Worker 	return(NULL);
1053*6777b538SAndroid Build Coastguard Worker     uri = xmlCreateURI();
1054*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
1055*6777b538SAndroid Build Coastguard Worker         if (raw) {
1056*6777b538SAndroid Build Coastguard Worker 	    uri->cleanup |= XML_URI_NO_UNESCAPE;
1057*6777b538SAndroid Build Coastguard Worker 	}
1058*6777b538SAndroid Build Coastguard Worker 	ret = xmlParseURIReference(uri, str);
1059*6777b538SAndroid Build Coastguard Worker         if (ret) {
1060*6777b538SAndroid Build Coastguard Worker 	    xmlFreeURI(uri);
1061*6777b538SAndroid Build Coastguard Worker 	    return(NULL);
1062*6777b538SAndroid Build Coastguard Worker 	}
1063*6777b538SAndroid Build Coastguard Worker     }
1064*6777b538SAndroid Build Coastguard Worker     return(uri);
1065*6777b538SAndroid Build Coastguard Worker }
1066*6777b538SAndroid Build Coastguard Worker 
1067*6777b538SAndroid Build Coastguard Worker /************************************************************************
1068*6777b538SAndroid Build Coastguard Worker  *									*
1069*6777b538SAndroid Build Coastguard Worker  *			Generic URI structure functions			*
1070*6777b538SAndroid Build Coastguard Worker  *									*
1071*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
1072*6777b538SAndroid Build Coastguard Worker 
1073*6777b538SAndroid Build Coastguard Worker /**
1074*6777b538SAndroid Build Coastguard Worker  * xmlCreateURI:
1075*6777b538SAndroid Build Coastguard Worker  *
1076*6777b538SAndroid Build Coastguard Worker  * Simply creates an empty xmlURI
1077*6777b538SAndroid Build Coastguard Worker  *
1078*6777b538SAndroid Build Coastguard Worker  * Returns the new structure or NULL in case of error
1079*6777b538SAndroid Build Coastguard Worker  */
1080*6777b538SAndroid Build Coastguard Worker xmlURIPtr
xmlCreateURI(void)1081*6777b538SAndroid Build Coastguard Worker xmlCreateURI(void) {
1082*6777b538SAndroid Build Coastguard Worker     xmlURIPtr ret;
1083*6777b538SAndroid Build Coastguard Worker 
1084*6777b538SAndroid Build Coastguard Worker     ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI));
1085*6777b538SAndroid Build Coastguard Worker     if (ret == NULL)
1086*6777b538SAndroid Build Coastguard Worker 	return(NULL);
1087*6777b538SAndroid Build Coastguard Worker     memset(ret, 0, sizeof(xmlURI));
1088*6777b538SAndroid Build Coastguard Worker     ret->port = PORT_EMPTY;
1089*6777b538SAndroid Build Coastguard Worker     return(ret);
1090*6777b538SAndroid Build Coastguard Worker }
1091*6777b538SAndroid Build Coastguard Worker 
1092*6777b538SAndroid Build Coastguard Worker /**
1093*6777b538SAndroid Build Coastguard Worker  * xmlSaveUriRealloc:
1094*6777b538SAndroid Build Coastguard Worker  *
1095*6777b538SAndroid Build Coastguard Worker  * Function to handle properly a reallocation when saving an URI
1096*6777b538SAndroid Build Coastguard Worker  * Also imposes some limit on the length of an URI string output
1097*6777b538SAndroid Build Coastguard Worker  */
1098*6777b538SAndroid Build Coastguard Worker static xmlChar *
xmlSaveUriRealloc(xmlChar * ret,int * max)1099*6777b538SAndroid Build Coastguard Worker xmlSaveUriRealloc(xmlChar *ret, int *max) {
1100*6777b538SAndroid Build Coastguard Worker     xmlChar *temp;
1101*6777b538SAndroid Build Coastguard Worker     int tmp;
1102*6777b538SAndroid Build Coastguard Worker 
1103*6777b538SAndroid Build Coastguard Worker     if (*max > MAX_URI_LENGTH)
1104*6777b538SAndroid Build Coastguard Worker         return(NULL);
1105*6777b538SAndroid Build Coastguard Worker     tmp = *max * 2;
1106*6777b538SAndroid Build Coastguard Worker     temp = (xmlChar *) xmlRealloc(ret, (tmp + 1));
1107*6777b538SAndroid Build Coastguard Worker     if (temp == NULL)
1108*6777b538SAndroid Build Coastguard Worker         return(NULL);
1109*6777b538SAndroid Build Coastguard Worker     *max = tmp;
1110*6777b538SAndroid Build Coastguard Worker     return(temp);
1111*6777b538SAndroid Build Coastguard Worker }
1112*6777b538SAndroid Build Coastguard Worker 
1113*6777b538SAndroid Build Coastguard Worker /**
1114*6777b538SAndroid Build Coastguard Worker  * xmlSaveUri:
1115*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an xmlURI
1116*6777b538SAndroid Build Coastguard Worker  *
1117*6777b538SAndroid Build Coastguard Worker  * Save the URI as an escaped string
1118*6777b538SAndroid Build Coastguard Worker  *
1119*6777b538SAndroid Build Coastguard Worker  * Returns a new string (to be deallocated by caller)
1120*6777b538SAndroid Build Coastguard Worker  */
1121*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlSaveUri(xmlURIPtr uri)1122*6777b538SAndroid Build Coastguard Worker xmlSaveUri(xmlURIPtr uri) {
1123*6777b538SAndroid Build Coastguard Worker     xmlChar *ret = NULL;
1124*6777b538SAndroid Build Coastguard Worker     xmlChar *temp;
1125*6777b538SAndroid Build Coastguard Worker     const char *p;
1126*6777b538SAndroid Build Coastguard Worker     int len;
1127*6777b538SAndroid Build Coastguard Worker     int max;
1128*6777b538SAndroid Build Coastguard Worker 
1129*6777b538SAndroid Build Coastguard Worker     if (uri == NULL) return(NULL);
1130*6777b538SAndroid Build Coastguard Worker 
1131*6777b538SAndroid Build Coastguard Worker 
1132*6777b538SAndroid Build Coastguard Worker     max = 80;
1133*6777b538SAndroid Build Coastguard Worker     ret = (xmlChar *) xmlMallocAtomic(max + 1);
1134*6777b538SAndroid Build Coastguard Worker     if (ret == NULL)
1135*6777b538SAndroid Build Coastguard Worker 	return(NULL);
1136*6777b538SAndroid Build Coastguard Worker     len = 0;
1137*6777b538SAndroid Build Coastguard Worker 
1138*6777b538SAndroid Build Coastguard Worker     if (uri->scheme != NULL) {
1139*6777b538SAndroid Build Coastguard Worker 	p = uri->scheme;
1140*6777b538SAndroid Build Coastguard Worker 	while (*p != 0) {
1141*6777b538SAndroid Build Coastguard Worker 	    if (len >= max) {
1142*6777b538SAndroid Build Coastguard Worker                 temp = xmlSaveUriRealloc(ret, &max);
1143*6777b538SAndroid Build Coastguard Worker                 if (temp == NULL) goto mem_error;
1144*6777b538SAndroid Build Coastguard Worker 		ret = temp;
1145*6777b538SAndroid Build Coastguard Worker 	    }
1146*6777b538SAndroid Build Coastguard Worker 	    ret[len++] = *p++;
1147*6777b538SAndroid Build Coastguard Worker 	}
1148*6777b538SAndroid Build Coastguard Worker 	if (len >= max) {
1149*6777b538SAndroid Build Coastguard Worker             temp = xmlSaveUriRealloc(ret, &max);
1150*6777b538SAndroid Build Coastguard Worker             if (temp == NULL) goto mem_error;
1151*6777b538SAndroid Build Coastguard Worker             ret = temp;
1152*6777b538SAndroid Build Coastguard Worker 	}
1153*6777b538SAndroid Build Coastguard Worker 	ret[len++] = ':';
1154*6777b538SAndroid Build Coastguard Worker     }
1155*6777b538SAndroid Build Coastguard Worker     if (uri->opaque != NULL) {
1156*6777b538SAndroid Build Coastguard Worker 	p = uri->opaque;
1157*6777b538SAndroid Build Coastguard Worker 	while (*p != 0) {
1158*6777b538SAndroid Build Coastguard Worker 	    if (len + 3 >= max) {
1159*6777b538SAndroid Build Coastguard Worker                 temp = xmlSaveUriRealloc(ret, &max);
1160*6777b538SAndroid Build Coastguard Worker                 if (temp == NULL) goto mem_error;
1161*6777b538SAndroid Build Coastguard Worker                 ret = temp;
1162*6777b538SAndroid Build Coastguard Worker 	    }
1163*6777b538SAndroid Build Coastguard Worker 	    if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p)))
1164*6777b538SAndroid Build Coastguard Worker 		ret[len++] = *p++;
1165*6777b538SAndroid Build Coastguard Worker 	    else {
1166*6777b538SAndroid Build Coastguard Worker 		int val = *(unsigned char *)p++;
1167*6777b538SAndroid Build Coastguard Worker 		int hi = val / 0x10, lo = val % 0x10;
1168*6777b538SAndroid Build Coastguard Worker 		ret[len++] = '%';
1169*6777b538SAndroid Build Coastguard Worker 		ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1170*6777b538SAndroid Build Coastguard Worker 		ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1171*6777b538SAndroid Build Coastguard Worker 	    }
1172*6777b538SAndroid Build Coastguard Worker 	}
1173*6777b538SAndroid Build Coastguard Worker     } else {
1174*6777b538SAndroid Build Coastguard Worker 	if ((uri->server != NULL) || (uri->port != PORT_EMPTY)) {
1175*6777b538SAndroid Build Coastguard Worker 	    if (len + 3 >= max) {
1176*6777b538SAndroid Build Coastguard Worker                 temp = xmlSaveUriRealloc(ret, &max);
1177*6777b538SAndroid Build Coastguard Worker                 if (temp == NULL) goto mem_error;
1178*6777b538SAndroid Build Coastguard Worker                 ret = temp;
1179*6777b538SAndroid Build Coastguard Worker 	    }
1180*6777b538SAndroid Build Coastguard Worker 	    ret[len++] = '/';
1181*6777b538SAndroid Build Coastguard Worker 	    ret[len++] = '/';
1182*6777b538SAndroid Build Coastguard Worker 	    if (uri->user != NULL) {
1183*6777b538SAndroid Build Coastguard Worker 		p = uri->user;
1184*6777b538SAndroid Build Coastguard Worker 		while (*p != 0) {
1185*6777b538SAndroid Build Coastguard Worker 		    if (len + 3 >= max) {
1186*6777b538SAndroid Build Coastguard Worker                         temp = xmlSaveUriRealloc(ret, &max);
1187*6777b538SAndroid Build Coastguard Worker                         if (temp == NULL) goto mem_error;
1188*6777b538SAndroid Build Coastguard Worker                         ret = temp;
1189*6777b538SAndroid Build Coastguard Worker 		    }
1190*6777b538SAndroid Build Coastguard Worker 		    if ((IS_UNRESERVED(*(p))) ||
1191*6777b538SAndroid Build Coastguard Worker 			((*(p) == ';')) || ((*(p) == ':')) ||
1192*6777b538SAndroid Build Coastguard Worker 			((*(p) == '&')) || ((*(p) == '=')) ||
1193*6777b538SAndroid Build Coastguard Worker 			((*(p) == '+')) || ((*(p) == '$')) ||
1194*6777b538SAndroid Build Coastguard Worker 			((*(p) == ',')))
1195*6777b538SAndroid Build Coastguard Worker 			ret[len++] = *p++;
1196*6777b538SAndroid Build Coastguard Worker 		    else {
1197*6777b538SAndroid Build Coastguard Worker 			int val = *(unsigned char *)p++;
1198*6777b538SAndroid Build Coastguard Worker 			int hi = val / 0x10, lo = val % 0x10;
1199*6777b538SAndroid Build Coastguard Worker 			ret[len++] = '%';
1200*6777b538SAndroid Build Coastguard Worker 			ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1201*6777b538SAndroid Build Coastguard Worker 			ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1202*6777b538SAndroid Build Coastguard Worker 		    }
1203*6777b538SAndroid Build Coastguard Worker 		}
1204*6777b538SAndroid Build Coastguard Worker 		if (len + 3 >= max) {
1205*6777b538SAndroid Build Coastguard Worker                     temp = xmlSaveUriRealloc(ret, &max);
1206*6777b538SAndroid Build Coastguard Worker                     if (temp == NULL) goto mem_error;
1207*6777b538SAndroid Build Coastguard Worker                     ret = temp;
1208*6777b538SAndroid Build Coastguard Worker 		}
1209*6777b538SAndroid Build Coastguard Worker 		ret[len++] = '@';
1210*6777b538SAndroid Build Coastguard Worker 	    }
1211*6777b538SAndroid Build Coastguard Worker 	    if (uri->server != NULL) {
1212*6777b538SAndroid Build Coastguard Worker 		p = uri->server;
1213*6777b538SAndroid Build Coastguard Worker 		while (*p != 0) {
1214*6777b538SAndroid Build Coastguard Worker 		    if (len >= max) {
1215*6777b538SAndroid Build Coastguard Worker 			temp = xmlSaveUriRealloc(ret, &max);
1216*6777b538SAndroid Build Coastguard Worker 			if (temp == NULL) goto mem_error;
1217*6777b538SAndroid Build Coastguard Worker 			ret = temp;
1218*6777b538SAndroid Build Coastguard Worker 		    }
1219*6777b538SAndroid Build Coastguard Worker                     /* TODO: escaping? */
1220*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = (xmlChar) *p++;
1221*6777b538SAndroid Build Coastguard Worker 		}
1222*6777b538SAndroid Build Coastguard Worker 	    }
1223*6777b538SAndroid Build Coastguard Worker             if (uri->port > 0) {
1224*6777b538SAndroid Build Coastguard Worker                 if (len + 10 >= max) {
1225*6777b538SAndroid Build Coastguard Worker                     temp = xmlSaveUriRealloc(ret, &max);
1226*6777b538SAndroid Build Coastguard Worker                     if (temp == NULL) goto mem_error;
1227*6777b538SAndroid Build Coastguard Worker                     ret = temp;
1228*6777b538SAndroid Build Coastguard Worker                 }
1229*6777b538SAndroid Build Coastguard Worker                 len += snprintf((char *) &ret[len], max - len, ":%d", uri->port);
1230*6777b538SAndroid Build Coastguard Worker             }
1231*6777b538SAndroid Build Coastguard Worker 	} else if (uri->authority != NULL) {
1232*6777b538SAndroid Build Coastguard Worker 	    if (len + 3 >= max) {
1233*6777b538SAndroid Build Coastguard Worker                 temp = xmlSaveUriRealloc(ret, &max);
1234*6777b538SAndroid Build Coastguard Worker                 if (temp == NULL) goto mem_error;
1235*6777b538SAndroid Build Coastguard Worker                 ret = temp;
1236*6777b538SAndroid Build Coastguard Worker 	    }
1237*6777b538SAndroid Build Coastguard Worker 	    ret[len++] = '/';
1238*6777b538SAndroid Build Coastguard Worker 	    ret[len++] = '/';
1239*6777b538SAndroid Build Coastguard Worker 	    p = uri->authority;
1240*6777b538SAndroid Build Coastguard Worker 	    while (*p != 0) {
1241*6777b538SAndroid Build Coastguard Worker 		if (len + 3 >= max) {
1242*6777b538SAndroid Build Coastguard Worker                     temp = xmlSaveUriRealloc(ret, &max);
1243*6777b538SAndroid Build Coastguard Worker                     if (temp == NULL) goto mem_error;
1244*6777b538SAndroid Build Coastguard Worker                     ret = temp;
1245*6777b538SAndroid Build Coastguard Worker 		}
1246*6777b538SAndroid Build Coastguard Worker 		if ((IS_UNRESERVED(*(p))) ||
1247*6777b538SAndroid Build Coastguard Worker                     ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) ||
1248*6777b538SAndroid Build Coastguard Worker                     ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||
1249*6777b538SAndroid Build Coastguard Worker                     ((*(p) == '=')) || ((*(p) == '+')))
1250*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = *p++;
1251*6777b538SAndroid Build Coastguard Worker 		else {
1252*6777b538SAndroid Build Coastguard Worker 		    int val = *(unsigned char *)p++;
1253*6777b538SAndroid Build Coastguard Worker 		    int hi = val / 0x10, lo = val % 0x10;
1254*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = '%';
1255*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1256*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1257*6777b538SAndroid Build Coastguard Worker 		}
1258*6777b538SAndroid Build Coastguard Worker 	    }
1259*6777b538SAndroid Build Coastguard Worker 	} else if (uri->scheme != NULL) {
1260*6777b538SAndroid Build Coastguard Worker 	    if (len + 3 >= max) {
1261*6777b538SAndroid Build Coastguard Worker                 temp = xmlSaveUriRealloc(ret, &max);
1262*6777b538SAndroid Build Coastguard Worker                 if (temp == NULL) goto mem_error;
1263*6777b538SAndroid Build Coastguard Worker                 ret = temp;
1264*6777b538SAndroid Build Coastguard Worker 	    }
1265*6777b538SAndroid Build Coastguard Worker 	}
1266*6777b538SAndroid Build Coastguard Worker 	if (uri->path != NULL) {
1267*6777b538SAndroid Build Coastguard Worker 	    p = uri->path;
1268*6777b538SAndroid Build Coastguard Worker 	    /*
1269*6777b538SAndroid Build Coastguard Worker 	     * the colon in file:///d: should not be escaped or
1270*6777b538SAndroid Build Coastguard Worker 	     * Windows accesses fail later.
1271*6777b538SAndroid Build Coastguard Worker 	     */
1272*6777b538SAndroid Build Coastguard Worker 	    if ((uri->scheme != NULL) &&
1273*6777b538SAndroid Build Coastguard Worker 		(p[0] == '/') &&
1274*6777b538SAndroid Build Coastguard Worker 		(((p[1] >= 'a') && (p[1] <= 'z')) ||
1275*6777b538SAndroid Build Coastguard Worker 		 ((p[1] >= 'A') && (p[1] <= 'Z'))) &&
1276*6777b538SAndroid Build Coastguard Worker 		(p[2] == ':') &&
1277*6777b538SAndroid Build Coastguard Worker 	        (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
1278*6777b538SAndroid Build Coastguard Worker 		if (len + 3 >= max) {
1279*6777b538SAndroid Build Coastguard Worker                     temp = xmlSaveUriRealloc(ret, &max);
1280*6777b538SAndroid Build Coastguard Worker                     if (temp == NULL) goto mem_error;
1281*6777b538SAndroid Build Coastguard Worker                     ret = temp;
1282*6777b538SAndroid Build Coastguard Worker 		}
1283*6777b538SAndroid Build Coastguard Worker 		ret[len++] = *p++;
1284*6777b538SAndroid Build Coastguard Worker 		ret[len++] = *p++;
1285*6777b538SAndroid Build Coastguard Worker 		ret[len++] = *p++;
1286*6777b538SAndroid Build Coastguard Worker 	    }
1287*6777b538SAndroid Build Coastguard Worker 	    while (*p != 0) {
1288*6777b538SAndroid Build Coastguard Worker 		if (len + 3 >= max) {
1289*6777b538SAndroid Build Coastguard Worker                     temp = xmlSaveUriRealloc(ret, &max);
1290*6777b538SAndroid Build Coastguard Worker                     if (temp == NULL) goto mem_error;
1291*6777b538SAndroid Build Coastguard Worker                     ret = temp;
1292*6777b538SAndroid Build Coastguard Worker 		}
1293*6777b538SAndroid Build Coastguard Worker 		if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) ||
1294*6777b538SAndroid Build Coastguard Worker                     ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) ||
1295*6777b538SAndroid Build Coastguard Worker 	            ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||
1296*6777b538SAndroid Build Coastguard Worker 	            ((*(p) == ',')))
1297*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = *p++;
1298*6777b538SAndroid Build Coastguard Worker 		else {
1299*6777b538SAndroid Build Coastguard Worker 		    int val = *(unsigned char *)p++;
1300*6777b538SAndroid Build Coastguard Worker 		    int hi = val / 0x10, lo = val % 0x10;
1301*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = '%';
1302*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1303*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1304*6777b538SAndroid Build Coastguard Worker 		}
1305*6777b538SAndroid Build Coastguard Worker 	    }
1306*6777b538SAndroid Build Coastguard Worker 	}
1307*6777b538SAndroid Build Coastguard Worker 	if (uri->query_raw != NULL) {
1308*6777b538SAndroid Build Coastguard Worker 	    if (len + 1 >= max) {
1309*6777b538SAndroid Build Coastguard Worker                 temp = xmlSaveUriRealloc(ret, &max);
1310*6777b538SAndroid Build Coastguard Worker                 if (temp == NULL) goto mem_error;
1311*6777b538SAndroid Build Coastguard Worker                 ret = temp;
1312*6777b538SAndroid Build Coastguard Worker 	    }
1313*6777b538SAndroid Build Coastguard Worker 	    ret[len++] = '?';
1314*6777b538SAndroid Build Coastguard Worker 	    p = uri->query_raw;
1315*6777b538SAndroid Build Coastguard Worker 	    while (*p != 0) {
1316*6777b538SAndroid Build Coastguard Worker 		if (len + 1 >= max) {
1317*6777b538SAndroid Build Coastguard Worker                     temp = xmlSaveUriRealloc(ret, &max);
1318*6777b538SAndroid Build Coastguard Worker                     if (temp == NULL) goto mem_error;
1319*6777b538SAndroid Build Coastguard Worker                     ret = temp;
1320*6777b538SAndroid Build Coastguard Worker 		}
1321*6777b538SAndroid Build Coastguard Worker 		ret[len++] = *p++;
1322*6777b538SAndroid Build Coastguard Worker 	    }
1323*6777b538SAndroid Build Coastguard Worker 	} else if (uri->query != NULL) {
1324*6777b538SAndroid Build Coastguard Worker 	    if (len + 3 >= max) {
1325*6777b538SAndroid Build Coastguard Worker                 temp = xmlSaveUriRealloc(ret, &max);
1326*6777b538SAndroid Build Coastguard Worker                 if (temp == NULL) goto mem_error;
1327*6777b538SAndroid Build Coastguard Worker                 ret = temp;
1328*6777b538SAndroid Build Coastguard Worker 	    }
1329*6777b538SAndroid Build Coastguard Worker 	    ret[len++] = '?';
1330*6777b538SAndroid Build Coastguard Worker 	    p = uri->query;
1331*6777b538SAndroid Build Coastguard Worker 	    while (*p != 0) {
1332*6777b538SAndroid Build Coastguard Worker 		if (len + 3 >= max) {
1333*6777b538SAndroid Build Coastguard Worker                     temp = xmlSaveUriRealloc(ret, &max);
1334*6777b538SAndroid Build Coastguard Worker                     if (temp == NULL) goto mem_error;
1335*6777b538SAndroid Build Coastguard Worker                     ret = temp;
1336*6777b538SAndroid Build Coastguard Worker 		}
1337*6777b538SAndroid Build Coastguard Worker 		if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
1338*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = *p++;
1339*6777b538SAndroid Build Coastguard Worker 		else {
1340*6777b538SAndroid Build Coastguard Worker 		    int val = *(unsigned char *)p++;
1341*6777b538SAndroid Build Coastguard Worker 		    int hi = val / 0x10, lo = val % 0x10;
1342*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = '%';
1343*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1344*6777b538SAndroid Build Coastguard Worker 		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1345*6777b538SAndroid Build Coastguard Worker 		}
1346*6777b538SAndroid Build Coastguard Worker 	    }
1347*6777b538SAndroid Build Coastguard Worker 	}
1348*6777b538SAndroid Build Coastguard Worker     }
1349*6777b538SAndroid Build Coastguard Worker     if (uri->fragment != NULL) {
1350*6777b538SAndroid Build Coastguard Worker 	if (len + 3 >= max) {
1351*6777b538SAndroid Build Coastguard Worker             temp = xmlSaveUriRealloc(ret, &max);
1352*6777b538SAndroid Build Coastguard Worker             if (temp == NULL) goto mem_error;
1353*6777b538SAndroid Build Coastguard Worker             ret = temp;
1354*6777b538SAndroid Build Coastguard Worker 	}
1355*6777b538SAndroid Build Coastguard Worker 	ret[len++] = '#';
1356*6777b538SAndroid Build Coastguard Worker 	p = uri->fragment;
1357*6777b538SAndroid Build Coastguard Worker 	while (*p != 0) {
1358*6777b538SAndroid Build Coastguard Worker 	    if (len + 3 >= max) {
1359*6777b538SAndroid Build Coastguard Worker                 temp = xmlSaveUriRealloc(ret, &max);
1360*6777b538SAndroid Build Coastguard Worker                 if (temp == NULL) goto mem_error;
1361*6777b538SAndroid Build Coastguard Worker                 ret = temp;
1362*6777b538SAndroid Build Coastguard Worker 	    }
1363*6777b538SAndroid Build Coastguard Worker 	    if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
1364*6777b538SAndroid Build Coastguard Worker 		ret[len++] = *p++;
1365*6777b538SAndroid Build Coastguard Worker 	    else {
1366*6777b538SAndroid Build Coastguard Worker 		int val = *(unsigned char *)p++;
1367*6777b538SAndroid Build Coastguard Worker 		int hi = val / 0x10, lo = val % 0x10;
1368*6777b538SAndroid Build Coastguard Worker 		ret[len++] = '%';
1369*6777b538SAndroid Build Coastguard Worker 		ret[len++] = hi + (hi > 9? 'A'-10 : '0');
1370*6777b538SAndroid Build Coastguard Worker 		ret[len++] = lo + (lo > 9? 'A'-10 : '0');
1371*6777b538SAndroid Build Coastguard Worker 	    }
1372*6777b538SAndroid Build Coastguard Worker 	}
1373*6777b538SAndroid Build Coastguard Worker     }
1374*6777b538SAndroid Build Coastguard Worker     if (len >= max) {
1375*6777b538SAndroid Build Coastguard Worker         temp = xmlSaveUriRealloc(ret, &max);
1376*6777b538SAndroid Build Coastguard Worker         if (temp == NULL) goto mem_error;
1377*6777b538SAndroid Build Coastguard Worker         ret = temp;
1378*6777b538SAndroid Build Coastguard Worker     }
1379*6777b538SAndroid Build Coastguard Worker     ret[len] = 0;
1380*6777b538SAndroid Build Coastguard Worker     return(ret);
1381*6777b538SAndroid Build Coastguard Worker 
1382*6777b538SAndroid Build Coastguard Worker mem_error:
1383*6777b538SAndroid Build Coastguard Worker     xmlFree(ret);
1384*6777b538SAndroid Build Coastguard Worker     return(NULL);
1385*6777b538SAndroid Build Coastguard Worker }
1386*6777b538SAndroid Build Coastguard Worker 
1387*6777b538SAndroid Build Coastguard Worker /**
1388*6777b538SAndroid Build Coastguard Worker  * xmlPrintURI:
1389*6777b538SAndroid Build Coastguard Worker  * @stream:  a FILE* for the output
1390*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an xmlURI
1391*6777b538SAndroid Build Coastguard Worker  *
1392*6777b538SAndroid Build Coastguard Worker  * Prints the URI in the stream @stream.
1393*6777b538SAndroid Build Coastguard Worker  */
1394*6777b538SAndroid Build Coastguard Worker void
xmlPrintURI(FILE * stream,xmlURIPtr uri)1395*6777b538SAndroid Build Coastguard Worker xmlPrintURI(FILE *stream, xmlURIPtr uri) {
1396*6777b538SAndroid Build Coastguard Worker     xmlChar *out;
1397*6777b538SAndroid Build Coastguard Worker 
1398*6777b538SAndroid Build Coastguard Worker     out = xmlSaveUri(uri);
1399*6777b538SAndroid Build Coastguard Worker     if (out != NULL) {
1400*6777b538SAndroid Build Coastguard Worker 	fprintf(stream, "%s", (char *) out);
1401*6777b538SAndroid Build Coastguard Worker 	xmlFree(out);
1402*6777b538SAndroid Build Coastguard Worker     }
1403*6777b538SAndroid Build Coastguard Worker }
1404*6777b538SAndroid Build Coastguard Worker 
1405*6777b538SAndroid Build Coastguard Worker /**
1406*6777b538SAndroid Build Coastguard Worker  * xmlCleanURI:
1407*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an xmlURI
1408*6777b538SAndroid Build Coastguard Worker  *
1409*6777b538SAndroid Build Coastguard Worker  * Make sure the xmlURI struct is free of content
1410*6777b538SAndroid Build Coastguard Worker  */
1411*6777b538SAndroid Build Coastguard Worker static void
xmlCleanURI(xmlURIPtr uri)1412*6777b538SAndroid Build Coastguard Worker xmlCleanURI(xmlURIPtr uri) {
1413*6777b538SAndroid Build Coastguard Worker     if (uri == NULL) return;
1414*6777b538SAndroid Build Coastguard Worker 
1415*6777b538SAndroid Build Coastguard Worker     if (uri->scheme != NULL) xmlFree(uri->scheme);
1416*6777b538SAndroid Build Coastguard Worker     uri->scheme = NULL;
1417*6777b538SAndroid Build Coastguard Worker     if (uri->server != NULL) xmlFree(uri->server);
1418*6777b538SAndroid Build Coastguard Worker     uri->server = NULL;
1419*6777b538SAndroid Build Coastguard Worker     if (uri->user != NULL) xmlFree(uri->user);
1420*6777b538SAndroid Build Coastguard Worker     uri->user = NULL;
1421*6777b538SAndroid Build Coastguard Worker     if (uri->path != NULL) xmlFree(uri->path);
1422*6777b538SAndroid Build Coastguard Worker     uri->path = NULL;
1423*6777b538SAndroid Build Coastguard Worker     if (uri->fragment != NULL) xmlFree(uri->fragment);
1424*6777b538SAndroid Build Coastguard Worker     uri->fragment = NULL;
1425*6777b538SAndroid Build Coastguard Worker     if (uri->opaque != NULL) xmlFree(uri->opaque);
1426*6777b538SAndroid Build Coastguard Worker     uri->opaque = NULL;
1427*6777b538SAndroid Build Coastguard Worker     if (uri->authority != NULL) xmlFree(uri->authority);
1428*6777b538SAndroid Build Coastguard Worker     uri->authority = NULL;
1429*6777b538SAndroid Build Coastguard Worker     if (uri->query != NULL) xmlFree(uri->query);
1430*6777b538SAndroid Build Coastguard Worker     uri->query = NULL;
1431*6777b538SAndroid Build Coastguard Worker     if (uri->query_raw != NULL) xmlFree(uri->query_raw);
1432*6777b538SAndroid Build Coastguard Worker     uri->query_raw = NULL;
1433*6777b538SAndroid Build Coastguard Worker }
1434*6777b538SAndroid Build Coastguard Worker 
1435*6777b538SAndroid Build Coastguard Worker /**
1436*6777b538SAndroid Build Coastguard Worker  * xmlFreeURI:
1437*6777b538SAndroid Build Coastguard Worker  * @uri:  pointer to an xmlURI
1438*6777b538SAndroid Build Coastguard Worker  *
1439*6777b538SAndroid Build Coastguard Worker  * Free up the xmlURI struct
1440*6777b538SAndroid Build Coastguard Worker  */
1441*6777b538SAndroid Build Coastguard Worker void
xmlFreeURI(xmlURIPtr uri)1442*6777b538SAndroid Build Coastguard Worker xmlFreeURI(xmlURIPtr uri) {
1443*6777b538SAndroid Build Coastguard Worker     if (uri == NULL) return;
1444*6777b538SAndroid Build Coastguard Worker 
1445*6777b538SAndroid Build Coastguard Worker     if (uri->scheme != NULL) xmlFree(uri->scheme);
1446*6777b538SAndroid Build Coastguard Worker     if (uri->server != NULL) xmlFree(uri->server);
1447*6777b538SAndroid Build Coastguard Worker     if (uri->user != NULL) xmlFree(uri->user);
1448*6777b538SAndroid Build Coastguard Worker     if (uri->path != NULL) xmlFree(uri->path);
1449*6777b538SAndroid Build Coastguard Worker     if (uri->fragment != NULL) xmlFree(uri->fragment);
1450*6777b538SAndroid Build Coastguard Worker     if (uri->opaque != NULL) xmlFree(uri->opaque);
1451*6777b538SAndroid Build Coastguard Worker     if (uri->authority != NULL) xmlFree(uri->authority);
1452*6777b538SAndroid Build Coastguard Worker     if (uri->query != NULL) xmlFree(uri->query);
1453*6777b538SAndroid Build Coastguard Worker     if (uri->query_raw != NULL) xmlFree(uri->query_raw);
1454*6777b538SAndroid Build Coastguard Worker     xmlFree(uri);
1455*6777b538SAndroid Build Coastguard Worker }
1456*6777b538SAndroid Build Coastguard Worker 
1457*6777b538SAndroid Build Coastguard Worker /************************************************************************
1458*6777b538SAndroid Build Coastguard Worker  *									*
1459*6777b538SAndroid Build Coastguard Worker  *			Helper functions				*
1460*6777b538SAndroid Build Coastguard Worker  *									*
1461*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
1462*6777b538SAndroid Build Coastguard Worker 
1463*6777b538SAndroid Build Coastguard Worker static int
xmlIsPathSeparator(int c,int isFile)1464*6777b538SAndroid Build Coastguard Worker xmlIsPathSeparator(int c, int isFile) {
1465*6777b538SAndroid Build Coastguard Worker     (void) isFile;
1466*6777b538SAndroid Build Coastguard Worker 
1467*6777b538SAndroid Build Coastguard Worker     if (c == '/')
1468*6777b538SAndroid Build Coastguard Worker         return(1);
1469*6777b538SAndroid Build Coastguard Worker 
1470*6777b538SAndroid Build Coastguard Worker #ifdef _WIN32
1471*6777b538SAndroid Build Coastguard Worker     if (isFile && (c == '\\'))
1472*6777b538SAndroid Build Coastguard Worker         return(1);
1473*6777b538SAndroid Build Coastguard Worker #endif
1474*6777b538SAndroid Build Coastguard Worker 
1475*6777b538SAndroid Build Coastguard Worker     return(0);
1476*6777b538SAndroid Build Coastguard Worker }
1477*6777b538SAndroid Build Coastguard Worker 
1478*6777b538SAndroid Build Coastguard Worker /**
1479*6777b538SAndroid Build Coastguard Worker  * xmlNormalizePath:
1480*6777b538SAndroid Build Coastguard Worker  * @path:  pointer to the path string
1481*6777b538SAndroid Build Coastguard Worker  * @isFile:  true for filesystem paths, false for URIs
1482*6777b538SAndroid Build Coastguard Worker  *
1483*6777b538SAndroid Build Coastguard Worker  * Normalize a filesystem path or URI.
1484*6777b538SAndroid Build Coastguard Worker  *
1485*6777b538SAndroid Build Coastguard Worker  * Returns 0 or an error code
1486*6777b538SAndroid Build Coastguard Worker  */
1487*6777b538SAndroid Build Coastguard Worker static int
xmlNormalizePath(char * path,int isFile)1488*6777b538SAndroid Build Coastguard Worker xmlNormalizePath(char *path, int isFile) {
1489*6777b538SAndroid Build Coastguard Worker     char *cur, *out;
1490*6777b538SAndroid Build Coastguard Worker     int numSeg = 0;
1491*6777b538SAndroid Build Coastguard Worker 
1492*6777b538SAndroid Build Coastguard Worker     if (path == NULL)
1493*6777b538SAndroid Build Coastguard Worker 	return(-1);
1494*6777b538SAndroid Build Coastguard Worker 
1495*6777b538SAndroid Build Coastguard Worker     cur = path;
1496*6777b538SAndroid Build Coastguard Worker     out = path;
1497*6777b538SAndroid Build Coastguard Worker 
1498*6777b538SAndroid Build Coastguard Worker     if (*cur == 0)
1499*6777b538SAndroid Build Coastguard Worker         return(0);
1500*6777b538SAndroid Build Coastguard Worker 
1501*6777b538SAndroid Build Coastguard Worker     if (xmlIsPathSeparator(*cur, isFile)) {
1502*6777b538SAndroid Build Coastguard Worker         cur++;
1503*6777b538SAndroid Build Coastguard Worker         *out++ = '/';
1504*6777b538SAndroid Build Coastguard Worker     }
1505*6777b538SAndroid Build Coastguard Worker 
1506*6777b538SAndroid Build Coastguard Worker     while (*cur != 0) {
1507*6777b538SAndroid Build Coastguard Worker         /*
1508*6777b538SAndroid Build Coastguard Worker          * At this point, out is either empty or ends with a separator.
1509*6777b538SAndroid Build Coastguard Worker          * Collapse multiple separators first.
1510*6777b538SAndroid Build Coastguard Worker          */
1511*6777b538SAndroid Build Coastguard Worker         while (xmlIsPathSeparator(*cur, isFile)) {
1512*6777b538SAndroid Build Coastguard Worker #ifdef _WIN32
1513*6777b538SAndroid Build Coastguard Worker             /* Allow two separators at start of path */
1514*6777b538SAndroid Build Coastguard Worker             if ((isFile) && (out == path + 1))
1515*6777b538SAndroid Build Coastguard Worker                 *out++ = '/';
1516*6777b538SAndroid Build Coastguard Worker #endif
1517*6777b538SAndroid Build Coastguard Worker             cur++;
1518*6777b538SAndroid Build Coastguard Worker         }
1519*6777b538SAndroid Build Coastguard Worker 
1520*6777b538SAndroid Build Coastguard Worker         if (*cur == '.') {
1521*6777b538SAndroid Build Coastguard Worker             if (cur[1] == 0) {
1522*6777b538SAndroid Build Coastguard Worker                 /* Ignore "." at end of path */
1523*6777b538SAndroid Build Coastguard Worker                 break;
1524*6777b538SAndroid Build Coastguard Worker             } else if (xmlIsPathSeparator(cur[1], isFile)) {
1525*6777b538SAndroid Build Coastguard Worker                 /* Skip "./" */
1526*6777b538SAndroid Build Coastguard Worker                 cur += 2;
1527*6777b538SAndroid Build Coastguard Worker                 continue;
1528*6777b538SAndroid Build Coastguard Worker             } else if ((cur[1] == '.') &&
1529*6777b538SAndroid Build Coastguard Worker                        ((cur[2] == 0) || xmlIsPathSeparator(cur[2], isFile))) {
1530*6777b538SAndroid Build Coastguard Worker                 if (numSeg > 0) {
1531*6777b538SAndroid Build Coastguard Worker                     /* Handle ".." by removing last segment */
1532*6777b538SAndroid Build Coastguard Worker                     do {
1533*6777b538SAndroid Build Coastguard Worker                         out--;
1534*6777b538SAndroid Build Coastguard Worker                     } while ((out > path) &&
1535*6777b538SAndroid Build Coastguard Worker                              !xmlIsPathSeparator(out[-1], isFile));
1536*6777b538SAndroid Build Coastguard Worker                     numSeg--;
1537*6777b538SAndroid Build Coastguard Worker 
1538*6777b538SAndroid Build Coastguard Worker                     if (cur[2] == 0)
1539*6777b538SAndroid Build Coastguard Worker                         break;
1540*6777b538SAndroid Build Coastguard Worker                     cur += 3;
1541*6777b538SAndroid Build Coastguard Worker                     continue;
1542*6777b538SAndroid Build Coastguard Worker                 } else if (out[0] == '/') {
1543*6777b538SAndroid Build Coastguard Worker                     /* Ignore extraneous ".." in absolute paths */
1544*6777b538SAndroid Build Coastguard Worker                     if (cur[2] == 0)
1545*6777b538SAndroid Build Coastguard Worker                         break;
1546*6777b538SAndroid Build Coastguard Worker                     cur += 3;
1547*6777b538SAndroid Build Coastguard Worker                     continue;
1548*6777b538SAndroid Build Coastguard Worker                 } else {
1549*6777b538SAndroid Build Coastguard Worker                     /* Keep "../" at start of relative path */
1550*6777b538SAndroid Build Coastguard Worker                     numSeg--;
1551*6777b538SAndroid Build Coastguard Worker                 }
1552*6777b538SAndroid Build Coastguard Worker             }
1553*6777b538SAndroid Build Coastguard Worker         }
1554*6777b538SAndroid Build Coastguard Worker 
1555*6777b538SAndroid Build Coastguard Worker         /* Copy segment */
1556*6777b538SAndroid Build Coastguard Worker         while ((*cur != 0) && !xmlIsPathSeparator(*cur, isFile)) {
1557*6777b538SAndroid Build Coastguard Worker             *out++ = *cur++;
1558*6777b538SAndroid Build Coastguard Worker         }
1559*6777b538SAndroid Build Coastguard Worker 
1560*6777b538SAndroid Build Coastguard Worker         /* Copy separator */
1561*6777b538SAndroid Build Coastguard Worker         if (*cur != 0) {
1562*6777b538SAndroid Build Coastguard Worker             cur++;
1563*6777b538SAndroid Build Coastguard Worker             *out++ = '/';
1564*6777b538SAndroid Build Coastguard Worker         }
1565*6777b538SAndroid Build Coastguard Worker 
1566*6777b538SAndroid Build Coastguard Worker         numSeg++;
1567*6777b538SAndroid Build Coastguard Worker     }
1568*6777b538SAndroid Build Coastguard Worker 
1569*6777b538SAndroid Build Coastguard Worker     /* Keep "." if output is empty and it's a file */
1570*6777b538SAndroid Build Coastguard Worker     if ((isFile) && (out <= path))
1571*6777b538SAndroid Build Coastguard Worker         *out++ = '.';
1572*6777b538SAndroid Build Coastguard Worker     *out = 0;
1573*6777b538SAndroid Build Coastguard Worker 
1574*6777b538SAndroid Build Coastguard Worker     return(0);
1575*6777b538SAndroid Build Coastguard Worker }
1576*6777b538SAndroid Build Coastguard Worker 
1577*6777b538SAndroid Build Coastguard Worker /**
1578*6777b538SAndroid Build Coastguard Worker  * xmlNormalizeURIPath:
1579*6777b538SAndroid Build Coastguard Worker  * @path:  pointer to the path string
1580*6777b538SAndroid Build Coastguard Worker  *
1581*6777b538SAndroid Build Coastguard Worker  * Applies the 5 normalization steps to a path string--that is, RFC 2396
1582*6777b538SAndroid Build Coastguard Worker  * Section 5.2, steps 6.c through 6.g.
1583*6777b538SAndroid Build Coastguard Worker  *
1584*6777b538SAndroid Build Coastguard Worker  * Normalization occurs directly on the string, no new allocation is done
1585*6777b538SAndroid Build Coastguard Worker  *
1586*6777b538SAndroid Build Coastguard Worker  * Returns 0 or an error code
1587*6777b538SAndroid Build Coastguard Worker  */
1588*6777b538SAndroid Build Coastguard Worker int
xmlNormalizeURIPath(char * path)1589*6777b538SAndroid Build Coastguard Worker xmlNormalizeURIPath(char *path) {
1590*6777b538SAndroid Build Coastguard Worker     return(xmlNormalizePath(path, 0));
1591*6777b538SAndroid Build Coastguard Worker }
1592*6777b538SAndroid Build Coastguard Worker 
is_hex(char c)1593*6777b538SAndroid Build Coastguard Worker static int is_hex(char c) {
1594*6777b538SAndroid Build Coastguard Worker     if (((c >= '0') && (c <= '9')) ||
1595*6777b538SAndroid Build Coastguard Worker         ((c >= 'a') && (c <= 'f')) ||
1596*6777b538SAndroid Build Coastguard Worker         ((c >= 'A') && (c <= 'F')))
1597*6777b538SAndroid Build Coastguard Worker 	return(1);
1598*6777b538SAndroid Build Coastguard Worker     return(0);
1599*6777b538SAndroid Build Coastguard Worker }
1600*6777b538SAndroid Build Coastguard Worker 
1601*6777b538SAndroid Build Coastguard Worker /**
1602*6777b538SAndroid Build Coastguard Worker  * xmlURIUnescapeString:
1603*6777b538SAndroid Build Coastguard Worker  * @str:  the string to unescape
1604*6777b538SAndroid Build Coastguard Worker  * @len:   the length in bytes to unescape (or <= 0 to indicate full string)
1605*6777b538SAndroid Build Coastguard Worker  * @target:  optional destination buffer
1606*6777b538SAndroid Build Coastguard Worker  *
1607*6777b538SAndroid Build Coastguard Worker  * Unescaping routine, but does not check that the string is an URI. The
1608*6777b538SAndroid Build Coastguard Worker  * output is a direct unsigned char translation of %XX values (no encoding)
1609*6777b538SAndroid Build Coastguard Worker  * Note that the length of the result can only be smaller or same size as
1610*6777b538SAndroid Build Coastguard Worker  * the input string.
1611*6777b538SAndroid Build Coastguard Worker  *
1612*6777b538SAndroid Build Coastguard Worker  * Returns a copy of the string, but unescaped, will return NULL only in case
1613*6777b538SAndroid Build Coastguard Worker  * of error
1614*6777b538SAndroid Build Coastguard Worker  */
1615*6777b538SAndroid Build Coastguard Worker char *
xmlURIUnescapeString(const char * str,int len,char * target)1616*6777b538SAndroid Build Coastguard Worker xmlURIUnescapeString(const char *str, int len, char *target) {
1617*6777b538SAndroid Build Coastguard Worker     char *ret, *out;
1618*6777b538SAndroid Build Coastguard Worker     const char *in;
1619*6777b538SAndroid Build Coastguard Worker 
1620*6777b538SAndroid Build Coastguard Worker     if (str == NULL)
1621*6777b538SAndroid Build Coastguard Worker 	return(NULL);
1622*6777b538SAndroid Build Coastguard Worker     if (len <= 0) len = strlen(str);
1623*6777b538SAndroid Build Coastguard Worker     if (len < 0) return(NULL);
1624*6777b538SAndroid Build Coastguard Worker 
1625*6777b538SAndroid Build Coastguard Worker     if (target == NULL) {
1626*6777b538SAndroid Build Coastguard Worker 	ret = (char *) xmlMallocAtomic(len + 1);
1627*6777b538SAndroid Build Coastguard Worker 	if (ret == NULL)
1628*6777b538SAndroid Build Coastguard Worker 	    return(NULL);
1629*6777b538SAndroid Build Coastguard Worker     } else
1630*6777b538SAndroid Build Coastguard Worker 	ret = target;
1631*6777b538SAndroid Build Coastguard Worker     in = str;
1632*6777b538SAndroid Build Coastguard Worker     out = ret;
1633*6777b538SAndroid Build Coastguard Worker     while(len > 0) {
1634*6777b538SAndroid Build Coastguard Worker 	if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) {
1635*6777b538SAndroid Build Coastguard Worker             int c = 0;
1636*6777b538SAndroid Build Coastguard Worker 	    in++;
1637*6777b538SAndroid Build Coastguard Worker 	    if ((*in >= '0') && (*in <= '9'))
1638*6777b538SAndroid Build Coastguard Worker 	        c = (*in - '0');
1639*6777b538SAndroid Build Coastguard Worker 	    else if ((*in >= 'a') && (*in <= 'f'))
1640*6777b538SAndroid Build Coastguard Worker 	        c = (*in - 'a') + 10;
1641*6777b538SAndroid Build Coastguard Worker 	    else if ((*in >= 'A') && (*in <= 'F'))
1642*6777b538SAndroid Build Coastguard Worker 	        c = (*in - 'A') + 10;
1643*6777b538SAndroid Build Coastguard Worker 	    in++;
1644*6777b538SAndroid Build Coastguard Worker 	    if ((*in >= '0') && (*in <= '9'))
1645*6777b538SAndroid Build Coastguard Worker 	        c = c * 16 + (*in - '0');
1646*6777b538SAndroid Build Coastguard Worker 	    else if ((*in >= 'a') && (*in <= 'f'))
1647*6777b538SAndroid Build Coastguard Worker 	        c = c * 16 + (*in - 'a') + 10;
1648*6777b538SAndroid Build Coastguard Worker 	    else if ((*in >= 'A') && (*in <= 'F'))
1649*6777b538SAndroid Build Coastguard Worker 	        c = c * 16 + (*in - 'A') + 10;
1650*6777b538SAndroid Build Coastguard Worker 	    in++;
1651*6777b538SAndroid Build Coastguard Worker 	    len -= 3;
1652*6777b538SAndroid Build Coastguard Worker             /* Explicit sign change */
1653*6777b538SAndroid Build Coastguard Worker 	    *out++ = (char) c;
1654*6777b538SAndroid Build Coastguard Worker 	} else {
1655*6777b538SAndroid Build Coastguard Worker 	    *out++ = *in++;
1656*6777b538SAndroid Build Coastguard Worker 	    len--;
1657*6777b538SAndroid Build Coastguard Worker 	}
1658*6777b538SAndroid Build Coastguard Worker     }
1659*6777b538SAndroid Build Coastguard Worker     *out = 0;
1660*6777b538SAndroid Build Coastguard Worker     return(ret);
1661*6777b538SAndroid Build Coastguard Worker }
1662*6777b538SAndroid Build Coastguard Worker 
1663*6777b538SAndroid Build Coastguard Worker /**
1664*6777b538SAndroid Build Coastguard Worker  * xmlURIEscapeStr:
1665*6777b538SAndroid Build Coastguard Worker  * @str:  string to escape
1666*6777b538SAndroid Build Coastguard Worker  * @list: exception list string of chars not to escape
1667*6777b538SAndroid Build Coastguard Worker  *
1668*6777b538SAndroid Build Coastguard Worker  * This routine escapes a string to hex, ignoring unreserved characters
1669*6777b538SAndroid Build Coastguard Worker  * a-z, A-Z, 0-9, "-._~", a few sub-delims "!*'()", the gen-delim "@"
1670*6777b538SAndroid Build Coastguard Worker  * (why?) and the characters in the exception list.
1671*6777b538SAndroid Build Coastguard Worker  *
1672*6777b538SAndroid Build Coastguard Worker  * Returns a new escaped string or NULL in case of error.
1673*6777b538SAndroid Build Coastguard Worker  */
1674*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlURIEscapeStr(const xmlChar * str,const xmlChar * list)1675*6777b538SAndroid Build Coastguard Worker xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) {
1676*6777b538SAndroid Build Coastguard Worker     xmlChar *ret, ch;
1677*6777b538SAndroid Build Coastguard Worker     xmlChar *temp;
1678*6777b538SAndroid Build Coastguard Worker     const xmlChar *in;
1679*6777b538SAndroid Build Coastguard Worker     int len, out;
1680*6777b538SAndroid Build Coastguard Worker 
1681*6777b538SAndroid Build Coastguard Worker     if (str == NULL)
1682*6777b538SAndroid Build Coastguard Worker 	return(NULL);
1683*6777b538SAndroid Build Coastguard Worker     if (str[0] == 0)
1684*6777b538SAndroid Build Coastguard Worker 	return(xmlStrdup(str));
1685*6777b538SAndroid Build Coastguard Worker     len = xmlStrlen(str);
1686*6777b538SAndroid Build Coastguard Worker 
1687*6777b538SAndroid Build Coastguard Worker     len += 20;
1688*6777b538SAndroid Build Coastguard Worker     ret = (xmlChar *) xmlMallocAtomic(len);
1689*6777b538SAndroid Build Coastguard Worker     if (ret == NULL)
1690*6777b538SAndroid Build Coastguard Worker 	return(NULL);
1691*6777b538SAndroid Build Coastguard Worker     in = (const xmlChar *) str;
1692*6777b538SAndroid Build Coastguard Worker     out = 0;
1693*6777b538SAndroid Build Coastguard Worker     while(*in != 0) {
1694*6777b538SAndroid Build Coastguard Worker 	if (len - out <= 3) {
1695*6777b538SAndroid Build Coastguard Worker             if (len > INT_MAX / 2)
1696*6777b538SAndroid Build Coastguard Worker                 return(NULL);
1697*6777b538SAndroid Build Coastguard Worker             temp = xmlRealloc(ret, len * 2);
1698*6777b538SAndroid Build Coastguard Worker 	    if (temp == NULL) {
1699*6777b538SAndroid Build Coastguard Worker 		xmlFree(ret);
1700*6777b538SAndroid Build Coastguard Worker 		return(NULL);
1701*6777b538SAndroid Build Coastguard Worker 	    }
1702*6777b538SAndroid Build Coastguard Worker 	    ret = temp;
1703*6777b538SAndroid Build Coastguard Worker             len *= 2;
1704*6777b538SAndroid Build Coastguard Worker 	}
1705*6777b538SAndroid Build Coastguard Worker 
1706*6777b538SAndroid Build Coastguard Worker 	ch = *in;
1707*6777b538SAndroid Build Coastguard Worker 
1708*6777b538SAndroid Build Coastguard Worker 	if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!xmlStrchr(list, ch))) {
1709*6777b538SAndroid Build Coastguard Worker 	    unsigned char val;
1710*6777b538SAndroid Build Coastguard Worker 	    ret[out++] = '%';
1711*6777b538SAndroid Build Coastguard Worker 	    val = ch >> 4;
1712*6777b538SAndroid Build Coastguard Worker 	    if (val <= 9)
1713*6777b538SAndroid Build Coastguard Worker 		ret[out++] = '0' + val;
1714*6777b538SAndroid Build Coastguard Worker 	    else
1715*6777b538SAndroid Build Coastguard Worker 		ret[out++] = 'A' + val - 0xA;
1716*6777b538SAndroid Build Coastguard Worker 	    val = ch & 0xF;
1717*6777b538SAndroid Build Coastguard Worker 	    if (val <= 9)
1718*6777b538SAndroid Build Coastguard Worker 		ret[out++] = '0' + val;
1719*6777b538SAndroid Build Coastguard Worker 	    else
1720*6777b538SAndroid Build Coastguard Worker 		ret[out++] = 'A' + val - 0xA;
1721*6777b538SAndroid Build Coastguard Worker 	    in++;
1722*6777b538SAndroid Build Coastguard Worker 	} else {
1723*6777b538SAndroid Build Coastguard Worker 	    ret[out++] = *in++;
1724*6777b538SAndroid Build Coastguard Worker 	}
1725*6777b538SAndroid Build Coastguard Worker 
1726*6777b538SAndroid Build Coastguard Worker     }
1727*6777b538SAndroid Build Coastguard Worker     ret[out] = 0;
1728*6777b538SAndroid Build Coastguard Worker     return(ret);
1729*6777b538SAndroid Build Coastguard Worker }
1730*6777b538SAndroid Build Coastguard Worker 
1731*6777b538SAndroid Build Coastguard Worker /**
1732*6777b538SAndroid Build Coastguard Worker  * xmlURIEscape:
1733*6777b538SAndroid Build Coastguard Worker  * @str:  the string of the URI to escape
1734*6777b538SAndroid Build Coastguard Worker  *
1735*6777b538SAndroid Build Coastguard Worker  * Escaping routine, does not do validity checks !
1736*6777b538SAndroid Build Coastguard Worker  * It will try to escape the chars needing this, but this is heuristic
1737*6777b538SAndroid Build Coastguard Worker  * based it's impossible to be sure.
1738*6777b538SAndroid Build Coastguard Worker  *
1739*6777b538SAndroid Build Coastguard Worker  * Returns an copy of the string, but escaped
1740*6777b538SAndroid Build Coastguard Worker  *
1741*6777b538SAndroid Build Coastguard Worker  * 25 May 2001
1742*6777b538SAndroid Build Coastguard Worker  * Uses xmlParseURI and xmlURIEscapeStr to try to escape correctly
1743*6777b538SAndroid Build Coastguard Worker  * according to RFC2396.
1744*6777b538SAndroid Build Coastguard Worker  *   - Carl Douglas
1745*6777b538SAndroid Build Coastguard Worker  */
1746*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlURIEscape(const xmlChar * str)1747*6777b538SAndroid Build Coastguard Worker xmlURIEscape(const xmlChar * str)
1748*6777b538SAndroid Build Coastguard Worker {
1749*6777b538SAndroid Build Coastguard Worker     xmlChar *ret, *segment = NULL;
1750*6777b538SAndroid Build Coastguard Worker     xmlURIPtr uri;
1751*6777b538SAndroid Build Coastguard Worker     int ret2;
1752*6777b538SAndroid Build Coastguard Worker 
1753*6777b538SAndroid Build Coastguard Worker     if (str == NULL)
1754*6777b538SAndroid Build Coastguard Worker         return (NULL);
1755*6777b538SAndroid Build Coastguard Worker 
1756*6777b538SAndroid Build Coastguard Worker     uri = xmlCreateURI();
1757*6777b538SAndroid Build Coastguard Worker     if (uri != NULL) {
1758*6777b538SAndroid Build Coastguard Worker 	/*
1759*6777b538SAndroid Build Coastguard Worker 	 * Allow escaping errors in the unescaped form
1760*6777b538SAndroid Build Coastguard Worker 	 */
1761*6777b538SAndroid Build Coastguard Worker         uri->cleanup = XML_URI_ALLOW_UNWISE;
1762*6777b538SAndroid Build Coastguard Worker         ret2 = xmlParseURIReference(uri, (const char *)str);
1763*6777b538SAndroid Build Coastguard Worker         if (ret2) {
1764*6777b538SAndroid Build Coastguard Worker             xmlFreeURI(uri);
1765*6777b538SAndroid Build Coastguard Worker             return (NULL);
1766*6777b538SAndroid Build Coastguard Worker         }
1767*6777b538SAndroid Build Coastguard Worker     }
1768*6777b538SAndroid Build Coastguard Worker 
1769*6777b538SAndroid Build Coastguard Worker     if (!uri)
1770*6777b538SAndroid Build Coastguard Worker         return NULL;
1771*6777b538SAndroid Build Coastguard Worker 
1772*6777b538SAndroid Build Coastguard Worker     ret = NULL;
1773*6777b538SAndroid Build Coastguard Worker 
1774*6777b538SAndroid Build Coastguard Worker #define NULLCHK(p) if(!p) { \
1775*6777b538SAndroid Build Coastguard Worker          xmlFreeURI(uri); \
1776*6777b538SAndroid Build Coastguard Worker          xmlFree(ret); \
1777*6777b538SAndroid Build Coastguard Worker          return NULL; } \
1778*6777b538SAndroid Build Coastguard Worker 
1779*6777b538SAndroid Build Coastguard Worker     if (uri->scheme) {
1780*6777b538SAndroid Build Coastguard Worker         segment = xmlURIEscapeStr(BAD_CAST uri->scheme, BAD_CAST "+-.");
1781*6777b538SAndroid Build Coastguard Worker         NULLCHK(segment)
1782*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, segment);
1783*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, BAD_CAST ":");
1784*6777b538SAndroid Build Coastguard Worker         xmlFree(segment);
1785*6777b538SAndroid Build Coastguard Worker     }
1786*6777b538SAndroid Build Coastguard Worker 
1787*6777b538SAndroid Build Coastguard Worker     if (uri->authority) {
1788*6777b538SAndroid Build Coastguard Worker         segment =
1789*6777b538SAndroid Build Coastguard Worker             xmlURIEscapeStr(BAD_CAST uri->authority, BAD_CAST "/?;:@");
1790*6777b538SAndroid Build Coastguard Worker         NULLCHK(segment)
1791*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, BAD_CAST "//");
1792*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, segment);
1793*6777b538SAndroid Build Coastguard Worker         xmlFree(segment);
1794*6777b538SAndroid Build Coastguard Worker     }
1795*6777b538SAndroid Build Coastguard Worker 
1796*6777b538SAndroid Build Coastguard Worker     if (uri->user) {
1797*6777b538SAndroid Build Coastguard Worker         segment = xmlURIEscapeStr(BAD_CAST uri->user, BAD_CAST ";:&=+$,");
1798*6777b538SAndroid Build Coastguard Worker         NULLCHK(segment)
1799*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret,BAD_CAST "//");
1800*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, segment);
1801*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, BAD_CAST "@");
1802*6777b538SAndroid Build Coastguard Worker         xmlFree(segment);
1803*6777b538SAndroid Build Coastguard Worker     }
1804*6777b538SAndroid Build Coastguard Worker 
1805*6777b538SAndroid Build Coastguard Worker     if (uri->server) {
1806*6777b538SAndroid Build Coastguard Worker         segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@");
1807*6777b538SAndroid Build Coastguard Worker         NULLCHK(segment)
1808*6777b538SAndroid Build Coastguard Worker         if (uri->user == NULL)
1809*6777b538SAndroid Build Coastguard Worker             ret = xmlStrcat(ret, BAD_CAST "//");
1810*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, segment);
1811*6777b538SAndroid Build Coastguard Worker         xmlFree(segment);
1812*6777b538SAndroid Build Coastguard Worker     }
1813*6777b538SAndroid Build Coastguard Worker 
1814*6777b538SAndroid Build Coastguard Worker     if (uri->port > 0) {
1815*6777b538SAndroid Build Coastguard Worker         xmlChar port[11];
1816*6777b538SAndroid Build Coastguard Worker 
1817*6777b538SAndroid Build Coastguard Worker         snprintf((char *) port, 11, "%d", uri->port);
1818*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, BAD_CAST ":");
1819*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, port);
1820*6777b538SAndroid Build Coastguard Worker     }
1821*6777b538SAndroid Build Coastguard Worker 
1822*6777b538SAndroid Build Coastguard Worker     if (uri->path) {
1823*6777b538SAndroid Build Coastguard Worker         segment =
1824*6777b538SAndroid Build Coastguard Worker             xmlURIEscapeStr(BAD_CAST uri->path, BAD_CAST ":@&=+$,/?;");
1825*6777b538SAndroid Build Coastguard Worker         NULLCHK(segment)
1826*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, segment);
1827*6777b538SAndroid Build Coastguard Worker         xmlFree(segment);
1828*6777b538SAndroid Build Coastguard Worker     }
1829*6777b538SAndroid Build Coastguard Worker 
1830*6777b538SAndroid Build Coastguard Worker     if (uri->query_raw) {
1831*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, BAD_CAST "?");
1832*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, BAD_CAST uri->query_raw);
1833*6777b538SAndroid Build Coastguard Worker     }
1834*6777b538SAndroid Build Coastguard Worker     else if (uri->query) {
1835*6777b538SAndroid Build Coastguard Worker         segment =
1836*6777b538SAndroid Build Coastguard Worker             xmlURIEscapeStr(BAD_CAST uri->query, BAD_CAST ";/?:@&=+,$");
1837*6777b538SAndroid Build Coastguard Worker         NULLCHK(segment)
1838*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, BAD_CAST "?");
1839*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, segment);
1840*6777b538SAndroid Build Coastguard Worker         xmlFree(segment);
1841*6777b538SAndroid Build Coastguard Worker     }
1842*6777b538SAndroid Build Coastguard Worker 
1843*6777b538SAndroid Build Coastguard Worker     if (uri->opaque) {
1844*6777b538SAndroid Build Coastguard Worker         segment = xmlURIEscapeStr(BAD_CAST uri->opaque, BAD_CAST "");
1845*6777b538SAndroid Build Coastguard Worker         NULLCHK(segment)
1846*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, segment);
1847*6777b538SAndroid Build Coastguard Worker         xmlFree(segment);
1848*6777b538SAndroid Build Coastguard Worker     }
1849*6777b538SAndroid Build Coastguard Worker 
1850*6777b538SAndroid Build Coastguard Worker     if (uri->fragment) {
1851*6777b538SAndroid Build Coastguard Worker         segment = xmlURIEscapeStr(BAD_CAST uri->fragment, BAD_CAST "#");
1852*6777b538SAndroid Build Coastguard Worker         NULLCHK(segment)
1853*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, BAD_CAST "#");
1854*6777b538SAndroid Build Coastguard Worker         ret = xmlStrcat(ret, segment);
1855*6777b538SAndroid Build Coastguard Worker         xmlFree(segment);
1856*6777b538SAndroid Build Coastguard Worker     }
1857*6777b538SAndroid Build Coastguard Worker 
1858*6777b538SAndroid Build Coastguard Worker     xmlFreeURI(uri);
1859*6777b538SAndroid Build Coastguard Worker #undef NULLCHK
1860*6777b538SAndroid Build Coastguard Worker 
1861*6777b538SAndroid Build Coastguard Worker     return (ret);
1862*6777b538SAndroid Build Coastguard Worker }
1863*6777b538SAndroid Build Coastguard Worker 
1864*6777b538SAndroid Build Coastguard Worker /************************************************************************
1865*6777b538SAndroid Build Coastguard Worker  *									*
1866*6777b538SAndroid Build Coastguard Worker  *			Public functions				*
1867*6777b538SAndroid Build Coastguard Worker  *									*
1868*6777b538SAndroid Build Coastguard Worker  ************************************************************************/
1869*6777b538SAndroid Build Coastguard Worker 
1870*6777b538SAndroid Build Coastguard Worker static int
xmlIsAbsolutePath(const xmlChar * path)1871*6777b538SAndroid Build Coastguard Worker xmlIsAbsolutePath(const xmlChar *path) {
1872*6777b538SAndroid Build Coastguard Worker     int c = path[0];
1873*6777b538SAndroid Build Coastguard Worker 
1874*6777b538SAndroid Build Coastguard Worker     if (xmlIsPathSeparator(c, 1))
1875*6777b538SAndroid Build Coastguard Worker         return(1);
1876*6777b538SAndroid Build Coastguard Worker 
1877*6777b538SAndroid Build Coastguard Worker #ifdef _WIN32
1878*6777b538SAndroid Build Coastguard Worker     if ((((c >= 'A') && (c <= 'Z')) ||
1879*6777b538SAndroid Build Coastguard Worker          ((c >= 'a') && (c <= 'z'))) &&
1880*6777b538SAndroid Build Coastguard Worker         (path[1] == ':'))
1881*6777b538SAndroid Build Coastguard Worker         return(1);
1882*6777b538SAndroid Build Coastguard Worker #endif
1883*6777b538SAndroid Build Coastguard Worker 
1884*6777b538SAndroid Build Coastguard Worker     return(0);
1885*6777b538SAndroid Build Coastguard Worker }
1886*6777b538SAndroid Build Coastguard Worker 
1887*6777b538SAndroid Build Coastguard Worker /**
1888*6777b538SAndroid Build Coastguard Worker  * xmlResolvePath:
1889*6777b538SAndroid Build Coastguard Worker  * @ref:  the filesystem path
1890*6777b538SAndroid Build Coastguard Worker  * @base:  the base value
1891*6777b538SAndroid Build Coastguard Worker  * @out:  pointer to result URI
1892*6777b538SAndroid Build Coastguard Worker  *
1893*6777b538SAndroid Build Coastguard Worker  * Resolves a filesystem path from a base path.
1894*6777b538SAndroid Build Coastguard Worker  *
1895*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success, -1 if a memory allocation failed or an error
1896*6777b538SAndroid Build Coastguard Worker  * code if URI or base are invalid.
1897*6777b538SAndroid Build Coastguard Worker  */
1898*6777b538SAndroid Build Coastguard Worker static int
xmlResolvePath(const xmlChar * escRef,const xmlChar * base,xmlChar ** out)1899*6777b538SAndroid Build Coastguard Worker xmlResolvePath(const xmlChar *escRef, const xmlChar *base, xmlChar **out) {
1900*6777b538SAndroid Build Coastguard Worker     const xmlChar *fragment;
1901*6777b538SAndroid Build Coastguard Worker     xmlChar *tmp = NULL;
1902*6777b538SAndroid Build Coastguard Worker     xmlChar *ref = NULL;
1903*6777b538SAndroid Build Coastguard Worker     xmlChar *result = NULL;
1904*6777b538SAndroid Build Coastguard Worker     int ret = -1;
1905*6777b538SAndroid Build Coastguard Worker     int i;
1906*6777b538SAndroid Build Coastguard Worker 
1907*6777b538SAndroid Build Coastguard Worker     if (out == NULL)
1908*6777b538SAndroid Build Coastguard Worker         return(1);
1909*6777b538SAndroid Build Coastguard Worker     *out = NULL;
1910*6777b538SAndroid Build Coastguard Worker 
1911*6777b538SAndroid Build Coastguard Worker     if ((escRef == NULL) || (escRef[0] == 0)) {
1912*6777b538SAndroid Build Coastguard Worker         if ((base == NULL) || (base[0] == 0))
1913*6777b538SAndroid Build Coastguard Worker             return(1);
1914*6777b538SAndroid Build Coastguard Worker         ref = xmlStrdup(base);
1915*6777b538SAndroid Build Coastguard Worker         if (ref == NULL)
1916*6777b538SAndroid Build Coastguard Worker             goto err_memory;
1917*6777b538SAndroid Build Coastguard Worker         *out = ref;
1918*6777b538SAndroid Build Coastguard Worker         return(0);
1919*6777b538SAndroid Build Coastguard Worker     }
1920*6777b538SAndroid Build Coastguard Worker 
1921*6777b538SAndroid Build Coastguard Worker     /*
1922*6777b538SAndroid Build Coastguard Worker      * If a URI is resolved, we can assume it is a valid URI and not
1923*6777b538SAndroid Build Coastguard Worker      * a filesystem path. This means we have to unescape the part
1924*6777b538SAndroid Build Coastguard Worker      * before the fragment.
1925*6777b538SAndroid Build Coastguard Worker      */
1926*6777b538SAndroid Build Coastguard Worker     fragment = xmlStrchr(escRef, '#');
1927*6777b538SAndroid Build Coastguard Worker     if (fragment != NULL) {
1928*6777b538SAndroid Build Coastguard Worker         tmp = xmlStrndup(escRef, fragment - escRef);
1929*6777b538SAndroid Build Coastguard Worker         if (tmp == NULL)
1930*6777b538SAndroid Build Coastguard Worker             goto err_memory;
1931*6777b538SAndroid Build Coastguard Worker         escRef = tmp;
1932*6777b538SAndroid Build Coastguard Worker     }
1933*6777b538SAndroid Build Coastguard Worker 
1934*6777b538SAndroid Build Coastguard Worker     ref = (xmlChar *) xmlURIUnescapeString((char *) escRef, -1, NULL);
1935*6777b538SAndroid Build Coastguard Worker     if (ref == NULL)
1936*6777b538SAndroid Build Coastguard Worker         goto err_memory;
1937*6777b538SAndroid Build Coastguard Worker 
1938*6777b538SAndroid Build Coastguard Worker     if ((base == NULL) || (base[0] == 0))
1939*6777b538SAndroid Build Coastguard Worker         goto done;
1940*6777b538SAndroid Build Coastguard Worker 
1941*6777b538SAndroid Build Coastguard Worker     if (xmlIsAbsolutePath(ref))
1942*6777b538SAndroid Build Coastguard Worker         goto done;
1943*6777b538SAndroid Build Coastguard Worker 
1944*6777b538SAndroid Build Coastguard Worker     /*
1945*6777b538SAndroid Build Coastguard Worker      * Remove last segment from base
1946*6777b538SAndroid Build Coastguard Worker      */
1947*6777b538SAndroid Build Coastguard Worker     i = xmlStrlen(base);
1948*6777b538SAndroid Build Coastguard Worker     while ((i > 0) && !xmlIsPathSeparator(base[i-1], 1))
1949*6777b538SAndroid Build Coastguard Worker         i--;
1950*6777b538SAndroid Build Coastguard Worker 
1951*6777b538SAndroid Build Coastguard Worker     /*
1952*6777b538SAndroid Build Coastguard Worker      * Concatenate base and ref
1953*6777b538SAndroid Build Coastguard Worker      */
1954*6777b538SAndroid Build Coastguard Worker     if (i > 0) {
1955*6777b538SAndroid Build Coastguard Worker         int refLen = xmlStrlen(ref);
1956*6777b538SAndroid Build Coastguard Worker 
1957*6777b538SAndroid Build Coastguard Worker         result = xmlMalloc(i + refLen + 1);
1958*6777b538SAndroid Build Coastguard Worker         if (result == NULL)
1959*6777b538SAndroid Build Coastguard Worker             goto err_memory;
1960*6777b538SAndroid Build Coastguard Worker 
1961*6777b538SAndroid Build Coastguard Worker         memcpy(result, base, i);
1962*6777b538SAndroid Build Coastguard Worker         memcpy(result + i, ref, refLen + 1);
1963*6777b538SAndroid Build Coastguard Worker     }
1964*6777b538SAndroid Build Coastguard Worker 
1965*6777b538SAndroid Build Coastguard Worker     /*
1966*6777b538SAndroid Build Coastguard Worker      * Normalize
1967*6777b538SAndroid Build Coastguard Worker      */
1968*6777b538SAndroid Build Coastguard Worker     xmlNormalizePath((char *) result, 1);
1969*6777b538SAndroid Build Coastguard Worker 
1970*6777b538SAndroid Build Coastguard Worker done:
1971*6777b538SAndroid Build Coastguard Worker     if (result == NULL) {
1972*6777b538SAndroid Build Coastguard Worker         result = ref;
1973*6777b538SAndroid Build Coastguard Worker         ref = NULL;
1974*6777b538SAndroid Build Coastguard Worker     }
1975*6777b538SAndroid Build Coastguard Worker 
1976*6777b538SAndroid Build Coastguard Worker     if (fragment != NULL) {
1977*6777b538SAndroid Build Coastguard Worker         result = xmlStrcat(result, fragment);
1978*6777b538SAndroid Build Coastguard Worker         if (result == NULL)
1979*6777b538SAndroid Build Coastguard Worker             goto err_memory;
1980*6777b538SAndroid Build Coastguard Worker     }
1981*6777b538SAndroid Build Coastguard Worker 
1982*6777b538SAndroid Build Coastguard Worker     *out = result;
1983*6777b538SAndroid Build Coastguard Worker     ret = 0;
1984*6777b538SAndroid Build Coastguard Worker 
1985*6777b538SAndroid Build Coastguard Worker err_memory:
1986*6777b538SAndroid Build Coastguard Worker     xmlFree(tmp);
1987*6777b538SAndroid Build Coastguard Worker     xmlFree(ref);
1988*6777b538SAndroid Build Coastguard Worker     return(ret);
1989*6777b538SAndroid Build Coastguard Worker }
1990*6777b538SAndroid Build Coastguard Worker 
1991*6777b538SAndroid Build Coastguard Worker /**
1992*6777b538SAndroid Build Coastguard Worker  * xmlBulidURISafe:
1993*6777b538SAndroid Build Coastguard Worker  * @URI:  the URI instance found in the document
1994*6777b538SAndroid Build Coastguard Worker  * @base:  the base value
1995*6777b538SAndroid Build Coastguard Worker  * @valPtr:  pointer to result URI
1996*6777b538SAndroid Build Coastguard Worker  *
1997*6777b538SAndroid Build Coastguard Worker  * Computes he final URI of the reference done by checking that
1998*6777b538SAndroid Build Coastguard Worker  * the given URI is valid, and building the final URI using the
1999*6777b538SAndroid Build Coastguard Worker  * base URI. This is processed according to section 5.2 of the
2000*6777b538SAndroid Build Coastguard Worker  * RFC 2396
2001*6777b538SAndroid Build Coastguard Worker  *
2002*6777b538SAndroid Build Coastguard Worker  * 5.2. Resolving Relative References to Absolute Form
2003*6777b538SAndroid Build Coastguard Worker  *
2004*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success, -1 if a memory allocation failed or an error
2005*6777b538SAndroid Build Coastguard Worker  * code if URI or base are invalid.
2006*6777b538SAndroid Build Coastguard Worker  */
2007*6777b538SAndroid Build Coastguard Worker int
xmlBuildURISafe(const xmlChar * URI,const xmlChar * base,xmlChar ** valPtr)2008*6777b538SAndroid Build Coastguard Worker xmlBuildURISafe(const xmlChar *URI, const xmlChar *base, xmlChar **valPtr) {
2009*6777b538SAndroid Build Coastguard Worker     xmlChar *val = NULL;
2010*6777b538SAndroid Build Coastguard Worker     int ret, len, indx, cur, out;
2011*6777b538SAndroid Build Coastguard Worker     xmlURIPtr ref = NULL;
2012*6777b538SAndroid Build Coastguard Worker     xmlURIPtr bas = NULL;
2013*6777b538SAndroid Build Coastguard Worker     xmlURIPtr res = NULL;
2014*6777b538SAndroid Build Coastguard Worker 
2015*6777b538SAndroid Build Coastguard Worker     /*
2016*6777b538SAndroid Build Coastguard Worker      * 1) The URI reference is parsed into the potential four components and
2017*6777b538SAndroid Build Coastguard Worker      *    fragment identifier, as described in Section 4.3.
2018*6777b538SAndroid Build Coastguard Worker      *
2019*6777b538SAndroid Build Coastguard Worker      *    NOTE that a completely empty URI is treated by modern browsers
2020*6777b538SAndroid Build Coastguard Worker      *    as a reference to "." rather than as a synonym for the current
2021*6777b538SAndroid Build Coastguard Worker      *    URI.  Should we do that here?
2022*6777b538SAndroid Build Coastguard Worker      */
2023*6777b538SAndroid Build Coastguard Worker     if (URI == NULL)
2024*6777b538SAndroid Build Coastguard Worker         ret = 1;
2025*6777b538SAndroid Build Coastguard Worker     else if (URI[0] != 0)
2026*6777b538SAndroid Build Coastguard Worker         ret = xmlParseURISafe((const char *) URI, &ref);
2027*6777b538SAndroid Build Coastguard Worker     else
2028*6777b538SAndroid Build Coastguard Worker         ret = 0;
2029*6777b538SAndroid Build Coastguard Worker     if (ret != 0)
2030*6777b538SAndroid Build Coastguard Worker 	goto done;
2031*6777b538SAndroid Build Coastguard Worker     if ((ref != NULL) && (ref->scheme != NULL)) {
2032*6777b538SAndroid Build Coastguard Worker 	/*
2033*6777b538SAndroid Build Coastguard Worker 	 * The URI is absolute don't modify.
2034*6777b538SAndroid Build Coastguard Worker 	 */
2035*6777b538SAndroid Build Coastguard Worker 	val = xmlStrdup(URI);
2036*6777b538SAndroid Build Coastguard Worker         if (val == NULL)
2037*6777b538SAndroid Build Coastguard Worker             ret = -1;
2038*6777b538SAndroid Build Coastguard Worker 	goto done;
2039*6777b538SAndroid Build Coastguard Worker     }
2040*6777b538SAndroid Build Coastguard Worker 
2041*6777b538SAndroid Build Coastguard Worker     /*
2042*6777b538SAndroid Build Coastguard Worker      * If base has no scheme or authority, it is assumed to be a
2043*6777b538SAndroid Build Coastguard Worker      * filesystem path.
2044*6777b538SAndroid Build Coastguard Worker      */
2045*6777b538SAndroid Build Coastguard Worker     if (xmlStrstr(base, BAD_CAST "://") == NULL) {
2046*6777b538SAndroid Build Coastguard Worker         xmlFreeURI(ref);
2047*6777b538SAndroid Build Coastguard Worker         return(xmlResolvePath(URI, base, valPtr));
2048*6777b538SAndroid Build Coastguard Worker     }
2049*6777b538SAndroid Build Coastguard Worker 
2050*6777b538SAndroid Build Coastguard Worker     ret = xmlParseURISafe((const char *) base, &bas);
2051*6777b538SAndroid Build Coastguard Worker     if (ret < 0)
2052*6777b538SAndroid Build Coastguard Worker         goto done;
2053*6777b538SAndroid Build Coastguard Worker     if (ret != 0) {
2054*6777b538SAndroid Build Coastguard Worker 	if (ref) {
2055*6777b538SAndroid Build Coastguard Worker             ret = 0;
2056*6777b538SAndroid Build Coastguard Worker 	    val = xmlSaveUri(ref);
2057*6777b538SAndroid Build Coastguard Worker             if (val == NULL)
2058*6777b538SAndroid Build Coastguard Worker                 ret = -1;
2059*6777b538SAndroid Build Coastguard Worker         }
2060*6777b538SAndroid Build Coastguard Worker 	goto done;
2061*6777b538SAndroid Build Coastguard Worker     }
2062*6777b538SAndroid Build Coastguard Worker     if (ref == NULL) {
2063*6777b538SAndroid Build Coastguard Worker 	/*
2064*6777b538SAndroid Build Coastguard Worker 	 * the base fragment must be ignored
2065*6777b538SAndroid Build Coastguard Worker 	 */
2066*6777b538SAndroid Build Coastguard Worker 	if (bas->fragment != NULL) {
2067*6777b538SAndroid Build Coastguard Worker 	    xmlFree(bas->fragment);
2068*6777b538SAndroid Build Coastguard Worker 	    bas->fragment = NULL;
2069*6777b538SAndroid Build Coastguard Worker 	}
2070*6777b538SAndroid Build Coastguard Worker 	val = xmlSaveUri(bas);
2071*6777b538SAndroid Build Coastguard Worker         if (val == NULL)
2072*6777b538SAndroid Build Coastguard Worker             ret = -1;
2073*6777b538SAndroid Build Coastguard Worker 	goto done;
2074*6777b538SAndroid Build Coastguard Worker     }
2075*6777b538SAndroid Build Coastguard Worker 
2076*6777b538SAndroid Build Coastguard Worker     /*
2077*6777b538SAndroid Build Coastguard Worker      * 2) If the path component is empty and the scheme, authority, and
2078*6777b538SAndroid Build Coastguard Worker      *    query components are undefined, then it is a reference to the
2079*6777b538SAndroid Build Coastguard Worker      *    current document and we are done.  Otherwise, the reference URI's
2080*6777b538SAndroid Build Coastguard Worker      *    query and fragment components are defined as found (or not found)
2081*6777b538SAndroid Build Coastguard Worker      *    within the URI reference and not inherited from the base URI.
2082*6777b538SAndroid Build Coastguard Worker      *
2083*6777b538SAndroid Build Coastguard Worker      *    NOTE that in modern browsers, the parsing differs from the above
2084*6777b538SAndroid Build Coastguard Worker      *    in the following aspect:  the query component is allowed to be
2085*6777b538SAndroid Build Coastguard Worker      *    defined while still treating this as a reference to the current
2086*6777b538SAndroid Build Coastguard Worker      *    document.
2087*6777b538SAndroid Build Coastguard Worker      */
2088*6777b538SAndroid Build Coastguard Worker     ret = -1;
2089*6777b538SAndroid Build Coastguard Worker     res = xmlCreateURI();
2090*6777b538SAndroid Build Coastguard Worker     if (res == NULL)
2091*6777b538SAndroid Build Coastguard Worker 	goto done;
2092*6777b538SAndroid Build Coastguard Worker     if ((ref->scheme == NULL) && (ref->path == NULL) &&
2093*6777b538SAndroid Build Coastguard Worker 	((ref->authority == NULL) && (ref->server == NULL) &&
2094*6777b538SAndroid Build Coastguard Worker          (ref->port == PORT_EMPTY))) {
2095*6777b538SAndroid Build Coastguard Worker 	if (bas->scheme != NULL) {
2096*6777b538SAndroid Build Coastguard Worker 	    res->scheme = xmlMemStrdup(bas->scheme);
2097*6777b538SAndroid Build Coastguard Worker             if (res->scheme == NULL)
2098*6777b538SAndroid Build Coastguard Worker                 goto done;
2099*6777b538SAndroid Build Coastguard Worker         }
2100*6777b538SAndroid Build Coastguard Worker 	if (bas->authority != NULL) {
2101*6777b538SAndroid Build Coastguard Worker 	    res->authority = xmlMemStrdup(bas->authority);
2102*6777b538SAndroid Build Coastguard Worker             if (res->authority == NULL)
2103*6777b538SAndroid Build Coastguard Worker                 goto done;
2104*6777b538SAndroid Build Coastguard Worker         } else {
2105*6777b538SAndroid Build Coastguard Worker 	    if (bas->server != NULL) {
2106*6777b538SAndroid Build Coastguard Worker 		res->server = xmlMemStrdup(bas->server);
2107*6777b538SAndroid Build Coastguard Worker                 if (res->server == NULL)
2108*6777b538SAndroid Build Coastguard Worker                     goto done;
2109*6777b538SAndroid Build Coastguard Worker             }
2110*6777b538SAndroid Build Coastguard Worker 	    if (bas->user != NULL) {
2111*6777b538SAndroid Build Coastguard Worker 		res->user = xmlMemStrdup(bas->user);
2112*6777b538SAndroid Build Coastguard Worker                 if (res->user == NULL)
2113*6777b538SAndroid Build Coastguard Worker                     goto done;
2114*6777b538SAndroid Build Coastguard Worker             }
2115*6777b538SAndroid Build Coastguard Worker 	    res->port = bas->port;
2116*6777b538SAndroid Build Coastguard Worker 	}
2117*6777b538SAndroid Build Coastguard Worker 	if (bas->path != NULL) {
2118*6777b538SAndroid Build Coastguard Worker 	    res->path = xmlMemStrdup(bas->path);
2119*6777b538SAndroid Build Coastguard Worker             if (res->path == NULL)
2120*6777b538SAndroid Build Coastguard Worker                 goto done;
2121*6777b538SAndroid Build Coastguard Worker         }
2122*6777b538SAndroid Build Coastguard Worker 	if (ref->query_raw != NULL) {
2123*6777b538SAndroid Build Coastguard Worker 	    res->query_raw = xmlMemStrdup (ref->query_raw);
2124*6777b538SAndroid Build Coastguard Worker             if (res->query_raw == NULL)
2125*6777b538SAndroid Build Coastguard Worker                 goto done;
2126*6777b538SAndroid Build Coastguard Worker         } else if (ref->query != NULL) {
2127*6777b538SAndroid Build Coastguard Worker 	    res->query = xmlMemStrdup(ref->query);
2128*6777b538SAndroid Build Coastguard Worker             if (res->query == NULL)
2129*6777b538SAndroid Build Coastguard Worker                 goto done;
2130*6777b538SAndroid Build Coastguard Worker         } else if (bas->query_raw != NULL) {
2131*6777b538SAndroid Build Coastguard Worker 	    res->query_raw = xmlMemStrdup(bas->query_raw);
2132*6777b538SAndroid Build Coastguard Worker             if (res->query_raw == NULL)
2133*6777b538SAndroid Build Coastguard Worker                 goto done;
2134*6777b538SAndroid Build Coastguard Worker         } else if (bas->query != NULL) {
2135*6777b538SAndroid Build Coastguard Worker 	    res->query = xmlMemStrdup(bas->query);
2136*6777b538SAndroid Build Coastguard Worker             if (res->query == NULL)
2137*6777b538SAndroid Build Coastguard Worker                 goto done;
2138*6777b538SAndroid Build Coastguard Worker         }
2139*6777b538SAndroid Build Coastguard Worker 	if (ref->fragment != NULL) {
2140*6777b538SAndroid Build Coastguard Worker 	    res->fragment = xmlMemStrdup(ref->fragment);
2141*6777b538SAndroid Build Coastguard Worker             if (res->fragment == NULL)
2142*6777b538SAndroid Build Coastguard Worker                 goto done;
2143*6777b538SAndroid Build Coastguard Worker         }
2144*6777b538SAndroid Build Coastguard Worker 	goto step_7;
2145*6777b538SAndroid Build Coastguard Worker     }
2146*6777b538SAndroid Build Coastguard Worker 
2147*6777b538SAndroid Build Coastguard Worker     /*
2148*6777b538SAndroid Build Coastguard Worker      * 3) If the scheme component is defined, indicating that the reference
2149*6777b538SAndroid Build Coastguard Worker      *    starts with a scheme name, then the reference is interpreted as an
2150*6777b538SAndroid Build Coastguard Worker      *    absolute URI and we are done.  Otherwise, the reference URI's
2151*6777b538SAndroid Build Coastguard Worker      *    scheme is inherited from the base URI's scheme component.
2152*6777b538SAndroid Build Coastguard Worker      */
2153*6777b538SAndroid Build Coastguard Worker     if (ref->scheme != NULL) {
2154*6777b538SAndroid Build Coastguard Worker 	val = xmlSaveUri(ref);
2155*6777b538SAndroid Build Coastguard Worker         if (val != NULL)
2156*6777b538SAndroid Build Coastguard Worker             ret = 0;
2157*6777b538SAndroid Build Coastguard Worker 	goto done;
2158*6777b538SAndroid Build Coastguard Worker     }
2159*6777b538SAndroid Build Coastguard Worker     if (bas->scheme != NULL) {
2160*6777b538SAndroid Build Coastguard Worker 	res->scheme = xmlMemStrdup(bas->scheme);
2161*6777b538SAndroid Build Coastguard Worker         if (res->scheme == NULL)
2162*6777b538SAndroid Build Coastguard Worker             goto done;
2163*6777b538SAndroid Build Coastguard Worker     }
2164*6777b538SAndroid Build Coastguard Worker 
2165*6777b538SAndroid Build Coastguard Worker     if (ref->query_raw != NULL) {
2166*6777b538SAndroid Build Coastguard Worker 	res->query_raw = xmlMemStrdup(ref->query_raw);
2167*6777b538SAndroid Build Coastguard Worker         if (res->query_raw == NULL)
2168*6777b538SAndroid Build Coastguard Worker             goto done;
2169*6777b538SAndroid Build Coastguard Worker     } else if (ref->query != NULL) {
2170*6777b538SAndroid Build Coastguard Worker 	res->query = xmlMemStrdup(ref->query);
2171*6777b538SAndroid Build Coastguard Worker         if (res->query == NULL)
2172*6777b538SAndroid Build Coastguard Worker             goto done;
2173*6777b538SAndroid Build Coastguard Worker     }
2174*6777b538SAndroid Build Coastguard Worker     if (ref->fragment != NULL) {
2175*6777b538SAndroid Build Coastguard Worker 	res->fragment = xmlMemStrdup(ref->fragment);
2176*6777b538SAndroid Build Coastguard Worker         if (res->fragment == NULL)
2177*6777b538SAndroid Build Coastguard Worker             goto done;
2178*6777b538SAndroid Build Coastguard Worker     }
2179*6777b538SAndroid Build Coastguard Worker 
2180*6777b538SAndroid Build Coastguard Worker     /*
2181*6777b538SAndroid Build Coastguard Worker      * 4) If the authority component is defined, then the reference is a
2182*6777b538SAndroid Build Coastguard Worker      *    network-path and we skip to step 7.  Otherwise, the reference
2183*6777b538SAndroid Build Coastguard Worker      *    URI's authority is inherited from the base URI's authority
2184*6777b538SAndroid Build Coastguard Worker      *    component, which will also be undefined if the URI scheme does not
2185*6777b538SAndroid Build Coastguard Worker      *    use an authority component.
2186*6777b538SAndroid Build Coastguard Worker      */
2187*6777b538SAndroid Build Coastguard Worker     if ((ref->authority != NULL) || (ref->server != NULL) ||
2188*6777b538SAndroid Build Coastguard Worker          (ref->port != PORT_EMPTY)) {
2189*6777b538SAndroid Build Coastguard Worker 	if (ref->authority != NULL) {
2190*6777b538SAndroid Build Coastguard Worker 	    res->authority = xmlMemStrdup(ref->authority);
2191*6777b538SAndroid Build Coastguard Worker             if (res->authority == NULL)
2192*6777b538SAndroid Build Coastguard Worker                 goto done;
2193*6777b538SAndroid Build Coastguard Worker         } else {
2194*6777b538SAndroid Build Coastguard Worker             if (ref->server != NULL) {
2195*6777b538SAndroid Build Coastguard Worker                 res->server = xmlMemStrdup(ref->server);
2196*6777b538SAndroid Build Coastguard Worker                 if (res->server == NULL)
2197*6777b538SAndroid Build Coastguard Worker                     goto done;
2198*6777b538SAndroid Build Coastguard Worker             }
2199*6777b538SAndroid Build Coastguard Worker 	    if (ref->user != NULL) {
2200*6777b538SAndroid Build Coastguard Worker 		res->user = xmlMemStrdup(ref->user);
2201*6777b538SAndroid Build Coastguard Worker                 if (res->user == NULL)
2202*6777b538SAndroid Build Coastguard Worker                     goto done;
2203*6777b538SAndroid Build Coastguard Worker             }
2204*6777b538SAndroid Build Coastguard Worker             res->port = ref->port;
2205*6777b538SAndroid Build Coastguard Worker 	}
2206*6777b538SAndroid Build Coastguard Worker 	if (ref->path != NULL) {
2207*6777b538SAndroid Build Coastguard Worker 	    res->path = xmlMemStrdup(ref->path);
2208*6777b538SAndroid Build Coastguard Worker             if (res->path == NULL)
2209*6777b538SAndroid Build Coastguard Worker                 goto done;
2210*6777b538SAndroid Build Coastguard Worker         }
2211*6777b538SAndroid Build Coastguard Worker 	goto step_7;
2212*6777b538SAndroid Build Coastguard Worker     }
2213*6777b538SAndroid Build Coastguard Worker     if (bas->authority != NULL) {
2214*6777b538SAndroid Build Coastguard Worker 	res->authority = xmlMemStrdup(bas->authority);
2215*6777b538SAndroid Build Coastguard Worker         if (res->authority == NULL)
2216*6777b538SAndroid Build Coastguard Worker             goto done;
2217*6777b538SAndroid Build Coastguard Worker     } else if ((bas->server != NULL) || (bas->port != PORT_EMPTY)) {
2218*6777b538SAndroid Build Coastguard Worker 	if (bas->server != NULL) {
2219*6777b538SAndroid Build Coastguard Worker 	    res->server = xmlMemStrdup(bas->server);
2220*6777b538SAndroid Build Coastguard Worker             if (res->server == NULL)
2221*6777b538SAndroid Build Coastguard Worker                 goto done;
2222*6777b538SAndroid Build Coastguard Worker         }
2223*6777b538SAndroid Build Coastguard Worker 	if (bas->user != NULL) {
2224*6777b538SAndroid Build Coastguard Worker 	    res->user = xmlMemStrdup(bas->user);
2225*6777b538SAndroid Build Coastguard Worker             if (res->user == NULL)
2226*6777b538SAndroid Build Coastguard Worker                 goto done;
2227*6777b538SAndroid Build Coastguard Worker         }
2228*6777b538SAndroid Build Coastguard Worker 	res->port = bas->port;
2229*6777b538SAndroid Build Coastguard Worker     }
2230*6777b538SAndroid Build Coastguard Worker 
2231*6777b538SAndroid Build Coastguard Worker     /*
2232*6777b538SAndroid Build Coastguard Worker      * 5) If the path component begins with a slash character ("/"), then
2233*6777b538SAndroid Build Coastguard Worker      *    the reference is an absolute-path and we skip to step 7.
2234*6777b538SAndroid Build Coastguard Worker      */
2235*6777b538SAndroid Build Coastguard Worker     if ((ref->path != NULL) && (ref->path[0] == '/')) {
2236*6777b538SAndroid Build Coastguard Worker 	res->path = xmlMemStrdup(ref->path);
2237*6777b538SAndroid Build Coastguard Worker         if (res->path == NULL)
2238*6777b538SAndroid Build Coastguard Worker             goto done;
2239*6777b538SAndroid Build Coastguard Worker 	goto step_7;
2240*6777b538SAndroid Build Coastguard Worker     }
2241*6777b538SAndroid Build Coastguard Worker 
2242*6777b538SAndroid Build Coastguard Worker 
2243*6777b538SAndroid Build Coastguard Worker     /*
2244*6777b538SAndroid Build Coastguard Worker      * 6) If this step is reached, then we are resolving a relative-path
2245*6777b538SAndroid Build Coastguard Worker      *    reference.  The relative path needs to be merged with the base
2246*6777b538SAndroid Build Coastguard Worker      *    URI's path.  Although there are many ways to do this, we will
2247*6777b538SAndroid Build Coastguard Worker      *    describe a simple method using a separate string buffer.
2248*6777b538SAndroid Build Coastguard Worker      *
2249*6777b538SAndroid Build Coastguard Worker      * Allocate a buffer large enough for the result string.
2250*6777b538SAndroid Build Coastguard Worker      */
2251*6777b538SAndroid Build Coastguard Worker     len = 2; /* extra / and 0 */
2252*6777b538SAndroid Build Coastguard Worker     if (ref->path != NULL)
2253*6777b538SAndroid Build Coastguard Worker 	len += strlen(ref->path);
2254*6777b538SAndroid Build Coastguard Worker     if (bas->path != NULL)
2255*6777b538SAndroid Build Coastguard Worker 	len += strlen(bas->path);
2256*6777b538SAndroid Build Coastguard Worker     res->path = (char *) xmlMallocAtomic(len);
2257*6777b538SAndroid Build Coastguard Worker     if (res->path == NULL)
2258*6777b538SAndroid Build Coastguard Worker 	goto done;
2259*6777b538SAndroid Build Coastguard Worker     res->path[0] = 0;
2260*6777b538SAndroid Build Coastguard Worker 
2261*6777b538SAndroid Build Coastguard Worker     /*
2262*6777b538SAndroid Build Coastguard Worker      * a) All but the last segment of the base URI's path component is
2263*6777b538SAndroid Build Coastguard Worker      *    copied to the buffer.  In other words, any characters after the
2264*6777b538SAndroid Build Coastguard Worker      *    last (right-most) slash character, if any, are excluded.
2265*6777b538SAndroid Build Coastguard Worker      */
2266*6777b538SAndroid Build Coastguard Worker     cur = 0;
2267*6777b538SAndroid Build Coastguard Worker     out = 0;
2268*6777b538SAndroid Build Coastguard Worker     if (bas->path != NULL) {
2269*6777b538SAndroid Build Coastguard Worker 	while (bas->path[cur] != 0) {
2270*6777b538SAndroid Build Coastguard Worker 	    while ((bas->path[cur] != 0) && (bas->path[cur] != '/'))
2271*6777b538SAndroid Build Coastguard Worker 		cur++;
2272*6777b538SAndroid Build Coastguard Worker 	    if (bas->path[cur] == 0)
2273*6777b538SAndroid Build Coastguard Worker 		break;
2274*6777b538SAndroid Build Coastguard Worker 
2275*6777b538SAndroid Build Coastguard Worker 	    cur++;
2276*6777b538SAndroid Build Coastguard Worker 	    while (out < cur) {
2277*6777b538SAndroid Build Coastguard Worker 		res->path[out] = bas->path[out];
2278*6777b538SAndroid Build Coastguard Worker 		out++;
2279*6777b538SAndroid Build Coastguard Worker 	    }
2280*6777b538SAndroid Build Coastguard Worker 	}
2281*6777b538SAndroid Build Coastguard Worker     }
2282*6777b538SAndroid Build Coastguard Worker     res->path[out] = 0;
2283*6777b538SAndroid Build Coastguard Worker 
2284*6777b538SAndroid Build Coastguard Worker     /*
2285*6777b538SAndroid Build Coastguard Worker      * b) The reference's path component is appended to the buffer
2286*6777b538SAndroid Build Coastguard Worker      *    string.
2287*6777b538SAndroid Build Coastguard Worker      */
2288*6777b538SAndroid Build Coastguard Worker     if (ref->path != NULL && ref->path[0] != 0) {
2289*6777b538SAndroid Build Coastguard Worker 	indx = 0;
2290*6777b538SAndroid Build Coastguard Worker 	/*
2291*6777b538SAndroid Build Coastguard Worker 	 * Ensure the path includes a '/'
2292*6777b538SAndroid Build Coastguard Worker 	 */
2293*6777b538SAndroid Build Coastguard Worker 	if ((out == 0) && ((bas->server != NULL) || bas->port != PORT_EMPTY))
2294*6777b538SAndroid Build Coastguard Worker 	    res->path[out++] = '/';
2295*6777b538SAndroid Build Coastguard Worker 	while (ref->path[indx] != 0) {
2296*6777b538SAndroid Build Coastguard Worker 	    res->path[out++] = ref->path[indx++];
2297*6777b538SAndroid Build Coastguard Worker 	}
2298*6777b538SAndroid Build Coastguard Worker     }
2299*6777b538SAndroid Build Coastguard Worker     res->path[out] = 0;
2300*6777b538SAndroid Build Coastguard Worker 
2301*6777b538SAndroid Build Coastguard Worker     /*
2302*6777b538SAndroid Build Coastguard Worker      * Steps c) to h) are really path normalization steps
2303*6777b538SAndroid Build Coastguard Worker      */
2304*6777b538SAndroid Build Coastguard Worker     xmlNormalizeURIPath(res->path);
2305*6777b538SAndroid Build Coastguard Worker 
2306*6777b538SAndroid Build Coastguard Worker step_7:
2307*6777b538SAndroid Build Coastguard Worker 
2308*6777b538SAndroid Build Coastguard Worker     /*
2309*6777b538SAndroid Build Coastguard Worker      * 7) The resulting URI components, including any inherited from the
2310*6777b538SAndroid Build Coastguard Worker      *    base URI, are recombined to give the absolute form of the URI
2311*6777b538SAndroid Build Coastguard Worker      *    reference.
2312*6777b538SAndroid Build Coastguard Worker      */
2313*6777b538SAndroid Build Coastguard Worker     val = xmlSaveUri(res);
2314*6777b538SAndroid Build Coastguard Worker     if (val != NULL)
2315*6777b538SAndroid Build Coastguard Worker         ret = 0;
2316*6777b538SAndroid Build Coastguard Worker 
2317*6777b538SAndroid Build Coastguard Worker done:
2318*6777b538SAndroid Build Coastguard Worker     if (ref != NULL)
2319*6777b538SAndroid Build Coastguard Worker 	xmlFreeURI(ref);
2320*6777b538SAndroid Build Coastguard Worker     if (bas != NULL)
2321*6777b538SAndroid Build Coastguard Worker 	xmlFreeURI(bas);
2322*6777b538SAndroid Build Coastguard Worker     if (res != NULL)
2323*6777b538SAndroid Build Coastguard Worker 	xmlFreeURI(res);
2324*6777b538SAndroid Build Coastguard Worker     *valPtr = val;
2325*6777b538SAndroid Build Coastguard Worker     return(ret);
2326*6777b538SAndroid Build Coastguard Worker }
2327*6777b538SAndroid Build Coastguard Worker 
2328*6777b538SAndroid Build Coastguard Worker /**
2329*6777b538SAndroid Build Coastguard Worker  * xmlBuildURI:
2330*6777b538SAndroid Build Coastguard Worker  * @URI:  the URI instance found in the document
2331*6777b538SAndroid Build Coastguard Worker  * @base:  the base value
2332*6777b538SAndroid Build Coastguard Worker  *
2333*6777b538SAndroid Build Coastguard Worker  * Computes he final URI of the reference done by checking that
2334*6777b538SAndroid Build Coastguard Worker  * the given URI is valid, and building the final URI using the
2335*6777b538SAndroid Build Coastguard Worker  * base URI. This is processed according to section 5.2 of the
2336*6777b538SAndroid Build Coastguard Worker  * RFC 2396
2337*6777b538SAndroid Build Coastguard Worker  *
2338*6777b538SAndroid Build Coastguard Worker  * 5.2. Resolving Relative References to Absolute Form
2339*6777b538SAndroid Build Coastguard Worker  *
2340*6777b538SAndroid Build Coastguard Worker  * Returns a new URI string (to be freed by the caller) or NULL in case
2341*6777b538SAndroid Build Coastguard Worker  *         of error.
2342*6777b538SAndroid Build Coastguard Worker  */
2343*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlBuildURI(const xmlChar * URI,const xmlChar * base)2344*6777b538SAndroid Build Coastguard Worker xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
2345*6777b538SAndroid Build Coastguard Worker     xmlChar *out;
2346*6777b538SAndroid Build Coastguard Worker 
2347*6777b538SAndroid Build Coastguard Worker     xmlBuildURISafe(URI, base, &out);
2348*6777b538SAndroid Build Coastguard Worker     return(out);
2349*6777b538SAndroid Build Coastguard Worker }
2350*6777b538SAndroid Build Coastguard Worker 
2351*6777b538SAndroid Build Coastguard Worker /**
2352*6777b538SAndroid Build Coastguard Worker  * xmlBuildRelativeURISafe:
2353*6777b538SAndroid Build Coastguard Worker  * @URI:  the URI reference under consideration
2354*6777b538SAndroid Build Coastguard Worker  * @base:  the base value
2355*6777b538SAndroid Build Coastguard Worker  * @valPtr:  pointer to result URI
2356*6777b538SAndroid Build Coastguard Worker  *
2357*6777b538SAndroid Build Coastguard Worker  * Expresses the URI of the reference in terms relative to the
2358*6777b538SAndroid Build Coastguard Worker  * base.  Some examples of this operation include:
2359*6777b538SAndroid Build Coastguard Worker  *     base = "http://site1.com/docs/book1.html"
2360*6777b538SAndroid Build Coastguard Worker  *        URI input                        URI returned
2361*6777b538SAndroid Build Coastguard Worker  *     docs/pic1.gif                    pic1.gif
2362*6777b538SAndroid Build Coastguard Worker  *     docs/img/pic1.gif                img/pic1.gif
2363*6777b538SAndroid Build Coastguard Worker  *     img/pic1.gif                     ../img/pic1.gif
2364*6777b538SAndroid Build Coastguard Worker  *     http://site1.com/docs/pic1.gif   pic1.gif
2365*6777b538SAndroid Build Coastguard Worker  *     http://site2.com/docs/pic1.gif   http://site2.com/docs/pic1.gif
2366*6777b538SAndroid Build Coastguard Worker  *
2367*6777b538SAndroid Build Coastguard Worker  *     base = "docs/book1.html"
2368*6777b538SAndroid Build Coastguard Worker  *        URI input                        URI returned
2369*6777b538SAndroid Build Coastguard Worker  *     docs/pic1.gif                    pic1.gif
2370*6777b538SAndroid Build Coastguard Worker  *     docs/img/pic1.gif                img/pic1.gif
2371*6777b538SAndroid Build Coastguard Worker  *     img/pic1.gif                     ../img/pic1.gif
2372*6777b538SAndroid Build Coastguard Worker  *     http://site1.com/docs/pic1.gif   http://site1.com/docs/pic1.gif
2373*6777b538SAndroid Build Coastguard Worker  *
2374*6777b538SAndroid Build Coastguard Worker  *
2375*6777b538SAndroid Build Coastguard Worker  * Note: if the URI reference is really weird or complicated, it may be
2376*6777b538SAndroid Build Coastguard Worker  *       worthwhile to first convert it into a "nice" one by calling
2377*6777b538SAndroid Build Coastguard Worker  *       xmlBuildURI (using 'base') before calling this routine,
2378*6777b538SAndroid Build Coastguard Worker  *       since this routine (for reasonable efficiency) assumes URI has
2379*6777b538SAndroid Build Coastguard Worker  *       already been through some validation.
2380*6777b538SAndroid Build Coastguard Worker  *
2381*6777b538SAndroid Build Coastguard Worker  * Returns 0 on success, -1 if a memory allocation failed or an error
2382*6777b538SAndroid Build Coastguard Worker  * code if URI or base are invalid.
2383*6777b538SAndroid Build Coastguard Worker  */
2384*6777b538SAndroid Build Coastguard Worker int
xmlBuildRelativeURISafe(const xmlChar * URI,const xmlChar * base,xmlChar ** valPtr)2385*6777b538SAndroid Build Coastguard Worker xmlBuildRelativeURISafe(const xmlChar * URI, const xmlChar * base,
2386*6777b538SAndroid Build Coastguard Worker                         xmlChar **valPtr)
2387*6777b538SAndroid Build Coastguard Worker {
2388*6777b538SAndroid Build Coastguard Worker     xmlChar *val = NULL;
2389*6777b538SAndroid Build Coastguard Worker     int ret = 0;
2390*6777b538SAndroid Build Coastguard Worker     int ix;
2391*6777b538SAndroid Build Coastguard Worker     int nbslash = 0;
2392*6777b538SAndroid Build Coastguard Worker     int len;
2393*6777b538SAndroid Build Coastguard Worker     xmlURIPtr ref = NULL;
2394*6777b538SAndroid Build Coastguard Worker     xmlURIPtr bas = NULL;
2395*6777b538SAndroid Build Coastguard Worker     xmlChar *bptr, *uptr, *vptr;
2396*6777b538SAndroid Build Coastguard Worker     int remove_path = 0;
2397*6777b538SAndroid Build Coastguard Worker 
2398*6777b538SAndroid Build Coastguard Worker     if (valPtr == NULL)
2399*6777b538SAndroid Build Coastguard Worker         return(1);
2400*6777b538SAndroid Build Coastguard Worker     *valPtr = NULL;
2401*6777b538SAndroid Build Coastguard Worker     if ((URI == NULL) || (*URI == 0))
2402*6777b538SAndroid Build Coastguard Worker 	return(1);
2403*6777b538SAndroid Build Coastguard Worker 
2404*6777b538SAndroid Build Coastguard Worker     /*
2405*6777b538SAndroid Build Coastguard Worker      * First parse URI into a standard form
2406*6777b538SAndroid Build Coastguard Worker      */
2407*6777b538SAndroid Build Coastguard Worker     ref = xmlCreateURI ();
2408*6777b538SAndroid Build Coastguard Worker     if (ref == NULL) {
2409*6777b538SAndroid Build Coastguard Worker         ret = -1;
2410*6777b538SAndroid Build Coastguard Worker 	goto done;
2411*6777b538SAndroid Build Coastguard Worker     }
2412*6777b538SAndroid Build Coastguard Worker     /* If URI not already in "relative" form */
2413*6777b538SAndroid Build Coastguard Worker     if (URI[0] != '.') {
2414*6777b538SAndroid Build Coastguard Worker 	ret = xmlParseURIReference (ref, (const char *) URI);
2415*6777b538SAndroid Build Coastguard Worker 	if (ret != 0)
2416*6777b538SAndroid Build Coastguard Worker 	    goto done;		/* Error in URI, return NULL */
2417*6777b538SAndroid Build Coastguard Worker     } else {
2418*6777b538SAndroid Build Coastguard Worker 	ref->path = (char *)xmlStrdup(URI);
2419*6777b538SAndroid Build Coastguard Worker         if (ref->path == NULL) {
2420*6777b538SAndroid Build Coastguard Worker             ret = -1;
2421*6777b538SAndroid Build Coastguard Worker             goto done;
2422*6777b538SAndroid Build Coastguard Worker         }
2423*6777b538SAndroid Build Coastguard Worker     }
2424*6777b538SAndroid Build Coastguard Worker 
2425*6777b538SAndroid Build Coastguard Worker     /*
2426*6777b538SAndroid Build Coastguard Worker      * Next parse base into the same standard form
2427*6777b538SAndroid Build Coastguard Worker      */
2428*6777b538SAndroid Build Coastguard Worker     if ((base == NULL) || (*base == 0)) {
2429*6777b538SAndroid Build Coastguard Worker 	val = xmlStrdup (URI);
2430*6777b538SAndroid Build Coastguard Worker         if (val == NULL)
2431*6777b538SAndroid Build Coastguard Worker             ret = -1;
2432*6777b538SAndroid Build Coastguard Worker 	goto done;
2433*6777b538SAndroid Build Coastguard Worker     }
2434*6777b538SAndroid Build Coastguard Worker     bas = xmlCreateURI ();
2435*6777b538SAndroid Build Coastguard Worker     if (bas == NULL) {
2436*6777b538SAndroid Build Coastguard Worker         ret = -1;
2437*6777b538SAndroid Build Coastguard Worker 	goto done;
2438*6777b538SAndroid Build Coastguard Worker     }
2439*6777b538SAndroid Build Coastguard Worker     if (base[0] != '.') {
2440*6777b538SAndroid Build Coastguard Worker 	ret = xmlParseURIReference (bas, (const char *) base);
2441*6777b538SAndroid Build Coastguard Worker 	if (ret != 0)
2442*6777b538SAndroid Build Coastguard Worker 	    goto done;		/* Error in base, return NULL */
2443*6777b538SAndroid Build Coastguard Worker     } else {
2444*6777b538SAndroid Build Coastguard Worker 	bas->path = (char *)xmlStrdup(base);
2445*6777b538SAndroid Build Coastguard Worker         if (bas->path == NULL) {
2446*6777b538SAndroid Build Coastguard Worker             ret = -1;
2447*6777b538SAndroid Build Coastguard Worker             goto done;
2448*6777b538SAndroid Build Coastguard Worker         }
2449*6777b538SAndroid Build Coastguard Worker     }
2450*6777b538SAndroid Build Coastguard Worker 
2451*6777b538SAndroid Build Coastguard Worker     /*
2452*6777b538SAndroid Build Coastguard Worker      * If the scheme / server on the URI differs from the base,
2453*6777b538SAndroid Build Coastguard Worker      * just return the URI
2454*6777b538SAndroid Build Coastguard Worker      */
2455*6777b538SAndroid Build Coastguard Worker     if ((ref->scheme != NULL) &&
2456*6777b538SAndroid Build Coastguard Worker 	((bas->scheme == NULL) ||
2457*6777b538SAndroid Build Coastguard Worker 	 (xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) ||
2458*6777b538SAndroid Build Coastguard Worker 	 (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)) ||
2459*6777b538SAndroid Build Coastguard Worker          (bas->port != ref->port))) {
2460*6777b538SAndroid Build Coastguard Worker 	val = xmlStrdup (URI);
2461*6777b538SAndroid Build Coastguard Worker         if (val == NULL)
2462*6777b538SAndroid Build Coastguard Worker             ret = -1;
2463*6777b538SAndroid Build Coastguard Worker 	goto done;
2464*6777b538SAndroid Build Coastguard Worker     }
2465*6777b538SAndroid Build Coastguard Worker     if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) {
2466*6777b538SAndroid Build Coastguard Worker 	val = xmlStrdup(BAD_CAST "");
2467*6777b538SAndroid Build Coastguard Worker         if (val == NULL)
2468*6777b538SAndroid Build Coastguard Worker             ret = -1;
2469*6777b538SAndroid Build Coastguard Worker 	goto done;
2470*6777b538SAndroid Build Coastguard Worker     }
2471*6777b538SAndroid Build Coastguard Worker     if (bas->path == NULL) {
2472*6777b538SAndroid Build Coastguard Worker 	val = xmlStrdup((xmlChar *)ref->path);
2473*6777b538SAndroid Build Coastguard Worker         if (val == NULL)
2474*6777b538SAndroid Build Coastguard Worker             ret = -1;
2475*6777b538SAndroid Build Coastguard Worker 	goto done;
2476*6777b538SAndroid Build Coastguard Worker     }
2477*6777b538SAndroid Build Coastguard Worker     if (ref->path == NULL) {
2478*6777b538SAndroid Build Coastguard Worker         ref->path = (char *) "/";
2479*6777b538SAndroid Build Coastguard Worker 	remove_path = 1;
2480*6777b538SAndroid Build Coastguard Worker     }
2481*6777b538SAndroid Build Coastguard Worker 
2482*6777b538SAndroid Build Coastguard Worker     /*
2483*6777b538SAndroid Build Coastguard Worker      * At this point (at last!) we can compare the two paths
2484*6777b538SAndroid Build Coastguard Worker      *
2485*6777b538SAndroid Build Coastguard Worker      * First we take care of the special case where either of the
2486*6777b538SAndroid Build Coastguard Worker      * two path components may be missing (bug 316224)
2487*6777b538SAndroid Build Coastguard Worker      */
2488*6777b538SAndroid Build Coastguard Worker     bptr = (xmlChar *)bas->path;
2489*6777b538SAndroid Build Coastguard Worker     {
2490*6777b538SAndroid Build Coastguard Worker         xmlChar *rptr = (xmlChar *) ref->path;
2491*6777b538SAndroid Build Coastguard Worker         int pos = 0;
2492*6777b538SAndroid Build Coastguard Worker 
2493*6777b538SAndroid Build Coastguard Worker         /*
2494*6777b538SAndroid Build Coastguard Worker          * Next we compare the two strings and find where they first differ
2495*6777b538SAndroid Build Coastguard Worker          */
2496*6777b538SAndroid Build Coastguard Worker 	if ((*rptr == '.') && (rptr[1] == '/'))
2497*6777b538SAndroid Build Coastguard Worker             rptr += 2;
2498*6777b538SAndroid Build Coastguard Worker 	if ((*bptr == '.') && (bptr[1] == '/'))
2499*6777b538SAndroid Build Coastguard Worker             bptr += 2;
2500*6777b538SAndroid Build Coastguard Worker 	else if ((*bptr == '/') && (*rptr != '/'))
2501*6777b538SAndroid Build Coastguard Worker 	    bptr++;
2502*6777b538SAndroid Build Coastguard Worker 	while ((bptr[pos] == rptr[pos]) && (bptr[pos] != 0))
2503*6777b538SAndroid Build Coastguard Worker 	    pos++;
2504*6777b538SAndroid Build Coastguard Worker 
2505*6777b538SAndroid Build Coastguard Worker 	if (bptr[pos] == rptr[pos]) {
2506*6777b538SAndroid Build Coastguard Worker 	    val = xmlStrdup(BAD_CAST "");
2507*6777b538SAndroid Build Coastguard Worker             if (val == NULL)
2508*6777b538SAndroid Build Coastguard Worker                 ret = -1;
2509*6777b538SAndroid Build Coastguard Worker 	    goto done;		/* (I can't imagine why anyone would do this) */
2510*6777b538SAndroid Build Coastguard Worker 	}
2511*6777b538SAndroid Build Coastguard Worker 
2512*6777b538SAndroid Build Coastguard Worker 	/*
2513*6777b538SAndroid Build Coastguard Worker 	 * In URI, "back up" to the last '/' encountered.  This will be the
2514*6777b538SAndroid Build Coastguard Worker 	 * beginning of the "unique" suffix of URI
2515*6777b538SAndroid Build Coastguard Worker 	 */
2516*6777b538SAndroid Build Coastguard Worker 	ix = pos;
2517*6777b538SAndroid Build Coastguard Worker 	for (; ix > 0; ix--) {
2518*6777b538SAndroid Build Coastguard Worker 	    if (rptr[ix - 1] == '/')
2519*6777b538SAndroid Build Coastguard Worker 		break;
2520*6777b538SAndroid Build Coastguard Worker 	}
2521*6777b538SAndroid Build Coastguard Worker 	uptr = (xmlChar *)&rptr[ix];
2522*6777b538SAndroid Build Coastguard Worker 
2523*6777b538SAndroid Build Coastguard Worker 	/*
2524*6777b538SAndroid Build Coastguard Worker 	 * In base, count the number of '/' from the differing point
2525*6777b538SAndroid Build Coastguard Worker 	 */
2526*6777b538SAndroid Build Coastguard Worker 	for (; bptr[ix] != 0; ix++) {
2527*6777b538SAndroid Build Coastguard Worker 	    if (bptr[ix] == '/')
2528*6777b538SAndroid Build Coastguard Worker 		nbslash++;
2529*6777b538SAndroid Build Coastguard Worker 	}
2530*6777b538SAndroid Build Coastguard Worker 
2531*6777b538SAndroid Build Coastguard Worker 	/*
2532*6777b538SAndroid Build Coastguard Worker 	 * e.g: URI="foo/" base="foo/bar" -> "./"
2533*6777b538SAndroid Build Coastguard Worker 	 */
2534*6777b538SAndroid Build Coastguard Worker 	if (nbslash == 0 && !uptr[0]) {
2535*6777b538SAndroid Build Coastguard Worker 	    val = xmlStrdup(BAD_CAST "./");
2536*6777b538SAndroid Build Coastguard Worker             if (val == NULL)
2537*6777b538SAndroid Build Coastguard Worker                 ret = -1;
2538*6777b538SAndroid Build Coastguard Worker 	    goto done;
2539*6777b538SAndroid Build Coastguard Worker 	}
2540*6777b538SAndroid Build Coastguard Worker 
2541*6777b538SAndroid Build Coastguard Worker 	len = xmlStrlen (uptr) + 1;
2542*6777b538SAndroid Build Coastguard Worker     }
2543*6777b538SAndroid Build Coastguard Worker 
2544*6777b538SAndroid Build Coastguard Worker     if (nbslash == 0) {
2545*6777b538SAndroid Build Coastguard Worker 	if (uptr != NULL) {
2546*6777b538SAndroid Build Coastguard Worker 	    /* exception characters from xmlSaveUri */
2547*6777b538SAndroid Build Coastguard Worker 	    val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,");
2548*6777b538SAndroid Build Coastguard Worker             if (val == NULL)
2549*6777b538SAndroid Build Coastguard Worker                 ret = -1;
2550*6777b538SAndroid Build Coastguard Worker         }
2551*6777b538SAndroid Build Coastguard Worker 	goto done;
2552*6777b538SAndroid Build Coastguard Worker     }
2553*6777b538SAndroid Build Coastguard Worker 
2554*6777b538SAndroid Build Coastguard Worker     /*
2555*6777b538SAndroid Build Coastguard Worker      * Allocate just enough space for the returned string -
2556*6777b538SAndroid Build Coastguard Worker      * length of the remainder of the URI, plus enough space
2557*6777b538SAndroid Build Coastguard Worker      * for the "../" groups, plus one for the terminator
2558*6777b538SAndroid Build Coastguard Worker      */
2559*6777b538SAndroid Build Coastguard Worker     val = (xmlChar *) xmlMalloc (len + 3 * nbslash);
2560*6777b538SAndroid Build Coastguard Worker     if (val == NULL) {
2561*6777b538SAndroid Build Coastguard Worker         ret = -1;
2562*6777b538SAndroid Build Coastguard Worker 	goto done;
2563*6777b538SAndroid Build Coastguard Worker     }
2564*6777b538SAndroid Build Coastguard Worker     vptr = val;
2565*6777b538SAndroid Build Coastguard Worker     /*
2566*6777b538SAndroid Build Coastguard Worker      * Put in as many "../" as needed
2567*6777b538SAndroid Build Coastguard Worker      */
2568*6777b538SAndroid Build Coastguard Worker     for (; nbslash>0; nbslash--) {
2569*6777b538SAndroid Build Coastguard Worker 	*vptr++ = '.';
2570*6777b538SAndroid Build Coastguard Worker 	*vptr++ = '.';
2571*6777b538SAndroid Build Coastguard Worker 	*vptr++ = '/';
2572*6777b538SAndroid Build Coastguard Worker     }
2573*6777b538SAndroid Build Coastguard Worker     /*
2574*6777b538SAndroid Build Coastguard Worker      * Finish up with the end of the URI
2575*6777b538SAndroid Build Coastguard Worker      */
2576*6777b538SAndroid Build Coastguard Worker     if (uptr != NULL) {
2577*6777b538SAndroid Build Coastguard Worker         if ((vptr > val) && (len > 0) &&
2578*6777b538SAndroid Build Coastguard Worker 	    (uptr[0] == '/') && (vptr[-1] == '/')) {
2579*6777b538SAndroid Build Coastguard Worker 	    memcpy (vptr, uptr + 1, len - 1);
2580*6777b538SAndroid Build Coastguard Worker 	    vptr[len - 2] = 0;
2581*6777b538SAndroid Build Coastguard Worker 	} else {
2582*6777b538SAndroid Build Coastguard Worker 	    memcpy (vptr, uptr, len);
2583*6777b538SAndroid Build Coastguard Worker 	    vptr[len - 1] = 0;
2584*6777b538SAndroid Build Coastguard Worker 	}
2585*6777b538SAndroid Build Coastguard Worker     } else {
2586*6777b538SAndroid Build Coastguard Worker 	vptr[len - 1] = 0;
2587*6777b538SAndroid Build Coastguard Worker     }
2588*6777b538SAndroid Build Coastguard Worker 
2589*6777b538SAndroid Build Coastguard Worker     /* escape the freshly-built path */
2590*6777b538SAndroid Build Coastguard Worker     vptr = val;
2591*6777b538SAndroid Build Coastguard Worker 	/* exception characters from xmlSaveUri */
2592*6777b538SAndroid Build Coastguard Worker     val = xmlURIEscapeStr(vptr, BAD_CAST "/;&=+$,");
2593*6777b538SAndroid Build Coastguard Worker     if (val == NULL)
2594*6777b538SAndroid Build Coastguard Worker         ret = -1;
2595*6777b538SAndroid Build Coastguard Worker     else
2596*6777b538SAndroid Build Coastguard Worker         ret = 0;
2597*6777b538SAndroid Build Coastguard Worker     xmlFree(vptr);
2598*6777b538SAndroid Build Coastguard Worker 
2599*6777b538SAndroid Build Coastguard Worker done:
2600*6777b538SAndroid Build Coastguard Worker     /*
2601*6777b538SAndroid Build Coastguard Worker      * Free the working variables
2602*6777b538SAndroid Build Coastguard Worker      */
2603*6777b538SAndroid Build Coastguard Worker     if (remove_path != 0)
2604*6777b538SAndroid Build Coastguard Worker         ref->path = NULL;
2605*6777b538SAndroid Build Coastguard Worker     if (ref != NULL)
2606*6777b538SAndroid Build Coastguard Worker 	xmlFreeURI (ref);
2607*6777b538SAndroid Build Coastguard Worker     if (bas != NULL)
2608*6777b538SAndroid Build Coastguard Worker 	xmlFreeURI (bas);
2609*6777b538SAndroid Build Coastguard Worker     if (ret != 0) {
2610*6777b538SAndroid Build Coastguard Worker         xmlFree(val);
2611*6777b538SAndroid Build Coastguard Worker         val = NULL;
2612*6777b538SAndroid Build Coastguard Worker     }
2613*6777b538SAndroid Build Coastguard Worker 
2614*6777b538SAndroid Build Coastguard Worker     *valPtr = val;
2615*6777b538SAndroid Build Coastguard Worker     return(ret);
2616*6777b538SAndroid Build Coastguard Worker }
2617*6777b538SAndroid Build Coastguard Worker 
2618*6777b538SAndroid Build Coastguard Worker /*
2619*6777b538SAndroid Build Coastguard Worker  * xmlBuildRelativeURI:
2620*6777b538SAndroid Build Coastguard Worker  * @URI:  the URI reference under consideration
2621*6777b538SAndroid Build Coastguard Worker  * @base:  the base value
2622*6777b538SAndroid Build Coastguard Worker  *
2623*6777b538SAndroid Build Coastguard Worker  * See xmlBuildRelativeURISafe.
2624*6777b538SAndroid Build Coastguard Worker  *
2625*6777b538SAndroid Build Coastguard Worker  * Returns a new URI string (to be freed by the caller) or NULL in case
2626*6777b538SAndroid Build Coastguard Worker  * error.
2627*6777b538SAndroid Build Coastguard Worker  */
2628*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlBuildRelativeURI(const xmlChar * URI,const xmlChar * base)2629*6777b538SAndroid Build Coastguard Worker xmlBuildRelativeURI(const xmlChar * URI, const xmlChar * base)
2630*6777b538SAndroid Build Coastguard Worker {
2631*6777b538SAndroid Build Coastguard Worker     xmlChar *val;
2632*6777b538SAndroid Build Coastguard Worker 
2633*6777b538SAndroid Build Coastguard Worker     xmlBuildRelativeURISafe(URI, base, &val);
2634*6777b538SAndroid Build Coastguard Worker     return(val);
2635*6777b538SAndroid Build Coastguard Worker }
2636*6777b538SAndroid Build Coastguard Worker 
2637*6777b538SAndroid Build Coastguard Worker /**
2638*6777b538SAndroid Build Coastguard Worker  * xmlCanonicPath:
2639*6777b538SAndroid Build Coastguard Worker  * @path:  the resource locator in a filesystem notation
2640*6777b538SAndroid Build Coastguard Worker  *
2641*6777b538SAndroid Build Coastguard Worker  * Prepares a path.
2642*6777b538SAndroid Build Coastguard Worker  *
2643*6777b538SAndroid Build Coastguard Worker  * If the path contains the substring "://", it is considered a
2644*6777b538SAndroid Build Coastguard Worker  * Legacy Extended IRI. Characters which aren't allowed in URIs are
2645*6777b538SAndroid Build Coastguard Worker  * escaped.
2646*6777b538SAndroid Build Coastguard Worker  *
2647*6777b538SAndroid Build Coastguard Worker  * Otherwise, the path is considered a filesystem path which is
2648*6777b538SAndroid Build Coastguard Worker  * copied without modification.
2649*6777b538SAndroid Build Coastguard Worker  *
2650*6777b538SAndroid Build Coastguard Worker  * The caller is responsible for freeing the memory occupied
2651*6777b538SAndroid Build Coastguard Worker  * by the returned string. If there is insufficient memory available, or the
2652*6777b538SAndroid Build Coastguard Worker  * argument is NULL, the function returns NULL.
2653*6777b538SAndroid Build Coastguard Worker  */
2654*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlCanonicPath(const xmlChar * path)2655*6777b538SAndroid Build Coastguard Worker xmlCanonicPath(const xmlChar *path)
2656*6777b538SAndroid Build Coastguard Worker {
2657*6777b538SAndroid Build Coastguard Worker     xmlChar *ret;
2658*6777b538SAndroid Build Coastguard Worker 
2659*6777b538SAndroid Build Coastguard Worker     if (path == NULL)
2660*6777b538SAndroid Build Coastguard Worker 	return(NULL);
2661*6777b538SAndroid Build Coastguard Worker 
2662*6777b538SAndroid Build Coastguard Worker     /* Check if this is an "absolute uri" */
2663*6777b538SAndroid Build Coastguard Worker     if (xmlStrstr(path, BAD_CAST "://") != NULL) {
2664*6777b538SAndroid Build Coastguard Worker 	/*
2665*6777b538SAndroid Build Coastguard Worker          * Escape all characters except reserved, unreserved and the
2666*6777b538SAndroid Build Coastguard Worker          * percent sign.
2667*6777b538SAndroid Build Coastguard Worker          *
2668*6777b538SAndroid Build Coastguard Worker          * xmlURIEscapeStr already keeps unreserved characters, so we
2669*6777b538SAndroid Build Coastguard Worker          * pass gen-delims, sub-delims and "%" to ignore.
2670*6777b538SAndroid Build Coastguard Worker          */
2671*6777b538SAndroid Build Coastguard Worker         ret = xmlURIEscapeStr(path, BAD_CAST ":/?#[]@!$&()*+,;='%");
2672*6777b538SAndroid Build Coastguard Worker     } else {
2673*6777b538SAndroid Build Coastguard Worker         ret = xmlStrdup((const xmlChar *) path);
2674*6777b538SAndroid Build Coastguard Worker     }
2675*6777b538SAndroid Build Coastguard Worker 
2676*6777b538SAndroid Build Coastguard Worker     return(ret);
2677*6777b538SAndroid Build Coastguard Worker }
2678*6777b538SAndroid Build Coastguard Worker 
2679*6777b538SAndroid Build Coastguard Worker /**
2680*6777b538SAndroid Build Coastguard Worker  * xmlPathToURI:
2681*6777b538SAndroid Build Coastguard Worker  * @path:  the resource locator in a filesystem notation
2682*6777b538SAndroid Build Coastguard Worker  *
2683*6777b538SAndroid Build Coastguard Worker  * Constructs an URI expressing the existing path
2684*6777b538SAndroid Build Coastguard Worker  *
2685*6777b538SAndroid Build Coastguard Worker  * Returns a new URI, or a duplicate of the path parameter if the
2686*6777b538SAndroid Build Coastguard Worker  * construction fails. The caller is responsible for freeing the memory
2687*6777b538SAndroid Build Coastguard Worker  * occupied by the returned string. If there is insufficient memory available,
2688*6777b538SAndroid Build Coastguard Worker  * or the argument is NULL, the function returns NULL.
2689*6777b538SAndroid Build Coastguard Worker  */
2690*6777b538SAndroid Build Coastguard Worker xmlChar *
xmlPathToURI(const xmlChar * path)2691*6777b538SAndroid Build Coastguard Worker xmlPathToURI(const xmlChar *path)
2692*6777b538SAndroid Build Coastguard Worker {
2693*6777b538SAndroid Build Coastguard Worker     return(xmlCanonicPath(path));
2694*6777b538SAndroid Build Coastguard Worker }
2695