summaryrefslogtreecommitdiff
path: root/uri.c
diff options
context:
space:
mode:
Diffstat (limited to 'uri.c')
-rw-r--r--uri.c144
1 files changed, 98 insertions, 46 deletions
diff --git a/uri.c b/uri.c
index a00415c..3722311 100644
--- a/uri.c
+++ b/uri.c
@@ -2130,9 +2130,11 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
int ix;
int pos = 0;
int nbslash = 0;
+ int len;
xmlURIPtr ref = NULL;
xmlURIPtr bas = NULL;
xmlChar *bptr, *uptr, *vptr;
+ int remove_path = 0;
if ((URI == NULL) || (*URI == 0))
return NULL;
@@ -2173,63 +2175,101 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * 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))) {
+ ((bas->scheme == NULL) ||
+ (xmlStrcmp ((xmlChar *)bas->scheme, (xmlChar *)ref->scheme)) ||
+ (xmlStrcmp ((xmlChar *)bas->server, (xmlChar *)ref->server)))) {
val = xmlStrdup (URI);
goto done;
}
+ if (xmlStrEqual((xmlChar *)bas->path, (xmlChar *)ref->path)) {
+ val = xmlStrdup(BAD_CAST "");
+ goto done;
+ }
+ if (bas->path == NULL) {
+ val = xmlStrdup((xmlChar *)ref->path);
+ goto done;
+ }
+ if (ref->path == NULL) {
+ ref->path = (char *) "/";
+ remove_path = 1;
+ }
/*
* At this point (at last!) we can compare the two paths
*
- * First we compare the two strings and find where they first differ
+ * First we take care of the special case where either of the
+ * two path components may be missing (bug 316224)
*/
- 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 (bas->path == NULL) {
+ if (ref->path != NULL) {
+ uptr = (xmlChar *) ref->path;
+ if (*uptr == '/')
+ uptr++;
+ val = xmlStrdup(uptr);
+ }
+ goto done;
}
- if (ix == 0) {
- uptr = (xmlChar *)ref->path;
+ bptr = (xmlChar *)bas->path;
+ if (ref->path == NULL) {
+ for (ix = 0; bptr[ix] != 0; ix++) {
+ if (bptr[ix] == '/')
+ nbslash++;
+ }
+ uptr = NULL;
+ len = 1; /* this is for a string terminator only */
} else {
- ix++;
- uptr = (xmlChar *)&ref->path[ix];
- }
-
/*
- * In base, count the number of '/' from the differing point
+ * Next we compare the two strings and find where they first differ
*/
- if (bptr[pos] != ref->path[pos]) { /* check for trivial URI == base */
- for (; bptr[ix] != 0; ix++) {
- if (bptr[ix] == '/')
- nbslash++;
+ 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 = xmlStrdup(BAD_CAST "");
+ 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--;
+ else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] == '/'))
+ ix -= 2;
+ 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++;
+ }
+ }
+ len = xmlStrlen (uptr) + 1;
+ }
+
if (nbslash == 0) {
- val = xmlStrdup (uptr);
+ if (uptr != NULL)
+ val = xmlStrdup (uptr);
goto done;
}
@@ -2238,8 +2278,7 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
* 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);
+ val = (xmlChar *) xmlMalloc (len + 3 * nbslash);
if (val == NULL) {
xmlGenericError(xmlGenericErrorContext,
"xmlBuildRelativeURI: out of memory\n");
@@ -2257,12 +2296,25 @@ xmlBuildRelativeURI (const xmlChar * URI, const xmlChar * base)
/*
* Finish up with the end of the URI
*/
- memcpy (vptr, uptr, ix);
+ if (uptr != NULL) {
+ if ((vptr > val) && (len > 0) &&
+ (uptr[0] == '/') && (vptr[-1] == '/')) {
+ memcpy (vptr, uptr + 1, len - 1);
+ vptr[len - 2] = 0;
+ } else {
+ memcpy (vptr, uptr, len);
+ vptr[len - 1] = 0;
+ }
+ } else {
+ vptr[len - 1] = 0;
+ }
- done:
+done:
/*
* Free the working variables
*/
+ if (remove_path != 0)
+ ref->path = NULL;
if (ref != NULL)
xmlFreeURI (ref);
if (bas != NULL)