diff options
Diffstat (limited to 'uri.c')
-rw-r--r-- | uri.c | 144 |
1 files changed, 98 insertions, 46 deletions
@@ -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) |