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