1ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * uri.c: set of generic URI related routines
3ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Reference: RFCs 3986, 2732 and 2373
5ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
6ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * See Copyright for the status of this software.
7ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
8ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * daniel@veillard.com
9ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
10ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
11ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#define IN_LIBXML
12ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#include "libxml.h"
13ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
14ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#include <string.h>
15ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
16ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#include <libxml/xmlmemory.h>
17ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#include <libxml/uri.h>
18ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#include <libxml/globals.h>
19ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#include <libxml/xmlerror.h>
20ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun/**
2294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * MAX_URI_LENGTH:
2394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun *
2494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * The definition of the URI regexp in the above RFC has no size limit
2594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * In practice they are usually relativey short except for the
2694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * data URI scheme as defined in RFC 2397. Even for data URI the usual
2794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * maximum size before hitting random practical limits is around 64 KB
2894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * and 4KB is usually a maximum admitted limit for proper operations.
2994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * The value below is more a security limit than anything else and
3094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * really should never be hit by 'normal' operations
3194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * Set to 1 MByte in 2012, this is only enforced on output
3294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun */
3394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun#define MAX_URI_LENGTH 1024 * 1024
3494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun
3594442ad4107000e6d49f9b85a46a591495a57632Selim Gurunstatic void
3694442ad4107000e6d49f9b85a46a591495a57632Selim GurunxmlURIErrMemory(const char *extra)
3794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun{
3894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    if (extra)
3994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        __xmlRaiseError(NULL, NULL, NULL,
4094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        NULL, NULL, XML_FROM_URI,
4194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
4294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        extra, NULL, NULL, 0, 0,
4394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        "Memory allocation failed : %s\n", extra);
4494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    else
4594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        __xmlRaiseError(NULL, NULL, NULL,
4694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        NULL, NULL, XML_FROM_URI,
4794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
4894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        NULL, NULL, NULL, 0, 0,
4994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        "Memory allocation failed\n");
5094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun}
5194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun
5260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic void xmlCleanURI(xmlURIPtr uri);
53ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
54ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
5560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Old rule from 2396 used in legacy handling code
56ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * alpha    = lowalpha | upalpha
57ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
58ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x))
59ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
60ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
61ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
62ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
63ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *            "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
64ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *            "u" | "v" | "w" | "x" | "y" | "z"
65ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
66ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
67ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z'))
68ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
69ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
70ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" |
71ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *           "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" |
72ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *           "U" | "V" | "W" | "X" | "Y" | "Z"
73ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
74ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z'))
75ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
76ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#ifdef IS_DIGIT
77ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#undef IS_DIGIT
78ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#endif
79ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
80ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
81ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
82ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9'))
83ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
84ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
85ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * alphanum = alpha | digit
86ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
87ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
88ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x))
89ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
90ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
91ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
92ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
93ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
9460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') ||     \
9560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') ||    \
96ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    ((x) == '(') || ((x) == ')'))
97ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
9860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/*
9960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * unwise = "{" | "}" | "|" | "\" | "^" | "`"
10060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
101ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
10260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define IS_UNWISE(p)                                                    \
10360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) ||         \
10460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott       ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) ||        \
10560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott       ((*(p) == ']')) || ((*(p) == '`')))
106ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
107ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," |
10860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *            "[" | "]"
109ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
110ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
11160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \
11260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \
11360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \
11460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ((x) == ']'))
115ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
116ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
117ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * unreserved = alphanum | mark
118ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
119ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
120ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x))
121ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
122ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
12360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Skip to next pointer char, handle escaped sequences
124ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
125ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
12660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define NEXT(p) ((*p == '%')? p += 3 : p++)
127ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
128ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
12960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Productions from the spec.
13060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
13160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *    authority     = server | reg_name
13260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *    reg_name      = 1*( unreserved | escaped | "$" | "," |
13360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                        ";" | ":" | "@" | "&" | "=" | "+" )
13460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
13560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * path          = [ abs_path | opaque_part ]
136ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
13760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
13860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n))
13960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
14060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/************************************************************************
14160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *									*
14260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                         RFC 3986 parser				*
14360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *									*
14460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott ************************************************************************/
14560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
14660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9'))
14760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) ||		\
14860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott                      ((*(p) >= 'A') && (*(p) <= 'Z')))
14960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define ISA_HEXDIG(p)							\
15060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott       (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) ||		\
15160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ((*(p) >= 'A') && (*(p) <= 'F')))
152ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
153ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
15460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
15560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                     / "*" / "+" / "," / ";" / "="
156ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
15760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define ISA_SUB_DELIM(p)						\
15860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) ||		\
15960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott       ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) ||		\
16060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott       ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) ||		\
161df143a5041f03a22808b59c76698770b74692815Selim Gurun       ((*(p) == '=')) || ((*(p) == '\'')))
162ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
163ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
16460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *    gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
165ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
16660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define ISA_GEN_DELIM(p)						\
16760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      (((*(p) == ':')) || ((*(p) == '/')) || ((*(p) == '?')) ||         \
16860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott       ((*(p) == '#')) || ((*(p) == '[')) || ((*(p) == ']')) ||         \
16960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott       ((*(p) == '@')))
170ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
171ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
17260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *    reserved      = gen-delims / sub-delims
173ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
17460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define ISA_RESERVED(p) (ISA_GEN_DELIM(p) || (ISA_SUB_DELIM(p)))
175ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
176ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
17760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
178ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
17960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define ISA_UNRESERVED(p)						\
18060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) ||		\
18160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott       ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~')))
182ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
183ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
18460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *    pct-encoded   = "%" HEXDIG HEXDIG
185ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
18660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define ISA_PCT_ENCODED(p)						\
18760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2)))
188ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
189ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
19060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
191ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
19260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define ISA_PCHAR(p)							\
19360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) ||	\
19460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      ((*(p) == ':')) || ((*(p) == '@')))
195ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
19660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
19760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986Scheme:
19860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
19960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  pointer to the string to analyze
20060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
20160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an URI scheme
20260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
20360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
20460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
20560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
20660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
20760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
20860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986Scheme(xmlURIPtr uri, const char **str) {
20960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
210ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
21160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (str == NULL)
21260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(-1);
213ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
21460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
21560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (!ISA_ALPHA(cur))
21660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(2);
21760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur++;
21860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (ISA_ALPHA(cur) || ISA_DIGIT(cur) ||
21960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott           (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++;
22060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
22160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->scheme != NULL) xmlFree(uri->scheme);
22260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	uri->scheme = STRNDUP(*str, cur - *str);
22360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
22460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
22560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(0);
22660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
227ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
22860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
22960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986Fragment:
23060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
23160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  pointer to the string to analyze
23260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
23360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse the query part of an URI
23460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
23560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * fragment      = *( pchar / "/" / "?" )
23660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * NOTE: the strict syntax as defined by 3986 does not allow '[' and ']'
23760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *       in the fragment identifier but this is used very broadly for
23860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *       xpointer scheme selection, so we are allowing it here to not break
23960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *       for example all the DocBook processing chains.
24060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
24160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
242ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
24360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
24460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986Fragment(xmlURIPtr uri, const char **str)
24560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
24660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
247ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
24860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (str == NULL)
24960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        return (-1);
250ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
25160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
25260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
25360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
25460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott           (*cur == '[') || (*cur == ']') ||
25560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
25660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NEXT(cur);
25760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
25860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (uri->fragment != NULL)
25960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott            xmlFree(uri->fragment);
26060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->cleanup & 2)
26160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    uri->fragment = STRNDUP(*str, cur - *str);
26260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	else
26360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL);
26460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
26560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
26660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return (0);
26760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
26860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
26960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
27060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986Query:
27160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
27260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  pointer to the string to analyze
273ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
27460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse the query part of an URI
275ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
27660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * query = *uric
27760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
27860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
279ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
28060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
28160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986Query(xmlURIPtr uri, const char **str)
28260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
28360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
284ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
28560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (str == NULL)
28660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        return (-1);
287ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
28860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
28960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
29060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
29160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
29260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NEXT(cur);
29360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
29460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (uri->query != NULL)
29560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott            xmlFree(uri->query);
29660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->cleanup & 2)
29760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    uri->query = STRNDUP(*str, cur - *str);
29860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	else
29960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    uri->query = xmlURIUnescapeString(*str, cur - *str, NULL);
30060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
30160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	/* Save the raw bytes of the query as well.
30260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	 * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114
30360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	 */
30460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->query_raw != NULL)
30560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    xmlFree (uri->query_raw);
30660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	uri->query_raw = STRNDUP (*str, cur - *str);
30760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
30860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
30960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return (0);
31060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
311ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
312ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
31360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986Port:
31460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
31560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
316ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
31760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse a port  part and fills in the appropriate fields
31860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
319ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
32060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * port          = *DIGIT
32160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
32260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
323ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
32460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
32560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986Port(xmlURIPtr uri, const char **str)
32660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
32760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur = *str;
328ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
32960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ISA_DIGIT(cur)) {
33060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri != NULL)
33160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    uri->port = 0;
33260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	while (ISA_DIGIT(cur)) {
33360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (uri != NULL)
33460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		uri->port = uri->port * 10 + (*cur - '0');
33560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    cur++;
33660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
33760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	*str = cur;
33860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(0);
339ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
34060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(1);
341ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
342ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
343ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
34460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986Userinfo:
34560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
34660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
347ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
34860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an user informations part and fills in the appropriate fields
34960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
350ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
35160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
35260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
35360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
354ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
35560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
35660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986Userinfo(xmlURIPtr uri, const char **str)
35760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
35860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
359ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
36060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
36160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) ||
36260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott           ISA_SUB_DELIM(cur) || (*cur == ':'))
36360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	NEXT(cur);
36460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*cur == '@') {
36560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri != NULL) {
36660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (uri->user != NULL) xmlFree(uri->user);
36760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (uri->cleanup & 2)
36860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		uri->user = STRNDUP(*str, cur - *str);
36960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else
37060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		uri->user = xmlURIUnescapeString(*str, cur - *str, NULL);
37160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
37260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	*str = cur;
37360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(0);
37460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
37560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(1);
37660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
377ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
37860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
37960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986DecOctet:
38060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
38160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
38260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *    dec-octet     = DIGIT                 ; 0-9
38360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                  / %x31-39 DIGIT         ; 10-99
38460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                  / "1" 2DIGIT            ; 100-199
38560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                  / "2" %x30-34 DIGIT     ; 200-249
38660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                  / "25" %x30-35          ; 250-255
38760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
38860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Skip a dec-octet.
38960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
39060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 if found and skipped, 1 otherwise
39160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
39260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
39360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986DecOctet(const char **str) {
39460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur = *str;
395ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
39660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (!(ISA_DIGIT(cur)))
39760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        return(1);
39860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (!ISA_DIGIT(cur+1))
39960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	cur++;
40060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur+2)))
40160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	cur += 2;
40260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2)))
40360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	cur += 3;
40460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    else if ((*cur == '2') && (*(cur + 1) >= '0') &&
40560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	     (*(cur + 1) <= '4') && (ISA_DIGIT(cur + 2)))
40660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	cur += 3;
40760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    else if ((*cur == '2') && (*(cur + 1) == '5') &&
40860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	     (*(cur + 2) >= '0') && (*(cur + 1) <= '5'))
40960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	cur += 3;
41060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    else
41160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        return(1);
41260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
41360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(0);
41460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
41560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
41660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986Host:
41760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
41860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
41960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
42060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an host part and fills in the appropriate fields
42160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
42260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
42360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * host          = IP-literal / IPv4address / reg-name
42460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * IP-literal    = "[" ( IPv6address / IPvFuture  ) "]"
42560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * IPv4address   = dec-octet "." dec-octet "." dec-octet "." dec-octet
42660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * reg-name      = *( unreserved / pct-encoded / sub-delims )
42760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
42860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
42960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
43060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
43160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986Host(xmlURIPtr uri, const char **str)
43260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
43360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur = *str;
43460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *host;
435ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
43660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    host = cur;
43760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    /*
43860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * IPv6 and future adressing scheme are enclosed between brackets
43960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     */
44060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*cur == '[') {
44160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur++;
44260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	while ((*cur != ']') && (*cur != 0))
44360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    cur++;
44460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (*cur != ']')
44560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    return(1);
44660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	cur++;
44760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	goto found;
448ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
44960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    /*
45060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * try to parse an IPv4
45160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     */
45260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ISA_DIGIT(cur)) {
45360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (xmlParse3986DecOctet(&cur) != 0)
45460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    goto not_ipv4;
45560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (*cur != '.')
45660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    goto not_ipv4;
45760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	cur++;
45860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (xmlParse3986DecOctet(&cur) != 0)
45960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    goto not_ipv4;
46060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (*cur != '.')
46160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    goto not_ipv4;
46260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (xmlParse3986DecOctet(&cur) != 0)
46360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    goto not_ipv4;
46460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (*cur != '.')
46560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    goto not_ipv4;
46660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (xmlParse3986DecOctet(&cur) != 0)
46760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    goto not_ipv4;
46860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	goto found;
46960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottnot_ipv4:
47060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur = *str;
471ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
47260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    /*
47360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * then this should be a hostname which can be empty
47460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     */
47560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur))
47660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NEXT(cur);
47760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottfound:
47860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
47960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->authority != NULL) xmlFree(uri->authority);
48060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	uri->authority = NULL;
48160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->server != NULL) xmlFree(uri->server);
48260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (cur != host) {
48360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (uri->cleanup & 2)
48460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		uri->server = STRNDUP(host, cur - host);
48560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else
48660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		uri->server = xmlURIUnescapeString(host, cur - host, NULL);
48760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	} else
48860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    uri->server = NULL;
489ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
49060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
49160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(0);
492ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
493ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
494ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
49560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986Authority:
49660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
49760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
498ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
49960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an authority part and fills in the appropriate fields
50060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
50160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
50260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * authority     = [ userinfo "@" ] host [ ":" port ]
50360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
50460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
505ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
50660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
50760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986Authority(xmlURIPtr uri, const char **str)
50860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
50960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
51060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
511ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
51260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
51360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    /*
51460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * try to parse an userinfo and check for the trailing @
51560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     */
51660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = xmlParse3986Userinfo(uri, &cur);
51760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if ((ret != 0) || (*cur != '@'))
51860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur = *str;
51960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    else
52060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur++;
52160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = xmlParse3986Host(uri, &cur);
52260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ret != 0) return(ret);
52360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*cur == ':') {
52460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur++;
52560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlParse3986Port(uri, &cur);
52660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
527ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
52860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
52960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(0);
530ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
531ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
532ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
53360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986Segment:
53460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
53560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @forbid: an optional forbidden character
53660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @empty: allow an empty segment
537ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
53860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse a segment and fills in the appropriate fields
53960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
54060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
54160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * segment       = *pchar
54260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * segment-nz    = 1*pchar
54360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
54460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *               ; non-zero-length segment without any colon ":"
54560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
54660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
547ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
54860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
54960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986Segment(const char **str, char forbid, int empty)
55060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
55160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
552ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
55360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
55460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (!ISA_PCHAR(cur)) {
55560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (empty)
55660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    return(0);
55760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(1);
55860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
55960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (ISA_PCHAR(cur) && (*cur != forbid))
56060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NEXT(cur);
56160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
56260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return (0);
563ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
564ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
565ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
56660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986PathAbEmpty:
56760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
56860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
569ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
57060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an path absolute or empty and fills in the appropriate fields
57160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
57260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
57360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * path-abempty  = *( "/" segment )
57460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
57560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
576ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
57760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
57860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986PathAbEmpty(xmlURIPtr uri, const char **str)
57960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
58060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
58160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
582ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
58360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
584ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
58560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (*cur == '/') {
58660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur++;
58760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986Segment(&cur, 0, 1);
58860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
58960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
59060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
59160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->path != NULL) xmlFree(uri->path);
592df143a5041f03a22808b59c76698770b74692815Selim Gurun        if (*str != cur) {
593df143a5041f03a22808b59c76698770b74692815Selim Gurun            if (uri->cleanup & 2)
594df143a5041f03a22808b59c76698770b74692815Selim Gurun                uri->path = STRNDUP(*str, cur - *str);
595df143a5041f03a22808b59c76698770b74692815Selim Gurun            else
596df143a5041f03a22808b59c76698770b74692815Selim Gurun                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
597df143a5041f03a22808b59c76698770b74692815Selim Gurun        } else {
598df143a5041f03a22808b59c76698770b74692815Selim Gurun            uri->path = NULL;
599df143a5041f03a22808b59c76698770b74692815Selim Gurun        }
60060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
60160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
60260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return (0);
60360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
604ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
605ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
60660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986PathAbsolute:
60760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
60860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
609ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
61060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an path absolute and fills in the appropriate fields
61160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
612ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
61360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * path-absolute = "/" [ segment-nz *( "/" segment ) ]
614ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
61560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
616ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
61760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
61860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986PathAbsolute(xmlURIPtr uri, const char **str)
61960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
62060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
62160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
622ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
62360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
624ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
62560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*cur != '/')
62660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        return(1);
62760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur++;
62860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = xmlParse3986Segment(&cur, 0, 0);
62960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ret == 0) {
63060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	while (*cur == '/') {
631ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    cur++;
63260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret = xmlParse3986Segment(&cur, 0, 1);
63360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (ret != 0) return(ret);
63460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
635ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
63660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
63760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->path != NULL) xmlFree(uri->path);
638df143a5041f03a22808b59c76698770b74692815Selim Gurun        if (cur != *str) {
639df143a5041f03a22808b59c76698770b74692815Selim Gurun            if (uri->cleanup & 2)
640df143a5041f03a22808b59c76698770b74692815Selim Gurun                uri->path = STRNDUP(*str, cur - *str);
641df143a5041f03a22808b59c76698770b74692815Selim Gurun            else
642df143a5041f03a22808b59c76698770b74692815Selim Gurun                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
643df143a5041f03a22808b59c76698770b74692815Selim Gurun        } else {
644df143a5041f03a22808b59c76698770b74692815Selim Gurun            uri->path = NULL;
645df143a5041f03a22808b59c76698770b74692815Selim Gurun        }
64660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
64760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
64860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return (0);
64960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
650ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
65160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
65260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986PathRootless:
65360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
65460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
65560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
65660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an path without root and fills in the appropriate fields
65760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
65860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
65960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * path-rootless = segment-nz *( "/" segment )
66060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
66160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
66260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
66360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
66460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986PathRootless(xmlURIPtr uri, const char **str)
66560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
66660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
66760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
668ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
66960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
670ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
67160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = xmlParse3986Segment(&cur, 0, 0);
67260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ret != 0) return(ret);
67360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (*cur == '/') {
67460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur++;
67560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986Segment(&cur, 0, 1);
67660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
67760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
67860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
67960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->path != NULL) xmlFree(uri->path);
680df143a5041f03a22808b59c76698770b74692815Selim Gurun        if (cur != *str) {
681df143a5041f03a22808b59c76698770b74692815Selim Gurun            if (uri->cleanup & 2)
682df143a5041f03a22808b59c76698770b74692815Selim Gurun                uri->path = STRNDUP(*str, cur - *str);
683df143a5041f03a22808b59c76698770b74692815Selim Gurun            else
684df143a5041f03a22808b59c76698770b74692815Selim Gurun                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
685df143a5041f03a22808b59c76698770b74692815Selim Gurun        } else {
686df143a5041f03a22808b59c76698770b74692815Selim Gurun            uri->path = NULL;
687df143a5041f03a22808b59c76698770b74692815Selim Gurun        }
68860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
68960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
69060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return (0);
69160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
692ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
69360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
69460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986PathNoScheme:
69560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
69660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
69760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
69860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an path which is not a scheme and fills in the appropriate fields
69960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
70060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
70160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * path-noscheme = segment-nz-nc *( "/" segment )
70260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
70360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
70460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
70560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
70660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986PathNoScheme(xmlURIPtr uri, const char **str)
70760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
70860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
70960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
710ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
71160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
712ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
71360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = xmlParse3986Segment(&cur, ':', 0);
71460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ret != 0) return(ret);
71560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (*cur == '/') {
71660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur++;
71760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986Segment(&cur, 0, 1);
71860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
71960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
72060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
72160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->path != NULL) xmlFree(uri->path);
722df143a5041f03a22808b59c76698770b74692815Selim Gurun        if (cur != *str) {
723df143a5041f03a22808b59c76698770b74692815Selim Gurun            if (uri->cleanup & 2)
724df143a5041f03a22808b59c76698770b74692815Selim Gurun                uri->path = STRNDUP(*str, cur - *str);
725df143a5041f03a22808b59c76698770b74692815Selim Gurun            else
726df143a5041f03a22808b59c76698770b74692815Selim Gurun                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
727df143a5041f03a22808b59c76698770b74692815Selim Gurun        } else {
728df143a5041f03a22808b59c76698770b74692815Selim Gurun            uri->path = NULL;
729df143a5041f03a22808b59c76698770b74692815Selim Gurun        }
73060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
73160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
73260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return (0);
73360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
734ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
73560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
73660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986HierPart:
73760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
73860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
73960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
74060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an hierarchical part and fills in the appropriate fields
74160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
74260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
74360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * hier-part     = "//" authority path-abempty
74460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                / path-absolute
74560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                / path-rootless
74660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *                / path-empty
74760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
74860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
74960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
75060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
75160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986HierPart(xmlURIPtr uri, const char **str)
75260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
75360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *cur;
75460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
755ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
75660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = *str;
757ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
75860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if ((*cur == '/') && (*(cur + 1) == '/')) {
75960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur += 2;
76060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986Authority(uri, &cur);
76160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
76260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986PathAbEmpty(uri, &cur);
76360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
76460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	*str = cur;
76560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(0);
76660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    } else if (*cur == '/') {
76760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlParse3986PathAbsolute(uri, &cur);
76860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
76960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    } else if (ISA_PCHAR(cur)) {
77060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlParse3986PathRootless(uri, &cur);
77160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
77260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    } else {
77360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	/* path-empty is effectively empty */
77460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri != NULL) {
77560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (uri->path != NULL) xmlFree(uri->path);
77660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    uri->path = NULL;
77760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
778ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
77960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *str = cur;
78060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return (0);
78160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
782ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
78360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
78460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986RelativeRef:
78560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
78660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
78760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
78860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an URI string and fills in the appropriate fields
78960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
79060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
79160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
79260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * relative-part = "//" authority path-abempty
79360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *               / path-absolute
79460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *               / path-noscheme
79560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *               / path-empty
79660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
79760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
79860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
79960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
80060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986RelativeRef(xmlURIPtr uri, const char *str) {
80160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
802ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
80360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if ((*str == '/') && (*(str + 1) == '/')) {
80460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        str += 2;
80560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986Authority(uri, &str);
80660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
80760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986PathAbEmpty(uri, &str);
80860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
80960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    } else if (*str == '/') {
81060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986PathAbsolute(uri, &str);
81160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
81260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    } else if (ISA_PCHAR(str)) {
81360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlParse3986PathNoScheme(uri, &str);
81460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
81560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    } else {
81660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	/* path-empty is effectively empty */
81760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri != NULL) {
81860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (uri->path != NULL) xmlFree(uri->path);
81960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    uri->path = NULL;
82060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
821ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
822ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
82360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*str == '?') {
82460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	str++;
82560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986Query(uri, &str);
82660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
82760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
82860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*str == '#') {
82960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	str++;
83060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986Fragment(uri, &str);
83160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
83260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
83360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*str != 0) {
83460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	xmlCleanURI(uri);
83560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(1);
83660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
837ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    return(0);
838ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
839ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
84060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
84160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
84260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986URI:
84360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
84460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
84560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
84660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an URI string and fills in the appropriate fields
84760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
84860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
84960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * scheme ":" hier-part [ "?" query ] [ "#" fragment ]
85060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
85160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
85260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
85360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
85460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986URI(xmlURIPtr uri, const char *str) {
85560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
85660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
85760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = xmlParse3986Scheme(uri, &str);
85860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ret != 0) return(ret);
85960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*str != ':') {
86060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(1);
86160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
86260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    str++;
86360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = xmlParse3986HierPart(uri, &str);
86460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ret != 0) return(ret);
86560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*str == '?') {
86660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	str++;
86760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986Query(uri, &str);
86860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
86960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
87060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*str == '#') {
87160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	str++;
87260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986Fragment(uri, &str);
87360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) return(ret);
87460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
87560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (*str != 0) {
87660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	xmlCleanURI(uri);
877ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return(1);
87860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
879ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    return(0);
880ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
881ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
882ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
88360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParse3986URIReference:
88460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
88560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
886ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
88760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an URI reference string and fills in the appropriate fields
88860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of the @uri structure
889ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
89060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * URI-reference = URI / relative-ref
89160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
89260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
893ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
89460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int
89560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParse3986URIReference(xmlURIPtr uri, const char *str) {
89660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
897ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
898ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (str == NULL)
89960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(-1);
90060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlCleanURI(uri);
901ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
90260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    /*
90360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * Try first to parse absolute refs, then fallback to relative if
90460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * it fails.
90560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     */
90660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = xmlParse3986URI(uri, str);
90760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ret != 0) {
90860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	xmlCleanURI(uri);
90960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlParse3986RelativeRef(uri, str);
91060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret != 0) {
91160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    xmlCleanURI(uri);
91260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    return(ret);
91360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
91460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
91560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(0);
91660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
91760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
91860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
91960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParseURI:
92060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the URI string to analyze
92160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
92260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an URI based on RFC 3986
92360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
92460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
92560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
92660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns a newly built xmlURIPtr or NULL in case of error
92760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
92860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlURIPtr
92960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParseURI(const char *str) {
93060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlURIPtr uri;
93160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
93260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
93360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (str == NULL)
93460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(NULL);
93560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri = xmlCreateURI();
93660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
93760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParse3986URIReference(uri, str);
93860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (ret) {
93960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    xmlFreeURI(uri);
940ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    return(NULL);
941ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
94260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
94360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(uri);
94460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
94560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
94660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
94760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParseURIReference:
94860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an URI structure
94960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to analyze
95060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
95160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an URI reference string based on RFC 3986 and fills in the
95260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * appropriate fields of the @uri structure
95360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
95460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * URI-reference = URI / relative-ref
95560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
95660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or the error code
95760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
95860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottint
95960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParseURIReference(xmlURIPtr uri, const char *str) {
96060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(xmlParse3986URIReference(uri, str));
96160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
96260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
96360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
96460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlParseURIRaw:
96560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the URI string to analyze
96660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @raw:  if 1 unescaping of URI pieces are disabled
96760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
96860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Parse an URI but allows to keep intact the original fragments.
96960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
97060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * URI-reference = URI / relative-ref
97160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
97260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns a newly built xmlURIPtr or NULL in case of error
97360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
97460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlURIPtr
97560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlParseURIRaw(const char *str, int raw) {
97660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlURIPtr uri;
97760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret;
97860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
97960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (str == NULL)
98060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(NULL);
98160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri = xmlCreateURI();
98260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri != NULL) {
98360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (raw) {
98460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    uri->cleanup |= 2;
98560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
98660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = xmlParseURIReference(uri, str);
98760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (ret) {
98860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    xmlFreeURI(uri);
98960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    return(NULL);
990ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
991ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
99260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(uri);
99360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
99460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
99560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/************************************************************************
99660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *									*
99760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *			Generic URI structure functions			*
99860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *									*
99960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott ************************************************************************/
100060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
100160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
100260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlCreateURI:
100360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
100460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Simply creates an empty xmlURI
100560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
100660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns the new structure or NULL in case of error
100760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
100860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlURIPtr
100960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlCreateURI(void) {
101060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlURIPtr ret;
101160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
101260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI));
101360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ret == NULL) {
101494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        xmlURIErrMemory("creating URI structure\n");
101560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(NULL);
101660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
101760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    memset(ret, 0, sizeof(xmlURI));
1018ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    return(ret);
1019ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
1020ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1021ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
102294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * xmlSaveUriRealloc:
102394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun *
102494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * Function to handle properly a reallocation when saving an URI
102594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * Also imposes some limit on the length of an URI string output
102694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun */
102794442ad4107000e6d49f9b85a46a591495a57632Selim Gurunstatic xmlChar *
102894442ad4107000e6d49f9b85a46a591495a57632Selim GurunxmlSaveUriRealloc(xmlChar *ret, int *max) {
102994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    xmlChar *temp;
103094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    int tmp;
103194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun
103294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    if (*max > MAX_URI_LENGTH) {
103394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        xmlURIErrMemory("reaching arbitrary MAX_URI_LENGTH limit\n");
103494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        return(NULL);
103594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    }
103694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    tmp = *max * 2;
103794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    temp = (xmlChar *) xmlRealloc(ret, (tmp + 1));
103894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    if (temp == NULL) {
103994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        xmlURIErrMemory("saving URI\n");
104094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        return(NULL);
104194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    }
104294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    *max = tmp;
104394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    return(temp);
104494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun}
104594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun
104694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun/**
104760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlSaveUri:
104860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an xmlURI
1049ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
105060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Save the URI as an escaped string
1051ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
105260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns a new string (to be deallocated by caller)
1053ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
1054ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source ProjectxmlChar *
105560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlSaveUri(xmlURIPtr uri) {
105660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlChar *ret = NULL;
105760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlChar *temp;
105860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *p;
105960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int len;
106060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int max;
1061ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
106260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri == NULL) return(NULL);
1063ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1064ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
106560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    max = 80;
106660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar));
1067ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ret == NULL) {
106894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        xmlURIErrMemory("saving URI\n");
1069ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return(NULL);
1070ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
107160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    len = 0;
107260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
107360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->scheme != NULL) {
107460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	p = uri->scheme;
107560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	while (*p != 0) {
107660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (len >= max) {
107794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                temp = xmlSaveUriRealloc(ret, &max);
107894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                if (temp == NULL) goto mem_error;
107960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret = temp;
108060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
108160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[len++] = *p++;
108260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
108360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (len >= max) {
108494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun            temp = xmlSaveUriRealloc(ret, &max);
108594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun            if (temp == NULL) goto mem_error;
108694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun            ret = temp;
1087ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
108860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret[len++] = ':';
108960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
109060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->opaque != NULL) {
109160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	p = uri->opaque;
109260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	while (*p != 0) {
109360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (len + 3 >= max) {
109494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                temp = xmlSaveUriRealloc(ret, &max);
109594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                if (temp == NULL) goto mem_error;
109694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                ret = temp;
109760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
109860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p)))
109960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = *p++;
110060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else {
110160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		int val = *(unsigned char *)p++;
110260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		int hi = val / 0x10, lo = val % 0x10;
110360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = '%';
110460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = hi + (hi > 9? 'A'-10 : '0');
110560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = lo + (lo > 9? 'A'-10 : '0');
110660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
110760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
110860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    } else {
110960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->server != NULL) {
111060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (len + 3 >= max) {
111194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                temp = xmlSaveUriRealloc(ret, &max);
111294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                if (temp == NULL) goto mem_error;
111394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                ret = temp;
111460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
111560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[len++] = '/';
111660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[len++] = '/';
111760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (uri->user != NULL) {
111860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		p = uri->user;
111960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		while (*p != 0) {
112060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    if (len + 3 >= max) {
112194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        temp = xmlSaveUriRealloc(ret, &max);
112294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        if (temp == NULL) goto mem_error;
112394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                        ret = temp;
112460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    }
112560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    if ((IS_UNRESERVED(*(p))) ||
112660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			((*(p) == ';')) || ((*(p) == ':')) ||
112760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			((*(p) == '&')) || ((*(p) == '=')) ||
112860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			((*(p) == '+')) || ((*(p) == '$')) ||
112960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			((*(p) == ',')))
113060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			ret[len++] = *p++;
113160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    else {
113260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			int val = *(unsigned char *)p++;
113360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			int hi = val / 0x10, lo = val % 0x10;
113460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			ret[len++] = '%';
113560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			ret[len++] = hi + (hi > 9? 'A'-10 : '0');
113660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott			ret[len++] = lo + (lo > 9? 'A'-10 : '0');
113760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    }
113860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
113960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if (len + 3 >= max) {
114094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    temp = xmlSaveUriRealloc(ret, &max);
114194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    if (temp == NULL) goto mem_error;
114294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    ret = temp;
114360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
114460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = '@';
114560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
114660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    p = uri->server;
114760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    while (*p != 0) {
114860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if (len >= max) {
114994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    temp = xmlSaveUriRealloc(ret, &max);
115094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    if (temp == NULL) goto mem_error;
115194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    ret = temp;
115260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
115360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = *p++;
115460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
115560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (uri->port > 0) {
115660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if (len + 10 >= max) {
115794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    temp = xmlSaveUriRealloc(ret, &max);
115894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    if (temp == NULL) goto mem_error;
115994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    ret = temp;
116060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
116160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		len += snprintf((char *) &ret[len], max - len, ":%d", uri->port);
116260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
116360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	} else if (uri->authority != NULL) {
116460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (len + 3 >= max) {
116594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                temp = xmlSaveUriRealloc(ret, &max);
116694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                if (temp == NULL) goto mem_error;
116794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                ret = temp;
116860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
116960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[len++] = '/';
117060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[len++] = '/';
117160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    p = uri->authority;
117260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    while (*p != 0) {
117360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if (len + 3 >= max) {
117494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    temp = xmlSaveUriRealloc(ret, &max);
117594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    if (temp == NULL) goto mem_error;
117694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    ret = temp;
117760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
117860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if ((IS_UNRESERVED(*(p))) ||
117960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott                    ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) ||
118060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott                    ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||
118160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott                    ((*(p) == '=')) || ((*(p) == '+')))
118260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = *p++;
118360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		else {
118460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    int val = *(unsigned char *)p++;
118560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    int hi = val / 0x10, lo = val % 0x10;
118660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = '%';
118760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
118860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
118960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
119060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
119160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	} else if (uri->scheme != NULL) {
119260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (len + 3 >= max) {
119394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                temp = xmlSaveUriRealloc(ret, &max);
119494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                if (temp == NULL) goto mem_error;
119594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                ret = temp;
119660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
119760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[len++] = '/';
119860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[len++] = '/';
119960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
120060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->path != NULL) {
120160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    p = uri->path;
120260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    /*
120360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	     * the colon in file:///d: should not be escaped or
120460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	     * Windows accesses fail later.
120560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	     */
120660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if ((uri->scheme != NULL) &&
120760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		(p[0] == '/') &&
120860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		(((p[1] >= 'a') && (p[1] <= 'z')) ||
120960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		 ((p[1] >= 'A') && (p[1] <= 'Z'))) &&
121060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		(p[2] == ':') &&
121160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	        (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
121260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if (len + 3 >= max) {
121394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    temp = xmlSaveUriRealloc(ret, &max);
121494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    if (temp == NULL) goto mem_error;
121594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    ret = temp;
121660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
121760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = *p++;
121860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = *p++;
121960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = *p++;
122060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
122160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    while (*p != 0) {
122260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if (len + 3 >= max) {
122394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    temp = xmlSaveUriRealloc(ret, &max);
122494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    if (temp == NULL) goto mem_error;
122594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    ret = temp;
122660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
122760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) ||
122860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott                    ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) ||
122960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	            ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||
123060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	            ((*(p) == ',')))
123160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = *p++;
123260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		else {
123360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    int val = *(unsigned char *)p++;
123460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    int hi = val / 0x10, lo = val % 0x10;
123560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = '%';
123660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
123760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
123860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
123960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
124060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
124160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (uri->query_raw != NULL) {
124260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (len + 1 >= max) {
124394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                temp = xmlSaveUriRealloc(ret, &max);
124494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                if (temp == NULL) goto mem_error;
124594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                ret = temp;
124660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
124760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[len++] = '?';
124860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    p = uri->query_raw;
124960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    while (*p != 0) {
125060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if (len + 1 >= max) {
125194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    temp = xmlSaveUriRealloc(ret, &max);
125294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    if (temp == NULL) goto mem_error;
125394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    ret = temp;
125460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
125560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = *p++;
125660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
125760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	} else if (uri->query != NULL) {
125860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (len + 3 >= max) {
125994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                temp = xmlSaveUriRealloc(ret, &max);
126094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                if (temp == NULL) goto mem_error;
126194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                ret = temp;
126260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
126360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[len++] = '?';
126460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    p = uri->query;
126560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    while (*p != 0) {
126660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if (len + 3 >= max) {
126794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    temp = xmlSaveUriRealloc(ret, &max);
126894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    if (temp == NULL) goto mem_error;
126994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                    ret = temp;
127060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
127194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun		if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
127260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = *p++;
127360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		else {
127460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    int val = *(unsigned char *)p++;
127560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    int hi = val / 0x10, lo = val % 0x10;
127660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = '%';
127760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
127860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
127960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		}
128060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
1281ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
1282ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
128360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->fragment != NULL) {
128460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (len + 3 >= max) {
128594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun            temp = xmlSaveUriRealloc(ret, &max);
128694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun            if (temp == NULL) goto mem_error;
128794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun            ret = temp;
128860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
128960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret[len++] = '#';
129060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	p = uri->fragment;
129160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	while (*p != 0) {
129260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (len + 3 >= max) {
129394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                temp = xmlSaveUriRealloc(ret, &max);
129494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                if (temp == NULL) goto mem_error;
129594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                ret = temp;
129660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
129794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun	    if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
129860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = *p++;
129960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else {
130060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		int val = *(unsigned char *)p++;
130160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		int hi = val / 0x10, lo = val % 0x10;
130260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = '%';
130360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = hi + (hi > 9? 'A'-10 : '0');
130460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[len++] = lo + (lo > 9? 'A'-10 : '0');
130560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
130660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
1307ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
130860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (len >= max) {
130994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        temp = xmlSaveUriRealloc(ret, &max);
131094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        if (temp == NULL) goto mem_error;
131194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        ret = temp;
1312ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1313df143a5041f03a22808b59c76698770b74692815Selim Gurun    ret[len] = 0;
131460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(ret);
131594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun
131694442ad4107000e6d49f9b85a46a591495a57632Selim Gurunmem_error:
131794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    xmlFree(ret);
131894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    return(NULL);
1319ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
1320ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1321ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
132260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlPrintURI:
132360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @stream:  a FILE* for the output
132460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an xmlURI
1325ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
132660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Prints the URI in the stream @stream.
1327ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
132860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottvoid
132960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlPrintURI(FILE *stream, xmlURIPtr uri) {
133060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlChar *out;
1331ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
133260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    out = xmlSaveUri(uri);
133360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (out != NULL) {
133460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	fprintf(stream, "%s", (char *) out);
133560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	xmlFree(out);
1336ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1337ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
1338ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1339ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
134060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlCleanURI:
134160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an xmlURI
1342ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
134360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Make sure the xmlURI struct is free of content
1344ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
134560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic void
134660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlCleanURI(xmlURIPtr uri) {
134760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri == NULL) return;
1348ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
134960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->scheme != NULL) xmlFree(uri->scheme);
135060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri->scheme = NULL;
135160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->server != NULL) xmlFree(uri->server);
135260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri->server = NULL;
135360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->user != NULL) xmlFree(uri->user);
135460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri->user = NULL;
135560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->path != NULL) xmlFree(uri->path);
135660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri->path = NULL;
135760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->fragment != NULL) xmlFree(uri->fragment);
135860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri->fragment = NULL;
135960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->opaque != NULL) xmlFree(uri->opaque);
136060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri->opaque = NULL;
136160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->authority != NULL) xmlFree(uri->authority);
136260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri->authority = NULL;
136360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->query != NULL) xmlFree(uri->query);
136460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri->query = NULL;
136560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->query_raw != NULL) xmlFree(uri->query_raw);
136660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    uri->query_raw = NULL;
136760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott}
1368ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
136960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/**
137060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlFreeURI:
137160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @uri:  pointer to an xmlURI
137260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
137360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Free up the xmlURI struct
137460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott */
137560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottvoid
137660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlFreeURI(xmlURIPtr uri) {
137760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri == NULL) return;
137860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
137960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->scheme != NULL) xmlFree(uri->scheme);
138060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->server != NULL) xmlFree(uri->server);
138160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->user != NULL) xmlFree(uri->user);
138260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->path != NULL) xmlFree(uri->path);
138360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->fragment != NULL) xmlFree(uri->fragment);
138460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->opaque != NULL) xmlFree(uri->opaque);
138560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->authority != NULL) xmlFree(uri->authority);
138660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->query != NULL) xmlFree(uri->query);
138760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->query_raw != NULL) xmlFree(uri->query_raw);
138860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlFree(uri);
1389ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
1390ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
139160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott/************************************************************************
139260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *									*
139360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *			Helper functions				*
139460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *									*
139560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott ************************************************************************/
139660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
1397ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
139860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlNormalizeURIPath:
139960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @path:  pointer to the path string
1400ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
140160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Applies the 5 normalization steps to a path string--that is, RFC 2396
140260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Section 5.2, steps 6.c through 6.g.
1403ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
140460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Normalization occurs directly on the string, no new allocation is done
140560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
140660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns 0 or an error code
1407ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
140860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottint
140960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlNormalizeURIPath(char *path) {
141060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    char *cur, *out;
1411ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
141260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (path == NULL)
1413ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return(-1);
1414ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
141560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    /* Skip all initial "/" chars.  We want to get to the beginning of the
141660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * first non-empty segment.
1417ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
141860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = path;
141960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (cur[0] == '/')
142060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      ++cur;
142160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (cur[0] == '\0')
142260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      return(0);
142360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
142460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    /* Keep everything we've seen so far.  */
142560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    out = cur;
142660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
1427ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
142860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * Analyze each segment in sequence for cases (c) and (d).
1429ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
143060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (cur[0] != '\0') {
1431ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/*
143260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	 * c) All occurrences of "./", where "." is a complete path segment,
143360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	 *    are removed from the buffer string.
1434ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 */
143560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if ((cur[0] == '.') && (cur[1] == '/')) {
143660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    cur += 2;
143760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    /* '//' normalization should be done at this point too */
143860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    while (cur[0] == '/')
1439ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		cur++;
144060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    continue;
1441ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
1442ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
144360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	/*
144460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	 * d) If the buffer string ends with "." as a complete path segment,
144560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	 *    that "." is removed.
144660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	 */
144760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if ((cur[0] == '.') && (cur[1] == '\0'))
144860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    break;
1449ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
145060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	/* Otherwise keep the segment.  */
145160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	while (cur[0] != '/') {
145260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott            if (cur[0] == '\0')
145360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott              goto done_cd;
145460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    (out++)[0] = (cur++)[0];
145560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
145660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	/* nomalize // */
145760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	while ((cur[0] == '/') && (cur[1] == '/'))
145860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    cur++;
1459ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
146060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        (out++)[0] = (cur++)[0];
1461ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
146260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott done_cd:
146360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    out[0] = '\0';
146460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
146560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    /* Reset to the beginning of the first segment for the next sequence.  */
146660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    cur = path;
146760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (cur[0] == '/')
146860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      ++cur;
146960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (cur[0] == '\0')
147060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(0);
147160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
147260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    /*
147360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * Analyze each segment in sequence for cases (e) and (f).
147460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *
147560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * e) All occurrences of "<segment>/../", where <segment> is a
147660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    complete path segment not equal to "..", are removed from the
147760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    buffer string.  Removal of these path segments is performed
147860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    iteratively, removing the leftmost matching pattern on each
147960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    iteration, until no matching pattern remains.
148060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *
148160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * f) If the buffer string ends with "<segment>/..", where <segment>
148260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    is a complete path segment not equal to "..", that
148360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    "<segment>/.." is removed.
148460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *
148560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * To satisfy the "iterative" clause in (e), we need to collapse the
148660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * string every time we find something that needs to be removed.  Thus,
148760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * we don't need to keep two pointers into the string: we only need a
148860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * "current position" pointer.
148960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     */
149060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while (1) {
149160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        char *segp, *tmp;
1492ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
149360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        /* At the beginning of each iteration of this loop, "cur" points to
149460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * the first character of the segment we want to examine.
149560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         */
1496ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
149760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        /* Find the end of the current segment.  */
149860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segp = cur;
149960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        while ((segp[0] != '/') && (segp[0] != '\0'))
150060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          ++segp;
1501ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
150260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        /* If this is the last segment, we're done (we need at least two
150360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * segments to meet the criteria for the (e) and (f) cases).
150460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         */
150560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (segp[0] == '\0')
150660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          break;
1507ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
150860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        /* If the first segment is "..", or if the next segment _isn't_ "..",
150960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * keep this segment and try the next one.
151060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         */
151160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ++segp;
151260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (((cur[0] == '.') && (cur[1] == '.') && (segp == cur+3))
151360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott            || ((segp[0] != '.') || (segp[1] != '.')
151460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott                || ((segp[2] != '/') && (segp[2] != '\0')))) {
151560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          cur = segp;
151660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          continue;
1517ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        }
1518ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
151960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        /* If we get here, remove this segment and the next one and back up
152060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * to the previous segment (if there is one), to implement the
152160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * "iteratively" clause.  It's pretty much impossible to back up
152260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * while maintaining two pointers into the buffer, so just compact
152360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * the whole buffer now.
1524ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project         */
1525ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
152660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        /* If this is the end of the buffer, we're done.  */
152760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (segp[2] == '\0') {
152860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          cur[0] = '\0';
152960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          break;
1530ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        }
153160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        /* Valgrind complained, strcpy(cur, segp + 3); */
153294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        /* string will overlap, do not use strcpy */
153394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        tmp = cur;
153494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        segp += 3;
153594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        while ((*tmp++ = *segp++) != 0)
153694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun          ;
1537ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
153860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        /* If there are no previous segments, then keep going from here.  */
153960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segp = cur;
154060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        while ((segp > path) && ((--segp)[0] == '/'))
154160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          ;
154260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (segp == path)
154360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          continue;
1544ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
154560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        /* "segp" is pointing to the end of a previous segment; find it's
154660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * start.  We need to back up to the previous segment and start
154760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * over with that to handle things like "foo/bar/../..".  If we
154860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * don't do this, then on the first pass we'll remove the "bar/..",
154960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * but be pointing at the second ".." so we won't realize we can also
155060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         * remove the "foo/..".
155160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott         */
155260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        cur = segp;
155360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        while ((cur > path) && (cur[-1] != '/'))
155460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          --cur;
155560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
155660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    out[0] = '\0';
1557ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1558ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
155960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * g) If the resulting buffer string still begins with one or more
156060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    complete path segments of "..", then the reference is
156160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    considered to be in error. Implementations may handle this
156260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    error by retaining these components in the resolved path (i.e.,
156360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    treating them as part of the final URI), by removing them from
156460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    the resolved path (i.e., discarding relative levels above the
156560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *    root), or by avoiding traversal of the reference.
156660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     *
156760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott     * We discard them from the final path.
1568ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
156960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (path[0] == '/') {
157060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      cur = path;
157160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      while ((cur[0] == '/') && (cur[1] == '.') && (cur[2] == '.')
157260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott             && ((cur[3] == '/') || (cur[3] == '\0')))
157360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	cur += 3;
1574ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
157560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      if (cur != path) {
157660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	out = path;
157760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	while (cur[0] != '\0')
157860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott          (out++)[0] = (cur++)[0];
157960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	out[0] = 0;
158060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott      }
1581ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1582ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1583ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    return(0);
1584ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
1585ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
158660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottstatic int is_hex(char c) {
158760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (((c >= '0') && (c <= '9')) ||
158860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ((c >= 'a') && (c <= 'f')) ||
158960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ((c >= 'A') && (c <= 'F')))
1590ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return(1);
159160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(0);
1592ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
1593ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1594ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
159560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlURIUnescapeString:
159660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string to unescape
159760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @len:   the length in bytes to unescape (or <= 0 to indicate full string)
159860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @target:  optional destination buffer
1599ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
160060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Unescaping routine, but does not check that the string is an URI. The
160160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * output is a direct unsigned char translation of %XX values (no encoding)
160260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Note that the length of the result can only be smaller or same size as
160360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * the input string.
1604ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
160560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns a copy of the string, but unescaped, will return NULL only in case
160660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * of error
1607ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
160860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scottchar *
160960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlURIUnescapeString(const char *str, int len, char *target) {
161060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    char *ret, *out;
161160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const char *in;
1612ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1613ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (str == NULL)
161460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(NULL);
161560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (len <= 0) len = strlen(str);
161660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (len < 0) return(NULL);
161760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
161860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (target == NULL) {
161960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = (char *) xmlMallocAtomic(len + 1);
162060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (ret == NULL) {
162194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun            xmlURIErrMemory("unescaping URI value\n");
162260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    return(NULL);
1623ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
162460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    } else
162560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ret = target;
162660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    in = str;
162760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    out = ret;
162860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while(len > 0) {
162960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) {
163060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    in++;
163194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun	    if ((*in >= '0') && (*in <= '9'))
163260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	        *out = (*in - '0');
163360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else if ((*in >= 'a') && (*in <= 'f'))
163460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	        *out = (*in - 'a') + 10;
163560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else if ((*in >= 'A') && (*in <= 'F'))
163660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	        *out = (*in - 'A') + 10;
163760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    in++;
163894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun	    if ((*in >= '0') && (*in <= '9'))
163960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	        *out = *out * 16 + (*in - '0');
164060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else if ((*in >= 'a') && (*in <= 'f'))
164160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	        *out = *out * 16 + (*in - 'a') + 10;
164260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else if ((*in >= 'A') && (*in <= 'F'))
164360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	        *out = *out * 16 + (*in - 'A') + 10;
164460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    in++;
164560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    len -= 3;
164660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    out++;
164760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	} else {
164860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    *out++ = *in++;
164960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    len--;
1650ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
1651ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
165260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    *out = 0;
1653ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    return(ret);
1654ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
1655ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1656ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
165760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlURIEscapeStr:
165860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  string to escape
165960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @list: exception list string of chars not to escape
1660ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
166160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * This routine escapes a string to hex, ignoring reserved characters (a-z)
166260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * and the characters in the exception list.
1663ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
166460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns a new escaped string or NULL in case of error.
1665ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
166660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlChar *
166760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlURIEscapeStr(const xmlChar *str, const xmlChar *list) {
166860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlChar *ret, ch;
166960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlChar *temp;
167060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    const xmlChar *in;
167194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    int len, out;
1672ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1673ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (str == NULL)
167460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(NULL);
167560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (str[0] == 0)
167660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(xmlStrdup(str));
167760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    len = xmlStrlen(str);
167860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (!(len > 0)) return(NULL);
1679ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
168060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    len += 20;
168160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = (xmlChar *) xmlMallocAtomic(len);
168260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (ret == NULL) {
168394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        xmlURIErrMemory("escaping URI value\n");
168460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	return(NULL);
1685ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
168660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    in = (const xmlChar *) str;
168760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    out = 0;
168860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    while(*in != 0) {
168960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if (len - out <= 3) {
169094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun            temp = xmlSaveUriRealloc(ret, &len);
169160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (temp == NULL) {
169294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun                xmlURIErrMemory("escaping URI value\n");
169360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		xmlFree(ret);
169460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		return(NULL);
169560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    }
169660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret = temp;
169760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
169860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
169960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	ch = *in;
170060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
170160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!xmlStrchr(list, ch))) {
170260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    unsigned char val;
170360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[out++] = '%';
170460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    val = ch >> 4;
170560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (val <= 9)
170660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[out++] = '0' + val;
170760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else
170860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[out++] = 'A' + val - 0xA;
170960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    val = ch & 0xF;
171060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    if (val <= 9)
171160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[out++] = '0' + val;
171260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    else
171360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret[out++] = 'A' + val - 0xA;
171460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    in++;
171560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	} else {
171660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	    ret[out++] = *in++;
171760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	}
1718ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1719ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
172060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret[out] = 0;
172160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return(ret);
1722ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
1723ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1724ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
172560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * xmlURIEscape:
172660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * @str:  the string of the URI to escape
1727ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
172860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Escaping routine, does not do validity checks !
172960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * It will try to escape the chars needing this, but this is heuristic
173060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * based it's impossible to be sure.
1731ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
173260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Returns an copy of the string, but escaped
173360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *
173460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * 25 May 2001
173560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * Uses xmlParseURI and xmlURIEscapeStr to try to escape correctly
173660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott * according to RFC2396.
173760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott *   - Carl Douglas
1738ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
173960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlChar *
174060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick ScottxmlURIEscape(const xmlChar * str)
174160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott{
174260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlChar *ret, *segment = NULL;
1743ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlURIPtr uri;
174460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    int ret2;
174560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
174660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#define NULLCHK(p) if(!p) { \
174794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun         xmlURIErrMemory("escaping URI value\n"); \
174894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun         xmlFreeURI(uri); \
174994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun         return NULL; } \
1750ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1751ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (str == NULL)
175260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        return (NULL);
175360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
1754ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    uri = xmlCreateURI();
1755ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (uri != NULL) {
175660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	/*
175760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	 * Allow escaping errors in the unescaped form
175860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott	 */
175960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        uri->cleanup = 1;
176060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret2 = xmlParseURIReference(uri, (const char *)str);
176160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        if (ret2) {
176260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott            xmlFreeURI(uri);
176360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott            return (NULL);
176460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        }
1765ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1766ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
176760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (!uri)
176860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        return NULL;
1769ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
177060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    ret = NULL;
177160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
177260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->scheme) {
177360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segment = xmlURIEscapeStr(BAD_CAST uri->scheme, BAD_CAST "+-.");
177460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NULLCHK(segment)
177560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, segment);
177660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, BAD_CAST ":");
177760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        xmlFree(segment);
1778ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
177960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
178060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->authority) {
178160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segment =
178260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott            xmlURIEscapeStr(BAD_CAST uri->authority, BAD_CAST "/?;:@");
178360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NULLCHK(segment)
178460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, BAD_CAST "//");
178560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, segment);
178660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        xmlFree(segment);
178760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
178860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
178960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->user) {
179060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segment = xmlURIEscapeStr(BAD_CAST uri->user, BAD_CAST ";:&=+$,");
179160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NULLCHK(segment)
179294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun		ret = xmlStrcat(ret,BAD_CAST "//");
179360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, segment);
179460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, BAD_CAST "@");
179560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        xmlFree(segment);
179660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
179760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
179860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->server) {
179960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@");
180060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NULLCHK(segment)
180160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		if (uri->user == NULL)
180260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott		ret = xmlStrcat(ret, BAD_CAST "//");
180360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, segment);
180460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        xmlFree(segment);
180560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
180660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
180760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->port) {
180860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        xmlChar port[10];
180960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
181060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        snprintf((char *) port, 10, "%d", uri->port);
181160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, BAD_CAST ":");
181260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, port);
181360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
181460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
181560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->path) {
181660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segment =
181760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott            xmlURIEscapeStr(BAD_CAST uri->path, BAD_CAST ":@&=+$,/?;");
181860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NULLCHK(segment)
181960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, segment);
182060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        xmlFree(segment);
182160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
182260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
182360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->query_raw) {
182460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, BAD_CAST "?");
182560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, BAD_CAST uri->query_raw);
182660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
182760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    else if (uri->query) {
182860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segment =
182960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott            xmlURIEscapeStr(BAD_CAST uri->query, BAD_CAST ";/?:@&=+,$");
183060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NULLCHK(segment)
183160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, BAD_CAST "?");
183260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, segment);
183360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        xmlFree(segment);
183460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
183560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
183660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->opaque) {
183760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segment = xmlURIEscapeStr(BAD_CAST uri->opaque, BAD_CAST "");
183860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NULLCHK(segment)
183960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, segment);
184060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        xmlFree(segment);
184160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
184260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
184360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if (uri->fragment) {
184460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        segment = xmlURIEscapeStr(BAD_CAST uri->fragment, BAD_CAST "#");
184560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        NULLCHK(segment)
184660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, BAD_CAST "#");
184760a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        ret = xmlStrcat(ret, segment);
184860a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        xmlFree(segment);
184960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    }
185060a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
185160a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    xmlFreeURI(uri);
185260a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott#undef NULLCHK
185360a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
185460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    return (ret);
1855ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
1856ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1857ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/************************************************************************
1858ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *									*
1859ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *			Public functions				*
1860ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *									*
1861ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project ************************************************************************/
1862ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1863ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
1864ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * xmlBuildURI:
1865ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * @URI:  the URI instance found in the document
1866ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * @base:  the base value
1867ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
1868ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * Computes he final URI of the reference done by checking that
1869ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * the given URI is valid, and building the final URI using the
187094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * base URI. This is processed according to section 5.2 of the
1871ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * RFC 2396
1872ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
1873ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * 5.2. Resolving Relative References to Absolute Form
1874ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
1875ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * Returns a new URI string (to be freed by the caller) or NULL in case
1876ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *         of error.
1877ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
1878ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source ProjectxmlChar *
1879ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source ProjectxmlBuildURI(const xmlChar *URI, const xmlChar *base) {
1880ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlChar *val = NULL;
1881ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    int ret, len, indx, cur, out;
1882ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlURIPtr ref = NULL;
1883ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlURIPtr bas = NULL;
1884ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlURIPtr res = NULL;
1885ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1886ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
1887ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * 1) The URI reference is parsed into the potential four components and
1888ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    fragment identifier, as described in Section 4.3.
1889ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *
1890ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    NOTE that a completely empty URI is treated by modern browsers
1891ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    as a reference to "." rather than as a synonym for the current
1892ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    URI.  Should we do that here?
1893ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
189494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    if (URI == NULL)
1895ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ret = -1;
1896ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    else {
1897ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (*URI) {
1898ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    ref = xmlCreateURI();
1899ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    if (ref == NULL)
1900ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		goto done;
1901ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    ret = xmlParseURIReference(ref, (const char *) URI);
1902ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
1903ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	else
1904ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    ret = 0;
1905ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1906ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ret != 0)
1907ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
1908ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((ref != NULL) && (ref->scheme != NULL)) {
1909ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/*
1910ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 * The URI is absolute don't modify.
1911ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 */
1912ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	val = xmlStrdup(URI);
1913ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
1914ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1915ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (base == NULL)
1916ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ret = -1;
1917ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    else {
1918ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	bas = xmlCreateURI();
1919ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (bas == NULL)
1920ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    goto done;
1921ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ret = xmlParseURIReference(bas, (const char *) base);
1922ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1923ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ret != 0) {
1924ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (ref)
1925ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    val = xmlSaveUri(ref);
1926ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
1927ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1928ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref == NULL) {
1929ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/*
1930ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 * the base fragment must be ignored
1931ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 */
1932ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (bas->fragment != NULL) {
1933ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    xmlFree(bas->fragment);
1934ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    bas->fragment = NULL;
1935ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
1936ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	val = xmlSaveUri(bas);
1937ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
1938ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1939ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1940ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
1941ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * 2) If the path component is empty and the scheme, authority, and
1942ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    query components are undefined, then it is a reference to the
1943ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    current document and we are done.  Otherwise, the reference URI's
1944ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    query and fragment components are defined as found (or not found)
1945ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    within the URI reference and not inherited from the base URI.
1946ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *
1947ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    NOTE that in modern browsers, the parsing differs from the above
1948ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    in the following aspect:  the query component is allowed to be
1949ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    defined while still treating this as a reference to the current
1950ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    document.
1951ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
1952ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    res = xmlCreateURI();
1953ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (res == NULL)
1954ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
1955ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((ref->scheme == NULL) && (ref->path == NULL) &&
1956ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	((ref->authority == NULL) && (ref->server == NULL))) {
1957ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (bas->scheme != NULL)
1958ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->scheme = xmlMemStrdup(bas->scheme);
1959ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (bas->authority != NULL)
1960ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->authority = xmlMemStrdup(bas->authority);
1961ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	else if (bas->server != NULL) {
1962ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->server = xmlMemStrdup(bas->server);
1963ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    if (bas->user != NULL)
1964ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		res->user = xmlMemStrdup(bas->user);
196594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun	    res->port = bas->port;
1966ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
1967ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (bas->path != NULL)
1968ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->path = xmlMemStrdup(bas->path);
1969ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (ref->query_raw != NULL)
1970ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->query_raw = xmlMemStrdup (ref->query_raw);
1971ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	else if (ref->query != NULL)
1972ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->query = xmlMemStrdup(ref->query);
1973ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	else if (bas->query_raw != NULL)
1974ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->query_raw = xmlMemStrdup(bas->query_raw);
1975ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	else if (bas->query != NULL)
1976ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->query = xmlMemStrdup(bas->query);
1977ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (ref->fragment != NULL)
1978ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->fragment = xmlMemStrdup(ref->fragment);
1979ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto step_7;
1980ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1981ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
1982ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
1983ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * 3) If the scheme component is defined, indicating that the reference
1984ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    starts with a scheme name, then the reference is interpreted as an
1985ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    absolute URI and we are done.  Otherwise, the reference URI's
1986ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    scheme is inherited from the base URI's scheme component.
1987ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
1988ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref->scheme != NULL) {
1989ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	val = xmlSaveUri(ref);
1990ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
1991ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
1992ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (bas->scheme != NULL)
1993ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	res->scheme = xmlMemStrdup(bas->scheme);
199494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun
1995ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref->query_raw != NULL)
1996ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	res->query_raw = xmlMemStrdup(ref->query_raw);
1997ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    else if (ref->query != NULL)
1998ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	res->query = xmlMemStrdup(ref->query);
1999ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref->fragment != NULL)
2000ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	res->fragment = xmlMemStrdup(ref->fragment);
2001ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2002ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2003ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * 4) If the authority component is defined, then the reference is a
2004ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    network-path and we skip to step 7.  Otherwise, the reference
2005ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    URI's authority is inherited from the base URI's authority
2006ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    component, which will also be undefined if the URI scheme does not
2007ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    use an authority component.
2008ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2009ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((ref->authority != NULL) || (ref->server != NULL)) {
2010ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (ref->authority != NULL)
2011ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->authority = xmlMemStrdup(ref->authority);
2012ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	else {
2013ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->server = xmlMemStrdup(ref->server);
2014ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    if (ref->user != NULL)
2015ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		res->user = xmlMemStrdup(ref->user);
201694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun            res->port = ref->port;
2017ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2018ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (ref->path != NULL)
2019ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->path = xmlMemStrdup(ref->path);
2020ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto step_7;
2021ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2022ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (bas->authority != NULL)
2023ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	res->authority = xmlMemStrdup(bas->authority);
2024ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    else if (bas->server != NULL) {
2025ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	res->server = xmlMemStrdup(bas->server);
2026ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (bas->user != NULL)
2027ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->user = xmlMemStrdup(bas->user);
202894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun	res->port = bas->port;
2029ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2030ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2031ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2032ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * 5) If the path component begins with a slash character ("/"), then
2033ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    the reference is an absolute-path and we skip to step 7.
2034ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2035ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((ref->path != NULL) && (ref->path[0] == '/')) {
2036ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	res->path = xmlMemStrdup(ref->path);
2037ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto step_7;
2038ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2039ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2040ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2041ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2042ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * 6) If this step is reached, then we are resolving a relative-path
2043ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    reference.  The relative path needs to be merged with the base
2044ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    URI's path.  Although there are many ways to do this, we will
2045ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    describe a simple method using a separate string buffer.
2046ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *
2047ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * Allocate a buffer large enough for the result string.
2048ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2049ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    len = 2; /* extra / and 0 */
2050ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref->path != NULL)
2051ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	len += strlen(ref->path);
2052ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (bas->path != NULL)
2053ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	len += strlen(bas->path);
2054ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    res->path = (char *) xmlMallocAtomic(len);
2055ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (res->path == NULL) {
205694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        xmlURIErrMemory("resolving URI against base\n");
2057ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
2058ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2059ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    res->path[0] = 0;
2060ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2061ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2062ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * a) All but the last segment of the base URI's path component is
2063ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    copied to the buffer.  In other words, any characters after the
2064ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    last (right-most) slash character, if any, are excluded.
2065ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2066ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    cur = 0;
2067ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    out = 0;
2068ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (bas->path != NULL) {
2069ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	while (bas->path[cur] != 0) {
2070ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    while ((bas->path[cur] != 0) && (bas->path[cur] != '/'))
2071ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		cur++;
2072ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    if (bas->path[cur] == 0)
2073ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		break;
2074ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2075ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    cur++;
2076ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    while (out < cur) {
2077ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		res->path[out] = bas->path[out];
2078ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		out++;
2079ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    }
2080ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2081ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2082ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    res->path[out] = 0;
2083ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2084ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2085ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * b) The reference's path component is appended to the buffer
2086ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    string.
2087ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2088ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref->path != NULL && ref->path[0] != 0) {
2089ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	indx = 0;
2090ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/*
2091ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 * Ensure the path includes a '/'
2092ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 */
2093ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if ((out == 0) && (bas->server != NULL))
2094ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->path[out++] = '/';
2095ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	while (ref->path[indx] != 0) {
2096ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    res->path[out++] = ref->path[indx++];
2097ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2098ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2099ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    res->path[out] = 0;
2100ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2101ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2102ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * Steps c) to h) are really path normalization steps
2103ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2104ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlNormalizeURIPath(res->path);
2105ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2106ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Projectstep_7:
2107ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2108ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2109ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * 7) The resulting URI components, including any inherited from the
2110ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    base URI, are recombined to give the absolute form of the URI
2111ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *    reference.
2112ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2113ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    val = xmlSaveUri(res);
2114ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2115ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Projectdone:
2116ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref != NULL)
2117ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	xmlFreeURI(ref);
2118ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (bas != NULL)
2119ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	xmlFreeURI(bas);
2120ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (res != NULL)
2121ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	xmlFreeURI(res);
2122ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    return(val);
2123ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
2124ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2125ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
2126ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * xmlBuildRelativeURI:
2127ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * @URI:  the URI reference under consideration
2128ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * @base:  the base value
2129ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
2130ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * Expresses the URI of the reference in terms relative to the
2131ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * base.  Some examples of this operation include:
2132ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     base = "http://site1.com/docs/book1.html"
2133ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *        URI input                        URI returned
2134ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     docs/pic1.gif                    pic1.gif
2135ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     docs/img/pic1.gif                img/pic1.gif
2136ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     img/pic1.gif                     ../img/pic1.gif
2137ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     http://site1.com/docs/pic1.gif   pic1.gif
2138ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     http://site2.com/docs/pic1.gif   http://site2.com/docs/pic1.gif
2139ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
2140ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     base = "docs/book1.html"
2141ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *        URI input                        URI returned
2142ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     docs/pic1.gif                    pic1.gif
2143ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     docs/img/pic1.gif                img/pic1.gif
2144ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     img/pic1.gif                     ../img/pic1.gif
2145ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *     http://site1.com/docs/pic1.gif   http://site1.com/docs/pic1.gif
2146ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
2147ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
2148ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * Note: if the URI reference is really wierd or complicated, it may be
2149ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *       worthwhile to first convert it into a "nice" one by calling
2150ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *       xmlBuildURI (using 'base') before calling this routine,
2151ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *       since this routine (for reasonable efficiency) assumes URI has
2152ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *       already been through some validation.
2153ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
2154ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * Returns a new URI string (to be freed by the caller) or NULL in case
2155ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * error.
2156ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
2157ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source ProjectxmlChar *
2158ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source ProjectxmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
2159ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project{
2160ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlChar *val = NULL;
2161ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    int ret;
2162ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    int ix;
2163ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    int pos = 0;
2164ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    int nbslash = 0;
2165ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    int len;
2166ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlURIPtr ref = NULL;
2167ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlURIPtr bas = NULL;
2168ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlChar *bptr, *uptr, *vptr;
2169ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    int remove_path = 0;
2170ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2171ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((URI == NULL) || (*URI == 0))
2172ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return NULL;
2173ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2174ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2175ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * First parse URI into a standard form
2176ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2177ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    ref = xmlCreateURI ();
2178ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref == NULL)
2179ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return NULL;
2180ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /* If URI not already in "relative" form */
2181ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (URI[0] != '.') {
2182ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ret = xmlParseURIReference (ref, (const char *) URI);
2183ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (ret != 0)
2184ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    goto done;		/* Error in URI, return NULL */
2185ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    } else
2186ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ref->path = (char *)xmlStrdup(URI);
2187ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2188ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2189ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * Next parse base into the same standard form
2190ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2191ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((base == NULL) || (*base == 0)) {
2192ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	val = xmlStrdup (URI);
2193ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
2194ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2195ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    bas = xmlCreateURI ();
2196ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (bas == NULL)
2197ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
2198ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (base[0] != '.') {
2199ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ret = xmlParseURIReference (bas, (const char *) base);
2200ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (ret != 0)
2201ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    goto done;		/* Error in base, return NULL */
2202ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    } else
2203ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	bas->path = (char *)xmlStrdup(base);
2204ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2205ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2206ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * If the scheme / server on the URI differs from the base,
2207ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * just return the URI
2208ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2209ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((ref->scheme != NULL) &&
2210ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	((bas->scheme == NULL) ||
2211ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 (xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) ||
2212ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)))) {
2213ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	val = xmlStrdup (URI);
2214ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
2215ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2216ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) {
2217ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	val = xmlStrdup(BAD_CAST "");
2218ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
2219ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2220ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (bas->path == NULL) {
2221ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	val = xmlStrdup((xmlChar *)ref->path);
2222ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
2223ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2224ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref->path == NULL) {
2225ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        ref->path = (char *) "/";
2226ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	remove_path = 1;
2227ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2228ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2229ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2230ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * At this point (at last!) we can compare the two paths
2231ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     *
2232ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * First we take care of the special case where either of the
2233ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * two path components may be missing (bug 316224)
2234ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2235ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (bas->path == NULL) {
2236ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (ref->path != NULL) {
2237ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    uptr = (xmlChar *) ref->path;
2238ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    if (*uptr == '/')
2239ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		uptr++;
2240ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    /* exception characters from xmlSaveUri */
2241ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,");
2242ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2243ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
2244ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2245ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    bptr = (xmlChar *)bas->path;
2246ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref->path == NULL) {
2247ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	for (ix = 0; bptr[ix] != 0; ix++) {
2248ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    if (bptr[ix] == '/')
2249ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		nbslash++;
2250ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2251ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	uptr = NULL;
2252ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	len = 1;	/* this is for a string terminator only */
2253ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    } else {
2254ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2255ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * Next we compare the two strings and find where they first differ
2256ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2257ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/'))
2258ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project            pos += 2;
2259ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if ((*bptr == '.') && (bptr[1] == '/'))
2260ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project            bptr += 2;
2261ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	else if ((*bptr == '/') && (ref->path[pos] != '/'))
2262ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    bptr++;
2263ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0))
2264ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    pos++;
2265ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2266ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (bptr[pos] == ref->path[pos]) {
2267ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    val = xmlStrdup(BAD_CAST "");
2268ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    goto done;		/* (I can't imagine why anyone would do this) */
2269ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2270ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2271ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/*
2272ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 * In URI, "back up" to the last '/' encountered.  This will be the
2273ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 * beginning of the "unique" suffix of URI
2274ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 */
2275ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ix = pos;
2276ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if ((ref->path[ix] == '/') && (ix > 0))
2277ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    ix--;
2278ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/'))
2279ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    ix -= 2;
2280ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	for (; ix > 0; ix--) {
2281ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    if (ref->path[ix] == '/')
2282ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		break;
2283ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2284ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (ix == 0) {
2285ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    uptr = (xmlChar *)ref->path;
2286ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	} else {
2287ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    ix++;
2288ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    uptr = (xmlChar *)&ref->path[ix];
2289ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2290ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2291ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/*
2292ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 * In base, count the number of '/' from the differing point
2293ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 */
2294ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (bptr[pos] != ref->path[pos]) {/* check for trivial URI == base */
2295ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    for (; bptr[ix] != 0; ix++) {
2296ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		if (bptr[ix] == '/')
2297ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		    nbslash++;
2298ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    }
2299ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2300ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	len = xmlStrlen (uptr) + 1;
2301ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
230294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun
2303ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (nbslash == 0) {
2304ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (uptr != NULL)
2305ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    /* exception characters from xmlSaveUri */
2306ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,");
2307ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
2308ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2309ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2310ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2311ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * Allocate just enough space for the returned string -
2312ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * length of the remainder of the URI, plus enough space
2313ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * for the "../" groups, plus one for the terminator
2314ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2315ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    val = (xmlChar *) xmlMalloc (len + 3 * nbslash);
2316ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (val == NULL) {
231794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        xmlURIErrMemory("building relative URI\n");
2318ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	goto done;
2319ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2320ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    vptr = val;
2321ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2322ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * Put in as many "../" as needed
2323ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2324ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    for (; nbslash>0; nbslash--) {
2325ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	*vptr++ = '.';
2326ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	*vptr++ = '.';
2327ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	*vptr++ = '/';
2328ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2329ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2330ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * Finish up with the end of the URI
2331ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2332ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (uptr != NULL) {
2333ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        if ((vptr > val) && (len > 0) &&
2334ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    (uptr[0] == '/') && (vptr[-1] == '/')) {
2335ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    memcpy (vptr, uptr + 1, len - 1);
2336ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    vptr[len - 2] = 0;
2337ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	} else {
2338ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    memcpy (vptr, uptr, len);
2339ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    vptr[len - 1] = 0;
2340ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2341ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    } else {
2342ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	vptr[len - 1] = 0;
2343ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2344ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2345ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /* escape the freshly-built path */
2346ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    vptr = val;
2347ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/* exception characters from xmlSaveUri */
2348ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    val = xmlURIEscapeStr(vptr, BAD_CAST "/;&=+$,");
2349ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlFree(vptr);
2350ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2351ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Projectdone:
2352ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2353ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * Free the working variables
2354ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2355ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (remove_path != 0)
2356ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        ref->path = NULL;
2357ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (ref != NULL)
2358ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	xmlFreeURI (ref);
2359ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (bas != NULL)
2360ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	xmlFreeURI (bas);
2361ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2362ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    return val;
2363ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
2364ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2365ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
2366ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * xmlCanonicPath:
2367ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * @path:  the resource locator in a filesystem notation
2368ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
236994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * Constructs a canonic path from the specified path.
2370ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
237194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * Returns a new canonic path, or a duplicate of the path parameter if the
2372ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * construction fails. The caller is responsible for freeing the memory occupied
237394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * by the returned string. If there is insufficient memory available, or the
2374ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * argument is NULL, the function returns NULL.
2375ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
237694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun#define IS_WINDOWS_PATH(p)					\
2377ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	((p != NULL) &&						\
2378ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 (((p[0] >= 'a') && (p[0] <= 'z')) ||			\
2379ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	  ((p[0] >= 'A') && (p[0] <= 'Z'))) &&			\
2380ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 (p[1] == ':') && ((p[2] == '/') || (p[2] == '\\')))
2381ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source ProjectxmlChar *
2382ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source ProjectxmlCanonicPath(const xmlChar *path)
2383ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project{
2384ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/*
2385ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * For Windows implementations, additional work needs to be done to
2386ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * replace backslashes in pathnames with "forward slashes"
2387ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
238894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun#if defined(_WIN32) && !defined(__CYGWIN__)
2389ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    int len = 0;
2390ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    int i = 0;
2391ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlChar *p = NULL;
2392ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#endif
2393ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlURIPtr uri;
2394ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlChar *ret;
2395ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    const xmlChar *absuri;
2396ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2397ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (path == NULL)
2398ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return(NULL);
239960a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
240094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun#if defined(_WIN32)
240194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    /*
240294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun     * We must not change the backslashes to slashes if the the path
240394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun     * starts with \\?\
240494442ad4107000e6d49f9b85a46a591495a57632Selim Gurun     * Those paths can be up to 32k characters long.
240594442ad4107000e6d49f9b85a46a591495a57632Selim Gurun     * Was added specifically for OpenOffice, those paths can't be converted
240694442ad4107000e6d49f9b85a46a591495a57632Selim Gurun     * to URIs anyway.
240794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun     */
240894442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
240994442ad4107000e6d49f9b85a46a591495a57632Selim Gurun        (path[3] == '\\') )
241094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun	return xmlStrdup((const xmlChar *) path);
241194442ad4107000e6d49f9b85a46a591495a57632Selim Gurun#endif
241294442ad4107000e6d49f9b85a46a591495a57632Selim Gurun
241394442ad4107000e6d49f9b85a46a591495a57632Selim Gurun	/* sanitize filename starting with // so it can be used as URI */
241460a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott    if ((path[0] == '/') && (path[1] == '/') && (path[2] != '/'))
241560a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott        path++;
241660a4c356ee9ce5e9ccb23347c0381f0436192691Patrick Scott
2417ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((uri = xmlParseURI((const char *) path)) != NULL) {
2418ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	xmlFreeURI(uri);
2419ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return xmlStrdup(path);
2420ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2421ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2422ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /* Check if this is an "absolute uri" */
2423ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    absuri = xmlStrstr(path, BAD_CAST "://");
2424ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (absuri != NULL) {
2425ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        int l, j;
2426ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	unsigned char c;
2427ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	xmlChar *escURI;
2428ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2429ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        /*
2430ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 * this looks like an URI where some parts have not been
2431ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 * escaped leading to a parsing problem.  Check that the first
2432ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 * part matches a protocol.
2433ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	 */
2434ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	l = absuri - path;
2435ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/* Bypass if first part (part before the '://') is > 20 chars */
2436ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if ((l <= 0) || (l > 20))
2437ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    goto path_processing;
2438ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/* Bypass if any non-alpha characters are present in first part */
2439ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	for (j = 0;j < l;j++) {
2440ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    c = path[j];
2441ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))))
2442ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	        goto path_processing;
2443ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2444ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2445ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/* Escape all except the characters specified in the supplied path */
2446ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        escURI = xmlURIEscapeStr(path, BAD_CAST ":/?_.#&;=");
2447ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (escURI != NULL) {
2448ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    /* Try parsing the escaped path */
2449ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    uri = xmlParseURI((const char *) escURI);
2450ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    /* If successful, return the escaped string */
2451ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    if (uri != NULL) {
2452ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	        xmlFreeURI(uri);
2453ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project		return escURI;
2454ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    }
2455ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2456ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2457ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2458ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Projectpath_processing:
2459ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/* For Windows implementations, replace backslashes with 'forward slashes' */
246094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun#if defined(_WIN32) && !defined(__CYGWIN__)
2461ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /*
2462ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     * Create a URI structure
2463ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project     */
2464ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    uri = xmlCreateURI();
2465ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (uri == NULL) {		/* Guard against 'out of memory' */
2466ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        return(NULL);
2467ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2468ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2469ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    len = xmlStrlen(path);
2470ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((len > 2) && IS_WINDOWS_PATH(path)) {
2471ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        /* make the scheme 'file' */
2472ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	uri->scheme = xmlStrdup(BAD_CAST "file");
2473ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/* allocate space for leading '/' + path + string terminator */
2474ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	uri->path = xmlMallocAtomic(len + 2);
2475ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (uri->path == NULL) {
2476ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    xmlFreeURI(uri);	/* Guard agains 'out of memory' */
2477ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    return(NULL);
2478ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2479ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	/* Put in leading '/' plus path */
2480ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	uri->path[0] = '/';
2481ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	p = uri->path + 1;
2482ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	strncpy(p, path, len + 1);
2483ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    } else {
2484ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	uri->path = xmlStrdup(path);
2485ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (uri->path == NULL) {
2486ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    xmlFreeURI(uri);
2487ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    return(NULL);
2488ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	}
2489ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	p = uri->path;
2490ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2491ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /* Now change all occurences of '\' to '/' */
2492ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    while (*p != '\0') {
2493ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (*p == '\\')
2494ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    *p = '/';
2495ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	p++;
2496ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2497ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2498ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (uri->scheme == NULL) {
2499ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ret = xmlStrdup((const xmlChar *) uri->path);
2500ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    } else {
2501ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ret = xmlSaveUri(uri);
2502ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2503ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2504ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlFreeURI(uri);
2505ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#else
2506ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    ret = xmlStrdup((const xmlChar *) path);
2507ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#endif
2508ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    return(ret);
2509ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
2510ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2511ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project/**
2512ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * xmlPathToURI:
2513ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * @path:  the resource locator in a filesystem notation
2514ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
2515ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * Constructs an URI expressing the existing path
2516ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project *
251794442ad4107000e6d49f9b85a46a591495a57632Selim Gurun * Returns a new URI, or a duplicate of the path parameter if the
2518ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * construction fails. The caller is responsible for freeing the memory
2519ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * occupied by the returned string. If there is insufficient memory available,
2520ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project * or the argument is NULL, the function returns NULL.
2521ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project */
2522ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source ProjectxmlChar *
2523ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source ProjectxmlPathToURI(const xmlChar *path)
2524ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project{
2525ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlURIPtr uri;
2526ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlURI temp;
2527ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlChar *ret, *cal;
2528ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2529ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (path == NULL)
2530ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        return(NULL);
2531ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project
2532ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((uri = xmlParseURI((const char *) path)) != NULL) {
2533ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	xmlFreeURI(uri);
2534ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return xmlStrdup(path);
2535ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2536ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    cal = xmlCanonicPath(path);
2537ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if (cal == NULL)
2538ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project        return(NULL);
2539ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#if defined(_WIN32) && !defined(__CYGWIN__)
254094442ad4107000e6d49f9b85a46a591495a57632Selim Gurun    /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?)
2541ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project       If 'cal' is a valid URI allready then we are done here, as continuing would make
2542ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project       it invalid. */
2543ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    if ((uri = xmlParseURI((const char *) cal)) != NULL) {
2544ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	xmlFreeURI(uri);
2545ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	return cal;
2546ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2547ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    /* 'cal' can contain a relative path with backslashes. If that is processed
2548ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project       by xmlSaveURI, they will be escaped and the external entity loader machinery
2549ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project       will fail. So convert them to slashes. Misuse 'ret' for walking. */
2550ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    ret = cal;
2551ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    while (*ret != '\0') {
2552ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	if (*ret == '\\')
2553ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	    *ret = '/';
2554ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project	ret++;
2555ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    }
2556ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#endif
2557ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    memset(&temp, 0, sizeof(temp));
2558ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    temp.path = (char *) cal;
2559ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    ret = xmlSaveUri(&temp);
2560ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    xmlFree(cal);
2561ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project    return(ret);
2562ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project}
2563ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#define bottom_uri
2564ab4e2e90f63db6b1cd8bb2e453cac899ef43d42bThe Android Open Source Project#include "elfgcchack.h"
2565