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

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-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: XMLURL.cpp,v 1.7 2003/05/16 06:01:53 knoaman Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/util/BinFileInputStream.hpp>
  63. #include <xercesc/util/Janitor.hpp>
  64. #include <xercesc/util/PlatformUtils.hpp>
  65. #include <xercesc/util/RuntimeException.hpp>
  66. #include <xercesc/util/TransService.hpp>
  67. #include <xercesc/util/XMLURL.hpp>
  68. #include <xercesc/util/XMLNetAccessor.hpp>
  69. #include <xercesc/util/XMLString.hpp>
  70. #include <xercesc/util/XMLUniDefs.hpp>
  71. #include <xercesc/util/XMLUni.hpp>
  72. #include <xercesc/util/XMLUri.hpp>
  73. XERCES_CPP_NAMESPACE_BEGIN
  74. // ---------------------------------------------------------------------------
  75. //  Local types
  76. //
  77. //  TypeEntry
  78. //      This structure defines a single entry in the list of URL types. Each
  79. //      entry indicates the prefix for that type of URL, and the SourceTypes
  80. //      value it maps to.
  81. // ---------------------------------------------------------------------------
  82. struct ProtoEntry
  83. {
  84.     XMLURL::Protocols   protocol;
  85.     const XMLCh*        prefix;
  86.     unsigned int        defPort;
  87. };
  88. // ---------------------------------------------------------------------------
  89. //  Local data
  90. //
  91. //  gXXXString
  92. //      These are the strings for our prefix types. They all have to be
  93. //      Unicode strings all the time, so we can't just do regular strings.
  94. //
  95. //  gProtoList
  96. //      The list of URL types that we support and some info related to each
  97. //      one.
  98. //
  99. //  gMaxProtoLen
  100. //      The length of the longest protocol string
  101. //
  102. //      NOTE:!!! Be sure to keep this up to date if new protocols are added!
  103. // ---------------------------------------------------------------------------
  104. static const XMLCh  gFileString[] =
  105. {
  106.         chLatin_f, chLatin_i, chLatin_l, chLatin_e, chNull
  107. };
  108. static const XMLCh gFTPString[]  =
  109. {
  110.         chLatin_f, chLatin_t, chLatin_p, chNull
  111. };
  112. static const XMLCh gHTTPString[] =
  113. {
  114.         chLatin_h, chLatin_t, chLatin_t, chLatin_p, chNull
  115. };
  116. static ProtoEntry gProtoList[XMLURL::Protocols_Count] =
  117. {
  118.         { XMLURL::File     , gFileString    , 0  }
  119.     ,   { XMLURL::HTTP     , gHTTPString    , 80 }
  120.     ,   { XMLURL::FTP      , gFTPString     , 21 }
  121. };
  122. // !!! Keep these up to date with list above!
  123. static const unsigned int gMaxProtoLen = 4;
  124. // ---------------------------------------------------------------------------
  125. //  Local methods
  126. // ---------------------------------------------------------------------------
  127. static bool isHexDigit(const XMLCh toCheck)
  128. {
  129.     if ((toCheck >= chDigit_0) && (toCheck <= chDigit_9)
  130.     ||  (toCheck >= chLatin_A) && (toCheck <= chLatin_Z)
  131.     ||  (toCheck >= chLatin_a) && (toCheck <= chLatin_z))
  132.     {
  133.         return true;
  134.     }
  135.     return false;
  136. }
  137. static unsigned int xlatHexDigit(const XMLCh toXlat)
  138. {
  139.     if ((toXlat >= chDigit_0) && (toXlat <= chDigit_9))
  140.         return (unsigned int)(toXlat - chDigit_0);
  141.     if ((toXlat >= chLatin_A) && (toXlat <= chLatin_Z))
  142.         return (unsigned int)(toXlat - chLatin_A) + 10;
  143.     return (unsigned int)(toXlat - chLatin_a) + 10;
  144. }
  145. // ---------------------------------------------------------------------------
  146. //  XMLURL: Public, static methods
  147. // ---------------------------------------------------------------------------
  148. XMLURL::Protocols XMLURL::lookupByName(const XMLCh* const protoName)
  149. {
  150.     for (unsigned int index = 0; index < XMLURL::Protocols_Count; index++)
  151.     {
  152.         if (!XMLString::compareIString(gProtoList[index].prefix, protoName))
  153.             return gProtoList[index].protocol;
  154.     }
  155.     return XMLURL::Unknown;
  156. }
  157. // ---------------------------------------------------------------------------
  158. //  XMLURL: Constructors and Destructor
  159. // ---------------------------------------------------------------------------
  160. XMLURL::XMLURL(MemoryManager* const manager) :
  161.     fMemoryManager(manager)
  162.     , fFragment(0)
  163.     , fHost(0)
  164.     , fPassword(0)
  165.     , fPath(0)
  166.     , fPortNum(0)
  167.     , fProtocol(XMLURL::Unknown)
  168.     , fQuery(0)
  169.     , fUser(0)
  170.     , fURLText(0)
  171.     , fHasInvalidChar(false)
  172. {
  173. }
  174. XMLURL::XMLURL(const XMLCh* const    baseURL
  175.              , const XMLCh* const    relativeURL
  176.              , MemoryManager* const manager) :
  177.     fMemoryManager(manager)
  178.     , fFragment(0)
  179.     , fHost(0)
  180.     , fPassword(0)
  181.     , fPath(0)
  182.     , fPortNum(0)
  183.     , fProtocol(XMLURL::Unknown)
  184.     , fQuery(0)
  185.     , fUser(0)
  186.     , fURLText(0)
  187.     , fHasInvalidChar(false)
  188. {
  189. try
  190. {
  191. setURL(baseURL, relativeURL);
  192. }
  193.     catch(...)
  194.     {
  195.         cleanup();
  196.         throw;
  197.     }
  198. }
  199. XMLURL::XMLURL(const XMLCh* const  baseURL
  200.              , const char* const   relativeURL
  201.              , MemoryManager* const manager) :
  202.     fMemoryManager(manager)
  203.     , fFragment(0)
  204.     , fHost(0)
  205.     , fPassword(0)
  206.     , fPath(0)
  207.     , fPortNum(0)
  208.     , fProtocol(XMLURL::Unknown)
  209.     , fQuery(0)
  210.     , fUser(0)
  211.     , fURLText(0)
  212.     , fHasInvalidChar(false)
  213. {
  214.     XMLCh* tmpRel = XMLString::transcode(relativeURL, fMemoryManager);
  215.     ArrayJanitor<XMLCh> janRel(tmpRel, fMemoryManager);
  216. try
  217. {
  218. setURL(baseURL, tmpRel);
  219. }
  220.     catch(...)
  221.     {
  222.         cleanup();
  223.         throw;
  224.     }
  225. }
  226. XMLURL::XMLURL(const XMLURL&         baseURL
  227.              , const XMLCh* const    relativeURL) :
  228.     fMemoryManager(baseURL.fMemoryManager)
  229.     , fFragment(0)
  230.     , fHost(0)
  231.     , fPassword(0)
  232.     , fPath(0)
  233.     , fPortNum(0)
  234.     , fProtocol(XMLURL::Unknown)
  235.     , fQuery(0)
  236.     , fUser(0)
  237.     , fURLText(0)
  238.     , fHasInvalidChar(false)
  239. {
  240. try
  241. {
  242. setURL(baseURL, relativeURL);
  243. }
  244.     catch(...)
  245.     {
  246.         cleanup();
  247.         throw;
  248.     }
  249. }
  250. XMLURL::XMLURL(const  XMLURL&        baseURL
  251.              , const char* const     relativeURL) :
  252.     fMemoryManager(baseURL.fMemoryManager)
  253.     , fFragment(0)
  254.     , fHost(0)
  255.     , fPassword(0)
  256.     , fPath(0)
  257.     , fPortNum(0)
  258.     , fProtocol(XMLURL::Unknown)
  259.     , fQuery(0)
  260.     , fUser(0)
  261.     , fURLText(0)
  262.     , fHasInvalidChar(false)
  263. {
  264.     XMLCh* tmpRel = XMLString::transcode(relativeURL, fMemoryManager);
  265.     ArrayJanitor<XMLCh> janRel(tmpRel, fMemoryManager);
  266. try
  267. {
  268. setURL(baseURL, tmpRel);
  269. }
  270.     catch(...)
  271.     {
  272.         cleanup();
  273.         throw;
  274.     }
  275. }
  276. XMLURL::XMLURL(const XMLCh* const urlText,
  277.                MemoryManager* const manager) :
  278.     fMemoryManager(manager)
  279.     , fFragment(0)
  280.     , fHost(0)
  281.     , fPassword(0)
  282.     , fPath(0)
  283.     , fPortNum(0)
  284.     , fProtocol(XMLURL::Unknown)
  285.     , fQuery(0)
  286.     , fUser(0)
  287.     , fURLText(0)
  288.     , fHasInvalidChar(false)
  289. {
  290. try
  291. {
  292.     setURL(urlText);
  293. }
  294.     catch(...)
  295.     {
  296.         cleanup();
  297.         throw;
  298.     }
  299. }
  300. XMLURL::XMLURL(const char* const urlText,
  301.                MemoryManager* const manager) :
  302.     fMemoryManager(manager)
  303.     , fFragment(0)
  304.     , fHost(0)
  305.     , fPassword(0)
  306.     , fPath(0)
  307.     , fPortNum(0)
  308.     , fProtocol(XMLURL::Unknown)
  309.     , fQuery(0)
  310.     , fUser(0)
  311.     , fURLText(0)
  312.     , fHasInvalidChar(false)
  313. {
  314.     XMLCh* tmpText = XMLString::transcode(urlText, fMemoryManager);
  315.     ArrayJanitor<XMLCh> janRel(tmpText, fMemoryManager);
  316. try
  317. {
  318.     setURL(tmpText);
  319. }
  320.     catch(...)
  321.     {
  322.         cleanup();
  323.         throw;
  324.     }
  325. }
  326. XMLURL::XMLURL(const XMLURL& toCopy) :
  327.     fMemoryManager(toCopy.fMemoryManager)
  328.     , fFragment(0)
  329.     , fHost(0)
  330.     , fPassword(0)
  331.     , fPath(0)
  332.     , fPortNum(toCopy.fPortNum)
  333.     , fProtocol(toCopy.fProtocol)
  334.     , fQuery(0)
  335.     , fUser(0)
  336.     , fURLText(0)
  337.     , fHasInvalidChar(toCopy.fHasInvalidChar)
  338. {
  339.     try
  340.     {
  341.         fFragment = XMLString::replicate(toCopy.fFragment, fMemoryManager);
  342.         fHost = XMLString::replicate(toCopy.fHost, fMemoryManager);
  343.         fPassword = XMLString::replicate(toCopy.fPassword, fMemoryManager);
  344.         fPath = XMLString::replicate(toCopy.fPath, fMemoryManager);
  345.         fQuery = XMLString::replicate(toCopy.fQuery, fMemoryManager);
  346.         fUser = XMLString::replicate(toCopy.fUser, fMemoryManager);
  347.         fURLText = XMLString::replicate(toCopy.fURLText, fMemoryManager);
  348.     }
  349.     catch(...)
  350.     {
  351.         cleanup();
  352.     }
  353. }
  354. XMLURL::~XMLURL()
  355. {
  356.     cleanup();
  357. }
  358. // ---------------------------------------------------------------------------
  359. //  XMLURL: Public operators
  360. // ---------------------------------------------------------------------------
  361. XMLURL& XMLURL::operator=(const XMLURL& toAssign)
  362. {
  363.     if (this == &toAssign)
  364.         return *this;
  365.     // Clean up our stuff
  366.     cleanup();
  367.     // And copy his stuff
  368.     fFragment = XMLString::replicate(toAssign.fFragment, fMemoryManager);
  369.     fHost = XMLString::replicate(toAssign.fHost, fMemoryManager);
  370.     fPassword = XMLString::replicate(toAssign.fPassword, fMemoryManager);
  371.     fPath = XMLString::replicate(toAssign.fPath, fMemoryManager);
  372.     fProtocol = toAssign.fProtocol;
  373.     fQuery = XMLString::replicate(toAssign.fQuery, fMemoryManager);
  374.     fUser = XMLString::replicate(toAssign.fUser, fMemoryManager);
  375.     fURLText = XMLString::replicate(toAssign.fURLText, fMemoryManager);
  376.     return *this;
  377. }
  378. bool XMLURL::operator==(const XMLURL& toCompare) const
  379. {
  380.     //
  381.     //  Compare the two complete URLs (which have been processed the same
  382.     //  way so they should now be the same even if they came in via different
  383.     //  relative parts.
  384.     //
  385.     if (!XMLString::equals(getURLText(), toCompare.getURLText()))
  386.         return false;
  387.     return true;
  388. }
  389. // ---------------------------------------------------------------------------
  390. //  XMLURL: Getter methods
  391. // ---------------------------------------------------------------------------
  392. unsigned int XMLURL::getPortNum() const
  393. {
  394.     //
  395.     //  If it was not provided explicitly, then lets return the default one
  396.     //  for the protocol.
  397.     //
  398.     if (!fPortNum)
  399.     {
  400.         if (fProtocol == Unknown)
  401.             return 0;
  402.         return gProtoList[fProtocol].defPort;
  403.     }
  404.     return fPortNum;
  405. }
  406. const XMLCh* XMLURL::getProtocolName() const
  407. {
  408.     // Check to see if its ever been set
  409.     if (fProtocol == Unknown)
  410.         ThrowXML(MalformedURLException, XMLExcepts::URL_NoProtocolPresent);
  411.     return gProtoList[fProtocol].prefix;
  412. }
  413. // ---------------------------------------------------------------------------
  414. //  XMLURL: Setter methods
  415. // ---------------------------------------------------------------------------
  416. void XMLURL::setURL(const XMLCh* const urlText)
  417. {
  418.     //
  419.     //  Try to parse the URL.
  420.     //
  421.     cleanup();
  422.     parse(urlText);
  423. }
  424. void XMLURL::setURL(const XMLCh* const    baseURL
  425.                   , const XMLCh* const    relativeURL)
  426. {
  427.     cleanup();
  428.     // Parse our URL string
  429.     parse(relativeURL);
  430. //
  431. //  If its relative and the base is non-null and non-empty, then
  432. //  parse the base URL string and conglomerate them.
  433. //
  434. if (isRelative() && baseURL)
  435. {
  436. if (*baseURL)
  437. {
  438. XMLURL basePart(baseURL, fMemoryManager);
  439. if (!conglomerateWithBase(basePart, false))
  440. {
  441. cleanup();
  442. ThrowXML(MalformedURLException, XMLExcepts::URL_RelativeBaseURL);
  443. }
  444. }
  445. }
  446. }
  447. void XMLURL::setURL(const XMLURL&         baseURL
  448.                   , const XMLCh* const    relativeURL)
  449. {
  450.     cleanup();
  451. // Parse our URL string
  452.     parse(relativeURL);
  453.     // If its relative, then conglomerate with the base URL
  454.     if (isRelative())
  455. conglomerateWithBase(baseURL);
  456. }
  457. // ---------------------------------------------------------------------------
  458. //  XMLURL: Miscellaneous methods
  459. // ---------------------------------------------------------------------------
  460. bool XMLURL::isRelative() const
  461. {
  462.     // If no protocol then relative
  463.     if (fProtocol == Unknown)
  464.         return true;
  465.     // If no path, or the path is not absolute, then relative
  466.     if (!fPath)
  467.         return true;
  468.     if (*fPath != chForwardSlash)
  469.         return true;
  470.     return false;
  471. }
  472. bool XMLURL::hasInvalidChar() const {
  473.     return fHasInvalidChar;
  474. }
  475. BinInputStream* XMLURL::makeNewStream() const
  476. {
  477.     //
  478.     //  If its a local host, then we short circuit it and use our own file
  479.     //  stream support. Otherwise, we just let it fall through and let the
  480.     //  installed network access object provide a stream.
  481.     //
  482.     if (fProtocol == XMLURL::File)
  483.     {
  484.         if (!fHost || !XMLString::compareIString(fHost, XMLUni::fgLocalHostString))
  485.         {
  486.             XMLCh* realPath = XMLString::replicate(fPath, fMemoryManager);
  487.             ArrayJanitor<XMLCh> basePathName(realPath, fMemoryManager);
  488.             //
  489.             // Need to manually replace any character reference %xx first
  490.             // HTTP protocol will be done automatically by the netaccessor
  491.             //
  492.             int end = XMLString::stringLen(realPath);
  493.             int percentIndex = XMLString::indexOf(realPath, chPercent, 0);
  494.             while (percentIndex != -1) {
  495.                 if (percentIndex+2 >= end ||
  496.                     !isHexDigit(realPath[percentIndex+1]) ||
  497.                     !isHexDigit(realPath[percentIndex+2]))
  498.                 {
  499.                     XMLCh value1[4];
  500.                     XMLString::moveChars(value1, &(realPath[percentIndex]), 3);
  501.                     value1[3] = chNull;
  502.                     ThrowXML2(MalformedURLException
  503.                             , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence
  504.                             , realPath
  505.                             , value1);
  506.                 }
  507.                 unsigned int value = (xlatHexDigit(realPath[percentIndex+1]) * 16) + xlatHexDigit(realPath[percentIndex+2]);
  508.                 realPath[percentIndex] = XMLCh(value);
  509.                 int i =0;
  510.                 for (i = percentIndex + 1; i < end - 2 ; i++)
  511.                     realPath[i] = realPath[i+2];
  512.                 realPath[i] = chNull;
  513.                 end = i;
  514.                 percentIndex = XMLString::indexOf(realPath, chPercent, percentIndex);
  515.             }
  516.             BinFileInputStream* retStrm = new (fMemoryManager) BinFileInputStream(realPath);
  517.             if (!retStrm->getIsOpen())
  518.             {
  519.                 delete retStrm;
  520.                 return 0;
  521.             }
  522.             return retStrm;
  523.         }
  524.     }
  525.     //
  526.     //  If we don't have have an installed net accessor object, then we
  527.     //  have to just throw here.
  528.     //
  529.     if (!XMLPlatformUtils::fgNetAccessor)
  530.         ThrowXML(MalformedURLException, XMLExcepts::URL_UnsupportedProto);
  531.     // Else ask the net accessor to create the stream
  532.     return XMLPlatformUtils::fgNetAccessor->makeNew(*this);
  533. }
  534. void XMLURL::makeRelativeTo(const XMLCh* const baseURLText)
  535. {
  536.     // If this one is not relative, don't bother
  537.     if (!isRelative())
  538.         return;
  539.     XMLURL baseURL(baseURLText, fMemoryManager);
  540.     conglomerateWithBase(baseURL);
  541. }
  542. void XMLURL::makeRelativeTo(const XMLURL& baseURL)
  543. {
  544.     // If this one is not relative, don't bother
  545.     if (!isRelative())
  546.         return;
  547.     conglomerateWithBase(baseURL);
  548. }
  549. // ---------------------------------------------------------------------------
  550. //  XMLURL: Private helper methods
  551. // ---------------------------------------------------------------------------
  552. //
  553. //  This method will take the broken out parts of the URL and build up the
  554. //  full text. We don't do this unless someone asks us to, since its often
  555. //  never required.
  556. //
  557. void XMLURL::buildFullText()
  558. {
  559.     // Calculate the worst case size of the buffer required
  560.     unsigned int bufSize = gMaxProtoLen + 1
  561.                            + XMLString::stringLen(fFragment) + 1
  562.                            + XMLString::stringLen(fHost) + 2
  563.                            + XMLString::stringLen(fPassword) + 1
  564.                            + XMLString::stringLen(fPath)
  565.                            + XMLString::stringLen(fQuery) + 1
  566.                            + XMLString::stringLen(fUser) + 1
  567.                            + 32;
  568.     // Clean up the existing buffer and allocate another
  569.     fMemoryManager->deallocate(fURLText);//delete [] fURLText;
  570.     fURLText = (XMLCh*) fMemoryManager->allocate((bufSize) * sizeof(XMLCh));//new XMLCh[bufSize];
  571.     *fURLText = 0;
  572.     XMLCh* outPtr = fURLText;
  573.     if (fProtocol != Unknown)
  574.     {
  575.         XMLString::catString(fURLText, getProtocolName());
  576.         outPtr += XMLString::stringLen(fURLText);
  577.         *outPtr++ = chColon;
  578.         *outPtr++ = chForwardSlash;
  579.         *outPtr++ = chForwardSlash;
  580.     }
  581.     if (fUser)
  582.     {
  583.         XMLString::copyString(outPtr, fUser);
  584.         outPtr += XMLString::stringLen(fUser);
  585.         if (fPassword)
  586.         {
  587.             *outPtr++ = chColon;
  588.             XMLString::copyString(outPtr, fPassword);
  589.             outPtr += XMLString::stringLen(fPassword);
  590.         }
  591.         *outPtr++ = chAt;
  592.     }
  593.     if (fHost)
  594.     {
  595.         XMLString::copyString(outPtr, fHost);
  596.         outPtr += XMLString::stringLen(fHost);
  597.         //
  598.         //  If the port is zero, then we don't put it in. Else we need
  599.         //  to because it was explicitly provided.
  600.         //
  601.         if (fPortNum)
  602.         {
  603.             *outPtr++ = chColon;
  604.             XMLCh tmpBuf[16];
  605.             XMLString::binToText(fPortNum, tmpBuf, 16, 10);
  606.             XMLString::copyString(outPtr, tmpBuf);
  607.             outPtr += XMLString::stringLen(tmpBuf);
  608.         }
  609.     }
  610.     if (fPath)
  611.     {
  612.         XMLString::copyString(outPtr, fPath);
  613.         outPtr += XMLString::stringLen(fPath);
  614.     }
  615.     if (fQuery)
  616.     {
  617.         *outPtr++ = chQuestion;
  618.         XMLString::copyString(outPtr, fQuery);
  619.         outPtr += XMLString::stringLen(fQuery);
  620.     }
  621.     if (fFragment)
  622.     {
  623.         *outPtr++ = chPound;
  624.         XMLString::copyString(outPtr, fFragment);
  625.         outPtr += XMLString::stringLen(fFragment);
  626.     }
  627.     // Cap it off in case the last op was not a string copy
  628.     *outPtr = 0;
  629. }
  630. //
  631. //  Just a central place to handle cleanup, since its done from a number
  632. //  of different spots.
  633. //
  634. void XMLURL::cleanup()
  635. {
  636.     fMemoryManager->deallocate(fFragment);//delete [] fFragment;
  637.     fMemoryManager->deallocate(fHost);//delete [] fHost;
  638.     fMemoryManager->deallocate(fPassword);//delete [] fPassword;
  639.     fMemoryManager->deallocate(fPath);//delete [] fPath;
  640.     fMemoryManager->deallocate(fQuery);//delete [] fQuery;
  641.     fMemoryManager->deallocate(fUser);//delete [] fUser;
  642.     fMemoryManager->deallocate(fURLText);//delete [] fURLText;
  643.     fFragment = 0;
  644.     fHost = 0;
  645.     fPassword = 0;
  646.     fPath = 0;
  647.     fQuery = 0;
  648.     fUser = 0;
  649.     fURLText = 0;
  650.     fProtocol = Unknown;
  651.     fPortNum = 0;
  652. }
  653. //This function  has been modified to take a bool parameter and the
  654. //functionality inside looks irrational but is only to make
  655. //solaris 2.7 CC 5.0 optimized build happy.
  656. bool XMLURL::conglomerateWithBase(const XMLURL& baseURL, bool useExceptions)
  657. {
  658.     // The base URL cannot be relative
  659.     if (baseURL.isRelative())
  660.     {
  661.         if (useExceptions)
  662. ThrowXML(MalformedURLException, XMLExcepts::URL_RelativeBaseURL);
  663.         else
  664.             return false;
  665.     }
  666.     //
  667.     //  Check a special case. If all we have is a fragment, then we want
  668.     //  to just take the base host and path, plus our fragment.
  669.     //
  670.     if ((fProtocol == Unknown)
  671.     &&  !fHost
  672.     &&  !fPath
  673.     &&  fFragment)
  674.     {
  675.         // Just in case, make sure we don't leak the user or password values
  676.         fMemoryManager->deallocate(fUser);//delete [] fUser;
  677.         fUser = 0;
  678.         fMemoryManager->deallocate(fPassword);//delete [] fPassword;
  679.         fPassword = 0;
  680.         // Copy over the protocol and port number as is
  681.         fProtocol = baseURL.fProtocol;
  682.         fPortNum = baseURL.fPortNum;
  683.         // Replicate the base fields that are provided
  684.         fHost = XMLString::replicate(baseURL.fHost, fMemoryManager);
  685.         fUser = XMLString::replicate(baseURL.fUser, fMemoryManager);
  686.         fPassword = XMLString::replicate(baseURL.fPassword, fMemoryManager);
  687.         fPath = XMLString::replicate(baseURL.fPath, fMemoryManager);
  688.         return true;
  689.     }
  690.     //
  691.     //  All we have to do is run up through our fields and, for each one
  692.     //  that we don't have, use the based URL's. Once we hit one field
  693.     //  that we have, we stop.
  694.     //
  695.     if (fProtocol != Unknown)
  696.         return true;
  697.     fProtocol = baseURL.fProtocol;
  698.     //
  699.     //  If the protocol is not file, and we either already have our own
  700.     //  host, or the base does not have one, then we are done.
  701.     //
  702.     if (fProtocol != File)
  703.     {
  704.         if (fHost || !baseURL.fHost)
  705.             return true;
  706.     }
  707.     // Replicate all of the hosty stuff if the base has one
  708.     if (baseURL.fHost)
  709.     {
  710.         // Just in case, make sure we don't leak a user or password field
  711.         fMemoryManager->deallocate(fUser);//delete [] fUser;
  712.         fUser = 0;
  713.         fMemoryManager->deallocate(fPassword);//delete [] fPassword;
  714.         fPassword = 0;
  715.         fMemoryManager->deallocate(fHost);//delete [] fHost;
  716.         fHost = 0;
  717.         fHost = XMLString::replicate(baseURL.fHost, fMemoryManager);
  718.         fUser = XMLString::replicate(baseURL.fUser, fMemoryManager);
  719.         fPassword = XMLString::replicate(baseURL.fPassword, fMemoryManager);
  720.         fPortNum = baseURL.fPortNum;
  721.     }
  722.     // If we have a path and its absolute, then we are done
  723.     const bool hadPath = (fPath != 0);
  724.     if (hadPath)
  725.     {
  726.         if (*fPath == chForwardSlash)
  727.             return true;
  728.     }
  729.     // Its a relative path, so weave them together.
  730.     if (baseURL.fPath) {
  731.         XMLCh* temp = XMLPlatformUtils::weavePaths(baseURL.fPath, fPath);
  732.         fMemoryManager->deallocate(fPath);//delete [] fPath;
  733.         fPath = temp;
  734.     }
  735.     // If we had any original path, then we are done
  736.     if (hadPath)
  737.         return true;
  738.     // We had no original path, so go on to deal with the query/fragment parts
  739.     if (fQuery || !baseURL.fQuery)
  740.         return true;
  741.     fQuery = XMLString::replicate(baseURL.fQuery, fMemoryManager);
  742.     if (fFragment || !baseURL.fFragment)
  743.         return true;
  744.     fFragment = XMLString::replicate(baseURL.fFragment, fMemoryManager);
  745. return true;
  746. }
  747. void XMLURL::parse(const XMLCh* const urlText)
  748. {
  749.     // Simplify things by checking for the psycho scenarios first
  750.     if (!*urlText)
  751.         ThrowXML(MalformedURLException, XMLExcepts::URL_NoProtocolPresent);
  752.     // Before we start, check if this urlText contains valid uri characters
  753.     if (!XMLUri::isURIString(urlText))
  754.         fHasInvalidChar = true;
  755.     else
  756.         fHasInvalidChar = false;
  757.     //
  758.     //  The first thing we will do is to check for a file name, so that
  759.     //  we don't waste time thinking its a URL. If its in the form x:
  760.     //  or x:/ and x is an ASCII letter, then assume that's the deal.
  761.     //
  762.     if (((*urlText >= chLatin_A) && (*urlText <= chLatin_Z))
  763.     ||  ((*urlText >= chLatin_a) && (*urlText <= chLatin_z)))
  764.     {
  765.         if (*(urlText + 1) == chColon)
  766.         {
  767.             if ((*(urlText + 2) == chForwardSlash)
  768.             ||  (*(urlText + 2) == chBackSlash))
  769.             {
  770.                 ThrowXML(MalformedURLException, XMLExcepts::URL_NoProtocolPresent);
  771.             }
  772.         }
  773.     }
  774.     // Get a copy of the URL that we can modify
  775.     XMLCh* srcCpy = XMLString::replicate(urlText, fMemoryManager);
  776.     ArrayJanitor<XMLCh> janSrcCopy(srcCpy, fMemoryManager);
  777.     //
  778.     //  Get a pointer now that we can run up thrown the source as we parse
  779.     //  bits and pieces out of it.
  780.     //
  781.     XMLCh* srcPtr = srcCpy;
  782.     // Run up past any spaces
  783.     while (*srcPtr)
  784.     {
  785.         if (!XMLPlatformUtils::fgTransService->isSpace(*srcPtr))
  786.             break;
  787.         srcPtr++;
  788.     }
  789.     // Make sure it wasn't all space
  790.     if (!*srcPtr)
  791.         ThrowXML(MalformedURLException, XMLExcepts::URL_NoProtocolPresent);
  792.     //
  793.     //  Ok, the next thing we have to do is to find either a / or : character.
  794.     //  If the : is first, we assume we have a protocol. If the / is first,
  795.     //  then we skip to the host processing.
  796.     //
  797.     static const XMLCh listOne[]    = { chColon, chForwardSlash, chNull };
  798.     static const XMLCh listTwo[]    = { chAt, chNull };
  799.     static const XMLCh listThree[]  = { chColon, chNull };
  800.     static const XMLCh listFour[]   = { chForwardSlash, chNull };
  801.     static const XMLCh listFive[]   = { chPound, chQuestion, chNull };
  802.     static const XMLCh listSix[]    = { chPound, chNull };
  803.     XMLCh* ptr1 = XMLString::findAny(srcPtr, listOne);
  804.     XMLCh* ptr2;
  805.     // If we found a protocol, then deal with it
  806.     if (ptr1)
  807.     {
  808.         if (*ptr1 == chColon)
  809.         {
  810.             // Cap the string at the colon
  811.             *ptr1 = 0;
  812.             // And try to find it in our list of protocols
  813.             fProtocol = lookupByName(srcPtr);
  814.             if (fProtocol == Unknown)
  815.             {
  816.                 ThrowXML1
  817.                 (
  818.                     MalformedURLException
  819.                     , XMLExcepts::URL_UnsupportedProto1
  820.                     , srcPtr
  821.                 );
  822.             }
  823.             // And move our source pointer up past what we've processed
  824.             srcPtr = (ptr1 + 1);
  825.         }
  826.     }
  827.     //
  828.     //  Ok, next we need to see if we have any host part. If the next
  829.     //  two characters are //, then we need to check, else move on.
  830.     //
  831.     if ((*srcPtr == chForwardSlash) && (*(srcPtr + 1) == chForwardSlash))
  832.     {
  833.         // Move up past the slashes
  834.         srcPtr += 2;
  835.         //
  836.         //  If we aren't at the end of the string, then there has to be a
  837.         //  host part at this point. we will just look for the next / char
  838.         //  or end of string and make all of that the host for now.
  839.         //
  840.         if (*srcPtr)
  841.         {
  842.             // Search from here for a / character
  843.             ptr1 = XMLString::findAny(srcPtr, listFour);
  844.             //
  845.             //  If we found something, then the host is between where
  846.             //  we are and what we found. Else the host is the rest of
  847.             //  the content and we are done. If its empty, leave it null.
  848.             //
  849.             if (ptr1)
  850.             {
  851.                 if (ptr1 != srcPtr)
  852.                 {
  853.                     fMemoryManager->deallocate(fHost);//delete [] fHost;
  854.                     fHost = (XMLCh*) fMemoryManager->allocate
  855.                     (
  856.                         (ptr1 - srcPtr + 1) * sizeof(XMLCh)
  857.                     );//new XMLCh[(ptr1 - srcPtr) + 1];
  858.                     ptr2 = fHost;
  859.                     while (srcPtr < ptr1)
  860.                         *ptr2++ = *srcPtr++;
  861.                     *ptr2 = 0;
  862.                 }
  863.             }
  864.              else
  865.             {
  866.                 fMemoryManager->deallocate(fHost);//delete [] fHost;
  867.                 fHost = XMLString::replicate(srcPtr, fMemoryManager);
  868.                 // Update source pointer to the end
  869.                 srcPtr += XMLString::stringLen(fHost);
  870.             }
  871.         }
  872.     }
  873.     else
  874.     {
  875.         //
  876.         // http protocol requires two forward slashes
  877.         // we didn't get them, so throw an exception
  878.         //
  879.         if (fProtocol == HTTP) {
  880.             ThrowXML
  881.                 (
  882.                     MalformedURLException
  883.                     , XMLExcepts::URL_ExpectingTwoSlashes
  884.                 );
  885.         }
  886.     }
  887.     //
  888.     //  If there was a host part, then we have to grovel through it for
  889.     //  all the bits and pieces it can hold.
  890.     //
  891.     if (fHost)
  892.     {
  893.         //
  894.         //  Look for a '@' character, which indicates a user name. If we
  895.         //  find one, then everything between the start of the host data
  896.         //  and the character is the user name.
  897.         //
  898.         ptr1 = XMLString::findAny(fHost, listTwo);
  899.         if (ptr1)
  900.         {
  901.             // Get this info out as the user name
  902.             *ptr1 = 0;
  903.             fMemoryManager->deallocate(fUser);//delete [] fUser;
  904.             fUser = XMLString::replicate(fHost, fMemoryManager);
  905.             ptr1++;
  906.             // And now cut these chars from the host string
  907.             XMLString::cut(fHost, ptr1 - fHost);
  908.             // Is there a password inside the user string?
  909.             ptr2 = XMLString::findAny(fUser, listThree);
  910.             if (ptr2)
  911.             {
  912.                 // Remove it from the user name string
  913.                 *ptr2 = 0;
  914.                 // And copy out the remainder to the password field
  915.                 ptr2++;
  916.                 fMemoryManager->deallocate(fPassword);//delete [] fPassword;
  917.                 fPassword = XMLString::replicate(ptr2, fMemoryManager);
  918.             }
  919.         }
  920.         //
  921.         //  Ok, so now we are at the actual host name, if any. If we are
  922.         //  not at the end of the host data, then lets see if we have a
  923.         //  port trailing the
  924.         //
  925.         ptr1 = XMLString::findAny(fHost, listThree);
  926.         if (ptr1)
  927.         {
  928.             // Remove it from the host name
  929.             *ptr1 = 0;
  930.             // Try to convert it to a numeric port value and store it
  931.             ptr1++;
  932.             if (!XMLString::textToBin(ptr1, fPortNum))
  933.                 ThrowXML(MalformedURLException, XMLExcepts::URL_BadPortField);
  934.         }
  935.         // If the host ended up empty, then toss is
  936.         if (!*fHost)
  937.         {
  938.             delete[] fHost;
  939.             fHost = 0;
  940.         }
  941.     }
  942.     // If we are at the end, then we are done now
  943.     if (!*srcPtr)
  944. {
  945.         return;
  946. }
  947.     //
  948.     //  Next is the path part. It can be absolute, i.e. starting with a
  949.     //  forward slash character, or relative. Its basically everything up
  950.     //  to the end of the string or to any trailing query or fragment.
  951.     //
  952.     ptr1 = XMLString::findAny(srcPtr, listFive);
  953.     if (!ptr1)
  954.     {
  955.         fMemoryManager->deallocate(fPath);//delete [] fPath;
  956.         fPath = XMLString::replicate(srcPtr, fMemoryManager);
  957.         return;
  958.     }
  959.     // Everything from where we are to what we found is the path
  960.     if (ptr1 > srcPtr)
  961.     {
  962.         fMemoryManager->deallocate(fPath);//delete [] fPath;
  963.         fPath = (XMLCh*) fMemoryManager->allocate
  964.         (
  965.             (ptr1 - srcPtr + 1) * sizeof(XMLCh)
  966.         );//new XMLCh[(ptr1 - srcPtr) + 1];
  967.         ptr2 = fPath;
  968.         while (srcPtr < ptr1)
  969.             *ptr2++ = *srcPtr++;
  970.         *ptr2 = 0;
  971.     }
  972.     //
  973.     //  If we found a fragment, then it is the rest of the string and we
  974.     //  are done.
  975.     //
  976.     if (*srcPtr == chPound)
  977.     {
  978.         srcPtr++;
  979.         fMemoryManager->deallocate(fFragment);//delete [] fFragment;
  980.         fFragment = XMLString::replicate(srcPtr, fMemoryManager);
  981.         return;
  982.     }
  983.     //
  984.     //  The query is either the rest of the string, or up to the fragment
  985.     //  separator.
  986.     //
  987.     srcPtr++;
  988.     ptr1 = XMLString::findAny(srcPtr, listSix);
  989.     fMemoryManager->deallocate(fQuery);//delete [] fQuery;
  990.     if (!ptr1)
  991.     {
  992.         fQuery = XMLString::replicate(srcPtr, fMemoryManager);
  993.         return;
  994.     }
  995.      else
  996.     {
  997.         fQuery = (XMLCh*) fMemoryManager->allocate
  998.         (
  999.             (ptr1 - srcPtr + 1) * sizeof(XMLCh)
  1000.         );//new XMLCh[(ptr1 - srcPtr) + 1];
  1001.         ptr2 = fQuery;
  1002.         while (srcPtr < ptr1)
  1003.             *ptr2++ = *srcPtr++;
  1004.         *ptr2 = 0;
  1005.     }
  1006.     // If we are not at the end now, then everything else is the fragment
  1007.     if (*srcPtr == chPound)
  1008.     {
  1009.         srcPtr++;
  1010.         fMemoryManager->deallocate(fFragment);//delete [] fFragment;
  1011.         fFragment = XMLString::replicate(srcPtr, fMemoryManager);
  1012.     }
  1013. }
  1014. XERCES_CPP_NAMESPACE_END