Index: third_party/libxml/uri.c |
diff --git a/third_party/libxml/uri.c b/third_party/libxml/uri.c |
index fafd11258a174e9be785afc7cf06918e4c6a3950..950e177bd62ce068c729f5f130768f5429ddbf53 100644 |
--- a/third_party/libxml/uri.c |
+++ b/third_party/libxml/uri.c |
@@ -1,7 +1,7 @@ |
/** |
* uri.c: set of generic URI related routines |
* |
- * Reference: RFCs 2396, 2732 and 2373 |
+ * Reference: RFCs 3986, 2732 and 2373 |
* |
* See Copyright for the status of this software. |
* |
@@ -18,14 +18,10 @@ |
#include <libxml/globals.h> |
#include <libxml/xmlerror.h> |
-/************************************************************************ |
- * * |
- * Macros to differentiate various character type * |
- * directly extracted from RFC 2396 * |
- * * |
- ************************************************************************/ |
+static void xmlCleanURI(xmlURIPtr uri); |
/* |
+ * Old rule from 2396 used in legacy handling code |
* alpha = lowalpha | upalpha |
*/ |
#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x)) |
@@ -61,31 +57,30 @@ |
#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x)) |
/* |
- * hex = digit | "A" | "B" | "C" | "D" | "E" | "F" | |
- * "a" | "b" | "c" | "d" | "e" | "f" |
- */ |
- |
-#define IS_HEX(x) ((IS_DIGIT(x)) || (((x) >= 'a') && ((x) <= 'f')) || \ |
- (((x) >= 'A') && ((x) <= 'F'))) |
- |
-/* |
* mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" |
*/ |
-#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') || \ |
- ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') || \ |
+#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') || \ |
+ ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') || \ |
((x) == '(') || ((x) == ')')) |
+/* |
+ * unwise = "{" | "}" | "|" | "\" | "^" | "`" |
+ */ |
+#define IS_UNWISE(p) \ |
+ (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \ |
+ ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \ |
+ ((*(p) == ']')) || ((*(p) == '`'))) |
/* |
* reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," | |
- * "[" | "]" |
+ * "[" | "]" |
*/ |
-#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \ |
- ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \ |
- ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \ |
- ((x) == ']')) |
+#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \ |
+ ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \ |
+ ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \ |
+ ((x) == ']')) |
/* |
* unreserved = alphanum | mark |
@@ -94,98 +89,877 @@ |
#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x)) |
/* |
- * escaped = "%" hex hex |
+ * Skip to next pointer char, handle escaped sequences |
*/ |
-#define IS_ESCAPED(p) ((*(p) == '%') && (IS_HEX((p)[1])) && \ |
- (IS_HEX((p)[2]))) |
+#define NEXT(p) ((*p == '%')? p += 3 : p++) |
/* |
- * uric_no_slash = unreserved | escaped | ";" | "?" | ":" | "@" | |
- * "&" | "=" | "+" | "$" | "," |
+ * Productions from the spec. |
+ * |
+ * authority = server | reg_name |
+ * reg_name = 1*( unreserved | escaped | "$" | "," | |
+ * ";" | ":" | "@" | "&" | "=" | "+" ) |
+ * |
+ * path = [ abs_path | opaque_part ] |
*/ |
-#define IS_URIC_NO_SLASH(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) ||\ |
- ((*(p) == ';')) || ((*(p) == '?')) || ((*(p) == ':')) ||\ |
- ((*(p) == '@')) || ((*(p) == '&')) || ((*(p) == '=')) ||\ |
- ((*(p) == '+')) || ((*(p) == '$')) || ((*(p) == ','))) |
+ |
+#define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n)) |
+ |
+/************************************************************************ |
+ * * |
+ * RFC 3986 parser * |
+ * * |
+ ************************************************************************/ |
+ |
+#define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9')) |
+#define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) || \ |
+ ((*(p) >= 'A') && (*(p) <= 'Z'))) |
+#define ISA_HEXDIG(p) \ |
+ (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) || \ |
+ ((*(p) >= 'A') && (*(p) <= 'F'))) |
/* |
- * pchar = unreserved | escaped | ":" | "@" | "&" | "=" | "+" | "$" | "," |
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" |
+ * / "*" / "+" / "," / ";" / "=" |
*/ |
-#define IS_PCHAR(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ |
- ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||\ |
- ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||\ |
- ((*(p) == ','))) |
+#define ISA_SUB_DELIM(p) \ |
+ (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) || \ |
+ ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) || \ |
+ ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) || \ |
+ ((*(p) == '='))) |
/* |
- * rel_segment = 1*( unreserved | escaped | |
- * ";" | "@" | "&" | "=" | "+" | "$" | "," ) |
+ * gen-delims = ":" / "/" / "?" / "#" / "[" / "]" / "@" |
*/ |
+#define ISA_GEN_DELIM(p) \ |
+ (((*(p) == ':')) || ((*(p) == '/')) || ((*(p) == '?')) || \ |
+ ((*(p) == '#')) || ((*(p) == '[')) || ((*(p) == ']')) || \ |
+ ((*(p) == '@'))) |
-#define IS_SEGMENT(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ |
- ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || \ |
- ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \ |
- ((*(p) == ','))) |
+/* |
+ * reserved = gen-delims / sub-delims |
+ */ |
+#define ISA_RESERVED(p) (ISA_GEN_DELIM(p) || (ISA_SUB_DELIM(p))) |
/* |
- * scheme = alpha *( alpha | digit | "+" | "-" | "." ) |
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" |
*/ |
+#define ISA_UNRESERVED(p) \ |
+ ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) || \ |
+ ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~'))) |
-#define IS_SCHEME(x) ((IS_ALPHA(x)) || (IS_DIGIT(x)) || \ |
- ((x) == '+') || ((x) == '-') || ((x) == '.')) |
+/* |
+ * pct-encoded = "%" HEXDIG HEXDIG |
+ */ |
+#define ISA_PCT_ENCODED(p) \ |
+ ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2))) |
/* |
- * reg_name = 1*( unreserved | escaped | "$" | "," | |
- * ";" | ":" | "@" | "&" | "=" | "+" ) |
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" |
+ */ |
+#define ISA_PCHAR(p) \ |
+ (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) || \ |
+ ((*(p) == ':')) || ((*(p) == '@'))) |
+ |
+/** |
+ * xmlParse3986Scheme: |
+ * @uri: pointer to an URI structure |
+ * @str: pointer to the string to analyze |
+ * |
+ * Parse an URI scheme |
+ * |
+ * ALPHA *( ALPHA / DIGIT / "+" / "-" / "." ) |
+ * |
+ * Returns 0 or the error code |
*/ |
+static int |
+xmlParse3986Scheme(xmlURIPtr uri, const char **str) { |
+ const char *cur; |
-#define IS_REG_NAME(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ |
- ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || \ |
- ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) || \ |
- ((*(p) == '=')) || ((*(p) == '+'))) |
+ if (str == NULL) |
+ return(-1); |
-/* |
- * userinfo = *( unreserved | escaped | ";" | ":" | "&" | "=" | |
- * "+" | "$" | "," ) |
+ cur = *str; |
+ if (!ISA_ALPHA(cur)) |
+ return(2); |
+ cur++; |
+ while (ISA_ALPHA(cur) || ISA_DIGIT(cur) || |
+ (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++; |
+ if (uri != NULL) { |
+ if (uri->scheme != NULL) xmlFree(uri->scheme); |
+ uri->scheme = STRNDUP(*str, cur - *str); |
+ } |
+ *str = cur; |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParse3986Fragment: |
+ * @uri: pointer to an URI structure |
+ * @str: pointer to the string to analyze |
+ * |
+ * Parse the query part of an URI |
+ * |
+ * fragment = *( pchar / "/" / "?" ) |
+ * NOTE: the strict syntax as defined by 3986 does not allow '[' and ']' |
+ * in the fragment identifier but this is used very broadly for |
+ * xpointer scheme selection, so we are allowing it here to not break |
+ * for example all the DocBook processing chains. |
+ * |
+ * Returns 0 or the error code |
*/ |
-#define IS_USERINFO(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ |
- ((*(p) == ';')) || ((*(p) == ':')) || ((*(p) == '&')) || \ |
- ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) || \ |
- ((*(p) == ','))) |
+static int |
+xmlParse3986Fragment(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur; |
-/* |
- * uric = reserved | unreserved | escaped |
+ if (str == NULL) |
+ return (-1); |
+ |
+ cur = *str; |
+ |
+ while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || |
+ (*cur == '[') || (*cur == ']') || |
+ ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) |
+ NEXT(cur); |
+ if (uri != NULL) { |
+ if (uri->fragment != NULL) |
+ xmlFree(uri->fragment); |
+ if (uri->cleanup & 2) |
+ uri->fragment = STRNDUP(*str, cur - *str); |
+ else |
+ uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL); |
+ } |
+ *str = cur; |
+ return (0); |
+} |
+ |
+/** |
+ * xmlParse3986Query: |
+ * @uri: pointer to an URI structure |
+ * @str: pointer to the string to analyze |
+ * |
+ * Parse the query part of an URI |
+ * |
+ * query = *uric |
+ * |
+ * Returns 0 or the error code |
*/ |
+static int |
+xmlParse3986Query(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur; |
-#define IS_URIC(p) ((IS_UNRESERVED(*(p))) || (IS_ESCAPED(p)) || \ |
- (IS_RESERVED(*(p)))) |
+ if (str == NULL) |
+ return (-1); |
-/* |
-* unwise = "{" | "}" | "|" | "\" | "^" | "`" |
-*/ |
+ cur = *str; |
-#define IS_UNWISE(p) \ |
- (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) || \ |
- ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) || \ |
- ((*(p) == ']')) || ((*(p) == '`'))) |
+ while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') || |
+ ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) |
+ NEXT(cur); |
+ if (uri != NULL) { |
+ if (uri->query != NULL) |
+ xmlFree(uri->query); |
+ if (uri->cleanup & 2) |
+ uri->query = STRNDUP(*str, cur - *str); |
+ else |
+ uri->query = xmlURIUnescapeString(*str, cur - *str, NULL); |
-/* |
- * Skip to next pointer char, handle escaped sequences |
+ /* Save the raw bytes of the query as well. |
+ * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114 |
+ */ |
+ if (uri->query_raw != NULL) |
+ xmlFree (uri->query_raw); |
+ uri->query_raw = STRNDUP (*str, cur - *str); |
+ } |
+ *str = cur; |
+ return (0); |
+} |
+ |
+/** |
+ * xmlParse3986Port: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse a port part and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * port = *DIGIT |
+ * |
+ * Returns 0 or the error code |
*/ |
+static int |
+xmlParse3986Port(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur = *str; |
-#define NEXT(p) ((*p == '%')? p += 3 : p++) |
+ if (ISA_DIGIT(cur)) { |
+ if (uri != NULL) |
+ uri->port = 0; |
+ while (ISA_DIGIT(cur)) { |
+ if (uri != NULL) |
+ uri->port = uri->port * 10 + (*cur - '0'); |
+ cur++; |
+ } |
+ *str = cur; |
+ return(0); |
+ } |
+ return(1); |
+} |
-/* |
- * Productions from the spec. |
+/** |
+ * xmlParse3986Userinfo: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
* |
- * authority = server | reg_name |
- * reg_name = 1*( unreserved | escaped | "$" | "," | |
- * ";" | ":" | "@" | "&" | "=" | "+" ) |
+ * Parse an user informations part and fills in the appropriate fields |
+ * of the @uri structure |
* |
- * path = [ abs_path | opaque_part ] |
+ * userinfo = *( unreserved / pct-encoded / sub-delims / ":" ) |
+ * |
+ * Returns 0 or the error code |
*/ |
+static int |
+xmlParse3986Userinfo(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur; |
-#define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n)) |
+ cur = *str; |
+ while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || |
+ ISA_SUB_DELIM(cur) || (*cur == ':')) |
+ NEXT(cur); |
+ if (*cur == '@') { |
+ if (uri != NULL) { |
+ if (uri->user != NULL) xmlFree(uri->user); |
+ if (uri->cleanup & 2) |
+ uri->user = STRNDUP(*str, cur - *str); |
+ else |
+ uri->user = xmlURIUnescapeString(*str, cur - *str, NULL); |
+ } |
+ *str = cur; |
+ return(0); |
+ } |
+ return(1); |
+} |
+ |
+/** |
+ * xmlParse3986DecOctet: |
+ * @str: the string to analyze |
+ * |
+ * dec-octet = DIGIT ; 0-9 |
+ * / %x31-39 DIGIT ; 10-99 |
+ * / "1" 2DIGIT ; 100-199 |
+ * / "2" %x30-34 DIGIT ; 200-249 |
+ * / "25" %x30-35 ; 250-255 |
+ * |
+ * Skip a dec-octet. |
+ * |
+ * Returns 0 if found and skipped, 1 otherwise |
+ */ |
+static int |
+xmlParse3986DecOctet(const char **str) { |
+ const char *cur = *str; |
+ |
+ if (!(ISA_DIGIT(cur))) |
+ return(1); |
+ if (!ISA_DIGIT(cur+1)) |
+ cur++; |
+ else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur+2))) |
+ cur += 2; |
+ else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2))) |
+ cur += 3; |
+ else if ((*cur == '2') && (*(cur + 1) >= '0') && |
+ (*(cur + 1) <= '4') && (ISA_DIGIT(cur + 2))) |
+ cur += 3; |
+ else if ((*cur == '2') && (*(cur + 1) == '5') && |
+ (*(cur + 2) >= '0') && (*(cur + 1) <= '5')) |
+ cur += 3; |
+ else |
+ return(1); |
+ *str = cur; |
+ return(0); |
+} |
+/** |
+ * xmlParse3986Host: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an host part and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * host = IP-literal / IPv4address / reg-name |
+ * IP-literal = "[" ( IPv6address / IPvFuture ) "]" |
+ * IPv4address = dec-octet "." dec-octet "." dec-octet "." dec-octet |
+ * reg-name = *( unreserved / pct-encoded / sub-delims ) |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986Host(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur = *str; |
+ const char *host; |
+ |
+ host = cur; |
+ /* |
+ * IPv6 and future adressing scheme are enclosed between brackets |
+ */ |
+ if (*cur == '[') { |
+ cur++; |
+ while ((*cur != ']') && (*cur != 0)) |
+ cur++; |
+ if (*cur != ']') |
+ return(1); |
+ cur++; |
+ goto found; |
+ } |
+ /* |
+ * try to parse an IPv4 |
+ */ |
+ if (ISA_DIGIT(cur)) { |
+ if (xmlParse3986DecOctet(&cur) != 0) |
+ goto not_ipv4; |
+ if (*cur != '.') |
+ goto not_ipv4; |
+ cur++; |
+ if (xmlParse3986DecOctet(&cur) != 0) |
+ goto not_ipv4; |
+ if (*cur != '.') |
+ goto not_ipv4; |
+ if (xmlParse3986DecOctet(&cur) != 0) |
+ goto not_ipv4; |
+ if (*cur != '.') |
+ goto not_ipv4; |
+ if (xmlParse3986DecOctet(&cur) != 0) |
+ goto not_ipv4; |
+ goto found; |
+not_ipv4: |
+ cur = *str; |
+ } |
+ /* |
+ * then this should be a hostname which can be empty |
+ */ |
+ while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur)) |
+ NEXT(cur); |
+found: |
+ if (uri != NULL) { |
+ if (uri->authority != NULL) xmlFree(uri->authority); |
+ uri->authority = NULL; |
+ if (uri->server != NULL) xmlFree(uri->server); |
+ if (cur != host) { |
+ if (uri->cleanup & 2) |
+ uri->server = STRNDUP(host, cur - host); |
+ else |
+ uri->server = xmlURIUnescapeString(host, cur - host, NULL); |
+ } else |
+ uri->server = NULL; |
+ } |
+ *str = cur; |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParse3986Authority: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an authority part and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * authority = [ userinfo "@" ] host [ ":" port ] |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986Authority(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur; |
+ int ret; |
+ |
+ cur = *str; |
+ /* |
+ * try to parse an userinfo and check for the trailing @ |
+ */ |
+ ret = xmlParse3986Userinfo(uri, &cur); |
+ if ((ret != 0) || (*cur != '@')) |
+ cur = *str; |
+ else |
+ cur++; |
+ ret = xmlParse3986Host(uri, &cur); |
+ if (ret != 0) return(ret); |
+ if (*cur == ':') { |
+ cur++; |
+ ret = xmlParse3986Port(uri, &cur); |
+ if (ret != 0) return(ret); |
+ } |
+ *str = cur; |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParse3986Segment: |
+ * @str: the string to analyze |
+ * @forbid: an optional forbidden character |
+ * @empty: allow an empty segment |
+ * |
+ * Parse a segment and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * segment = *pchar |
+ * segment-nz = 1*pchar |
+ * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" ) |
+ * ; non-zero-length segment without any colon ":" |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986Segment(const char **str, char forbid, int empty) |
+{ |
+ const char *cur; |
+ |
+ cur = *str; |
+ if (!ISA_PCHAR(cur)) { |
+ if (empty) |
+ return(0); |
+ return(1); |
+ } |
+ while (ISA_PCHAR(cur) && (*cur != forbid)) |
+ NEXT(cur); |
+ *str = cur; |
+ return (0); |
+} |
+ |
+/** |
+ * xmlParse3986PathAbEmpty: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an path absolute or empty and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * path-abempty = *( "/" segment ) |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986PathAbEmpty(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur; |
+ int ret; |
+ |
+ cur = *str; |
+ |
+ while (*cur == '/') { |
+ cur++; |
+ ret = xmlParse3986Segment(&cur, 0, 1); |
+ if (ret != 0) return(ret); |
+ } |
+ if (uri != NULL) { |
+ if (uri->path != NULL) xmlFree(uri->path); |
+ if (*str != cur) { |
+ if (uri->cleanup & 2) |
+ uri->path = STRNDUP(*str, cur - *str); |
+ else |
+ uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); |
+ } else { |
+ uri->path = NULL; |
+ } |
+ } |
+ *str = cur; |
+ return (0); |
+} |
+ |
+/** |
+ * xmlParse3986PathAbsolute: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an path absolute and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * path-absolute = "/" [ segment-nz *( "/" segment ) ] |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986PathAbsolute(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur; |
+ int ret; |
+ |
+ cur = *str; |
+ |
+ if (*cur != '/') |
+ return(1); |
+ cur++; |
+ ret = xmlParse3986Segment(&cur, 0, 0); |
+ if (ret == 0) { |
+ while (*cur == '/') { |
+ cur++; |
+ ret = xmlParse3986Segment(&cur, 0, 1); |
+ if (ret != 0) return(ret); |
+ } |
+ } |
+ if (uri != NULL) { |
+ if (uri->path != NULL) xmlFree(uri->path); |
+ if (cur != *str) { |
+ if (uri->cleanup & 2) |
+ uri->path = STRNDUP(*str, cur - *str); |
+ else |
+ uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); |
+ } else { |
+ uri->path = NULL; |
+ } |
+ } |
+ *str = cur; |
+ return (0); |
+} |
+ |
+/** |
+ * xmlParse3986PathRootless: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an path without root and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * path-rootless = segment-nz *( "/" segment ) |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986PathRootless(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur; |
+ int ret; |
+ |
+ cur = *str; |
+ |
+ ret = xmlParse3986Segment(&cur, 0, 0); |
+ if (ret != 0) return(ret); |
+ while (*cur == '/') { |
+ cur++; |
+ ret = xmlParse3986Segment(&cur, 0, 1); |
+ if (ret != 0) return(ret); |
+ } |
+ if (uri != NULL) { |
+ if (uri->path != NULL) xmlFree(uri->path); |
+ if (cur != *str) { |
+ if (uri->cleanup & 2) |
+ uri->path = STRNDUP(*str, cur - *str); |
+ else |
+ uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); |
+ } else { |
+ uri->path = NULL; |
+ } |
+ } |
+ *str = cur; |
+ return (0); |
+} |
+ |
+/** |
+ * xmlParse3986PathNoScheme: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an path which is not a scheme and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * path-noscheme = segment-nz-nc *( "/" segment ) |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986PathNoScheme(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur; |
+ int ret; |
+ |
+ cur = *str; |
+ |
+ ret = xmlParse3986Segment(&cur, ':', 0); |
+ if (ret != 0) return(ret); |
+ while (*cur == '/') { |
+ cur++; |
+ ret = xmlParse3986Segment(&cur, 0, 1); |
+ if (ret != 0) return(ret); |
+ } |
+ if (uri != NULL) { |
+ if (uri->path != NULL) xmlFree(uri->path); |
+ if (cur != *str) { |
+ if (uri->cleanup & 2) |
+ uri->path = STRNDUP(*str, cur - *str); |
+ else |
+ uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); |
+ } else { |
+ uri->path = NULL; |
+ } |
+ } |
+ *str = cur; |
+ return (0); |
+} |
+ |
+/** |
+ * xmlParse3986HierPart: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an hierarchical part and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * hier-part = "//" authority path-abempty |
+ * / path-absolute |
+ * / path-rootless |
+ * / path-empty |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986HierPart(xmlURIPtr uri, const char **str) |
+{ |
+ const char *cur; |
+ int ret; |
+ |
+ cur = *str; |
+ |
+ if ((*cur == '/') && (*(cur + 1) == '/')) { |
+ cur += 2; |
+ ret = xmlParse3986Authority(uri, &cur); |
+ if (ret != 0) return(ret); |
+ ret = xmlParse3986PathAbEmpty(uri, &cur); |
+ if (ret != 0) return(ret); |
+ *str = cur; |
+ return(0); |
+ } else if (*cur == '/') { |
+ ret = xmlParse3986PathAbsolute(uri, &cur); |
+ if (ret != 0) return(ret); |
+ } else if (ISA_PCHAR(cur)) { |
+ ret = xmlParse3986PathRootless(uri, &cur); |
+ if (ret != 0) return(ret); |
+ } else { |
+ /* path-empty is effectively empty */ |
+ if (uri != NULL) { |
+ if (uri->path != NULL) xmlFree(uri->path); |
+ uri->path = NULL; |
+ } |
+ } |
+ *str = cur; |
+ return (0); |
+} |
+ |
+/** |
+ * xmlParse3986RelativeRef: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an URI string and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * relative-ref = relative-part [ "?" query ] [ "#" fragment ] |
+ * relative-part = "//" authority path-abempty |
+ * / path-absolute |
+ * / path-noscheme |
+ * / path-empty |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986RelativeRef(xmlURIPtr uri, const char *str) { |
+ int ret; |
+ |
+ if ((*str == '/') && (*(str + 1) == '/')) { |
+ str += 2; |
+ ret = xmlParse3986Authority(uri, &str); |
+ if (ret != 0) return(ret); |
+ ret = xmlParse3986PathAbEmpty(uri, &str); |
+ if (ret != 0) return(ret); |
+ } else if (*str == '/') { |
+ ret = xmlParse3986PathAbsolute(uri, &str); |
+ if (ret != 0) return(ret); |
+ } else if (ISA_PCHAR(str)) { |
+ ret = xmlParse3986PathNoScheme(uri, &str); |
+ if (ret != 0) return(ret); |
+ } else { |
+ /* path-empty is effectively empty */ |
+ if (uri != NULL) { |
+ if (uri->path != NULL) xmlFree(uri->path); |
+ uri->path = NULL; |
+ } |
+ } |
+ |
+ if (*str == '?') { |
+ str++; |
+ ret = xmlParse3986Query(uri, &str); |
+ if (ret != 0) return(ret); |
+ } |
+ if (*str == '#') { |
+ str++; |
+ ret = xmlParse3986Fragment(uri, &str); |
+ if (ret != 0) return(ret); |
+ } |
+ if (*str != 0) { |
+ xmlCleanURI(uri); |
+ return(1); |
+ } |
+ return(0); |
+} |
+ |
+ |
+/** |
+ * xmlParse3986URI: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an URI string and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * scheme ":" hier-part [ "?" query ] [ "#" fragment ] |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986URI(xmlURIPtr uri, const char *str) { |
+ int ret; |
+ |
+ ret = xmlParse3986Scheme(uri, &str); |
+ if (ret != 0) return(ret); |
+ if (*str != ':') { |
+ return(1); |
+ } |
+ str++; |
+ ret = xmlParse3986HierPart(uri, &str); |
+ if (ret != 0) return(ret); |
+ if (*str == '?') { |
+ str++; |
+ ret = xmlParse3986Query(uri, &str); |
+ if (ret != 0) return(ret); |
+ } |
+ if (*str == '#') { |
+ str++; |
+ ret = xmlParse3986Fragment(uri, &str); |
+ if (ret != 0) return(ret); |
+ } |
+ if (*str != 0) { |
+ xmlCleanURI(uri); |
+ return(1); |
+ } |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParse3986URIReference: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an URI reference string and fills in the appropriate fields |
+ * of the @uri structure |
+ * |
+ * URI-reference = URI / relative-ref |
+ * |
+ * Returns 0 or the error code |
+ */ |
+static int |
+xmlParse3986URIReference(xmlURIPtr uri, const char *str) { |
+ int ret; |
+ |
+ if (str == NULL) |
+ return(-1); |
+ xmlCleanURI(uri); |
+ |
+ /* |
+ * Try first to parse absolute refs, then fallback to relative if |
+ * it fails. |
+ */ |
+ ret = xmlParse3986URI(uri, str); |
+ if (ret != 0) { |
+ xmlCleanURI(uri); |
+ ret = xmlParse3986RelativeRef(uri, str); |
+ if (ret != 0) { |
+ xmlCleanURI(uri); |
+ return(ret); |
+ } |
+ } |
+ return(0); |
+} |
+ |
+/** |
+ * xmlParseURI: |
+ * @str: the URI string to analyze |
+ * |
+ * Parse an URI based on RFC 3986 |
+ * |
+ * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] |
+ * |
+ * Returns a newly built xmlURIPtr or NULL in case of error |
+ */ |
+xmlURIPtr |
+xmlParseURI(const char *str) { |
+ xmlURIPtr uri; |
+ int ret; |
+ |
+ if (str == NULL) |
+ return(NULL); |
+ uri = xmlCreateURI(); |
+ if (uri != NULL) { |
+ ret = xmlParse3986URIReference(uri, str); |
+ if (ret) { |
+ xmlFreeURI(uri); |
+ return(NULL); |
+ } |
+ } |
+ return(uri); |
+} |
+ |
+/** |
+ * xmlParseURIReference: |
+ * @uri: pointer to an URI structure |
+ * @str: the string to analyze |
+ * |
+ * Parse an URI reference string based on RFC 3986 and fills in the |
+ * appropriate fields of the @uri structure |
+ * |
+ * URI-reference = URI / relative-ref |
+ * |
+ * Returns 0 or the error code |
+ */ |
+int |
+xmlParseURIReference(xmlURIPtr uri, const char *str) { |
+ return(xmlParse3986URIReference(uri, str)); |
+} |
+ |
+/** |
+ * xmlParseURIRaw: |
+ * @str: the URI string to analyze |
+ * @raw: if 1 unescaping of URI pieces are disabled |
+ * |
+ * Parse an URI but allows to keep intact the original fragments. |
+ * |
+ * URI-reference = URI / relative-ref |
+ * |
+ * Returns a newly built xmlURIPtr or NULL in case of error |
+ */ |
+xmlURIPtr |
+xmlParseURIRaw(const char *str, int raw) { |
+ xmlURIPtr uri; |
+ int ret; |
+ |
+ if (str == NULL) |
+ return(NULL); |
+ uri = xmlCreateURI(); |
+ if (uri != NULL) { |
+ if (raw) { |
+ uri->cleanup |= 2; |
+ } |
+ ret = xmlParseURIReference(uri, str); |
+ if (ret) { |
+ xmlFreeURI(uri); |
+ return(NULL); |
+ } |
+ } |
+ return(uri); |
+} |
/************************************************************************ |
* * |
@@ -225,6 +999,7 @@ xmlCreateURI(void) { |
xmlChar * |
xmlSaveUri(xmlURIPtr uri) { |
xmlChar *ret = NULL; |
+ xmlChar *temp; |
const char *p; |
int len; |
int max; |
@@ -246,23 +1021,27 @@ xmlSaveUri(xmlURIPtr uri) { |
while (*p != 0) { |
if (len >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
ret[len++] = *p++; |
} |
if (len >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
ret[len++] = ':'; |
} |
@@ -271,12 +1050,14 @@ xmlSaveUri(xmlURIPtr uri) { |
while (*p != 0) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p))) |
ret[len++] = *p++; |
@@ -292,12 +1073,14 @@ xmlSaveUri(xmlURIPtr uri) { |
if (uri->server != NULL) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
ret[len++] = '/'; |
ret[len++] = '/'; |
@@ -306,13 +1089,15 @@ xmlSaveUri(xmlURIPtr uri) { |
while (*p != 0) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
if ((IS_UNRESERVED(*(p))) || |
((*(p) == ';')) || ((*(p) == ':')) || |
@@ -330,13 +1115,15 @@ xmlSaveUri(xmlURIPtr uri) { |
} |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
ret[len++] = '@'; |
} |
@@ -344,39 +1131,45 @@ xmlSaveUri(xmlURIPtr uri) { |
while (*p != 0) { |
if (len >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
ret[len++] = *p++; |
} |
if (uri->port > 0) { |
if (len + 10 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
len += snprintf((char *) &ret[len], max - len, ":%d", uri->port); |
} |
} else if (uri->authority != NULL) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
- xmlGenericError(xmlGenericErrorContext, |
- "xmlSaveUri: out of memory\n"); |
- return(NULL); |
- } |
+ if (temp == NULL) { |
+ xmlGenericError(xmlGenericErrorContext, |
+ "xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
+ return(NULL); |
+ } |
+ ret = temp; |
} |
ret[len++] = '/'; |
ret[len++] = '/'; |
@@ -384,13 +1177,15 @@ xmlSaveUri(xmlURIPtr uri) { |
while (*p != 0) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
if ((IS_UNRESERVED(*(p))) || |
((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || |
@@ -408,13 +1203,15 @@ xmlSaveUri(xmlURIPtr uri) { |
} else if (uri->scheme != NULL) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
- xmlGenericError(xmlGenericErrorContext, |
- "xmlSaveUri: out of memory\n"); |
- return(NULL); |
- } |
+ if (temp == NULL) { |
+ xmlGenericError(xmlGenericErrorContext, |
+ "xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
+ return(NULL); |
+ } |
+ ret = temp; |
} |
ret[len++] = '/'; |
ret[len++] = '/'; |
@@ -430,7 +1227,7 @@ xmlSaveUri(xmlURIPtr uri) { |
(((p[1] >= 'a') && (p[1] <= 'z')) || |
((p[1] >= 'A') && (p[1] <= 'Z'))) && |
(p[2] == ':') && |
- (xmlStrEqual(uri->scheme, BAD_CAST "file"))) { |
+ (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) { |
if (len + 3 >= max) { |
max *= 2; |
ret = (xmlChar *) xmlRealloc(ret, |
@@ -448,13 +1245,15 @@ xmlSaveUri(xmlURIPtr uri) { |
while (*p != 0) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) || |
((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || |
@@ -473,52 +1272,60 @@ xmlSaveUri(xmlURIPtr uri) { |
if (uri->query_raw != NULL) { |
if (len + 1 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
- xmlGenericError(xmlGenericErrorContext, |
- "xmlSaveUri: out of memory\n"); |
- return(NULL); |
- } |
+ if (temp == NULL) { |
+ xmlGenericError(xmlGenericErrorContext, |
+ "xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
+ return(NULL); |
+ } |
+ ret = temp; |
} |
ret[len++] = '?'; |
p = uri->query_raw; |
while (*p != 0) { |
if (len + 1 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
ret[len++] = *p++; |
} |
} else if (uri->query != NULL) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
- xmlGenericError(xmlGenericErrorContext, |
- "xmlSaveUri: out of memory\n"); |
- return(NULL); |
- } |
+ if (temp == NULL) { |
+ xmlGenericError(xmlGenericErrorContext, |
+ "xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
+ return(NULL); |
+ } |
+ ret = temp; |
} |
ret[len++] = '?'; |
p = uri->query; |
while (*p != 0) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) |
ret[len++] = *p++; |
@@ -535,26 +1342,30 @@ xmlSaveUri(xmlURIPtr uri) { |
if (uri->fragment != NULL) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
- xmlGenericError(xmlGenericErrorContext, |
- "xmlSaveUri: out of memory\n"); |
- return(NULL); |
- } |
+ if (temp == NULL) { |
+ xmlGenericError(xmlGenericErrorContext, |
+ "xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
+ return(NULL); |
+ } |
+ ret = temp; |
} |
ret[len++] = '#'; |
p = uri->fragment; |
while (*p != 0) { |
if (len + 3 >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, |
+ temp = (xmlChar *) xmlRealloc(ret, |
(max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
- xmlGenericError(xmlGenericErrorContext, |
- "xmlSaveUri: out of memory\n"); |
- return(NULL); |
- } |
+ if (temp == NULL) { |
+ xmlGenericError(xmlGenericErrorContext, |
+ "xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
+ return(NULL); |
+ } |
+ ret = temp; |
} |
if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) |
ret[len++] = *p++; |
@@ -569,14 +1380,16 @@ xmlSaveUri(xmlURIPtr uri) { |
} |
if (len >= max) { |
max *= 2; |
- ret = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
- if (ret == NULL) { |
- xmlGenericError(xmlGenericErrorContext, |
- "xmlSaveUri: out of memory\n"); |
- return(NULL); |
- } |
+ temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); |
+ if (temp == NULL) { |
+ xmlGenericError(xmlGenericErrorContext, |
+ "xmlSaveUri: out of memory\n"); |
+ xmlFree(ret); |
+ return(NULL); |
+ } |
+ ret = temp; |
} |
- ret[len++] = 0; |
+ ret[len] = 0; |
return(ret); |
} |
@@ -928,6 +1741,7 @@ xmlURIUnescapeString(const char *str, int len, char *target) { |
xmlChar * |
xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) { |
xmlChar *ret, ch; |
+ xmlChar *temp; |
const xmlChar *in; |
unsigned int len, out; |
@@ -951,12 +1765,14 @@ xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) { |
while(*in != 0) { |
if (len - out <= 3) { |
len += 20; |
- ret = (xmlChar *) xmlRealloc(ret, len); |
- if (ret == NULL) { |
+ temp = (xmlChar *) xmlRealloc(ret, len); |
+ if (temp == NULL) { |
xmlGenericError(xmlGenericErrorContext, |
"xmlURIEscapeStr: out of memory\n"); |
+ xmlFree(ret); |
return(NULL); |
} |
+ ret = temp; |
} |
ch = *in; |
@@ -1009,7 +1825,8 @@ xmlURIEscape(const xmlChar * str) |
#define NULLCHK(p) if(!p) { \ |
xmlGenericError(xmlGenericErrorContext, \ |
"xmlURIEscape: out of memory\n"); \ |
- return NULL; } |
+ xmlFreeURI(uri); \ |
+ return NULL; } \ |
if (str == NULL) |
return (NULL); |
@@ -1062,7 +1879,7 @@ xmlURIEscape(const xmlChar * str) |
segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@"); |
NULLCHK(segment) |
if (uri->user == NULL) |
- ret = xmlStrcat(ret, BAD_CAST "//"); |
+ ret = xmlStrcat(ret, BAD_CAST "//"); |
ret = xmlStrcat(ret, segment); |
xmlFree(segment); |
} |
@@ -1119,787 +1936,6 @@ xmlURIEscape(const xmlChar * str) |
/************************************************************************ |
* * |
- * Escaped URI parsing * |
- * * |
- ************************************************************************/ |
- |
-/** |
- * xmlParseURIFragment: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse an URI fragment string and fills in the appropriate fields |
- * of the @uri structure. |
- * |
- * fragment = *uric |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseURIFragment(xmlURIPtr uri, const char **str) |
-{ |
- const char *cur; |
- |
- if (str == NULL) |
- return (-1); |
- |
- cur = *str; |
- |
- while (IS_URIC(cur) || IS_UNWISE(cur)) |
- NEXT(cur); |
- if (uri != NULL) { |
- if (uri->fragment != NULL) |
- xmlFree(uri->fragment); |
- if (uri->cleanup & 2) |
- uri->fragment = STRNDUP(*str, cur - *str); |
- else |
- uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL); |
- } |
- *str = cur; |
- return (0); |
-} |
- |
-/** |
- * xmlParseURIQuery: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse the query part of an URI |
- * |
- * query = *uric |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseURIQuery(xmlURIPtr uri, const char **str) |
-{ |
- const char *cur; |
- |
- if (str == NULL) |
- return (-1); |
- |
- cur = *str; |
- |
- while ((IS_URIC(cur)) || |
- ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) |
- NEXT(cur); |
- if (uri != NULL) { |
- if (uri->query != NULL) |
- xmlFree(uri->query); |
- if (uri->cleanup & 2) |
- uri->query = STRNDUP(*str, cur - *str); |
- else |
- uri->query = xmlURIUnescapeString(*str, cur - *str, NULL); |
- |
- /* Save the raw bytes of the query as well. |
- * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114 |
- */ |
- if (uri->query_raw != NULL) |
- xmlFree (uri->query_raw); |
- uri->query_raw = STRNDUP (*str, cur - *str); |
- } |
- *str = cur; |
- return (0); |
-} |
- |
-/** |
- * xmlParseURIScheme: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse an URI scheme |
- * |
- * scheme = alpha *( alpha | digit | "+" | "-" | "." ) |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseURIScheme(xmlURIPtr uri, const char **str) { |
- const char *cur; |
- |
- if (str == NULL) |
- return(-1); |
- |
- cur = *str; |
- if (!IS_ALPHA(*cur)) |
- return(2); |
- cur++; |
- while (IS_SCHEME(*cur)) cur++; |
- if (uri != NULL) { |
- if (uri->scheme != NULL) xmlFree(uri->scheme); |
- uri->scheme = STRNDUP(*str, cur - *str); |
- } |
- *str = cur; |
- return(0); |
-} |
- |
-/** |
- * xmlParseURIOpaquePart: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse an URI opaque part |
- * |
- * opaque_part = uric_no_slash *uric |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseURIOpaquePart(xmlURIPtr uri, const char **str) |
-{ |
- const char *cur; |
- |
- if (str == NULL) |
- return (-1); |
- |
- cur = *str; |
- if (!((IS_URIC_NO_SLASH(cur)) || |
- ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))) { |
- return (3); |
- } |
- NEXT(cur); |
- while ((IS_URIC(cur)) || |
- ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) |
- NEXT(cur); |
- if (uri != NULL) { |
- if (uri->opaque != NULL) |
- xmlFree(uri->opaque); |
- if (uri->cleanup & 2) |
- uri->opaque = STRNDUP(*str, cur - *str); |
- else |
- uri->opaque = xmlURIUnescapeString(*str, cur - *str, NULL); |
- } |
- *str = cur; |
- return (0); |
-} |
- |
-/** |
- * xmlParseURIServer: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse a server subpart of an URI, it's a finer grain analysis |
- * of the authority part. |
- * |
- * server = [ [ userinfo "@" ] hostport ] |
- * userinfo = *( unreserved | escaped | |
- * ";" | ":" | "&" | "=" | "+" | "$" | "," ) |
- * hostport = host [ ":" port ] |
- * host = hostname | IPv4address | IPv6reference |
- * hostname = *( domainlabel "." ) toplabel [ "." ] |
- * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum |
- * toplabel = alpha | alpha *( alphanum | "-" ) alphanum |
- * IPv6reference = "[" IPv6address "]" |
- * IPv6address = hexpart [ ":" IPv4address ] |
- * IPv4address = 1*3digit "." 1*3digit "." 1*3digit "." 1*3digit |
- * hexpart = hexseq | hexseq "::" [ hexseq ]| "::" [ hexseq ] |
- * hexseq = hex4 *( ":" hex4) |
- * hex4 = 1*4hexdig |
- * port = *digit |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseURIServer(xmlURIPtr uri, const char **str) { |
- const char *cur; |
- const char *host, *tmp; |
- const int IPV4max = 4; |
- const int IPV6max = 8; |
- int oct; |
- |
- if (str == NULL) |
- return(-1); |
- |
- cur = *str; |
- |
- /* |
- * is there a userinfo ? |
- */ |
- while (IS_USERINFO(cur)) NEXT(cur); |
- if (*cur == '@') { |
- if (uri != NULL) { |
- if (uri->user != NULL) xmlFree(uri->user); |
- if (uri->cleanup & 2) |
- uri->user = STRNDUP(*str, cur - *str); |
- else |
- uri->user = xmlURIUnescapeString(*str, cur - *str, NULL); |
- } |
- cur++; |
- } else { |
- if (uri != NULL) { |
- if (uri->user != NULL) xmlFree(uri->user); |
- uri->user = NULL; |
- } |
- cur = *str; |
- } |
- /* |
- * This can be empty in the case where there is no server |
- */ |
- host = cur; |
- if (*cur == '/') { |
- if (uri != NULL) { |
- if (uri->authority != NULL) xmlFree(uri->authority); |
- uri->authority = NULL; |
- if (uri->server != NULL) xmlFree(uri->server); |
- uri->server = NULL; |
- uri->port = 0; |
- } |
- return(0); |
- } |
- /* |
- * host part of hostport can denote an IPV4 address, an IPV6 address |
- * or an unresolved name. Check the IP first, its easier to detect |
- * errors if wrong one. |
- * An IPV6 address must start with a '[' and end with a ']'. |
- */ |
- if (*cur == '[') { |
- int compress=0; |
- cur++; |
- for (oct = 0; oct < IPV6max; ++oct) { |
- if (*cur == ':') { |
- if (compress) |
- return(3); /* multiple compression attempted */ |
- if (!oct) { /* initial char is compression */ |
- if (*++cur != ':') |
- return(3); |
- } |
- compress = 1; /* set compression-encountered flag */ |
- cur++; /* skip over the second ':' */ |
- continue; |
- } |
- while(IS_HEX(*cur)) cur++; |
- if (oct == (IPV6max-1)) |
- continue; |
- if (*cur != ':') |
- break; |
- cur++; |
- } |
- if ((!compress) && (oct != IPV6max)) |
- return(3); |
- if (*cur != ']') |
- return(3); |
- if (uri != NULL) { |
- if (uri->server != NULL) xmlFree(uri->server); |
- uri->server = (char *)xmlStrndup((xmlChar *)host+1, |
- (cur-host)-1); |
- } |
- cur++; |
- } else { |
- /* |
- * Not IPV6, maybe IPV4 |
- */ |
- for (oct = 0; oct < IPV4max; ++oct) { |
- if (*cur == '.') |
- return(3); /* e.g. http://.xml/ or http://18.29..30/ */ |
- while(IS_DIGIT(*cur)) cur++; |
- if (oct == (IPV4max-1)) |
- continue; |
- if (*cur != '.') |
- break; |
- cur++; |
- } |
- } |
- if ((host[0] != '[') && (oct < IPV4max || (*cur == '.' && cur++) || |
- IS_ALPHA(*cur))) { |
- /* maybe host_name */ |
- if (!IS_ALPHANUM(*cur)) |
- return(4); /* e.g. http://xml.$oft */ |
- do { |
- do ++cur; while (IS_ALPHANUM(*cur)); |
- if (*cur == '-') { |
- --cur; |
- if (*cur == '.') |
- return(5); /* e.g. http://xml.-soft */ |
- ++cur; |
- continue; |
- } |
- if (*cur == '.') { |
- --cur; |
- if (*cur == '-') |
- return(6); /* e.g. http://xml-.soft */ |
- if (*cur == '.') |
- return(7); /* e.g. http://xml..soft */ |
- ++cur; |
- continue; |
- } |
- break; |
- } while (1); |
- tmp = cur; |
- if (tmp[-1] == '.') |
- --tmp; /* e.g. http://xml.$Oft/ */ |
- do --tmp; while (tmp >= host && IS_ALPHANUM(*tmp)); |
- if ((++tmp == host || tmp[-1] == '.') && !IS_ALPHA(*tmp)) |
- return(8); /* e.g. http://xmlsOft.0rg/ */ |
- } |
- if (uri != NULL) { |
- if (uri->authority != NULL) xmlFree(uri->authority); |
- uri->authority = NULL; |
- if (host[0] != '[') { /* it's not an IPV6 addr */ |
- if (uri->server != NULL) xmlFree(uri->server); |
- if (uri->cleanup & 2) |
- uri->server = STRNDUP(host, cur - host); |
- else |
- uri->server = xmlURIUnescapeString(host, cur - host, NULL); |
- } |
- } |
- /* |
- * finish by checking for a port presence. |
- */ |
- if (*cur == ':') { |
- cur++; |
- if (IS_DIGIT(*cur)) { |
- if (uri != NULL) |
- uri->port = 0; |
- while (IS_DIGIT(*cur)) { |
- if (uri != NULL) |
- uri->port = uri->port * 10 + (*cur - '0'); |
- cur++; |
- } |
- } |
- } |
- *str = cur; |
- return(0); |
-} |
- |
-/** |
- * xmlParseURIRelSegment: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse an URI relative segment |
- * |
- * rel_segment = 1*( unreserved | escaped | ";" | "@" | "&" | "=" | |
- * "+" | "$" | "," ) |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseURIRelSegment(xmlURIPtr uri, const char **str) |
-{ |
- const char *cur; |
- |
- if (str == NULL) |
- return (-1); |
- |
- cur = *str; |
- if (!((IS_SEGMENT(cur)) || |
- ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))) { |
- return (3); |
- } |
- NEXT(cur); |
- while ((IS_SEGMENT(cur)) || |
- ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) |
- NEXT(cur); |
- if (uri != NULL) { |
- if (uri->path != NULL) |
- xmlFree(uri->path); |
- if (uri->cleanup & 2) |
- uri->path = STRNDUP(*str, cur - *str); |
- else |
- uri->path = xmlURIUnescapeString(*str, cur - *str, NULL); |
- } |
- *str = cur; |
- return (0); |
-} |
- |
-/** |
- * xmlParseURIPathSegments: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * @slash: should we add a leading slash |
- * |
- * Parse an URI set of path segments |
- * |
- * path_segments = segment *( "/" segment ) |
- * segment = *pchar *( ";" param ) |
- * param = *pchar |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseURIPathSegments(xmlURIPtr uri, const char **str, int slash) |
-{ |
- const char *cur; |
- |
- if (str == NULL) |
- return (-1); |
- |
- cur = *str; |
- |
- do { |
- while ((IS_PCHAR(cur)) || |
- ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) |
- NEXT(cur); |
- while (*cur == ';') { |
- cur++; |
- while ((IS_PCHAR(cur)) || |
- ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur)))) |
- NEXT(cur); |
- } |
- if (*cur != '/') |
- break; |
- cur++; |
- } while (1); |
- if (uri != NULL) { |
- int len, len2 = 0; |
- char *path; |
- |
- /* |
- * Concat the set of path segments to the current path |
- */ |
- len = cur - *str; |
- if (slash) |
- len++; |
- |
- if (uri->path != NULL) { |
- len2 = strlen(uri->path); |
- len += len2; |
- } |
- path = (char *) xmlMallocAtomic(len + 1); |
- if (path == NULL) { |
- xmlGenericError(xmlGenericErrorContext, |
- "xmlParseURIPathSegments: out of memory\n"); |
- *str = cur; |
- return (-1); |
- } |
- if (uri->path != NULL) |
- memcpy(path, uri->path, len2); |
- if (slash) { |
- path[len2] = '/'; |
- len2++; |
- } |
- path[len2] = 0; |
- if (cur - *str > 0) { |
- if (uri->cleanup & 2) { |
- memcpy(&path[len2], *str, cur - *str); |
- path[len2 + (cur - *str)] = 0; |
- } else |
- xmlURIUnescapeString(*str, cur - *str, &path[len2]); |
- } |
- if (uri->path != NULL) |
- xmlFree(uri->path); |
- uri->path = path; |
- } |
- *str = cur; |
- return (0); |
-} |
- |
-/** |
- * xmlParseURIAuthority: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse the authority part of an URI. |
- * |
- * authority = server | reg_name |
- * server = [ [ userinfo "@" ] hostport ] |
- * reg_name = 1*( unreserved | escaped | "$" | "," | ";" | ":" | |
- * "@" | "&" | "=" | "+" ) |
- * |
- * Note : this is completely ambiguous since reg_name is allowed to |
- * use the full set of chars in use by server: |
- * |
- * 3.2.1. Registry-based Naming Authority |
- * |
- * The structure of a registry-based naming authority is specific |
- * to the URI scheme, but constrained to the allowed characters |
- * for an authority component. |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseURIAuthority(xmlURIPtr uri, const char **str) { |
- const char *cur; |
- int ret; |
- |
- if (str == NULL) |
- return(-1); |
- |
- cur = *str; |
- |
- /* |
- * try first to parse it as a server string. |
- */ |
- ret = xmlParseURIServer(uri, str); |
- if ((ret == 0) && (*str != NULL) && |
- ((**str == 0) || (**str == '/') || (**str == '?'))) |
- return(0); |
- *str = cur; |
- |
- /* |
- * failed, fallback to reg_name |
- */ |
- if (!IS_REG_NAME(cur)) { |
- return(5); |
- } |
- NEXT(cur); |
- while (IS_REG_NAME(cur)) NEXT(cur); |
- if (uri != NULL) { |
- if (uri->server != NULL) xmlFree(uri->server); |
- uri->server = NULL; |
- if (uri->user != NULL) xmlFree(uri->user); |
- uri->user = NULL; |
- if (uri->authority != NULL) xmlFree(uri->authority); |
- if (uri->cleanup & 2) |
- uri->authority = STRNDUP(*str, cur - *str); |
- else |
- uri->authority = xmlURIUnescapeString(*str, cur - *str, NULL); |
- } |
- *str = cur; |
- return(0); |
-} |
- |
-/** |
- * xmlParseURIHierPart: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse an URI hierarchical part |
- * |
- * hier_part = ( net_path | abs_path ) [ "?" query ] |
- * abs_path = "/" path_segments |
- * net_path = "//" authority [ abs_path ] |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseURIHierPart(xmlURIPtr uri, const char **str) { |
- int ret; |
- const char *cur; |
- |
- if (str == NULL) |
- return(-1); |
- |
- cur = *str; |
- |
- if ((cur[0] == '/') && (cur[1] == '/')) { |
- cur += 2; |
- ret = xmlParseURIAuthority(uri, &cur); |
- if (ret != 0) |
- return(ret); |
- if (cur[0] == '/') { |
- cur++; |
- ret = xmlParseURIPathSegments(uri, &cur, 1); |
- } |
- } else if (cur[0] == '/') { |
- cur++; |
- ret = xmlParseURIPathSegments(uri, &cur, 1); |
- } else { |
- return(4); |
- } |
- if (ret != 0) |
- return(ret); |
- if (*cur == '?') { |
- cur++; |
- ret = xmlParseURIQuery(uri, &cur); |
- if (ret != 0) |
- return(ret); |
- } |
- *str = cur; |
- return(0); |
-} |
- |
-/** |
- * xmlParseAbsoluteURI: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse an URI reference string and fills in the appropriate fields |
- * of the @uri structure |
- * |
- * absoluteURI = scheme ":" ( hier_part | opaque_part ) |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseAbsoluteURI(xmlURIPtr uri, const char **str) { |
- int ret; |
- const char *cur; |
- |
- if (str == NULL) |
- return(-1); |
- |
- cur = *str; |
- |
- ret = xmlParseURIScheme(uri, str); |
- if (ret != 0) return(ret); |
- if (**str != ':') { |
- *str = cur; |
- return(1); |
- } |
- (*str)++; |
- if (**str == '/') |
- return(xmlParseURIHierPart(uri, str)); |
- return(xmlParseURIOpaquePart(uri, str)); |
-} |
- |
-/** |
- * xmlParseRelativeURI: |
- * @uri: pointer to an URI structure |
- * @str: pointer to the string to analyze |
- * |
- * Parse an relative URI string and fills in the appropriate fields |
- * of the @uri structure |
- * |
- * relativeURI = ( net_path | abs_path | rel_path ) [ "?" query ] |
- * abs_path = "/" path_segments |
- * net_path = "//" authority [ abs_path ] |
- * rel_path = rel_segment [ abs_path ] |
- * |
- * Returns 0 or the error code |
- */ |
-static int |
-xmlParseRelativeURI(xmlURIPtr uri, const char **str) { |
- int ret = 0; |
- const char *cur; |
- |
- if (str == NULL) |
- return(-1); |
- |
- cur = *str; |
- if ((cur[0] == '/') && (cur[1] == '/')) { |
- cur += 2; |
- ret = xmlParseURIAuthority(uri, &cur); |
- if (ret != 0) |
- return(ret); |
- if (cur[0] == '/') { |
- cur++; |
- ret = xmlParseURIPathSegments(uri, &cur, 1); |
- } |
- } else if (cur[0] == '/') { |
- cur++; |
- ret = xmlParseURIPathSegments(uri, &cur, 1); |
- } else if (cur[0] != '#' && cur[0] != '?') { |
- ret = xmlParseURIRelSegment(uri, &cur); |
- if (ret != 0) |
- return(ret); |
- if (cur[0] == '/') { |
- cur++; |
- ret = xmlParseURIPathSegments(uri, &cur, 1); |
- } |
- } |
- if (ret != 0) |
- return(ret); |
- if (*cur == '?') { |
- cur++; |
- ret = xmlParseURIQuery(uri, &cur); |
- if (ret != 0) |
- return(ret); |
- } |
- *str = cur; |
- return(ret); |
-} |
- |
-/** |
- * xmlParseURIReference: |
- * @uri: pointer to an URI structure |
- * @str: the string to analyze |
- * |
- * Parse an URI reference string and fills in the appropriate fields |
- * of the @uri structure |
- * |
- * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] |
- * |
- * Returns 0 or the error code |
- */ |
-int |
-xmlParseURIReference(xmlURIPtr uri, const char *str) { |
- int ret; |
- const char *tmp = str; |
- |
- if (str == NULL) |
- return(-1); |
- xmlCleanURI(uri); |
- |
- /* |
- * Try first to parse absolute refs, then fallback to relative if |
- * it fails. |
- */ |
- ret = xmlParseAbsoluteURI(uri, &str); |
- if (ret != 0) { |
- xmlCleanURI(uri); |
- str = tmp; |
- ret = xmlParseRelativeURI(uri, &str); |
- } |
- if (ret != 0) { |
- xmlCleanURI(uri); |
- return(ret); |
- } |
- |
- if (*str == '#') { |
- str++; |
- ret = xmlParseURIFragment(uri, &str); |
- if (ret != 0) return(ret); |
- } |
- if (*str != 0) { |
- xmlCleanURI(uri); |
- return(1); |
- } |
- return(0); |
-} |
- |
-/** |
- * xmlParseURI: |
- * @str: the URI string to analyze |
- * |
- * Parse an URI |
- * |
- * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] |
- * |
- * Returns a newly built xmlURIPtr or NULL in case of error |
- */ |
-xmlURIPtr |
-xmlParseURI(const char *str) { |
- xmlURIPtr uri; |
- int ret; |
- |
- if (str == NULL) |
- return(NULL); |
- uri = xmlCreateURI(); |
- if (uri != NULL) { |
- ret = xmlParseURIReference(uri, str); |
- if (ret) { |
- xmlFreeURI(uri); |
- return(NULL); |
- } |
- } |
- return(uri); |
-} |
- |
-/** |
- * xmlParseURIRaw: |
- * @str: the URI string to analyze |
- * @raw: if 1 unescaping of URI pieces are disabled |
- * |
- * Parse an URI but allows to keep intact the original fragments. |
- * |
- * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ] |
- * |
- * Returns a newly built xmlURIPtr or NULL in case of error |
- */ |
-xmlURIPtr |
-xmlParseURIRaw(const char *str, int raw) { |
- xmlURIPtr uri; |
- int ret; |
- |
- if (str == NULL) |
- return(NULL); |
- uri = xmlCreateURI(); |
- if (uri != NULL) { |
- if (raw) { |
- uri->cleanup |= 2; |
- } |
- ret = xmlParseURIReference(uri, str); |
- if (ret) { |
- xmlFreeURI(uri); |
- return(NULL); |
- } |
- } |
- return(uri); |
-} |
- |
-/************************************************************************ |
- * * |
* Public functions * |
* * |
************************************************************************/ |