📄 uri.c
字号:
* it fails.
*/
ret = xmlParseAbsoluteURI(uri, &str);
if (ret != 0) {
xmlCleanURI(uri);
str = tmp;
ret = xmlParseRelativeURI(uri, &str);
}
if (ret != 0) {
xmlCleanURI(uri);
return(ret);
}
if (*str == '#') {
str++;
ret = xmlParseURIFragment(uri, &str);
if (ret != 0) return(ret);
}
if (*str != 0) {
xmlCleanURI(uri);
return(1);
}
return(0);
}
/**
* xmlParseURI:
* @str: the URI string to analyze
*
* Parse an URI
*
* URI-reference = [ absoluteURI | relativeURI ] [ "#" fragment ]
*
* Returns a newly built xmlURIPtr or NULL in case of error
*/
xmlURIPtr
xmlParseURI(const char *str) {
xmlURIPtr uri;
int ret;
if (str == NULL)
return(NULL);
uri = xmlCreateURI();
if (uri != NULL) {
ret = xmlParseURIReference(uri, str);
if (ret) {
xmlFreeURI(uri);
return(NULL);
}
}
return(uri);
}
/************************************************************************
* *
* Public functions *
* *
************************************************************************/
/**
* xmlBuildURI:
* @URI: the URI instance found in the document
* @base: the base value
*
* 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
* RFC 2396
*
* 5.2. Resolving Relative References to Absolute Form
*
* Returns a new URI string (to be freed by the caller) or NULL in case
* of error.
*/
xmlChar *
xmlBuildURI(const xmlChar *URI, const xmlChar *base) {
xmlChar *val = NULL;
int ret, len, indx, cur, out;
xmlURIPtr ref = NULL;
xmlURIPtr bas = NULL;
xmlURIPtr res = NULL;
/*
* 1) The URI reference is parsed into the potential four components and
* fragment identifier, as described in Section 4.3.
*
* NOTE that a completely empty URI is treated by modern browsers
* as a reference to "." rather than as a synonym for the current
* URI. Should we do that here?
*/
if (URI == NULL)
ret = -1;
else {
if (*URI) {
ref = xmlCreateURI();
if (ref == NULL)
goto done;
ret = xmlParseURIReference(ref, (const char *) URI);
}
else
ret = 0;
}
if (ret != 0)
goto done;
if ((ref != NULL) && (ref->scheme != NULL)) {
/*
* The URI is absolute don't modify.
*/
val = xmlStrdup(URI);
goto done;
}
if (base == NULL)
ret = -1;
else {
bas = xmlCreateURI();
if (bas == NULL)
goto done;
ret = xmlParseURIReference(bas, (const char *) base);
}
if (ret != 0) {
if (ref)
val = xmlSaveUri(ref);
goto done;
}
if (ref == NULL) {
/*
* the base fragment must be ignored
*/
if (bas->fragment != NULL) {
xmlFree(bas->fragment);
bas->fragment = NULL;
}
val = xmlSaveUri(bas);
goto done;
}
/*
* 2) If the path component is empty and the scheme, authority, and
* query components are undefined, then it is a reference to the
* current document and we are done. Otherwise, the reference URI's
* query and fragment components are defined as found (or not found)
* within the URI reference and not inherited from the base URI.
*
* NOTE that in modern browsers, the parsing differs from the above
* in the following aspect: the query component is allowed to be
* defined while still treating this as a reference to the current
* document.
*/
res = xmlCreateURI();
if (res == NULL)
goto done;
if ((ref->scheme == NULL) && (ref->path == NULL) &&
((ref->authority == NULL) && (ref->server == NULL))) {
if (bas->scheme != NULL)
res->scheme = xmlMemStrdup(bas->scheme);
if (bas->authority != NULL)
res->authority = xmlMemStrdup(bas->authority);
else if (bas->server != NULL) {
res->server = xmlMemStrdup(bas->server);
if (bas->user != NULL)
res->user = xmlMemStrdup(bas->user);
res->port = bas->port;
}
if (bas->path != NULL)
res->path = xmlMemStrdup(bas->path);
if (ref->query != NULL)
res->query = xmlMemStrdup(ref->query);
else if (bas->query != NULL)
res->query = xmlMemStrdup(bas->query);
if (ref->fragment != NULL)
res->fragment = xmlMemStrdup(ref->fragment);
goto step_7;
}
/*
* 3) If the scheme component is defined, indicating that the reference
* starts with a scheme name, then the reference is interpreted as an
* absolute URI and we are done. Otherwise, the reference URI's
* scheme is inherited from the base URI's scheme component.
*/
if (ref->scheme != NULL) {
val = xmlSaveUri(ref);
goto done;
}
if (bas->scheme != NULL)
res->scheme = xmlMemStrdup(bas->scheme);
if (ref->query != NULL)
res->query = xmlMemStrdup(ref->query);
if (ref->fragment != NULL)
res->fragment = xmlMemStrdup(ref->fragment);
/*
* 4) If the authority component is defined, then the reference is a
* network-path and we skip to step 7. Otherwise, the reference
* URI's authority is inherited from the base URI's authority
* component, which will also be undefined if the URI scheme does not
* use an authority component.
*/
if ((ref->authority != NULL) || (ref->server != NULL)) {
if (ref->authority != NULL)
res->authority = xmlMemStrdup(ref->authority);
else {
res->server = xmlMemStrdup(ref->server);
if (ref->user != NULL)
res->user = xmlMemStrdup(ref->user);
res->port = ref->port;
}
if (ref->path != NULL)
res->path = xmlMemStrdup(ref->path);
goto step_7;
}
if (bas->authority != NULL)
res->authority = xmlMemStrdup(bas->authority);
else if (bas->server != NULL) {
res->server = xmlMemStrdup(bas->server);
if (bas->user != NULL)
res->user = xmlMemStrdup(bas->user);
res->port = bas->port;
}
/*
* 5) If the path component begins with a slash character ("/"), then
* the reference is an absolute-path and we skip to step 7.
*/
if ((ref->path != NULL) && (ref->path[0] == '/')) {
res->path = xmlMemStrdup(ref->path);
goto step_7;
}
/*
* 6) If this step is reached, then we are resolving a relative-path
* reference. The relative path needs to be merged with the base
* URI's path. Although there are many ways to do this, we will
* describe a simple method using a separate string buffer.
*
* Allocate a buffer large enough for the result string.
*/
len = 2; /* extra / and 0 */
if (ref->path != NULL)
len += strlen(ref->path);
if (bas->path != NULL)
len += strlen(bas->path);
res->path = (char *) xmlMallocAtomic(len);
if (res->path == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlBuildURI: out of memory\n");
goto done;
}
res->path[0] = 0;
/*
* a) All but the last segment of the base URI's path component is
* copied to the buffer. In other words, any characters after the
* last (right-most) slash character, if any, are excluded.
*/
cur = 0;
out = 0;
if (bas->path != NULL) {
while (bas->path[cur] != 0) {
while ((bas->path[cur] != 0) && (bas->path[cur] != '/'))
cur++;
if (bas->path[cur] == 0)
break;
cur++;
while (out < cur) {
res->path[out] = bas->path[out];
out++;
}
}
}
res->path[out] = 0;
/*
* b) The reference's path component is appended to the buffer
* string.
*/
if (ref->path != NULL && ref->path[0] != 0) {
indx = 0;
/*
* Ensure the path includes a '/'
*/
if ((out == 0) && (bas->server != NULL))
res->path[out++] = '/';
while (ref->path[indx] != 0) {
res->path[out++] = ref->path[indx++];
}
}
res->path[out] = 0;
/*
* Steps c) to h) are really path normalization steps
*/
xmlNormalizeURIPath(res->path);
step_7:
/*
* 7) The resulting URI components, including any inherited from the
* base URI, are recombined to give the absolute form of the URI
* reference.
*/
val = xmlSaveUri(res);
done:
if (ref != NULL)
xmlFreeURI(ref);
if (bas != NULL)
xmlFreeURI(bas);
if (res != NULL)
xmlFreeURI(res);
return(val);
}
/**
* xmlBuildRelativeURI:
* @URI: the URI reference under consideration
* @base: the base value
*
* Expresses the URI of the reference in terms relative to the
* base. Some examples of this operation include:
* base = "http://site1.com/docs/book1.html"
* URI input URI returned
* docs/pic1.gif pic1.gif
* docs/img/pic1.gif img/pic1.gif
* img/pic1.gif ../img/pic1.gif
* http://site1.com/docs/pic1.gif pic1.gif
* http://site2.com/docs/pic1.gif http://site2.com/docs/pic1.gif
*
* base = "docs/book1.html"
* URI input URI returned
* docs/pic1.gif pic1.gif
* docs/img/pic1.gif img/pic1.gif
* img/pic1.gif ../img/pic1.gif
* http://site1.com/docs/pic1.gif http://site1.com/docs/pic1.gif
*
*
* Note: if the URI reference is really wierd or complicated, it may be
* worthwhile to first convert it into a "nice" one by calling
* xmlBuildURI (using 'base') before calling this routine,
* since this routine (for reasonable efficiency) assumes URI has
* already been through some validation.
*
* Returns a new URI string (to be freed by the caller) or NULL in case
* error.
*/
xmlChar *
xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
{
xmlChar *val = NULL;
int ret;
int ix;
int pos = 0;
int nbslash = 0;
xmlURIPtr ref = NULL;
xmlURIPtr bas = NULL;
xmlChar *bptr, *uptr, *vptr;
if ((URI == NULL) || (*URI == 0))
return NULL;
/*
* Special case - if URI starts with '.', we assume it's already
* in relative form, so nothing to do.
*/
if (*URI == '.') {
val = xmlStrdup (URI);
goto done;
}
/*
* First parse URI into a standard form
*/
ref = xmlCreateURI ();
if (ref == NULL)
return NULL;
ret = xmlParseURIReference (ref, (const char *) URI);
if (ret != 0)
goto done; /* Error in URI, return NULL */
/*
* Next parse base into the same standard form
*/
if ((base == NULL) || (*base == 0)) {
val = xmlStrdup (URI);
goto done;
}
bas = xmlCreateURI ();
if (bas == NULL)
goto done;
ret = xmlParseURIReference (bas, (const char *) base);
if (ret != 0)
goto done; /* Error in base, return NULL */
/*
* If the scheme / server on the URI differs from the base,
* just return the URI
*/
if ((ref->scheme != NULL) &&
((bas->scheme == NULL) ||
xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme) ||
xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server))) {
val = xmlStrdup (URI);
goto done;
}
/*
* At this point (at last!) we can compare the two paths
*
* First we compare the two strings and find where they first differ
*/
bptr = (xmlChar *)bas->path;
if ((ref->path[pos] == '.') && (ref->path[pos+1] == '/'))
pos += 2;
if ((*bptr == '.') && (bptr[1] == '/'))
bptr += 2;
else if ((*bptr == '/') && (ref->path[pos] != '/'))
bptr++;
while ((bptr[pos] == ref->path[pos]) && (bptr[pos] != 0))
pos++;
if (bptr[pos] == ref->path[pos]) {
val = NULL; /* if no differences, return NULL */
goto done; /* (I can't imagine why anyone would do this) */
}
/*
* In URI, "back up" to the last '/' encountered. This will be the
* beginning of the "unique" suffix of URI
*/
ix = pos;
if ((ref->path[ix] == '/') && (ix > 0))
ix--;
for (; ix > 0; ix--) {
if (ref->path[ix] == '/')
break;
}
if (ix == 0) {
uptr = (xmlChar *)ref->path;
} else {
ix++;
uptr = (xmlChar *)&ref->path[ix];
}
/*
* In base, count the number of '/' from the differing point
*/
if (bptr[pos] != ref->path[pos]) { /* check for trivial URI == base */
for (; bptr[ix] != 0; ix++) {
if (bptr[ix] == '/')
nbslash++;
}
}
if (nbslash == 0) {
val = xmlStrdup (uptr);
goto done;
}
/*
* Allocate just enough space for the returned string -
* length of the remainder of the URI, plus enough space
* for the "../" groups, plus one for the terminator
*/
ix = xmlStrlen (uptr) + 1;
val = (xmlChar *) xmlMalloc (ix + 3 * nbslash);
if (val == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlBuildRelativeURI: out of memory\n");
goto done;
}
vptr = val;
/*
* Put in as many "../" as needed
*/
for (; nbslash>0; nbslash--) {
*vptr++ = '.';
*vptr++ = '.';
*vptr++ = '/';
}
/*
* Finish up with the end of the URI
*/
memcpy (vptr, uptr, ix);
done:
/*
* Free the working variables
*/
if (ref != NULL)
xmlFreeURI (ref);
if (bas != NULL)
xmlFreeURI (bas);
return val;
}
/**
* xmlCanonicPath:
* @path: the resource locator in a filesystem notation
*
* Constructs a canonic path from the specified path.
*
* 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
* argument is NULL, the function returns NULL.
*/
#define IS_WINDOWS_PATH(p) \
((p != NULL) && \
(((p[0] >= 'a') && (p[0] <= 'z')) || \
((p[0] >= 'A') && (p[0] <= 'Z'))) && \
(p[1] == ':') && ((p[2] == '/') || (p[2] == '\\')))
xmlChar*
xmlCanonicPath(const xmlChar *path)
{
#if defined(_WIN32) && !defined(__CYGWIN__)
int len = 0;
int i = 0;
xmlChar *p = NULL;
#endif
xmlChar *ret;
xmlURIPtr uri;
if (path == NULL)
return(NULL);
if ((uri = xmlParseURI((const char *) path)) != NULL) {
xmlFreeURI(uri);
return xmlStrdup(path);
}
uri = xmlCreateURI();
if (uri == NULL) {
return(NULL);
}
#if defined(_WIN32) && !defined(__CYGWIN__)
len = xmlStrlen(path);
if ((len > 2) && IS_WINDOWS_PATH(path)) {
uri->scheme = xmlStrdup(BAD_CAST "file");
uri->path = xmlMallocAtomic(len + 2); /* FIXME - check alloc! */
uri->path[0] = '/';
p = uri->path + 1;
strncpy(p, path, len + 1);
} else {
uri->path = xmlStrdup(path); /* FIXME - check alloc! */
p = uri->path;
}
while (*p != '\0') {
if (*p == '\\')
*p = '/';
p++;
}
#else
uri->path = (char *) xmlStrdup((const xmlChar *) path);
#endif
if (uri->path == NULL) {
xmlFreeURI(uri);
return(NULL);
}
ret = xmlSaveUri(uri);
xmlFreeURI(uri);
return(ret);
}
#define bottom_uri
#include "elfgcchack.h"
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -