home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2003 June
/
PCWorld_2003-06_cd.bin
/
KOMUNIK
/
MIRRORIT
/
SRC
/
URL.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1997-12-27
|
9KB
|
478 lines
// URL.cpp : implementation file
//
#include "stdafx.h"
#include "URL.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define SAFE "$-_.+"
#define EXTRA "!*'(),"
#define NATIONAL "{}|\\^~[]`"
#define RESERVED ";/?:@&="
#define PUNCTUATION "<>#%\""
#define DIGIT "0123456789"
#define HEX DIGIT "ABCDEF"
#define ESCAPE HEX "%"
#define LOWALPHA "abcdefghijklmnopqrstuvwxyz"
#define HIGHALPHA "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
#define ALPHA LOWALPHA HIGHALPHA
#define UNRESERVED ALPHA SAFE EXTRA NATIONAL
#define UCHAR UNRESERVED ESCAPE
#define PCHAR UCHAR ":@&="
#define SCHEME ALPHA DIGIT "+-."
#define _ABSOLUTE UCHAR RESERVED
#define NET_LOC PCHAR ";?"
#define PARAM PCHAR "/"
#define QUERY UCHAR RESERVED
LPCSTR const null = "";
/////////////////////////////////////////////////////////////////////////////
// CURL
CURL::CURL()
{
urltype = URL_EMPTY;
setschemetype();
}
CURL::~CURL()
{
}
// Do not edit the following lines, which are needed by ClassWizard.
#if 0
BEGIN_MESSAGE_MAP(CURL, CSocket)
//{{AFX_MSG_MAP(CURL)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
#endif // 0
/////////////////////////////////////////////////////////////////////////////
// CURL member functions
CURL::CURL(int aurltype, CString ascheme, CString anet_loc, CString apath, CString aparams, CString aquery, CString afragment)
{
urltype = aurltype;
scheme = ascheme;
path = apath;
net_loc = anet_loc;
path = apath;
params = aparams;
query = aquery;
fragment = afragment;
setschemetype();
}
int CURL::rel_path(LPCSTR s, LPCSTR & spath, LPCSTR & sparams, LPCSTR & squery)
{
LPTSTR s1 = NULL;
LPTSTR s2 = NULL;
if (*s && (*s == '/' || strchr(PCHAR, *s)))
{
spath = s++;
while (*s)
{
while (*s && strchr(PCHAR, *s)) s++;
if (*s == '/')
s++;
else
break;
}
}
s1 = (LPTSTR)s;
if (*s == ';')
{
sparams = ++s;
while (*s)
{
while (*s && strchr(PARAM, *s)) s++;
if (*s == ';')
s++;
else
break;
}
}
s2 = (LPTSTR)s;
if (*s == '?')
{
squery = ++s;
while (*s && strchr(QUERY, *s)) s++;
}
if (!*s)
{
*s1 = 0;
*s2 = 0;
}
return !*s;
}
int CURL::abs_path(LPCSTR s, LPCSTR & spath, LPCSTR & sparams, LPCSTR & squery)
{
return *s == '/' && rel_path(s + 1, spath, sparams, squery);
}
LPCSTR CURL::build(CString & url)
{
url = path;
if (!params.IsEmpty())
url += ";" + params;
if (!query.IsEmpty())
url += "?" + query;
if (!fragment.IsEmpty())
url += "#" + fragment;
if (!net_loc.IsEmpty())
{
if (!url.IsEmpty() && url[0] != '/') url = '/' + url;
url = "//" + net_loc + url;
}
if (!scheme.IsEmpty())
url = scheme + ":" + url;
return (LPCSTR) url;
}
CURL * CURL::expand(CURL * base)
{
LPCSTR sscheme;
LPCSTR snet_loc;
LPCSTR spath;
LPCSTR sparams;
LPCSTR squery;
LPCSTR sfragment;
LPTSTR buf;
LPTSTR buf2;
LPTSTR s1;
LPTSTR s2;
LPTSTR s3;
LPTSTR s4;
int surltype = URL_NOERROR;
//step 1 and 2b
if (base -> urltype == URL_EMPTY || !scheme.IsEmpty())
return new CURL(urltype, scheme, net_loc, path, params, query, fragment);
//step 2a
if (urltype == URL_EMPTY)
return new CURL(base -> urltype, base -> scheme, base -> net_loc,
base -> path, base -> params, base -> query, base -> fragment);
CString sbuf, sbuf2;
buf = sbuf.GetBuffer(path.GetLength() + base -> path.GetLength());
buf2 = sbuf2.GetBuffer(path.GetLength() + base -> path.GetLength());
//step 2c
sscheme = (LPCSTR) base -> scheme;
snet_loc = (LPCSTR) net_loc;
sparams = (LPCSTR) params;
squery = (LPCSTR) query;
spath = (LPCSTR) path;
sfragment = (LPCSTR) fragment;
//step 3
if (net_loc.IsEmpty())
{
snet_loc = (LPCSTR) base -> net_loc;
//step 4
if (* (LPCSTR) path != '/')
{
//step 5
if (path.IsEmpty())
{
spath = (LPCSTR) base -> path;
if (params.IsEmpty())
{
sparams = (LPCSTR) base -> params;
if (query.IsEmpty())
squery = (LPCSTR) base -> query;
}
}
else
{
strcpy(buf, (LPCSTR) base -> path);
spath = buf;
//step 6
if ((s1 = strrchr(buf, '/')) != NULL)
*(++s1) = 0;
strcat(buf, (LPCSTR) path);
//step 6a
s4 = s1 = buf;
s2 = buf2;
while (*s1)
{
s3 = (LPTSTR) nextsegment(s1);
if (strncmp(s1, "./", 2))
{
strncpy(s2, s1, s3 - s1);
s2 += s3 - s1;
s4 = s1;
}
s1 = s3;
}
*s2 = 0;
//step 6b
if (!strcmp(s4, "."))
*(--s2) = 0;
//step 6c
s1 = buf2;
s2 = buf;
while (*s1)
{
s3 = (LPTSTR) nextsegment(s1);
s4 = (LPTSTR) prevsegment(buf, s2);
if (strncmp(s1, "../", 3) || !s4 || !strncmp(s4, "../", 3))
{
strncpy(s2, s1, s3 - s1);
s2 += s3 - s1;
}
else
{
//remove prev segment if exists
s2 = s4;
}
s1 = s3;
}
*s2 = 0;
//step 6c
s1 = buf + strlen(buf);
while (s1 > buf)
{
if (*s1 == '/') s1--;
for (s2 = s1; s2 > buf && *(s2 - 1) != '/'; s2--);
if (!strncmp(s2, "..", 3) && s2 >= buf)
{
for (s3 = s2 - 2; s3 > buf && *(s3 - 1) != '/'; s3--);
s1 = s3;
}
else
break;
}
*s1 = 0;
spath = buf;
}
}
else
spath = (LPCSTR) path;
}
else
{
snet_loc = (LPCSTR) net_loc;
}
//step 7
if (!fragment.IsEmpty())
sfragment = (LPCSTR) fragment;
CURL *res = new CURL(surltype, sscheme, snet_loc, spath, sparams, squery, sfragment);
// res -> slash = sslash;
sbuf.ReleaseBuffer();
sbuf2.ReleaseBuffer();
return res;
}
LPCSTR CURL::prevsegment(LPCSTR base, LPCSTR s)
{
if (s < base + 2) return NULL;
s -= 2;
while (s > base && *s != '/') s--;
if (*s == '/') s++;
return s;
}
LPCSTR CURL::nextsegment(LPCSTR s)
{
while (*s && *s != '/') s++;
if (*s == '/') s++;
return s;
}
CURL::CURL(LPCSTR url)
{
parse(url);
}
LPCSTR CURL::relbuild(CString & relurl)
{
relurl = path;
if (!params.IsEmpty())
relurl += ";" + params;
if (!query.IsEmpty())
relurl += "?" + query;
if (!fragment.IsEmpty())
relurl += "#" + fragment;
if (relurl.IsEmpty()) relurl = "/";
return (LPCSTR) relurl;
}
void CURL::setschemetype()
{
CString sch(scheme);
sch.MakeLower();
if (!sch.Compare("file"))
schemetype = SCHEME_FILE;
else
if (!sch.Compare("http"))
schemetype = SCHEME_HTTP;
else
schemetype = SCHEME_UNKNOWN;
}
void CURL::topath(CString & res)
{
res = path;
if (res[0] == '/')
res = res.Mid(1);
LPTSTR s = res.GetBuffer(res.GetLength());
for (; *s; s++)
{
if (*s == '/')
*s = SEPCHAR;
else
if (*s == '|')
*s = ':';
}
res.ReleaseBuffer();
}
void CURL::getdir(CString & dir)
{
dir = path.Mid(1);
if (dir[dir.GetLength() - 1] != '/')
{
int i = dir.ReverseFind('/');
if (i == -1)
dir.Empty();
else
dir = dir.Left(i);
}
}
void CURL::getname(CString & name)
{
int i = path.ReverseFind('/');
if (i == -1)
name = path;
else
name = path.Mid(i + 1);
}
void CURL::parse(LPCSTR url)
{
LPTSTR s;
LPTSTR s1;
LPTSTR s2;
LPCSTR sfragment;
LPCSTR sscheme;
LPCSTR snet_loc;
LPCSTR spath;
LPCSTR squery;
LPCSTR sparams;
int relative, slash = 0;
CString copy(url);
s = copy.GetBuffer(copy.GetLength());
sfragment = null;
sscheme = null;
snet_loc = null;
spath = null;
squery = null;
sparams = null;
urltype = URL_EMPTY;
if (*s)
{
urltype = URL_NOERROR;
//fragment
sfragment = strchr(s, '#');
if (sfragment)
*((LPTSTR)sfragment++) = 0;
else
sfragment = null;
//scheme
s1 = s;
while (*s1 && strchr(SCHEME, *s1)) s1++;
if (*s1 == ':' && s1 > s)
{
sscheme = s;
if (*s1)
*(s1++) = 0;
}
else
{
sscheme = null;
s1 = s;
}
//net_loc
s2 = s1;
if (s1[0] == '/' && s1[1] == '/')
{
s1 += 2;
while (*s1 && strchr(NET_LOC, *s1)) s1++;
snet_loc = s2 + 2;
slash = *s1 == '/';
if (*s1)
*(s1++) = 0;
}
relative = abs_path(s1, spath, sparams, squery);
if (!relative)
relative = rel_path(s1, spath, sparams, squery);
else
slash = 1;
if (!relative)
{
while (*s1 && strchr(_ABSOLUTE, *s1)) s1++;
if (!*s1) urltype = URL_INVALID;
}
}
scheme = sscheme;
scheme.MakeLower();
net_loc = snet_loc;
if (slash)
path = _T("/") + CString(spath);
else
path = spath;
params = sparams;
query = squery;
fragment = sfragment;
copy.ReleaseBuffer();
setschemetype();
}