GME  13
XMLURL.cpp
Go to the documentation of this file.
00001 /*
00002  * Licensed to the Apache Software Foundation (ASF) under one or more
00003  * contributor license agreements.  See the NOTICE file distributed with
00004  * this work for additional information regarding copyright ownership.
00005  * The ASF licenses this file to You under the Apache License, Version 2.0
00006  * (the "License"); you may not use this file except in compliance with
00007  * the License.  You may obtain a copy of the License at
00008  *
00009  *      http://www.apache.org/licenses/LICENSE-2.0
00010  *
00011  * Unless required by applicable law or agreed to in writing, software
00012  * distributed under the License is distributed on an "AS IS" BASIS,
00013  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00014  * See the License for the specific language governing permissions and
00015  * limitations under the License.
00016  */
00017 
00018 /*
00019  * $Id: XMLURL.cpp 901107 2010-01-20 08:45:02Z borisk $
00020  */
00021 
00022 
00023 // ---------------------------------------------------------------------------
00024 //  Includes
00025 // ---------------------------------------------------------------------------
00026 #include <xercesc/util/BinFileInputStream.hpp>
00027 #include <xercesc/util/Janitor.hpp>
00028 #include <xercesc/util/PlatformUtils.hpp>
00029 #include <xercesc/util/RuntimeException.hpp>
00030 #include <xercesc/util/TransService.hpp>
00031 #include <xercesc/util/XMLURL.hpp>
00032 #include <xercesc/util/XMLNetAccessor.hpp>
00033 #include <xercesc/util/XMLString.hpp>
00034 #include <xercesc/util/XMLUniDefs.hpp>
00035 #include <xercesc/util/XMLUni.hpp>
00036 #include <xercesc/util/XMLUri.hpp>
00037 #include <xercesc/util/OutOfMemoryException.hpp>
00038 #include <xercesc/util/XMLChar.hpp>
00039 
00040 XERCES_CPP_NAMESPACE_BEGIN
00041 
00042 
00043 
00044 // ---------------------------------------------------------------------------
00045 //  Local types
00046 //
00047 //  TypeEntry
00048 //      This structure defines a single entry in the list of URL types. Each
00049 //      entry indicates the prefix for that type of URL, and the SourceTypes
00050 //      value it maps to.
00051 // ---------------------------------------------------------------------------
00052 struct ProtoEntry
00053 {
00054     XMLURL::Protocols   protocol;
00055     const XMLCh*        prefix;
00056     unsigned int        defPort;
00057 };
00058 
00059 
00060 // ---------------------------------------------------------------------------
00061 //  Local data
00062 //
00063 //  gXXXString
00064 //      These are the strings for our prefix types. They all have to be
00065 //      Unicode strings all the time, so we can't just do regular strings.
00066 //
00067 //  gProtoList
00068 //      The list of URL types that we support and some info related to each
00069 //      one.
00070 //
00071 //  gMaxProtoLen
00072 //      The length of the longest protocol string
00073 //
00074 //      NOTE:!!! Be sure to keep this up to date if new protocols are added!
00075 // ---------------------------------------------------------------------------
00076 static const XMLCh  gFileString[] =
00077 {
00078         chLatin_f, chLatin_i, chLatin_l, chLatin_e, chNull
00079 };
00080 
00081 static const XMLCh gFTPString[]  =
00082 {
00083         chLatin_f, chLatin_t, chLatin_p, chNull
00084 };
00085 
00086 static const XMLCh gHTTPString[] =
00087 {
00088         chLatin_h, chLatin_t, chLatin_t, chLatin_p, chNull
00089 };
00090 
00091 static const XMLCh gHTTPSString[] =
00092 {
00093         chLatin_h, chLatin_t, chLatin_t, chLatin_p, chLatin_s, chNull
00094 };
00095 
00096 static ProtoEntry gProtoList[XMLURL::Protocols_Count] =
00097 {
00098         { XMLURL::File     , gFileString    , 0  }
00099     ,   { XMLURL::HTTP     , gHTTPString    , 80 }
00100     ,   { XMLURL::FTP      , gFTPString     , 21 }
00101     ,   { XMLURL::HTTPS    , gHTTPSString   , 443 }
00102 };
00103 
00104 // !!! Keep these up to date with list above!
00105 static const unsigned int gMaxProtoLen = 5;
00106 
00107 static const XMLCh gListOne[]    = { chColon, chForwardSlash, chNull };
00108 static const XMLCh gListTwo[]    = { chAt, chNull };
00109 static const XMLCh gListThree[]  = { chColon, chNull };
00110 static const XMLCh gListFour[]   = { chForwardSlash, chNull };
00111 static const XMLCh gListFive[]   = { chPound, chQuestion, chNull };
00112 static const XMLCh gListSix[]    = { chPound, chNull };
00113 
00114 // ---------------------------------------------------------------------------
00115 //  Local methods
00116 // ---------------------------------------------------------------------------
00117 static bool isHexDigit(const XMLCh toCheck)
00118 {
00119     if (((toCheck >= chDigit_0) && (toCheck <= chDigit_9))
00120     ||  ((toCheck >= chLatin_A) && (toCheck <= chLatin_Z))
00121     ||  ((toCheck >= chLatin_a) && (toCheck <= chLatin_z)))
00122     {
00123         return true;
00124     }
00125     return false;
00126 }
00127 
00128 static unsigned int xlatHexDigit(const XMLCh toXlat)
00129 {
00130     if ((toXlat >= chDigit_0) && (toXlat <= chDigit_9))
00131         return (unsigned int)(toXlat - chDigit_0);
00132 
00133     if ((toXlat >= chLatin_A) && (toXlat <= chLatin_Z))
00134         return (unsigned int)(toXlat - chLatin_A) + 10;
00135 
00136     return (unsigned int)(toXlat - chLatin_a) + 10;
00137 }
00138 
00139 
00140 
00141 // ---------------------------------------------------------------------------
00142 //  XMLURL: Public, static methods
00143 // ---------------------------------------------------------------------------
00144 XMLURL::Protocols XMLURL::lookupByName(const XMLCh* const protoName)
00145 {
00146     for (unsigned int index = 0; index < XMLURL::Protocols_Count; index++)
00147     {
00148         if (!XMLString::compareIStringASCII(protoName, gProtoList[index].prefix))
00149             return gProtoList[index].protocol;
00150     }
00151     return XMLURL::Unknown;
00152 }
00153 
00154 
00155 
00156 // ---------------------------------------------------------------------------
00157 //  XMLURL: Constructors and Destructor
00158 // ---------------------------------------------------------------------------
00159 XMLURL::XMLURL(MemoryManager* const manager) :
00160 
00161     fMemoryManager(manager)
00162     , fFragment(0)
00163     , fHost(0)
00164     , fPassword(0)
00165     , fPath(0)
00166     , fPortNum(0)
00167     , fProtocol(XMLURL::Unknown)
00168     , fQuery(0)
00169     , fUser(0)
00170     , fURLText(0)
00171     , fHasInvalidChar(false)
00172 {
00173 }
00174 
00175 typedef JanitorMemFunCall<XMLURL>   CleanupType;
00176 
00177 XMLURL::XMLURL(const XMLCh* const    baseURL
00178              , const XMLCh* const    relativeURL
00179              , MemoryManager* const manager) :
00180 
00181     fMemoryManager(manager)
00182     , fFragment(0)
00183     , fHost(0)
00184     , fPassword(0)
00185     , fPath(0)
00186     , fPortNum(0)
00187     , fProtocol(XMLURL::Unknown)
00188     , fQuery(0)
00189     , fUser(0)
00190     , fURLText(0)
00191     , fHasInvalidChar(false)
00192 {
00193     CleanupType cleanup(this, &XMLURL::cleanUp);
00194 
00195         try
00196         {
00197         setURL(baseURL, relativeURL);
00198         }
00199     catch(const OutOfMemoryException&)
00200     {
00201         cleanup.release();
00202 
00203         throw;
00204     }
00205 
00206     cleanup.release();
00207 }
00208 
00209 XMLURL::XMLURL(const XMLCh* const  baseURL
00210              , const char* const   relativeURL
00211              , MemoryManager* const manager) :
00212 
00213     fMemoryManager(manager)
00214     , fFragment(0)
00215     , fHost(0)
00216     , fPassword(0)
00217     , fPath(0)
00218     , fPortNum(0)
00219     , fProtocol(XMLURL::Unknown)
00220     , fQuery(0)
00221     , fUser(0)
00222     , fURLText(0)
00223     , fHasInvalidChar(false)
00224 {
00225     CleanupType cleanup(this, &XMLURL::cleanUp);
00226 
00227     XMLCh* tmpRel = XMLString::transcode(relativeURL, fMemoryManager);
00228     ArrayJanitor<XMLCh> janRel(tmpRel, fMemoryManager);
00229         try
00230         {
00231                 setURL(baseURL, tmpRel);
00232         }
00233     catch(const OutOfMemoryException&)
00234     {
00235         cleanup.release();
00236 
00237         throw;
00238     }
00239 
00240     cleanup.release();
00241 }
00242 
00243 XMLURL::XMLURL(const XMLURL&         baseURL
00244              , const XMLCh* const    relativeURL) :
00245 
00246     fMemoryManager(baseURL.fMemoryManager)
00247     , fFragment(0)
00248     , fHost(0)
00249     , fPassword(0)
00250     , fPath(0)
00251     , fPortNum(0)
00252     , fProtocol(XMLURL::Unknown)
00253     , fQuery(0)
00254     , fUser(0)
00255     , fURLText(0)
00256     , fHasInvalidChar(false)
00257 {
00258     CleanupType cleanup(this, &XMLURL::cleanUp);
00259 
00260         try
00261         {
00262                 setURL(baseURL, relativeURL);
00263         }
00264     catch(const OutOfMemoryException&)
00265     {
00266         cleanup.release();
00267 
00268         throw;
00269     }
00270 
00271     cleanup.release();
00272 }
00273 
00274 XMLURL::XMLURL(const  XMLURL&        baseURL
00275              , const char* const     relativeURL) :
00276 
00277     fMemoryManager(baseURL.fMemoryManager)
00278     , fFragment(0)
00279     , fHost(0)
00280     , fPassword(0)
00281     , fPath(0)
00282     , fPortNum(0)
00283     , fProtocol(XMLURL::Unknown)
00284     , fQuery(0)
00285     , fUser(0)
00286     , fURLText(0)
00287     , fHasInvalidChar(false)
00288 {
00289     CleanupType cleanup(this, &XMLURL::cleanUp);
00290 
00291     XMLCh* tmpRel = XMLString::transcode(relativeURL, fMemoryManager);
00292     ArrayJanitor<XMLCh> janRel(tmpRel, fMemoryManager);
00293         try
00294         {
00295                 setURL(baseURL, tmpRel);
00296         }
00297     catch(const OutOfMemoryException&)
00298     {
00299         cleanup.release();
00300 
00301         throw;
00302     }
00303 
00304     cleanup.release();
00305 }
00306 
00307 XMLURL::XMLURL(const XMLCh* const urlText,
00308                MemoryManager* const manager) :
00309 
00310     fMemoryManager(manager)
00311     , fFragment(0)
00312     , fHost(0)
00313     , fPassword(0)
00314     , fPath(0)
00315     , fPortNum(0)
00316     , fProtocol(XMLURL::Unknown)
00317     , fQuery(0)
00318     , fUser(0)
00319     , fURLText(0)
00320     , fHasInvalidChar(false)
00321 {
00322     CleanupType cleanup(this, &XMLURL::cleanUp);
00323 
00324         try
00325         {
00326             setURL(urlText);
00327         }
00328     catch(const OutOfMemoryException&)
00329     {
00330         cleanup.release();
00331 
00332         throw;
00333     }
00334 
00335     cleanup.release();
00336 }
00337 
00338 XMLURL::XMLURL(const char* const urlText,
00339                MemoryManager* const manager) :
00340 
00341     fMemoryManager(manager)
00342     , fFragment(0)
00343     , fHost(0)
00344     , fPassword(0)
00345     , fPath(0)
00346     , fPortNum(0)
00347     , fProtocol(XMLURL::Unknown)
00348     , fQuery(0)
00349     , fUser(0)
00350     , fURLText(0)
00351     , fHasInvalidChar(false)
00352 {
00353     CleanupType cleanup(this, &XMLURL::cleanUp);
00354 
00355     XMLCh* tmpText = XMLString::transcode(urlText, fMemoryManager);
00356     ArrayJanitor<XMLCh> janRel(tmpText, fMemoryManager);
00357         try
00358         {
00359             setURL(tmpText);
00360         }
00361     catch(const OutOfMemoryException&)
00362     {
00363         cleanup.release();
00364 
00365         throw;
00366     }
00367 
00368     cleanup.release();
00369 }
00370 
00371 XMLURL::XMLURL(const XMLURL& toCopy) :
00372     XMemory(toCopy)
00373     , fMemoryManager(toCopy.fMemoryManager)
00374     , fFragment(0)
00375     , fHost(0)
00376     , fPassword(0)
00377     , fPath(0)
00378     , fPortNum(toCopy.fPortNum)
00379     , fProtocol(toCopy.fProtocol)
00380     , fQuery(0)
00381     , fUser(0)
00382     , fURLText(0)
00383     , fHasInvalidChar(toCopy.fHasInvalidChar)
00384 {
00385     CleanupType cleanup(this, &XMLURL::cleanUp);
00386 
00387     try
00388     {
00389         fFragment = XMLString::replicate(toCopy.fFragment, fMemoryManager);
00390         fHost = XMLString::replicate(toCopy.fHost, fMemoryManager);
00391         fPassword = XMLString::replicate(toCopy.fPassword, fMemoryManager);
00392         fPath = XMLString::replicate(toCopy.fPath, fMemoryManager);
00393         fQuery = XMLString::replicate(toCopy.fQuery, fMemoryManager);
00394         fUser = XMLString::replicate(toCopy.fUser, fMemoryManager);
00395         fURLText = XMLString::replicate(toCopy.fURLText, fMemoryManager);
00396     }
00397     catch(const OutOfMemoryException&)
00398     {
00399         cleanup.release();
00400 
00401         throw;
00402     }
00403 
00404     cleanup.release();
00405 }
00406 
00407 XMLURL::~XMLURL()
00408 {
00409     cleanUp();
00410 }
00411 
00412 
00413 // ---------------------------------------------------------------------------
00414 //  XMLURL: Public operators
00415 // ---------------------------------------------------------------------------
00416 XMLURL& XMLURL::operator=(const XMLURL& toAssign)
00417 {
00418     if (this == &toAssign)
00419         return *this;
00420 
00421     // Clean up our stuff
00422     cleanUp();
00423 
00424     // And copy his stuff
00425     fMemoryManager = toAssign.fMemoryManager;
00426     fFragment = XMLString::replicate(toAssign.fFragment, fMemoryManager);
00427     fHost = XMLString::replicate(toAssign.fHost, fMemoryManager);
00428     fPassword = XMLString::replicate(toAssign.fPassword, fMemoryManager);
00429     fPath = XMLString::replicate(toAssign.fPath, fMemoryManager);
00430     fPortNum = toAssign.fPortNum;
00431     fProtocol = toAssign.fProtocol;
00432     fQuery = XMLString::replicate(toAssign.fQuery, fMemoryManager);
00433     fUser = XMLString::replicate(toAssign.fUser, fMemoryManager);
00434     fURLText = XMLString::replicate(toAssign.fURLText, fMemoryManager);
00435     fHasInvalidChar = toAssign.fHasInvalidChar;
00436 
00437     return *this;
00438 }
00439 
00440 bool XMLURL::operator==(const XMLURL& toCompare) const
00441 {
00442     //
00443     //  Compare the two complete URLs (which have been processed the same
00444     //  way so they should now be the same even if they came in via different
00445     //  relative parts.
00446     //
00447     if (!XMLString::equals(getURLText(), toCompare.getURLText()))
00448         return false;
00449 
00450     return true;
00451 }
00452 
00453 
00454 
00455 // ---------------------------------------------------------------------------
00456 //  XMLURL: Getter methods
00457 // ---------------------------------------------------------------------------
00458 unsigned int XMLURL::getPortNum() const
00459 {
00460     //
00461     //  If it was not provided explicitly, then lets return the default one
00462     //  for the protocol.
00463     //
00464     if (!fPortNum)
00465     {
00466         if (fProtocol == Unknown)
00467             return 0;
00468         return gProtoList[fProtocol].defPort;
00469     }
00470     return fPortNum;
00471 }
00472 
00473 
00474 const XMLCh* XMLURL::getProtocolName() const
00475 {
00476     // Check to see if its ever been set
00477     if (fProtocol == Unknown)
00478         ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
00479 
00480     return gProtoList[fProtocol].prefix;
00481 }
00482 
00483 
00484 // ---------------------------------------------------------------------------
00485 //  XMLURL: Setter methods
00486 // ---------------------------------------------------------------------------
00487 void XMLURL::setURL(const XMLCh* const urlText)
00488 {
00489     //
00490     //  Try to parse the URL.
00491     //
00492     cleanUp();
00493     parse(urlText);
00494 }
00495 
00496 void XMLURL::setURL(const XMLCh* const    baseURL
00497                   , const XMLCh* const    relativeURL)
00498 {
00499     cleanUp();
00500 
00501     // Parse our URL string
00502     parse(relativeURL);
00503 
00504         //
00505         //  If its relative and the base is non-null and non-empty, then
00506         //  parse the base URL string and conglomerate them.
00507         //
00508         if (isRelative() && baseURL)
00509         {
00510                 if (*baseURL)
00511                 {
00512                         XMLURL basePart(baseURL, fMemoryManager);
00513                         if (!conglomerateWithBase(basePart, false))
00514                         {
00515                                 cleanUp();
00516                                 ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_RelativeBaseURL, fMemoryManager);
00517                         }
00518                 }
00519         }
00520 }
00521 
00522 // this version of setURL doesn't throw a malformedurl exception
00523 // instead it returns false when it failed (or when it would of
00524 // thrown a malformedurl exception)
00525 bool XMLURL::setURL(const XMLCh* const    baseURL
00526                   , const XMLCh* const    relativeURL
00527                   , XMLURL& xmlURL)
00528 {
00529     cleanUp();
00530 
00531     // Parse our URL string
00532     if (parse(relativeURL, xmlURL))
00533     {
00534             //  If its relative and the base is non-null and non-empty, then
00535             //  parse the base URL string and conglomerate them.
00536             //
00537             if (isRelative() && baseURL && *baseURL)
00538             {
00539                 XMLURL basePart(fMemoryManager);
00540             if (parse(baseURL, basePart)  && conglomerateWithBase(basePart, false))
00541             {
00542                         return true;
00543                     }
00544             }
00545         else
00546             return true;
00547     }
00548     return false;
00549 }
00550 
00551 void XMLURL::setURL(const XMLURL&         baseURL
00552                   , const XMLCh* const    relativeURL)
00553 {
00554     cleanUp();
00555 
00556         // Parse our URL string
00557     parse(relativeURL);
00558 
00559     // If its relative, then conglomerate with the base URL
00560     if (isRelative())
00561                 conglomerateWithBase(baseURL);
00562 }
00563 
00564 
00565 // ---------------------------------------------------------------------------
00566 //  XMLURL: Miscellaneous methods
00567 // ---------------------------------------------------------------------------
00568 bool XMLURL::isRelative() const
00569 {
00570     // If no protocol then relative
00571     if (fProtocol == Unknown)
00572         return true;
00573 
00574     // If no path, or the path is not absolute, then relative
00575     if (!fPath)
00576         return true;
00577 
00578     if (*fPath != chForwardSlash)
00579         return true;
00580 
00581     return false;
00582 }
00583 
00584 
00585 bool XMLURL::hasInvalidChar() const {
00586     return fHasInvalidChar;
00587 }
00588 
00589 
00590 BinInputStream* XMLURL::makeNewStream() const
00591 {
00592     //
00593     //  If its a local host, then we short circuit it and use our own file
00594     //  stream support. Otherwise, we just let it fall through and let the
00595     //  installed network access object provide a stream.
00596     //
00597     if (fProtocol == XMLURL::File)
00598     {
00599         if (!fHost || !XMLString::compareIStringASCII(fHost, XMLUni::fgLocalHostString))
00600         {
00601 
00602             XMLCh* realPath = XMLString::replicate(fPath, fMemoryManager);
00603             ArrayJanitor<XMLCh> basePathName(realPath, fMemoryManager);
00604 
00605             //
00606             // Need to manually replace any character reference %xx first
00607             // HTTP protocol will be done automatically by the netaccessor
00608             //
00609             XMLSize_t end = XMLString::stringLen(realPath);
00610             int percentIndex = XMLString::indexOf(realPath, chPercent, 0, fMemoryManager);
00611 
00612             while (percentIndex != -1) {
00613 
00614                 if (percentIndex+2 >= (int)end ||
00615                     !isHexDigit(realPath[percentIndex+1]) ||
00616                     !isHexDigit(realPath[percentIndex+2]))
00617                 {
00618                     XMLCh value1[4];
00619                     XMLString::moveChars(value1, &(realPath[percentIndex]), 3);
00620                     value1[3] = chNull;
00621                     ThrowXMLwithMemMgr2(MalformedURLException
00622                             , XMLExcepts::XMLNUM_URI_Component_Invalid_EscapeSequence
00623                             , realPath
00624                             , value1
00625                             , fMemoryManager);
00626                 }
00627 
00628                 unsigned int value = (xlatHexDigit(realPath[percentIndex+1]) * 16) + xlatHexDigit(realPath[percentIndex+2]);
00629 
00630                 realPath[percentIndex] = XMLCh(value);
00631 
00632                 XMLSize_t i =0;
00633                 for (i = percentIndex + 1; i < end - 2 ; i++)
00634                     realPath[i] = realPath[i+2];
00635                 realPath[i] = chNull;
00636                 end = i;
00637 
00638                 if (((XMLSize_t)(percentIndex + 1)) < end)
00639                   percentIndex = XMLString::indexOf(realPath, chPercent, percentIndex + 1, fMemoryManager);
00640                 else
00641                   percentIndex = -1;
00642             }
00643 
00644 
00645             BinFileInputStream* retStrm = new (fMemoryManager) BinFileInputStream(realPath, fMemoryManager);
00646             if (!retStrm->getIsOpen())
00647             {
00648                 delete retStrm;
00649                 return 0;
00650             }
00651             return retStrm;
00652         }
00653     }
00654 
00655     //
00656     //  If we don't have have an installed net accessor object, then we
00657     //  have to just throw here.
00658     //
00659     if (!XMLPlatformUtils::fgNetAccessor)
00660         ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_UnsupportedProto, fMemoryManager);
00661 
00662     // Else ask the net accessor to create the stream
00663     return XMLPlatformUtils::fgNetAccessor->makeNew(*this);
00664 }
00665 
00666 void XMLURL::makeRelativeTo(const XMLCh* const baseURLText)
00667 {
00668     // If this one is not relative, don't bother
00669     if (!isRelative())
00670         return;
00671 
00672     XMLURL baseURL(baseURLText, fMemoryManager);
00673     conglomerateWithBase(baseURL);
00674 }
00675 
00676 void XMLURL::makeRelativeTo(const XMLURL& baseURL)
00677 {
00678     // If this one is not relative, don't bother
00679     if (!isRelative())
00680         return;
00681     conglomerateWithBase(baseURL);
00682 }
00683 
00684 
00685 
00686 
00687 // ---------------------------------------------------------------------------
00688 //  XMLURL: Private helper methods
00689 // ---------------------------------------------------------------------------
00690 
00691 //
00692 //  This method will take the broken out parts of the URL and build up the
00693 //  full text. We don't do this unless someone asks us to, since its often
00694 //  never required.
00695 //
00696 void XMLURL::buildFullText()
00697 {
00698     // Calculate the worst case size of the buffer required
00699     XMLSize_t bufSize = gMaxProtoLen + 1
00700                            + XMLString::stringLen(fFragment) + 1
00701                            + XMLString::stringLen(fHost) + 2
00702                            + XMLString::stringLen(fPassword) + 1
00703                            + XMLString::stringLen(fPath)
00704                            + XMLString::stringLen(fQuery) + 1
00705                            + XMLString::stringLen(fUser) + 1
00706                            + 32;
00707 
00708     // Clean up the existing buffer and allocate another
00709     fMemoryManager->deallocate(fURLText);//delete [] fURLText;
00710     fURLText = (XMLCh*) fMemoryManager->allocate((bufSize) * sizeof(XMLCh));//new XMLCh[bufSize];
00711     *fURLText = 0;
00712 
00713     XMLCh* outPtr = fURLText;
00714     if (fProtocol != Unknown)
00715     {
00716         XMLString::catString(fURLText, getProtocolName());
00717         outPtr += XMLString::stringLen(fURLText);
00718         *outPtr++ = chColon;
00719         *outPtr++ = chForwardSlash;
00720         *outPtr++ = chForwardSlash;
00721     }
00722 
00723     if (fUser)
00724     {
00725         XMLString::copyString(outPtr, fUser);
00726         outPtr += XMLString::stringLen(fUser);
00727 
00728         if (fPassword)
00729         {
00730             *outPtr++ = chColon;
00731             XMLString::copyString(outPtr, fPassword);
00732             outPtr += XMLString::stringLen(fPassword);
00733         }
00734 
00735         *outPtr++ = chAt;
00736     }
00737 
00738     if (fHost)
00739     {
00740         XMLString::copyString(outPtr, fHost);
00741         outPtr += XMLString::stringLen(fHost);
00742 
00743         //
00744         //  If the port is zero, then we don't put it in. Else we need
00745         //  to because it was explicitly provided.
00746         //
00747         if (fPortNum)
00748         {
00749             *outPtr++ = chColon;
00750 
00751             XMLCh tmpBuf[17];
00752             XMLString::binToText(fPortNum, tmpBuf, 16, 10, fMemoryManager);
00753             XMLString::copyString(outPtr, tmpBuf);
00754             outPtr += XMLString::stringLen(tmpBuf);
00755         }
00756     }
00757 
00758     if (fPath)
00759     {
00760         XMLString::copyString(outPtr, fPath);
00761         outPtr += XMLString::stringLen(fPath);
00762     }
00763 
00764     if (fQuery)
00765     {
00766         *outPtr++ = chQuestion;
00767         XMLString::copyString(outPtr, fQuery);
00768         outPtr += XMLString::stringLen(fQuery);
00769     }
00770 
00771     if (fFragment)
00772     {
00773         *outPtr++ = chPound;
00774         XMLString::copyString(outPtr, fFragment);
00775         outPtr += XMLString::stringLen(fFragment);
00776     }
00777 
00778     // Cap it off in case the last op was not a string copy
00779     *outPtr = 0;
00780 }
00781 
00782 
00783 //
00784 //  Just a central place to handle cleanup, since its done from a number
00785 //  of different spots.
00786 //
00787 void XMLURL::cleanUp()
00788 {
00789     fMemoryManager->deallocate(fFragment);//delete [] fFragment;
00790     fMemoryManager->deallocate(fHost);//delete [] fHost;
00791     fMemoryManager->deallocate(fPassword);//delete [] fPassword;
00792     fMemoryManager->deallocate(fPath);//delete [] fPath;
00793     fMemoryManager->deallocate(fQuery);//delete [] fQuery;
00794     fMemoryManager->deallocate(fUser);//delete [] fUser;
00795     fMemoryManager->deallocate(fURLText);//delete [] fURLText;
00796 
00797     fFragment = 0;
00798     fHost = 0;
00799     fPassword = 0;
00800     fPath = 0;
00801     fQuery = 0;
00802     fUser = 0;
00803     fURLText = 0;
00804 
00805     fProtocol = Unknown;
00806     fPortNum = 0;
00807     fHasInvalidChar = false;
00808 }
00809 
00810 
00811 //This function  has been modified to take a bool parameter and the
00812 //functionality inside looks irrational but is only to make
00813 //solaris 2.7 CC 5.0 optimized build happy.
00814 
00815 bool XMLURL::conglomerateWithBase(const XMLURL& baseURL, bool useExceptions)
00816 {
00817     // The base URL cannot be relative
00818     if (baseURL.isRelative())
00819     {
00820         if (useExceptions)
00821                         ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_RelativeBaseURL, fMemoryManager);
00822         else
00823             return false;
00824     }
00825 
00826     //
00827     //  Check a special case. If all we have is a fragment, then we want
00828     //  to just take the base host and path, plus our fragment.
00829     //
00830     if ((fProtocol == Unknown)
00831     &&  !fHost
00832     &&  !fPath
00833     &&  fFragment)
00834     {
00835         // Just in case, make sure we don't leak the user or password values
00836         fMemoryManager->deallocate(fUser);//delete [] fUser;
00837         fUser = 0;
00838         fMemoryManager->deallocate(fPassword);//delete [] fPassword;
00839         fPassword = 0;
00840 
00841         // Copy over the protocol and port number as is
00842         fProtocol = baseURL.fProtocol;
00843         fPortNum = baseURL.fPortNum;
00844 
00845         // Replicate the base fields that are provided
00846         fHost = XMLString::replicate(baseURL.fHost, fMemoryManager);
00847         fUser = XMLString::replicate(baseURL.fUser, fMemoryManager);
00848         fPassword = XMLString::replicate(baseURL.fPassword, fMemoryManager);
00849         fPath = XMLString::replicate(baseURL.fPath, fMemoryManager);
00850         return true;
00851     }
00852 
00853     //
00854     //  All we have to do is run up through our fields and, for each one
00855     //  that we don't have, use the based URL's. Once we hit one field
00856     //  that we have, we stop.
00857     //
00858     if (fProtocol != Unknown)
00859         return true;
00860     fProtocol = baseURL.fProtocol;
00861 
00862     //
00863     //  If the protocol is not file, and we either already have our own
00864     //  host, or the base does not have one, then we are done.
00865     //
00866     if (fProtocol != File)
00867     {
00868         if (fHost || !baseURL.fHost)
00869             return true;
00870     }
00871 
00872     // Replicate all of the hosty stuff if the base has one
00873     if (baseURL.fHost)
00874     {
00875         // Just in case, make sure we don't leak a user or password field
00876         fMemoryManager->deallocate(fUser);//delete [] fUser;
00877         fUser = 0;
00878         fMemoryManager->deallocate(fPassword);//delete [] fPassword;
00879         fPassword = 0;
00880         fMemoryManager->deallocate(fHost);//delete [] fHost;
00881         fHost = 0;
00882 
00883         fHost = XMLString::replicate(baseURL.fHost, fMemoryManager);
00884         fUser = XMLString::replicate(baseURL.fUser, fMemoryManager);
00885         fPassword = XMLString::replicate(baseURL.fPassword, fMemoryManager);
00886 
00887         fPortNum = baseURL.fPortNum;
00888     }
00889 
00890     // If we have a path and its absolute, then we are done
00891     const bool hadPath = (fPath != 0);
00892     if (hadPath)
00893     {
00894         if (*fPath == chForwardSlash)
00895             return true;
00896     }
00897 
00898     // Its a relative path, so weave them together.
00899     if (baseURL.fPath) {
00900         XMLCh* temp = XMLPlatformUtils::weavePaths(baseURL.fPath, fPath ,fMemoryManager);
00901         fMemoryManager->deallocate(fPath);//delete [] fPath;
00902         fPath = temp;
00903     }
00904 
00905     // If we had any original path, then we are done
00906     if (hadPath)
00907         return true;
00908 
00909     // We had no original path, so go on to deal with the query/fragment parts
00910     if (fQuery || !baseURL.fQuery)
00911         return true;
00912     fQuery = XMLString::replicate(baseURL.fQuery, fMemoryManager);
00913 
00914     if (fFragment || !baseURL.fFragment)
00915         return true;
00916     fFragment = XMLString::replicate(baseURL.fFragment, fMemoryManager);
00917         return true;
00918 }
00919 
00920 
00921 void XMLURL::parse(const XMLCh* const urlText)
00922 {
00923     // Simplify things by checking for the psycho scenarios first
00924     if (!*urlText)
00925         ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
00926 
00927     // Before we start, check if this urlText contains valid uri characters
00928     if (!XMLUri::isURIString(urlText))
00929         fHasInvalidChar = true;
00930     else
00931         fHasInvalidChar = false;
00932 
00933     //
00934     //  The first thing we will do is to check for a file name, so that
00935     //  we don't waste time thinking its a URL. If its in the form x:\ or x:/
00936     //  and x is an ASCII letter, then assume that's the deal.
00937     //
00938     if (((*urlText >= chLatin_A) && (*urlText <= chLatin_Z))
00939     ||  ((*urlText >= chLatin_a) && (*urlText <= chLatin_z)))
00940     {
00941         if (*(urlText + 1) == chColon)
00942         {
00943             if ((*(urlText + 2) == chForwardSlash)
00944             ||  (*(urlText + 2) == chBackSlash))
00945             {
00946                 ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
00947             }
00948         }
00949     }
00950 
00951     // Get a copy of the URL that we can modify
00952     XMLCh* srcCpy = XMLString::replicate(urlText, fMemoryManager);
00953     ArrayJanitor<XMLCh> janSrcCopy(srcCpy, fMemoryManager);
00954 
00955     //
00956     //  Get a pointer now that we can run up thrown the source as we parse
00957     //  bits and pieces out of it.
00958     //
00959     XMLCh* srcPtr = srcCpy;
00960 
00961     // Run up past any spaces
00962     while (*srcPtr)
00963     {
00964         if (!XMLChar1_0::isWhitespace(*srcPtr))
00965             break;
00966         srcPtr++;
00967     }
00968 
00969     // Make sure it wasn't all space
00970     if (!*srcPtr)
00971         ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
00972 
00973     //
00974     //  Ok, the next thing we have to do is to find either a / or : character.
00975     //  If the : is first, we assume we have a protocol. If the / is first,
00976     //  then we skip to the host processing.
00977     //
00978     XMLCh* ptr1 = XMLString::findAny(srcPtr, gListOne);
00979     XMLCh* ptr2;
00980 
00981     // If we found a protocol, then deal with it
00982     if (ptr1)
00983     {
00984         if (*ptr1 == chColon)
00985         {
00986             // Cap the string at the colon
00987             *ptr1 = 0;
00988 
00989             // And try to find it in our list of protocols
00990             fProtocol = lookupByName(srcPtr);
00991 
00992             if (fProtocol == Unknown)
00993             {
00994                 ThrowXMLwithMemMgr1
00995                 (
00996                     MalformedURLException
00997                     , XMLExcepts::URL_UnsupportedProto1
00998                     , srcPtr
00999                     , fMemoryManager
01000                 );
01001             }
01002 
01003             // And move our source pointer up past what we've processed
01004             srcPtr = (ptr1 + 1);
01005         }
01006     }
01007 
01008     //
01009     //  Ok, next we need to see if we have any host part. If the next
01010     //  two characters are //, then we need to check, else move on.
01011     //
01012     if ((*srcPtr == chForwardSlash) && (*(srcPtr + 1) == chForwardSlash))
01013     {
01014         // Move up past the slashes
01015         srcPtr += 2;
01016 
01017         //
01018         //  If we aren't at the end of the string, then there has to be a
01019         //  host part at this point. we will just look for the next / char
01020         //  or end of string and make all of that the host for now.
01021         //
01022         if (*srcPtr)
01023         {
01024             // Search from here for a / character
01025             ptr1 = XMLString::findAny(srcPtr, gListFour);
01026 
01027             //
01028             //  If we found something, then the host is between where
01029             //  we are and what we found. Else the host is the rest of
01030             //  the content and we are done. If its empty, leave it null.
01031             //
01032             if (ptr1)
01033             {
01034                 if (ptr1 != srcPtr)
01035                 {
01036                     fMemoryManager->deallocate(fHost);//delete [] fHost;
01037                     fHost = (XMLCh*) fMemoryManager->allocate
01038                     (
01039                         ((ptr1 - srcPtr) + 1) * sizeof(XMLCh)
01040                     );//new XMLCh[(ptr1 - srcPtr) + 1];
01041                     ptr2 = fHost;
01042                     while (srcPtr < ptr1)
01043                         *ptr2++ = *srcPtr++;
01044                     *ptr2 = 0;
01045                 }
01046             }
01047              else
01048             {
01049                 fMemoryManager->deallocate(fHost);//delete [] fHost;
01050                 fHost = XMLString::replicate(srcPtr, fMemoryManager);
01051 
01052                 // Update source pointer to the end
01053                 srcPtr += XMLString::stringLen(fHost);
01054             }
01055         }
01056     }
01057     else
01058     {
01059         //
01060         // http protocol requires two forward slashes
01061         // we didn't get them, so throw an exception
01062         //
01063         if (fProtocol == HTTP) {
01064             ThrowXMLwithMemMgr
01065                 (
01066                     MalformedURLException
01067                     , XMLExcepts::URL_ExpectingTwoSlashes
01068                     , fMemoryManager
01069                 );
01070         }
01071     }
01072 
01073     //
01074     //  If there was a host part, then we have to grovel through it for
01075     //  all the bits and pieces it can hold.
01076     //
01077     if (fHost)
01078     {
01079         //
01080         //  Look for a '@' character, which indicates a user name. If we
01081         //  find one, then everything between the start of the host data
01082         //  and the character is the user name.
01083         //
01084         ptr1 = XMLString::findAny(fHost, gListTwo);
01085         if (ptr1)
01086         {
01087             // Get this info out as the user name
01088             *ptr1 = 0;
01089             fMemoryManager->deallocate(fUser);//delete [] fUser;
01090             fUser = XMLString::replicate(fHost, fMemoryManager);
01091             ptr1++;
01092 
01093             // And now cut these chars from the host string
01094             XMLString::cut(fHost, ptr1 - fHost);
01095 
01096             // Is there a password inside the user string?
01097             ptr2 = XMLString::findAny(fUser, gListThree);
01098             if (ptr2)
01099             {
01100                 // Remove it from the user name string
01101                 *ptr2 = 0;
01102 
01103                 // And copy out the remainder to the password field
01104                 ptr2++;
01105                 fMemoryManager->deallocate(fPassword);//delete [] fPassword;
01106                 fPassword = XMLString::replicate(ptr2, fMemoryManager);
01107             }
01108         }
01109 
01110         //
01111         //  Ok, so now we are at the actual host name, if any. If we are
01112         //  not at the end of the host data, then lets see if we have a
01113         //  port trailing the
01114         //
01115         ptr1 = XMLString::findAny(fHost, gListThree);
01116         if (ptr1)
01117         {
01118             // Remove it from the host name
01119             *ptr1 = 0;
01120 
01121             // Try to convert it to a numeric port value and store it
01122             ptr1++;
01123             if (!XMLString::textToBin(ptr1, fPortNum, fMemoryManager))
01124                 ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_BadPortField, fMemoryManager);
01125         }
01126 
01127         // If the host ended up empty, then toss is
01128         if (!*fHost)
01129         {
01130             fMemoryManager->deallocate(fHost);//delete[] fHost;
01131             fHost = 0;
01132         }
01133     }
01134 
01135     // If we are at the end, then we are done now
01136     if (!*srcPtr) {
01137         if(fHost) {
01138             static const XMLCh slash[] = { chForwardSlash, chNull };
01139             fPath = XMLString::replicate(slash, fMemoryManager);
01140         }
01141         return;
01142     }
01143 
01144     //
01145     //  Next is the path part. It can be absolute, i.e. starting with a
01146     //  forward slash character, or relative. Its basically everything up
01147     //  to the end of the string or to any trailing query or fragment.
01148     //
01149     ptr1 = XMLString::findAny(srcPtr, gListFive);
01150     if (!ptr1)
01151     {
01152         fMemoryManager->deallocate(fPath);//delete [] fPath;
01153         fPath = XMLString::replicate(srcPtr, fMemoryManager);
01154         return;
01155     }
01156 
01157     // Everything from where we are to what we found is the path
01158     if (ptr1 > srcPtr)
01159     {
01160         fMemoryManager->deallocate(fPath);//delete [] fPath;
01161         fPath = (XMLCh*) fMemoryManager->allocate
01162         (
01163             ((ptr1 - srcPtr) + 1) * sizeof(XMLCh)
01164         );//new XMLCh[(ptr1 - srcPtr) + 1];
01165         ptr2 = fPath;
01166         while (srcPtr < ptr1)
01167             *ptr2++ = *srcPtr++;
01168         *ptr2 = 0;
01169     }
01170 
01171     //
01172     //  If we found a fragment, then it is the rest of the string and we
01173     //  are done.
01174     //
01175     if (*srcPtr == chPound)
01176     {
01177         srcPtr++;
01178         fMemoryManager->deallocate(fFragment);//delete [] fFragment;
01179         fFragment = XMLString::replicate(srcPtr, fMemoryManager);
01180         return;
01181     }
01182 
01183     //
01184     //  The query is either the rest of the string, or up to the fragment
01185     //  separator.
01186     //
01187     srcPtr++;
01188     ptr1 = XMLString::findAny(srcPtr, gListSix);
01189     fMemoryManager->deallocate(fQuery);//delete [] fQuery;
01190     if (!ptr1)
01191     {
01192         fQuery = XMLString::replicate(srcPtr, fMemoryManager);
01193         return;
01194     }
01195      else
01196     {
01197         fQuery = (XMLCh*) fMemoryManager->allocate
01198         (
01199             ((ptr1 - srcPtr) + 1) * sizeof(XMLCh)
01200         );//new XMLCh[(ptr1 - srcPtr) + 1];
01201         ptr2 = fQuery;
01202         while (srcPtr < ptr1)
01203             *ptr2++ = *srcPtr++;
01204         *ptr2 = 0;
01205     }
01206 
01207     // If we are not at the end now, then everything else is the fragment
01208     if (*srcPtr == chPound)
01209     {
01210         srcPtr++;
01211         fMemoryManager->deallocate(fFragment);//delete [] fFragment;
01212         fFragment = XMLString::replicate(srcPtr, fMemoryManager);
01213     }
01214 }
01215 
01216 bool XMLURL::parse(const XMLCh* const urlText, XMLURL& xmlURL)
01217 {
01218     // Simplify things by checking for the psycho scenarios first
01219     if (!*urlText)
01220         return false;
01221 
01222     // Before we start, check if this urlText contains valid uri characters
01223     if (!XMLUri::isURIString(urlText))
01224         xmlURL.fHasInvalidChar = true;
01225     else
01226         xmlURL.fHasInvalidChar = false;
01227 
01228     //
01229     //  The first thing we will do is to check for a file name, so that
01230     //  we don't waste time thinking its a URL. If its in the form x:\ or x:/
01231     //  and x is an ASCII letter, then assume that's the deal.
01232     //
01233     if (((*urlText >= chLatin_A) && (*urlText <= chLatin_Z))
01234     ||  ((*urlText >= chLatin_a) && (*urlText <= chLatin_z)))
01235     {
01236         if (*(urlText + 1) == chColon)
01237         {
01238             if ((*(urlText + 2) == chForwardSlash)
01239             ||  (*(urlText + 2) == chBackSlash))
01240             {
01241                 return false;
01242             }
01243         }
01244     }
01245 
01246     // Get a copy of the URL that we can modify
01247     XMLCh* srcCpy = XMLString::replicate(urlText, xmlURL.fMemoryManager);
01248     ArrayJanitor<XMLCh> janSrcCopy(srcCpy, xmlURL.fMemoryManager);
01249 
01250     //
01251     //  Get a pointer now that we can run up thrown the source as we parse
01252     //  bits and pieces out of it.
01253     //
01254     XMLCh* srcPtr = srcCpy;
01255 
01256     // Run up past any spaces
01257     while (*srcPtr)
01258     {
01259         if (!XMLChar1_0::isWhitespace(*srcPtr))
01260             break;
01261         srcPtr++;
01262     }
01263 
01264     // Make sure it wasn't all space
01265     if (!*srcPtr)
01266         return false;
01267 
01268     //
01269     //  Ok, the next thing we have to do is to find either a / or : character.
01270     //  If the : is first, we assume we have a protocol. If the / is first,
01271     //  then we skip to the host processing.
01272     //
01273     XMLCh* ptr1 = XMLString::findAny(srcPtr, gListOne);
01274     XMLCh* ptr2;
01275 
01276     // If we found a protocol, then deal with it
01277     if (ptr1)
01278     {
01279         if (*ptr1 == chColon)
01280         {
01281             // Cap the string at the colon
01282             *ptr1 = 0;
01283 
01284             // And try to find it in our list of protocols
01285             xmlURL.fProtocol = lookupByName(srcPtr);
01286 
01287             if (xmlURL.fProtocol == Unknown)
01288                 return false;
01289 
01290             // And move our source pointer up past what we've processed
01291             srcPtr = (ptr1 + 1);
01292         }
01293     }
01294 
01295     //
01296     //  Ok, next we need to see if we have any host part. If the next
01297     //  two characters are //, then we need to check, else move on.
01298     //
01299     if ((*srcPtr == chForwardSlash) && (*(srcPtr + 1) == chForwardSlash))
01300     {
01301         // Move up past the slashes
01302         srcPtr += 2;
01303 
01304         //
01305         //  If we aren't at the end of the string, then there has to be a
01306         //  host part at this point. we will just look for the next / char
01307         //  or end of string and make all of that the host for now.
01308         //
01309         if (*srcPtr)
01310         {
01311             // Search from here for a / character
01312             ptr1 = XMLString::findAny(srcPtr, gListFour);
01313 
01314             //
01315             //  If we found something, then the host is between where
01316             //  we are and what we found. Else the host is the rest of
01317             //  the content and we are done. If its empty, leave it null.
01318             //
01319             if (ptr1)
01320             {
01321                 if (ptr1 != srcPtr)
01322                 {
01323                     xmlURL.fHost = (XMLCh*) xmlURL.fMemoryManager->allocate
01324                     (
01325                         ((ptr1 - srcPtr) + 1) * sizeof(XMLCh)
01326                     );//new XMLCh[(ptr1 - srcPtr) + 1];
01327                     ptr2 = xmlURL.fHost;
01328                     while (srcPtr < ptr1)
01329                         *ptr2++ = *srcPtr++;
01330                     *ptr2 = 0;
01331                 }
01332             }
01333              else
01334             {
01335                 xmlURL.fHost = XMLString::replicate(srcPtr, xmlURL.fMemoryManager);
01336 
01337                 // Update source pointer to the end
01338                 srcPtr += XMLString::stringLen(xmlURL.fHost);
01339             }
01340         }
01341     }
01342     else
01343     {
01344         //
01345         // http protocol requires two forward slashes
01346         // we didn't get them, so throw an exception
01347         //
01348         if (xmlURL.fProtocol == HTTP)
01349             return false;
01350     }
01351 
01352     //
01353     //  If there was a host part, then we have to grovel through it for
01354     //  all the bits and pieces it can hold.
01355     //
01356     if (xmlURL.fHost)
01357     {
01358         //
01359         //  Look for a '@' character, which indicates a user name. If we
01360         //  find one, then everything between the start of the host data
01361         //  and the character is the user name.
01362         //
01363         ptr1 = XMLString::findAny(xmlURL.fHost, gListTwo);
01364         if (ptr1)
01365         {
01366             // Get this info out as the user name
01367             *ptr1 = 0;
01368             xmlURL.fUser = XMLString::replicate(xmlURL.fHost, xmlURL.fMemoryManager);
01369             ptr1++;
01370 
01371             // And now cut these chars from the host string
01372             XMLString::cut(xmlURL.fHost, ptr1 - xmlURL.fHost);
01373 
01374             // Is there a password inside the user string?
01375             ptr2 = XMLString::findAny(xmlURL.fUser, gListThree);
01376             if (ptr2)
01377             {
01378                 // Remove it from the user name string
01379                 *ptr2 = 0;
01380 
01381                 // And copy out the remainder to the password field
01382                 ptr2++;
01383                 xmlURL.fPassword = XMLString::replicate(ptr2, xmlURL.fMemoryManager);
01384             }
01385         }
01386 
01387         //
01388         //  Ok, so now we are at the actual host name, if any. If we are
01389         //  not at the end of the host data, then lets see if we have a
01390         //  port trailing the
01391         //
01392         ptr1 = XMLString::findAny(xmlURL.fHost, gListThree);
01393         if (ptr1)
01394         {
01395             // Remove it from the host name
01396             *ptr1 = 0;
01397 
01398             // Try to convert it to a numeric port value and store it
01399             ptr1++;
01400             if (!XMLString::textToBin(ptr1, xmlURL.fPortNum, xmlURL.fMemoryManager))
01401                 return false;
01402         }
01403 
01404         // If the host ended up empty, then toss is
01405         if (!*(xmlURL.fHost))
01406         {
01407             xmlURL.fMemoryManager->deallocate(xmlURL.fHost);//delete[] fHost;
01408             xmlURL.fHost = 0;
01409         }
01410     }
01411 
01412     // If we are at the end, then we are done now
01413     if (!*srcPtr) {
01414         if(xmlURL.fHost) {
01415             static const XMLCh slash[] = { chForwardSlash, chNull };
01416             xmlURL.fPath = XMLString::replicate(slash, xmlURL.fMemoryManager);
01417         }
01418         return true;
01419     }
01420 
01421     //
01422     //  Next is the path part. It can be absolute, i.e. starting with a
01423     //  forward slash character, or relative. Its basically everything up
01424     //  to the end of the string or to any trailing query or fragment.
01425     //
01426     ptr1 = XMLString::findAny(srcPtr, gListFive);
01427     if (!ptr1)
01428     {
01429         xmlURL.fPath = XMLString::replicate(srcPtr, xmlURL.fMemoryManager);
01430         return true;
01431     }
01432 
01433     // Everything from where we are to what we found is the path
01434     if (ptr1 > srcPtr)
01435     {
01436         xmlURL.fPath = (XMLCh*) xmlURL.fMemoryManager->allocate
01437         (
01438             ((ptr1 - srcPtr) + 1) * sizeof(XMLCh)
01439         );//new XMLCh[(ptr1 - srcPtr) + 1];
01440         ptr2 = xmlURL.fPath;
01441         while (srcPtr < ptr1)
01442             *ptr2++ = *srcPtr++;
01443         *ptr2 = 0;
01444     }
01445 
01446     //
01447     //  If we found a fragment, then it is the rest of the string and we
01448     //  are done.
01449     //
01450     if (*srcPtr == chPound)
01451     {
01452         srcPtr++;
01453         xmlURL.fFragment = XMLString::replicate(srcPtr, xmlURL.fMemoryManager);
01454         return true;
01455     }
01456 
01457     //
01458     //  The query is either the rest of the string, or up to the fragment
01459     //  separator.
01460     //
01461     srcPtr++;
01462     ptr1 = XMLString::findAny(srcPtr, gListSix);
01463     if (!ptr1)
01464     {
01465         xmlURL.fQuery = XMLString::replicate(srcPtr, xmlURL.fMemoryManager);
01466         return true;
01467     }
01468      else
01469     {
01470         xmlURL.fQuery = (XMLCh*) xmlURL.fMemoryManager->allocate
01471         (
01472             ((ptr1 - srcPtr) + 1) * sizeof(XMLCh)
01473         );//new XMLCh[(ptr1 - srcPtr) + 1];
01474         ptr2 = xmlURL.fQuery;
01475         while (srcPtr < ptr1)
01476             *ptr2++ = *srcPtr++;
01477         *ptr2 = 0;
01478     }
01479 
01480     // If we are not at the end now, then everything else is the fragment
01481     if (*srcPtr == chPound)
01482     {
01483         srcPtr++;
01484         xmlURL.fFragment = XMLString::replicate(srcPtr, xmlURL.fMemoryManager);
01485     }
01486 
01487     return true;
01488 }
01489 
01490 XERCES_CPP_NAMESPACE_END