📄 chxavurlrep.cpp
字号:
/*============================================================================*
*
* (c) 1995-2002 RealNetworks, Inc. Patents pending. All rights reserved.
*
*============================================================================*/
#include "chxavurlrep.h"
#include "char_stack.h"
#include "chxavconvertutil.h"
#include "chxavvector.h"
inline
static bool IsURLAlpha(char ch)
{
return (((ch >= 'a') && (ch <= 'z')) ||
((ch >= 'A') && (ch <= 'Z')));
}
inline
static bool IsURLDigit(char ch)
{
return ((ch >= '0') && (ch <= '9'));
}
inline
static bool IsURLAlnum(char ch)
{
return (IsURLAlpha(ch) || IsURLDigit(ch));
}
inline
static bool IsURLSchemeChar(char ch)
{
return (IsURLAlnum(ch) || strchr("+-.", ch));
}
CHXAvURLRep::CHXAvURLRep(const CHXString& url_string)
: m_String(""),
m_Protocol(""),
m_Host(""),
m_Port(0),
m_parseSuccess(false),
m_hasNetPath(false),
m_hasAbsPath(false),
m_hasQuery(false)
{
m_parseSuccess =ParseURL(url_string, m_Protocol, m_Host, m_Port,
m_Path, m_Query, m_Fragment,
m_hasNetPath, m_hasAbsPath, m_hasQuery,
m_hasFragment);
BuildURL(m_String, m_Protocol, m_Host, m_Port,
m_Path, m_Query, m_Fragment,
m_hasNetPath, m_hasAbsPath, m_hasQuery, m_hasFragment);
}
CHXAvURLRep::~CHXAvURLRep()
{}
int CHXAvURLRep::operator==(const CHXAvURLRep& url) const
{
return
(stricmp(url.m_Protocol, m_Protocol) == 0) &&
(stricmp(url.m_Host, m_Host) == 0) &&
url.m_Port == m_Port &&
url.m_Path == m_Path &&
url.m_Query == m_Query &&
url.m_Fragment == m_Fragment &&
url.m_hasNetPath == m_hasNetPath &&
url.m_hasAbsPath == m_hasAbsPath &&
url.m_hasQuery == m_hasQuery &&
url.m_hasFragment == m_hasFragment;
}
int CHXAvURLRep::operator!=(const CHXAvURLRep& url) const
{
return ! operator==(url);
}
CHXAvURLRep::CHXAvURLRep(const CHXString& protocol, const CHXString& host,
int port,
const CHXString& path,
const CHXString& query)
: m_String(""),
m_Protocol(protocol),
m_Host(host),
m_Port(port),
m_parseSuccess(true),
m_hasNetPath(false),
m_hasAbsPath(false),
m_hasQuery(false),
m_hasFragment(false)
{
m_Path.EscapePathStr(path);
m_Query.EscapeQueryStr(query);
if (protocol.GetLength() ||
host.GetLength())
m_hasNetPath = true;
if (m_hasNetPath && path.GetLength())
m_hasAbsPath = true;
if (query.GetLength())
m_hasQuery = true;
BuildURL(m_String, m_Protocol, m_Host, m_Port,
m_Path, m_Query, m_Fragment,
m_hasNetPath, m_hasAbsPath, m_hasQuery, m_hasFragment);
}
CHXAvURLRep::CHXAvURLRep(const CHXString& protocol, const CHXString& host,
int port,
const CHXAvEscapedString& path,
const CHXAvEscapedString& query)
: m_String(""),
m_Protocol(protocol),
m_Host(host),
m_Port(port),
m_Path(path),
m_Query(query),
m_parseSuccess(true),
m_hasNetPath(false),
m_hasAbsPath(false),
m_hasQuery(false),
m_hasFragment(false)
{
if (protocol.GetLength() ||
host.GetLength())
m_hasNetPath = true;
if (m_hasNetPath && path.GetEscapedStr().GetLength())
m_hasAbsPath = true;
if (query.GetEscapedStr().GetLength())
m_hasQuery = true;
BuildURL(m_String, m_Protocol, m_Host, m_Port,
m_Path, m_Query, m_Fragment,
m_hasNetPath, m_hasAbsPath, m_hasQuery, m_hasFragment);
}
const CHXString& CHXAvURLRep::String() const
{
return m_String;
}
const CHXString& CHXAvURLRep::Protocol() const
{
return m_Protocol;
}
const CHXString& CHXAvURLRep::Host() const
{
return m_Host;
}
int CHXAvURLRep::Port() const
{
return m_Port;
}
const CHXString& CHXAvURLRep::Path() const
{
return m_Path.GetUnEscapedStr();
}
const CHXAvEscapedString& CHXAvURLRep::EscapedPath() const
{
return m_Path;
}
const CHXString& CHXAvURLRep::Query() const
{
return m_Query.GetUnEscapedStr();
}
const CHXAvEscapedString& CHXAvURLRep::EscapedQuery() const
{
return m_Query;
}
const CHXAvEscapedString& CHXAvURLRep::EscapedFragment() const
{
return m_Fragment;
}
bool CHXAvURLRep::IsAbsoluteURL() const
{
return (m_Protocol.GetLength() &&
(m_Path.GetEscapedStr().GetLength() ||
m_hasNetPath || m_hasAbsPath || m_hasQuery || m_hasFragment));
}
bool CHXAvURLRep::HasNetPath() const
{
return m_hasNetPath;
}
bool CHXAvURLRep::HasAbsolutePath() const
{
return m_hasAbsPath;
}
bool CHXAvURLRep::HasQuery() const
{
return m_hasQuery;
}
bool CHXAvURLRep::HasFragment() const
{
return m_hasFragment;
}
void CHXAvURLRep::BuildURL(CHXString& url,
const CHXString& protocol, const CHXString& host,
int port, const CHXAvEscapedString& path,
const CHXAvEscapedString& query,
const CHXAvEscapedString& fragment,
bool hasNetPath,
bool hasAbsPath,
bool hasQuery,
bool hasFragment)
{
url = "";
if (protocol.GetLength())
{
url += protocol;
url += ":";
}
if (hasNetPath)
{
url += "//";
url += host;
if (port > 0)
{
char buf[32];
::sprintf(buf, ":%d", port);
url += buf;
}
}
if (hasAbsPath)
url += "/";
if (path.GetEscapedStr().GetLength())
{
url += path.GetEscapedStr();
}
if (hasQuery)
{
url += "?";
url += query.GetEscapedStr();
}
if (hasFragment)
{
url += "#";
url += fragment.GetEscapedStr();
}
}
bool CHXAvURLRep::ParseURL(const CHXString& url,
CHXString& protocol, CHXString& host,
int& port, CHXAvEscapedString& path,
CHXAvEscapedString& query,
CHXAvEscapedString& fragment,
bool& hasNetPath,
bool& hasAbsPath,
bool& hasQuery,
bool& hasFragment)
{
bool ret = true;
const char* pu = url;
CharStack pf;
pf.Reset();
// protocol: scan to first ':', '/', '?', '#' or EOS
CollectChars(pu, ":/?#", pf);
// protocol found
if (*pu == ':')
{
protocol = pf.Finish();
pu++; // skip ':'
pf.Reset(); // Clear consumed characters
if (!*pu)
{
// <scheme>: form is not a valid URL
ret = false;
}
}
else // no protocol
protocol = "";
// Check for a net path
if ((strlen(pf.Finish()) == 0) &&
(pu[0] == '/') && (pu[1] == '/'))
{
// This is a net path
hasNetPath = true;
pu += 2; // Skip "//"
// Collect the host name
CollectChars(pu, ":/?#", pf);
host = pf.Finish();
pf.Reset(); // Clear consumed characters
// maybe port: scan to '/' or EOS
if (*pu == ':')
{
++pu; // Skip ':'
// Collect port number
CollectChars(pu, "/?#", pf);
if (strlen(pf.Finish()) != 0)
{
if (!CHXAvConvertUtil::StringToInt(pf.Finish(), port))
{
// Port number conversion failed
ret = false;
}
pf.Reset(); // Clear consumed characters
}
else
{
port = 0;
// No port number present
ret = false;
}
}
else
port = 0;
if ((*pu == '?') || (*pu == '#'))
{
// Query or fragment delimiter before the path
ret = false;
}
}
else
{
// No net path is present
hasNetPath = false;
host = "";
port = 0;
}
// Check for absolute path
if ((strlen(pf.Finish()) == 0) &&
(*pu == '/'))
{
// This is an absolute path.
hasAbsPath = true;
pu++; // Skip the '/' since we don't
// want it appearing in our path
}
else
hasAbsPath = false;
// NOTE : pf may contain data at this point in the
// case of a relative URL
// Collect the rest of the path
CollectChars(pu, "?#", pf);
path = CHXAvEscapedString(pf.Finish());
pf.Reset(); // Clear consumed characters
// query scan to EOS
if (*pu == '?')
{
++pu; // Skip '?'
hasQuery = true;
// Collect the rest the query part
CollectChars(pu, "#", pf);
query = CHXAvEscapedString(pf.Finish());
pf.Reset(); // Clear consumed characters
}
else
{
query = CHXAvEscapedString("");
hasQuery = false;
}
if (*pu == '#')
{
++pu; // Skip '#'
hasFragment = true;
// Put the rest of the string in the fragment
fragment = CHXAvEscapedString(pu);
}
else
{
fragment = CHXAvEscapedString("");
hasFragment = false;
}
return ret;
}
bool CHXAvURLRep::Valid() const
{
return (m_parseSuccess &&
ValidProtocol() &&
ValidHostname() &&
m_Path.ValidPath() &&
m_Query.ValidQuery());
}
bool CHXAvURLRep::ValidProtocol() const
{
bool ret = true;
const char* pTmp = m_Protocol;
for(; *pTmp && ret; pTmp++)
{
// RFC 2068 'scheme' production
if (!IsURLSchemeChar(*pTmp))
ret = false;
}
return ret;
}
bool CHXAvURLRep::ValidHostname() const
{
// Checks for valid hostname as specified by RFC 952 and RFC 1123
bool ret = true;
const char* pTmp = m_Host;
if (*pTmp != '\0')
{
int len = 0;
if (IsURLAlnum(*pTmp))
{
for(; *pTmp && ret; pTmp++, len++)
{
if (!IsURLAlnum(*pTmp) && (*pTmp != '.') && (*pTmp != '-'))
ret = false;
}
}
else
{
// RFC 1123 Sec 2.1 specifies that it MUST start with a letter OR
// a number.
ret = false;
}
if (ret)
{
if (len > 1)
{
pTmp--; // move back to the last character
if ((*pTmp == '-') || (*pTmp == '.'))
{
// a hostname cannot end with a '-' or '.'
ret = false;
}
}
else
{
// a hostname MUST be more than 1 character long
ret = false;
}
}
}
return ret;
}
void CHXAvURLRep::CollectChars(const char*& pu, const char* pExtraDelim,
CharStack& token)
{
for(; *pu && !strchr(pExtraDelim, *pu); token++)
*token = *pu++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -