XMLUri.cpp
上传用户:zhuqijet
上传日期:2013-06-25
资源大小:10074k
文件大小:44k
源码类别:

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: XMLUri.cpp,v 1.12 2003/05/16 06:01:53 knoaman Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/PlatformUtils.hpp>
  63. #include <xercesc/util/Janitor.hpp>
  64. #include <xercesc/util/XMLURL.hpp>
  65. #include <xercesc/util/XMLUri.hpp>
  66. #include <xercesc/util/XMLString.hpp>
  67. #include <xercesc/util/XMLUniDefs.hpp>
  68. #include <xercesc/util/XMLUni.hpp>
  69. XERCES_CPP_NAMESPACE_BEGIN
  70. // ---------------------------------------------------------------------------
  71. //  XMLUri: static data
  72. // ---------------------------------------------------------------------------
  73. //      Amended by RFC2732
  74. //      reserved      = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" |
  75. //                      "$" | "," | "[" | "]"
  76. //
  77. const XMLCh XMLUri::RESERVED_CHARACTERS[] =
  78. {
  79.     chSemiColon, chForwardSlash, chQuestion, chColon, chAt,
  80.     chAmpersand, chEqual, chPlus, chDollarSign, chComma, chNull
  81. };
  82. //
  83. //      mark          = "-" | "_" | "." | "!" | "~" | "*" | "'" |
  84. //                      "(" | ")"
  85. //
  86. const XMLCh XMLUri::MARK_CHARACTERS[] =
  87. {
  88.     chDash, chUnderscore, chPeriod, chBang, chTilde,
  89.     chAsterisk, chSingleQuote, chOpenParen, chCloseParen, chNull
  90. };
  91. //
  92. //      scheme        = alpha *( alpha | digit | "+" | "-" | "." )
  93. //
  94. const XMLCh XMLUri::SCHEME_CHARACTERS[] =
  95. {
  96.     chPlus, chDash, chPeriod, chNull
  97. };
  98. //
  99. //      userinfo      = *( unreserved | escaped |
  100. //                         ";" | ":" | "&" | "=" | "+" | "$" | "," )
  101. //
  102. const XMLCh XMLUri::USERINFO_CHARACTERS[] =
  103. {
  104.     chSemiColon, chColon, chAmpersand, chEqual, chPlus,
  105.     chDollarSign, chPeriod, chNull
  106. };
  107. // ---------------------------------------------------------------------------
  108. //  Local methods and data
  109. // ---------------------------------------------------------------------------
  110. static const int BUF_LEN = 64;
  111. static XMLCh value1[BUF_LEN+1];
  112. //
  113. // "Scheme"
  114. // "SchemeSpecificPart"
  115. // "Parameters"
  116. // "UserInfo"
  117. // "Host"
  118. // "Port"
  119. // "Path"
  120. // "Query"
  121. // "Fragment"
  122. //
  123. static const XMLCh errMsg_SCHEME[] =
  124. {
  125.     chLatin_S, chLatin_c, chLatin_h, chLatin_e,
  126.     chLatin_m, chLatin_e, chNull
  127. };
  128. static const XMLCh errMsg_SCHEMESPART[] =
  129. {
  130.     chLatin_S, chLatin_c, chLatin_h, chLatin_e, chLatin_m, chLatin_e,
  131.     chLatin_S, chLatin_p, chLatin_e, chLatin_c, chLatin_i, chLatin_f,
  132.     chLatin_i, chLatin_c, chLatin_P, chLatin_a, chLatin_r, chLatin_t,
  133.     chNull
  134. };
  135. static const XMLCh errMsg_PARAMS[] =
  136. {
  137.     chLatin_P, chLatin_a, chLatin_r, chLatin_a, chLatin_m,
  138.     chLatin_e, chLatin_t, chLatin_e, chLatin_r, chLatin_s, chNull
  139. };
  140. static const XMLCh errMsg_USERINFO[] =
  141. {
  142.     chLatin_U, chLatin_s, chLatin_e, chLatin_r,
  143.     chLatin_i, chLatin_n, chLatin_f, chLatin_o, chNull
  144. };
  145. static const XMLCh errMsg_HOST[] =
  146. {
  147.     chLatin_H, chLatin_o, chLatin_s, chLatin_t, chNull
  148. };
  149. static const XMLCh errMsg_PORT[] =
  150. {
  151.     chLatin_P, chLatin_o, chLatin_r, chLatin_t, chNull
  152. };
  153. static const XMLCh errMsg_PATH[] =
  154. {
  155.     chLatin_P, chLatin_a, chLatin_t, chLatin_h, chNull
  156. };
  157. static const XMLCh errMsg_QUERY[] =
  158. {
  159.     chLatin_Q, chLatin_u, chLatin_e, chLatin_r, chLatin_y, chNull
  160. };
  161. static const XMLCh errMsg_FRAGMENT[] =
  162. {
  163.     chLatin_F, chLatin_r, chLatin_a, chLatin_g,
  164.     chLatin_m, chLatin_e, chLatin_n, chLatin_t, chNull
  165. };
  166. //
  167. //  "//"
  168. //  "/"
  169. //  "./"
  170. //  "/."
  171. //  "/../"
  172. //  "/.."
  173. //
  174. static const XMLCh DOUBLE_SLASH[] =
  175. {
  176.     chForwardSlash, chForwardSlash, chNull
  177. };
  178. static const XMLCh SINGLE_SLASH[] =
  179. {
  180.     chForwardSlash, chNull
  181. };
  182. static const XMLCh SLASH_DOT_SLASH[] =
  183. {
  184.     chForwardSlash, chPeriod, chForwardSlash, chNull
  185. };
  186. static const XMLCh SLASH_DOT[] =
  187. {
  188.     chForwardSlash, chPeriod, chNull
  189. };
  190. static const XMLCh SLASH_DOTDOT_SLASH[] =
  191. {
  192.     chForwardSlash, chPeriod, chPeriod, chForwardSlash, chNull
  193. };
  194. static const XMLCh SLASH_DOTDOT[] =
  195. {
  196.     chForwardSlash, chPeriod, chPeriod, chNull
  197. };
  198. //
  199. //  ":/?#"
  200. //
  201. // REVISIT: why?
  202. static const XMLCh SCHEME_SEPARATORS[] =
  203. {
  204.     chColon, chForwardSlash, chQuestion, chPound, chNull
  205. };
  206. //
  207. //  "?#"
  208. //
  209. static const XMLCh PATH_SEPARATORS[] =
  210. {
  211.     chQuestion, chPound, chNull
  212. };
  213. // ---------------------------------------------------------------------------
  214. //  XMLUri: Constructors and Helper methods
  215. // ---------------------------------------------------------------------------
  216. // ctor# 2
  217. XMLUri::XMLUri(const XMLCh* const uriSpec,
  218.                MemoryManager* const manager)
  219. : fScheme(0)
  220. , fUserInfo(0)
  221. , fHost(0)
  222. , fPort(-1)
  223. , fPath(0)
  224. , fQueryString(0)
  225. , fFragment(0)
  226. , fURIText(0)
  227. , fMemoryManager(manager)
  228. {
  229.     try {
  230.         initialize((XMLUri *)0, uriSpec);
  231.     }
  232.     catch (...)
  233.     {
  234.         cleanUp();
  235.         throw;
  236.     }
  237. }
  238. // ctor# 7 relative ctor
  239. XMLUri::XMLUri(const XMLUri* const      baseURI
  240.               , const XMLCh* const   uriSpec
  241.               , MemoryManager* const manager)
  242. : fScheme(0)
  243. , fUserInfo(0)
  244. , fHost(0)
  245. , fPort(-1)
  246. , fPath(0)
  247. , fQueryString(0)
  248. , fFragment(0)
  249. , fURIText(0)
  250. , fMemoryManager(manager)
  251. {
  252.     try {
  253.         initialize(baseURI, uriSpec);
  254.     }
  255.     catch (...)
  256.     {
  257.         cleanUp();
  258.         throw;
  259.     }
  260. }
  261. //Copy constructor
  262. XMLUri::XMLUri(const XMLUri& toCopy)
  263. : fScheme(0)
  264. , fUserInfo(0)
  265. , fHost(0)
  266. , fPort(-1)
  267. , fPath(0)
  268. , fQueryString(0)
  269. , fFragment(0)
  270. , fURIText(0)
  271. , fMemoryManager(toCopy.fMemoryManager)
  272. {
  273.     try {
  274.         initialize(toCopy);
  275.     }
  276.     catch (...)
  277.     {
  278.         cleanUp();
  279.         throw;
  280.     }
  281. }
  282. XMLUri& XMLUri::operator=(const XMLUri& toAssign)
  283. {
  284.     try {
  285.         initialize(toAssign);
  286.     }
  287.     catch (...)
  288.     {
  289.         cleanUp();
  290.         throw;
  291.     }
  292.     return *this;
  293. }
  294. XMLUri::~XMLUri()
  295. {
  296.     cleanUp();
  297. }
  298. void XMLUri::cleanUp()
  299. {
  300.     if (fScheme)
  301.         fMemoryManager->deallocate(fScheme);//delete[] fScheme;
  302.     if (fUserInfo)
  303.         fMemoryManager->deallocate(fUserInfo);//delete[] fUserInfo;
  304.     if (fHost)
  305.         fMemoryManager->deallocate(fHost);//delete[] fHost;
  306.     if (fPath)
  307.         fMemoryManager->deallocate(fPath);//delete[] fPath;
  308.     if (fQueryString)
  309.         fMemoryManager->deallocate(fQueryString);//delete[] fQueryString;
  310.     if (fFragment)
  311.         fMemoryManager->deallocate(fFragment);//delete[] fFragment;
  312.     fMemoryManager->deallocate(fURIText);//delete[] fURIText;
  313. }
  314. void XMLUri::initialize(const XMLUri& toCopy)
  315. {
  316.     //
  317.     // assuming that all fields from the toCopy are valid,
  318.     // therefore need NOT to go through various setXXX() methods
  319.     //
  320.     fMemoryManager = toCopy.fMemoryManager;
  321.     fScheme = XMLString::replicate(toCopy.fScheme, fMemoryManager);
  322. fUserInfo = XMLString::replicate(toCopy.fUserInfo, fMemoryManager);
  323. fHost = XMLString::replicate(toCopy.fHost, fMemoryManager);
  324. fPort = toCopy.fPort;
  325. fPath = XMLString::replicate(toCopy.fPath, fMemoryManager);
  326. fQueryString = XMLString::replicate(toCopy.fQueryString, fMemoryManager);
  327. fFragment = XMLString::replicate(toCopy.fFragment, fMemoryManager);
  328. }
  329. void XMLUri::initialize(const XMLUri* const baseURI
  330.                       , const XMLCh*  const uriSpec)
  331. {
  332.     // get a trimmed version of uriSpec
  333.     // uriSpec will NO LONGER be used in this function.
  334.     //
  335.     XMLCh* trimedUriSpec = XMLString::replicate(uriSpec, fMemoryManager);
  336.     XMLString::trim(trimedUriSpec);
  337.     ArrayJanitor<XMLCh> janName(trimedUriSpec, fMemoryManager);
  338.     int trimedUriSpecLen = XMLString::stringLen(trimedUriSpec);
  339.     if ( !baseURI &&
  340.         (!trimedUriSpec || trimedUriSpecLen == 0))
  341.     {
  342.         ThrowXML1(MalformedURLException
  343.                , XMLExcepts::XMLNUM_URI_Component_Empty
  344.                , errMsg_PARAMS);
  345.     }
  346. // just make a copy of the base if spec is empty
  347. if (!trimedUriSpec || trimedUriSpecLen == 0)
  348.     {
  349.         initialize(*baseURI);
  350.         return;
  351. }
  352. int index = 0;
  353. // Check for scheme, which must be before `/'. Also handle names with
  354. // DOS drive letters ('D:'), so 1-character schemes are not allowed.
  355.     int colonIdx = XMLString::indexOf(trimedUriSpec, chColon);
  356.     int slashIdx = XMLString::indexOf(trimedUriSpec, chForwardSlash);
  357. if ((colonIdx < 2)                         ||
  358.         (colonIdx > slashIdx && slashIdx != -1) )
  359.     {
  360.         int fragmentIdx = XMLString::indexOf(trimedUriSpec, chPound);  //'#'
  361.         // A standalone base is a valid URI according to spec
  362.         if ( !baseURI && fragmentIdx != 0 )
  363.         {
  364.             ThrowXML(MalformedURLException, XMLExcepts::XMLNUM_URI_No_Scheme);
  365.         }
  366.     }
  367. else
  368.     {
  369.         initializeScheme(trimedUriSpec);
  370.         index = XMLString::stringLen(fScheme)+1;
  371.     }
  372.     // It's an error if we stop here
  373.     if (index == trimedUriSpecLen)
  374.     {
  375.         ThrowXML1(MalformedURLException
  376.                 , XMLExcepts::XMLNUM_URI_Component_Empty
  377.                 , errMsg_PATH);
  378. }
  379. // two slashes means generic URI syntax, so we get the authority
  380.     XMLCh* authUriSpec = (XMLCh*) fMemoryManager->allocate
  381.     (
  382.         (trimedUriSpecLen+1) * sizeof(XMLCh)
  383.     );//new XMLCh[trimedUriSpecLen+1];
  384.     ArrayJanitor<XMLCh> authName(authUriSpec, fMemoryManager);
  385.     XMLString::subString(authUriSpec, trimedUriSpec, index, trimedUriSpecLen);
  386.     if (((index+1) < trimedUriSpecLen) &&
  387.         XMLString::startsWith(authUriSpec, DOUBLE_SLASH))
  388.     {
  389.         index += 2;
  390.         int startPos = index;
  391.         // get authority - everything up to path, query or fragment
  392.         XMLCh testChar;
  393.         while (index < trimedUriSpecLen)
  394.         {
  395.             testChar = trimedUriSpec[index];
  396.             if (testChar == chForwardSlash ||
  397.                 testChar == chQuestion     ||
  398.                 testChar == chPound         )
  399.             {
  400.                 break;
  401.             }
  402.             index++;
  403.         }
  404.         // if we found authority, parse it out, otherwise we set the
  405.         // host to empty string
  406.         if (index > startPos)
  407.         {
  408.             XMLString::subString(authUriSpec, trimedUriSpec, startPos, index);
  409.             initializeAuthority(authUriSpec);
  410.         }
  411.         else
  412.         {
  413.             //fHost = 0;
  414.             setHost(0);
  415.         }
  416.     }
  417.     // we need to check if index has exceed the lenght or not
  418.     if (index >= trimedUriSpecLen)
  419.         return;
  420.     XMLCh* pathUriSpec = (XMLCh*) fMemoryManager->allocate
  421.     (
  422.         (trimedUriSpecLen+1) * sizeof(XMLCh)
  423.     );//new XMLCh[trimedUriSpecLen+1];
  424.     ArrayJanitor<XMLCh> pathUriSpecName(pathUriSpec, fMemoryManager);
  425.     XMLString::subString(pathUriSpec, trimedUriSpec, index, trimedUriSpecLen);
  426. initializePath(pathUriSpec);
  427. // Resolve relative URI to base URI - see RFC 2396 Section 5.2
  428. // In some cases, it might make more sense to throw an exception
  429. // (when scheme is specified is the string spec and the base URI
  430. // is also specified, for example), but we're just following the
  431. // RFC specifications
  432. if ( baseURI )
  433.     {
  434.         // check to see if this is the current doc - RFC 2396 5.2 #2
  435.         // note that this is slightly different from the RFC spec in that
  436.         // we don't include the check for query string being null
  437.         // - this handles cases where the urispec is just a query
  438.         // string or a fragment (e.g. "?y" or "#s") -
  439.         // see <http://www.ics.uci.edu/~fielding/url/test1.html> which
  440.         // identified this as a bug in the RFC
  441.         if ((!fPath || !*fPath) &&
  442.             fScheme == 0 &&
  443.             fHost == 0)
  444.         {
  445.             fScheme = XMLString::replicate(baseURI->getScheme(), fMemoryManager);
  446.             fMemoryManager->deallocate(fUserInfo);//delete [] fUserInfo;
  447.             fUserInfo = XMLString::replicate(baseURI->getUserInfo(), fMemoryManager);
  448.             fHost = XMLString::replicate(baseURI->getHost(), fMemoryManager);
  449.             fPort = baseURI->getPort();
  450.             fMemoryManager->deallocate(fPath);//delete [] fPath;
  451.             fPath = XMLString::replicate(baseURI->getPath(), fMemoryManager);
  452.             if ( !fQueryString )
  453.             {
  454.                 fQueryString = XMLString::replicate(baseURI->getQueryString(), fMemoryManager);
  455.             }
  456.             return;
  457.         }
  458.         // check for scheme - RFC 2396 5.2 #3
  459.         // if we found a scheme, it means absolute URI, so we're done
  460.         if (fScheme == 0)
  461.         {
  462.             fScheme = XMLString::replicate(baseURI->getScheme(), fMemoryManager);
  463.         }
  464.         else
  465.         {
  466.             return;
  467.         }
  468.         // check for authority - RFC 2396 5.2 #4
  469.         // if we found a host, then we've got a network path, so we're done
  470.         if (fHost == 0)
  471.         {
  472.             fMemoryManager->deallocate(fUserInfo);//delete [] fUserInfo;
  473.             fUserInfo = XMLString::replicate(baseURI->getUserInfo(), fMemoryManager);
  474.             fHost = XMLString::replicate(baseURI->getHost(), fMemoryManager);
  475.             fPort = baseURI->getPort();
  476.         }
  477.         else
  478.         {
  479.             return;
  480.         }
  481.         // check for absolute path - RFC 2396 5.2 #5
  482.         if ((fPath && *fPath) &&
  483.             XMLString::startsWith(fPath, SINGLE_SLASH))
  484.         {
  485.             return;
  486.         }
  487.         // if we get to this point, we need to resolve relative path
  488.         // RFC 2396 5.2 #6
  489.         XMLCh* basePath = XMLString::replicate(baseURI->getPath(), fMemoryManager);
  490.         ArrayJanitor<XMLCh> basePathName(basePath, fMemoryManager);
  491.         int bufLen = trimedUriSpecLen+XMLString::stringLen(fPath)+XMLString::stringLen(basePath)+1;
  492.         XMLCh* path = (XMLCh*) fMemoryManager->allocate(bufLen * sizeof(XMLCh));//new XMLCh[bufLen];
  493.         ArrayJanitor<XMLCh> pathName(path, fMemoryManager);
  494.         path[0] = 0;
  495.         XMLCh* tmp1 = (XMLCh*) fMemoryManager->allocate(bufLen * sizeof(XMLCh));//new XMLCh[bufLen];
  496.         ArrayJanitor<XMLCh> tmp1Name(tmp1, fMemoryManager);
  497.         XMLCh* tmp2 = (XMLCh*) fMemoryManager->allocate(bufLen * sizeof(XMLCh));//new XMLCh[bufLen];
  498.         ArrayJanitor<XMLCh> tmp2Name(tmp2, fMemoryManager);
  499.         // 6a - get all but the last segment of the base URI path
  500.         if (basePath)
  501.         {
  502.             int lastSlash = XMLString::lastIndexOf(basePath, chForwardSlash);
  503.             if (lastSlash != -1)
  504.             {
  505.                 XMLString::subString(path, basePath, 0, lastSlash+1);
  506.             }
  507.         }
  508.         // 6b - append the relative URI path
  509.         XMLString::catString(path, fPath);
  510.         // 6c - remove all "./" where "." is a complete path segment
  511.         index = -1;
  512.         while ((index = XMLString::patternMatch(path, SLASH_DOT_SLASH)) != -1)
  513.         {
  514.             XMLString::subString(tmp1, path, 0, index);
  515.             XMLString::subString(tmp2, path, index+2, XMLString::stringLen(path));
  516.             path[0] = 0;
  517.             XMLString::catString(path, tmp1);
  518.             XMLString::catString(path, tmp2);
  519.         }
  520.         // 6d - remove "." if path ends with "." as a complete path segment
  521.         if (XMLString::endsWith(path, SLASH_DOT))
  522.         {
  523.             path[XMLString::stringLen(path) - 1] = chNull;
  524.         }
  525.         // 6e - remove all "<segment>/../" where "<segment>" is a complete
  526.         // path segment not equal to ".."
  527.         index = -1;
  528.         int segIndex = -1;
  529. int offset = 1;
  530.         while ((index = XMLString::patternMatch(&(path[offset]), SLASH_DOTDOT_SLASH)) != -1)
  531.         {
  532. // Undo offset
  533. index += offset;
  534. // Find start of <segment> within substring ending at found point.
  535. XMLString::subString(tmp1, path, 0, index-1);
  536. segIndex = XMLString::lastIndexOf(tmp1, chForwardSlash);
  537. // Ensure <segment> exists and != ".."
  538.             if (segIndex != -1                &&
  539.                 (path[segIndex+1] != chPeriod ||
  540.                  path[segIndex+2] != chPeriod ||
  541.  segIndex + 3 != index))
  542.             {
  543.                 XMLString::subString(tmp1, path, 0, segIndex);
  544.                 XMLString::subString(tmp2, path, index+3, XMLString::stringLen(path));
  545.                 path[0] = 0;
  546.                 XMLString::catString(path, tmp1);
  547.                 XMLString::catString(path, tmp2);
  548.                 offset = (segIndex == 0 ? 1 : segIndex);
  549.             }
  550.             else
  551.             {
  552.                 offset += 4;
  553.             }
  554.         }// while
  555.         // 6f - remove ending "<segment>/.." where "<segment>" is a
  556.         // complete path segment
  557.         if (XMLString::endsWith(path, SLASH_DOTDOT))
  558.         {
  559. // Find start of <segment> within substring ending at found point.
  560.             index = XMLString::stringLen(path) - 3;
  561. XMLString::subString(tmp1, path, 0, index-1);
  562. segIndex = XMLString::lastIndexOf(tmp1, chForwardSlash);
  563.             if (segIndex != -1                &&
  564.                 (path[segIndex+1] != chPeriod ||
  565.                  path[segIndex+2] != chPeriod ||
  566.  segIndex + 3 != index))
  567.             {
  568.                 path[segIndex+1] = chNull;
  569.             }
  570.         }
  571.         if (getPath())
  572.             fMemoryManager->deallocate(fPath);//delete [] fPath;
  573.         fPath = XMLString::replicate(path, fMemoryManager);
  574.     }
  575. }
  576. // ---------------------------------------------------------------------------
  577. //  Components initialization
  578. // ---------------------------------------------------------------------------
  579. //
  580. // authority     = server | reg_name
  581. // server        = [ [ userinfo "@" ] hostport ]
  582. // hostport      = host [ ":" port ]
  583. //
  584. // reg_name      = 1*( unreserved | escaped | "$" | "," |
  585. //                    ";" | ":" | "@" | "&" | "=" | "+" )
  586. //
  587. // userinfo      = *( unreserved | escaped |
  588. //                 ";" | ":" | "&" | "=" | "+" | "$" | "," )
  589. //
  590. void XMLUri::initializeAuthority(const XMLCh* const uriSpec)
  591. {
  592.     int index = 0;
  593. int start = 0;
  594.     const int end = XMLString::stringLen(uriSpec);
  595.     //
  596.     // server = [ [ userinfo "@" ] hostport ]
  597. // userinfo is everything up @,
  598.     //
  599.     XMLCh* userinfo = (XMLCh*) fMemoryManager->allocate
  600.     (
  601.         (end+1) * sizeof(XMLCh)
  602.     );//new XMLCh[end+1];
  603.     ArrayJanitor<XMLCh> userName(userinfo, fMemoryManager);
  604.     index = XMLString::indexOf(&(uriSpec[start]), chAt);
  605.     if ( index != -1)
  606.     {
  607.         XMLString::subString(userinfo, &(uriSpec[start]), 0, index);
  608.         index++; // skip the @
  609. start += index;
  610.     }
  611.     else
  612.     {
  613.         XMLString::copyString(userinfo, XMLUni::fgZeroLenString);
  614.     }
  615.     //
  616.     // hostport = host [ ":" port ]
  617. // host is everything up to ':'
  618.     //
  619. XMLCh* host = (XMLCh*) fMemoryManager->allocate
  620.     (
  621.         (end+1) * sizeof(XMLCh)
  622.     );//new XMLCh[end+1];
  623.     ArrayJanitor<XMLCh> hostName(host, fMemoryManager);
  624.     index = XMLString::indexOf(&(uriSpec[start]), chColon);
  625.     if ( index != -1)
  626.     {
  627.         XMLString::subString(host, &(uriSpec[start]), 0, index);
  628.         index++;  // skip the :
  629. start +=index;
  630.     }
  631.     else
  632.     {
  633.         XMLString::subString(host, &(uriSpec[start]), 0, end-start);
  634. start=end;
  635.     }
  636.     // port is everything after ":"
  637.     XMLCh* portStr = (XMLCh*) fMemoryManager->allocate
  638.     (
  639.         (end+1) * sizeof(XMLCh)
  640.     );//new XMLCh[end+1];
  641.     ArrayJanitor<XMLCh> portName(portStr, fMemoryManager);
  642.     int port = -1;
  643.     if ((host && *host) &&   // non empty host
  644.         (index != -1)                    &&   // ":" found
  645.         (start < end)                     )   // ":" is not the last
  646.     {
  647.         XMLString::subString(portStr, &(uriSpec[start]), 0, end-start);
  648.         if (portStr && *portStr)
  649.         {
  650.             try
  651.             {
  652.                 port = XMLString::parseInt(portStr);
  653.             }
  654.             catch (...)
  655.             {
  656.                 throw;
  657.             }
  658.         }
  659.     } // if > 0
  660.     // The order is important, do not change
  661.     //
  662.     setHost(host);
  663.     setPort(port);
  664. setUserInfo(userinfo);
  665. }
  666. // scheme = alpha *( alpha | digit | "+" | "-" | "." )
  667. void XMLUri::initializeScheme(const XMLCh* const uriSpec)
  668. {
  669.     const XMLCh* tmpPtr = XMLString::findAny(uriSpec, SCHEME_SEPARATORS);
  670.     if ( !tmpPtr )
  671.     {
  672.         ThrowXML(MalformedURLException, XMLExcepts::XMLNUM_URI_No_Scheme);
  673.     }
  674. else
  675.     {
  676.         XMLCh* scheme = (XMLCh*) fMemoryManager->allocate
  677.         (
  678.             (XMLString::stringLen(uriSpec) + 1) * sizeof(XMLCh)
  679.         );//new XMLCh[XMLString::stringLen(uriSpec)+1];
  680.         ArrayJanitor<XMLCh> tmpName(scheme, fMemoryManager);
  681.         XMLString::subString(scheme, uriSpec, 0, (tmpPtr - uriSpec));
  682.         setScheme(scheme);
  683. }
  684. }
  685. void XMLUri::initializePath(const XMLCh* const uriSpec)
  686. {
  687. if ( !uriSpec )
  688.     {
  689.         ThrowXML1(MalformedURLException
  690.                 , XMLExcepts::XMLNUM_URI_Component_Empty
  691.                 , errMsg_PATH);
  692. }
  693. int index = 0;
  694. int start = 0;
  695.     int end = XMLString::stringLen(uriSpec);
  696. XMLCh testChar;
  697. // path - everything up to query string or fragment
  698. while (index < end)
  699.     {
  700.         testChar = uriSpec[index];
  701.         if (testChar == chQuestion || testChar == chPound)
  702.         {
  703.             break;
  704.         }
  705.         // check for valid escape sequence
  706.         if (testChar == chPercent)
  707.         {
  708.             if (index+2 >= end ||
  709.                 !XMLString::isHex(uriSpec[index+1]) ||
  710.                 !XMLString::isHex(uriSpec[index+2]))
  711.             {
  712.                 XMLString::moveChars(value1, &(uriSpec[index]), 3);
  713.                 value1[3] = chNull;
  714.                 ThrowXML2(MalformedURLException
  715.                         , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence
  716.                         , errMsg_PATH
  717.                         , value1);
  718.             }
  719.         }
  720.         else if (!isReservedCharacter(testChar) &&
  721.                  !isUnreservedCharacter(testChar))
  722.         {
  723.             value1[0] = testChar;
  724.             value1[1] = chNull;
  725.             ThrowXML2(MalformedURLException
  726.                     , XMLExcepts::XMLNUM_URI_Component_Invalid_Char
  727.                     , errMsg_PATH
  728.                     , value1);
  729.         }
  730.         index++;
  731.     }//while (index < end)
  732.     if (getPath())
  733.     {
  734.         fMemoryManager->deallocate(fPath);//delete [] fPath;
  735.     }
  736.     fPath = (XMLCh*) fMemoryManager->allocate((index+1) * sizeof(XMLCh));//new XMLCh[index+1];
  737.     XMLString::subString(fPath, uriSpec, start, index);
  738. // query - starts with ? and up to fragment or end
  739. if (testChar == chQuestion)
  740.     {
  741.         index++;
  742.         start = index;
  743.         while (index < end)
  744.         {
  745.             testChar = uriSpec[index];
  746.             if (testChar == chPound)
  747.             {
  748.                 break;
  749.             }
  750.             if (testChar == chPercent)
  751.             {
  752.                 if (index+2 >= end ||
  753.                     !XMLString::isHex(uriSpec[index+1]) ||
  754.                     !XMLString::isHex(uriSpec[index+2]))
  755.                 {
  756.                     XMLString::moveChars(value1, &(uriSpec[index]), 3);
  757.                     value1[3] = chNull;
  758.                     ThrowXML2(MalformedURLException
  759.                             , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence
  760.                             , errMsg_QUERY
  761.                             , value1);
  762.                 }
  763.             }
  764.             else if (!isReservedCharacter(testChar) &&
  765.                      !isUnreservedCharacter(testChar))
  766.             {
  767.                 value1[0] = testChar;
  768.                 value1[1] = chNull;
  769.                 ThrowXML2(MalformedURLException
  770.                         , XMLExcepts::XMLNUM_URI_Component_Invalid_Char
  771.                         , errMsg_QUERY
  772.                         , value1);
  773.             }
  774.             index++;
  775.         }
  776.         if (getQueryString())
  777.         {
  778.             fMemoryManager->deallocate(fQueryString);//delete [] fQueryString;
  779.         }
  780.         fQueryString = (XMLCh*) fMemoryManager->allocate
  781.         (
  782.             (index - start + 1) * sizeof(XMLCh)
  783.         );//new XMLCh[index - start + 1];
  784.         XMLString::subString(fQueryString, uriSpec, start, index);
  785.     }
  786. // fragment - starts with #
  787. if (testChar == chPound)
  788.     {
  789.         index++;
  790.         start = index;
  791.         while (index < end)
  792.         {
  793.             testChar = uriSpec[index];
  794.             if (testChar == chPercent)
  795.             {
  796.                 if (index+2 >= end ||
  797.                     !XMLString::isHex(uriSpec[index+1]) ||
  798.                     !XMLString::isHex(uriSpec[index+2]))
  799.                 {
  800.                     XMLString::moveChars(value1, &(uriSpec[index]), 3);
  801.                     value1[3] = chNull;
  802.                     ThrowXML2(MalformedURLException
  803.                             , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence
  804.                             , errMsg_FRAGMENT
  805.                             , value1);
  806.                 }
  807.             }
  808.             else if (!isReservedCharacter(testChar) &&
  809.                      !isUnreservedCharacter(testChar))
  810.             {
  811.                 value1[0] = testChar;
  812.                 value1[1] = chNull;
  813.                 ThrowXML2(MalformedURLException
  814.                         , XMLExcepts::XMLNUM_URI_Component_Invalid_Char
  815.                         , errMsg_FRAGMENT
  816.                         , value1);
  817.             }
  818.             index++;
  819.         }
  820.         if (getFragment())
  821.             fMemoryManager->deallocate(fFragment);//delete [] fFragment;
  822.         //make sure that there is something following the '#'
  823.         if (index > start)
  824.         {
  825.             fFragment = (XMLCh*) fMemoryManager->allocate
  826.             (
  827.                 (index - start + 1) * sizeof(XMLCh)
  828.             );//new XMLCh[index - start + 1];
  829.             XMLString::subString(fFragment, uriSpec, start, index);
  830.         }
  831.         else
  832.         {
  833.             // RFC 2396, 4.0. URI Reference
  834.             // URI-reference = [absoulteURI | relativeURI] [# fragment]
  835.             //
  836.             // RFC 2396, 4.1. Fragment Identifier
  837.             // fragment = *uric
  838.             //
  839.             // empty fragment is valid
  840.             fFragment = 0;
  841.         }
  842.     }
  843. }
  844. // ---------------------------------------------------------------------------
  845. //  Setter
  846. // ---------------------------------------------------------------------------
  847. void XMLUri::setScheme(const XMLCh* const newScheme)
  848. {
  849.     if ( !newScheme )
  850.     {
  851.         ThrowXML1(MalformedURLException
  852.                 , XMLExcepts::XMLNUM_URI_Component_Set_Null
  853.                 , errMsg_SCHEME);
  854.     }
  855.     if (!isConformantSchemeName(newScheme))
  856.     {
  857.         ThrowXML2(MalformedURLException
  858.                 , XMLExcepts::XMLNUM_URI_Component_Not_Conformant
  859.                 , errMsg_SCHEME
  860.                 , newScheme);
  861.     }
  862.     if (getScheme())
  863.     {
  864.         fMemoryManager->deallocate(fScheme);//delete [] fScheme;
  865.     }
  866.     fScheme = XMLString::replicate(newScheme, fMemoryManager);
  867.     XMLString::lowerCase(fScheme);
  868. }
  869. //
  870. // server = [ [ userinfo "@" ] hostport ]
  871. // hostport = host [":" port]
  872. //
  873. // setUserInfo(), setHost() and setPort() are closely related
  874. // three methods, in a word, userinfo and port has dependency
  875. // on host.
  876. //
  877. // if host is not present, userinfo must be null and port = -1
  878. //
  879. void XMLUri::setUserInfo(const XMLCh* const newUserInfo)
  880. {
  881.     if ( newUserInfo &&
  882.          !getHost()    )
  883.     {
  884.         ThrowXML2(MalformedURLException
  885.                 , XMLExcepts::XMLNUM_URI_NullHost
  886.                 , errMsg_USERINFO
  887.                 , newUserInfo);
  888.     }
  889.     try
  890.     {
  891.         isConformantUserInfo(newUserInfo);
  892.     }
  893.     catch (...)
  894.     {
  895.         throw;
  896.     }
  897.     if (getUserInfo())
  898.     {
  899.         fMemoryManager->deallocate(fUserInfo);//delete [] fUserInfo;
  900.     }
  901.     //sometimes we get passed a empty string rather than a null.
  902.     //Other procedures rely on it being null
  903.     if(newUserInfo && *newUserInfo) {
  904.         fUserInfo = XMLString::replicate(newUserInfo, fMemoryManager);
  905.     }
  906. }
  907. void XMLUri::setHost(const XMLCh* const newHost)
  908. {
  909.     if ( !newHost ||
  910.         XMLString::isAllWhiteSpace(newHost))
  911.     {
  912.         if (getHost())
  913.             fMemoryManager->deallocate(fHost);//delete [] fHost;
  914.         fHost = 0;
  915.         setUserInfo(0);
  916.         setPort(-1);
  917.         return;
  918.     }
  919.     if (!isWellFormedAddress(newHost))
  920.     {
  921.         ThrowXML2(MalformedURLException
  922.                 , XMLExcepts::XMLNUM_URI_Component_Not_Conformant
  923.                 , errMsg_HOST
  924.                 , newHost);
  925.     }
  926.     if (getHost())
  927.     {
  928.         fMemoryManager->deallocate(fHost);//delete [] fHost;
  929.     }
  930.     fHost = XMLString::replicate(newHost, fMemoryManager);
  931. }
  932. void XMLUri::setPort(int newPort)
  933. {
  934.     if (newPort >= 0 && newPort <= 65535)
  935.     {
  936.         if (!getHost())
  937.         {
  938.             XMLString::binToText(newPort, value1, BUF_LEN, 10);
  939.             ThrowXML2(MalformedURLException
  940.                     , XMLExcepts::XMLNUM_URI_NullHost
  941.                     , errMsg_PORT
  942.                     , value1);
  943.         }
  944.     }
  945.     else if (newPort != -1)
  946.     {
  947.         XMLString::binToText(newPort, value1, BUF_LEN, 10);
  948.         ThrowXML1(MalformedURLException
  949.                 , XMLExcepts::XMLNUM_URI_PortNo_Invalid
  950.                 , value1);
  951.     }
  952.     fPort = newPort;
  953. }
  954. //
  955. // setPath(), setQueryString() and setFragment() are closely
  956. // related three methods as well.
  957. //
  958. void XMLUri::setPath(const XMLCh* const newPath)
  959. {
  960.     if (!newPath)
  961.     {
  962.         if (getPath())
  963.             fMemoryManager->deallocate(fPath);//delete [] fPath;
  964.         fPath = 0;
  965.         setQueryString(0);
  966.         setFragment(0);
  967.     }
  968.     else
  969.     {
  970.       initializePath(newPath);
  971.     }
  972.   }
  973. //
  974. // fragment = *uric
  975. //
  976. void XMLUri::setFragment(const XMLCh* const newFragment)
  977. {
  978. if ( !newFragment )
  979.     {
  980.         if (getFragment())
  981.             fMemoryManager->deallocate(fFragment);//delete [] fFragment;
  982.         fFragment = 0;
  983. }
  984. else if (!isGenericURI())
  985.     {
  986.         ThrowXML2(MalformedURLException
  987.                 , XMLExcepts::XMLNUM_URI_Component_for_GenURI_Only
  988.                 , errMsg_FRAGMENT
  989.                 , newFragment);
  990. }
  991. else if ( !getPath() )
  992.     {
  993.         ThrowXML2(MalformedURLException
  994.                , XMLExcepts::XMLNUM_URI_NullPath
  995.                , errMsg_FRAGMENT
  996.                , newFragment);
  997. }
  998. else if (!isURIString(newFragment))
  999.     {
  1000.         ThrowXML1(MalformedURLException
  1001.                 , XMLExcepts::XMLNUM_URI_Component_Invalid_Char
  1002.                 , errMsg_FRAGMENT);
  1003. }
  1004. else
  1005.     {
  1006.         if (getFragment())
  1007.         {
  1008.             fMemoryManager->deallocate(fFragment);//delete [] fFragment;
  1009.         }
  1010.         fFragment = XMLString::replicate(newFragment, fMemoryManager);
  1011. }
  1012. }
  1013. //
  1014. // query = *uric
  1015. //
  1016. void XMLUri::setQueryString(const XMLCh* const newQueryString)
  1017. {
  1018. if ( !newQueryString )
  1019.     {
  1020.         if (getQueryString())
  1021.             fMemoryManager->deallocate(fQueryString);//delete [] fQueryString;
  1022.         fQueryString = 0;
  1023. }
  1024. else if (!isGenericURI())
  1025.     {
  1026.         ThrowXML2(MalformedURLException
  1027.                 , XMLExcepts::XMLNUM_URI_Component_for_GenURI_Only
  1028.                 , errMsg_QUERY
  1029.                 , newQueryString);
  1030. }
  1031. else if ( !getPath() )
  1032.     {
  1033.         ThrowXML2(MalformedURLException
  1034.                 , XMLExcepts::XMLNUM_URI_NullPath
  1035.                 , errMsg_QUERY
  1036.                 , newQueryString);
  1037. }
  1038. else if (!isURIString(newQueryString))
  1039.     {
  1040.         ThrowXML2(MalformedURLException
  1041.                , XMLExcepts::XMLNUM_URI_Component_Invalid_Char
  1042.                , errMsg_QUERY
  1043.                , newQueryString);
  1044. }
  1045. else
  1046.     {
  1047.         if (getQueryString())
  1048.         {
  1049.             fMemoryManager->deallocate(fQueryString);//delete [] fQueryString;
  1050.         }
  1051.         fQueryString = XMLString::replicate(newQueryString, fMemoryManager);
  1052. }
  1053. }
  1054. // ---------------------------------------------------------------------------
  1055. //  XMLUri: Public, static methods
  1056. // ---------------------------------------------------------------------------
  1057. //
  1058. //  scheme = alpha *( alpha | digit | "+" | "-" | "." )
  1059. //  alphanum = alpha | digit
  1060. //
  1061. bool XMLUri::isConformantSchemeName(const XMLCh* const scheme)
  1062. {
  1063. if ( !scheme )
  1064.         return false;
  1065.     const XMLCh* tmpStr = scheme;
  1066.     if (!XMLString::isAlpha(*tmpStr))     // first: alpha
  1067.         return false;
  1068.     // second onwards: ( alpha | digit | "+" | "-" | "." )
  1069.     tmpStr++;
  1070.     while (*tmpStr)
  1071.     {
  1072.         if ( !XMLString::isAlphaNum(*tmpStr) &&
  1073.              (XMLString::indexOf(SCHEME_CHARACTERS, *tmpStr) == -1))
  1074.             return false;
  1075.         tmpStr++;
  1076.     }
  1077.     return true;
  1078. }
  1079. //
  1080. // userinfo = *( unreserved | escaped |
  1081. //              ";" | ":" | "&" | "=" | "+" | "$" | "," )
  1082. //
  1083. void XMLUri::isConformantUserInfo(const XMLCh* const userInfo)
  1084. {
  1085. if ( !userInfo )
  1086.         return;
  1087.     const XMLCh* tmpStr = userInfo;
  1088.     while (*tmpStr)
  1089.     {
  1090.         if ( isUnreservedCharacter(*tmpStr) ||
  1091.             (XMLString::indexOf(USERINFO_CHARACTERS, *tmpStr) != -1))
  1092.         {
  1093.             tmpStr++;
  1094.         }
  1095.         else if (*tmpStr == chPercent)               // '%'
  1096.         {
  1097.             if (XMLString::isHex(*(tmpStr+1)) &&     // 1st hex
  1098.                 XMLString::isHex(*(tmpStr+2))  )     // 2nd hex
  1099.             {
  1100.                 tmpStr+=3;
  1101.             }
  1102.             else
  1103.             {
  1104.                 value1[0] = chPercent;
  1105.                 value1[1] = *(tmpStr+1);
  1106.                 value1[2] = *(tmpStr+2);
  1107.                 value1[3] = chNull;
  1108.                 ThrowXML2(MalformedURLException
  1109.                         , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence
  1110.                         , errMsg_USERINFO
  1111.                         , value1);
  1112.             }
  1113.         }
  1114.         else
  1115.         {
  1116.             ThrowXML2(MalformedURLException
  1117.                     , XMLExcepts::XMLNUM_URI_Component_Invalid_Char
  1118.                     , errMsg_USERINFO
  1119.                     , userInfo);
  1120.         }
  1121.     } //while
  1122.     return;
  1123. }
  1124. //
  1125. // uric     = reserved | unreserved | escaped
  1126. // escaped  = "%" hex hex
  1127. // hex      = digit | "A" | "B" | "C" | "D" | "E" | "F" |
  1128. //                    "a" | "b" | "c" | "d" | "e" | "f"
  1129. //
  1130. bool XMLUri::isURIString(const XMLCh* const uricString)
  1131. {
  1132. if (!uricString || !*uricString)
  1133.         return false;
  1134.     const XMLCh* tmpStr = uricString;
  1135.     while (*tmpStr)
  1136.     {
  1137.         if (isReservedCharacter(*tmpStr)    ||
  1138.             isUnreservedCharacter(*tmpStr)   )
  1139.         {
  1140.             tmpStr++;
  1141.         }
  1142.         else if (*tmpStr == chPercent)               // '%'
  1143.         {
  1144.             if (XMLString::isHex(*(tmpStr+1)) &&     // 1st hex
  1145.                 XMLString::isHex(*(tmpStr+2))  )     // 2nd hex
  1146.             {
  1147.                 tmpStr+=3;
  1148.             }
  1149.             else
  1150.             {
  1151.                 return false;
  1152.             }
  1153.         }
  1154.         else
  1155.         {
  1156.             return false;
  1157.         }
  1158.     }
  1159.     return true;
  1160. }
  1161. //
  1162. //  host          = hostname | IPv4address
  1163. //
  1164. //  hostname      = *( domainlabel "." ) toplabel [ "." ]
  1165. //  domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
  1166. //  toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
  1167. //
  1168. //  IPv4address   = 1*digit "." 1*digit "." 1*digit "." 1*digit
  1169. //
  1170. bool XMLUri::isWellFormedAddress(const XMLCh* const addrString)
  1171. {
  1172. if (!addrString)
  1173.         return false;
  1174.     //
  1175.     // check length
  1176.     //
  1177.     XMLCh* tmpAddr = XMLString::replicate(addrString, XMLPlatformUtils::fgMemoryManager);
  1178.     ArrayJanitor<XMLCh>  janName(tmpAddr, XMLPlatformUtils::fgMemoryManager);
  1179.     XMLString::trim(tmpAddr);
  1180.     if ((!tmpAddr || !*tmpAddr) ||
  1181.         (XMLString::stringLen(tmpAddr) > 255) )
  1182.         return false;
  1183.     //
  1184.     // the frist letter shall NOT be "." or "-"
  1185.     //
  1186. if (*addrString == chPeriod ||
  1187.         *addrString == chDash    )
  1188.         return false;
  1189. // rightmost domain label starting with digit indicates IP address
  1190. // since top level domain label can only start with an alpha
  1191. // see RFC 2396 Section 3.2.2
  1192.     int addrStrLen = XMLString::stringLen(addrString);
  1193.     int lastPeriodPos = XMLString::lastIndexOf(addrString, chPeriod);
  1194.     // if the string ends with "."
  1195.     // get the second last "."
  1196.     if (lastPeriodPos + 1 == addrStrLen)
  1197.     {
  1198.         XMLCh* tmp2 = (XMLCh*) XMLPlatformUtils::fgMemoryManager->allocate
  1199.         (
  1200.             addrStrLen * sizeof(XMLCh)
  1201.         );//new XMLCh[addrStrLen];
  1202.         XMLString::subString(tmp2, addrString, 0, lastPeriodPos);
  1203.         lastPeriodPos = XMLString::lastIndexOf(tmp2, chPeriod);
  1204.         XMLPlatformUtils::fgMemoryManager->deallocate(tmp2);//delete [] tmp2;
  1205.         if ( XMLString::isDigit(addrString[lastPeriodPos + 1]))
  1206. return false;
  1207.     }
  1208. if (XMLString::isDigit(addrString[lastPeriodPos + 1]))
  1209.     {
  1210.         //
  1211.         // IPv4address   = 1*digit "." 1*digit "." 1*digit "." 1*digit
  1212.         //
  1213.         // make sure that
  1214.         // 1) we see only digits and dot separators,
  1215.         // 2) that any dot separator is preceded and followed by a digit
  1216.         // 3) that we find 3 dots
  1217.         int numDots = 0;
  1218.         for (int i = 0; i < addrStrLen; i++)
  1219.         {
  1220.             if (addrString[i] == chPeriod)
  1221.             {
  1222.                 if (((i > 0)  &&
  1223.                     (!XMLString::isDigit(addrString[i-1]))) ||
  1224.                     ((i + 1 < addrStrLen) &&
  1225.                     (!XMLString::isDigit(addrString[i+1])))  )
  1226.                 {
  1227.                     return false;
  1228.                 }
  1229.                 numDots++;
  1230.             }
  1231.             else if (!XMLString::isDigit(addrString[i]))
  1232.             {
  1233.                 return false;
  1234.             }
  1235.         } //for
  1236.         if (numDots != 3)
  1237.         {
  1238.             return false;
  1239.         }
  1240.     } // end of IPv4address
  1241. else
  1242.     {
  1243.         //
  1244.         //  hostname      = *( domainlabel "." ) toplabel [ "." ]
  1245.         //  domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
  1246.         //  toplabel      = alpha | alpha *( alphanum | "-" ) alphanum
  1247.         //
  1248.         // domain labels can contain alphanumerics and '-"
  1249.         // but must start and end with an alphanumeric
  1250.         for (int i = 0; i < addrStrLen; i++)
  1251.         {
  1252.             if (addrString[i] == chPeriod)
  1253.             {
  1254.               if (((i > 0)  &&
  1255.                    (!XMLString::isAlphaNum(addrString[i-1]))) ||
  1256.                   ((i + 1 < addrStrLen) &&
  1257.                    (!XMLString::isAlphaNum(addrString[i+1])))  )
  1258.                 {
  1259.                     return false;
  1260.                 }
  1261.             }
  1262.             else if (!XMLString::isAlphaNum(addrString[i]) &&
  1263.                       addrString[i] != chDash)
  1264.             {
  1265.                 return false;
  1266.             }
  1267.         } //for
  1268.     }
  1269.     return true;
  1270. }
  1271. bool XMLUri::isGenericURI()
  1272. {
  1273.     return (getHost() != 0);
  1274. }
  1275. //
  1276. //  This method will take the broken out parts of the URI and build up the
  1277. //  full text. We don't do this unless someone asks us to, since its often
  1278. //  never required.
  1279. //
  1280. void XMLUri::buildFullText()
  1281. {
  1282.     // Calculate the worst case size of the buffer required
  1283.     unsigned int bufSize = XMLString::stringLen(fScheme) + 1
  1284.                            + XMLString::stringLen(fFragment) + 1
  1285.                            + XMLString::stringLen(fHost) + 2
  1286.                            + XMLString::stringLen(fPath)
  1287.                            + XMLString::stringLen(fQueryString) + 1
  1288.                            + XMLString::stringLen(fUserInfo) + 1
  1289.                            + 32;
  1290.     // Clean up the existing buffer and allocate another
  1291.     fMemoryManager->deallocate(fURIText);//delete [] fURIText;
  1292.     fURIText = (XMLCh*) fMemoryManager->allocate(bufSize * sizeof(XMLCh));//new XMLCh[bufSize];
  1293.     *fURIText = 0;
  1294.     XMLCh* outPtr = fURIText;
  1295.     if (fScheme != 0)
  1296.     {
  1297.         XMLString::catString(fURIText, getScheme());
  1298.         outPtr += XMLString::stringLen(fURIText);
  1299.         *outPtr++ = chColon;
  1300.         *outPtr++ = chForwardSlash;
  1301.         *outPtr++ = chForwardSlash;
  1302.     }
  1303.     if (fUserInfo)
  1304.     {
  1305.         XMLString::copyString(outPtr, fUserInfo);
  1306.         outPtr += XMLString::stringLen(fUserInfo);
  1307.         /*REVISIT dont have password field in uri - is this right??
  1308.         if (fPassword)
  1309.         {
  1310.             *outPtr++ = chColon;
  1311.             XMLString::copyString(outPtr, fPassword);
  1312.             outPtr += XMLString::stringLen(fPassword);
  1313.         }
  1314.         */
  1315.         *outPtr++ = chAt;
  1316.     }
  1317.     if (fHost)
  1318.     {
  1319.         XMLString::copyString(outPtr, fHost);
  1320.         outPtr += XMLString::stringLen(fHost);
  1321.         //
  1322.         //  If the port is -1, then we don't put it in. Else we need
  1323.         //  to because it was explicitly provided.
  1324.         //
  1325.         if (fPort != -1)
  1326.         {
  1327.             *outPtr++ = chColon;
  1328.             XMLCh tmpBuf[16];
  1329.             XMLString::binToText(fPort, tmpBuf, 16, 10);
  1330.             XMLString::copyString(outPtr, tmpBuf);
  1331.             outPtr += XMLString::stringLen(tmpBuf);
  1332.         }
  1333.     }
  1334.     if (fPath)
  1335.     {
  1336.         XMLString::copyString(outPtr, fPath);
  1337.         outPtr += XMLString::stringLen(fPath);
  1338.     }
  1339.     if (fQueryString)
  1340.     {
  1341.         *outPtr++ = chQuestion;
  1342.         XMLString::copyString(outPtr, fQueryString);
  1343.         outPtr += XMLString::stringLen(fQueryString);
  1344.     }
  1345.     if (fFragment)
  1346.     {
  1347.         *outPtr++ = chPound;
  1348.         XMLString::copyString(outPtr, fFragment);
  1349.         outPtr += XMLString::stringLen(fFragment);
  1350.     }
  1351.     // Cap it off in case the last op was not a string copy
  1352.     *outPtr = 0;
  1353. }
  1354. XERCES_CPP_NAMESPACE_END