Blame uri.c

Packit Service a31ea6
/**
Packit Service a31ea6
 * uri.c: set of generic URI related routines
Packit Service a31ea6
 *
Packit Service a31ea6
 * Reference: RFCs 3986, 2732 and 2373
Packit Service a31ea6
 *
Packit Service a31ea6
 * See Copyright for the status of this software.
Packit Service a31ea6
 *
Packit Service a31ea6
 * daniel@veillard.com
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define IN_LIBXML
Packit Service a31ea6
#include "libxml.h"
Packit Service a31ea6
Packit Service a31ea6
#include <string.h>
Packit Service a31ea6
Packit Service a31ea6
#include <libxml/xmlmemory.h>
Packit Service a31ea6
#include <libxml/uri.h>
Packit Service a31ea6
#include <libxml/globals.h>
Packit Service a31ea6
#include <libxml/xmlerror.h>
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * MAX_URI_LENGTH:
Packit Service a31ea6
 *
Packit Service a31ea6
 * The definition of the URI regexp in the above RFC has no size limit
Packit Service a31ea6
 * In practice they are usually relativey short except for the
Packit Service a31ea6
 * data URI scheme as defined in RFC 2397. Even for data URI the usual
Packit Service a31ea6
 * maximum size before hitting random practical limits is around 64 KB
Packit Service a31ea6
 * and 4KB is usually a maximum admitted limit for proper operations.
Packit Service a31ea6
 * The value below is more a security limit than anything else and
Packit Service a31ea6
 * really should never be hit by 'normal' operations
Packit Service a31ea6
 * Set to 1 MByte in 2012, this is only enforced on output
Packit Service a31ea6
 */
Packit Service a31ea6
#define MAX_URI_LENGTH 1024 * 1024
Packit Service a31ea6
Packit Service a31ea6
static void
Packit Service a31ea6
xmlURIErrMemory(const char *extra)
Packit Service a31ea6
{
Packit Service a31ea6
    if (extra)
Packit Service a31ea6
        __xmlRaiseError(NULL, NULL, NULL,
Packit Service a31ea6
                        NULL, NULL, XML_FROM_URI,
Packit Service a31ea6
                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
Packit Service a31ea6
                        extra, NULL, NULL, 0, 0,
Packit Service a31ea6
                        "Memory allocation failed : %s\n", extra);
Packit Service a31ea6
    else
Packit Service a31ea6
        __xmlRaiseError(NULL, NULL, NULL,
Packit Service a31ea6
                        NULL, NULL, XML_FROM_URI,
Packit Service a31ea6
                        XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0,
Packit Service a31ea6
                        NULL, NULL, NULL, 0, 0,
Packit Service a31ea6
                        "Memory allocation failed\n");
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
static void xmlCleanURI(xmlURIPtr uri);
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * Old rule from 2396 used in legacy handling code
Packit Service a31ea6
 * alpha    = lowalpha | upalpha
Packit Service a31ea6
 */
Packit Service a31ea6
#define IS_ALPHA(x) (IS_LOWALPHA(x) || IS_UPALPHA(x))
Packit Service a31ea6
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * lowalpha = "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" |
Packit Service a31ea6
 *            "k" | "l" | "m" | "n" | "o" | "p" | "q" | "r" | "s" | "t" |
Packit Service a31ea6
 *            "u" | "v" | "w" | "x" | "y" | "z"
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define IS_LOWALPHA(x) (((x) >= 'a') && ((x) <= 'z'))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * upalpha = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" |
Packit Service a31ea6
 *           "K" | "L" | "M" | "N" | "O" | "P" | "Q" | "R" | "S" | "T" |
Packit Service a31ea6
 *           "U" | "V" | "W" | "X" | "Y" | "Z"
Packit Service a31ea6
 */
Packit Service a31ea6
#define IS_UPALPHA(x) (((x) >= 'A') && ((x) <= 'Z'))
Packit Service a31ea6
Packit Service a31ea6
#ifdef IS_DIGIT
Packit Service a31ea6
#undef IS_DIGIT
Packit Service a31ea6
#endif
Packit Service a31ea6
/*
Packit Service a31ea6
 * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
Packit Service a31ea6
 */
Packit Service a31ea6
#define IS_DIGIT(x) (((x) >= '0') && ((x) <= '9'))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * alphanum = alpha | digit
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define IS_ALPHANUM(x) (IS_ALPHA(x) || IS_DIGIT(x))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")"
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define IS_MARK(x) (((x) == '-') || ((x) == '_') || ((x) == '.') ||     \
Packit Service a31ea6
    ((x) == '!') || ((x) == '~') || ((x) == '*') || ((x) == '\'') ||    \
Packit Service a31ea6
    ((x) == '(') || ((x) == ')'))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * unwise = "{" | "}" | "|" | "\" | "^" | "`"
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define IS_UNWISE(p)                                                    \
Packit Service a31ea6
      (((*(p) == '{')) || ((*(p) == '}')) || ((*(p) == '|')) ||         \
Packit Service a31ea6
       ((*(p) == '\\')) || ((*(p) == '^')) || ((*(p) == '[')) ||        \
Packit Service a31ea6
       ((*(p) == ']')) || ((*(p) == '`')))
Packit Service a31ea6
/*
Packit Service a31ea6
 * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," |
Packit Service a31ea6
 *            "[" | "]"
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define IS_RESERVED(x) (((x) == ';') || ((x) == '/') || ((x) == '?') || \
Packit Service a31ea6
        ((x) == ':') || ((x) == '@') || ((x) == '&') || ((x) == '=') || \
Packit Service a31ea6
        ((x) == '+') || ((x) == '$') || ((x) == ',') || ((x) == '[') || \
Packit Service a31ea6
        ((x) == ']'))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * unreserved = alphanum | mark
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define IS_UNRESERVED(x) (IS_ALPHANUM(x) || IS_MARK(x))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * Skip to next pointer char, handle escaped sequences
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define NEXT(p) ((*p == '%')? p += 3 : p++)
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 * Productions from the spec.
Packit Service a31ea6
 *
Packit Service a31ea6
 *    authority     = server | reg_name
Packit Service a31ea6
 *    reg_name      = 1*( unreserved | escaped | "$" | "," |
Packit Service a31ea6
 *                        ";" | ":" | "@" | "&" | "=" | "+" )
Packit Service a31ea6
 *
Packit Service a31ea6
 * path          = [ abs_path | opaque_part ]
Packit Service a31ea6
 */
Packit Service a31ea6
Packit Service a31ea6
#define STRNDUP(s, n) (char *) xmlStrndup((const xmlChar *)(s), (n))
Packit Service a31ea6
Packit Service a31ea6
/************************************************************************
Packit Service a31ea6
 *									*
Packit Service a31ea6
 *                         RFC 3986 parser				*
Packit Service a31ea6
 *									*
Packit Service a31ea6
 ************************************************************************/
Packit Service a31ea6
Packit Service a31ea6
#define ISA_DIGIT(p) ((*(p) >= '0') && (*(p) <= '9'))
Packit Service a31ea6
#define ISA_ALPHA(p) (((*(p) >= 'a') && (*(p) <= 'z')) ||		\
Packit Service a31ea6
                      ((*(p) >= 'A') && (*(p) <= 'Z')))
Packit Service a31ea6
#define ISA_HEXDIG(p)							\
Packit Service a31ea6
       (ISA_DIGIT(p) || ((*(p) >= 'a') && (*(p) <= 'f')) ||		\
Packit Service a31ea6
        ((*(p) >= 'A') && (*(p) <= 'F')))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 *    sub-delims    = "!" / "$" / "&" / "'" / "(" / ")"
Packit Service a31ea6
 *                     / "*" / "+" / "," / ";" / "="
Packit Service a31ea6
 */
Packit Service a31ea6
#define ISA_SUB_DELIM(p)						\
Packit Service a31ea6
      (((*(p) == '!')) || ((*(p) == '$')) || ((*(p) == '&')) ||		\
Packit Service a31ea6
       ((*(p) == '(')) || ((*(p) == ')')) || ((*(p) == '*')) ||		\
Packit Service a31ea6
       ((*(p) == '+')) || ((*(p) == ',')) || ((*(p) == ';')) ||		\
Packit Service a31ea6
       ((*(p) == '=')) || ((*(p) == '\'')))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 *    gen-delims    = ":" / "/" / "?" / "#" / "[" / "]" / "@"
Packit Service a31ea6
 */
Packit Service a31ea6
#define ISA_GEN_DELIM(p)						\
Packit Service a31ea6
      (((*(p) == ':')) || ((*(p) == '/')) || ((*(p) == '?')) ||         \
Packit Service a31ea6
       ((*(p) == '#')) || ((*(p) == '[')) || ((*(p) == ']')) ||         \
Packit Service a31ea6
       ((*(p) == '@')))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 *    reserved      = gen-delims / sub-delims
Packit Service a31ea6
 */
Packit Service a31ea6
#define ISA_RESERVED(p) (ISA_GEN_DELIM(p) || (ISA_SUB_DELIM(p)))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 *    unreserved    = ALPHA / DIGIT / "-" / "." / "_" / "~"
Packit Service a31ea6
 */
Packit Service a31ea6
#define ISA_UNRESERVED(p)						\
Packit Service a31ea6
      ((ISA_ALPHA(p)) || (ISA_DIGIT(p)) || ((*(p) == '-')) ||		\
Packit Service a31ea6
       ((*(p) == '.')) || ((*(p) == '_')) || ((*(p) == '~')))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 *    pct-encoded   = "%" HEXDIG HEXDIG
Packit Service a31ea6
 */
Packit Service a31ea6
#define ISA_PCT_ENCODED(p)						\
Packit Service a31ea6
     ((*(p) == '%') && (ISA_HEXDIG(p + 1)) && (ISA_HEXDIG(p + 2)))
Packit Service a31ea6
Packit Service a31ea6
/*
Packit Service a31ea6
 *    pchar         = unreserved / pct-encoded / sub-delims / ":" / "@"
Packit Service a31ea6
 */
Packit Service a31ea6
#define ISA_PCHAR(p)							\
Packit Service a31ea6
     (ISA_UNRESERVED(p) || ISA_PCT_ENCODED(p) || ISA_SUB_DELIM(p) ||	\
Packit Service a31ea6
      ((*(p) == ':')) || ((*(p) == '@')))
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986Scheme:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  pointer to the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an URI scheme
Packit Service a31ea6
 *
