OLD | NEW |
1 /** | 1 /** |
2 * uri.c: set of generic URI related routines | 2 * uri.c: set of generic URI related routines |
3 * | 3 * |
4 * Reference: RFCs 2396, 2732 and 2373 | 4 * Reference: RFCs 3986, 2732 and 2373 |
5 * | 5 * |
6 * See Copyright for the status of this software. | 6 * See Copyright for the status of this software. |
7 * | 7 * |
8 * daniel@veillard.com | 8 * daniel@veillard.com |
9 */ | 9 */ |
10 | 10 |
11 #define IN_LIBXML | 11 #define IN_LIBXML |
12 #include "libxml.h" | 12 #include "libxml.h" |
13 | 13 |
14 #include <string.h> | 14 #include <string.h> |
15 | 15 |
16 #include <libxml/xmlmemory.h> | 16 #include <libxml/xmlmemory.h> |
17 #include <libxml/uri.h> | 17 #include <libxml/uri.h> |
18 #include <libxml/globals.h> | 18 #include <libxml/globals.h> |
19 #include <libxml/xmlerror.h> | 19 #include <libxml/xmlerror.h> |
20 | 20 |
21 /************************************************************************ | 21 static void xmlCleanURI(xmlURIPtr uri); |
22 *» » » » » » » » » * | |
23 *» » Macros to differentiate various character type» » * | |
24 *» » » directly extracted from RFC 2396» » * | |
25 *» » » » » » » » » * | |
26 ************************************************************************/ | |
27 | 22 |
28 /* | 23 /* |
| 24 * Old rule from 2396 used in legacy handling code |
29 * alpha = lowalpha | upalpha | 25 * alpha = lowalpha | upalpha |
30 */ | 26 */ |
31 #define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x)) | 27 #define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x)) |
32 | 28 |
33 | 29 |
34 /* | 30 /* |
35 * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | | 31 * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | |
36 * "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | | 32 * "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" | |
37 * "u" | "v" | "w" | "x" | "y" | "z" | 33 * "u" | "v" | "w" | "x" | "y" | "z" |
38 */ | 34 */ |
(...skipping 15 matching lines...) Expand all Loading... |
54 */ | 50 */ |
55 #define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9')) | 51 #define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9')) |
56 | 52 |
57 /* | 53 /* |
58 * alphanum = alpha | digit | 54 * alphanum = alpha | digit |
59 */ | 55 */ |
60 | 56 |
61 #define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x)) | 57 #define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x)) |
62 | 58 |
63 /* | 59 /* |
64 * hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | | |
65 * "a" | "b" | "c" | "d" | "e" | "f" | |
66 */ | |
67 | |
68 #define IS_HEX(x) ((IS_DIGIT(x)) || (((x) >= 'a') && ((x) <= 'f')) || \ | |
69 (((x) >= 'A') && ((x) <= 'F'))) | |
70 | |
71 /* | |
72 * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" | 60 * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" |
73 */ | 61 */ |
74 | 62 |
75 #define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') ||» \ | 63 #define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') || \ |
76 ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') ||» \ | 64 ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') || \ |
77 ((x) == '(') || ((x) == ')')) | 65 ((x) == '(') || ((x) == ')')) |
78 | 66 |
| 67 /* |
| 68 * unwise = "{" | "}" | "|" | "\" | "^" | "`" |
| 69 */ |
79 | 70 |
| 71 #define IS_UNWISE(p) \ |
| 72 (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \ |
| 73 ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \ |
| 74 ((*(p) == ']')) || ((*(p) == '`'))) |
80 /* | 75 /* |
81 * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," | | 76 * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," | |
82 * » "[" | "]" | 77 * "[" | "]" |
83 */ | 78 */ |
84 | 79 |
85 #define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') ||»\ | 80 #define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \ |
86 ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') ||»\ | 81 ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \ |
87 » ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \ | 82 ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \ |
88 » ((x) == ']')) | 83 ((x) == ']')) |
89 | 84 |
90 /* | 85 /* |
91 * unreserved = alphanum | mark | 86 * unreserved = alphanum | mark |
92 */ | 87 */ |
93 | 88 |
94 #define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x)) | 89 #define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x)) |
95 | 90 |
96 /* | 91 /* |
97 * escaped = "%" hex hex | |
98 */ | |
99 | |
100 #define IS_ESCAPED(p) ((*(p) == '%') && (IS_HEX((p)[1])) && \ | |
101 (IS_HEX((p)[2]))) | |
102 | |
103 /* | |
104 * uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | | |
105 * "&" | "=" | "+" | "$" | "," | |
106 */ | |
107 #define IS_URIC_NO_SLASH(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) ||\ | |
108 ((*(p) == ';')) || ((*(p) == '?')) || ((*(p) == ':')) ||\ | |
109 ((*(p) == '@')) || ((*(p) == '&')) || ((*(p) == '=')) ||\ | |
110 ((*(p) == '+')) || ((*(p) == '$')) || ((*(p) == ','))) | |
111 | |
112 /* | |
113 * pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | "," | |
114 */ | |
115 #define IS_PCHAR(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ | |
116 ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||\ | |
117 ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||\ | |
118 ((*(p) == ','))) | |
119 | |
120 /* | |
121 * rel_segment = 1*( unreserved | escaped | | |
122 * ";" | "@" | "&" | "=" | "+" | "$" | "," ) | |
123 */ | |
124 | |
125 #define IS_SEGMENT(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ | |
126 ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || \ | |
127 ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \ | |
128 ((*(p) == ','))) | |
129 | |
130 /* | |
131 * scheme = alpha *( alpha | digit | "+" | "-" | "." ) | |
132 */ | |
133 | |
134 #define IS_SCHEME(x) ((IS_ALPHA(x)) || (IS_DIGIT(x)) || \ | |
135 ((x) == '+') || ((x) == '-') || ((x) == '.')) | |
136 | |
137 /* | |
138 * reg_name = 1*( unreserved | escaped | "$" | "," | | |
139 * ";" | ":" | "@" | "&" | "=" | "+" ) | |
140 */ | |
141 | |
142 #define IS_REG_NAME(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ | |
143 ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || \ | |
144 ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || \ | |
145 ((*(p) == '=')) || ((*(p) == '+'))) | |
146 | |
147 /* | |
148 * userinfo = *( unreserved | escaped | ";" | ":" | "&" | "=" | | |
149 * "+" | "$" | "," ) | |
150 */ | |
151 #define IS_USERINFO(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ | |
152 ((*(p) == ';')) || ((*(p) == ':')) || ((*(p) == '&')) || \ | |
153 ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \ | |
154 ((*(p) == ','))) | |
155 | |
156 /* | |
157 * uric = reserved | unreserved | escaped | |
158 */ | |
159 | |
160 #define IS_URIC(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ | |
161 (IS_RESERVED(*(p)))) | |
162 | |
163 /* | |
164 * unwise = "{" | "}" | "|" | "\" | "^" | "`" | |
165 */ | |
166 | |
167 #define IS_UNWISE(p) \ | |
168 (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \ | |
169 ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \ | |
170 ((*(p) == ']')) || ((*(p) == '`'))) | |
171 | |
172 /* | |
173 * Skip to next pointer char, handle escaped sequences | 92 * Skip to next pointer char, handle escaped sequences |
174 */ | 93 */ |
175 | 94 |
176 #define NEXT(p) ((*p == '%')? p += 3 : p++) | 95 #define NEXT(p) ((*p == '%')? p += 3 : p++) |
177 | 96 |
178 /* | 97 /* |
179 * Productions from the spec. | 98 * Productions from the spec. |
180 * | 99 * |
181 * authority = server | reg_name | 100 * authority = server | reg_name |
182 * reg_name = 1*( unreserved | escaped | "$" | "," | | 101 * reg_name = 1*( unreserved | escaped | "$" | "," | |
183 * ";" | ":" | "@" | "&" | "=" | "+" ) | 102 * ";" | ":" | "@" | "&" | "=" | "+" ) |
184 * | 103 * |
185 * path = [ abs_path | opaque_part ] | 104 * path = [ abs_path | opaque_part ] |
186 */ | 105 */ |
187 | 106 |
188 #define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n)) | 107 #define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n)) |
189 | 108 |
190 /************************************************************************ | 109 /************************************************************************ |
191 * * | 110 * * |
| 111 * RFC 3986 parser * |
| 112 * * |
| 113 ************************************************************************/ |
| 114 |
| 115 #define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9')) |
| 116 #define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) || \ |
| 117 ((*(p) >= 'A') && (*(p) <= 'Z'))) |
| 118 #define ISA_HEXDIG(p) \ |
| 119 (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) || \ |
| 120 ((*(p) >= 'A') && (*(p) <= 'F'))) |
| 121 |
| 122 /* |
| 123 * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" |
| 124 * / "*" / "+" / "," / ";" / "=" |
| 125 */ |
| 126 #define ISA_SUB_DELIM(p) \ |
| 127 (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) || \ |
| 128 ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) || \ |
| 129 ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) || \ |
| 130 ((*(p) == '='))) |
| 131 |
| 132 /* |
| 133 * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" |
| 134 */ |
| 135 #define ISA_GEN_DELIM(p) \ |
| 136 (((*(p) == ':')) || ((*(p) == '/')) || ((*(p) == '?')) || \ |
| 137 ((*(p) == '#')) || ((*(p) == '[')) || ((*(p) == ']')) || \ |
| 138 ((*(p) == '@'))) |
| 139 |
| 140 /* |
| 141 * reserved = gen-delims / sub-delims |
| 142 */ |
| 143 #define ISA_RESERVED(p) (ISA_GEN_DELIM(p) || (ISA_SUB_DELIM(p))) |
| 144 |
| 145 /* |
| 146 * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" |
| 147 */ |
| 148 #define ISA_UNRESERVED(p) \ |
| 149 ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) || \ |
| 150 ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~'))) |
| 151 |
| 152 /* |
| 153 * pct-encoded = "%" HEXDIG HEXDIG |
| 154 */ |
| 155 #define ISA_PCT_ENCODED(p) \ |
| 156 ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2))) |
| 157 |
| 158 /* |
| 159 * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" |
| 160 */ |
| 161 #define ISA_PCHAR(p) \ |
| 162 (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) || \ |
| 163 ((*(p) == ':')) || ((*(p) == '@'))) |
| 164 |
| 165 /** |
| 166 * xmlParse3986Scheme: |
| 167 * @uri: pointer to an URI structure |
| 168 * @str: pointer to the string to analyze |
| 169 * |
| 170 * Parse an URI scheme |
| 171 * |
| 172 * ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) |
| 173 * |
| 174 * Returns 0 or the error code |
| 175 */ |
| 176 static int |
| 177 xmlParse3986Scheme(xmlURIPtr uri, const char **str) { |
| 178 const char *cur; |
| 179 |
| 180 if (str == NULL) |
| 181 return(-1); |
| 182 |
| 183 cur = *str; |
| 184 if (!ISA_ALPHA(cur)) |
| 185 return(2); |
| 186 cur++; |
| 187 while (ISA_ALPHA(cur) || ISA_DIGIT(cur) || |
| 188 (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++; |
| 189 if (uri != NULL) { |
| 190 if (uri->scheme != NULL) xmlFree(uri->scheme); |
| 191 uri->scheme = STRNDUP(*str, cur - *str); |
| 192 } |
| 193 *str = cur; |
| 194 return(0); |
| 195 } |
| 196 |
| 197 /** |
| 198 * xmlParse3986Fragment: |
| 199 * @uri: pointer to an URI structure |
| 200 * @str: pointer to the string to analyze |
| 201 * |
| 202 * Parse the query part of an URI |
| 203 * |
| 204 * fragment = *( pchar / "/" / "?" ) |
| 205 * NOTE: the strict syntax as defined by 3986 does not allow '[' and ']' |
| 206 * in the fragment identifier but this is used very broadly for |
| 207 * xpointer scheme selection, so we are allowing it here to not break |
| 208 * for example all the DocBook processing chains. |
| 209 * |
| 210 * Returns 0 or the error code |
| 211 */ |
| 212 static int |
| 213 xmlParse3986Fragment(xmlURIPtr uri, const char **str) |
| 214 { |
| 215 const char *cur; |
| 216 |
| 217 if (str == NULL) |
| 218 return (-1); |
| 219 |
| 220 cur = *str; |
| 221 |
| 222 while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || |
| 223 (*cur == '[') || (*cur == ']') || |
| 224 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) |
| 225 NEXT(cur); |
| 226 if (uri != NULL) { |
| 227 if (uri->fragment != NULL) |
| 228 xmlFree(uri->fragment); |
| 229 if (uri->cleanup & 2) |
| 230 uri->fragment = STRNDUP(*str, cur - *str); |
| 231 else |
| 232 uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL); |
| 233 } |
| 234 *str = cur; |
| 235 return (0); |
| 236 } |
| 237 |
| 238 /** |
| 239 * xmlParse3986Query: |
| 240 * @uri: pointer to an URI structure |
| 241 * @str: pointer to the string to analyze |
| 242 * |
| 243 * Parse the query part of an URI |
| 244 * |
| 245 * query = *uric |
| 246 * |
| 247 * Returns 0 or the error code |
| 248 */ |
| 249 static int |
| 250 xmlParse3986Query(xmlURIPtr uri, const char **str) |
| 251 { |
| 252 const char *cur; |
| 253 |
| 254 if (str == NULL) |
| 255 return (-1); |
| 256 |
| 257 cur = *str; |
| 258 |
| 259 while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || |
| 260 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) |
| 261 NEXT(cur); |
| 262 if (uri != NULL) { |
| 263 if (uri->query != NULL) |
| 264 xmlFree(uri->query); |
| 265 if (uri->cleanup & 2) |
| 266 uri->query = STRNDUP(*str, cur - *str); |
| 267 else |
| 268 uri->query = xmlURIUnescapeString(*str, cur - *str, NULL); |
| 269 |
| 270 /* Save the raw bytes of the query as well. |
| 271 * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114 |
| 272 */ |
| 273 if (uri->query_raw != NULL) |
| 274 xmlFree (uri->query_raw); |
| 275 uri->query_raw = STRNDUP (*str, cur - *str); |
| 276 } |
| 277 *str = cur; |
| 278 return (0); |
| 279 } |
| 280 |
| 281 /** |
| 282 * xmlParse3986Port: |
| 283 * @uri: pointer to an URI structure |
| 284 * @str: the string to analyze |
| 285 * |
| 286 * Parse a port part and fills in the appropriate fields |
| 287 * of the @uri structure |
| 288 * |
| 289 * port = *DIGIT |
| 290 * |
| 291 * Returns 0 or the error code |
| 292 */ |
| 293 static int |
| 294 xmlParse3986Port(xmlURIPtr uri, const char **str) |
| 295 { |
| 296 const char *cur = *str; |
| 297 |
| 298 if (ISA_DIGIT(cur)) { |
| 299 if (uri != NULL) |
| 300 uri->port = 0; |
| 301 while (ISA_DIGIT(cur)) { |
| 302 if (uri != NULL) |
| 303 uri->port = uri->port * 10 + (*cur - '0'); |
| 304 cur++; |
| 305 } |
| 306 *str = cur; |
| 307 return(0); |
| 308 } |
| 309 return(1); |
| 310 } |
| 311 |
| 312 /** |
| 313 * xmlParse3986Userinfo: |
| 314 * @uri: pointer to an URI structure |
| 315 * @str: the string to analyze |
| 316 * |
| 317 * Parse an user informations part and fills in the appropriate fields |
| 318 * of the @uri structure |
| 319 * |
| 320 * userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) |
| 321 * |
| 322 * Returns 0 or the error code |
| 323 */ |
| 324 static int |
| 325 xmlParse3986Userinfo(xmlURIPtr uri, const char **str) |
| 326 { |
| 327 const char *cur; |
| 328 |
| 329 cur = *str; |
| 330 while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || |
| 331 ISA_SUB_DELIM(cur) || (*cur == ':')) |
| 332 NEXT(cur); |
| 333 if (*cur == '@') { |
| 334 if (uri != NULL) { |
| 335 if (uri->user != NULL) xmlFree(uri->user); |
| 336 if (uri->cleanup & 2) |
| 337 uri->user = STRNDUP(*str, cur - *str); |
| 338 else |
| 339 uri->user = xmlURIUnescapeString(*str, cur - *str, NULL); |
| 340 } |
| 341 *str = cur; |
| 342 return(0); |
| 343 } |
| 344 return(1); |
| 345 } |
| 346 |
| 347 /** |
| 348 * xmlParse3986DecOctet: |
| 349 * @str: the string to analyze |
| 350 * |
| 351 * dec-octet = DIGIT ; 0-9 |
| 352 * / %x31-39 DIGIT ; 10-99 |
| 353 * / "1" 2DIGIT ; 100-199 |
| 354 * / "2" %x30-34 DIGIT ; 200-249 |
| 355 * / "25" %x30-35 ; 250-255 |
| 356 * |
| 357 * Skip a dec-octet. |
| 358 * |
| 359 * Returns 0 if found and skipped, 1 otherwise |
| 360 */ |
| 361 static int |
| 362 xmlParse3986DecOctet(const char **str) { |
| 363 const char *cur = *str; |
| 364 |
| 365 if (!(ISA_DIGIT(cur))) |
| 366 return(1); |
| 367 if (!ISA_DIGIT(cur+1)) |
| 368 cur++; |
| 369 else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur+2))) |
| 370 cur += 2; |
| 371 else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2))) |
| 372 cur += 3; |
| 373 else if ((*cur == '2') && (*(cur + 1) >= '0') && |
| 374 (*(cur + 1) <= '4') && (ISA_DIGIT(cur + 2))) |
| 375 cur += 3; |
| 376 else if ((*cur == '2') && (*(cur + 1) == '5') && |
| 377 (*(cur + 2) >= '0') && (*(cur + 1) <= '5')) |
| 378 cur += 3; |
| 379 else |
| 380 return(1); |
| 381 *str = cur; |
| 382 return(0); |
| 383 } |
| 384 /** |
| 385 * xmlParse3986Host: |
| 386 * @uri: pointer to an URI structure |
| 387 * @str: the string to analyze |
| 388 * |
| 389 * Parse an host part and fills in the appropriate fields |
| 390 * of the @uri structure |
| 391 * |
| 392 * host = IP-literal / IPv4address / reg-name |
| 393 * IP-literal = "[" ( IPv6address / IPvFuture ) "]" |
| 394 * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet |
| 395 * reg-name = *( unreserved / pct-encoded / sub-delims ) |
| 396 * |
| 397 * Returns 0 or the error code |
| 398 */ |
| 399 static int |
| 400 xmlParse3986Host(xmlURIPtr uri, const char **str) |
| 401 { |
| 402 const char *cur = *str; |
| 403 const char *host; |
| 404 |
| 405 host = cur; |
| 406 /* |
| 407 * IPv6 and future adressing scheme are enclosed between brackets |
| 408 */ |
| 409 if (*cur == '[') { |
| 410 cur++; |
| 411 while ((*cur != ']') && (*cur != 0)) |
| 412 cur++; |
| 413 if (*cur != ']') |
| 414 return(1); |
| 415 cur++; |
| 416 goto found; |
| 417 } |
| 418 /* |
| 419 * try to parse an IPv4 |
| 420 */ |
| 421 if (ISA_DIGIT(cur)) { |
| 422 if (xmlParse3986DecOctet(&cur) != 0) |
| 423 goto not_ipv4; |
| 424 if (*cur != '.') |
| 425 goto not_ipv4; |
| 426 cur++; |
| 427 if (xmlParse3986DecOctet(&cur) != 0) |
| 428 goto not_ipv4; |
| 429 if (*cur != '.') |
| 430 goto not_ipv4; |
| 431 if (xmlParse3986DecOctet(&cur) != 0) |
| 432 goto not_ipv4; |
| 433 if (*cur != '.') |
| 434 goto not_ipv4; |
| 435 if (xmlParse3986DecOctet(&cur) != 0) |
| 436 goto not_ipv4; |
| 437 goto found; |
| 438 not_ipv4: |
| 439 cur = *str; |
| 440 } |
| 441 /* |
| 442 * then this should be a hostname which can be empty |
| 443 */ |
| 444 while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur)) |
| 445 NEXT(cur); |
| 446 found: |
| 447 if (uri != NULL) { |
| 448 if (uri->authority != NULL) xmlFree(uri->authority); |
| 449 uri->authority = NULL; |
| 450 if (uri->server != NULL) xmlFree(uri->server); |
| 451 if (cur != host) { |
| 452 if (uri->cleanup & 2) |
| 453 uri->server = STRNDUP(host, cur - host); |
| 454 else |
| 455 uri->server = xmlURIUnescapeString(host, cur - host, NULL); |
| 456 } else |
| 457 uri->server = NULL; |
| 458 } |
| 459 *str = cur; |
| 460 return(0); |
| 461 } |
| 462 |
| 463 /** |
| 464 * xmlParse3986Authority: |
| 465 * @uri: pointer to an URI structure |
| 466 * @str: the string to analyze |
| 467 * |
| 468 * Parse an authority part and fills in the appropriate fields |
| 469 * of the @uri structure |
| 470 * |
| 471 * authority = [ userinfo "@" ] host [ ":" port ] |
| 472 * |
| 473 * Returns 0 or the error code |
| 474 */ |
| 475 static int |
| 476 xmlParse3986Authority(xmlURIPtr uri, const char **str) |
| 477 { |
| 478 const char *cur; |
| 479 int ret; |
| 480 |
| 481 cur = *str; |
| 482 /* |
| 483 * try to parse an userinfo and check for the trailing @ |
| 484 */ |
| 485 ret = xmlParse3986Userinfo(uri, &cur); |
| 486 if ((ret != 0) || (*cur != '@')) |
| 487 cur = *str; |
| 488 else |
| 489 cur++; |
| 490 ret = xmlParse3986Host(uri, &cur); |
| 491 if (ret != 0) return(ret); |
| 492 if (*cur == ':') { |
| 493 cur++; |
| 494 ret = xmlParse3986Port(uri, &cur); |
| 495 if (ret != 0) return(ret); |
| 496 } |
| 497 *str = cur; |
| 498 return(0); |
| 499 } |
| 500 |
| 501 /** |
| 502 * xmlParse3986Segment: |
| 503 * @str: the string to analyze |
| 504 * @forbid: an optional forbidden character |
| 505 * @empty: allow an empty segment |
| 506 * |
| 507 * Parse a segment and fills in the appropriate fields |
| 508 * of the @uri structure |
| 509 * |
| 510 * segment = *pchar |
| 511 * segment-nz = 1*pchar |
| 512 * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) |
| 513 * ; non-zero-length segment without any colon ":" |
| 514 * |
| 515 * Returns 0 or the error code |
| 516 */ |
| 517 static int |
| 518 xmlParse3986Segment(const char **str, char forbid, int empty) |
| 519 { |
| 520 const char *cur; |
| 521 |
| 522 cur = *str; |
| 523 if (!ISA_PCHAR(cur)) { |
| 524 if (empty) |
| 525 return(0); |
| 526 return(1); |
| 527 } |
| 528 while (ISA_PCHAR(cur) && (*cur != forbid)) |
| 529 NEXT(cur); |
| 530 *str = cur; |
| 531 return (0); |
| 532 } |
| 533 |
| 534 /** |
| 535 * xmlParse3986PathAbEmpty: |
| 536 * @uri: pointer to an URI structure |
| 537 * @str: the string to analyze |
| 538 * |
| 539 * Parse an path absolute or empty and fills in the appropriate fields |
| 540 * of the @uri structure |
| 541 * |
| 542 * path-abempty = *( "/" segment ) |
| 543 * |
| 544 * Returns 0 or the error code |
| 545 */ |
| 546 static int |
| 547 xmlParse3986PathAbEmpty(xmlURIPtr uri, const char **str) |
| 548 { |
| 549 const char *cur; |
| 550 int ret; |
| 551 |
| 552 cur = *str; |
| 553 |
| 554 while (*cur == '/') { |
| 555 cur++; |
| 556 ret = xmlParse3986Segment(&cur, 0, 1); |
| 557 if (ret != 0) return(ret); |
| 558 } |
| 559 if (uri != NULL) { |
| 560 if (uri->path != NULL) xmlFree(uri->path); |
| 561 if (*str != cur) { |
| 562 if (uri->cleanup & 2) |
| 563 uri->path = STRNDUP(*str, cur - *str); |
| 564 else |
| 565 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); |
| 566 } else { |
| 567 uri->path = NULL; |
| 568 } |
| 569 } |
| 570 *str = cur; |
| 571 return (0); |
| 572 } |
| 573 |
| 574 /** |
| 575 * xmlParse3986PathAbsolute: |
| 576 * @uri: pointer to an URI structure |
| 577 * @str: the string to analyze |
| 578 * |
| 579 * Parse an path absolute and fills in the appropriate fields |
| 580 * of the @uri structure |
| 581 * |
| 582 * path-absolute = "/" [ segment-nz *( "/" segment ) ] |
| 583 * |
| 584 * Returns 0 or the error code |
| 585 */ |
| 586 static int |
| 587 xmlParse3986PathAbsolute(xmlURIPtr uri, const char **str) |
| 588 { |
| 589 const char *cur; |
| 590 int ret; |
| 591 |
| 592 cur = *str; |
| 593 |
| 594 if (*cur != '/') |
| 595 return(1); |
| 596 cur++; |
| 597 ret = xmlParse3986Segment(&cur, 0, 0); |
| 598 if (ret == 0) { |
| 599 while (*cur == '/') { |
| 600 cur++; |
| 601 ret = xmlParse3986Segment(&cur, 0, 1); |
| 602 if (ret != 0) return(ret); |
| 603 } |
| 604 } |
| 605 if (uri != NULL) { |
| 606 if (uri->path != NULL) xmlFree(uri->path); |
| 607 if (cur != *str) { |
| 608 if (uri->cleanup & 2) |
| 609 uri->path = STRNDUP(*str, cur - *str); |
| 610 else |
| 611 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); |
| 612 } else { |
| 613 uri->path = NULL; |
| 614 } |
| 615 } |
| 616 *str = cur; |
| 617 return (0); |
| 618 } |
| 619 |
| 620 /** |
| 621 * xmlParse3986PathRootless: |
| 622 * @uri: pointer to an URI structure |
| 623 * @str: the string to analyze |
| 624 * |
| 625 * Parse an path without root and fills in the appropriate fields |
| 626 * of the @uri structure |
| 627 * |
| 628 * path-rootless = segment-nz *( "/" segment ) |
| 629 * |
| 630 * Returns 0 or the error code |
| 631 */ |
| 632 static int |
| 633 xmlParse3986PathRootless(xmlURIPtr uri, const char **str) |
| 634 { |
| 635 const char *cur; |
| 636 int ret; |
| 637 |
| 638 cur = *str; |
| 639 |
| 640 ret = xmlParse3986Segment(&cur, 0, 0); |
| 641 if (ret != 0) return(ret); |
| 642 while (*cur == '/') { |
| 643 cur++; |
| 644 ret = xmlParse3986Segment(&cur, 0, 1); |
| 645 if (ret != 0) return(ret); |
| 646 } |
| 647 if (uri != NULL) { |
| 648 if (uri->path != NULL) xmlFree(uri->path); |
| 649 if (cur != *str) { |
| 650 if (uri->cleanup & 2) |
| 651 uri->path = STRNDUP(*str, cur - *str); |
| 652 else |
| 653 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); |
| 654 } else { |
| 655 uri->path = NULL; |
| 656 } |
| 657 } |
| 658 *str = cur; |
| 659 return (0); |
| 660 } |
| 661 |
| 662 /** |
| 663 * xmlParse3986PathNoScheme: |
| 664 * @uri: pointer to an URI structure |
| 665 * @str: the string to analyze |
| 666 * |
| 667 * Parse an path which is not a scheme and fills in the appropriate fields |
| 668 * of the @uri structure |
| 669 * |
| 670 * path-noscheme = segment-nz-nc *( "/" segment ) |
| 671 * |
| 672 * Returns 0 or the error code |
| 673 */ |
| 674 static int |
| 675 xmlParse3986PathNoScheme(xmlURIPtr uri, const char **str) |
| 676 { |
| 677 const char *cur; |
| 678 int ret; |
| 679 |
| 680 cur = *str; |
| 681 |
| 682 ret = xmlParse3986Segment(&cur, ':', 0); |
| 683 if (ret != 0) return(ret); |
| 684 while (*cur == '/') { |
| 685 cur++; |
| 686 ret = xmlParse3986Segment(&cur, 0, 1); |
| 687 if (ret != 0) return(ret); |
| 688 } |
| 689 if (uri != NULL) { |
| 690 if (uri->path != NULL) xmlFree(uri->path); |
| 691 if (cur != *str) { |
| 692 if (uri->cleanup & 2) |
| 693 uri->path = STRNDUP(*str, cur - *str); |
| 694 else |
| 695 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); |
| 696 } else { |
| 697 uri->path = NULL; |
| 698 } |
| 699 } |
| 700 *str = cur; |
| 701 return (0); |
| 702 } |
| 703 |
| 704 /** |
| 705 * xmlParse3986HierPart: |
| 706 * @uri: pointer to an URI structure |
| 707 * @str: the string to analyze |
| 708 * |
| 709 * Parse an hierarchical part and fills in the appropriate fields |
| 710 * of the @uri structure |
| 711 * |
| 712 * hier-part = "//" authority path-abempty |
| 713 * / path-absolute |
| 714 * / path-rootless |
| 715 * / path-empty |
| 716 * |
| 717 * Returns 0 or the error code |
| 718 */ |
| 719 static int |
| 720 xmlParse3986HierPart(xmlURIPtr uri, const char **str) |
| 721 { |
| 722 const char *cur; |
| 723 int ret; |
| 724 |
| 725 cur = *str; |
| 726 |
| 727 if ((*cur == '/') && (*(cur + 1) == '/')) { |
| 728 cur += 2; |
| 729 ret = xmlParse3986Authority(uri, &cur); |
| 730 if (ret != 0) return(ret); |
| 731 ret = xmlParse3986PathAbEmpty(uri, &cur); |
| 732 if (ret != 0) return(ret); |
| 733 *str = cur; |
| 734 return(0); |
| 735 } else if (*cur == '/') { |
| 736 ret = xmlParse3986PathAbsolute(uri, &cur); |
| 737 if (ret != 0) return(ret); |
| 738 } else if (ISA_PCHAR(cur)) { |
| 739 ret = xmlParse3986PathRootless(uri, &cur); |
| 740 if (ret != 0) return(ret); |
| 741 } else { |
| 742 /* path-empty is effectively empty */ |
| 743 if (uri != NULL) { |
| 744 if (uri->path != NULL) xmlFree(uri->path); |
| 745 uri->path = NULL; |
| 746 } |
| 747 } |
| 748 *str = cur; |
| 749 return (0); |
| 750 } |
| 751 |
| 752 /** |
| 753 * xmlParse3986RelativeRef: |
| 754 * @uri: pointer to an URI structure |
| 755 * @str: the string to analyze |
| 756 * |
| 757 * Parse an URI string and fills in the appropriate fields |
| 758 * of the @uri structure |
| 759 * |
| 760 * relative-ref = relative-part [ "?" query ] [ "#" fragment ] |
| 761 * relative-part = "//" authority path-abempty |
| 762 * / path-absolute |
| 763 * / path-noscheme |
| 764 * / path-empty |
| 765 * |
| 766 * Returns 0 or the error code |
| 767 */ |
| 768 static int |
| 769 xmlParse3986RelativeRef(xmlURIPtr uri, const char *str) { |
| 770 int ret; |
| 771 |
| 772 if ((*str == '/') && (*(str + 1) == '/')) { |
| 773 str += 2; |
| 774 ret = xmlParse3986Authority(uri, &str); |
| 775 if (ret != 0) return(ret); |
| 776 ret = xmlParse3986PathAbEmpty(uri, &str); |
| 777 if (ret != 0) return(ret); |
| 778 } else if (*str == '/') { |
| 779 ret = xmlParse3986PathAbsolute(uri, &str); |
| 780 if (ret != 0) return(ret); |
| 781 } else if (ISA_PCHAR(str)) { |
| 782 ret = xmlParse3986PathNoScheme(uri, &str); |
| 783 if (ret != 0) return(ret); |
| 784 } else { |
| 785 /* path-empty is effectively empty */ |
| 786 if (uri != NULL) { |
| 787 if (uri->path != NULL) xmlFree(uri->path); |
| 788 uri->path = NULL; |
| 789 } |
| 790 } |
| 791 |
| 792 if (*str == '?') { |
| 793 str++; |
| 794 ret = xmlParse3986Query(uri, &str); |
| 795 if (ret != 0) return(ret); |
| 796 } |
| 797 if (*str == '#') { |
| 798 str++; |
| 799 ret = xmlParse3986Fragment(uri, &str); |
| 800 if (ret != 0) return(ret); |
| 801 } |
| 802 if (*str != 0) { |
| 803 xmlCleanURI(uri); |
| 804 return(1); |
| 805 } |
| 806 return(0); |
| 807 } |
| 808 |
| 809 |
| 810 /** |
| 811 * xmlParse3986URI: |
| 812 * @uri: pointer to an URI structure |
| 813 * @str: the string to analyze |
| 814 * |
| 815 * Parse an URI string and fills in the appropriate fields |
| 816 * of the @uri structure |
| 817 * |
| 818 * scheme ":" hier-part [ "?" query ] [ "#" fragment ] |
| 819 * |
| 820 * Returns 0 or the error code |
| 821 */ |
| 822 static int |
| 823 xmlParse3986URI(xmlURIPtr uri, const char *str) { |
| 824 int ret; |
| 825 |
| 826 ret = xmlParse3986Scheme(uri, &str); |
| 827 if (ret != 0) return(ret); |
| 828 if (*str != ':') { |
| 829 return(1); |
| 830 } |
| 831 str++; |
| 832 ret = xmlParse3986HierPart(uri, &str); |
| 833 if (ret != 0) return(ret); |
| 834 if (*str == '?') { |
| 835 str++; |
| 836 ret = xmlParse3986Query(uri, &str); |
| 837 if (ret != 0) return(ret); |
| 838 } |
| 839 if (*str == '#') { |
| 840 str++; |
| 841 ret = xmlParse3986Fragment(uri, &str); |
| 842 if (ret != 0) return(ret); |
| 843 } |
| 844 if (*str != 0) { |
| 845 xmlCleanURI(uri); |
| 846 return(1); |
| 847 } |
| 848 return(0); |
| 849 } |
| 850 |
| 851 /** |
| 852 * xmlParse3986URIReference: |
| 853 * @uri: pointer to an URI structure |
| 854 * @str: the string to analyze |
| 855 * |
| 856 * Parse an URI reference string and fills in the appropriate fields |
| 857 * of the @uri structure |
| 858 * |
| 859 * URI-reference = URI / relative-ref |
| 860 * |
| 861 * Returns 0 or the error code |
| 862 */ |
| 863 static int |
| 864 xmlParse3986URIReference(xmlURIPtr uri, const char *str) { |
| 865 int ret; |
| 866 |
| 867 if (str == NULL) |
| 868 return(-1); |
| 869 xmlCleanURI(uri); |
| 870 |
| 871 /* |
| 872 * Try first to parse absolute refs, then fallback to relative if |
| 873 * it fails. |
| 874 */ |
| 875 ret = xmlParse3986URI(uri, str); |
| 876 if (ret != 0) { |
| 877 xmlCleanURI(uri); |
| 878 ret = xmlParse3986RelativeRef(uri, str); |
| 879 if (ret != 0) { |
| 880 xmlCleanURI(uri); |
| 881 return(ret); |
| 882 } |
| 883 } |
| 884 return(0); |
| 885 } |
| 886 |
| 887 /** |
| 888 * xmlParseURI: |
| 889 * @str: the URI string to analyze |
| 890 * |
| 891 * Parse an URI based on RFC 3986 |
| 892 * |
| 893 * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] |
| 894 * |
| 895 * Returns a newly built xmlURIPtr or NULL in case of error |
| 896 */ |
| 897 xmlURIPtr |
| 898 xmlParseURI(const char *str) { |
| 899 xmlURIPtr uri; |
| 900 int ret; |
| 901 |
| 902 if (str == NULL) |
| 903 return(NULL); |
| 904 uri = xmlCreateURI(); |
| 905 if (uri != NULL) { |
| 906 ret = xmlParse3986URIReference(uri, str); |
| 907 if (ret) { |
| 908 xmlFreeURI(uri); |
| 909 return(NULL); |
| 910 } |
| 911 } |
| 912 return(uri); |
| 913 } |
| 914 |
| 915 /** |
| 916 * xmlParseURIReference: |
| 917 * @uri: pointer to an URI structure |
| 918 * @str: the string to analyze |
| 919 * |
| 920 * Parse an URI reference string based on RFC 3986 and fills in the |
| 921 * appropriate fields of the @uri structure |
| 922 * |
| 923 * URI-reference = URI / relative-ref |
| 924 * |
| 925 * Returns 0 or the error code |
| 926 */ |
| 927 int |
| 928 xmlParseURIReference(xmlURIPtr uri, const char *str) { |
| 929 return(xmlParse3986URIReference(uri, str)); |
| 930 } |
| 931 |
| 932 /** |
| 933 * xmlParseURIRaw: |
| 934 * @str: the URI string to analyze |
| 935 * @raw: if 1 unescaping of URI pieces are disabled |
| 936 * |
| 937 * Parse an URI but allows to keep intact the original fragments. |
| 938 * |
| 939 * URI-reference = URI / relative-ref |
| 940 * |
| 941 * Returns a newly built xmlURIPtr or NULL in case of error |
| 942 */ |
| 943 xmlURIPtr |
| 944 xmlParseURIRaw(const char *str, int raw) { |
| 945 xmlURIPtr uri; |
| 946 int ret; |
| 947 |
| 948 if (str == NULL) |
| 949 return(NULL); |
| 950 uri = xmlCreateURI(); |
| 951 if (uri != NULL) { |
| 952 if (raw) { |
| 953 uri->cleanup |= 2; |
| 954 } |
| 955 ret = xmlParseURIReference(uri, str); |
| 956 if (ret) { |
| 957 xmlFreeURI(uri); |
| 958 return(NULL); |
| 959 } |
| 960 } |
| 961 return(uri); |
| 962 } |
| 963 |
| 964 /************************************************************************ |
| 965 * * |
192 * Generic URI structure functions * | 966 * Generic URI structure functions * |
193 * * | 967 * * |
194 ************************************************************************/ | 968 ************************************************************************/ |
195 | 969 |
196 /** | 970 /** |
197 * xmlCreateURI: | 971 * xmlCreateURI: |
198 * | 972 * |
199 * Simply creates an empty xmlURI | 973 * Simply creates an empty xmlURI |
200 * | 974 * |
201 * Returns the new structure or NULL in case of error | 975 * Returns the new structure or NULL in case of error |
(...skipping 16 matching lines...) Expand all Loading... |
218 * xmlSaveUri: | 992 * xmlSaveUri: |
219 * @uri: pointer to an xmlURI | 993 * @uri: pointer to an xmlURI |
220 * | 994 * |
221 * Save the URI as an escaped string | 995 * Save the URI as an escaped string |
222 * | 996 * |
223 * Returns a new string (to be deallocated by caller) | 997 * Returns a new string (to be deallocated by caller) |
224 */ | 998 */ |
225 xmlChar * | 999 xmlChar * |
226 xmlSaveUri(xmlURIPtr uri) { | 1000 xmlSaveUri(xmlURIPtr uri) { |
227 xmlChar *ret = NULL; | 1001 xmlChar *ret = NULL; |
| 1002 xmlChar *temp; |
228 const char *p; | 1003 const char *p; |
229 int len; | 1004 int len; |
230 int max; | 1005 int max; |
231 | 1006 |
232 if (uri == NULL) return(NULL); | 1007 if (uri == NULL) return(NULL); |
233 | 1008 |
234 | 1009 |
235 max = 80; | 1010 max = 80; |
236 ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar)); | 1011 ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar)); |
237 if (ret == NULL) { | 1012 if (ret == NULL) { |
238 xmlGenericError(xmlGenericErrorContext, | 1013 xmlGenericError(xmlGenericErrorContext, |
239 "xmlSaveUri: out of memory\n"); | 1014 "xmlSaveUri: out of memory\n"); |
240 return(NULL); | 1015 return(NULL); |
241 } | 1016 } |
242 len = 0; | 1017 len = 0; |
243 | 1018 |
244 if (uri->scheme != NULL) { | 1019 if (uri->scheme != NULL) { |
245 p = uri->scheme; | 1020 p = uri->scheme; |
246 while (*p != 0) { | 1021 while (*p != 0) { |
247 if (len >= max) { | 1022 if (len >= max) { |
248 max *= 2; | 1023 max *= 2; |
249 » » ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); | 1024 » » temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
250 » » if (ret == NULL) { | 1025 » » if (temp == NULL) { |
251 xmlGenericError(xmlGenericErrorContext, | 1026 xmlGenericError(xmlGenericErrorContext, |
252 "xmlSaveUri: out of memory\n"); | 1027 "xmlSaveUri: out of memory\n"); |
| 1028 xmlFree(ret); |
253 return(NULL); | 1029 return(NULL); |
254 } | 1030 } |
| 1031 ret = temp; |
255 } | 1032 } |
256 ret[len++] = *p++; | 1033 ret[len++] = *p++; |
257 } | 1034 } |
258 if (len >= max) { | 1035 if (len >= max) { |
259 max *= 2; | 1036 max *= 2; |
260 » ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); | 1037 » temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
261 » if (ret == NULL) { | 1038 » if (temp == NULL) { |
262 xmlGenericError(xmlGenericErrorContext, | 1039 xmlGenericError(xmlGenericErrorContext, |
263 "xmlSaveUri: out of memory\n"); | 1040 "xmlSaveUri: out of memory\n"); |
| 1041 xmlFree(ret); |
264 return(NULL); | 1042 return(NULL); |
265 } | 1043 } |
| 1044 ret = temp; |
266 } | 1045 } |
267 ret[len++] = ':'; | 1046 ret[len++] = ':'; |
268 } | 1047 } |
269 if (uri->opaque != NULL) { | 1048 if (uri->opaque != NULL) { |
270 p = uri->opaque; | 1049 p = uri->opaque; |
271 while (*p != 0) { | 1050 while (*p != 0) { |
272 if (len + 3 >= max) { | 1051 if (len + 3 >= max) { |
273 max *= 2; | 1052 max *= 2; |
274 » » ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); | 1053 » » temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
275 » » if (ret == NULL) { | 1054 » » if (temp == NULL) { |
276 xmlGenericError(xmlGenericErrorContext, | 1055 xmlGenericError(xmlGenericErrorContext, |
277 "xmlSaveUri: out of memory\n"); | 1056 "xmlSaveUri: out of memory\n"); |
| 1057 xmlFree(ret); |
278 return(NULL); | 1058 return(NULL); |
279 } | 1059 } |
| 1060 ret = temp; |
280 } | 1061 } |
281 if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p))) | 1062 if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p))) |
282 ret[len++] = *p++; | 1063 ret[len++] = *p++; |
283 else { | 1064 else { |
284 int val = *(unsigned char *)p++; | 1065 int val = *(unsigned char *)p++; |
285 int hi = val / 0x10, lo = val % 0x10; | 1066 int hi = val / 0x10, lo = val % 0x10; |
286 ret[len++] = '%'; | 1067 ret[len++] = '%'; |
287 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); | 1068 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); |
288 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); | 1069 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); |
289 } | 1070 } |
290 } | 1071 } |
291 } else { | 1072 } else { |
292 if (uri->server != NULL) { | 1073 if (uri->server != NULL) { |
293 if (len + 3 >= max) { | 1074 if (len + 3 >= max) { |
294 max *= 2; | 1075 max *= 2; |
295 » » ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); | 1076 » » temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
296 » » if (ret == NULL) { | 1077 » » if (temp == NULL) { |
297 xmlGenericError(xmlGenericErrorContext, | 1078 xmlGenericError(xmlGenericErrorContext, |
298 "xmlSaveUri: out of memory\n"); | 1079 "xmlSaveUri: out of memory\n"); |
| 1080 xmlFree(ret); |
299 return(NULL); | 1081 return(NULL); |
300 } | 1082 } |
| 1083 ret = temp; |
301 } | 1084 } |
302 ret[len++] = '/'; | 1085 ret[len++] = '/'; |
303 ret[len++] = '/'; | 1086 ret[len++] = '/'; |
304 if (uri->user != NULL) { | 1087 if (uri->user != NULL) { |
305 p = uri->user; | 1088 p = uri->user; |
306 while (*p != 0) { | 1089 while (*p != 0) { |
307 if (len + 3 >= max) { | 1090 if (len + 3 >= max) { |
308 max *= 2; | 1091 max *= 2; |
309 » » » ret = (xmlChar *) xmlRealloc(ret, | 1092 » » » temp = (xmlChar *) xmlRealloc(ret, |
310 (max + 1) * sizeof(xmlChar)); | 1093 (max + 1) * sizeof(xmlChar)); |
311 » » » if (ret == NULL) { | 1094 » » » if (temp == NULL) { |
312 xmlGenericError(xmlGenericErrorContext, | 1095 xmlGenericError(xmlGenericErrorContext, |
313 "xmlSaveUri: out of memory\n"); | 1096 "xmlSaveUri: out of memory\n"); |
| 1097 xmlFree(ret); |
314 return(NULL); | 1098 return(NULL); |
315 } | 1099 } |
| 1100 ret = temp; |
316 } | 1101 } |
317 if ((IS_UNRESERVED(*(p))) || | 1102 if ((IS_UNRESERVED(*(p))) || |
318 ((*(p) == ';')) || ((*(p) == ':')) || | 1103 ((*(p) == ';')) || ((*(p) == ':')) || |
319 ((*(p) == '&')) || ((*(p) == '=')) || | 1104 ((*(p) == '&')) || ((*(p) == '=')) || |
320 ((*(p) == '+')) || ((*(p) == '$')) || | 1105 ((*(p) == '+')) || ((*(p) == '$')) || |
321 ((*(p) == ','))) | 1106 ((*(p) == ','))) |
322 ret[len++] = *p++; | 1107 ret[len++] = *p++; |
323 else { | 1108 else { |
324 int val = *(unsigned char *)p++; | 1109 int val = *(unsigned char *)p++; |
325 int hi = val / 0x10, lo = val % 0x10; | 1110 int hi = val / 0x10, lo = val % 0x10; |
326 ret[len++] = '%'; | 1111 ret[len++] = '%'; |
327 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); | 1112 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); |
328 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); | 1113 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); |
329 } | 1114 } |
330 } | 1115 } |
331 if (len + 3 >= max) { | 1116 if (len + 3 >= max) { |
332 max *= 2; | 1117 max *= 2; |
333 » » ret = (xmlChar *) xmlRealloc(ret, | 1118 » » temp = (xmlChar *) xmlRealloc(ret, |
334 (max + 1) * sizeof(xmlChar)); | 1119 (max + 1) * sizeof(xmlChar)); |
335 » » if (ret == NULL) { | 1120 » » if (temp == NULL) { |
336 xmlGenericError(xmlGenericErrorContext, | 1121 xmlGenericError(xmlGenericErrorContext, |
337 "xmlSaveUri: out of memory\n"); | 1122 "xmlSaveUri: out of memory\n"); |
| 1123 xmlFree(ret); |
338 return(NULL); | 1124 return(NULL); |
339 } | 1125 } |
| 1126 ret = temp; |
340 } | 1127 } |
341 ret[len++] = '@'; | 1128 ret[len++] = '@'; |
342 } | 1129 } |
343 p = uri->server; | 1130 p = uri->server; |
344 while (*p != 0) { | 1131 while (*p != 0) { |
345 if (len >= max) { | 1132 if (len >= max) { |
346 max *= 2; | 1133 max *= 2; |
347 » » ret = (xmlChar *) xmlRealloc(ret, | 1134 » » temp = (xmlChar *) xmlRealloc(ret, |
348 (max + 1) * sizeof(xmlChar)); | 1135 (max + 1) * sizeof(xmlChar)); |
349 » » if (ret == NULL) { | 1136 » » if (temp == NULL) { |
350 xmlGenericError(xmlGenericErrorContext, | 1137 xmlGenericError(xmlGenericErrorContext, |
351 "xmlSaveUri: out of memory\n"); | 1138 "xmlSaveUri: out of memory\n"); |
| 1139 xmlFree(ret); |
352 return(NULL); | 1140 return(NULL); |
353 } | 1141 } |
| 1142 ret = temp; |
354 } | 1143 } |
355 ret[len++] = *p++; | 1144 ret[len++] = *p++; |
356 } | 1145 } |
357 if (uri->port > 0) { | 1146 if (uri->port > 0) { |
358 if (len + 10 >= max) { | 1147 if (len + 10 >= max) { |
359 max *= 2; | 1148 max *= 2; |
360 » » ret = (xmlChar *) xmlRealloc(ret, | 1149 » » temp = (xmlChar *) xmlRealloc(ret, |
361 (max + 1) * sizeof(xmlChar)); | 1150 (max + 1) * sizeof(xmlChar)); |
362 » » if (ret == NULL) { | 1151 » » if (temp == NULL) { |
363 xmlGenericError(xmlGenericErrorContext, | 1152 xmlGenericError(xmlGenericErrorContext, |
364 "xmlSaveUri: out of memory\n"); | 1153 "xmlSaveUri: out of memory\n"); |
| 1154 xmlFree(ret); |
365 return(NULL); | 1155 return(NULL); |
366 } | 1156 } |
| 1157 ret = temp; |
367 } | 1158 } |
368 len += snprintf((char *) &ret[len], max - len, ":%d", uri->port)
; | 1159 len += snprintf((char *) &ret[len], max - len, ":%d", uri->port)
; |
369 } | 1160 } |
370 } else if (uri->authority != NULL) { | 1161 } else if (uri->authority != NULL) { |
371 if (len + 3 >= max) { | 1162 if (len + 3 >= max) { |
372 max *= 2; | 1163 max *= 2; |
373 » » ret = (xmlChar *) xmlRealloc(ret, | 1164 » » temp = (xmlChar *) xmlRealloc(ret, |
374 (max + 1) * sizeof(xmlChar)); | 1165 (max + 1) * sizeof(xmlChar)); |
375 » » if (ret == NULL) { | 1166 » » if (temp == NULL) { |
376 » » xmlGenericError(xmlGenericErrorContext, | 1167 » » » xmlGenericError(xmlGenericErrorContext, |
377 » » » "xmlSaveUri: out of memory\n"); | 1168 » » » » "xmlSaveUri: out of memory\n"); |
378 » » return(NULL); | 1169 xmlFree(ret); |
379 » » } | 1170 » » » return(NULL); |
| 1171 » » } |
| 1172 » » ret = temp; |
380 } | 1173 } |
381 ret[len++] = '/'; | 1174 ret[len++] = '/'; |
382 ret[len++] = '/'; | 1175 ret[len++] = '/'; |
383 p = uri->authority; | 1176 p = uri->authority; |
384 while (*p != 0) { | 1177 while (*p != 0) { |
385 if (len + 3 >= max) { | 1178 if (len + 3 >= max) { |
386 max *= 2; | 1179 max *= 2; |
387 » » ret = (xmlChar *) xmlRealloc(ret, | 1180 » » temp = (xmlChar *) xmlRealloc(ret, |
388 (max + 1) * sizeof(xmlChar)); | 1181 (max + 1) * sizeof(xmlChar)); |
389 » » if (ret == NULL) { | 1182 » » if (temp == NULL) { |
390 xmlGenericError(xmlGenericErrorContext, | 1183 xmlGenericError(xmlGenericErrorContext, |
391 "xmlSaveUri: out of memory\n"); | 1184 "xmlSaveUri: out of memory\n"); |
| 1185 xmlFree(ret); |
392 return(NULL); | 1186 return(NULL); |
393 } | 1187 } |
| 1188 ret = temp; |
394 } | 1189 } |
395 if ((IS_UNRESERVED(*(p))) || | 1190 if ((IS_UNRESERVED(*(p))) || |
396 ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || | 1191 ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || |
397 ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || | 1192 ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || |
398 ((*(p) == '=')) || ((*(p) == '+'))) | 1193 ((*(p) == '=')) || ((*(p) == '+'))) |
399 ret[len++] = *p++; | 1194 ret[len++] = *p++; |
400 else { | 1195 else { |
401 int val = *(unsigned char *)p++; | 1196 int val = *(unsigned char *)p++; |
402 int hi = val / 0x10, lo = val % 0x10; | 1197 int hi = val / 0x10, lo = val % 0x10; |
403 ret[len++] = '%'; | 1198 ret[len++] = '%'; |
404 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); | 1199 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); |
405 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); | 1200 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); |
406 } | 1201 } |
407 } | 1202 } |
408 } else if (uri->scheme != NULL) { | 1203 } else if (uri->scheme != NULL) { |
409 if (len + 3 >= max) { | 1204 if (len + 3 >= max) { |
410 max *= 2; | 1205 max *= 2; |
411 » » ret = (xmlChar *) xmlRealloc(ret, | 1206 » » temp = (xmlChar *) xmlRealloc(ret, |
412 (max + 1) * sizeof(xmlChar)); | 1207 (max + 1) * sizeof(xmlChar)); |
413 » » if (ret == NULL) { | 1208 » » if (temp == NULL) { |
414 » » xmlGenericError(xmlGenericErrorContext, | 1209 » » » xmlGenericError(xmlGenericErrorContext, |
415 » » » "xmlSaveUri: out of memory\n"); | 1210 » » » » "xmlSaveUri: out of memory\n"); |
416 » » return(NULL); | 1211 xmlFree(ret); |
417 » » } | 1212 » » » return(NULL); |
| 1213 » » } |
| 1214 » » ret = temp; |
418 } | 1215 } |
419 ret[len++] = '/'; | 1216 ret[len++] = '/'; |
420 ret[len++] = '/'; | 1217 ret[len++] = '/'; |
421 } | 1218 } |
422 if (uri->path != NULL) { | 1219 if (uri->path != NULL) { |
423 p = uri->path; | 1220 p = uri->path; |
424 /* | 1221 /* |
425 * the colon in file:///d: should not be escaped or | 1222 * the colon in file:///d: should not be escaped or |
426 * Windows accesses fail later. | 1223 * Windows accesses fail later. |
427 */ | 1224 */ |
428 if ((uri->scheme != NULL) && | 1225 if ((uri->scheme != NULL) && |
429 (p[0] == '/') && | 1226 (p[0] == '/') && |
430 (((p[1] >= 'a') && (p[1] <= 'z')) || | 1227 (((p[1] >= 'a') && (p[1] <= 'z')) || |
431 ((p[1] >= 'A') && (p[1] <= 'Z'))) && | 1228 ((p[1] >= 'A') && (p[1] <= 'Z'))) && |
432 (p[2] == ':') && | 1229 (p[2] == ':') && |
433 » (xmlStrEqual(uri->scheme, BAD_CAST "file"))) { | 1230 » (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) { |
434 if (len + 3 >= max) { | 1231 if (len + 3 >= max) { |
435 max *= 2; | 1232 max *= 2; |
436 ret = (xmlChar *) xmlRealloc(ret, | 1233 ret = (xmlChar *) xmlRealloc(ret, |
437 (max + 1) * sizeof(xmlChar)); | 1234 (max + 1) * sizeof(xmlChar)); |
438 if (ret == NULL) { | 1235 if (ret == NULL) { |
439 xmlGenericError(xmlGenericErrorContext, | 1236 xmlGenericError(xmlGenericErrorContext, |
440 "xmlSaveUri: out of memory\n"); | 1237 "xmlSaveUri: out of memory\n"); |
441 return(NULL); | 1238 return(NULL); |
442 } | 1239 } |
443 } | 1240 } |
444 ret[len++] = *p++; | 1241 ret[len++] = *p++; |
445 ret[len++] = *p++; | 1242 ret[len++] = *p++; |
446 ret[len++] = *p++; | 1243 ret[len++] = *p++; |
447 } | 1244 } |
448 while (*p != 0) { | 1245 while (*p != 0) { |
449 if (len + 3 >= max) { | 1246 if (len + 3 >= max) { |
450 max *= 2; | 1247 max *= 2; |
451 » » ret = (xmlChar *) xmlRealloc(ret, | 1248 » » temp = (xmlChar *) xmlRealloc(ret, |
452 (max + 1) * sizeof(xmlChar)); | 1249 (max + 1) * sizeof(xmlChar)); |
453 » » if (ret == NULL) { | 1250 » » if (temp == NULL) { |
454 xmlGenericError(xmlGenericErrorContext, | 1251 xmlGenericError(xmlGenericErrorContext, |
455 "xmlSaveUri: out of memory\n"); | 1252 "xmlSaveUri: out of memory\n"); |
| 1253 xmlFree(ret); |
456 return(NULL); | 1254 return(NULL); |
457 } | 1255 } |
| 1256 ret = temp; |
458 } | 1257 } |
459 if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) || | 1258 if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) || |
460 ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || | 1259 ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || |
461 ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || | 1260 ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || |
462 ((*(p) == ','))) | 1261 ((*(p) == ','))) |
463 ret[len++] = *p++; | 1262 ret[len++] = *p++; |
464 else { | 1263 else { |
465 int val = *(unsigned char *)p++; | 1264 int val = *(unsigned char *)p++; |
466 int hi = val / 0x10, lo = val % 0x10; | 1265 int hi = val / 0x10, lo = val % 0x10; |
467 ret[len++] = '%'; | 1266 ret[len++] = '%'; |
468 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); | 1267 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); |
469 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); | 1268 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); |
470 } | 1269 } |
471 } | 1270 } |
472 } | 1271 } |
473 if (uri->query_raw != NULL) { | 1272 if (uri->query_raw != NULL) { |
474 if (len + 1 >= max) { | 1273 if (len + 1 >= max) { |
475 max *= 2; | 1274 max *= 2; |
476 » » ret = (xmlChar *) xmlRealloc(ret, | 1275 » » temp = (xmlChar *) xmlRealloc(ret, |
477 (max + 1) * sizeof(xmlChar)); | 1276 (max + 1) * sizeof(xmlChar)); |
478 » » if (ret == NULL) { | 1277 » » if (temp == NULL) { |
479 » » xmlGenericError(xmlGenericErrorContext, | 1278 » » » xmlGenericError(xmlGenericErrorContext, |
480 » » » "xmlSaveUri: out of memory\n"); | 1279 » » » » "xmlSaveUri: out of memory\n"); |
481 » » return(NULL); | 1280 xmlFree(ret); |
482 » » } | 1281 » » » return(NULL); |
| 1282 » » } |
| 1283 » » ret = temp; |
483 } | 1284 } |
484 ret[len++] = '?'; | 1285 ret[len++] = '?'; |
485 p = uri->query_raw; | 1286 p = uri->query_raw; |
486 while (*p != 0) { | 1287 while (*p != 0) { |
487 if (len + 1 >= max) { | 1288 if (len + 1 >= max) { |
488 max *= 2; | 1289 max *= 2; |
489 » » ret = (xmlChar *) xmlRealloc(ret, | 1290 » » temp = (xmlChar *) xmlRealloc(ret, |
490 (max + 1) * sizeof(xmlChar)); | 1291 (max + 1) * sizeof(xmlChar)); |
491 » » if (ret == NULL) { | 1292 » » if (temp == NULL) { |
492 xmlGenericError(xmlGenericErrorContext, | 1293 xmlGenericError(xmlGenericErrorContext, |
493 "xmlSaveUri: out of memory\n"); | 1294 "xmlSaveUri: out of memory\n"); |
| 1295 xmlFree(ret); |
494 return(NULL); | 1296 return(NULL); |
495 } | 1297 } |
| 1298 ret = temp; |
496 } | 1299 } |
497 ret[len++] = *p++; | 1300 ret[len++] = *p++; |
498 } | 1301 } |
499 } else if (uri->query != NULL) { | 1302 } else if (uri->query != NULL) { |
500 if (len + 3 >= max) { | 1303 if (len + 3 >= max) { |
501 max *= 2; | 1304 max *= 2; |
502 » » ret = (xmlChar *) xmlRealloc(ret, | 1305 » » temp = (xmlChar *) xmlRealloc(ret, |
503 (max + 1) * sizeof(xmlChar)); | 1306 (max + 1) * sizeof(xmlChar)); |
504 » » if (ret == NULL) { | 1307 » » if (temp == NULL) { |
505 » » xmlGenericError(xmlGenericErrorContext, | 1308 » » » xmlGenericError(xmlGenericErrorContext, |
506 » » » "xmlSaveUri: out of memory\n"); | 1309 » » » » "xmlSaveUri: out of memory\n"); |
507 » » return(NULL); | 1310 xmlFree(ret); |
508 » » } | 1311 » » » return(NULL); |
| 1312 » » } |
| 1313 » » ret = temp; |
509 } | 1314 } |
510 ret[len++] = '?'; | 1315 ret[len++] = '?'; |
511 p = uri->query; | 1316 p = uri->query; |
512 while (*p != 0) { | 1317 while (*p != 0) { |
513 if (len + 3 >= max) { | 1318 if (len + 3 >= max) { |
514 max *= 2; | 1319 max *= 2; |
515 » » ret = (xmlChar *) xmlRealloc(ret, | 1320 » » temp = (xmlChar *) xmlRealloc(ret, |
516 (max + 1) * sizeof(xmlChar)); | 1321 (max + 1) * sizeof(xmlChar)); |
517 » » if (ret == NULL) { | 1322 » » if (temp == NULL) { |
518 xmlGenericError(xmlGenericErrorContext, | 1323 xmlGenericError(xmlGenericErrorContext, |
519 "xmlSaveUri: out of memory\n"); | 1324 "xmlSaveUri: out of memory\n"); |
| 1325 xmlFree(ret); |
520 return(NULL); | 1326 return(NULL); |
521 } | 1327 } |
| 1328 ret = temp; |
522 } | 1329 } |
523 if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) | 1330 if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) |
524 ret[len++] = *p++; | 1331 ret[len++] = *p++; |
525 else { | 1332 else { |
526 int val = *(unsigned char *)p++; | 1333 int val = *(unsigned char *)p++; |
527 int hi = val / 0x10, lo = val % 0x10; | 1334 int hi = val / 0x10, lo = val % 0x10; |
528 ret[len++] = '%'; | 1335 ret[len++] = '%'; |
529 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); | 1336 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); |
530 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); | 1337 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); |
531 } | 1338 } |
532 } | 1339 } |
533 } | 1340 } |
534 } | 1341 } |
535 if (uri->fragment != NULL) { | 1342 if (uri->fragment != NULL) { |
536 if (len + 3 >= max) { | 1343 if (len + 3 >= max) { |
537 max *= 2; | 1344 max *= 2; |
538 » ret = (xmlChar *) xmlRealloc(ret, | 1345 » temp = (xmlChar *) xmlRealloc(ret, |
539 (max + 1) * sizeof(xmlChar)); | 1346 (max + 1) * sizeof(xmlChar)); |
540 » if (ret == NULL) { | 1347 » if (temp == NULL) { |
541 » » xmlGenericError(xmlGenericErrorContext, | 1348 » » » xmlGenericError(xmlGenericErrorContext, |
542 » » » "xmlSaveUri: out of memory\n"); | 1349 » » » » "xmlSaveUri: out of memory\n"); |
543 » » return(NULL); | 1350 xmlFree(ret); |
544 » } | 1351 » » » return(NULL); |
| 1352 » » } |
| 1353 » » ret = temp; |
545 } | 1354 } |
546 ret[len++] = '#'; | 1355 ret[len++] = '#'; |
547 p = uri->fragment; | 1356 p = uri->fragment; |
548 while (*p != 0) { | 1357 while (*p != 0) { |
549 if (len + 3 >= max) { | 1358 if (len + 3 >= max) { |
550 max *= 2; | 1359 max *= 2; |
551 » » ret = (xmlChar *) xmlRealloc(ret, | 1360 » » temp = (xmlChar *) xmlRealloc(ret, |
552 (max + 1) * sizeof(xmlChar)); | 1361 (max + 1) * sizeof(xmlChar)); |
553 » » if (ret == NULL) { | 1362 » » if (temp == NULL) { |
554 » » xmlGenericError(xmlGenericErrorContext, | 1363 » » » xmlGenericError(xmlGenericErrorContext, |
555 » » » "xmlSaveUri: out of memory\n"); | 1364 » » » » "xmlSaveUri: out of memory\n"); |
556 » » return(NULL); | 1365 xmlFree(ret); |
557 » » } | 1366 » » » return(NULL); |
| 1367 » » } |
| 1368 » » ret = temp; |
558 } | 1369 } |
559 if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) | 1370 if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) |
560 ret[len++] = *p++; | 1371 ret[len++] = *p++; |
561 else { | 1372 else { |
562 int val = *(unsigned char *)p++; | 1373 int val = *(unsigned char *)p++; |
563 int hi = val / 0x10, lo = val % 0x10; | 1374 int hi = val / 0x10, lo = val % 0x10; |
564 ret[len++] = '%'; | 1375 ret[len++] = '%'; |
565 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); | 1376 ret[len++] = hi + (hi > 9? 'A'-10 : '0'); |
566 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); | 1377 ret[len++] = lo + (lo > 9? 'A'-10 : '0'); |
567 } | 1378 } |
568 } | 1379 } |
569 } | 1380 } |
570 if (len >= max) { | 1381 if (len >= max) { |
571 max *= 2; | 1382 max *= 2; |
572 » ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); | 1383 » temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
573 » if (ret == NULL) { | 1384 » if (temp == NULL) { |
574 » xmlGenericError(xmlGenericErrorContext, | 1385 » » » xmlGenericError(xmlGenericErrorContext, |
575 » » "xmlSaveUri: out of memory\n"); | 1386 » » » » "xmlSaveUri: out of memory\n"); |
576 » return(NULL); | 1387 xmlFree(ret); |
577 » } | 1388 » » » return(NULL); |
| 1389 » » } |
| 1390 » » ret = temp; |
578 } | 1391 } |
579 ret[len++] = 0; | 1392 ret[len] = 0; |
580 return(ret); | 1393 return(ret); |
581 } | 1394 } |
582 | 1395 |
583 /** | 1396 /** |
584 * xmlPrintURI: | 1397 * xmlPrintURI: |
585 * @stream: a FILE* for the output | 1398 * @stream: a FILE* for the output |
586 * @uri: pointer to an xmlURI | 1399 * @uri: pointer to an xmlURI |
587 * | 1400 * |
588 * Prints the URI in the stream @stream. | 1401 * Prints the URI in the stream @stream. |
589 */ | 1402 */ |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
921 * @list: exception list string of chars not to escape | 1734 * @list: exception list string of chars not to escape |
922 * | 1735 * |
923 * This routine escapes a string to hex, ignoring reserved characters (a-z) | 1736 * This routine escapes a string to hex, ignoring reserved characters (a-z) |
924 * and the characters in the exception list. | 1737 * and the characters in the exception list. |
925 * | 1738 * |
926 * Returns a new escaped string or NULL in case of error. | 1739 * Returns a new escaped string or NULL in case of error. |
927 */ | 1740 */ |
928 xmlChar * | 1741 xmlChar * |
929 xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) { | 1742 xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) { |
930 xmlChar *ret, ch; | 1743 xmlChar *ret, ch; |
| 1744 xmlChar *temp; |
931 const xmlChar *in; | 1745 const xmlChar *in; |
932 | 1746 |
933 unsigned int len, out; | 1747 unsigned int len, out; |
934 | 1748 |
935 if (str == NULL) | 1749 if (str == NULL) |
936 return(NULL); | 1750 return(NULL); |
937 if (str[0] == 0) | 1751 if (str[0] == 0) |
938 return(xmlStrdup(str)); | 1752 return(xmlStrdup(str)); |
939 len = xmlStrlen(str); | 1753 len = xmlStrlen(str); |
940 if (!(len > 0)) return(NULL); | 1754 if (!(len > 0)) return(NULL); |
941 | 1755 |
942 len += 20; | 1756 len += 20; |
943 ret = (xmlChar *) xmlMallocAtomic(len); | 1757 ret = (xmlChar *) xmlMallocAtomic(len); |
944 if (ret == NULL) { | 1758 if (ret == NULL) { |
945 xmlGenericError(xmlGenericErrorContext, | 1759 xmlGenericError(xmlGenericErrorContext, |
946 "xmlURIEscapeStr: out of memory\n"); | 1760 "xmlURIEscapeStr: out of memory\n"); |
947 return(NULL); | 1761 return(NULL); |
948 } | 1762 } |
949 in = (const xmlChar *) str; | 1763 in = (const xmlChar *) str; |
950 out = 0; | 1764 out = 0; |
951 while(*in != 0) { | 1765 while(*in != 0) { |
952 if (len - out <= 3) { | 1766 if (len - out <= 3) { |
953 len += 20; | 1767 len += 20; |
954 » ret = (xmlChar *) xmlRealloc(ret, len); | 1768 » temp = (xmlChar *) xmlRealloc(ret, len); |
955 » if (ret == NULL) { | 1769 » if (temp == NULL) { |
956 xmlGenericError(xmlGenericErrorContext, | 1770 xmlGenericError(xmlGenericErrorContext, |
957 "xmlURIEscapeStr: out of memory\n"); | 1771 "xmlURIEscapeStr: out of memory\n"); |
| 1772 xmlFree(ret); |
958 return(NULL); | 1773 return(NULL); |
959 } | 1774 } |
| 1775 ret = temp; |
960 } | 1776 } |
961 | 1777 |
962 ch = *in; | 1778 ch = *in; |
963 | 1779 |
964 if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!xmlStrchr(list, ch))) { | 1780 if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!xmlStrchr(list, ch))) { |
965 unsigned char val; | 1781 unsigned char val; |
966 ret[out++] = '%'; | 1782 ret[out++] = '%'; |
967 val = ch >> 4; | 1783 val = ch >> 4; |
968 if (val <= 9) | 1784 if (val <= 9) |
969 ret[out++] = '0' + val; | 1785 ret[out++] = '0' + val; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1002 xmlChar * | 1818 xmlChar * |
1003 xmlURIEscape(const xmlChar * str) | 1819 xmlURIEscape(const xmlChar * str) |
1004 { | 1820 { |
1005 xmlChar *ret, *segment = NULL; | 1821 xmlChar *ret, *segment = NULL; |
1006 xmlURIPtr uri; | 1822 xmlURIPtr uri; |
1007 int ret2; | 1823 int ret2; |
1008 | 1824 |
1009 #define NULLCHK(p) if(!p) { \ | 1825 #define NULLCHK(p) if(!p) { \ |
1010 xmlGenericError(xmlGenericErrorContext, \ | 1826 xmlGenericError(xmlGenericErrorContext, \ |
1011 "xmlURIEscape: out of memory\n"); \ | 1827 "xmlURIEscape: out of memory\n"); \ |
1012 return NULL; } | 1828 xmlFreeURI(uri); \ |
| 1829 return NULL; } \ |
1013 | 1830 |
1014 if (str == NULL) | 1831 if (str == NULL) |
1015 return (NULL); | 1832 return (NULL); |
1016 | 1833 |
1017 uri = xmlCreateURI(); | 1834 uri = xmlCreateURI(); |
1018 if (uri != NULL) { | 1835 if (uri != NULL) { |
1019 /* | 1836 /* |
1020 * Allow escaping errors in the unescaped form | 1837 * Allow escaping errors in the unescaped form |
1021 */ | 1838 */ |
1022 uri->cleanup = 1; | 1839 uri->cleanup = 1; |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1055 ret = xmlStrcat(ret,BAD_CAST "//"); | 1872 ret = xmlStrcat(ret,BAD_CAST "//"); |
1056 ret = xmlStrcat(ret, segment); | 1873 ret = xmlStrcat(ret, segment); |
1057 ret = xmlStrcat(ret, BAD_CAST "@"); | 1874 ret = xmlStrcat(ret, BAD_CAST "@"); |
1058 xmlFree(segment); | 1875 xmlFree(segment); |
1059 } | 1876 } |
1060 | 1877 |
1061 if (uri->server) { | 1878 if (uri->server) { |
1062 segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@"); | 1879 segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@"); |
1063 NULLCHK(segment) | 1880 NULLCHK(segment) |
1064 if (uri->user == NULL) | 1881 if (uri->user == NULL) |
1065 »» ret = xmlStrcat(ret, BAD_CAST "//"); | 1882 » » ret = xmlStrcat(ret, BAD_CAST "//"); |
1066 ret = xmlStrcat(ret, segment); | 1883 ret = xmlStrcat(ret, segment); |
1067 xmlFree(segment); | 1884 xmlFree(segment); |
1068 } | 1885 } |
1069 | 1886 |
1070 if (uri->port) { | 1887 if (uri->port) { |
1071 xmlChar port[10]; | 1888 xmlChar port[10]; |
1072 | 1889 |
1073 snprintf((char *) port, 10, "%d", uri->port); | 1890 snprintf((char *) port, 10, "%d", uri->port); |
1074 ret = xmlStrcat(ret, BAD_CAST ":"); | 1891 ret = xmlStrcat(ret, BAD_CAST ":"); |
1075 ret = xmlStrcat(ret, port); | 1892 ret = xmlStrcat(ret, port); |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 } | 1929 } |
1113 | 1930 |
1114 xmlFreeURI(uri); | 1931 xmlFreeURI(uri); |
1115 #undef NULLCHK | 1932 #undef NULLCHK |
1116 | 1933 |
1117 return (ret); | 1934 return (ret); |
1118 } | 1935 } |
1119 | 1936 |
1120 /************************************************************************ | 1937 /************************************************************************ |
1121 * * | 1938 * * |
1122 * Escaped URI parsing * | |
1123 * * | |
1124 ************************************************************************/ | |
1125 | |
1126 /** | |
1127 * xmlParseURIFragment: | |
1128 * @uri: pointer to an URI structure | |
1129 * @str: pointer to the string to analyze | |
1130 * | |
1131 * Parse an URI fragment string and fills in the appropriate fields | |
1132 * of the @uri structure. | |
1133 * | |
1134 * fragment = *uric | |
1135 * | |
1136 * Returns 0 or the error code | |
1137 */ | |
1138 static int | |
1139 xmlParseURIFragment(xmlURIPtr uri, const char **str) | |
1140 { | |
1141 const char *cur; | |
1142 | |
1143 if (str == NULL) | |
1144 return (-1); | |
1145 | |
1146 cur = *str; | |
1147 | |
1148 while (IS_URIC(cur) || IS_UNWISE(cur)) | |
1149 NEXT(cur); | |
1150 if (uri != NULL) { | |
1151 if (uri->fragment != NULL) | |
1152 xmlFree(uri->fragment); | |
1153 if (uri->cleanup & 2) | |
1154 uri->fragment = STRNDUP(*str, cur - *str); | |
1155 else | |
1156 uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL); | |
1157 } | |
1158 *str = cur; | |
1159 return (0); | |
1160 } | |
1161 | |
1162 /** | |
1163 * xmlParseURIQuery: | |
1164 * @uri: pointer to an URI structure | |
1165 * @str: pointer to the string to analyze | |
1166 * | |
1167 * Parse the query part of an URI | |
1168 * | |
1169 * query = *uric | |
1170 * | |
1171 * Returns 0 or the error code | |
1172 */ | |
1173 static int | |
1174 xmlParseURIQuery(xmlURIPtr uri, const char **str) | |
1175 { | |
1176 const char *cur; | |
1177 | |
1178 if (str == NULL) | |
1179 return (-1); | |
1180 | |
1181 cur = *str; | |
1182 | |
1183 while ((IS_URIC(cur)) || | |
1184 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) | |
1185 NEXT(cur); | |
1186 if (uri != NULL) { | |
1187 if (uri->query != NULL) | |
1188 xmlFree(uri->query); | |
1189 if (uri->cleanup & 2) | |
1190 uri->query = STRNDUP(*str, cur - *str); | |
1191 else | |
1192 uri->query = xmlURIUnescapeString(*str, cur - *str, NULL); | |
1193 | |
1194 /* Save the raw bytes of the query as well. | |
1195 * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114 | |
1196 */ | |
1197 if (uri->query_raw != NULL) | |
1198 xmlFree (uri->query_raw); | |
1199 uri->query_raw = STRNDUP (*str, cur - *str); | |
1200 } | |
1201 *str = cur; | |
1202 return (0); | |
1203 } | |
1204 | |
1205 /** | |
1206 * xmlParseURIScheme: | |
1207 * @uri: pointer to an URI structure | |
1208 * @str: pointer to the string to analyze | |
1209 * | |
1210 * Parse an URI scheme | |
1211 * | |
1212 * scheme = alpha *( alpha | digit | "+" | "-" | "." ) | |
1213 * | |
1214 * Returns 0 or the error code | |
1215 */ | |
1216 static int | |
1217 xmlParseURIScheme(xmlURIPtr uri, const char **str) { | |
1218 const char *cur; | |
1219 | |
1220 if (str == NULL) | |
1221 return(-1); | |
1222 | |
1223 cur = *str; | |
1224 if (!IS_ALPHA(*cur)) | |
1225 return(2); | |
1226 cur++; | |
1227 while (IS_SCHEME(*cur)) cur++; | |
1228 if (uri != NULL) { | |
1229 if (uri->scheme != NULL) xmlFree(uri->scheme); | |
1230 uri->scheme = STRNDUP(*str, cur - *str); | |
1231 } | |
1232 *str = cur; | |
1233 return(0); | |
1234 } | |
1235 | |
1236 /** | |
1237 * xmlParseURIOpaquePart: | |
1238 * @uri: pointer to an URI structure | |
1239 * @str: pointer to the string to analyze | |
1240 * | |
1241 * Parse an URI opaque part | |
1242 * | |
1243 * opaque_part = uric_no_slash *uric | |
1244 * | |
1245 * Returns 0 or the error code | |
1246 */ | |
1247 static int | |
1248 xmlParseURIOpaquePart(xmlURIPtr uri, const char **str) | |
1249 { | |
1250 const char *cur; | |
1251 | |
1252 if (str == NULL) | |
1253 return (-1); | |
1254 | |
1255 cur = *str; | |
1256 if (!((IS_URIC_NO_SLASH(cur)) || | |
1257 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))) { | |
1258 return (3); | |
1259 } | |
1260 NEXT(cur); | |
1261 while ((IS_URIC(cur)) || | |
1262 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) | |
1263 NEXT(cur); | |
1264 if (uri != NULL) { | |
1265 if (uri->opaque != NULL) | |
1266 xmlFree(uri->opaque); | |
1267 if (uri->cleanup & 2) | |
1268 uri->opaque = STRNDUP(*str, cur - *str); | |
1269 else | |
1270 uri->opaque = xmlURIUnescapeString(*str, cur - *str, NULL); | |
1271 } | |
1272 *str = cur; | |
1273 return (0); | |
1274 } | |
1275 | |
1276 /** | |
1277 * xmlParseURIServer: | |
1278 * @uri: pointer to an URI structure | |
1279 * @str: pointer to the string to analyze | |
1280 * | |
1281 * Parse a server subpart of an URI, it's a finer grain analysis | |
1282 * of the authority part. | |
1283 * | |
1284 * server = [ [ userinfo "@" ] hostport ] | |
1285 * userinfo = *( unreserved | escaped | | |
1286 * ";" | ":" | "&" | "=" | "+" | "$" | "," ) | |
1287 * hostport = host [ ":" port ] | |
1288 * host = hostname | IPv4address | IPv6reference | |
1289 * hostname = *( domainlabel "." ) toplabel [ "." ] | |
1290 * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum | |
1291 * toplabel = alpha | alpha *( alphanum | "-" ) alphanum | |
1292 * IPv6reference = "[" IPv6address "]" | |
1293 * IPv6address = hexpart [ ":" IPv4address ] | |
1294 * IPv4address = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit | |
1295 * hexpart = hexseq | hexseq "::" [ hexseq ]| "::" [ hexseq ] | |
1296 * hexseq = hex4 *( ":" hex4) | |
1297 * hex4 = 1*4hexdig | |
1298 * port = *digit | |
1299 * | |
1300 * Returns 0 or the error code | |
1301 */ | |
1302 static int | |
1303 xmlParseURIServer(xmlURIPtr uri, const char **str) { | |
1304 const char *cur; | |
1305 const char *host, *tmp; | |
1306 const int IPV4max = 4; | |
1307 const int IPV6max = 8; | |
1308 int oct; | |
1309 | |
1310 if (str == NULL) | |
1311 return(-1); | |
1312 | |
1313 cur = *str; | |
1314 | |
1315 /* | |
1316 * is there a userinfo ? | |
1317 */ | |
1318 while (IS_USERINFO(cur)) NEXT(cur); | |
1319 if (*cur == '@') { | |
1320 if (uri != NULL) { | |
1321 if (uri->user != NULL) xmlFree(uri->user); | |
1322 if (uri->cleanup & 2) | |
1323 uri->user = STRNDUP(*str, cur - *str); | |
1324 else | |
1325 uri->user = xmlURIUnescapeString(*str, cur - *str, NULL); | |
1326 } | |
1327 cur++; | |
1328 } else { | |
1329 if (uri != NULL) { | |
1330 if (uri->user != NULL) xmlFree(uri->user); | |
1331 uri->user = NULL; | |
1332 } | |
1333 cur = *str; | |
1334 } | |
1335 /* | |
1336 * This can be empty in the case where there is no server | |
1337 */ | |
1338 host = cur; | |
1339 if (*cur == '/') { | |
1340 if (uri != NULL) { | |
1341 if (uri->authority != NULL) xmlFree(uri->authority); | |
1342 uri->authority = NULL; | |
1343 if (uri->server != NULL) xmlFree(uri->server); | |
1344 uri->server = NULL; | |
1345 uri->port = 0; | |
1346 } | |
1347 return(0); | |
1348 } | |
1349 /* | |
1350 * host part of hostport can denote an IPV4 address, an IPV6 address | |
1351 * or an unresolved name. Check the IP first, its easier to detect | |
1352 * errors if wrong one. | |
1353 * An IPV6 address must start with a '[' and end with a ']'. | |
1354 */ | |
1355 if (*cur == '[') { | |
1356 int compress=0; | |
1357 cur++; | |
1358 for (oct = 0; oct < IPV6max; ++oct) { | |
1359 if (*cur == ':') { | |
1360 if (compress) | |
1361 return(3); /* multiple compression attempted */ | |
1362 if (!oct) { /* initial char is compression */ | |
1363 if (*++cur != ':') | |
1364 return(3); | |
1365 } | |
1366 compress = 1; /* set compression-encountered flag */ | |
1367 cur++; /* skip over the second ':' */ | |
1368 continue; | |
1369 } | |
1370 while(IS_HEX(*cur)) cur++; | |
1371 if (oct == (IPV6max-1)) | |
1372 continue; | |
1373 if (*cur != ':') | |
1374 break; | |
1375 cur++; | |
1376 } | |
1377 if ((!compress) && (oct != IPV6max)) | |
1378 return(3); | |
1379 if (*cur != ']') | |
1380 return(3); | |
1381 if (uri != NULL) { | |
1382 if (uri->server != NULL) xmlFree(uri->server); | |
1383 uri->server = (char *)xmlStrndup((xmlChar *)host+1, | |
1384 (cur-host)-1); | |
1385 } | |
1386 cur++; | |
1387 } else { | |
1388 /* | |
1389 * Not IPV6, maybe IPV4 | |
1390 */ | |
1391 for (oct = 0; oct < IPV4max; ++oct) { | |
1392 if (*cur == '.') | |
1393 return(3); /* e.g. http://.xml/ or http://18.29..30/ */ | |
1394 while(IS_DIGIT(*cur)) cur++; | |
1395 if (oct == (IPV4max-1)) | |
1396 continue; | |
1397 if (*cur != '.') | |
1398 break; | |
1399 cur++; | |
1400 } | |
1401 } | |
1402 if ((host[0] != '[') && (oct < IPV4max || (*cur == '.' && cur++) || | |
1403 IS_ALPHA(*cur))) { | |
1404 /* maybe host_name */ | |
1405 if (!IS_ALPHANUM(*cur)) | |
1406 return(4); /* e.g. http://xml.$oft */ | |
1407 do { | |
1408 do ++cur; while (IS_ALPHANUM(*cur)); | |
1409 if (*cur == '-') { | |
1410 --cur; | |
1411 if (*cur == '.') | |
1412 return(5); /* e.g. http://xml.-soft */ | |
1413 ++cur; | |
1414 continue; | |
1415 } | |
1416 if (*cur == '.') { | |
1417 --cur; | |
1418 if (*cur == '-') | |
1419 return(6); /* e.g. http://xml-.soft */ | |
1420 if (*cur == '.') | |
1421 return(7); /* e.g. http://xml..soft */ | |
1422 ++cur; | |
1423 continue; | |
1424 } | |
1425 break; | |
1426 } while (1); | |
1427 tmp = cur; | |
1428 if (tmp[-1] == '.') | |
1429 --tmp; /* e.g. http://xml.$Oft/ */ | |
1430 do --tmp; while (tmp >= host && IS_ALPHANUM(*tmp)); | |
1431 if ((++tmp == host || tmp[-1] == '.') && !IS_ALPHA(*tmp)) | |
1432 return(8); /* e.g. http://xmlsOft.0rg/ */ | |
1433 } | |
1434 if (uri != NULL) { | |
1435 if (uri->authority != NULL) xmlFree(uri->authority); | |
1436 uri->authority = NULL; | |
1437 if (host[0] != '[') { /* it's not an IPV6 addr */ | |
1438 if (uri->server != NULL) xmlFree(uri->server); | |
1439 if (uri->cleanup & 2) | |
1440 uri->server = STRNDUP(host, cur - host); | |
1441 else | |
1442 uri->server = xmlURIUnescapeString(host, cur - host, NULL); | |
1443 } | |
1444 } | |
1445 /* | |
1446 * finish by checking for a port presence. | |
1447 */ | |
1448 if (*cur == ':') { | |
1449 cur++; | |
1450 if (IS_DIGIT(*cur)) { | |
1451 if (uri != NULL) | |
1452 uri->port = 0; | |
1453 while (IS_DIGIT(*cur)) { | |
1454 if (uri != NULL) | |
1455 uri->port = uri->port * 10 + (*cur - '0'); | |
1456 cur++; | |
1457 } | |
1458 } | |
1459 } | |
1460 *str = cur; | |
1461 return(0); | |
1462 } | |
1463 | |
1464 /** | |
1465 * xmlParseURIRelSegment: | |
1466 * @uri: pointer to an URI structure | |
1467 * @str: pointer to the string to analyze | |
1468 * | |
1469 * Parse an URI relative segment | |
1470 * | |
1471 * rel_segment = 1*( unreserved | escaped | ";" | "@" | "&" | "=" | | |
1472 * "+" | "$" | "," ) | |
1473 * | |
1474 * Returns 0 or the error code | |
1475 */ | |
1476 static int | |
1477 xmlParseURIRelSegment(xmlURIPtr uri, const char **str) | |
1478 { | |
1479 const char *cur; | |
1480 | |
1481 if (str == NULL) | |
1482 return (-1); | |
1483 | |
1484 cur = *str; | |
1485 if (!((IS_SEGMENT(cur)) || | |
1486 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))) { | |
1487 return (3); | |
1488 } | |
1489 NEXT(cur); | |
1490 while ((IS_SEGMENT(cur)) || | |
1491 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) | |
1492 NEXT(cur); | |
1493 if (uri != NULL) { | |
1494 if (uri->path != NULL) | |
1495 xmlFree(uri->path); | |
1496 if (uri->cleanup & 2) | |
1497 uri->path = STRNDUP(*str, cur - *str); | |
1498 else | |
1499 uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); | |
1500 } | |
1501 *str = cur; | |
1502 return (0); | |
1503 } | |
1504 | |
1505 /** | |
1506 * xmlParseURIPathSegments: | |
1507 * @uri: pointer to an URI structure | |
1508 * @str: pointer to the string to analyze | |
1509 * @slash: should we add a leading slash | |
1510 * | |
1511 * Parse an URI set of path segments | |
1512 * | |
1513 * path_segments = segment *( "/" segment ) | |
1514 * segment = *pchar *( ";" param ) | |
1515 * param = *pchar | |
1516 * | |
1517 * Returns 0 or the error code | |
1518 */ | |
1519 static int | |
1520 xmlParseURIPathSegments(xmlURIPtr uri, const char **str, int slash) | |
1521 { | |
1522 const char *cur; | |
1523 | |
1524 if (str == NULL) | |
1525 return (-1); | |
1526 | |
1527 cur = *str; | |
1528 | |
1529 do { | |
1530 while ((IS_PCHAR(cur)) || | |
1531 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) | |
1532 NEXT(cur); | |
1533 while (*cur == ';') { | |
1534 cur++; | |
1535 while ((IS_PCHAR(cur)) || | |
1536 ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) | |
1537 NEXT(cur); | |
1538 } | |
1539 if (*cur != '/') | |
1540 break; | |
1541 cur++; | |
1542 } while (1); | |
1543 if (uri != NULL) { | |
1544 int len, len2 = 0; | |
1545 char *path; | |
1546 | |
1547 /* | |
1548 * Concat the set of path segments to the current path | |
1549 */ | |
1550 len = cur - *str; | |
1551 if (slash) | |
1552 len++; | |
1553 | |
1554 if (uri->path != NULL) { | |
1555 len2 = strlen(uri->path); | |
1556 len += len2; | |
1557 } | |
1558 path = (char *) xmlMallocAtomic(len + 1); | |
1559 if (path == NULL) { | |
1560 xmlGenericError(xmlGenericErrorContext, | |
1561 "xmlParseURIPathSegments: out of memory\n"); | |
1562 *str = cur; | |
1563 return (-1); | |
1564 } | |
1565 if (uri->path != NULL) | |
1566 memcpy(path, uri->path, len2); | |
1567 if (slash) { | |
1568 path[len2] = '/'; | |
1569 len2++; | |
1570 } | |
1571 path[len2] = 0; | |
1572 if (cur - *str > 0) { | |
1573 if (uri->cleanup & 2) { | |
1574 memcpy(&path[len2], *str, cur - *str); | |
1575 path[len2 + (cur - *str)] = 0; | |
1576 } else | |
1577 xmlURIUnescapeString(*str, cur - *str, &path[len2]); | |
1578 } | |
1579 if (uri->path != NULL) | |
1580 xmlFree(uri->path); | |
1581 uri->path = path; | |
1582 } | |
1583 *str = cur; | |
1584 return (0); | |
1585 } | |
1586 | |
1587 /** | |
1588 * xmlParseURIAuthority: | |
1589 * @uri: pointer to an URI structure | |
1590 * @str: pointer to the string to analyze | |
1591 * | |
1592 * Parse the authority part of an URI. | |
1593 * | |
1594 * authority = server | reg_name | |
1595 * server = [ [ userinfo "@" ] hostport ] | |
1596 * reg_name = 1*( unreserved | escaped | "$" | "," | ";" | ":" | | |
1597 * "@" | "&" | "=" | "+" ) | |
1598 * | |
1599 * Note : this is completely ambiguous since reg_name is allowed to | |
1600 * use the full set of chars in use by server: | |
1601 * | |
1602 * 3.2.1. Registry-based Naming Authority | |
1603 * | |
1604 * The structure of a registry-based naming authority is specific | |
1605 * to the URI scheme, but constrained to the allowed characters | |
1606 * for an authority component. | |
1607 * | |
1608 * Returns 0 or the error code | |
1609 */ | |
1610 static int | |
1611 xmlParseURIAuthority(xmlURIPtr uri, const char **str) { | |
1612 const char *cur; | |
1613 int ret; | |
1614 | |
1615 if (str == NULL) | |
1616 return(-1); | |
1617 | |
1618 cur = *str; | |
1619 | |
1620 /* | |
1621 * try first to parse it as a server string. | |
1622 */ | |
1623 ret = xmlParseURIServer(uri, str); | |
1624 if ((ret == 0) && (*str != NULL) && | |
1625 ((**str == 0) || (**str == '/') || (**str == '?'))) | |
1626 return(0); | |
1627 *str = cur; | |
1628 | |
1629 /* | |
1630 * failed, fallback to reg_name | |
1631 */ | |
1632 if (!IS_REG_NAME(cur)) { | |
1633 return(5); | |
1634 } | |
1635 NEXT(cur); | |
1636 while (IS_REG_NAME(cur)) NEXT(cur); | |
1637 if (uri != NULL) { | |
1638 if (uri->server != NULL) xmlFree(uri->server); | |
1639 uri->server = NULL; | |
1640 if (uri->user != NULL) xmlFree(uri->user); | |
1641 uri->user = NULL; | |
1642 if (uri->authority != NULL) xmlFree(uri->authority); | |
1643 if (uri->cleanup & 2) | |
1644 uri->authority = STRNDUP(*str, cur - *str); | |
1645 else | |
1646 uri->authority = xmlURIUnescapeString(*str, cur - *str, NULL); | |
1647 } | |
1648 *str = cur; | |
1649 return(0); | |
1650 } | |
1651 | |
1652 /** | |
1653 * xmlParseURIHierPart: | |
1654 * @uri: pointer to an URI structure | |
1655 * @str: pointer to the string to analyze | |
1656 * | |
1657 * Parse an URI hierarchical part | |
1658 * | |
1659 * hier_part = ( net_path | abs_path ) [ "?" query ] | |
1660 * abs_path = "/" path_segments | |
1661 * net_path = "//" authority [ abs_path ] | |
1662 * | |
1663 * Returns 0 or the error code | |
1664 */ | |
1665 static int | |
1666 xmlParseURIHierPart(xmlURIPtr uri, const char **str) { | |
1667 int ret; | |
1668 const char *cur; | |
1669 | |
1670 if (str == NULL) | |
1671 return(-1); | |
1672 | |
1673 cur = *str; | |
1674 | |
1675 if ((cur[0] == '/') && (cur[1] == '/')) { | |
1676 cur += 2; | |
1677 ret = xmlParseURIAuthority(uri, &cur); | |
1678 if (ret != 0) | |
1679 return(ret); | |
1680 if (cur[0] == '/') { | |
1681 cur++; | |
1682 ret = xmlParseURIPathSegments(uri, &cur, 1); | |
1683 } | |
1684 } else if (cur[0] == '/') { | |
1685 cur++; | |
1686 ret = xmlParseURIPathSegments(uri, &cur, 1); | |
1687 } else { | |
1688 return(4); | |
1689 } | |
1690 if (ret != 0) | |
1691 return(ret); | |
1692 if (*cur == '?') { | |
1693 cur++; | |
1694 ret = xmlParseURIQuery(uri, &cur); | |
1695 if (ret != 0) | |
1696 return(ret); | |
1697 } | |
1698 *str = cur; | |
1699 return(0); | |
1700 } | |
1701 | |
1702 /** | |
1703 * xmlParseAbsoluteURI: | |
1704 * @uri: pointer to an URI structure | |
1705 * @str: pointer to the string to analyze | |
1706 * | |
1707 * Parse an URI reference string and fills in the appropriate fields | |
1708 * of the @uri structure | |
1709 * | |
1710 * absoluteURI = scheme ":" ( hier_part | opaque_part ) | |
1711 * | |
1712 * Returns 0 or the error code | |
1713 */ | |
1714 static int | |
1715 xmlParseAbsoluteURI(xmlURIPtr uri, const char **str) { | |
1716 int ret; | |
1717 const char *cur; | |
1718 | |
1719 if (str == NULL) | |
1720 return(-1); | |
1721 | |
1722 cur = *str; | |
1723 | |
1724 ret = xmlParseURIScheme(uri, str); | |
1725 if (ret != 0) return(ret); | |
1726 if (**str != ':') { | |
1727 *str = cur; | |
1728 return(1); | |
1729 } | |
1730 (*str)++; | |
1731 if (**str == '/') | |
1732 return(xmlParseURIHierPart(uri, str)); | |
1733 return(xmlParseURIOpaquePart(uri, str)); | |
1734 } | |
1735 | |
1736 /** | |
1737 * xmlParseRelativeURI: | |
1738 * @uri: pointer to an URI structure | |
1739 * @str: pointer to the string to analyze | |
1740 * | |
1741 * Parse an relative URI string and fills in the appropriate fields | |
1742 * of the @uri structure | |
1743 * | |
1744 * relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] | |
1745 * abs_path = "/" path_segments | |
1746 * net_path = "//" authority [ abs_path ] | |
1747 * rel_path = rel_segment [ abs_path ] | |
1748 * | |
1749 * Returns 0 or the error code | |
1750 */ | |
1751 static int | |
1752 xmlParseRelativeURI(xmlURIPtr uri, const char **str) { | |
1753 int ret = 0; | |
1754 const char *cur; | |
1755 | |
1756 if (str == NULL) | |
1757 return(-1); | |
1758 | |
1759 cur = *str; | |
1760 if ((cur[0] == '/') && (cur[1] == '/')) { | |
1761 cur += 2; | |
1762 ret = xmlParseURIAuthority(uri, &cur); | |
1763 if (ret != 0) | |
1764 return(ret); | |
1765 if (cur[0] == '/') { | |
1766 cur++; | |
1767 ret = xmlParseURIPathSegments(uri, &cur, 1); | |
1768 } | |
1769 } else if (cur[0] == '/') { | |
1770 cur++; | |
1771 ret = xmlParseURIPathSegments(uri, &cur, 1); | |
1772 } else if (cur[0] != '#' && cur[0] != '?') { | |
1773 ret = xmlParseURIRelSegment(uri, &cur); | |
1774 if (ret != 0) | |
1775 return(ret); | |
1776 if (cur[0] == '/') { | |
1777 cur++; | |
1778 ret = xmlParseURIPathSegments(uri, &cur, 1); | |
1779 } | |
1780 } | |
1781 if (ret != 0) | |
1782 return(ret); | |
1783 if (*cur == '?') { | |
1784 cur++; | |
1785 ret = xmlParseURIQuery(uri, &cur); | |
1786 if (ret != 0) | |
1787 return(ret); | |
1788 } | |
1789 *str = cur; | |
1790 return(ret); | |
1791 } | |
1792 | |
1793 /** | |
1794 * xmlParseURIReference: | |
1795 * @uri: pointer to an URI structure | |
1796 * @str: the string to analyze | |
1797 * | |
1798 * Parse an URI reference string and fills in the appropriate fields | |
1799 * of the @uri structure | |
1800 * | |
1801 * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] | |
1802 * | |
1803 * Returns 0 or the error code | |
1804 */ | |
1805 int | |
1806 xmlParseURIReference(xmlURIPtr uri, const char *str) { | |
1807 int ret; | |
1808 const char *tmp = str; | |
1809 | |
1810 if (str == NULL) | |
1811 return(-1); | |
1812 xmlCleanURI(uri); | |
1813 | |
1814 /* | |
1815 * Try first to parse absolute refs, then fallback to relative if | |
1816 * it fails. | |
1817 */ | |
1818 ret = xmlParseAbsoluteURI(uri, &str); | |
1819 if (ret != 0) { | |
1820 xmlCleanURI(uri); | |
1821 str = tmp; | |
1822 ret = xmlParseRelativeURI(uri, &str); | |
1823 } | |
1824 if (ret != 0) { | |
1825 xmlCleanURI(uri); | |
1826 return(ret); | |
1827 } | |
1828 | |
1829 if (*str == '#') { | |
1830 str++; | |
1831 ret = xmlParseURIFragment(uri, &str); | |
1832 if (ret != 0) return(ret); | |
1833 } | |
1834 if (*str != 0) { | |
1835 xmlCleanURI(uri); | |
1836 return(1); | |
1837 } | |
1838 return(0); | |
1839 } | |
1840 | |
1841 /** | |
1842 * xmlParseURI: | |
1843 * @str: the URI string to analyze | |
1844 * | |
1845 * Parse an URI | |
1846 * | |
1847 * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] | |
1848 * | |
1849 * Returns a newly built xmlURIPtr or NULL in case of error | |
1850 */ | |
1851 xmlURIPtr | |
1852 xmlParseURI(const char *str) { | |
1853 xmlURIPtr uri; | |
1854 int ret; | |
1855 | |
1856 if (str == NULL) | |
1857 return(NULL); | |
1858 uri = xmlCreateURI(); | |
1859 if (uri != NULL) { | |
1860 ret = xmlParseURIReference(uri, str); | |
1861 if (ret) { | |
1862 xmlFreeURI(uri); | |
1863 return(NULL); | |
1864 } | |
1865 } | |
1866 return(uri); | |
1867 } | |
1868 | |
1869 /** | |
1870 * xmlParseURIRaw: | |
1871 * @str: the URI string to analyze | |
1872 * @raw: if 1 unescaping of URI pieces are disabled | |
1873 * | |
1874 * Parse an URI but allows to keep intact the original fragments. | |
1875 * | |
1876 * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] | |
1877 * | |
1878 * Returns a newly built xmlURIPtr or NULL in case of error | |
1879 */ | |
1880 xmlURIPtr | |
1881 xmlParseURIRaw(const char *str, int raw) { | |
1882 xmlURIPtr uri; | |
1883 int ret; | |
1884 | |
1885 if (str == NULL) | |
1886 return(NULL); | |
1887 uri = xmlCreateURI(); | |
1888 if (uri != NULL) { | |
1889 if (raw) { | |
1890 uri->cleanup |= 2; | |
1891 } | |
1892 ret = xmlParseURIReference(uri, str); | |
1893 if (ret) { | |
1894 xmlFreeURI(uri); | |
1895 return(NULL); | |
1896 } | |
1897 } | |
1898 return(uri); | |
1899 } | |
1900 | |
1901 /************************************************************************ | |
1902 * * | |
1903 * Public functions * | 1939 * Public functions * |
1904 * * | 1940 * * |
1905 ************************************************************************/ | 1941 ************************************************************************/ |
1906 | 1942 |
1907 /** | 1943 /** |
1908 * xmlBuildURI: | 1944 * xmlBuildURI: |
1909 * @URI: the URI instance found in the document | 1945 * @URI: the URI instance found in the document |
1910 * @base: the base value | 1946 * @base: the base value |
1911 * | 1947 * |
1912 * Computes he final URI of the reference done by checking that | 1948 * Computes he final URI of the reference done by checking that |
(...skipping 675 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2588 } | 2624 } |
2589 #endif | 2625 #endif |
2590 memset(&temp, 0, sizeof(temp)); | 2626 memset(&temp, 0, sizeof(temp)); |
2591 temp.path = (char *) cal; | 2627 temp.path = (char *) cal; |
2592 ret = xmlSaveUri(&temp); | 2628 ret = xmlSaveUri(&temp); |
2593 xmlFree(cal); | 2629 xmlFree(cal); |
2594 return(ret); | 2630 return(ret); |
2595 } | 2631 } |
2596 #define bottom_uri | 2632 #define bottom_uri |
2597 #include "elfgcchack.h" | 2633 #include "elfgcchack.h" |
OLD | NEW |