351 lines
8.3 KiB
C
351 lines
8.3 KiB
C
#include <stdio.h>
|
|
#include <string.h>
|
|
#include "global.h"
|
|
#include "url.h"
|
|
/*
|
|
[scheme[p://] [host[:port]] [/path] [?query]
|
|
|
|
*/
|
|
|
|
/*******************************************************************************
|
|
|
|
URL processing
|
|
|
|
URLs start their life as strings from the user or links embedded in gmi files.
|
|
sUrl structure encapsulate a local copy of the URL and facilitate normalization.
|
|
|
|
An sUrl may be initialized in one of the following ways:
|
|
* copied from another sUrl;
|
|
* set from a full sUrl;
|
|
* set from a partial url using another, base sUrl.
|
|
|
|
It is processed in order to set internal component offsets.
|
|
|
|
It is normalized to eliminate . and .. components.
|
|
|
|
Notes:
|
|
|
|
port is tracked as an actual port and not an offset!
|
|
|
|
oFile is used only for base sUrls, and is normally not searched/initialized.
|
|
|
|
******************************************************************************/
|
|
int url_is_spartan(char* url){
|
|
return !(strncmp("spartan://",url,10));
|
|
}
|
|
|
|
int url_is_full(char* url){
|
|
return (NULL != strstr(url,"://"));
|
|
}
|
|
|
|
char* sUrl_path(sUrl* purl){
|
|
return purl->buf + purl->oPath;
|
|
}
|
|
|
|
U16 sUrl_port(sUrl* purl){
|
|
return purl->port;
|
|
}
|
|
|
|
/*******************************************************************************
|
|
|
|
print the sUrl
|
|
|
|
******************************************************************************/
|
|
void sUrl_dump(sUrl* purl){
|
|
printf("sUrl at %p\n",purl);
|
|
int ohost = purl->oHost;
|
|
int opath = purl->oPath;
|
|
char* buf = purl->buf;
|
|
|
|
if(opath){
|
|
printf("scheme: %*.*s\n",ohost,ohost,buf);
|
|
printf("host: %*.*s\n",opath-ohost,opath-ohost,buf+ohost);
|
|
printf("port: %d\n",purl->port);
|
|
printf("path: %s\n",buf+opath);
|
|
} else {
|
|
printf("invalid:[%s]\n",buf);
|
|
}
|
|
}
|
|
// fputs(purl->buf,f);
|
|
|
|
|
|
/*******************************************************************************
|
|
|
|
Set the sUrl to the string fragment provided. The sUrl is reset and needs
|
|
further processing!
|
|
|
|
******************************************************************************/
|
|
int sUrl_set(sUrl*p,char*str,U32 len){
|
|
if(!len)
|
|
len = strlen(str);
|
|
if (len > URL_MAX) return 1; // didn't fit
|
|
p->oHost = 0;
|
|
p->oPath = 0;
|
|
p->oFile = 0;
|
|
p->port = 300;
|
|
strncpy(p->buf,str,len);
|
|
p->buf[len]=0;
|
|
return 0;
|
|
}
|
|
/*******************************************************************************
|
|
|
|
Copy the src sUrl into the destingation sUrl, along with all components.
|
|
|
|
******************************************************************************/
|
|
sUrl* sUrl_copy(sUrl* dst, sUrl* src){
|
|
memcpy(dst,src,sizeof(sUrl));
|
|
return dst;
|
|
}
|
|
/*******************************************************************************
|
|
|
|
file Return the pointer to the file component of this URL, and set the internal
|
|
offset.
|
|
|
|
******************************************************************************/
|
|
char* sUrl_file(sUrl*p){
|
|
char* pfile = strrchr(p->buf,'/') + 1;
|
|
p->oFile = pfile - (p->buf);
|
|
return pfile;
|
|
}
|
|
|
|
|
|
U32 host_port(char* p){
|
|
char c;
|
|
do {
|
|
c=*p++;
|
|
if(!c) return 300; // at end? default
|
|
if('/'==c) return 300; // at /? default
|
|
if(':'==c) break; // at : parse
|
|
} while (1);
|
|
|
|
U32 val = 0;
|
|
|
|
while((c=*p++)) {
|
|
c-= '0';
|
|
if( (c<0) || (c>9))
|
|
return 0; //invalid port
|
|
val = (val * 10) + c;
|
|
}
|
|
|
|
return val;
|
|
}
|
|
/*******************************************************************************
|
|
|
|
full - parse the buffer of this sUrl to set the internal offsets (but not file),
|
|
assuming a full URL (it must have a ://).
|
|
|
|
Return: 0 on success; 1 if not a full URL.
|
|
|
|
******************************************************************************/
|
|
/* url_do_full -- Try to parse a full URL */
|
|
//
|
|
int sUrl_full(sUrl* purl){
|
|
char* p = strstr(purl->buf,"://"); //if scheme is there it ends with spartan|://|host|/|
|
|
if(!p) return 1; //no scheme sigil = error!
|
|
p+=3;
|
|
|
|
U32 port = host_port(p);
|
|
if(!p) return 1; //invalid port
|
|
purl->port = port;
|
|
|
|
purl->oHost = p-(purl->buf);
|
|
char* path = strchr(p+3,'/'); //host ends with a /path
|
|
if(!path) { // if no path provided,
|
|
path = p + 3 + (strlen(p+3));
|
|
*path = '/';
|
|
*(path+1)=0;
|
|
}
|
|
purl->oPath = path - purl->buf;
|
|
return 0;
|
|
}
|
|
/*******************************************************************************
|
|
|
|
rel - given a base sUrl and a string with local url, mutate sUrl into a full
|
|
rul
|
|
|
|
******************************************************************************/
|
|
void sUrl_rel(sUrl*base,char* str,U32 len){
|
|
char* dst = base->buf + (('/'==*str) ? base->oPath : base->oFile);
|
|
strncpy(dst,str,len);
|
|
dst[len]=0;
|
|
}
|
|
/*******************************************************************************
|
|
|
|
norm - given a full but not canonical sUrl, process to eliminate ./ and ../
|
|
|
|
return: 0 success
|
|
1 error
|
|
******************************************************************************/
|
|
// backup from p to the previous '/'
|
|
char* _norm_backup(char* p,char* start){
|
|
while(--p >= start)
|
|
if('/'==*p)
|
|
return p;
|
|
return NULL;
|
|
}
|
|
|
|
int sUrl_norm(sUrl* purl){
|
|
char* start = purl->buf + purl->oPath;
|
|
char* src = start;
|
|
char* dst = start;
|
|
|
|
//printf("normalizing[%s]\n",src);
|
|
char c;
|
|
while((c = (*dst++ = *src++))){
|
|
// printf("c=%c[%s]\n",c,src-1);
|
|
if('/'==c){
|
|
if(!strncmp(src,"../",3)){
|
|
if(!(dst = _norm_backup(dst-1,start)))
|
|
return 1;
|
|
else
|
|
src += 2; //src and dest at respecive '/'s
|
|
|
|
} else if(!strncmp(src,"./",2)) {
|
|
src += 2;
|
|
} else if(!strcmp(src,"..")){
|
|
if(!(dst = _norm_backup(dst-1,start)))
|
|
return 2;
|
|
dst++; // leave the slash
|
|
src += 2;
|
|
*dst++=0;
|
|
// printf("src:[%s]; dst:[%s];\n",src,dst);
|
|
} else if(!strcmp(src,".")){
|
|
*dst++=0;
|
|
}
|
|
}
|
|
}
|
|
*start = '/';
|
|
|
|
// printf("postnorm[%s]\n",start);
|
|
return 0;
|
|
}
|
|
/*******************************************************************************
|
|
|
|
|
|
******************************************************************************/
|
|
|
|
U32 sUrl_host_length(sUrl* purl){
|
|
return (purl->oPath - purl->oHost);
|
|
}
|
|
|
|
/*
|
|
char URL_base[1024];
|
|
int baselen;
|
|
int bhost_off;
|
|
int bpath_off;
|
|
*/
|
|
/*
|
|
char buf[2048];
|
|
char* scheme;
|
|
char* host;
|
|
char* path;
|
|
|
|
|
|
int url_make_base(){
|
|
strcpy(URL_base,scheme);
|
|
baselen = strlen(URL_base);
|
|
bhost_off = host - scheme;
|
|
bpath_off = path - scheme;
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int url_do_part(char*src){
|
|
scheme = src-baselen;
|
|
strncpy(scheme,URL_base,baselen);
|
|
host = scheme + bhost_off;
|
|
path = scheme + bpath_off;
|
|
return 0;
|
|
}
|
|
*/
|
|
/* url_do_full -- Try to parse a full URL */
|
|
/*
|
|
int url_do_full(char*src){
|
|
char* p = strstr(src,"://"); //if scheme is there it ends with spartan|://|host|/|
|
|
if(!p)
|
|
return 1; //no scheme sigil = error!
|
|
|
|
scheme = src; //scheme at start
|
|
host = p+3; //host starts after ://
|
|
path = strchr(host,'/'); //host ends with a /path
|
|
if(!path) { // if no path provided,
|
|
int i = strlen(host); // append a '/' and make one.
|
|
path = host+i;
|
|
*path='/';
|
|
*(path+1)=0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
//int url_is_full(char*src){
|
|
|
|
|
|
|
|
char* path_norm(char* path){
|
|
*(path-1) = 0;
|
|
char* src = path;
|
|
char* dst = path;
|
|
char c;
|
|
while((c=(*dst++ = *src++))){
|
|
if('/'==c){
|
|
if(!strncmp(src,"../",3)){
|
|
if(!(dst = path_backup(dst-1)))
|
|
return NULL;
|
|
src += 2;
|
|
} else if(!strncmp(src,"./",2)) {
|
|
src += 2;
|
|
} else if(!strcmp(src,"..")){
|
|
if(!(dst = path_backup(dst-1)))
|
|
return NULL;
|
|
dst++; // leave the slash
|
|
src += 2;
|
|
// printf("src:[%s]; dst:[%s];\n",src,dst);
|
|
} else if(!strcmp(src,".")){
|
|
src++;
|
|
}
|
|
}
|
|
}
|
|
return path;
|
|
}
|
|
|
|
*/
|
|
/*
|
|
int main(int argc,char**argv)
|
|
{
|
|
sUrl base;
|
|
sUrl_set(&base,"spartan://192.168.0.2:8888/servlet/rece/holo");
|
|
sUrl_full(&base);
|
|
printf("FILE: %s\n",sUrl_file(&base));
|
|
|
|
|
|
sUrl url;
|
|
sUrl_copy(&url, &base);
|
|
sUrl_rel(&url,argv[1]);
|
|
|
|
int q = sUrl_norm(&url);
|
|
printf("normalize returned %d\n",q);
|
|
sUrl_print(&url);
|
|
return 0;
|
|
// strcpy(URL_base,"spartan://192.168.0.2:8888/servlet/rece/");
|
|
//baselen = strlen(URL_base);
|
|
//bhost_off = 10;
|
|
//bpath_off = 26;
|
|
*/
|
|
/*
|
|
memset(buf,0,2048);
|
|
strcpy(buf+256,argv[1]);
|
|
q = url_do_full(buf+256);
|
|
int lScheme = (int)(host-scheme);
|
|
printf("Returned %d\n",q);
|
|
printf("scheme: %*.*s\n",lScheme,lScheme,scheme);
|
|
printf("host: %s\n",host);
|
|
printf("path: %s\n",path);
|
|
*/
|
|
|
|
// char* p = path_norm(path);
|
|
//printf("norm: %s\n",p);
|
|
|
|
//}
|
|
|