version 1.24, 1997/02/18 15:04:55
|
version 1.25, 1997/03/18 12:06:51
|
Line 7
|
Line 7
|
|
|
/* |
/* |
* AHTURLTools.c: contains all the functions for testing, manipulating, |
* AHTURLTools.c: contains all the functions for testing, manipulating, |
* and normalizing URLs. |
* and normalizing URLs. It also contains a local copy of the libWWW |
|
* URL parsing functions. |
* |
* |
* Authors: J. Kahan, I. Vatton |
* Authors: J. Kahan, I. Vatton |
* |
* |
Line 174 char *path;
|
Line 175 char *path;
|
i = 0; |
i = 0; |
while (suffix[i] != EOS) |
while (suffix[i] != EOS) |
{ |
{ |
nsuffix[i] = TOLOWER (suffix[i]); |
nsuffix[i] = tolower (suffix[i]); |
i++; |
i++; |
} |
} |
nsuffix[i] = EOS; |
nsuffix[i] = EOS; |
Line 190 char *path;
|
Line 191 char *path;
|
i = 0; |
i = 0; |
while (suffix[i] != EOS) |
while (suffix[i] != EOS) |
{ |
{ |
nsuffix[i] = TOLOWER (suffix[i]); |
nsuffix[i] = tolower (suffix[i]); |
i++; |
i++; |
} |
} |
nsuffix[i] = EOS; |
nsuffix[i] = EOS; |
Line 231 char *path;
|
Line 232 char *path;
|
i = 0; |
i = 0; |
while (suffix[i] != EOS) |
while (suffix[i] != EOS) |
{ |
{ |
nsuffix[i] = TOLOWER (suffix[i]); |
nsuffix[i] = tolower (suffix[i]); |
i++; |
i++; |
} |
} |
nsuffix[i] = EOS; |
nsuffix[i] = EOS; |
Line 268 char *path;
|
Line 269 char *path;
|
i = 0; |
i = 0; |
while (suffix[i] != EOS) |
while (suffix[i] != EOS) |
{ |
{ |
nsuffix[i] = TOLOWER (suffix[i]); |
nsuffix[i] = tolower (suffix[i]); |
i++; |
i++; |
} |
} |
nsuffix[i] = EOS; |
nsuffix[i] = EOS; |
Line 288 char *path;
|
Line 289 char *path;
|
i = 0; |
i = 0; |
while (suffix[i] != EOS) |
while (suffix[i] != EOS) |
{ |
{ |
nsuffix[i] = TOLOWER (suffix[i]); |
nsuffix[i] = tolower (suffix[i]); |
i++; |
i++; |
} |
} |
nsuffix[i] = EOS; |
nsuffix[i] = EOS; |
Line 452 char *docName;
|
Line 453 char *docName;
|
/* the name is complete, go to the Sixth Step */ |
/* the name is complete, go to the Sixth Step */ |
strcpy (newName, tempOrgName); |
strcpy (newName, tempOrgName); |
/* verify if the URL has the form "protocol://server:port" */ |
/* verify if the URL has the form "protocol://server:port" */ |
ptr = HTParse (newName, "", PARSE_ACCESS | PARSE_HOST | |
ptr = AmayaParseUrl (newName, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | |
PARSE_PUNCTUATION); |
AMAYA_PARSE_PUNCTUATION); |
if (ptr && !strcmp (ptr, newName)) |
if (ptr && !strcmp (ptr, newName)) |
{ |
{ |
/* it has this form, we complete it by adding a "/" */ |
/* it has this form, we complete it by adding a "/" */ |
strcat (newName, "/"); |
strcat (newName, "/"); |
} |
} |
if (ptr) |
if (ptr) |
HT_FREE (ptr); |
TtaFreeMemory (ptr); |
} |
} |
else if ( doc == 0) |
else if ( doc == 0) |
/* the name is complete, go to the Sixth Step */ |
/* the name is complete, go to the Sixth Step */ |
Line 494 char *docName;
|
Line 495 char *docName;
|
if (basename[0] != EOS && basename[length] != '/') |
if (basename[0] != EOS && basename[length] != '/') |
/* verify if the base has the form "protocol://server:port" */ |
/* verify if the base has the form "protocol://server:port" */ |
{ |
{ |
ptr = HTParse (basename, "", PARSE_ACCESS | PARSE_HOST | |
ptr = AmayaParseUrl (basename, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | |
PARSE_PUNCTUATION); |
AMAYA_PARSE_PUNCTUATION); |
if (ptr && !strcmp (ptr, basename)) |
if (ptr && !strcmp (ptr, basename)) |
{ |
{ |
/* it has this form, we complete it by adding a "/" */ |
/* it has this form, we complete it by adding a "/" */ |
Line 503 char *docName;
|
Line 504 char *docName;
|
length++; |
length++; |
} |
} |
if (ptr) |
if (ptr) |
HT_FREE (ptr); |
TtaFreeMemory (ptr); |
} |
} |
/* Third Step: prepare the base |
/* Third Step: prepare the base |
** Removing anything after the |
** Removing anything after the |
Line 576 char *docName;
|
Line 577 char *docName;
|
** Fifth Step, calculate the absolute URL, using the base |
** Fifth Step, calculate the absolute URL, using the base |
*/ |
*/ |
|
|
ptr = HTParse (tempOrgName, basename, PARSE_ALL); |
ptr = AmayaParseUrl (tempOrgName, basename, AMAYA_PARSE_ALL); |
|
|
if (ptr) |
if (ptr) |
{ |
{ |
ptr = HTSimplify (&ptr); |
ptr = AmayaSimplifyUrl (&ptr); |
strcpy (newName, ptr); |
strcpy (newName, ptr); |
HT_FREE (ptr); |
TtaFreeMemory (ptr); |
} |
} |
else |
else |
newName[0] = EOS; |
newName[0] = EOS; |
Line 635 char *path;
|
Line 636 char *path;
|
char *basename_ptr1, *basename_ptr2; |
char *basename_ptr1, *basename_ptr2; |
boolean result; |
boolean result; |
|
|
basename_ptr1 = HTParse (url1, "", PARSE_ACCESS | PARSE_HOST | PARSE_PUNCTUATION); |
basename_ptr1 = AmayaParseUrl (url1, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION); |
basename_ptr2 = HTParse (url2, "", PARSE_ACCESS | PARSE_HOST | PARSE_PUNCTUATION); |
basename_ptr2 = AmayaParseUrl (url2, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION); |
|
|
if (strcmp (basename_ptr1, basename_ptr2)) |
if (strcmp (basename_ptr1, basename_ptr2)) |
result = FALSE; |
result = FALSE; |
else |
else |
result = TRUE; |
result = TRUE; |
|
|
HT_FREE (basename_ptr1); |
TtaFreeMemory (basename_ptr1); |
HT_FREE (basename_ptr2); |
TtaFreeMemory (basename_ptr2); |
|
|
return (result); |
return (result); |
} |
} |
Line 670 char base_url;
|
Line 671 char base_url;
|
|
|
/* verify if we are in the same host */ |
/* verify if we are in the same host */ |
|
|
base_ptr = HTParse (base_url, "", PARSE_ACCESS | PARSE_HOST | PARSE_PUNCTUATION); |
base_ptr = AmayaParseUrl (base_url, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION); |
url_ptr = HTParse (url, "", PARSE_ACCESS | PARSE_HOST | PARSE_PUNCTUATION); |
url_ptr = AmayaParseUrl (url, "", AMAYA_PARSE_ACCESS | AMAYA_PARSE_HOST | AMAYA_PARSE_PUNCTUATION); |
|
|
if (!strcmp (base_ptr, url_ptr)) |
if (!strcmp (base_ptr, url_ptr)) |
{ |
{ |
HT_FREE (base_ptr); |
TtaFreeMemory (base_ptr); |
HT_FREE (url_ptr); |
TtaFreeMemory (url_ptr); |
|
|
/* Normalize the URLs */ |
/* Normalize the URLs */ |
|
|
base_ptr = HTParse (base_url, "", PARSE_ALL); |
base_ptr = AmayaParseUrl (base_url, "", AMAYA_PARSE_ALL); |
url_ptr = HTParse (url, "", PARSE_ALL); |
url_ptr = AmayaParseUrl (url, "", AMAYA_PARSE_ALL); |
|
|
/* Use libwww to make relative name */ |
/* Use libwww to make relative name */ |
|
|
result = HTRelative (url_ptr, base_ptr); |
result = AmayaRelativeUrl (url_ptr, base_ptr); |
HT_FREE (base_ptr); |
TtaFreeMemory (base_ptr); |
HT_FREE (url_ptr); |
TtaFreeMemory (url_ptr); |
} |
} |
else |
else |
result = (char *) NULL; |
result = (char *) NULL; |
Line 712 char *path;
|
Line 713 char *path;
|
if (!path || path[0] == EOS || path[strlen(path)] == DIR_SEP) |
if (!path || path[0] == EOS || path[strlen(path)] == DIR_SEP) |
return (FALSE); |
return (FALSE); |
|
|
root = HTParse(path, (char *) NULL, PARSE_PATH | PARSE_PUNCTUATION); |
root = AmayaParseUrl(path, (char *) NULL, AMAYA_PARSE_PATH | AMAYA_PARSE_PUNCTUATION); |
|
|
if (root) |
if (root) |
{ |
{ |
strcpy (temppath, root); |
strcpy (temppath, root); |
HT_FREE (root); |
TtaFreeMemory (root); |
/* Get the suffix */ |
/* Get the suffix */ |
ExtractSuffix (temppath, suffix); |
ExtractSuffix (temppath, suffix); |
|
|
Line 775 char *string;
|
Line 776 char *string;
|
return; |
return; |
|
|
for (i = 0; string[i] != EOS; i++) |
for (i = 0; string[i] != EOS; i++) |
string[i] = TOLOWER (string[i]); |
string[i] = tolower (string[i]); |
} |
} |
|
|
|
|
Line 816 char *inputURL;
|
Line 817 char *inputURL;
|
} |
} |
} |
} |
|
|
|
/************************************************************************ |
|
* * |
|
* Local Adaptation of the libWWW Library/src/AmayaParseUrl.c code. * |
|
* * |
|
************************************************************************/ |
|
|
|
#define StringAllocCopy(dest,src) { \ |
|
if (src == NULL) dest = NULL; \ |
|
else { \ |
|
if ((dest = (char *) TtaGetMemory(strlen(src) + 1)) == NULL) \ |
|
exit(1); \ |
|
else strcpy(dest, src); }} \ |
|
|
|
typedef struct _HTURI { |
|
char * access; /* Now known as "scheme" */ |
|
char * host; |
|
char * absolute; |
|
char * relative; |
|
char * fragment; |
|
} HTURI; |
|
|
|
/*---------------------------------------------------------------------- |
|
scan |
|
Scan a filename for its consituents |
|
----------------------------------- |
|
|
|
On entry, |
|
name points to a document name which may be incomplete. |
|
On exit, |
|
absolute or relative may be nonzero (but not both). |
|
host, fragment and access may be nonzero if they were specified. |
|
Any which are nonzero point to zero terminated strings. |
|
----------------------------------------------------------------------*/ |
|
#ifdef __STDC__ |
|
static void scan (char * name, HTURI * parts) |
|
#else /* __STDC__ */ |
|
static void scan (name, parts) |
|
char *name; |
|
HTURI *parts; |
|
|
|
#endif /* __STDC__ */ |
|
{ |
|
char * p; |
|
char * after_access = name; |
|
memset(parts, '\0', sizeof(HTURI)); |
|
|
|
/* Look for fragment identifier */ |
|
if ((p = strrchr(name, '#')) != NULL) { |
|
*p++ = '\0'; |
|
parts->fragment = p; |
|
} |
|
|
|
for(p=name; *p; p++) { |
|
if (*p=='/' || *p=='#' || *p=='?') |
|
break; |
|
if (*p==':') { |
|
*p = 0; |
|
parts->access = after_access; /* Scheme has been specified */ |
|
|
|
/* The combination of gcc, the "-O" flag and the HP platform is |
|
unhealthy. The following three lines is a quick & dirty fix, but is |
|
not recommended. Rather, turn off "-O". */ |
|
|
|
/* after_access = p;*/ |
|
/* while (*after_access == 0)*/ |
|
/* after_access++;*/ |
|
|
|
after_access = p+1; |
|
|
|
if (0==strcasecmp("URL", parts->access)) { |
|
parts->access = NULL; /* Ignore IETF's URL: pre-prefix */ |
|
} else break; |
|
} |
|
} |
|
|
|
p = after_access; |
|
if (*p=='/'){ |
|
if (p[1]=='/') { |
|
parts->host = p+2; /* host has been specified */ |
|
*p=0; /* Terminate access */ |
|
p=strchr(parts->host,'/'); /* look for end of host name if any */ |
|
if(p) { |
|
*p=0; /* Terminate host */ |
|
parts->absolute = p+1; /* Root has been found */ |
|
} |
|
} else { |
|
parts->absolute = p+1; /* Root found but no host */ |
|
} |
|
} else { |
|
parts->relative = (*after_access) ? after_access : 0; /* zero for "" */ |
|
} |
|
} |
|
|
|
|
|
/*---------------------------------------------------------------------- |
|
AmayaParseUrl |
|
Parse a Name relative to another name |
|
------------------------------------- |
|
|
|
This returns those parts of a name which are given (and requested) |
|
substituting bits from the related name where necessary. |
|
|
|
On entry, |
|
aName A filename given |
|
relatedName A name relative to which aName is to be parsed. Give |
|
it an empty string if aName is absolute. |
|
wanted A mask for the bits which are wanted. |
|
|
|
On exit, |
|
returns A pointer to a malloc'd string which MUST BE FREED |
|
|
|
----------------------------------------------------------------------*/ |
|
#ifdef __STDC__ |
|
char * AmayaParseUrl (const char *aName, const char *relatedName, int wanted) |
|
#else /* __STDC__ */ |
|
char * AmayaParseUrl (aName, relatedName, wanted) |
|
const char *aName; |
|
const char *relatedName; |
|
int wanted; |
|
|
|
#endif /* __STDC__ */ |
|
{ |
|
char * result = 0; |
|
char * return_value = 0; |
|
int len; |
|
char * name = 0; |
|
char * rel = 0; |
|
char * p; |
|
char * access; |
|
HTURI given, related; |
|
|
|
if (!relatedName) /* HWL 23/8/94: dont dump due to NULL */ |
|
relatedName = ""; |
|
|
|
/* Make working copies of input strings to cut up: */ |
|
len = strlen(aName)+strlen(relatedName)+10; |
|
if ((result=(char *) TtaGetMemory(len)) == NULL) /* Lots of space: more than enough */ |
|
exit(1); |
|
StringAllocCopy(name, aName); |
|
StringAllocCopy(rel, relatedName); |
|
|
|
scan(name, &given); |
|
scan(rel, &related); |
|
result[0]=0; /* Clear string */ |
|
access = given.access ? given.access : related.access; |
|
if (wanted & AMAYA_PARSE_ACCESS) |
|
if (access) { |
|
strcat(result, access); |
|
if(wanted & AMAYA_PARSE_PUNCTUATION) strcat(result, ":"); |
|
} |
|
|
|
if (given.access && related.access) /* If different, inherit nothing. */ |
|
if (strcmp(given.access, related.access)!=0) { |
|
related.host=0; |
|
related.absolute=0; |
|
related.relative=0; |
|
related.fragment=0; |
|
} |
|
|
|
if (wanted & AMAYA_PARSE_HOST) |
|
if(given.host || related.host) { |
|
if(wanted & AMAYA_PARSE_PUNCTUATION) strcat(result, "//"); |
|
strcat(result, given.host ? given.host : related.host); |
|
} |
|
|
|
if (given.host && related.host) /* If different hosts, inherit no path. */ |
|
if (strcmp(given.host, related.host)!=0) { |
|
related.absolute=0; |
|
related.relative=0; |
|
related.fragment=0; |
|
} |
|
|
|
if (wanted & AMAYA_PARSE_PATH) { |
|
if(given.absolute) { /* All is given */ |
|
if(wanted & AMAYA_PARSE_PUNCTUATION) strcat(result, "/"); |
|
strcat(result, given.absolute); |
|
} else if(related.absolute) { /* Adopt path not name */ |
|
strcat(result, "/"); |
|
strcat(result, related.absolute); |
|
if (given.relative) { |
|
p = strchr(result, '?'); /* Search part? */ |
|
if (!p) p=result+strlen(result)-1; |
|
for (; *p!='/'; p--); /* last / */ |
|
p[1]=0; /* Remove filename */ |
|
strcat(result, given.relative); /* Add given one */ |
|
#if 0 |
|
result = AmayaSimplifyUrl (&result); |
|
#endif |
|
} |
|
} else if(given.relative) { |
|
strcat(result, given.relative); /* what we've got */ |
|
} else if(related.relative) { |
|
strcat(result, related.relative); |
|
} else { /* No inheritance */ |
|
strcat(result, "/"); |
|
} |
|
} |
|
|
|
if (wanted & AMAYA_PARSE_ANCHOR) |
|
if(given.fragment || related.fragment) { |
|
if(given.absolute && given.fragment) { /*Fixes for relURLs...*/ |
|
if(wanted & AMAYA_PARSE_PUNCTUATION) strcat(result, "#"); |
|
strcat(result, given.fragment); |
|
} else if (!(given.absolute) && !(given.fragment)) { |
|
strcat(result, ""); |
|
} else { |
|
if(wanted & AMAYA_PARSE_PUNCTUATION) strcat(result, "#"); |
|
strcat(result, given.fragment ? given.fragment : related.fragment); |
|
} |
|
} |
|
TtaFreeMemory(rel); |
|
TtaFreeMemory(name); |
|
|
|
StringAllocCopy(return_value, result); |
|
TtaFreeMemory(result); |
|
return return_value; /* exactly the right length */ |
|
} |
|
|
|
/*---------------------------------------------------------------------- |
|
HTCanon |
|
Canonicalizes the URL in the following manner starting from the host |
|
pointer: |
|
|
|
1) The host name is converted to lowercase |
|
2) Chop off port if `:80' (http), `:70' (gopher), or `:21' (ftp) |
|
|
|
Return: OK The position of the current path part of the URL |
|
which might be the old one or a new one. |
|
|
|
----------------------------------------------------------------------*/ |
|
#ifdef __STDC__ |
|
static char * HTCanon (char ** filename, char * host) |
|
#else /* __STDC__ */ |
|
static char * HTCanon (filename,host) |
|
char **filename; |
|
char *host; |
|
#endif /* __STDC__ */ |
|
{ |
|
char *newname = NULL; |
|
char *port; |
|
char *strptr; |
|
char *path; |
|
char *access = host-3; |
|
|
|
while (access>*filename && *(access-1)!='/') /* Find access method */ |
|
access--; |
|
if ((path = strchr(host, '/')) == NULL) /* Find path */ |
|
path = host + strlen(host); |
|
if ((strptr = strchr(host, '@')) != NULL && strptr<path) /* UserId */ |
|
host = strptr; |
|
if ((port = strchr(host, ':')) != NULL && port>path) /* Port number */ |
|
port = NULL; |
|
|
|
strptr = host; /* Convert to lower-case */ |
|
while (strptr<path) { |
|
*strptr = tolower(*strptr); |
|
strptr++; |
|
} |
|
|
|
/* Does the URL contain a full domain name? This also works for a |
|
numerical host name. The domain name is already made lower-case |
|
and without a trailing dot. */ |
|
{ |
|
char *dot = port ? port : path; |
|
if (dot > *filename && *--dot=='.') { |
|
char *orig=dot, *dest=dot+1; |
|
while((*orig++ = *dest++)); |
|
if (port) port--; |
|
path--; |
|
} |
|
} |
|
/* Chop off port if `:', `:80' (http), `:70' (gopher), or `:21' (ftp) */ |
|
if (port) { |
|
if (!*(port+1) || *(port+1)=='/') { |
|
if (!newname) { |
|
char *orig=port, *dest=port+1; |
|
while((*orig++ = *dest++)); |
|
} |
|
} else if ((!strncmp(access, "http", 4) && |
|
(*(port+1)=='8'&&*(port+2)=='0'&&(*(port+3)=='/'||!*(port+3)))) || |
|
(!strncmp(access, "gopher", 6) && |
|
(*(port+1)=='7'&&*(port+2)=='0'&&(*(port+3)=='/'||!*(port+3)))) || |
|
(!strncmp(access, "ftp", 3) && |
|
(*(port+1)=='2'&&*(port+2)=='1'&&(*(port+3)=='/'||!*(port+3))))) { |
|
if (!newname) { |
|
char *orig=port, *dest=port+3; |
|
while((*orig++ = *dest++)); |
|
path -= 3; /* Update path position, Henry Minsky */ |
|
} |
|
} else if (newname) |
|
strncat(newname, port, (int) (path-port)); |
|
} |
|
|
|
if (newname) { |
|
char *newpath = newname+strlen(newname); |
|
strcat(newname, path); |
|
path = newpath; |
|
TtaFreeMemory(*filename); /* Free old copy */ |
|
*filename = newname; |
|
} |
|
return path; |
|
} |
|
|
|
|
|
/*---------------------------------------------------------------------- |
|
AmayaSimplifyUrl |
|
Simplify a URI |
|
-------------- |
|
A URI is allowed to contain the seqeunce xxx/../ which may be |
|
replaced by "" , and the seqeunce "/./" which may be replaced by "/". |
|
Simplification helps us recognize duplicate URIs. |
|
|
|
Thus, /etc/junk/../fred becomes /etc/fred |
|
/etc/junk/./fred becomes /etc/junk/fred |
|
|
|
but we should NOT change |
|
http://fred.xxx.edu/../.. |
|
|
|
or ../../albert.html |
|
|
|
In order to avoid empty URLs the following URLs become: |
|
|
|
/fred/.. becomes /fred/.. |
|
/fred/././.. becomes /fred/.. |
|
/fred/.././junk/.././ becomes /fred/.. |
|
|
|
If more than one set of `://' is found (several proxies in cascade) then |
|
only the part after the last `://' is simplified. |
|
|
|
Returns: A string which might be the old one or a new one. |
|
|
|
----------------------------------------------------------------------*/ |
|
#ifdef __STDC__ |
|
char *AmayaSimplifyUrl (char ** url) |
|
#else /* __STDC__ */ |
|
char *AmayaSimplifyUrl (url) |
|
char **url; |
|
#endif /* __STDC__ */ |
|
{ |
|
char *path; |
|
char *p; |
|
if (!url || !*url) { |
|
return *url; |
|
} |
|
|
|
/* Find any scheme name */ |
|
if ((path = strstr(*url, "://")) != NULL) { /* Find host name */ |
|
char *newptr; |
|
char *access = *url; |
|
while (access<path && (*access=tolower(*access))) access++; |
|
path += 3; |
|
while ((newptr = strstr(path, "://")) != NULL) /* For proxies */ |
|
path = newptr+3; |
|
path = HTCanon(url, path); /* We have a host name */ |
|
} else if ((path = strstr(*url, ":/")) != NULL) { |
|
path += 2; |
|
} else |
|
path = *url; |
|
if (*path == '/' && *(path+1)=='/') { /* Some URLs start //<foo> */ |
|
path += 1; |
|
} else if (!strncmp(path, "news:", 5)) { |
|
char *ptr = strchr(path+5, '@'); |
|
if (!ptr) ptr = path+5; |
|
while (*ptr) { /* Make group or host lower case */ |
|
*ptr = tolower(*ptr); |
|
ptr++; |
|
} |
|
return *url; /* Doesn't need to do any more */ |
|
} |
|
if ((p = path)) { |
|
char *end; |
|
if (!((end = strchr(path, ';')) || (end = strchr(path, '?')) || |
|
(end = strchr(path, '#')))) |
|
end = path+strlen(path); |
|
|
|
/* Parse string second time to simplify */ |
|
p = path; |
|
while(p<end) { |
|
if (*p=='/') { |
|
if (p>*url && *(p+1)=='.' && (*(p+2)=='/' || !*(p+2))) { |
|
char *orig = p+1; |
|
char *dest = (*(p+2)!='/') ? p+2 : p+3; |
|
while ((*orig++ = *dest++)); /* Remove a slash and a dot */ |
|
end = orig-1; |
|
} else if (*(p+1)=='.' && *(p+2)=='.' && (*(p+3)=='/' || !*(p+3))) { |
|
char *q = p; |
|
while (q>path && *--q!='/'); /* prev slash */ |
|
if (strncmp(q, "/../", 4)) { |
|
char *orig = q+1; |
|
char *dest = (*(p+3)!='/') ? p+3 : p+4; |
|
while ((*orig++ = *dest++)); /* Remove /xxx/.. */ |
|
end = orig-1; |
|
p = q; /* Start again with prev slash */ |
|
} else |
|
p++; |
|
} else if (*(p+1)=='/') { |
|
while (*(p+1)=='/') { |
|
char *orig=p, *dest=p+1; |
|
while ((*orig++ = *dest++)); /* Remove multiple /'s */ |
|
end = orig-1; |
|
} |
|
} else |
|
p++; |
|
} else |
|
p++; |
|
} |
|
} |
|
return *url; |
|
} |
|
|
|
/*---------------------------------------------------------------------- |
|
AmayaRelativeUrl |
|
Make Relative Name |
|
------------------ |
|
|
|
This function creates and returns a string which gives an expression of |
|
one address as related to another. Where there is no relation, an absolute |
|
address is retured. |
|
|
|
On entry, |
|
Both names must be absolute, fully qualified names of nodes |
|
(no fragment bits) |
|
|
|
On exit, |
|
The return result points to a newly allocated name which, if |
|
parsed by AmayaParseUrl relative to relatedName, will yield aName. |
|
The caller is responsible for freeing the resulting name later. |
|
|
|
----------------------------------------------------------------------*/ |
|
#ifdef __STDC__ |
|
char * AmayaRelativeUrl (const char * aName, const char * relatedName) |
|
#else /* __STDC__ */ |
|
char * AmayaRelativeUrl (const char * aName, const char * relatedName) |
|
const char *aName; |
|
#endif /* __STDC__ */ |
|
{ |
|
char * result = 0; |
|
const char *p = aName; |
|
const char *q = relatedName; |
|
const char * after_access = 0; |
|
const char * path = 0; |
|
const char * last_slash = 0; |
|
int slashes = 0; |
|
|
|
for(;*p; p++, q++) { /* Find extent of match */ |
|
if (*p!=*q) break; |
|
if (*p==':') after_access = p+1; |
|
if (*p=='/') { |
|
last_slash = p; |
|
slashes++; |
|
if (slashes==3) path=p; |
|
} |
|
} |
|
|
|
/* q, p point to the first non-matching character or zero */ |
|
|
|
if (!after_access) { /* Different access */ |
|
StringAllocCopy(result, aName); |
|
} else if (slashes<3){ /* Different nodes */ |
|
StringAllocCopy(result, after_access); |
|
} else { /* Some path in common */ |
|
int levels= 0; |
|
for(; *q && (*q!='#'); q++) if (*q=='/') levels++; |
|
if ((result = (char *) TtaGetMemory(3*levels + strlen(last_slash) + 1)) == NULL) |
|
exit(1); |
|
result[0]=0; |
|
for(;levels; levels--)strcat(result, "../"); |
|
strcat(result, last_slash+1); |
|
} |
|
return result; |
|
} |
|
|
|
|
/* |
/* |
end of Module AHTURLTools.c |
end of Module AHTURLTools.c |