[xml] relative uri
- From: François Delyon <f delyon satimage fr>
- To: xml gnome org
- Subject: [xml] relative uri
- Date: Tue, 20 Oct 2009 16:51:58 +0200
Hi all,
I have some remarks about the implementation of xmlBuildRelativeURI
in uri.c (libxml 2.7.3)
1-critical bug
line 2371
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) */
}
the use of bptr[pos] is irrelevant. I suspect that the first four
lines have been added quickly to solve some bad case.
My opinion is that the four first lines are not very important (the
same kind of problem may occur later in the path) and that
xmlBuildRelativeURI should normalize the paths before processing in
order to get human and efficient relative uris.
2- bad answer.
if the basepath is "/a/b" and the path is "/a/c:d",
xmlBuildRelativeURI return "c:d" which is not a relative uri. The
relative uri is "./c:d"
This remark is perhaps not very useful for libxml2 since
xmlBuildRelativeURI is called in very few places.
3- cosmetic problem
line 2392
else if ((ref->path[ix] == 0) && (ix > 1) && (ref->path[ix - 1] ==
'/'))
ix -= 2;
basepath "/a/b" path "/a/c" gives "../a/c" where I expect "c"
and
basepath "/a/b" path "/a/" gives "../a/" where I expect "."
4-question
xmlBuildRelativeURI return things like xmlURIEscapeStr(uptr,
BAD_CAST "/;&=+$,").
Must I understand that the path in a xmlURIPtr is not escaped?
I think that I missed something.
------
I am not familiar with the development of libxml, but I can suggest
the following code to build a relative path.
François.
/*
assume that basepath and path are normalized
return 0 only if malloc fails
*/
char* RelativePath(const char* basepath,const char* path){
int pos = 0;
int nbslash = 0;
int len;
const char *bptr, *uptr;char *vptr,*val=0;
if(path==0 || *path==0)
return RelativePath(basepath, "/");
if (basepath == NULL || *basepath==0) {
if (path != NULL) {
uptr = path;
if (*uptr == '/')
uptr++;
return strdup(uptr);
}else
return strdup("");
}
bptr = basepath;
if (path == NULL || *path==0) {
for (pos = 0; bptr[pos] != 0; pos++) {
if (bptr[pos] == '/')
nbslash++;
}
val = (char *) malloc (1 + 3 * nbslash);
if (val == NULL)
return val;
vptr = val;
for (; nbslash>0; nbslash--) {
*vptr++ = '.';
*vptr++ = '.';
*vptr++ = '/';
}
*vptr=0;
return val;
}
/*
* Next we compare the two strings and find where they first differ
*/
while ((bptr[pos] == path[pos]) && (bptr[pos] != 0))
pos++;
if (bptr[pos] == path[pos])
return strdup("");
if ((path[pos] == '/') && (pos > 0))
pos--;
for (; pos > 0; pos--) {
if (path[pos] == '/'){
pos++;
break;
}
}
uptr = &path[pos];
/*
* In base, count the number of '/' from the differing point
*/
for (; bptr[pos] != 0; pos++) {
if (bptr[pos] == '/')
nbslash++;
}
len = strlen(uptr) + 1;
if (nbslash == 0) {
if (uptr != NULL && *uptr!=0){
/* "a:b" is not a relative uri, use "./a:b" instead */
for(bptr=uptr;*bptr;bptr++){
if(*bptr=='/')break;
if(*bptr==':'){
len=strlen(uptr);
val=(char*)malloc(len+3);
if(!val)return 0;
val[0]='.';val[1]='/';
memcpy(val+2,uptr,len+1);
return val;
}
}
return strdup (uptr);
}else
/* base="/a/b" path="/a/" ->"." */
return strdup (".");
}
/*
* 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
*/
val = (char *) malloc (len + 3 * nbslash);
if (val == NULL)
return val;
vptr = val;
for (; nbslash>0; nbslash--) {
*vptr++ = '.';
*vptr++ = '.';
*vptr++ = '/';
}
/*
* Finish up with the end of the URI
*/
if (uptr != NULL) memcpy (vptr, uptr, len);
vptr[len - 1] = 0;
return val;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]