chxavurlrep.cpp
上传用户:zhongxx05
上传日期:2007-06-06
资源大小:33641k
文件大小:10k
源码类别:

Symbian

开发平台:

C/C++

  1. /*============================================================================*
  2.  *
  3.  * (c) 1995-2002 RealNetworks, Inc. Patents pending. All rights reserved.
  4.  *
  5.  *============================================================================*/
  6.  
  7. #include "chxavurlrep.h"
  8. #include "char_stack.h"
  9. #include "chxavconvertutil.h"
  10. #include "chxavvector.h"
  11. inline
  12. static bool IsURLAlpha(char ch)
  13. {
  14.     return (((ch >= 'a') && (ch <= 'z')) ||
  15.     ((ch >= 'A') && (ch <= 'Z')));
  16. }
  17. inline
  18. static bool IsURLDigit(char ch)
  19. {
  20.     return ((ch >= '0') && (ch <= '9'));
  21. }
  22. inline
  23. static bool IsURLAlnum(char ch)
  24. {
  25.     return (IsURLAlpha(ch) || IsURLDigit(ch));
  26. }
  27. inline
  28. static bool IsURLSchemeChar(char ch)
  29. {
  30.     return (IsURLAlnum(ch) || strchr("+-.", ch));
  31. }
  32. CHXAvURLRep::CHXAvURLRep(const CHXString& url_string)
  33.     : m_String(""),
  34.       m_Protocol(""),
  35.       m_Host(""),
  36.       m_Port(0),
  37.       m_parseSuccess(false),
  38.       m_hasNetPath(false),
  39.       m_hasAbsPath(false),
  40.       m_hasQuery(false)
  41. {
  42.     m_parseSuccess =ParseURL(url_string, m_Protocol, m_Host, m_Port, 
  43.      m_Path, m_Query, m_Fragment,
  44.      m_hasNetPath, m_hasAbsPath, m_hasQuery, 
  45.      m_hasFragment);
  46.     BuildURL(m_String, m_Protocol, m_Host, m_Port, 
  47.      m_Path, m_Query, m_Fragment,
  48.      m_hasNetPath, m_hasAbsPath, m_hasQuery, m_hasFragment);
  49. }
  50. CHXAvURLRep::~CHXAvURLRep()
  51. {}
  52. int CHXAvURLRep::operator==(const CHXAvURLRep& url) const
  53. {
  54.     return
  55. (stricmp(url.m_Protocol, m_Protocol) == 0) &&
  56. (stricmp(url.m_Host, m_Host) == 0) &&
  57. url.m_Port     == m_Port &&
  58. url.m_Path     == m_Path &&
  59. url.m_Query    == m_Query &&
  60. url.m_Fragment == m_Fragment &&
  61. url.m_hasNetPath == m_hasNetPath &&
  62. url.m_hasAbsPath == m_hasAbsPath &&
  63. url.m_hasQuery   == m_hasQuery &&
  64. url.m_hasFragment   == m_hasFragment;
  65. }
  66. int CHXAvURLRep::operator!=(const CHXAvURLRep& url) const
  67. {
  68.     return ! operator==(url);
  69. }
  70. CHXAvURLRep::CHXAvURLRep(const CHXString& protocol, const CHXString& host,
  71.    int port,
  72.    const CHXString& path,
  73.    const CHXString& query)
  74.     : m_String(""),
  75.       m_Protocol(protocol),
  76.       m_Host(host),
  77.       m_Port(port),
  78.       m_parseSuccess(true),
  79.       m_hasNetPath(false),
  80.       m_hasAbsPath(false),
  81.       m_hasQuery(false),
  82.       m_hasFragment(false)
  83. {
  84.     m_Path.EscapePathStr(path);
  85.     m_Query.EscapeQueryStr(query);
  86.     if (protocol.GetLength() ||
  87. host.GetLength())
  88. m_hasNetPath = true;
  89.     if (m_hasNetPath && path.GetLength())
  90. m_hasAbsPath = true;
  91.     if (query.GetLength())
  92. m_hasQuery = true;
  93.     BuildURL(m_String, m_Protocol, m_Host, m_Port, 
  94.      m_Path, m_Query, m_Fragment,
  95.      m_hasNetPath, m_hasAbsPath, m_hasQuery, m_hasFragment);
  96. }
  97. CHXAvURLRep::CHXAvURLRep(const CHXString& protocol, const CHXString& host,
  98.    int port,
  99.    const CHXAvEscapedString& path,
  100.    const CHXAvEscapedString& query)
  101.     : m_String(""),
  102.       m_Protocol(protocol),
  103.       m_Host(host),
  104.       m_Port(port),
  105.       m_Path(path),
  106.       m_Query(query),
  107.       m_parseSuccess(true),
  108.       m_hasNetPath(false),
  109.       m_hasAbsPath(false),
  110.       m_hasQuery(false),
  111.       m_hasFragment(false)
  112. {
  113.     if (protocol.GetLength() ||
  114. host.GetLength())
  115. m_hasNetPath = true;
  116.     if (m_hasNetPath && path.GetEscapedStr().GetLength())
  117. m_hasAbsPath = true;
  118.     if (query.GetEscapedStr().GetLength())
  119. m_hasQuery = true;
  120.     BuildURL(m_String, m_Protocol, m_Host, m_Port, 
  121.      m_Path, m_Query, m_Fragment,
  122.      m_hasNetPath, m_hasAbsPath, m_hasQuery, m_hasFragment);
  123. }
  124. const CHXString& CHXAvURLRep::String() const
  125. {
  126.     return m_String;
  127. }
  128. const CHXString& CHXAvURLRep::Protocol() const
  129. {
  130.     return m_Protocol;
  131. }
  132. const CHXString& CHXAvURLRep::Host() const
  133. {
  134.     return m_Host;
  135. }
  136. int CHXAvURLRep::Port() const
  137. {
  138.     return m_Port;
  139. }
  140. const CHXString& CHXAvURLRep::Path() const
  141. {
  142.     return m_Path.GetUnEscapedStr();
  143. }
  144.  
  145. const CHXAvEscapedString& CHXAvURLRep::EscapedPath() const
  146. {
  147.     return m_Path;
  148. }
  149. const CHXString& CHXAvURLRep::Query() const
  150. {
  151.     return m_Query.GetUnEscapedStr();
  152. }
  153.  
  154. const CHXAvEscapedString& CHXAvURLRep::EscapedQuery() const
  155. {
  156.     return m_Query;
  157. }
  158. const CHXAvEscapedString& CHXAvURLRep::EscapedFragment() const
  159. {
  160.     return m_Fragment;
  161. }
  162. bool CHXAvURLRep::IsAbsoluteURL() const
  163. {
  164.     return (m_Protocol.GetLength() &&
  165.     (m_Path.GetEscapedStr().GetLength() ||
  166.      m_hasNetPath || m_hasAbsPath || m_hasQuery || m_hasFragment));
  167. }
  168. bool CHXAvURLRep::HasNetPath() const
  169. {
  170.     return m_hasNetPath;
  171. }
  172. bool CHXAvURLRep::HasAbsolutePath() const
  173. {
  174.     return m_hasAbsPath;
  175. }
  176. bool CHXAvURLRep::HasQuery() const
  177. {
  178.     return m_hasQuery;
  179. }
  180. bool CHXAvURLRep::HasFragment() const
  181. {
  182.     return m_hasFragment;
  183. }
  184.   
  185. void CHXAvURLRep::BuildURL(CHXString& url,
  186. const CHXString& protocol, const CHXString& host,
  187. int port, const CHXAvEscapedString& path, 
  188. const CHXAvEscapedString& query,
  189. const CHXAvEscapedString& fragment,
  190. bool hasNetPath,
  191. bool hasAbsPath,
  192. bool hasQuery,
  193. bool hasFragment)
  194. {
  195.     url = "";
  196.     if (protocol.GetLength())
  197.     {
  198. url += protocol;
  199. url += ":";
  200.     }
  201.     if (hasNetPath)
  202.     {
  203. url += "//";
  204. url += host;
  205. if (port > 0)
  206. {
  207.     char buf[32];
  208.     ::sprintf(buf, ":%d", port);
  209.     url += buf;
  210. }
  211.     }
  212.     
  213.     if (hasAbsPath)
  214. url += "/";
  215.     if (path.GetEscapedStr().GetLength())
  216.     {
  217. url += path.GetEscapedStr();
  218.     }
  219.     if (hasQuery)
  220.     {
  221. url += "?";
  222. url += query.GetEscapedStr();
  223.     }
  224.     if (hasFragment)
  225.     {
  226. url += "#";
  227. url += fragment.GetEscapedStr();
  228.     }
  229. }
  230. bool CHXAvURLRep::ParseURL(const CHXString& url,
  231. CHXString& protocol, CHXString& host,
  232. int& port, CHXAvEscapedString& path,  
  233. CHXAvEscapedString& query,
  234. CHXAvEscapedString& fragment,
  235. bool& hasNetPath,
  236. bool& hasAbsPath,
  237. bool& hasQuery,
  238. bool& hasFragment)
  239. {
  240.     bool ret = true;
  241.     const char* pu = url;
  242.     CharStack pf;
  243.     pf.Reset();
  244.                            // protocol: scan to first ':', '/', '?', '#' or EOS
  245.     CollectChars(pu, ":/?#", pf);
  246. // protocol found
  247.     if (*pu == ':')
  248.     {
  249. protocol = pf.Finish();
  250. pu++; // skip ':'
  251. pf.Reset();  // Clear consumed characters
  252. if (!*pu)
  253. {
  254.     // <scheme>: form is not a valid URL
  255.     ret = false;
  256. }
  257.     }
  258.     else // no protocol
  259. protocol = "";
  260.     // Check for a net path
  261.     if ((strlen(pf.Finish()) == 0) &&
  262. (pu[0] == '/') && (pu[1] == '/'))
  263.     {
  264. // This is a net path
  265. hasNetPath = true;
  266. pu += 2; // Skip "//"
  267. // Collect the host name
  268. CollectChars(pu, ":/?#", pf);
  269. host = pf.Finish();
  270. pf.Reset(); // Clear consumed characters
  271. // maybe port: scan to '/' or EOS
  272. if (*pu == ':')
  273. {
  274.     ++pu; // Skip ':'
  275.                                // Collect port number
  276.     CollectChars(pu, "/?#", pf);
  277.     if (strlen(pf.Finish()) != 0)
  278.     {
  279. if (!CHXAvConvertUtil::StringToInt(pf.Finish(), port))
  280. {
  281.     // Port number conversion failed
  282.     ret = false;
  283. }
  284. pf.Reset(); // Clear consumed characters
  285.     }
  286.     else
  287.     {
  288. port = 0;
  289. // No port number present
  290. ret = false;
  291.     }
  292. }
  293. else
  294.     port = 0;
  295. if ((*pu == '?') || (*pu == '#'))
  296. {
  297.     // Query or fragment delimiter before the path
  298.     ret = false;
  299. }
  300.     }
  301.     else
  302.     {
  303. // No net path is present
  304. hasNetPath = false;
  305. host = "";
  306. port = 0;
  307.     }
  308.     // Check for absolute path
  309.     if ((strlen(pf.Finish()) == 0) &&
  310. (*pu == '/'))
  311.     {
  312. // This is an absolute path.
  313. hasAbsPath = true;
  314. pu++; // Skip the '/' since we don't
  315.       // want it appearing in our path
  316.     }
  317.     else
  318. hasAbsPath = false;
  319.     // NOTE : pf may contain data at this point in the
  320.     //        case of a relative URL
  321.     // Collect the rest of the path
  322.     CollectChars(pu, "?#", pf);
  323.     path = CHXAvEscapedString(pf.Finish());
  324.     pf.Reset(); // Clear consumed characters
  325.     
  326.      // query scan to EOS
  327.     if (*pu == '?')
  328.     {
  329. ++pu; // Skip '?'
  330. hasQuery = true;
  331. // Collect the rest the query part
  332. CollectChars(pu, "#", pf);
  333. query = CHXAvEscapedString(pf.Finish());
  334. pf.Reset(); // Clear consumed characters
  335.     }
  336.     else
  337.     {
  338. query = CHXAvEscapedString("");
  339. hasQuery = false;
  340.     }
  341.     if (*pu == '#')
  342.     {
  343. ++pu; // Skip '#'
  344. hasFragment = true;
  345. // Put the rest of the string in the fragment
  346. fragment = CHXAvEscapedString(pu);
  347.     }
  348.     else
  349.     {
  350. fragment = CHXAvEscapedString("");
  351. hasFragment = false;
  352.     }
  353.     return ret;
  354. }
  355. bool CHXAvURLRep::Valid() const
  356. {
  357.     return (m_parseSuccess &&
  358.     ValidProtocol() &&
  359.     ValidHostname() &&
  360.     m_Path.ValidPath() && 
  361.     m_Query.ValidQuery());
  362. }
  363. bool CHXAvURLRep::ValidProtocol() const
  364. {
  365.     bool ret = true;
  366.     
  367.     const char* pTmp = m_Protocol;
  368.     for(; *pTmp && ret; pTmp++)
  369.     {
  370. // RFC 2068 'scheme' production
  371. if (!IsURLSchemeChar(*pTmp))
  372.     ret = false;
  373.     }
  374.     return ret;
  375. }
  376. bool CHXAvURLRep::ValidHostname() const
  377. {
  378.     // Checks for valid hostname as specified by RFC 952 and RFC 1123
  379.     bool ret = true;
  380.     
  381.     const char* pTmp = m_Host;
  382.     if (*pTmp != '')
  383.     {
  384. int len = 0;
  385. if (IsURLAlnum(*pTmp))
  386. {
  387.     for(; *pTmp && ret; pTmp++, len++)
  388.     {     
  389. if (!IsURLAlnum(*pTmp) && (*pTmp != '.') && (*pTmp != '-'))
  390.     ret = false;
  391.     }
  392. }
  393. else
  394. {
  395.     // RFC 1123 Sec 2.1 specifies that it MUST start with a letter OR
  396.     // a number.
  397.     ret = false;
  398. }
  399. if (ret)
  400. {
  401.     if (len > 1)
  402.     {
  403. pTmp--; // move back to the last character
  404. if ((*pTmp == '-') || (*pTmp == '.'))
  405. {
  406.     // a hostname cannot end with a '-' or '.'
  407.     ret = false;
  408. }
  409.     }
  410.     else
  411.     {
  412. // a hostname MUST be more than 1 character long
  413. ret = false;
  414.     }
  415. }
  416.     }
  417.     return ret;
  418. }
  419. void CHXAvURLRep::CollectChars(const char*& pu, const char* pExtraDelim,
  420.     CharStack& token)
  421. {
  422.     for(; *pu && !strchr(pExtraDelim, *pu); token++)
  423. *token = *pu++;
  424. }