chxavurlrep.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:10k
- /*============================================================================*
- *
- * (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 != ' ')
- {
- 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++;
- }