Packit Service a31ea6
 * ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986Scheme(xmlURIPtr uri, const char **str) {
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
Packit Service a31ea6
    if (str == NULL)
Packit Service a31ea6
	return(-1);
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
    if (!ISA_ALPHA(cur))
Packit Service a31ea6
	return(2);
Packit Service a31ea6
    cur++;
Packit Service a31ea6
    while (ISA_ALPHA(cur) || ISA_DIGIT(cur) ||
Packit Service a31ea6
           (*cur == '+') || (*cur == '-') || (*cur == '.')) cur++;
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
	if (uri->scheme != NULL) xmlFree(uri->scheme);
Packit Service a31ea6
	uri->scheme = STRNDUP(*str, cur - *str);
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986Fragment:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  pointer to the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse the query part of an URI
Packit Service a31ea6
 *
Packit Service a31ea6
 * fragment      = *( pchar / "/" / "?" )
Packit Service a31ea6
 * NOTE: the strict syntax as defined by 3986 does not allow '[' and ']'
Packit Service a31ea6
 *       in the fragment identifier but this is used very broadly for
Packit Service a31ea6
 *       xpointer scheme selection, so we are allowing it here to not break
Packit Service a31ea6
 *       for example all the DocBook processing chains.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986Fragment(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
Packit Service a31ea6
    if (str == NULL)
Packit Service a31ea6
        return (-1);
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
Packit Service a31ea6
    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
Packit Service a31ea6
           (*cur == '[') || (*cur == ']') ||
Packit Service a31ea6
           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
Packit Service a31ea6
        NEXT(cur);
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
        if (uri->fragment != NULL)
Packit Service a31ea6
            xmlFree(uri->fragment);
Packit Service a31ea6
	if (uri->cleanup & 2)
Packit Service a31ea6
	    uri->fragment = STRNDUP(*str, cur - *str);
Packit Service a31ea6
	else
Packit Service a31ea6
	    uri->fragment = xmlURIUnescapeString(*str, cur - *str, NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986Query:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  pointer to the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse the query part of an URI
Packit Service a31ea6
 *
Packit Service a31ea6
 * query = *uric
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986Query(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
Packit Service a31ea6
    if (str == NULL)
Packit Service a31ea6
        return (-1);
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
Packit Service a31ea6
    while ((ISA_PCHAR(cur)) || (*cur == '/') || (*cur == '?') ||
Packit Service a31ea6
           ((uri != NULL) && (uri->cleanup & 1) && (IS_UNWISE(cur))))
Packit Service a31ea6
        NEXT(cur);
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
        if (uri->query != NULL)
Packit Service a31ea6
            xmlFree(uri->query);
Packit Service a31ea6
	if (uri->cleanup & 2)
Packit Service a31ea6
	    uri->query = STRNDUP(*str, cur - *str);
Packit Service a31ea6
	else
Packit Service a31ea6
	    uri->query = xmlURIUnescapeString(*str, cur - *str, NULL);
Packit Service a31ea6
Packit Service a31ea6
	/* Save the raw bytes of the query as well.
Packit Service a31ea6
	 * See: http://mail.gnome.org/archives/xml/2007-April/thread.html#00114
Packit Service a31ea6
	 */
Packit Service a31ea6
	if (uri->query_raw != NULL)
Packit Service a31ea6
	    xmlFree (uri->query_raw);
Packit Service a31ea6
	uri->query_raw = STRNDUP (*str, cur - *str);
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986Port:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse a port part and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * port          = *DIGIT
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986Port(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur = *str;
Packit Service a31ea6
    unsigned port = 0; /* unsigned for defined overflow behavior */
Packit Service a31ea6
Packit Service a31ea6
    if (ISA_DIGIT(cur)) {
Packit Service a31ea6
	while (ISA_DIGIT(cur)) {
Packit Service a31ea6
	    port = port * 10 + (*cur - '0');
Packit Service a31ea6
Packit Service a31ea6
	    cur++;
Packit Service a31ea6
	}
Packit Service a31ea6
	if (uri != NULL)
Packit Service a31ea6
	    uri->port = port & INT_MAX; /* port value modulo INT_MAX+1 */
Packit Service a31ea6
	*str = cur;
Packit Service a31ea6
	return(0);
Packit Service a31ea6
    }
Packit Service a31ea6
    return(1);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986Userinfo:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an user informations part and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * userinfo      = *( unreserved / pct-encoded / sub-delims / ":" )
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986Userinfo(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) ||
Packit Service a31ea6
           ISA_SUB_DELIM(cur) || (*cur == ':'))
Packit Service a31ea6
	NEXT(cur);
Packit Service a31ea6
    if (*cur == '@') {
Packit Service a31ea6
	if (uri != NULL) {
Packit Service a31ea6
	    if (uri->user != NULL) xmlFree(uri->user);
Packit Service a31ea6
	    if (uri->cleanup & 2)
Packit Service a31ea6
		uri->user = STRNDUP(*str, cur - *str);
Packit Service a31ea6
	    else
Packit Service a31ea6
		uri->user = xmlURIUnescapeString(*str, cur - *str, NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
	*str = cur;
Packit Service a31ea6
	return(0);
Packit Service a31ea6
    }
Packit Service a31ea6
    return(1);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986DecOctet:
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 *    dec-octet     = DIGIT                 ; 0-9
Packit Service a31ea6
 *                  / %x31-39 DIGIT         ; 10-99
Packit Service a31ea6
 *                  / "1" 2DIGIT            ; 100-199
Packit Service a31ea6
 *                  / "2" %x30-34 DIGIT     ; 200-249
Packit Service a31ea6
 *                  / "25" %x30-35          ; 250-255
Packit Service a31ea6
 *
Packit Service a31ea6
 * Skip a dec-octet.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 if found and skipped, 1 otherwise
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986DecOctet(const char **str) {
Packit Service a31ea6
    const char *cur = *str;
Packit Service a31ea6
Packit Service a31ea6
    if (!(ISA_DIGIT(cur)))
Packit Service a31ea6
        return(1);
Packit Service a31ea6
    if (!ISA_DIGIT(cur+1))
Packit Service a31ea6
	cur++;
Packit Service a31ea6
    else if ((*cur != '0') && (ISA_DIGIT(cur + 1)) && (!ISA_DIGIT(cur+2)))
Packit Service a31ea6
	cur += 2;
Packit Service a31ea6
    else if ((*cur == '1') && (ISA_DIGIT(cur + 1)) && (ISA_DIGIT(cur + 2)))
Packit Service a31ea6
	cur += 3;
Packit Service a31ea6
    else if ((*cur == '2') && (*(cur + 1) >= '0') &&
Packit Service a31ea6
	     (*(cur + 1) <= '4') && (ISA_DIGIT(cur + 2)))
Packit Service a31ea6
	cur += 3;
Packit Service a31ea6
    else if ((*cur == '2') && (*(cur + 1) == '5') &&
Packit Service a31ea6
	     (*(cur + 2) >= '0') && (*(cur + 1) <= '5'))
Packit Service a31ea6
	cur += 3;
Packit Service a31ea6
    else
Packit Service a31ea6
        return(1);
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986Host:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an host part and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * host          = IP-literal / IPv4address / reg-name
Packit Service a31ea6
 * IP-literal    = "[" ( IPv6address / IPvFuture  ) "]"
Packit Service a31ea6
 * IPv4address   = dec-octet "." dec-octet "." dec-octet "." dec-octet
Packit Service a31ea6
 * reg-name      = *( unreserved / pct-encoded / sub-delims )
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986Host(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur = *str;
Packit Service a31ea6
    const char *host;
Packit Service a31ea6
Packit Service a31ea6
    host = cur;
Packit Service a31ea6
    /*
Packit Service a31ea6
     * IPv6 and future adressing scheme are enclosed between brackets
Packit Service a31ea6
     */
Packit Service a31ea6
    if (*cur == '[') {
Packit Service a31ea6
        cur++;
Packit Service a31ea6
	while ((*cur != ']') && (*cur != 0))
Packit Service a31ea6
	    cur++;
Packit Service a31ea6
	if (*cur != ']')
Packit Service a31ea6
	    return(1);
Packit Service a31ea6
	cur++;
Packit Service a31ea6
	goto found;
Packit Service a31ea6
    }
Packit Service a31ea6
    /*
Packit Service a31ea6
     * try to parse an IPv4
Packit Service a31ea6
     */
Packit Service a31ea6
    if (ISA_DIGIT(cur)) {
Packit Service a31ea6
        if (xmlParse3986DecOctet(&cur) != 0)
Packit Service a31ea6
	    goto not_ipv4;
Packit Service a31ea6
	if (*cur != '.')
Packit Service a31ea6
	    goto not_ipv4;
Packit Service a31ea6
	cur++;
Packit Service a31ea6
        if (xmlParse3986DecOctet(&cur) != 0)
Packit Service a31ea6
	    goto not_ipv4;
Packit Service a31ea6
	if (*cur != '.')
Packit Service a31ea6
	    goto not_ipv4;
Packit Service a31ea6
        if (xmlParse3986DecOctet(&cur) != 0)
Packit Service a31ea6
	    goto not_ipv4;
Packit Service a31ea6
	if (*cur != '.')
Packit Service a31ea6
	    goto not_ipv4;
Packit Service a31ea6
        if (xmlParse3986DecOctet(&cur) != 0)
Packit Service a31ea6
	    goto not_ipv4;
Packit Service a31ea6
	goto found;
Packit Service a31ea6
not_ipv4:
Packit Service a31ea6
        cur = *str;
Packit Service a31ea6
    }
Packit Service a31ea6
    /*
Packit Service a31ea6
     * then this should be a hostname which can be empty
Packit Service a31ea6
     */
Packit Service a31ea6
    while (ISA_UNRESERVED(cur) || ISA_PCT_ENCODED(cur) || ISA_SUB_DELIM(cur))
Packit Service a31ea6
        NEXT(cur);
Packit Service a31ea6
found:
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
	if (uri->authority != NULL) xmlFree(uri->authority);
Packit Service a31ea6
	uri->authority = NULL;
Packit Service a31ea6
	if (uri->server != NULL) xmlFree(uri->server);
Packit Service a31ea6
	if (cur != host) {
Packit Service a31ea6
	    if (uri->cleanup & 2)
Packit Service a31ea6
		uri->server = STRNDUP(host, cur - host);
Packit Service a31ea6
	    else
Packit Service a31ea6
		uri->server = xmlURIUnescapeString(host, cur - host, NULL);
Packit Service a31ea6
	} else
Packit Service a31ea6
	    uri->server = NULL;
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986Authority:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an authority part and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * authority     = [ userinfo "@" ] host [ ":" port ]
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986Authority(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
    /*
Packit Service a31ea6
     * try to parse an userinfo and check for the trailing @
Packit Service a31ea6
     */
Packit Service a31ea6
    ret = xmlParse3986Userinfo(uri, &cur);
Packit Service a31ea6
    if ((ret != 0) || (*cur != '@'))
Packit Service a31ea6
        cur = *str;
Packit Service a31ea6
    else
Packit Service a31ea6
        cur++;
Packit Service a31ea6
    ret = xmlParse3986Host(uri, &cur);
Packit Service a31ea6
    if (ret != 0) return(ret);
Packit Service a31ea6
    if (*cur == ':') {
Packit Service a31ea6
        cur++;
Packit Service a31ea6
        ret = xmlParse3986Port(uri, &cur);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986Segment:
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 * @forbid: an optional forbidden character
Packit Service a31ea6
 * @empty: allow an empty segment
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse a segment and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * segment       = *pchar
Packit Service a31ea6
 * segment-nz    = 1*pchar
Packit Service a31ea6
 * segment-nz-nc = 1*( unreserved / pct-encoded / sub-delims / "@" )
Packit Service a31ea6
 *               ; non-zero-length segment without any colon ":"
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986Segment(const char **str, char forbid, int empty)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
    if (!ISA_PCHAR(cur)) {
Packit Service a31ea6
        if (empty)
Packit Service a31ea6
	    return(0);
Packit Service a31ea6
	return(1);
Packit Service a31ea6
    }
Packit Service a31ea6
    while (ISA_PCHAR(cur) && (*cur != forbid))
Packit Service a31ea6
        NEXT(cur);
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986PathAbEmpty:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an path absolute or empty and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * path-abempty  = *( "/" segment )
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986PathAbEmpty(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
Packit Service a31ea6
    while (*cur == '/') {
Packit Service a31ea6
        cur++;
Packit Service a31ea6
	ret = xmlParse3986Segment(&cur, 0, 1);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
	if (uri->path != NULL) xmlFree(uri->path);
Packit Service a31ea6
        if (*str != cur) {
Packit Service a31ea6
            if (uri->cleanup & 2)
Packit Service a31ea6
                uri->path = STRNDUP(*str, cur - *str);
Packit Service a31ea6
            else
Packit Service a31ea6
                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
Packit Service a31ea6
        } else {
Packit Service a31ea6
            uri->path = NULL;
Packit Service a31ea6
        }
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986PathAbsolute:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an path absolute and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * path-absolute = "/" [ segment-nz *( "/" segment ) ]
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986PathAbsolute(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
Packit Service a31ea6
    if (*cur != '/')
Packit Service a31ea6
        return(1);
Packit Service a31ea6
    cur++;
Packit Service a31ea6
    ret = xmlParse3986Segment(&cur, 0, 0);
Packit Service a31ea6
    if (ret == 0) {
Packit Service a31ea6
	while (*cur == '/') {
Packit Service a31ea6
	    cur++;
Packit Service a31ea6
	    ret = xmlParse3986Segment(&cur, 0, 1);
Packit Service a31ea6
	    if (ret != 0) return(ret);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
	if (uri->path != NULL) xmlFree(uri->path);
Packit Service a31ea6
        if (cur != *str) {
Packit Service a31ea6
            if (uri->cleanup & 2)
Packit Service a31ea6
                uri->path = STRNDUP(*str, cur - *str);
Packit Service a31ea6
            else
Packit Service a31ea6
                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
Packit Service a31ea6
        } else {
Packit Service a31ea6
            uri->path = NULL;
Packit Service a31ea6
        }
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986PathRootless:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an path without root and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * path-rootless = segment-nz *( "/" segment )
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986PathRootless(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
Packit Service a31ea6
    ret = xmlParse3986Segment(&cur, 0, 0);
Packit Service a31ea6
    if (ret != 0) return(ret);
Packit Service a31ea6
    while (*cur == '/') {
Packit Service a31ea6
        cur++;
Packit Service a31ea6
	ret = xmlParse3986Segment(&cur, 0, 1);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
	if (uri->path != NULL) xmlFree(uri->path);
Packit Service a31ea6
        if (cur != *str) {
Packit Service a31ea6
            if (uri->cleanup & 2)
Packit Service a31ea6
                uri->path = STRNDUP(*str, cur - *str);
Packit Service a31ea6
            else
Packit Service a31ea6
                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
Packit Service a31ea6
        } else {
Packit Service a31ea6
            uri->path = NULL;
Packit Service a31ea6
        }
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986PathNoScheme:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an path which is not a scheme and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * path-noscheme = segment-nz-nc *( "/" segment )
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986PathNoScheme(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
Packit Service a31ea6
    ret = xmlParse3986Segment(&cur, ':', 0);
Packit Service a31ea6
    if (ret != 0) return(ret);
Packit Service a31ea6
    while (*cur == '/') {
Packit Service a31ea6
        cur++;
Packit Service a31ea6
	ret = xmlParse3986Segment(&cur, 0, 1);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
	if (uri->path != NULL) xmlFree(uri->path);
Packit Service a31ea6
        if (cur != *str) {
Packit Service a31ea6
            if (uri->cleanup & 2)
Packit Service a31ea6
                uri->path = STRNDUP(*str, cur - *str);
Packit Service a31ea6
            else
Packit Service a31ea6
                uri->path = xmlURIUnescapeString(*str, cur - *str, NULL);
Packit Service a31ea6
        } else {
Packit Service a31ea6
            uri->path = NULL;
Packit Service a31ea6
        }
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986HierPart:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an hierarchical part and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * hier-part     = "//" authority path-abempty
Packit Service a31ea6
 *                / path-absolute
Packit Service a31ea6
 *                / path-rootless
Packit Service a31ea6
 *                / path-empty
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986HierPart(xmlURIPtr uri, const char **str)
Packit Service a31ea6
{
Packit Service a31ea6
    const char *cur;
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    cur = *str;
Packit Service a31ea6
Packit Service a31ea6
    if ((*cur == '/') && (*(cur + 1) == '/')) {
Packit Service a31ea6
        cur += 2;
Packit Service a31ea6
	ret = xmlParse3986Authority(uri, &cur);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
	if (uri->server == NULL)
Packit Service a31ea6
	    uri->port = -1;
Packit Service a31ea6
	ret = xmlParse3986PathAbEmpty(uri, &cur);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
	*str = cur;
Packit Service a31ea6
	return(0);
Packit Service a31ea6
    } else if (*cur == '/') {
Packit Service a31ea6
        ret = xmlParse3986PathAbsolute(uri, &cur);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    } else if (ISA_PCHAR(cur)) {
Packit Service a31ea6
        ret = xmlParse3986PathRootless(uri, &cur);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    } else {
Packit Service a31ea6
	/* path-empty is effectively empty */
Packit Service a31ea6
	if (uri != NULL) {
Packit Service a31ea6
	    if (uri->path != NULL) xmlFree(uri->path);
Packit Service a31ea6
	    uri->path = NULL;
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    *str = cur;
Packit Service a31ea6
    return (0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986RelativeRef:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an URI string and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * relative-ref  = relative-part [ "?" query ] [ "#" fragment ]
Packit Service a31ea6
 * relative-part = "//" authority path-abempty
Packit Service a31ea6
 *               / path-absolute
Packit Service a31ea6
 *               / path-noscheme
Packit Service a31ea6
 *               / path-empty
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986RelativeRef(xmlURIPtr uri, const char *str) {
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    if ((*str == '/') && (*(str + 1) == '/')) {
Packit Service a31ea6
        str += 2;
Packit Service a31ea6
	ret = xmlParse3986Authority(uri, &str);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
	ret = xmlParse3986PathAbEmpty(uri, &str);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    } else if (*str == '/') {
Packit Service a31ea6
	ret = xmlParse3986PathAbsolute(uri, &str);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    } else if (ISA_PCHAR(str)) {
Packit Service a31ea6
        ret = xmlParse3986PathNoScheme(uri, &str);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    } else {
Packit Service a31ea6
	/* path-empty is effectively empty */
Packit Service a31ea6
	if (uri != NULL) {
Packit Service a31ea6
	    if (uri->path != NULL) xmlFree(uri->path);
Packit Service a31ea6
	    uri->path = NULL;
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (*str == '?') {
Packit Service a31ea6
	str++;
Packit Service a31ea6
	ret = xmlParse3986Query(uri, &str);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (*str == '#') {
Packit Service a31ea6
	str++;
Packit Service a31ea6
	ret = xmlParse3986Fragment(uri, &str);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (*str != 0) {
Packit Service a31ea6
	xmlCleanURI(uri);
Packit Service a31ea6
	return(1);
Packit Service a31ea6
    }
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986URI:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an URI string and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * scheme ":" hier-part [ "?" query ] [ "#" fragment ]
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986URI(xmlURIPtr uri, const char *str) {
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    ret = xmlParse3986Scheme(uri, &str);
Packit Service a31ea6
    if (ret != 0) return(ret);
Packit Service a31ea6
    if (*str != ':') {
Packit Service a31ea6
	return(1);
Packit Service a31ea6
    }
Packit Service a31ea6
    str++;
Packit Service a31ea6
    ret = xmlParse3986HierPart(uri, &str);
Packit Service a31ea6
    if (ret != 0) return(ret);
Packit Service a31ea6
    if (*str == '?') {
Packit Service a31ea6
	str++;
Packit Service a31ea6
	ret = xmlParse3986Query(uri, &str);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (*str == '#') {
Packit Service a31ea6
	str++;
Packit Service a31ea6
	ret = xmlParse3986Fragment(uri, &str);
Packit Service a31ea6
	if (ret != 0) return(ret);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (*str != 0) {
Packit Service a31ea6
	xmlCleanURI(uri);
Packit Service a31ea6
	return(1);
Packit Service a31ea6
    }
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParse3986URIReference:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an URI reference string and fills in the appropriate fields
Packit Service a31ea6
 * of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * URI-reference = URI / relative-ref
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
static int
Packit Service a31ea6
xmlParse3986URIReference(xmlURIPtr uri, const char *str) {
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    if (str == NULL)
Packit Service a31ea6
	return(-1);
Packit Service a31ea6
    xmlCleanURI(uri);
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Try first to parse absolute refs, then fallback to relative if
Packit Service a31ea6
     * it fails.
Packit Service a31ea6
     */
Packit Service a31ea6
    ret = xmlParse3986URI(uri, str);
Packit Service a31ea6
    if (ret != 0) {
Packit Service a31ea6
	xmlCleanURI(uri);
Packit Service a31ea6
        ret = xmlParse3986RelativeRef(uri, str);
Packit Service a31ea6
	if (ret != 0) {
Packit Service a31ea6
	    xmlCleanURI(uri);
Packit Service a31ea6
	    return(ret);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParseURI:
Packit Service a31ea6
 * @str:  the URI string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an URI based on RFC 3986
Packit Service a31ea6
 *
Packit Service a31ea6
 * URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a newly built xmlURIPtr or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
xmlURIPtr
Packit Service a31ea6
xmlParseURI(const char *str) {
Packit Service a31ea6
    xmlURIPtr uri;
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    if (str == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    uri = xmlCreateURI();
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
	ret = xmlParse3986URIReference(uri, str);
Packit Service a31ea6
        if (ret) {
Packit Service a31ea6
	    xmlFreeURI(uri);
Packit Service a31ea6
	    return(NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    return(uri);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParseURIReference:
Packit Service a31ea6
 * @uri:  pointer to an URI structure
Packit Service a31ea6
 * @str:  the string to analyze
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an URI reference string based on RFC 3986 and fills in the
Packit Service a31ea6
 * appropriate fields of the @uri structure
Packit Service a31ea6
 *
Packit Service a31ea6
 * URI-reference = URI / relative-ref
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or the error code
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlParseURIReference(xmlURIPtr uri, const char *str) {
Packit Service a31ea6
    return(xmlParse3986URIReference(uri, str));
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlParseURIRaw:
Packit Service a31ea6
 * @str:  the URI string to analyze
Packit Service a31ea6
 * @raw:  if 1 unescaping of URI pieces are disabled
Packit Service a31ea6
 *
Packit Service a31ea6
 * Parse an URI but allows to keep intact the original fragments.
Packit Service a31ea6
 *
Packit Service a31ea6
 * URI-reference = URI / relative-ref
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a newly built xmlURIPtr or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
xmlURIPtr
Packit Service a31ea6
xmlParseURIRaw(const char *str, int raw) {
Packit Service a31ea6
    xmlURIPtr uri;
Packit Service a31ea6
    int ret;
Packit Service a31ea6
Packit Service a31ea6
    if (str == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    uri = xmlCreateURI();
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
        if (raw) {
Packit Service a31ea6
	    uri->cleanup |= 2;
Packit Service a31ea6
	}
Packit Service a31ea6
	ret = xmlParseURIReference(uri, str);
Packit Service a31ea6
        if (ret) {
Packit Service a31ea6
	    xmlFreeURI(uri);
Packit Service a31ea6
	    return(NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    return(uri);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/************************************************************************
Packit Service a31ea6
 *									*
Packit Service a31ea6
 *			Generic URI structure functions			*
Packit Service a31ea6
 *									*
Packit Service a31ea6
 ************************************************************************/
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlCreateURI:
Packit Service a31ea6
 *
Packit Service a31ea6
 * Simply creates an empty xmlURI
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns the new structure or NULL in case of error
Packit Service a31ea6
 */
Packit Service a31ea6
xmlURIPtr
Packit Service a31ea6
xmlCreateURI(void) {
Packit Service a31ea6
    xmlURIPtr ret;
Packit Service a31ea6
Packit Service a31ea6
    ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlURIErrMemory("creating URI structure\n");
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    memset(ret, 0, sizeof(xmlURI));
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSaveUriRealloc:
Packit Service a31ea6
 *
Packit Service a31ea6
 * Function to handle properly a reallocation when saving an URI
Packit Service a31ea6
 * Also imposes some limit on the length of an URI string output
Packit Service a31ea6
 */
Packit Service a31ea6
static xmlChar *
Packit Service a31ea6
xmlSaveUriRealloc(xmlChar *ret, int *max) {
Packit Service a31ea6
    xmlChar *temp;
Packit Service a31ea6
    int tmp;
Packit Service a31ea6
Packit Service a31ea6
    if (*max > MAX_URI_LENGTH) {
Packit Service a31ea6
        xmlURIErrMemory("reaching arbitrary MAX_URI_LENGTH limit\n");
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    tmp = *max * 2;
Packit Service a31ea6
    temp = (xmlChar *) xmlRealloc(ret, (tmp + 1));
Packit Service a31ea6
    if (temp == NULL) {
Packit Service a31ea6
        xmlURIErrMemory("saving URI\n");
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    *max = tmp;
Packit Service a31ea6
    return(temp);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlSaveUri:
Packit Service a31ea6
 * @uri:  pointer to an xmlURI
Packit Service a31ea6
 *
Packit Service a31ea6
 * Save the URI as an escaped string
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a new string (to be deallocated by caller)
Packit Service a31ea6
 */
Packit Service a31ea6
xmlChar *
Packit Service a31ea6
xmlSaveUri(xmlURIPtr uri) {
Packit Service a31ea6
    xmlChar *ret = NULL;
Packit Service a31ea6
    xmlChar *temp;
Packit Service a31ea6
    const char *p;
Packit Service a31ea6
    int len;
Packit Service a31ea6
    int max;
Packit Service a31ea6
Packit Service a31ea6
    if (uri == NULL) return(NULL);
Packit Service a31ea6
Packit Service a31ea6
Packit Service a31ea6
    max = 80;
Packit Service a31ea6
    ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar));
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlURIErrMemory("saving URI\n");
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    len = 0;
Packit Service a31ea6
Packit Service a31ea6
    if (uri->scheme != NULL) {
Packit Service a31ea6
	p = uri->scheme;
Packit Service a31ea6
	while (*p != 0) {
Packit Service a31ea6
	    if (len >= max) {
Packit Service a31ea6
                temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                if (temp == NULL) goto mem_error;
Packit Service a31ea6
		ret = temp;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    ret[len++] = *p++;
Packit Service a31ea6
	}
Packit Service a31ea6
	if (len >= max) {
Packit Service a31ea6
            temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
            if (temp == NULL) goto mem_error;
Packit Service a31ea6
            ret = temp;
Packit Service a31ea6
	}
Packit Service a31ea6
	ret[len++] = ':';
Packit Service a31ea6
    }
Packit Service a31ea6
    if (uri->opaque != NULL) {
Packit Service a31ea6
	p = uri->opaque;
Packit Service a31ea6
	while (*p != 0) {
Packit Service a31ea6
	    if (len + 3 >= max) {
Packit Service a31ea6
                temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                if (temp == NULL) goto mem_error;
Packit Service a31ea6
                ret = temp;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p)))
Packit Service a31ea6
		ret[len++] = *p++;
Packit Service a31ea6
	    else {
Packit Service a31ea6
		int val = *(unsigned char *)p++;
Packit Service a31ea6
		int hi = val / 0x10, lo = val % 0x10;
Packit Service a31ea6
		ret[len++] = '%';
Packit Service a31ea6
		ret[len++] = hi + (hi > 9? 'A'-10 : '0');
Packit Service a31ea6
		ret[len++] = lo + (lo > 9? 'A'-10 : '0');
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
    } else {
Packit Service a31ea6
	if ((uri->server != NULL) || (uri->port == -1)) {
Packit Service a31ea6
	    if (len + 3 >= max) {
Packit Service a31ea6
                temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                if (temp == NULL) goto mem_error;
Packit Service a31ea6
                ret = temp;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    ret[len++] = '/';
Packit Service a31ea6
	    ret[len++] = '/';
Packit Service a31ea6
	    if (uri->user != NULL) {
Packit Service a31ea6
		p = uri->user;
Packit Service a31ea6
		while (*p != 0) {
Packit Service a31ea6
		    if (len + 3 >= max) {
Packit Service a31ea6
                        temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                        if (temp == NULL) goto mem_error;
Packit Service a31ea6
                        ret = temp;
Packit Service a31ea6
		    }
Packit Service a31ea6
		    if ((IS_UNRESERVED(*(p))) ||
Packit Service a31ea6
			((*(p) == ';')) || ((*(p) == ':')) ||
Packit Service a31ea6
			((*(p) == '&')) || ((*(p) == '=')) ||
Packit Service a31ea6
			((*(p) == '+')) || ((*(p) == '$')) ||
Packit Service a31ea6
			((*(p) == ',')))
Packit Service a31ea6
			ret[len++] = *p++;
Packit Service a31ea6
		    else {
Packit Service a31ea6
			int val = *(unsigned char *)p++;
Packit Service a31ea6
			int hi = val / 0x10, lo = val % 0x10;
Packit Service a31ea6
			ret[len++] = '%';
Packit Service a31ea6
			ret[len++] = hi + (hi > 9? 'A'-10 : '0');
Packit Service a31ea6
			ret[len++] = lo + (lo > 9? 'A'-10 : '0');
Packit Service a31ea6
		    }
Packit Service a31ea6
		}
Packit Service a31ea6
		if (len + 3 >= max) {
Packit Service a31ea6
                    temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                    if (temp == NULL) goto mem_error;
Packit Service a31ea6
                    ret = temp;
Packit Service a31ea6
		}
Packit Service a31ea6
		ret[len++] = '@';
Packit Service a31ea6
	    }
Packit Service a31ea6
	    if (uri->server != NULL) {
Packit Service a31ea6
		p = uri->server;
Packit Service a31ea6
		while (*p != 0) {
Packit Service a31ea6
		    if (len >= max) {
Packit Service a31ea6
			temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
			if (temp == NULL) goto mem_error;
Packit Service a31ea6
			ret = temp;
Packit Service a31ea6
		    }
Packit Service a31ea6
		    ret[len++] = *p++;
Packit Service a31ea6
		}
Packit Service a31ea6
		if (uri->port > 0) {
Packit Service a31ea6
		    if (len + 10 >= max) {
Packit Service a31ea6
			temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
			if (temp == NULL) goto mem_error;
Packit Service a31ea6
			ret = temp;
Packit Service a31ea6
		    }
Packit Service a31ea6
		    len += snprintf((char *) &ret[len], max - len, ":%d", uri->port);
Packit Service a31ea6
		}
Packit Service a31ea6
	    }
Packit Service a31ea6
	} else if (uri->authority != NULL) {
Packit Service a31ea6
	    if (len + 3 >= max) {
Packit Service a31ea6
                temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                if (temp == NULL) goto mem_error;
Packit Service a31ea6
                ret = temp;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    ret[len++] = '/';
Packit Service a31ea6
	    ret[len++] = '/';
Packit Service a31ea6
	    p = uri->authority;
Packit Service a31ea6
	    while (*p != 0) {
Packit Service a31ea6
		if (len + 3 >= max) {
Packit Service a31ea6
                    temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                    if (temp == NULL) goto mem_error;
Packit Service a31ea6
                    ret = temp;
Packit Service a31ea6
		}
Packit Service a31ea6
		if ((IS_UNRESERVED(*(p))) ||
Packit Service a31ea6
                    ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) ||
Packit Service a31ea6
                    ((*(p) == ':')) || ((*(p) == '@')) || ((*(p) == '&')) ||
Packit Service a31ea6
                    ((*(p) == '=')) || ((*(p) == '+')))
Packit Service a31ea6
		    ret[len++] = *p++;
Packit Service a31ea6
		else {
Packit Service a31ea6
		    int val = *(unsigned char *)p++;
Packit Service a31ea6
		    int hi = val / 0x10, lo = val % 0x10;
Packit Service a31ea6
		    ret[len++] = '%';
Packit Service a31ea6
		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
Packit Service a31ea6
		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
Packit Service a31ea6
		}
Packit Service a31ea6
	    }
Packit Service a31ea6
	} else if (uri->scheme != NULL) {
Packit Service a31ea6
	    if (len + 3 >= max) {
Packit Service a31ea6
                temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                if (temp == NULL) goto mem_error;
Packit Service a31ea6
                ret = temp;
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
	if (uri->path != NULL) {
Packit Service a31ea6
	    p = uri->path;
Packit Service a31ea6
	    /*
Packit Service a31ea6
	     * the colon in file:///d: should not be escaped or
Packit Service a31ea6
	     * Windows accesses fail later.
Packit Service a31ea6
	     */
Packit Service a31ea6
	    if ((uri->scheme != NULL) &&
Packit Service a31ea6
		(p[0] == '/') &&
Packit Service a31ea6
		(((p[1] >= 'a') && (p[1] <= 'z')) ||
Packit Service a31ea6
		 ((p[1] >= 'A') && (p[1] <= 'Z'))) &&
Packit Service a31ea6
		(p[2] == ':') &&
Packit Service a31ea6
	        (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) {
Packit Service a31ea6
		if (len + 3 >= max) {
Packit Service a31ea6
                    temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                    if (temp == NULL) goto mem_error;
Packit Service a31ea6
                    ret = temp;
Packit Service a31ea6
		}
Packit Service a31ea6
		ret[len++] = *p++;
Packit Service a31ea6
		ret[len++] = *p++;
Packit Service a31ea6
		ret[len++] = *p++;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    while (*p != 0) {
Packit Service a31ea6
		if (len + 3 >= max) {
Packit Service a31ea6
                    temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                    if (temp == NULL) goto mem_error;
Packit Service a31ea6
                    ret = temp;
Packit Service a31ea6
		}
Packit Service a31ea6
		if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) ||
Packit Service a31ea6
                    ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) ||
Packit Service a31ea6
	            ((*(p) == '=')) || ((*(p) == '+')) || ((*(p) == '$')) ||
Packit Service a31ea6
	            ((*(p) == ',')))
Packit Service a31ea6
		    ret[len++] = *p++;
Packit Service a31ea6
		else {
Packit Service a31ea6
		    int val = *(unsigned char *)p++;
Packit Service a31ea6
		    int hi = val / 0x10, lo = val % 0x10;
Packit Service a31ea6
		    ret[len++] = '%';
Packit Service a31ea6
		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
Packit Service a31ea6
		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
Packit Service a31ea6
		}
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
	if (uri->query_raw != NULL) {
Packit Service a31ea6
	    if (len + 1 >= max) {
Packit Service a31ea6
                temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                if (temp == NULL) goto mem_error;
Packit Service a31ea6
                ret = temp;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    ret[len++] = '?';
Packit Service a31ea6
	    p = uri->query_raw;
Packit Service a31ea6
	    while (*p != 0) {
Packit Service a31ea6
		if (len + 1 >= max) {
Packit Service a31ea6
                    temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                    if (temp == NULL) goto mem_error;
Packit Service a31ea6
                    ret = temp;
Packit Service a31ea6
		}
Packit Service a31ea6
		ret[len++] = *p++;
Packit Service a31ea6
	    }
Packit Service a31ea6
	} else if (uri->query != NULL) {
Packit Service a31ea6
	    if (len + 3 >= max) {
Packit Service a31ea6
                temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                if (temp == NULL) goto mem_error;
Packit Service a31ea6
                ret = temp;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    ret[len++] = '?';
Packit Service a31ea6
	    p = uri->query;
Packit Service a31ea6
	    while (*p != 0) {
Packit Service a31ea6
		if (len + 3 >= max) {
Packit Service a31ea6
                    temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                    if (temp == NULL) goto mem_error;
Packit Service a31ea6
                    ret = temp;
Packit Service a31ea6
		}
Packit Service a31ea6
		if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
Packit Service a31ea6
		    ret[len++] = *p++;
Packit Service a31ea6
		else {
Packit Service a31ea6
		    int val = *(unsigned char *)p++;
Packit Service a31ea6
		    int hi = val / 0x10, lo = val % 0x10;
Packit Service a31ea6
		    ret[len++] = '%';
Packit Service a31ea6
		    ret[len++] = hi + (hi > 9? 'A'-10 : '0');
Packit Service a31ea6
		    ret[len++] = lo + (lo > 9? 'A'-10 : '0');
Packit Service a31ea6
		}
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    if (uri->fragment != NULL) {
Packit Service a31ea6
	if (len + 3 >= max) {
Packit Service a31ea6
            temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
            if (temp == NULL) goto mem_error;
Packit Service a31ea6
            ret = temp;
Packit Service a31ea6
	}
Packit Service a31ea6
	ret[len++] = '#';
Packit Service a31ea6
	p = uri->fragment;
Packit Service a31ea6
	while (*p != 0) {
Packit Service a31ea6
	    if (len + 3 >= max) {
Packit Service a31ea6
                temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
                if (temp == NULL) goto mem_error;
Packit Service a31ea6
                ret = temp;
Packit Service a31ea6
	    }
Packit Service a31ea6
	    if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p))))
Packit Service a31ea6
		ret[len++] = *p++;
Packit Service a31ea6
	    else {
Packit Service a31ea6
		int val = *(unsigned char *)p++;
Packit Service a31ea6
		int hi = val / 0x10, lo = val % 0x10;
Packit Service a31ea6
		ret[len++] = '%';
Packit Service a31ea6
		ret[len++] = hi + (hi > 9? 'A'-10 : '0');
Packit Service a31ea6
		ret[len++] = lo + (lo > 9? 'A'-10 : '0');
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    if (len >= max) {
Packit Service a31ea6
        temp = xmlSaveUriRealloc(ret, &max;;
Packit Service a31ea6
        if (temp == NULL) goto mem_error;
Packit Service a31ea6
        ret = temp;
Packit Service a31ea6
    }
Packit Service a31ea6
    ret[len] = 0;
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
Packit Service a31ea6
mem_error:
Packit Service a31ea6
    xmlFree(ret);
Packit Service a31ea6
    return(NULL);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlPrintURI:
Packit Service a31ea6
 * @stream:  a FILE* for the output
Packit Service a31ea6
 * @uri:  pointer to an xmlURI
Packit Service a31ea6
 *
Packit Service a31ea6
 * Prints the URI in the stream @stream.
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlPrintURI(FILE *stream, xmlURIPtr uri) {
Packit Service a31ea6
    xmlChar *out;
Packit Service a31ea6
Packit Service a31ea6
    out = xmlSaveUri(uri);
Packit Service a31ea6
    if (out != NULL) {
Packit Service a31ea6
	fprintf(stream, "%s", (char *) out);
Packit Service a31ea6
	xmlFree(out);
Packit Service a31ea6
    }
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlCleanURI:
Packit Service a31ea6
 * @uri:  pointer to an xmlURI
Packit Service a31ea6
 *
Packit Service a31ea6
 * Make sure the xmlURI struct is free of content
Packit Service a31ea6
 */
Packit Service a31ea6
static void
Packit Service a31ea6
xmlCleanURI(xmlURIPtr uri) {
Packit Service a31ea6
    if (uri == NULL) return;
Packit Service a31ea6
Packit Service a31ea6
    if (uri->scheme != NULL) xmlFree(uri->scheme);
Packit Service a31ea6
    uri->scheme = NULL;
Packit Service a31ea6
    if (uri->server != NULL) xmlFree(uri->server);
Packit Service a31ea6
    uri->server = NULL;
Packit Service a31ea6
    if (uri->user != NULL) xmlFree(uri->user);
Packit Service a31ea6
    uri->user = NULL;
Packit Service a31ea6
    if (uri->path != NULL) xmlFree(uri->path);
Packit Service a31ea6
    uri->path = NULL;
Packit Service a31ea6
    if (uri->fragment != NULL) xmlFree(uri->fragment);
Packit Service a31ea6
    uri->fragment = NULL;
Packit Service a31ea6
    if (uri->opaque != NULL) xmlFree(uri->opaque);
Packit Service a31ea6
    uri->opaque = NULL;
Packit Service a31ea6
    if (uri->authority != NULL) xmlFree(uri->authority);
Packit Service a31ea6
    uri->authority = NULL;
Packit Service a31ea6
    if (uri->query != NULL) xmlFree(uri->query);
Packit Service a31ea6
    uri->query = NULL;
Packit Service a31ea6
    if (uri->query_raw != NULL) xmlFree(uri->query_raw);
Packit Service a31ea6
    uri->query_raw = NULL;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlFreeURI:
Packit Service a31ea6
 * @uri:  pointer to an xmlURI
Packit Service a31ea6
 *
Packit Service a31ea6
 * Free up the xmlURI struct
Packit Service a31ea6
 */
Packit Service a31ea6
void
Packit Service a31ea6
xmlFreeURI(xmlURIPtr uri) {
Packit Service a31ea6
    if (uri == NULL) return;
Packit Service a31ea6
Packit Service a31ea6
    if (uri->scheme != NULL) xmlFree(uri->scheme);
Packit Service a31ea6
    if (uri->server != NULL) xmlFree(uri->server);
Packit Service a31ea6
    if (uri->user != NULL) xmlFree(uri->user);
Packit Service a31ea6
    if (uri->path != NULL) xmlFree(uri->path);
Packit Service a31ea6
    if (uri->fragment != NULL) xmlFree(uri->fragment);
Packit Service a31ea6
    if (uri->opaque != NULL) xmlFree(uri->opaque);
Packit Service a31ea6
    if (uri->authority != NULL) xmlFree(uri->authority);
Packit Service a31ea6
    if (uri->query != NULL) xmlFree(uri->query);
Packit Service a31ea6
    if (uri->query_raw != NULL) xmlFree(uri->query_raw);
Packit Service a31ea6
    xmlFree(uri);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/************************************************************************
Packit Service a31ea6
 *									*
Packit Service a31ea6
 *			Helper functions				*
Packit Service a31ea6
 *									*
Packit Service a31ea6
 ************************************************************************/
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlNormalizeURIPath:
Packit Service a31ea6
 * @path:  pointer to the path string
Packit Service a31ea6
 *
Packit Service a31ea6
 * Applies the 5 normalization steps to a path string--that is, RFC 2396
Packit Service a31ea6
 * Section 5.2, steps 6.c through 6.g.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Normalization occurs directly on the string, no new allocation is done
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns 0 or an error code
Packit Service a31ea6
 */
Packit Service a31ea6
int
Packit Service a31ea6
xmlNormalizeURIPath(char *path) {
Packit Service a31ea6
    char *cur, *out;
Packit Service a31ea6
Packit Service a31ea6
    if (path == NULL)
Packit Service a31ea6
	return(-1);
Packit Service a31ea6
Packit Service a31ea6
    /* Skip all initial "/" chars.  We want to get to the beginning of the
Packit Service a31ea6
     * first non-empty segment.
Packit Service a31ea6
     */
Packit Service a31ea6
    cur = path;
Packit Service a31ea6
    while (cur[0] == '/')
Packit Service a31ea6
      ++cur;
Packit Service a31ea6
    if (cur[0] == '\0')
Packit Service a31ea6
      return(0);
Packit Service a31ea6
Packit Service a31ea6
    /* Keep everything we've seen so far.  */
Packit Service a31ea6
    out = cur;
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Analyze each segment in sequence for cases (c) and (d).
Packit Service a31ea6
     */
Packit Service a31ea6
    while (cur[0] != '\0') {
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * c) All occurrences of "./", where "." is a complete path segment,
Packit Service a31ea6
	 *    are removed from the buffer string.
Packit Service a31ea6
	 */
Packit Service a31ea6
	if ((cur[0] == '.') && (cur[1] == '/')) {
Packit Service a31ea6
	    cur += 2;
Packit Service a31ea6
	    /* '//' normalization should be done at this point too */
Packit Service a31ea6
	    while (cur[0] == '/')
Packit Service a31ea6
		cur++;
Packit Service a31ea6
	    continue;
Packit Service a31ea6
	}
Packit Service a31ea6
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * d) If the buffer string ends with "." as a complete path segment,
Packit Service a31ea6
	 *    that "." is removed.
Packit Service a31ea6
	 */
Packit Service a31ea6
	if ((cur[0] == '.') && (cur[1] == '\0'))
Packit Service a31ea6
	    break;
Packit Service a31ea6
Packit Service a31ea6
	/* Otherwise keep the segment.  */
Packit Service a31ea6
	while (cur[0] != '/') {
Packit Service a31ea6
            if (cur[0] == '\0')
Packit Service a31ea6
              goto done_cd;
Packit Service a31ea6
	    (out++)[0] = (cur++)[0];
Packit Service a31ea6
	}
Packit Service a31ea6
	/* nomalize // */
Packit Service a31ea6
	while ((cur[0] == '/') && (cur[1] == '/'))
Packit Service a31ea6
	    cur++;
Packit Service a31ea6
Packit Service a31ea6
        (out++)[0] = (cur++)[0];
Packit Service a31ea6
    }
Packit Service a31ea6
 done_cd:
Packit Service a31ea6
    out[0] = '\0';
Packit Service a31ea6
Packit Service a31ea6
    /* Reset to the beginning of the first segment for the next sequence.  */
Packit Service a31ea6
    cur = path;
Packit Service a31ea6
    while (cur[0] == '/')
Packit Service a31ea6
      ++cur;
Packit Service a31ea6
    if (cur[0] == '\0')
Packit Service a31ea6
	return(0);
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Analyze each segment in sequence for cases (e) and (f).
Packit Service a31ea6
     *
Packit Service a31ea6
     * e) All occurrences of "<segment>/../", where <segment> is a
Packit Service a31ea6
     *    complete path segment not equal to "..", are removed from the
Packit Service a31ea6
     *    buffer string.  Removal of these path segments is performed
Packit Service a31ea6
     *    iteratively, removing the leftmost matching pattern on each
Packit Service a31ea6
     *    iteration, until no matching pattern remains.
Packit Service a31ea6
     *
Packit Service a31ea6
     * f) If the buffer string ends with "<segment>/..", where <segment>
Packit Service a31ea6
     *    is a complete path segment not equal to "..", that
Packit Service a31ea6
     *    "<segment>/.." is removed.
Packit Service a31ea6
     *
Packit Service a31ea6
     * To satisfy the "iterative" clause in (e), we need to collapse the
Packit Service a31ea6
     * string every time we find something that needs to be removed.  Thus,
Packit Service a31ea6
     * we don't need to keep two pointers into the string: we only need a
Packit Service a31ea6
     * "current position" pointer.
Packit Service a31ea6
     */
Packit Service a31ea6
    while (1) {
Packit Service a31ea6
        char *segp, *tmp;
Packit Service a31ea6
Packit Service a31ea6
        /* At the beginning of each iteration of this loop, "cur" points to
Packit Service a31ea6
         * the first character of the segment we want to examine.
Packit Service a31ea6
         */
Packit Service a31ea6
Packit Service a31ea6
        /* Find the end of the current segment.  */
Packit Service a31ea6
        segp = cur;
Packit Service a31ea6
        while ((segp[0] != '/') && (segp[0] != '\0'))
Packit Service a31ea6
          ++segp;
Packit Service a31ea6
Packit Service a31ea6
        /* If this is the last segment, we're done (we need at least two
Packit Service a31ea6
         * segments to meet the criteria for the (e) and (f) cases).
Packit Service a31ea6
         */
Packit Service a31ea6
        if (segp[0] == '\0')
Packit Service a31ea6
          break;
Packit Service a31ea6
Packit Service a31ea6
        /* If the first segment is "..", or if the next segment _isn't_ "..",
Packit Service a31ea6
         * keep this segment and try the next one.
Packit Service a31ea6
         */
Packit Service a31ea6
        ++segp;
Packit Service a31ea6
        if (((cur[0] == '.') && (cur[1] == '.') && (segp == cur+3))
Packit Service a31ea6
            || ((segp[0] != '.') || (segp[1] != '.')
Packit Service a31ea6
                || ((segp[2] != '/') && (segp[2] != '\0')))) {
Packit Service a31ea6
          cur = segp;
Packit Service a31ea6
          continue;
Packit Service a31ea6
        }
Packit Service a31ea6
Packit Service a31ea6
        /* If we get here, remove this segment and the next one and back up
Packit Service a31ea6
         * to the previous segment (if there is one), to implement the
Packit Service a31ea6
         * "iteratively" clause.  It's pretty much impossible to back up
Packit Service a31ea6
         * while maintaining two pointers into the buffer, so just compact
Packit Service a31ea6
         * the whole buffer now.
Packit Service a31ea6
         */
Packit Service a31ea6
Packit Service a31ea6
        /* If this is the end of the buffer, we're done.  */
Packit Service a31ea6
        if (segp[2] == '\0') {
Packit Service a31ea6
          cur[0] = '\0';
Packit Service a31ea6
          break;
Packit Service a31ea6
        }
Packit Service a31ea6
        /* Valgrind complained, strcpy(cur, segp + 3); */
Packit Service a31ea6
        /* string will overlap, do not use strcpy */
Packit Service a31ea6
        tmp = cur;
Packit Service a31ea6
        segp += 3;
Packit Service a31ea6
        while ((*tmp++ = *segp++) != 0)
Packit Service a31ea6
          ;
Packit Service a31ea6
Packit Service a31ea6
        /* If there are no previous segments, then keep going from here.  */
Packit Service a31ea6
        segp = cur;
Packit Service a31ea6
        while ((segp > path) && ((--segp)[0] == '/'))
Packit Service a31ea6
          ;
Packit Service a31ea6
        if (segp == path)
Packit Service a31ea6
          continue;
Packit Service a31ea6
Packit Service a31ea6
        /* "segp" is pointing to the end of a previous segment; find it's
Packit Service a31ea6
         * start.  We need to back up to the previous segment and start
Packit Service a31ea6
         * over with that to handle things like "foo/bar/../..".  If we
Packit Service a31ea6
         * don't do this, then on the first pass we'll remove the "bar/..",
Packit Service a31ea6
         * but be pointing at the second ".." so we won't realize we can also
Packit Service a31ea6
         * remove the "foo/..".
Packit Service a31ea6
         */
Packit Service a31ea6
        cur = segp;
Packit Service a31ea6
        while ((cur > path) && (cur[-1] != '/'))
Packit Service a31ea6
          --cur;
Packit Service a31ea6
    }
Packit Service a31ea6
    out[0] = '\0';
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * g) If the resulting buffer string still begins with one or more
Packit Service a31ea6
     *    complete path segments of "..", then the reference is
Packit Service a31ea6
     *    considered to be in error. Implementations may handle this
Packit Service a31ea6
     *    error by retaining these components in the resolved path (i.e.,
Packit Service a31ea6
     *    treating them as part of the final URI), by removing them from
Packit Service a31ea6
     *    the resolved path (i.e., discarding relative levels above the
Packit Service a31ea6
     *    root), or by avoiding traversal of the reference.
Packit Service a31ea6
     *
Packit Service a31ea6
     * We discard them from the final path.
Packit Service a31ea6
     */
Packit Service a31ea6
    if (path[0] == '/') {
Packit Service a31ea6
      cur = path;
Packit Service a31ea6
      while ((cur[0] == '/') && (cur[1] == '.') && (cur[2] == '.')
Packit Service a31ea6
             && ((cur[3] == '/') || (cur[3] == '\0')))
Packit Service a31ea6
	cur += 3;
Packit Service a31ea6
Packit Service a31ea6
      if (cur != path) {
Packit Service a31ea6
	out = path;
Packit Service a31ea6
	while (cur[0] != '\0')
Packit Service a31ea6
          (out++)[0] = (cur++)[0];
Packit Service a31ea6
	out[0] = 0;
Packit Service a31ea6
      }
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
static int is_hex(char c) {
Packit Service a31ea6
    if (((c >= '0') && (c <= '9')) ||
Packit Service a31ea6
        ((c >= 'a') && (c <= 'f')) ||
Packit Service a31ea6
        ((c >= 'A') && (c <= 'F')))
Packit Service a31ea6
	return(1);
Packit Service a31ea6
    return(0);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlURIUnescapeString:
Packit Service a31ea6
 * @str:  the string to unescape
Packit Service a31ea6
 * @len:   the length in bytes to unescape (or <= 0 to indicate full string)
Packit Service a31ea6
 * @target:  optional destination buffer
Packit Service a31ea6
 *
Packit Service a31ea6
 * Unescaping routine, but does not check that the string is an URI. The
Packit Service a31ea6
 * output is a direct unsigned char translation of %XX values (no encoding)
Packit Service a31ea6
 * Note that the length of the result can only be smaller or same size as
Packit Service a31ea6
 * the input string.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a copy of the string, but unescaped, will return NULL only in case
Packit Service a31ea6
 * of error
Packit Service a31ea6
 */
Packit Service a31ea6
char *
Packit Service a31ea6
xmlURIUnescapeString(const char *str, int len, char *target) {
Packit Service a31ea6
    char *ret, *out;
Packit Service a31ea6
    const char *in;
Packit Service a31ea6
Packit Service a31ea6
    if (str == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    if (len <= 0) len = strlen(str);
Packit Service a31ea6
    if (len < 0) return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    if (target == NULL) {
Packit Service a31ea6
	ret = (char *) xmlMallocAtomic(len + 1);
Packit Service a31ea6
	if (ret == NULL) {
Packit Service a31ea6
            xmlURIErrMemory("unescaping URI value\n");
Packit Service a31ea6
	    return(NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
    } else
Packit Service a31ea6
	ret = target;
Packit Service a31ea6
    in = str;
Packit Service a31ea6
    out = ret;
Packit Service a31ea6
    while(len > 0) {
Packit Service a31ea6
	if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) {
Packit Service a31ea6
	    in++;
Packit Service a31ea6
	    if ((*in >= '0') && (*in <= '9'))
Packit Service a31ea6
	        *out = (*in - '0');
Packit Service a31ea6
	    else if ((*in >= 'a') && (*in <= 'f'))
Packit Service a31ea6
	        *out = (*in - 'a') + 10;
Packit Service a31ea6
	    else if ((*in >= 'A') && (*in <= 'F'))
Packit Service a31ea6
	        *out = (*in - 'A') + 10;
Packit Service a31ea6
	    in++;
Packit Service a31ea6
	    if ((*in >= '0') && (*in <= '9'))
Packit Service a31ea6
	        *out = *out * 16 + (*in - '0');
Packit Service a31ea6
	    else if ((*in >= 'a') && (*in <= 'f'))
Packit Service a31ea6
	        *out = *out * 16 + (*in - 'a') + 10;
Packit Service a31ea6
	    else if ((*in >= 'A') && (*in <= 'F'))
Packit Service a31ea6
	        *out = *out * 16 + (*in - 'A') + 10;
Packit Service a31ea6
	    in++;
Packit Service a31ea6
	    len -= 3;
Packit Service a31ea6
	    out++;
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    *out++ = *in++;
Packit Service a31ea6
	    len--;
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    *out = 0;
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlURIEscapeStr:
Packit Service a31ea6
 * @str:  string to escape
Packit Service a31ea6
 * @list: exception list string of chars not to escape
Packit Service a31ea6
 *
Packit Service a31ea6
 * This routine escapes a string to hex, ignoring reserved characters (a-z)
Packit Service a31ea6
 * and the characters in the exception list.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a new escaped string or NULL in case of error.
Packit Service a31ea6
 */
Packit Service a31ea6
xmlChar *
Packit Service a31ea6
xmlURIEscapeStr(const xmlChar *str, const xmlChar *list) {
Packit Service a31ea6
    xmlChar *ret, ch;
Packit Service a31ea6
    xmlChar *temp;
Packit Service a31ea6
    const xmlChar *in;
Packit Service a31ea6
    int len, out;
Packit Service a31ea6
Packit Service a31ea6
    if (str == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    if (str[0] == 0)
Packit Service a31ea6
	return(xmlStrdup(str));
Packit Service a31ea6
    len = xmlStrlen(str);
Packit Service a31ea6
    if (!(len > 0)) return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    len += 20;
Packit Service a31ea6
    ret = (xmlChar *) xmlMallocAtomic(len);
Packit Service a31ea6
    if (ret == NULL) {
Packit Service a31ea6
        xmlURIErrMemory("escaping URI value\n");
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
    in = (const xmlChar *) str;
Packit Service a31ea6
    out = 0;
Packit Service a31ea6
    while(*in != 0) {
Packit Service a31ea6
	if (len - out <= 3) {
Packit Service a31ea6
            temp = xmlSaveUriRealloc(ret, &len;;
Packit Service a31ea6
	    if (temp == NULL) {
Packit Service a31ea6
                xmlURIErrMemory("escaping URI value\n");
Packit Service a31ea6
		xmlFree(ret);
Packit Service a31ea6
		return(NULL);
Packit Service a31ea6
	    }
Packit Service a31ea6
	    ret = temp;
Packit Service a31ea6
	}
Packit Service a31ea6
Packit Service a31ea6
	ch = *in;
Packit Service a31ea6
Packit Service a31ea6
	if ((ch != '@') && (!IS_UNRESERVED(ch)) && (!xmlStrchr(list, ch))) {
Packit Service a31ea6
	    unsigned char val;
Packit Service a31ea6
	    ret[out++] = '%';
Packit Service a31ea6
	    val = ch >> 4;
Packit Service a31ea6
	    if (val <= 9)
Packit Service a31ea6
		ret[out++] = '0' + val;
Packit Service a31ea6
	    else
Packit Service a31ea6
		ret[out++] = 'A' + val - 0xA;
Packit Service a31ea6
	    val = ch & 0xF;
Packit Service a31ea6
	    if (val <= 9)
Packit Service a31ea6
		ret[out++] = '0' + val;
Packit Service a31ea6
	    else
Packit Service a31ea6
		ret[out++] = 'A' + val - 0xA;
Packit Service a31ea6
	    in++;
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    ret[out++] = *in++;
Packit Service a31ea6
	}
Packit Service a31ea6
Packit Service a31ea6
    }
Packit Service a31ea6
    ret[out] = 0;
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlURIEscape:
Packit Service a31ea6
 * @str:  the string of the URI to escape
Packit Service a31ea6
 *
Packit Service a31ea6
 * Escaping routine, does not do validity checks !
Packit Service a31ea6
 * It will try to escape the chars needing this, but this is heuristic
Packit Service a31ea6
 * based it's impossible to be sure.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns an copy of the string, but escaped
Packit Service a31ea6
 *
Packit Service a31ea6
 * 25 May 2001
Packit Service a31ea6
 * Uses xmlParseURI and xmlURIEscapeStr to try to escape correctly
Packit Service a31ea6
 * according to RFC2396.
Packit Service a31ea6
 *   - Carl Douglas
Packit Service a31ea6
 */
Packit Service a31ea6
xmlChar *
Packit Service a31ea6
xmlURIEscape(const xmlChar * str)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlChar *ret, *segment = NULL;
Packit Service a31ea6
    xmlURIPtr uri;
Packit Service a31ea6
    int ret2;
Packit Service a31ea6
Packit Service a31ea6
#define NULLCHK(p) if(!p) { \
Packit Service a31ea6
         xmlURIErrMemory("escaping URI value\n"); \
Packit Service a31ea6
         xmlFreeURI(uri); \
Packit Service a31ea6
         return NULL; } \
Packit Service a31ea6
Packit Service a31ea6
    if (str == NULL)
Packit Service a31ea6
        return (NULL);
Packit Service a31ea6
Packit Service a31ea6
    uri = xmlCreateURI();
Packit Service a31ea6
    if (uri != NULL) {
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * Allow escaping errors in the unescaped form
Packit Service a31ea6
	 */
Packit Service a31ea6
        uri->cleanup = 1;
Packit Service a31ea6
        ret2 = xmlParseURIReference(uri, (const char *)str);
Packit Service a31ea6
        if (ret2) {
Packit Service a31ea6
            xmlFreeURI(uri);
Packit Service a31ea6
            return (NULL);
Packit Service a31ea6
        }
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (!uri)
Packit Service a31ea6
        return NULL;
Packit Service a31ea6
Packit Service a31ea6
    ret = NULL;
Packit Service a31ea6
Packit Service a31ea6
    if (uri->scheme) {
Packit Service a31ea6
        segment = xmlURIEscapeStr(BAD_CAST uri->scheme, BAD_CAST "+-.");
Packit Service a31ea6
        NULLCHK(segment)
Packit Service a31ea6
        ret = xmlStrcat(ret, segment);
Packit Service a31ea6
        ret = xmlStrcat(ret, BAD_CAST ":");
Packit Service a31ea6
        xmlFree(segment);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (uri->authority) {
Packit Service a31ea6
        segment =
Packit Service a31ea6
            xmlURIEscapeStr(BAD_CAST uri->authority, BAD_CAST "/?;:@");
Packit Service a31ea6
        NULLCHK(segment)
Packit Service a31ea6
        ret = xmlStrcat(ret, BAD_CAST "//");
Packit Service a31ea6
        ret = xmlStrcat(ret, segment);
Packit Service a31ea6
        xmlFree(segment);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (uri->user) {
Packit Service a31ea6
        segment = xmlURIEscapeStr(BAD_CAST uri->user, BAD_CAST ";:&=+$,");
Packit Service a31ea6
        NULLCHK(segment)
Packit Service a31ea6
		ret = xmlStrcat(ret,BAD_CAST "//");
Packit Service a31ea6
        ret = xmlStrcat(ret, segment);
Packit Service a31ea6
        ret = xmlStrcat(ret, BAD_CAST "@");
Packit Service a31ea6
        xmlFree(segment);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (uri->server) {
Packit Service a31ea6
        segment = xmlURIEscapeStr(BAD_CAST uri->server, BAD_CAST "/?;:@");
Packit Service a31ea6
        NULLCHK(segment)
Packit Service a31ea6
		if (uri->user == NULL)
Packit Service a31ea6
		ret = xmlStrcat(ret, BAD_CAST "//");
Packit Service a31ea6
        ret = xmlStrcat(ret, segment);
Packit Service a31ea6
        xmlFree(segment);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (uri->port) {
Packit Service a31ea6
        xmlChar port[10];
Packit Service a31ea6
Packit Service a31ea6
        snprintf((char *) port, 10, "%d", uri->port);
Packit Service a31ea6
        ret = xmlStrcat(ret, BAD_CAST ":");
Packit Service a31ea6
        ret = xmlStrcat(ret, port);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (uri->path) {
Packit Service a31ea6
        segment =
Packit Service a31ea6
            xmlURIEscapeStr(BAD_CAST uri->path, BAD_CAST ":@&=+$,/?;");
Packit Service a31ea6
        NULLCHK(segment)
Packit Service a31ea6
        ret = xmlStrcat(ret, segment);
Packit Service a31ea6
        xmlFree(segment);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (uri->query_raw) {
Packit Service a31ea6
        ret = xmlStrcat(ret, BAD_CAST "?");
Packit Service a31ea6
        ret = xmlStrcat(ret, BAD_CAST uri->query_raw);
Packit Service a31ea6
    }
Packit Service a31ea6
    else if (uri->query) {
Packit Service a31ea6
        segment =
Packit Service a31ea6
            xmlURIEscapeStr(BAD_CAST uri->query, BAD_CAST ";/?:@&=+,$");
Packit Service a31ea6
        NULLCHK(segment)
Packit Service a31ea6
        ret = xmlStrcat(ret, BAD_CAST "?");
Packit Service a31ea6
        ret = xmlStrcat(ret, segment);
Packit Service a31ea6
        xmlFree(segment);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (uri->opaque) {
Packit Service a31ea6
        segment = xmlURIEscapeStr(BAD_CAST uri->opaque, BAD_CAST "");
Packit Service a31ea6
        NULLCHK(segment)
Packit Service a31ea6
        ret = xmlStrcat(ret, segment);
Packit Service a31ea6
        xmlFree(segment);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (uri->fragment) {
Packit Service a31ea6
        segment = xmlURIEscapeStr(BAD_CAST uri->fragment, BAD_CAST "#");
Packit Service a31ea6
        NULLCHK(segment)
Packit Service a31ea6
        ret = xmlStrcat(ret, BAD_CAST "#");
Packit Service a31ea6
        ret = xmlStrcat(ret, segment);
Packit Service a31ea6
        xmlFree(segment);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    xmlFreeURI(uri);
Packit Service a31ea6
#undef NULLCHK
Packit Service a31ea6
Packit Service a31ea6
    return (ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/************************************************************************
Packit Service a31ea6
 *									*
Packit Service a31ea6
 *			Public functions				*
Packit Service a31ea6
 *									*
Packit Service a31ea6
 ************************************************************************/
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlBuildURI:
Packit Service a31ea6
 * @URI:  the URI instance found in the document
Packit Service a31ea6
 * @base:  the base value
Packit Service a31ea6
 *
Packit Service a31ea6
 * Computes he final URI of the reference done by checking that
Packit Service a31ea6
 * the given URI is valid, and building the final URI using the
Packit Service a31ea6
 * base URI. This is processed according to section 5.2 of the
Packit Service a31ea6
 * RFC 2396
Packit Service a31ea6
 *
Packit Service a31ea6
 * 5.2. Resolving Relative References to Absolute Form
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a new URI string (to be freed by the caller) or NULL in case
Packit Service a31ea6
 *         of error.
Packit Service a31ea6
 */
Packit Service a31ea6
xmlChar *
Packit Service a31ea6
xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
Packit Service a31ea6
    xmlChar *val = NULL;
Packit Service a31ea6
    int ret, len, indx, cur, out;
Packit Service a31ea6
    xmlURIPtr ref = NULL;
Packit Service a31ea6
    xmlURIPtr bas = NULL;
Packit Service a31ea6
    xmlURIPtr res = NULL;
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * 1) The URI reference is parsed into the potential four components and
Packit Service a31ea6
     *    fragment identifier, as described in Section 4.3.
Packit Service a31ea6
     *
Packit Service a31ea6
     *    NOTE that a completely empty URI is treated by modern browsers
Packit Service a31ea6
     *    as a reference to "." rather than as a synonym for the current
Packit Service a31ea6
     *    URI.  Should we do that here?
Packit Service a31ea6
     */
Packit Service a31ea6
    if (URI == NULL)
Packit Service a31ea6
	ret = -1;
Packit Service a31ea6
    else {
Packit Service a31ea6
	if (*URI) {
Packit Service a31ea6
	    ref = xmlCreateURI();
Packit Service a31ea6
	    if (ref == NULL)
Packit Service a31ea6
		goto done;
Packit Service a31ea6
	    ret = xmlParseURIReference(ref, (const char *) URI);
Packit Service a31ea6
	}
Packit Service a31ea6
	else
Packit Service a31ea6
	    ret = 0;
Packit Service a31ea6
    }
Packit Service a31ea6
    if (ret != 0)
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    if ((ref != NULL) && (ref->scheme != NULL)) {
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * The URI is absolute don't modify.
Packit Service a31ea6
	 */
Packit Service a31ea6
	val = xmlStrdup(URI);
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    if (base == NULL)
Packit Service a31ea6
	ret = -1;
Packit Service a31ea6
    else {
Packit Service a31ea6
	bas = xmlCreateURI();
Packit Service a31ea6
	if (bas == NULL)
Packit Service a31ea6
	    goto done;
Packit Service a31ea6
	ret = xmlParseURIReference(bas, (const char *) base);
Packit Service a31ea6
    }
Packit Service a31ea6
    if (ret != 0) {
Packit Service a31ea6
	if (ref)
Packit Service a31ea6
	    val = xmlSaveUri(ref);
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    if (ref == NULL) {
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * the base fragment must be ignored
Packit Service a31ea6
	 */
Packit Service a31ea6
	if (bas->fragment != NULL) {
Packit Service a31ea6
	    xmlFree(bas->fragment);
Packit Service a31ea6
	    bas->fragment = NULL;
Packit Service a31ea6
	}
Packit Service a31ea6
	val = xmlSaveUri(bas);
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * 2) If the path component is empty and the scheme, authority, and
Packit Service a31ea6
     *    query components are undefined, then it is a reference to the
Packit Service a31ea6
     *    current document and we are done.  Otherwise, the reference URI's
Packit Service a31ea6
     *    query and fragment components are defined as found (or not found)
Packit Service a31ea6
     *    within the URI reference and not inherited from the base URI.
Packit Service a31ea6
     *
Packit Service a31ea6
     *    NOTE that in modern browsers, the parsing differs from the above
Packit Service a31ea6
     *    in the following aspect:  the query component is allowed to be
Packit Service a31ea6
     *    defined while still treating this as a reference to the current
Packit Service a31ea6
     *    document.
Packit Service a31ea6
     */
Packit Service a31ea6
    res = xmlCreateURI();
Packit Service a31ea6
    if (res == NULL)
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    if ((ref->scheme == NULL) && (ref->path == NULL) &&
Packit Service a31ea6
	((ref->authority == NULL) && (ref->server == NULL))) {
Packit Service a31ea6
	if (bas->scheme != NULL)
Packit Service a31ea6
	    res->scheme = xmlMemStrdup(bas->scheme);
Packit Service a31ea6
	if (bas->authority != NULL)
Packit Service a31ea6
	    res->authority = xmlMemStrdup(bas->authority);
Packit Service a31ea6
	else if ((bas->server != NULL) || (bas->port == -1)) {
Packit Service a31ea6
	    if (bas->server != NULL)
Packit Service a31ea6
		res->server = xmlMemStrdup(bas->server);
Packit Service a31ea6
	    if (bas->user != NULL)
Packit Service a31ea6
		res->user = xmlMemStrdup(bas->user);
Packit Service a31ea6
	    res->port = bas->port;
Packit Service a31ea6
	}
Packit Service a31ea6
	if (bas->path != NULL)
Packit Service a31ea6
	    res->path = xmlMemStrdup(bas->path);
Packit Service a31ea6
	if (ref->query_raw != NULL)
Packit Service a31ea6
	    res->query_raw = xmlMemStrdup (ref->query_raw);
Packit Service a31ea6
	else if (ref->query != NULL)
Packit Service a31ea6
	    res->query = xmlMemStrdup(ref->query);
Packit Service a31ea6
	else if (bas->query_raw != NULL)
Packit Service a31ea6
	    res->query_raw = xmlMemStrdup(bas->query_raw);
Packit Service a31ea6
	else if (bas->query != NULL)
Packit Service a31ea6
	    res->query = xmlMemStrdup(bas->query);
Packit Service a31ea6
	if (ref->fragment != NULL)
Packit Service a31ea6
	    res->fragment = xmlMemStrdup(ref->fragment);
Packit Service a31ea6
	goto step_7;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * 3) If the scheme component is defined, indicating that the reference
Packit Service a31ea6
     *    starts with a scheme name, then the reference is interpreted as an
Packit Service a31ea6
     *    absolute URI and we are done.  Otherwise, the reference URI's
Packit Service a31ea6
     *    scheme is inherited from the base URI's scheme component.
Packit Service a31ea6
     */
Packit Service a31ea6
    if (ref->scheme != NULL) {
Packit Service a31ea6
	val = xmlSaveUri(ref);
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    if (bas->scheme != NULL)
Packit Service a31ea6
	res->scheme = xmlMemStrdup(bas->scheme);
Packit Service a31ea6
Packit Service a31ea6
    if (ref->query_raw != NULL)
Packit Service a31ea6
	res->query_raw = xmlMemStrdup(ref->query_raw);
Packit Service a31ea6
    else if (ref->query != NULL)
Packit Service a31ea6
	res->query = xmlMemStrdup(ref->query);
Packit Service a31ea6
    if (ref->fragment != NULL)
Packit Service a31ea6
	res->fragment = xmlMemStrdup(ref->fragment);
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * 4) If the authority component is defined, then the reference is a
Packit Service a31ea6
     *    network-path and we skip to step 7.  Otherwise, the reference
Packit Service a31ea6
     *    URI's authority is inherited from the base URI's authority
Packit Service a31ea6
     *    component, which will also be undefined if the URI scheme does not
Packit Service a31ea6
     *    use an authority component.
Packit Service a31ea6
     */
Packit Service a31ea6
    if ((ref->authority != NULL) || (ref->server != NULL)) {
Packit Service a31ea6
	if (ref->authority != NULL)
Packit Service a31ea6
	    res->authority = xmlMemStrdup(ref->authority);
Packit Service a31ea6
	else {
Packit Service a31ea6
	    res->server = xmlMemStrdup(ref->server);
Packit Service a31ea6
	    if (ref->user != NULL)
Packit Service a31ea6
		res->user = xmlMemStrdup(ref->user);
Packit Service a31ea6
            res->port = ref->port;
Packit Service a31ea6
	}
Packit Service a31ea6
	if (ref->path != NULL)
Packit Service a31ea6
	    res->path = xmlMemStrdup(ref->path);
Packit Service a31ea6
	goto step_7;
Packit Service a31ea6
    }
Packit Service a31ea6
    if (bas->authority != NULL)
Packit Service a31ea6
	res->authority = xmlMemStrdup(bas->authority);
Packit Service a31ea6
    else if ((bas->server != NULL) || (bas->port == -1)) {
Packit Service a31ea6
	if (bas->server != NULL)
Packit Service a31ea6
	    res->server = xmlMemStrdup(bas->server);
Packit Service a31ea6
	if (bas->user != NULL)
Packit Service a31ea6
	    res->user = xmlMemStrdup(bas->user);
Packit Service a31ea6
	res->port = bas->port;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * 5) If the path component begins with a slash character ("/"), then
Packit Service a31ea6
     *    the reference is an absolute-path and we skip to step 7.
Packit Service a31ea6
     */
Packit Service a31ea6
    if ((ref->path != NULL) && (ref->path[0] == '/')) {
Packit Service a31ea6
	res->path = xmlMemStrdup(ref->path);
Packit Service a31ea6
	goto step_7;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * 6) If this step is reached, then we are resolving a relative-path
Packit Service a31ea6
     *    reference.  The relative path needs to be merged with the base
Packit Service a31ea6
     *    URI's path.  Although there are many ways to do this, we will
Packit Service a31ea6
     *    describe a simple method using a separate string buffer.
Packit Service a31ea6
     *
Packit Service a31ea6
     * Allocate a buffer large enough for the result string.
Packit Service a31ea6
     */
Packit Service a31ea6
    len = 2; /* extra / and 0 */
Packit Service a31ea6
    if (ref->path != NULL)
Packit Service a31ea6
	len += strlen(ref->path);
Packit Service a31ea6
    if (bas->path != NULL)
Packit Service a31ea6
	len += strlen(bas->path);
Packit Service a31ea6
    res->path = (char *) xmlMallocAtomic(len);
Packit Service a31ea6
    if (res->path == NULL) {
Packit Service a31ea6
        xmlURIErrMemory("resolving URI against base\n");
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    res->path[0] = 0;
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * a) All but the last segment of the base URI's path component is
Packit Service a31ea6
     *    copied to the buffer.  In other words, any characters after the
Packit Service a31ea6
     *    last (right-most) slash character, if any, are excluded.
Packit Service a31ea6
     */
Packit Service a31ea6
    cur = 0;
Packit Service a31ea6
    out = 0;
Packit Service a31ea6
    if (bas->path != NULL) {
Packit Service a31ea6
	while (bas->path[cur] != 0) {
Packit Service a31ea6
	    while ((bas->path[cur] != 0) && (bas->path[cur] != '/'))
Packit Service a31ea6
		cur++;
Packit Service a31ea6
	    if (bas->path[cur] == 0)
Packit Service a31ea6
		break;
Packit Service a31ea6
Packit Service a31ea6
	    cur++;
Packit Service a31ea6
	    while (out < cur) {
Packit Service a31ea6
		res->path[out] = bas->path[out];
Packit Service a31ea6
		out++;
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    res->path[out] = 0;
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * b) The reference's path component is appended to the buffer
Packit Service a31ea6
     *    string.
Packit Service a31ea6
     */
Packit Service a31ea6
    if (ref->path != NULL && ref->path[0] != 0) {
Packit Service a31ea6
	indx = 0;
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * Ensure the path includes a '/'
Packit Service a31ea6
	 */
Packit Service a31ea6
	if ((out == 0) && (bas->server != NULL))
Packit Service a31ea6
	    res->path[out++] = '/';
Packit Service a31ea6
	while (ref->path[indx] != 0) {
Packit Service a31ea6
	    res->path[out++] = ref->path[indx++];
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
    res->path[out] = 0;
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Steps c) to h) are really path normalization steps
Packit Service a31ea6
     */
Packit Service a31ea6
    xmlNormalizeURIPath(res->path);
Packit Service a31ea6
Packit Service a31ea6
step_7:
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * 7) The resulting URI components, including any inherited from the
Packit Service a31ea6
     *    base URI, are recombined to give the absolute form of the URI
Packit Service a31ea6
     *    reference.
Packit Service a31ea6
     */
Packit Service a31ea6
    val = xmlSaveUri(res);
Packit Service a31ea6
Packit Service a31ea6
done:
Packit Service a31ea6
    if (ref != NULL)
Packit Service a31ea6
	xmlFreeURI(ref);
Packit Service a31ea6
    if (bas != NULL)
Packit Service a31ea6
	xmlFreeURI(bas);
Packit Service a31ea6
    if (res != NULL)
Packit Service a31ea6
	xmlFreeURI(res);
Packit Service a31ea6
    return(val);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlBuildRelativeURI:
Packit Service a31ea6
 * @URI:  the URI reference under consideration
Packit Service a31ea6
 * @base:  the base value
Packit Service a31ea6
 *
Packit Service a31ea6
 * Expresses the URI of the reference in terms relative to the
Packit Service a31ea6
 * base.  Some examples of this operation include:
Packit Service a31ea6
 *     base = "http://site1.com/docs/book1.html"
Packit Service a31ea6
 *        URI input                        URI returned
Packit Service a31ea6
 *     docs/pic1.gif                    pic1.gif
Packit Service a31ea6
 *     docs/img/pic1.gif                img/pic1.gif
Packit Service a31ea6
 *     img/pic1.gif                     ../img/pic1.gif
Packit Service a31ea6
 *     http://site1.com/docs/pic1.gif   pic1.gif
Packit Service a31ea6
 *     http://site2.com/docs/pic1.gif   http://site2.com/docs/pic1.gif
Packit Service a31ea6
 *
Packit Service a31ea6
 *     base = "docs/book1.html"
Packit Service a31ea6
 *        URI input                        URI returned
Packit Service a31ea6
 *     docs/pic1.gif                    pic1.gif
Packit Service a31ea6
 *     docs/img/pic1.gif                img/pic1.gif
Packit Service a31ea6
 *     img/pic1.gif                     ../img/pic1.gif
Packit Service a31ea6
 *     http://site1.com/docs/pic1.gif   http://site1.com/docs/pic1.gif
Packit Service a31ea6
 *
Packit Service a31ea6
 *
Packit Service a31ea6
 * Note: if the URI reference is really wierd or complicated, it may be
Packit Service a31ea6
 *       worthwhile to first convert it into a "nice" one by calling
Packit Service a31ea6
 *       xmlBuildURI (using 'base') before calling this routine,
Packit Service a31ea6
 *       since this routine (for reasonable efficiency) assumes URI has
Packit Service a31ea6
 *       already been through some validation.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a new URI string (to be freed by the caller) or NULL in case
Packit Service a31ea6
 * error.
Packit Service a31ea6
 */
Packit Service a31ea6
xmlChar *
Packit Service a31ea6
xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlChar *val = NULL;
Packit Service a31ea6
    int ret;
Packit Service a31ea6
    int ix;
Packit Service a31ea6
    int nbslash = 0;
Packit Service a31ea6
    int len;
Packit Service a31ea6
    xmlURIPtr ref = NULL;
Packit Service a31ea6
    xmlURIPtr bas = NULL;
Packit Service a31ea6
    xmlChar *bptr, *uptr, *vptr;
Packit Service a31ea6
    int remove_path = 0;
Packit Service a31ea6
Packit Service a31ea6
    if ((URI == NULL) || (*URI == 0))
Packit Service a31ea6
	return NULL;
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * First parse URI into a standard form
Packit Service a31ea6
     */
Packit Service a31ea6
    ref = xmlCreateURI ();
Packit Service a31ea6
    if (ref == NULL)
Packit Service a31ea6
	return NULL;
Packit Service a31ea6
    /* If URI not already in "relative" form */
Packit Service a31ea6
    if (URI[0] != '.') {
Packit Service a31ea6
	ret = xmlParseURIReference (ref, (const char *) URI);
Packit Service a31ea6
	if (ret != 0)
Packit Service a31ea6
	    goto done;		/* Error in URI, return NULL */
Packit Service a31ea6
    } else
Packit Service a31ea6
	ref->path = (char *)xmlStrdup(URI);
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Next parse base into the same standard form
Packit Service a31ea6
     */
Packit Service a31ea6
    if ((base == NULL) || (*base == 0)) {
Packit Service a31ea6
	val = xmlStrdup (URI);
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    bas = xmlCreateURI ();
Packit Service a31ea6
    if (bas == NULL)
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    if (base[0] != '.') {
Packit Service a31ea6
	ret = xmlParseURIReference (bas, (const char *) base);
Packit Service a31ea6
	if (ret != 0)
Packit Service a31ea6
	    goto done;		/* Error in base, return NULL */
Packit Service a31ea6
    } else
Packit Service a31ea6
	bas->path = (char *)xmlStrdup(base);
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * If the scheme / server on the URI differs from the base,
Packit Service a31ea6
     * just return the URI
Packit Service a31ea6
     */
Packit Service a31ea6
    if ((ref->scheme != NULL) &&
Packit Service a31ea6
	((bas->scheme == NULL) ||
Packit Service a31ea6
	 (xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) ||
Packit Service a31ea6
	 (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)))) {
Packit Service a31ea6
	val = xmlStrdup (URI);
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) {
Packit Service a31ea6
	val = xmlStrdup(BAD_CAST "");
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    if (bas->path == NULL) {
Packit Service a31ea6
	val = xmlStrdup((xmlChar *)ref->path);
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    if (ref->path == NULL) {
Packit Service a31ea6
        ref->path = (char *) "/";
Packit Service a31ea6
	remove_path = 1;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * At this point (at last!) we can compare the two paths
Packit Service a31ea6
     *
Packit Service a31ea6
     * First we take care of the special case where either of the
Packit Service a31ea6
     * two path components may be missing (bug 316224)
Packit Service a31ea6
     */
Packit Service a31ea6
    if (bas->path == NULL) {
Packit Service a31ea6
	if (ref->path != NULL) {
Packit Service a31ea6
	    uptr = (xmlChar *) ref->path;
Packit Service a31ea6
	    if (*uptr == '/')
Packit Service a31ea6
		uptr++;
Packit Service a31ea6
	    /* exception characters from xmlSaveUri */
Packit Service a31ea6
	    val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,");
Packit Service a31ea6
	}
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    bptr = (xmlChar *)bas->path;
Packit Service a31ea6
    if (ref->path == NULL) {
Packit Service a31ea6
	for (ix = 0; bptr[ix] != 0; ix++) {
Packit Service a31ea6
	    if (bptr[ix] == '/')
Packit Service a31ea6
		nbslash++;
Packit Service a31ea6
	}
Packit Service a31ea6
	uptr = NULL;
Packit Service a31ea6
	len = 1;	/* this is for a string terminator only */
Packit Service a31ea6
    } else {
Packit Service a31ea6
        xmlChar *rptr = (xmlChar *) ref->path;
Packit Service a31ea6
        int pos = 0;
Packit Service a31ea6
Packit Service a31ea6
        /*
Packit Service a31ea6
         * Next we compare the two strings and find where they first differ
Packit Service a31ea6
         */
Packit Service a31ea6
	if ((*rptr == '.') && (rptr[1] == '/'))
Packit Service a31ea6
            rptr += 2;
Packit Service a31ea6
	if ((*bptr == '.') && (bptr[1] == '/'))
Packit Service a31ea6
            bptr += 2;
Packit Service a31ea6
	else if ((*bptr == '/') && (*rptr != '/'))
Packit Service a31ea6
	    bptr++;
Packit Service a31ea6
	while ((bptr[pos] == rptr[pos]) && (bptr[pos] != 0))
Packit Service a31ea6
	    pos++;
Packit Service a31ea6
Packit Service a31ea6
	if (bptr[pos] == rptr[pos]) {
Packit Service a31ea6
	    val = xmlStrdup(BAD_CAST "");
Packit Service a31ea6
	    goto done;		/* (I can't imagine why anyone would do this) */
Packit Service a31ea6
	}
Packit Service a31ea6
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * In URI, "back up" to the last '/' encountered.  This will be the
Packit Service a31ea6
	 * beginning of the "unique" suffix of URI
Packit Service a31ea6
	 */
Packit Service a31ea6
	ix = pos;
Packit Service a31ea6
	if ((rptr[ix] == '/') && (ix > 0))
Packit Service a31ea6
	    ix--;
Packit Service a31ea6
	else if ((rptr[ix] == 0) && (ix > 1) && (rptr[ix - 1] == '/'))
Packit Service a31ea6
	    ix -= 2;
Packit Service a31ea6
	for (; ix > 0; ix--) {
Packit Service a31ea6
	    if (rptr[ix] == '/')
Packit Service a31ea6
		break;
Packit Service a31ea6
	}
Packit Service a31ea6
	if (ix == 0) {
Packit Service a31ea6
	    uptr = (xmlChar *)rptr;
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    ix++;
Packit Service a31ea6
	    uptr = (xmlChar *)&rptr[ix];
Packit Service a31ea6
	}
Packit Service a31ea6
Packit Service a31ea6
	/*
Packit Service a31ea6
	 * In base, count the number of '/' from the differing point
Packit Service a31ea6
	 */
Packit Service a31ea6
	if (bptr[pos] != rptr[pos]) {/* check for trivial URI == base */
Packit Service a31ea6
	    for (; bptr[ix] != 0; ix++) {
Packit Service a31ea6
		if (bptr[ix] == '/')
Packit Service a31ea6
		    nbslash++;
Packit Service a31ea6
	    }
Packit Service a31ea6
	}
Packit Service a31ea6
	len = xmlStrlen (uptr) + 1;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (nbslash == 0) {
Packit Service a31ea6
	if (uptr != NULL)
Packit Service a31ea6
	    /* exception characters from xmlSaveUri */
Packit Service a31ea6
	    val = xmlURIEscapeStr(uptr, BAD_CAST "/;&=+$,");
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Allocate just enough space for the returned string -
Packit Service a31ea6
     * length of the remainder of the URI, plus enough space
Packit Service a31ea6
     * for the "../" groups, plus one for the terminator
Packit Service a31ea6
     */
Packit Service a31ea6
    val = (xmlChar *) xmlMalloc (len + 3 * nbslash);
Packit Service a31ea6
    if (val == NULL) {
Packit Service a31ea6
        xmlURIErrMemory("building relative URI\n");
Packit Service a31ea6
	goto done;
Packit Service a31ea6
    }
Packit Service a31ea6
    vptr = val;
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Put in as many "../" as needed
Packit Service a31ea6
     */
Packit Service a31ea6
    for (; nbslash>0; nbslash--) {
Packit Service a31ea6
	*vptr++ = '.';
Packit Service a31ea6
	*vptr++ = '.';
Packit Service a31ea6
	*vptr++ = '/';
Packit Service a31ea6
    }
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Finish up with the end of the URI
Packit Service a31ea6
     */
Packit Service a31ea6
    if (uptr != NULL) {
Packit Service a31ea6
        if ((vptr > val) && (len > 0) &&
Packit Service a31ea6
	    (uptr[0] == '/') && (vptr[-1] == '/')) {
Packit Service a31ea6
	    memcpy (vptr, uptr + 1, len - 1);
Packit Service a31ea6
	    vptr[len - 2] = 0;
Packit Service a31ea6
	} else {
Packit Service a31ea6
	    memcpy (vptr, uptr, len);
Packit Service a31ea6
	    vptr[len - 1] = 0;
Packit Service a31ea6
	}
Packit Service a31ea6
    } else {
Packit Service a31ea6
	vptr[len - 1] = 0;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /* escape the freshly-built path */
Packit Service a31ea6
    vptr = val;
Packit Service a31ea6
	/* exception characters from xmlSaveUri */
Packit Service a31ea6
    val = xmlURIEscapeStr(vptr, BAD_CAST "/;&=+$,");
Packit Service a31ea6
    xmlFree(vptr);
Packit Service a31ea6
Packit Service a31ea6
done:
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Free the working variables
Packit Service a31ea6
     */
Packit Service a31ea6
    if (remove_path != 0)
Packit Service a31ea6
        ref->path = NULL;
Packit Service a31ea6
    if (ref != NULL)
Packit Service a31ea6
	xmlFreeURI (ref);
Packit Service a31ea6
    if (bas != NULL)
Packit Service a31ea6
	xmlFreeURI (bas);
Packit Service a31ea6
Packit Service a31ea6
    return val;
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlCanonicPath:
Packit Service a31ea6
 * @path:  the resource locator in a filesystem notation
Packit Service a31ea6
 *
Packit Service a31ea6
 * Constructs a canonic path from the specified path.
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a new canonic path, or a duplicate of the path parameter if the
Packit Service a31ea6
 * construction fails. The caller is responsible for freeing the memory occupied
Packit Service a31ea6
 * by the returned string. If there is insufficient memory available, or the
Packit Service a31ea6
 * argument is NULL, the function returns NULL.
Packit Service a31ea6
 */
Packit Service a31ea6
#define IS_WINDOWS_PATH(p)					\
Packit Service a31ea6
	((p != NULL) &&						\
Packit Service a31ea6
	 (((p[0] >= 'a') && (p[0] <= 'z')) ||			\
Packit Service a31ea6
	  ((p[0] >= 'A') && (p[0] <= 'Z'))) &&			\
Packit Service a31ea6
	 (p[1] == ':') && ((p[2] == '/') || (p[2] == '\\')))
Packit Service a31ea6
xmlChar *
Packit Service a31ea6
xmlCanonicPath(const xmlChar *path)
Packit Service a31ea6
{
Packit Service a31ea6
/*
Packit Service a31ea6
 * For Windows implementations, additional work needs to be done to
Packit Service a31ea6
 * replace backslashes in pathnames with "forward slashes"
Packit Service a31ea6
 */
Packit Service a31ea6
#if defined(_WIN32) && !defined(__CYGWIN__)
Packit Service a31ea6
    int len = 0;
Packit Service a31ea6
    char *p = NULL;
Packit Service a31ea6
#endif
Packit Service a31ea6
    xmlURIPtr uri;
Packit Service a31ea6
    xmlChar *ret;
Packit Service a31ea6
    const xmlChar *absuri;
Packit Service a31ea6
Packit Service a31ea6
    if (path == NULL)
Packit Service a31ea6
	return(NULL);
Packit Service a31ea6
Packit Service a31ea6
#if defined(_WIN32)
Packit Service a31ea6
    /*
Packit Service a31ea6
     * We must not change the backslashes to slashes if the the path
Packit Service a31ea6
     * starts with \\?\
Packit Service a31ea6
     * Those paths can be up to 32k characters long.
Packit Service a31ea6
     * Was added specifically for OpenOffice, those paths can't be converted
Packit Service a31ea6
     * to URIs anyway.
Packit Service a31ea6
     */
Packit Service a31ea6
    if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') &&
Packit Service a31ea6
        (path[3] == '\\') )
Packit Service a31ea6
	return xmlStrdup((const xmlChar *) path);
Packit Service a31ea6
#endif
Packit Service a31ea6
Packit Service a31ea6
	/* sanitize filename starting with // so it can be used as URI */
Packit Service a31ea6
    if ((path[0] == '/') && (path[1] == '/') && (path[2] != '/'))
Packit Service a31ea6
        path++;
Packit Service a31ea6
Packit Service a31ea6
    if ((uri = xmlParseURI((const char *) path)) != NULL) {
Packit Service a31ea6
	xmlFreeURI(uri);
Packit Service a31ea6
	return xmlStrdup(path);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    /* Check if this is an "absolute uri" */
Packit Service a31ea6
    absuri = xmlStrstr(path, BAD_CAST "://");
Packit Service a31ea6
    if (absuri != NULL) {
Packit Service a31ea6
        int l, j;
Packit Service a31ea6
	unsigned char c;
Packit Service a31ea6
	xmlChar *escURI;
Packit Service a31ea6
Packit Service a31ea6
        /*
Packit Service a31ea6
	 * this looks like an URI where some parts have not been
Packit Service a31ea6
	 * escaped leading to a parsing problem.  Check that the first
Packit Service a31ea6
	 * part matches a protocol.
Packit Service a31ea6
	 */
Packit Service a31ea6
	l = absuri - path;
Packit Service a31ea6
	/* Bypass if first part (part before the '://') is > 20 chars */
Packit Service a31ea6
	if ((l <= 0) || (l > 20))
Packit Service a31ea6
	    goto path_processing;
Packit Service a31ea6
	/* Bypass if any non-alpha characters are present in first part */
Packit Service a31ea6
	for (j = 0;j < l;j++) {
Packit Service a31ea6
	    c = path[j];
Packit Service a31ea6
	    if (!(((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z'))))
Packit Service a31ea6
	        goto path_processing;
Packit Service a31ea6
	}
Packit Service a31ea6
Packit Service a31ea6
	/* Escape all except the characters specified in the supplied path */
Packit Service a31ea6
        escURI = xmlURIEscapeStr(path, BAD_CAST ":/?_.#&;=");
Packit Service a31ea6
	if (escURI != NULL) {
Packit Service a31ea6
	    /* Try parsing the escaped path */
Packit Service a31ea6
	    uri = xmlParseURI((const char *) escURI);
Packit Service a31ea6
	    /* If successful, return the escaped string */
Packit Service a31ea6
	    if (uri != NULL) {
Packit Service a31ea6
	        xmlFreeURI(uri);
Packit Service a31ea6
		return escURI;
Packit Service a31ea6
	    }
Packit Service a31ea6
            xmlFree(escURI);
Packit Service a31ea6
	}
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
path_processing:
Packit Service a31ea6
/* For Windows implementations, replace backslashes with 'forward slashes' */
Packit Service a31ea6
#if defined(_WIN32) && !defined(__CYGWIN__)
Packit Service a31ea6
    /*
Packit Service a31ea6
     * Create a URI structure
Packit Service a31ea6
     */
Packit Service a31ea6
    uri = xmlCreateURI();
Packit Service a31ea6
    if (uri == NULL) {		/* Guard against 'out of memory' */
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    len = xmlStrlen(path);
Packit Service a31ea6
    if ((len > 2) && IS_WINDOWS_PATH(path)) {
Packit Service a31ea6
        /* make the scheme 'file' */
Packit Service a31ea6
	uri->scheme = (char *) xmlStrdup(BAD_CAST "file");
Packit Service a31ea6
	/* allocate space for leading '/' + path + string terminator */
Packit Service a31ea6
	uri->path = xmlMallocAtomic(len + 2);
Packit Service a31ea6
	if (uri->path == NULL) {
Packit Service a31ea6
	    xmlFreeURI(uri);	/* Guard agains 'out of memory' */
Packit Service a31ea6
	    return(NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
	/* Put in leading '/' plus path */
Packit Service a31ea6
	uri->path[0] = '/';
Packit Service a31ea6
	p = uri->path + 1;
Packit Service a31ea6
	strncpy(p, (char *) path, len + 1);
Packit Service a31ea6
    } else {
Packit Service a31ea6
	uri->path = (char *) xmlStrdup(path);
Packit Service a31ea6
	if (uri->path == NULL) {
Packit Service a31ea6
	    xmlFreeURI(uri);
Packit Service a31ea6
	    return(NULL);
Packit Service a31ea6
	}
Packit Service a31ea6
	p = uri->path;
Packit Service a31ea6
    }
Packit Service a31ea6
    /* Now change all occurences of '\' to '/' */
Packit Service a31ea6
    while (*p != '\0') {
Packit Service a31ea6
	if (*p == '\\')
Packit Service a31ea6
	    *p = '/';
Packit Service a31ea6
	p++;
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    if (uri->scheme == NULL) {
Packit Service a31ea6
	ret = xmlStrdup((const xmlChar *) uri->path);
Packit Service a31ea6
    } else {
Packit Service a31ea6
	ret = xmlSaveUri(uri);
Packit Service a31ea6
    }
Packit Service a31ea6
Packit Service a31ea6
    xmlFreeURI(uri);
Packit Service a31ea6
#else
Packit Service a31ea6
    ret = xmlStrdup((const xmlChar *) path);
Packit Service a31ea6
#endif
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
}
Packit Service a31ea6
Packit Service a31ea6
/**
Packit Service a31ea6
 * xmlPathToURI:
Packit Service a31ea6
 * @path:  the resource locator in a filesystem notation
Packit Service a31ea6
 *
Packit Service a31ea6
 * Constructs an URI expressing the existing path
Packit Service a31ea6
 *
Packit Service a31ea6
 * Returns a new URI, or a duplicate of the path parameter if the
Packit Service a31ea6
 * construction fails. The caller is responsible for freeing the memory
Packit Service a31ea6
 * occupied by the returned string. If there is insufficient memory available,
Packit Service a31ea6
 * or the argument is NULL, the function returns NULL.
Packit Service a31ea6
 */
Packit Service a31ea6
xmlChar *
Packit Service a31ea6
xmlPathToURI(const xmlChar *path)
Packit Service a31ea6
{
Packit Service a31ea6
    xmlURIPtr uri;
Packit Service a31ea6
    xmlURI temp;
Packit Service a31ea6
    xmlChar *ret, *cal;
Packit Service a31ea6
Packit Service a31ea6
    if (path == NULL)
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
Packit Service a31ea6
    if ((uri = xmlParseURI((const char *) path)) != NULL) {
Packit Service a31ea6
	xmlFreeURI(uri);
Packit Service a31ea6
	return xmlStrdup(path);
Packit Service a31ea6
    }
Packit Service a31ea6
    cal = xmlCanonicPath(path);
Packit Service a31ea6
    if (cal == NULL)
Packit Service a31ea6
        return(NULL);
Packit Service a31ea6
#if defined(_WIN32) && !defined(__CYGWIN__)
Packit Service a31ea6
    /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?)
Packit Service a31ea6
       If 'cal' is a valid URI allready then we are done here, as continuing would make
Packit Service a31ea6
       it invalid. */
Packit Service a31ea6
    if ((uri = xmlParseURI((const char *) cal)) != NULL) {
Packit Service a31ea6
	xmlFreeURI(uri);
Packit Service a31ea6
	return cal;
Packit Service a31ea6
    }
Packit Service a31ea6
    /* 'cal' can contain a relative path with backslashes. If that is processed
Packit Service a31ea6
       by xmlSaveURI, they will be escaped and the external entity loader machinery
Packit Service a31ea6
       will fail. So convert them to slashes. Misuse 'ret' for walking. */
Packit Service a31ea6
    ret = cal;
Packit Service a31ea6
    while (*ret != '\0') {
Packit Service a31ea6
	if (*ret == '\\')
Packit Service a31ea6
	    *ret = '/';
Packit Service a31ea6
	ret++;
Packit Service a31ea6
    }
Packit Service a31ea6
#endif
Packit Service a31ea6
    memset(&temp, 0, sizeof(temp));
Packit Service a31ea6
    temp.path = (char *) cal;
Packit Service a31ea6
    ret = xmlSaveUri(&temp);
Packit Service a31ea6
    xmlFree(cal);
Packit Service a31ea6
    return(ret);
Packit Service a31ea6
}
Packit Service a31ea6
#define bottom_uri
Packit Service a31ea6
#include "elfgcchack.h"