Paul Cercueil / libxml2

Dependents:   libiio

Committer:
pcercuei
Date:
Thu Aug 25 10:07:34 2016 +0000
Revision:
1:26f20484cbdc
Parent:
0:03b5121a232e
Add config.h and dummy.c containing empty functions

Who changed what in which revision?

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