--- embedaddon/libxml2/uri.c 2013/07/22 01:22:20 1.1.1.2 +++ embedaddon/libxml2/uri.c 2014/06/15 19:53:31 1.1.1.3 @@ -1,12 +1,10 @@ /** - * uri.c: set of generic URI related routines + * uri.c: set of generic URI related routines * * Reference: RFCs 3986, 2732 and 2373 * * See Copyright for the status of this software. * - * TODO: that module behaves really badly on OOM situation - * * daniel@veillard.com */ @@ -20,6 +18,37 @@ #include #include +/** + * MAX_URI_LENGTH: + * + * The definition of the URI regexp in the above RFC has no size limit + * In practice they are usually relativey short except for the + * data URI scheme as defined in RFC 2397. Even for data URI the usual + * maximum size before hitting random practical limits is around 64 KB + * and 4KB is usually a maximum admitted limit for proper operations. + * The value below is more a security limit than anything else and + * really should never be hit by 'normal' operations + * Set to 1 MByte in 2012, this is only enforced on output + */ +#define MAX_URI_LENGTH 1024 * 1024 + +static void +xmlURIErrMemory(const char *extra) +{ + if (extra) + __xmlRaiseError(NULL, NULL, NULL, + NULL, NULL, XML_FROM_URI, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, + extra, NULL, NULL, 0, 0, + "Memory allocation failed : %s\n", extra); + else + __xmlRaiseError(NULL, NULL, NULL, + NULL, NULL, XML_FROM_URI, + XML_ERR_NO_MEMORY, XML_ERR_FATAL, NULL, 0, + NULL, NULL, NULL, 0, 0, + "Memory allocation failed\n"); +} + static void xmlCleanURI(xmlURIPtr uri); /* @@ -982,8 +1011,7 @@ xmlCreateURI(void) { ret = (xmlURIPtr) xmlMalloc(sizeof(xmlURI)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlCreateURI: out of memory\n"); + xmlURIErrMemory("creating URI structure\n"); return(NULL); } memset(ret, 0, sizeof(xmlURI)); @@ -991,6 +1019,31 @@ xmlCreateURI(void) { } /** + * xmlSaveUriRealloc: + * + * Function to handle properly a reallocation when saving an URI + * Also imposes some limit on the length of an URI string output + */ +static xmlChar * +xmlSaveUriRealloc(xmlChar *ret, int *max) { + xmlChar *temp; + int tmp; + + if (*max > MAX_URI_LENGTH) { + xmlURIErrMemory("reaching arbitrary MAX_URI_LENGTH limit\n"); + return(NULL); + } + tmp = *max * 2; + temp = (xmlChar *) xmlRealloc(ret, (tmp + 1)); + if (temp == NULL) { + xmlURIErrMemory("saving URI\n"); + return(NULL); + } + *max = tmp; + return(temp); +} + +/** * xmlSaveUri: * @uri: pointer to an xmlURI * @@ -1012,8 +1065,7 @@ xmlSaveUri(xmlURIPtr uri) { max = 80; ret = (xmlChar *) xmlMallocAtomic((max + 1) * sizeof(xmlChar)); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); + xmlURIErrMemory("saving URI\n"); return(NULL); } len = 0; @@ -1022,28 +1074,16 @@ xmlSaveUri(xmlURIPtr uri) { p = uri->scheme; while (*p != 0) { if (len >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; ret = temp; } ret[len++] = *p++; } if (len >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = ':'; } @@ -1051,15 +1091,9 @@ xmlSaveUri(xmlURIPtr uri) { p = uri->opaque; while (*p != 0) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } if (IS_RESERVED(*(p)) || IS_UNRESERVED(*(p))) ret[len++] = *p++; @@ -1074,15 +1108,9 @@ xmlSaveUri(xmlURIPtr uri) { } else { if (uri->server != NULL) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = '/'; ret[len++] = '/'; @@ -1090,16 +1118,9 @@ xmlSaveUri(xmlURIPtr uri) { p = uri->user; while (*p != 0) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } if ((IS_UNRESERVED(*(p))) || ((*(p) == ';')) || ((*(p) == ':')) || @@ -1116,78 +1137,43 @@ xmlSaveUri(xmlURIPtr uri) { } } if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = '@'; } p = uri->server; while (*p != 0) { if (len >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = *p++; } if (uri->port > 0) { if (len + 10 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } len += snprintf((char *) &ret[len], max - len, ":%d", uri->port); } } else if (uri->authority != NULL) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = '/'; ret[len++] = '/'; p = uri->authority; while (*p != 0) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } if ((IS_UNRESERVED(*(p))) || ((*(p) == '$')) || ((*(p) == ',')) || ((*(p) == ';')) || @@ -1204,16 +1190,9 @@ xmlSaveUri(xmlURIPtr uri) { } } else if (uri->scheme != NULL) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = '/'; ret[len++] = '/'; @@ -1231,14 +1210,9 @@ xmlSaveUri(xmlURIPtr uri) { (p[2] == ':') && (xmlStrEqual(BAD_CAST uri->scheme, BAD_CAST "file"))) { if (len + 3 >= max) { - max *= 2; - ret = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - return(NULL); - } + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = *p++; ret[len++] = *p++; @@ -1246,16 +1220,9 @@ xmlSaveUri(xmlURIPtr uri) { } while (*p != 0) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } if ((IS_UNRESERVED(*(p))) || ((*(p) == '/')) || ((*(p) == ';')) || ((*(p) == '@')) || ((*(p) == '&')) || @@ -1273,63 +1240,35 @@ xmlSaveUri(xmlURIPtr uri) { } if (uri->query_raw != NULL) { if (len + 1 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = '?'; p = uri->query_raw; while (*p != 0) { if (len + 1 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = *p++; } } else if (uri->query != NULL) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = '?'; p = uri->query; while (*p != 0) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } - if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) + if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) ret[len++] = *p++; else { int val = *(unsigned char *)p++; @@ -1343,33 +1282,19 @@ xmlSaveUri(xmlURIPtr uri) { } if (uri->fragment != NULL) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len++] = '#'; p = uri->fragment; while (*p != 0) { if (len + 3 >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, - (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } - if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) + if ((IS_UNRESERVED(*(p))) || (IS_RESERVED(*(p)))) ret[len++] = *p++; else { int val = *(unsigned char *)p++; @@ -1381,18 +1306,16 @@ xmlSaveUri(xmlURIPtr uri) { } } if (len >= max) { - max *= 2; - temp = (xmlChar *) xmlRealloc(ret, (max + 1) * sizeof(xmlChar)); - if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlSaveUri: out of memory\n"); - xmlFree(ret); - return(NULL); - } - ret = temp; + temp = xmlSaveUriRealloc(ret, &max); + if (temp == NULL) goto mem_error; + ret = temp; } ret[len] = 0; return(ret); + +mem_error: + xmlFree(ret); + return(NULL); } /** @@ -1695,8 +1618,7 @@ xmlURIUnescapeString(const char *str, int len, char *t if (target == NULL) { ret = (char *) xmlMallocAtomic(len + 1); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlURIUnescapeString: out of memory\n"); + xmlURIErrMemory("unescaping URI value\n"); return(NULL); } } else @@ -1706,14 +1628,14 @@ xmlURIUnescapeString(const char *str, int len, char *t while(len > 0) { if ((len > 2) && (*in == '%') && (is_hex(in[1])) && (is_hex(in[2]))) { in++; - if ((*in >= '0') && (*in <= '9')) + if ((*in >= '0') && (*in <= '9')) *out = (*in - '0'); else if ((*in >= 'a') && (*in <= 'f')) *out = (*in - 'a') + 10; else if ((*in >= 'A') && (*in <= 'F')) *out = (*in - 'A') + 10; in++; - if ((*in >= '0') && (*in <= '9')) + if ((*in >= '0') && (*in <= '9')) *out = *out * 16 + (*in - '0'); else if ((*in >= 'a') && (*in <= 'f')) *out = *out * 16 + (*in - 'a') + 10; @@ -1746,9 +1668,8 @@ xmlURIEscapeStr(const xmlChar *str, const xmlChar *lis xmlChar *ret, ch; xmlChar *temp; const xmlChar *in; + int len, out; - unsigned int len, out; - if (str == NULL) return(NULL); if (str[0] == 0) @@ -1759,19 +1680,16 @@ xmlURIEscapeStr(const xmlChar *str, const xmlChar *lis len += 20; ret = (xmlChar *) xmlMallocAtomic(len); if (ret == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlURIEscapeStr: out of memory\n"); + xmlURIErrMemory("escaping URI value\n"); return(NULL); } in = (const xmlChar *) str; out = 0; while(*in != 0) { if (len - out <= 3) { - len += 20; - temp = (xmlChar *) xmlRealloc(ret, len); + temp = xmlSaveUriRealloc(ret, &len); if (temp == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlURIEscapeStr: out of memory\n"); + xmlURIErrMemory("escaping URI value\n"); xmlFree(ret); return(NULL); } @@ -1826,10 +1744,9 @@ xmlURIEscape(const xmlChar * str) int ret2; #define NULLCHK(p) if(!p) { \ - xmlGenericError(xmlGenericErrorContext, \ - "xmlURIEscape: out of memory\n"); \ - xmlFreeURI(uri); \ - return NULL; } \ + xmlURIErrMemory("escaping URI value\n"); \ + xmlFreeURI(uri); \ + return NULL; } \ if (str == NULL) return (NULL); @@ -1872,7 +1789,7 @@ xmlURIEscape(const xmlChar * str) if (uri->user) { segment = xmlURIEscapeStr(BAD_CAST uri->user, BAD_CAST ";:&=+$,"); NULLCHK(segment) - ret = xmlStrcat(ret,BAD_CAST "//"); + ret = xmlStrcat(ret,BAD_CAST "//"); ret = xmlStrcat(ret, segment); ret = xmlStrcat(ret, BAD_CAST "@"); xmlFree(segment); @@ -1950,7 +1867,7 @@ xmlURIEscape(const xmlChar * str) * * Computes he final URI of the reference done by checking that * the given URI is valid, and building the final URI using the - * base URI. This is processed according to section 5.2 of the + * base URI. This is processed according to section 5.2 of the * RFC 2396 * * 5.2. Resolving Relative References to Absolute Form @@ -1974,7 +1891,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { * as a reference to "." rather than as a synonym for the current * URI. Should we do that here? */ - if (URI == NULL) + if (URI == NULL) ret = -1; else { if (*URI) { @@ -2045,7 +1962,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { res->server = xmlMemStrdup(bas->server); if (bas->user != NULL) res->user = xmlMemStrdup(bas->user); - res->port = bas->port; + res->port = bas->port; } if (bas->path != NULL) res->path = xmlMemStrdup(bas->path); @@ -2074,7 +1991,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { } if (bas->scheme != NULL) res->scheme = xmlMemStrdup(bas->scheme); - + if (ref->query_raw != NULL) res->query_raw = xmlMemStrdup(ref->query_raw); else if (ref->query != NULL) @@ -2096,7 +2013,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { res->server = xmlMemStrdup(ref->server); if (ref->user != NULL) res->user = xmlMemStrdup(ref->user); - res->port = ref->port; + res->port = ref->port; } if (ref->path != NULL) res->path = xmlMemStrdup(ref->path); @@ -2108,7 +2025,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { res->server = xmlMemStrdup(bas->server); if (bas->user != NULL) res->user = xmlMemStrdup(bas->user); - res->port = bas->port; + res->port = bas->port; } /* @@ -2136,8 +2053,7 @@ xmlBuildURI(const xmlChar *URI, const xmlChar *base) { len += strlen(bas->path); res->path = (char *) xmlMallocAtomic(len); if (res->path == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlBuildURI: out of memory\n"); + xmlURIErrMemory("resolving URI against base\n"); goto done; } res->path[0] = 0; @@ -2383,7 +2299,7 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlCha } len = xmlStrlen (uptr) + 1; } - + if (nbslash == 0) { if (uptr != NULL) /* exception characters from xmlSaveUri */ @@ -2398,8 +2314,7 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlCha */ val = (xmlChar *) xmlMalloc (len + 3 * nbslash); if (val == NULL) { - xmlGenericError(xmlGenericErrorContext, - "xmlBuildRelativeURI: out of memory\n"); + xmlURIErrMemory("building relative URI\n"); goto done; } vptr = val; @@ -2451,14 +2366,14 @@ done: * xmlCanonicPath: * @path: the resource locator in a filesystem notation * - * Constructs a canonic path from the specified path. + * Constructs a canonic path from the specified path. * - * Returns a new canonic path, or a duplicate of the path parameter if the + * Returns a new canonic path, or a duplicate of the path parameter if the * construction fails. The caller is responsible for freeing the memory occupied - * by the returned string. If there is insufficient memory available, or the + * by the returned string. If there is insufficient memory available, or the * argument is NULL, the function returns NULL. */ -#define IS_WINDOWS_PATH(p) \ +#define IS_WINDOWS_PATH(p) \ ((p != NULL) && \ (((p[0] >= 'a') && (p[0] <= 'z')) || \ ((p[0] >= 'A') && (p[0] <= 'Z'))) && \ @@ -2470,7 +2385,7 @@ xmlCanonicPath(const xmlChar *path) * For Windows implementations, additional work needs to be done to * replace backslashes in pathnames with "forward slashes" */ -#if defined(_WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) int len = 0; int i = 0; xmlChar *p = NULL; @@ -2482,7 +2397,20 @@ xmlCanonicPath(const xmlChar *path) if (path == NULL) return(NULL); - /* sanitize filename starting with // so it can be used as URI */ +#if defined(_WIN32) + /* + * We must not change the backslashes to slashes if the the path + * starts with \\?\ + * Those paths can be up to 32k characters long. + * Was added specifically for OpenOffice, those paths can't be converted + * to URIs anyway. + */ + if ((path[0] == '\\') && (path[1] == '\\') && (path[2] == '?') && + (path[3] == '\\') ) + return xmlStrdup((const xmlChar *) path); +#endif + + /* sanitize filename starting with // so it can be used as URI */ if ((path[0] == '/') && (path[1] == '/') && (path[2] != '/')) path++; @@ -2529,7 +2457,7 @@ xmlCanonicPath(const xmlChar *path) path_processing: /* For Windows implementations, replace backslashes with 'forward slashes' */ -#if defined(_WIN32) && !defined(__CYGWIN__) +#if defined(_WIN32) && !defined(__CYGWIN__) /* * Create a URI structure */ @@ -2586,7 +2514,7 @@ path_processing: * * Constructs an URI expressing the existing path * - * Returns a new URI, or a duplicate of the path parameter if the + * Returns a new URI, or a duplicate of the path parameter if the * construction fails. The caller is responsible for freeing the memory * occupied by the returned string. If there is insufficient memory available, * or the argument is NULL, the function returns NULL. @@ -2609,7 +2537,7 @@ xmlPathToURI(const xmlChar *path) if (cal == NULL) return(NULL); #if defined(_WIN32) && !defined(__CYGWIN__) - /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?) + /* xmlCanonicPath can return an URI on Windows (is that the intended behaviour?) If 'cal' is a valid URI allready then we are done here, as continuing would make it invalid. */ if ((uri = xmlParseURI((const char *) cal)) != NULL) {