home *** CD-ROM | disk | FTP | other *** search
- // 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();
- }
-