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

词法分析

开发平台:

Visual C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 2002, 2003 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: DGXMLScanner.cpp,v 1.14 2003/05/18 14:02:04 knoaman Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  Includes
  61. // ---------------------------------------------------------------------------
  62. #include <xercesc/internal/DGXMLScanner.hpp>
  63. #include <xercesc/util/Janitor.hpp>
  64. #include <xercesc/util/RuntimeException.hpp>
  65. #include <xercesc/util/UnexpectedEOFException.hpp>
  66. #include <xercesc/framework/URLInputSource.hpp>
  67. #include <xercesc/framework/LocalFileInputSource.hpp>
  68. #include <xercesc/framework/XMLDocumentHandler.hpp>
  69. #include <xercesc/framework/XMLEntityHandler.hpp>
  70. #include <xercesc/framework/XMLPScanToken.hpp>
  71. #include <xercesc/internal/EndOfEntityException.hpp>
  72. #include <xercesc/validators/common/GrammarResolver.hpp>
  73. #include <xercesc/validators/DTD/DocTypeHandler.hpp>
  74. #include <xercesc/validators/DTD/DTDScanner.hpp>
  75. #include <xercesc/validators/DTD/DTDValidator.hpp>
  76. XERCES_CPP_NAMESPACE_BEGIN
  77. // ---------------------------------------------------------------------------
  78. //  DGXMLScanner: Constructors and Destructor
  79. // ---------------------------------------------------------------------------
  80. DGXMLScanner::DGXMLScanner(XMLValidator* const valToAdopt, MemoryManager* const manager) :
  81.     XMLScanner(valToAdopt, manager)
  82.     , fElemStack(manager)
  83.     , fAttrNSList(0)
  84.     , fDTDValidator(0)
  85.     , fDTDGrammar(0)
  86. {
  87.     try
  88.     {
  89.         commonInit();
  90.         if (valToAdopt)
  91.         {
  92.             if (!valToAdopt->handlesDTD())
  93.                ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  94.         }
  95.         else
  96.         {
  97.             fValidator = fDTDValidator;
  98.         }
  99.     }
  100.     catch(...)
  101.     {
  102.         cleanUp();
  103.         throw;
  104.     }
  105. }
  106. DGXMLScanner::DGXMLScanner( XMLDocumentHandler* const docHandler
  107.                           , DocTypeHandler* const     docTypeHandler
  108.                           , XMLEntityHandler* const   entityHandler
  109.                           , XMLErrorReporter* const   errHandler
  110.                           , XMLValidator* const       valToAdopt
  111.                           , MemoryManager* const      manager) :
  112.     XMLScanner(docHandler, docTypeHandler, entityHandler, errHandler, valToAdopt, manager)
  113.     , fElemStack(manager)
  114.     , fAttrNSList(0)
  115.     , fDTDValidator(0)
  116.     , fDTDGrammar(0)
  117. {
  118.     try
  119.     {
  120.         commonInit();
  121.         if (valToAdopt)
  122.         {
  123.             if (!valToAdopt->handlesDTD())
  124.                ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  125.         }
  126.         else
  127.         {
  128.             fValidator = fDTDValidator;
  129.         }
  130.     }
  131.     catch(...)
  132.     {
  133.         cleanUp();
  134.         throw;
  135.     }
  136. }
  137. DGXMLScanner::~DGXMLScanner()
  138. {
  139.     cleanUp();
  140. }
  141. // ---------------------------------------------------------------------------
  142. //  XMLScanner: Getter methods
  143. // ---------------------------------------------------------------------------
  144. NameIdPool<DTDEntityDecl>* DGXMLScanner::getEntityDeclPool()
  145. {
  146.     return ((DTDGrammar*)fGrammar)->getEntityDeclPool();
  147. }
  148. const NameIdPool<DTDEntityDecl>* DGXMLScanner::getEntityDeclPool() const
  149. {
  150.     return ((DTDGrammar*)fGrammar)->getEntityDeclPool();
  151. }
  152. // ---------------------------------------------------------------------------
  153. //  DGXMLScanner: Main entry point to scan a document
  154. // ---------------------------------------------------------------------------
  155. void DGXMLScanner::scanDocument(const InputSource& src)
  156. {
  157.     //  Bump up the sequence id for this parser instance. This will invalidate
  158.     //  any previous progressive scan tokens.
  159.     fSequenceId++;
  160.     try
  161.     {
  162.         //  Reset the scanner and its plugged in stuff for a new run. This
  163.         //  resets all the data structures, creates the initial reader and
  164.         //  pushes it on the stack, and sets up the base document path.
  165.         scanReset(src);
  166.         // If we have a document handler, then call the start document
  167.         if (fDocHandler)
  168.             fDocHandler->startDocument();
  169.         //  Scan the prolog part, which is everything before the root element
  170.         //  including the DTD subsets.
  171.         scanProlog();
  172.         //  If we got to the end of input, then its not a valid XML file.
  173.         //  Else, go on to scan the content.
  174.         if (fReaderMgr.atEOF())
  175.         {
  176.             emitError(XMLErrs::EmptyMainEntity);
  177.         }
  178.         else
  179.         {
  180.             // Scan content, and tell it its not an external entity
  181.             if (scanContent(false))
  182.             {
  183.                 // Do post-parse validation if required
  184.                 if (fValidate)
  185.                 {
  186.                     //  We handle ID reference semantics at this level since
  187.                     //  its required by XML 1.0.
  188.                     checkIDRefs();
  189.                     // Then allow the validator to do any extra stuff it wants
  190. //                    fValidator->postParseValidation();
  191.                 }
  192.                 // That went ok, so scan for any miscellaneous stuff
  193.                 if (!fReaderMgr.atEOF())
  194.                     scanMiscellaneous();
  195.             }
  196.         }
  197.         // If we have a document handler, then call the end document
  198.         if (fDocHandler)
  199.             fDocHandler->endDocument();
  200.         // Reset the reader manager to close all files, sockets, etc...
  201.         fReaderMgr.reset();
  202.     }
  203.     //  NOTE:
  204.     //
  205.     //  In all of the error processing below, the emitError() call MUST come
  206.     //  before the flush of the reader mgr, or it will fail because it tries
  207.     //  to find out the position in the XML source of the error.
  208.     catch(const XMLErrs::Codes)
  209.     {
  210.         // This is a 'first fatal error' type exit, so reset and fall through
  211.         fReaderMgr.reset();
  212.     }
  213.     catch(const XMLValid::Codes)
  214.     {
  215.         // This is a 'first fatal error' type exit, so reset and fall through
  216.         fReaderMgr.reset();
  217.     }
  218.     catch(const XMLException& excToCatch)
  219.     {
  220.         //  Emit the error and catch any user exception thrown from here. Make
  221.         //  sure in all cases we flush the reader manager.
  222.         fInException = true;
  223.         try
  224.         {
  225.             if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
  226.                 emitError
  227.                 (
  228.                     XMLErrs::XMLException_Warning
  229.                     , excToCatch.getType()
  230.                     , excToCatch.getMessage()
  231.                 );
  232.             else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
  233.                 emitError
  234.                 (
  235.                     XMLErrs::XMLException_Fatal
  236.                     , excToCatch.getType()
  237.                     , excToCatch.getMessage()
  238.                 );
  239.             else
  240.                 emitError
  241.                 (
  242.                     XMLErrs::XMLException_Error
  243.                     , excToCatch.getType()
  244.                     , excToCatch.getMessage()
  245.                 );
  246.         }
  247.         catch(...)
  248.         {
  249.             // Flush the reader manager and rethrow user's error
  250.             fReaderMgr.reset();
  251.             throw;
  252.         }
  253.         // If it returned, then reset the reader manager and fall through
  254.         fReaderMgr.reset();
  255.     }
  256.     catch(...)
  257.     {
  258.         // Reset and rethrow
  259.         fReaderMgr.reset();
  260.         throw;
  261.     }
  262. }
  263. bool DGXMLScanner::scanNext(XMLPScanToken& token)
  264. {
  265.     // Make sure this token is still legal
  266.     if (!isLegalToken(token))
  267.         ThrowXML(RuntimeException, XMLExcepts::Scan_BadPScanToken);
  268.     // Find the next token and remember the reader id
  269.     unsigned int orgReader;
  270.     XMLTokens curToken;
  271.     bool retVal = true;
  272.     try
  273.     {
  274.         while (true)
  275.         {
  276.             //  We have to handle any end of entity exceptions that happen here.
  277.             //  We could be at the end of X nested entities, each of which will
  278.             //  generate an end of entity exception as we try to move forward.
  279.             try
  280.             {
  281.                 curToken = senseNextToken(orgReader);
  282.                 break;
  283.             }
  284.             catch(const EndOfEntityException& toCatch)
  285.             {
  286.                 // Send an end of entity reference event
  287.                 if (fDocHandler)
  288.                     fDocHandler->endEntityReference(toCatch.getEntity());
  289.             }
  290.         }
  291.         if (curToken == Token_CharData)
  292.         {
  293.             scanCharData(fCDataBuf);
  294.         }
  295.         else if (curToken == Token_EOF)
  296.         {
  297.             if (!fElemStack.isEmpty())
  298.             {
  299.                 const ElemStack::StackElem* topElem = fElemStack.popTop();
  300.                 emitError
  301.                 (
  302.                     XMLErrs::EndedWithTagsOnStack
  303.                     , topElem->fThisElement->getFullName()
  304.                 );
  305.             }
  306.             retVal = false;
  307.         }
  308.         else
  309.         {
  310.             // Its some sort of markup
  311.             bool gotData = true;
  312.             switch(curToken)
  313.             {
  314.                 case Token_CData :
  315.                     // Make sure we are within content
  316.                     if (fElemStack.isEmpty())
  317.                         emitError(XMLErrs::CDATAOutsideOfContent);
  318.                     scanCDSection();
  319.                     break;
  320.                 case Token_Comment :
  321.                     scanComment();
  322.                     break;
  323.                 case Token_EndTag :
  324.                     scanEndTag(gotData);
  325.                     break;
  326.                 case Token_PI :
  327.                     scanPI();
  328.                     break;
  329.                 case Token_StartTag :
  330.                     scanStartTag(gotData);
  331.                     break;
  332.                 default :
  333.                     fReaderMgr.skipToChar(chOpenAngle);
  334.                     break;
  335.             }
  336.             if (orgReader != fReaderMgr.getCurrentReaderNum())
  337.                 emitError(XMLErrs::PartialMarkupInEntity);
  338.             // If we hit the end, then do the miscellaneous part
  339.             if (!gotData)
  340.             {
  341.                 // Do post-parse validation if required
  342.                 if (fValidate)
  343.                 {
  344.                     //  We handle ID reference semantics at this level since
  345.                     //  its required by XML 1.0.
  346.                     checkIDRefs();
  347.                     // Then allow the validator to do any extra stuff it wants
  348. //                    fValidator->postParseValidation();
  349.                 }
  350.                 // That went ok, so scan for any miscellaneous stuff
  351.                 scanMiscellaneous();
  352.                 if (fDocHandler)
  353.                     fDocHandler->endDocument();
  354.             }
  355.         }
  356.     }
  357.     //  NOTE:
  358.     //
  359.     //  In all of the error processing below, the emitError() call MUST come
  360.     //  before the flush of the reader mgr, or it will fail because it tries
  361.     //  to find out the position in the XML source of the error.
  362.     catch(const XMLErrs::Codes)
  363.     {
  364.         // This is a 'first failure' exception, so reset and return failure
  365.         fReaderMgr.reset();
  366.         return false;
  367.     }
  368.     catch(const XMLValid::Codes)
  369.     {
  370.         // This is a 'first fatal error' type exit, so reset and reuturn failure
  371.         fReaderMgr.reset();
  372.         return false;
  373.     }
  374.     catch(const XMLException& excToCatch)
  375.     {
  376.         //  Emit the error and catch any user exception thrown from here. Make
  377.         //  sure in all cases we flush the reader manager.
  378.         fInException = true;
  379.         try
  380.         {
  381.             if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
  382.                 emitError
  383.                 (
  384.                     XMLErrs::XMLException_Warning
  385.                     , excToCatch.getType()
  386.                     , excToCatch.getMessage()
  387.                 );
  388.             else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
  389.                 emitError
  390.                 (
  391.                     XMLErrs::XMLException_Fatal
  392.                     , excToCatch.getType()
  393.                     , excToCatch.getMessage()
  394.                 );
  395.             else
  396.                 emitError
  397.                 (
  398.                     XMLErrs::XMLException_Error
  399.                     , excToCatch.getType()
  400.                     , excToCatch.getMessage()
  401.                 );
  402.         }
  403.         catch(...)
  404.         {
  405.             // Reset and rethrow user error
  406.             fReaderMgr.reset();
  407.             throw;
  408.         }
  409.         // Reset and return failure
  410.         fReaderMgr.reset();
  411.         return false;
  412.     }
  413.     catch(...)
  414.     {
  415.         // Reset and rethrow original error
  416.         fReaderMgr.reset();
  417.         throw;
  418.     }
  419.     // If we hit the end, then flush the reader manager
  420.     if (!retVal)
  421.         fReaderMgr.reset();
  422.     return retVal;
  423. }
  424. // ---------------------------------------------------------------------------
  425. //  DGXMLScanner: Private scanning methods
  426. // ---------------------------------------------------------------------------
  427. //  This method will kick off the scanning of the primary content of the
  428. //  document, i.e. the elements.
  429. bool DGXMLScanner::scanContent(const bool extEntity)
  430. {
  431.     //  Go into a loop until we hit the end of the root element, or we fall
  432.     //  out because there is no root element.
  433.     //
  434.     //  We have to do kind of a deeply nested double loop here in order to
  435.     //  avoid doing the setup/teardown of the exception handler on each
  436.     //  round. Doing it this way we only do it when an exception actually
  437.     //  occurs.
  438.     bool gotData = true;
  439.     bool inMarkup = false;
  440.     while (gotData)
  441.     {
  442.         try
  443.         {
  444.             while (gotData)
  445.             {
  446.                 //  Sense what the next top level token is. According to what
  447.                 //  this tells us, we will call something to handle that kind
  448.                 //  of thing.
  449.                 unsigned int orgReader;
  450.                 const XMLTokens curToken = senseNextToken(orgReader);
  451.                 //  Handle character data and end of file specially. Char data
  452.                 //  is not markup so we don't want to handle it in the loop
  453.                 //  below.
  454.                 if (curToken == Token_CharData)
  455.                 {
  456.                     //  Scan the character data and call appropriate events. Let
  457.                     //  him use our local character data buffer for efficiency.
  458.                     scanCharData(fCDataBuf);
  459.                     continue;
  460.                 }
  461.                 else if (curToken == Token_EOF)
  462.                 {
  463.                     //  The element stack better be empty at this point or we
  464.                     //  ended prematurely before all elements were closed.
  465.                     if (!fElemStack.isEmpty())
  466.                     {
  467.                         const ElemStack::StackElem* topElem = fElemStack.popTop();
  468.                         emitError
  469.                         (
  470.                             XMLErrs::EndedWithTagsOnStack
  471.                             , topElem->fThisElement->getFullName()
  472.                         );
  473.                     }
  474.                     // Its the end of file, so clear the got data flag
  475.                     gotData = false;
  476.                     continue;
  477.                 }
  478.                 // We are in some sort of markup now
  479.                 inMarkup = true;
  480.                 //  According to the token we got, call the appropriate
  481.                 //  scanning method.
  482.                 switch(curToken)
  483.                 {
  484.                     case Token_CData :
  485.                         // Make sure we are within content
  486.                         if (fElemStack.isEmpty())
  487.                             emitError(XMLErrs::CDATAOutsideOfContent);
  488.                         scanCDSection();
  489.                         break;
  490.                     case Token_Comment :
  491.                         scanComment();
  492.                         break;
  493.                     case Token_EndTag :
  494.                         scanEndTag(gotData);
  495.                         break;
  496.                     case Token_PI :
  497.                         scanPI();
  498.                         break;
  499.                     case Token_StartTag :
  500.                         scanStartTag(gotData);
  501.                         break;
  502.                     default :
  503.                         fReaderMgr.skipToChar(chOpenAngle);
  504.                         break;
  505.                 }
  506.                 if (orgReader != fReaderMgr.getCurrentReaderNum())
  507.                     emitError(XMLErrs::PartialMarkupInEntity);
  508.                 // And we are back out of markup again
  509.                 inMarkup = false;
  510.             }
  511.         }
  512.         catch(const EndOfEntityException& toCatch)
  513.         {
  514.             //  If we were in some markup when this happened, then its a
  515.             //  partial markup error.
  516.             if (inMarkup)
  517.                 emitError(XMLErrs::PartialMarkupInEntity);
  518.             // Send an end of entity reference event
  519.             if (fDocHandler)
  520.                 fDocHandler->endEntityReference(toCatch.getEntity());
  521.             inMarkup = false;
  522.         }
  523.     }
  524.     // It went ok, so return success
  525.     return true;
  526. }
  527. void DGXMLScanner::scanEndTag(bool& gotData)
  528. {
  529.     //  Assume we will still have data until proven otherwise. It will only
  530.     //  ever be false if this is the end of the root element.
  531.     gotData = true;
  532.     //  Check if the element stack is empty. If so, then this is an unbalanced
  533.     //  element (i.e. more ends than starts, perhaps because of bad text
  534.     //  causing one to be skipped.)
  535.     if (fElemStack.isEmpty())
  536.     {
  537.         emitError(XMLErrs::MoreEndThanStartTags);
  538.         fReaderMgr.skipPastChar(chCloseAngle);
  539.         ThrowXML(RuntimeException, XMLExcepts::Scan_UnbalancedStartEnd);
  540.     }
  541.     // After the </ is the element QName, so get a name from the input
  542.     if (!fReaderMgr.getName(fQNameBuf))
  543.     {
  544.         // It failed so we can't really do anything with it
  545.         emitError(XMLErrs::ExpectedElementName);
  546.         fReaderMgr.skipPastChar(chCloseAngle);
  547.         return;
  548.     }
  549.     // Resolve element name uri if needed
  550.     unsigned int uriId = fEmptyNamespaceId;
  551.     const ElemStack::StackElem* topElem = fElemStack.topElement();
  552.     if (fDoNamespaces)
  553.     {
  554.         uriId = resolvePrefix
  555.         (
  556.             topElem->fThisElement->getElementName()->getPrefix()
  557.             , ElemStack::Mode_Element
  558.         );
  559.     }
  560.     //  Pop the stack of the element we are supposed to be ending. Remember
  561.     //  that we don't own this. The stack just keeps them and reuses them.
  562.     fElemStack.popTop();
  563.     // See if it was the root element, to avoid multiple calls below
  564.     const bool isRoot = fElemStack.isEmpty();
  565.     // Make sure that its the end of the element that we expect
  566.     if (!XMLString::equals(topElem->fThisElement->getFullName(), fQNameBuf.getRawBuffer()))
  567.     {
  568.         emitError
  569.         (
  570.             XMLErrs::ExpectedEndOfTagX
  571.             , topElem->fThisElement->getFullName()
  572.         );
  573.     }
  574.     // Make sure we are back on the same reader as where we started
  575.     if (topElem->fReaderNum != fReaderMgr.getCurrentReaderNum())
  576.         emitError(XMLErrs::PartialTagMarkupError);
  577.     // Skip optional whitespace
  578.     fReaderMgr.skipPastSpaces();
  579.     // Make sure we find the closing bracket
  580.     if (!fReaderMgr.skippedChar(chCloseAngle))
  581.     {
  582.         emitError
  583.         (
  584.             XMLErrs::UnterminatedEndTag
  585.             , topElem->fThisElement->getFullName()
  586.         );
  587.     }
  588.     //  If validation is enabled, then lets pass him the list of children and
  589.     //  this element and let him validate it.
  590.     if (fValidate)
  591.     {
  592.         int res = fValidator->checkContent
  593.         (
  594.             topElem->fThisElement
  595.             , topElem->fChildren
  596.             , topElem->fChildCount
  597.         );
  598.         if (res >= 0)
  599.         {
  600.             //  One of the elements is not valid for the content. NOTE that
  601.             //  if no children were provided but the content model requires
  602.             //  them, it comes back with a zero value. But we cannot use that
  603.             //  to index the child array in this case, and have to put out a
  604.             //  special message.
  605.             if (!topElem->fChildCount)
  606.             {
  607.                 fValidator->emitError
  608.                 (
  609.                     XMLValid::EmptyNotValidForContent
  610.                     , topElem->fThisElement->getFormattedContentModel()
  611.                 );
  612.             }
  613.             else if ((unsigned int)res >= topElem->fChildCount)
  614.             {
  615.                 fValidator->emitError
  616.                 (
  617.                     XMLValid::NotEnoughElemsForCM
  618.                     , topElem->fThisElement->getFormattedContentModel()
  619.                 );
  620.             }
  621.             else
  622.             {
  623.                 fValidator->emitError
  624.                 (
  625.                     XMLValid::ElementNotValidForContent
  626.                     , topElem->fChildren[res]->getRawName()
  627.                     , topElem->fThisElement->getFormattedContentModel()
  628.                 );
  629.             }
  630.         }
  631.     }
  632.     // If we have a doc handler, tell it about the end tag
  633.     if (fDocHandler)
  634.     {
  635.         fDocHandler->endElement
  636.         (
  637.             *topElem->fThisElement
  638.             , uriId
  639.             , isRoot
  640.             , (fDoNamespaces)
  641.                 ? topElem->fThisElement->getElementName()->getPrefix()
  642.                 : XMLUni::fgZeroLenString
  643.         );
  644.     }
  645.     // If this was the root, then done with content
  646.     gotData = !isRoot;
  647. }
  648. //  This method handles the high level logic of scanning the DOCType
  649. //  declaration. This calls the DTDScanner and kicks off both the scanning of
  650. //  the internal subset and the scanning of the external subset, if any.
  651. //
  652. //  When we get here the '<!DOCTYPE' part has already been scanned, which is
  653. //  what told us that we had a doc type decl to parse.
  654. void DGXMLScanner::scanDocTypeDecl()
  655. {
  656.     if (fDocTypeHandler)
  657.         fDocTypeHandler->resetDocType();
  658.     // There must be some space after DOCTYPE
  659.     if (!fReaderMgr.skipPastSpaces())
  660.     {
  661.         emitError(XMLErrs::ExpectedWhitespace);
  662.         // Just skip the Doctype declaration and return
  663.         fReaderMgr.skipPastChar(chCloseAngle);
  664.         return;
  665.     }
  666.     // Get a buffer for the root element
  667.     XMLBufBid bbRootName(&fBufMgr);
  668.     //  Get a name from the input, which should be the name of the root
  669.     //  element of the upcoming content.
  670.     fReaderMgr.getName(bbRootName.getBuffer());
  671.     if (bbRootName.isEmpty())
  672.     {
  673.         emitError(XMLErrs::NoRootElemInDOCTYPE);
  674.         fReaderMgr.skipPastChar(chCloseAngle);
  675.         return;
  676.     }
  677.     //  Store the root element name for later check
  678.     setRootElemName(bbRootName.getRawBuffer());
  679.     //  This element obviously is not going to exist in the element decl
  680.     //  pool yet, but we need to call docTypeDecl. So force it into
  681.     //  the element decl pool, marked as being there because it was in
  682.     //  the DOCTYPE. Later, when its declared, the status will be updated.
  683.     //
  684.     //  Only do this if we are not reusing the validator! If we are reusing,
  685.     //  then look it up instead. It has to exist!
  686.     DTDElementDecl* rootDecl = new (fMemoryManager) DTDElementDecl
  687.     (
  688.         bbRootName.getRawBuffer()
  689.         , fEmptyNamespaceId
  690.         , DTDElementDecl::Any
  691.         , fMemoryManager
  692.     );
  693.     rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  694.     rootDecl->setExternalElemDeclaration(true);
  695.     ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl));
  696.     // Skip any spaces after the name
  697.     fReaderMgr.skipPastSpaces();
  698.     //  And now if we are looking at a >, then we are done. It is not
  699.     //  required to have an internal or external subset, though why you
  700.     //  would not escapes me.
  701.     if (fReaderMgr.skippedChar(chCloseAngle)) {
  702.         //  If we have a doc type handler and advanced callbacks are enabled,
  703.         //  call the doctype event.
  704.         if (fDocTypeHandler)
  705.             fDocTypeHandler->doctypeDecl(*rootDecl, 0, 0, false);
  706.         return;
  707.     }
  708.     // either internal/external subset
  709.     if (fValScheme == Val_Auto && !fValidate)
  710.         fValidate = true;
  711.     bool    hasIntSubset = false;
  712.     bool    hasExtSubset = false;
  713.     XMLCh*  sysId = 0;
  714.     XMLCh*  pubId = 0;
  715.     DTDScanner dtdScanner
  716.     (
  717.         (DTDGrammar*) fGrammar
  718.         , fDocTypeHandler
  719.         , fMemoryManager
  720.     );
  721.     dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
  722.     //  If the next character is '[' then we have no external subset cause
  723.     //  there is no system id, just the opening character of the internal
  724.     //  subset. Else, has to be an id.
  725.     //
  726.     // Just look at the next char, don't eat it.
  727.     if (fReaderMgr.peekNextChar() == chOpenSquare)
  728.     {
  729.         hasIntSubset = true;
  730.     }
  731.     else
  732.     {
  733.         // Indicate we have an external subset
  734.         hasExtSubset = true;
  735.         fHasNoDTD = false;
  736.         // Get buffers for the ids
  737.         XMLBufBid bbPubId(&fBufMgr);
  738.         XMLBufBid bbSysId(&fBufMgr);
  739.         // Get the external subset id
  740.         if (!dtdScanner.scanId(bbPubId.getBuffer(), bbSysId.getBuffer(), DTDScanner::IDType_External))
  741.         {
  742.             fReaderMgr.skipPastChar(chCloseAngle);
  743.             return;
  744.         }
  745.         // Get copies of the ids we got
  746.         pubId = XMLString::replicate(bbPubId.getRawBuffer(), fMemoryManager);
  747.         sysId = XMLString::replicate(bbSysId.getRawBuffer(), fMemoryManager);
  748.         // Skip spaces and check again for the opening of an internal subset
  749.         fReaderMgr.skipPastSpaces();
  750.         // Just look at the next char, don't eat it.
  751.         if (fReaderMgr.peekNextChar() == chOpenSquare) {
  752.             hasIntSubset = true;
  753.         }
  754.     }
  755.     // Insure that the ids get cleaned up, if they got allocated
  756.     ArrayJanitor<XMLCh> janSysId(sysId, fMemoryManager);
  757.     ArrayJanitor<XMLCh> janPubId(pubId, fMemoryManager);
  758.     //  If we have a doc type handler and advanced callbacks are enabled,
  759.     //  call the doctype event.
  760.     if (fDocTypeHandler)
  761.         fDocTypeHandler->doctypeDecl(*rootDecl, pubId, sysId, hasIntSubset, hasExtSubset);
  762.     //  Ok, if we had an internal subset, we are just past the [ character
  763.     //  and need to parse that first.
  764.     if (hasIntSubset)
  765.     {
  766.         // Eat the opening square bracket
  767.         fReaderMgr.getNextChar();
  768.         // We can't have any internal subset if we are reusing the validator
  769.         if (fUseCachedGrammar || fToCacheGrammar)
  770.             ThrowXML(RuntimeException, XMLExcepts::Val_CantHaveIntSS);
  771.         //  And try to scan the internal subset. If we fail, try to recover
  772.         //  by skipping forward tot he close angle and returning.
  773.         if (!dtdScanner.scanInternalSubset())
  774.         {
  775.             fReaderMgr.skipPastChar(chCloseAngle);
  776.             return;
  777.         }
  778.         //  Do a sanity check that some expanded PE did not propogate out of
  779.         //  the doctype. This could happen if it was terminated early by bad
  780.         //  syntax.
  781.         if (fReaderMgr.getReaderDepth() > 1)
  782.         {
  783.             emitError(XMLErrs::PEPropogated);
  784.             // Ask the reader manager to pop back down to the main level
  785.             fReaderMgr.cleanStackBackTo(1);
  786.         }
  787.         fReaderMgr.skipPastSpaces();
  788.     }
  789.     // And that should leave us at the closing > of the DOCTYPE line
  790.     if (!fReaderMgr.skippedChar(chCloseAngle))
  791.     {
  792.         //  Do a special check for the common scenario of an extra ] char at
  793.         //  the end. This is easy to recover from.
  794.         if (fReaderMgr.skippedChar(chCloseSquare)
  795.         &&  fReaderMgr.skippedChar(chCloseAngle))
  796.         {
  797.             emitError(XMLErrs::ExtraCloseSquare);
  798.         }
  799.          else
  800.         {
  801.             emitError(XMLErrs::UnterminatedDOCTYPE);
  802.             fReaderMgr.skipPastChar(chCloseAngle);
  803.         }
  804.     }
  805.     //  If we had an external subset, then we need to deal with that one
  806.     //  next. If we are reusing the validator, then don't scan it.
  807.     if (hasExtSubset) {
  808.         if (fUseCachedGrammar)
  809.         {
  810.             InputSource* sysIdSrc = resolveSystemId(sysId);
  811.             Janitor<InputSource> janSysIdSrc(sysIdSrc);
  812.             Grammar* grammar = fGrammarResolver->getGrammar(sysIdSrc->getSystemId());
  813.             if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType) {
  814.                 fDTDGrammar = (DTDGrammar*) grammar;
  815.                 fGrammar = fDTDGrammar;
  816.                 fValidator->setGrammar(fGrammar);
  817.                 rootDecl = (DTDElementDecl*) fGrammar->getElemDecl(fEmptyNamespaceId, 0, bbRootName.getRawBuffer(), Grammar::TOP_LEVEL_SCOPE);
  818.                 if (rootDecl)
  819.                     ((DTDGrammar*)fGrammar)->setRootElemId(rootDecl->getId());
  820.                 else {
  821.                     rootDecl = new (fMemoryManager) DTDElementDecl
  822.                     (
  823.                         bbRootName.getRawBuffer()
  824.                         , fEmptyNamespaceId
  825.                         , DTDElementDecl::Any
  826.                         , fMemoryManager
  827.                     );
  828.                     rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  829.                     rootDecl->setExternalElemDeclaration(true);
  830.                     ((DTDGrammar*)fGrammar)->setRootElemId(fGrammar->putElemDecl(rootDecl));
  831.                 }
  832.                 return;
  833.             }
  834.         }
  835.         if (fLoadExternalDTD || fValidate)
  836.         {
  837.             // And now create a reader to read this entity
  838.             InputSource* srcUsed;
  839.             XMLReader* reader = fReaderMgr.createReader
  840.             (
  841.                 sysId
  842.                 , pubId
  843.                 , false
  844.                 , XMLReader::RefFrom_NonLiteral
  845.                 , XMLReader::Type_General
  846.                 , XMLReader::Source_External
  847.                 , srcUsed
  848.                 , fCalculateSrcOfs
  849.             );
  850.             // Put a janitor on the input source
  851.             Janitor<InputSource> janSrc(srcUsed);
  852.             //  If it failed then throw an exception
  853.             if (!reader)
  854.                 ThrowXML1(RuntimeException, XMLExcepts::Gen_CouldNotOpenDTD, srcUsed->getSystemId());
  855.             if (fToCacheGrammar) {
  856.                 unsigned int stringId = fGrammarResolver->getStringPool()->addOrFind(srcUsed->getSystemId());
  857.                 const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(stringId);
  858.                 fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
  859.                 fGrammarResolver->putGrammar(sysIdStr, fGrammar);
  860.             }
  861.             //  In order to make the processing work consistently, we have to
  862.             //  make this look like an external entity. So create an entity
  863.             //  decl and fill it in and push it with the reader, as happens
  864.             //  with an external entity. Put a janitor on it to insure it gets
  865.             //  cleaned up. The reader manager does not adopt them.
  866.             const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
  867.             DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
  868.             declDTD->setSystemId(sysId);
  869.             Janitor<DTDEntityDecl> janDecl(declDTD);
  870.             // Mark this one as a throw at end
  871.             reader->setThrowAtEnd(true);
  872.             // And push it onto the stack, with its pseudo name
  873.             fReaderMgr.pushReader(reader, declDTD);
  874.             // Tell it its not in an include section
  875.             dtdScanner.scanExtSubsetDecl(false, true);
  876.         }
  877.     }
  878. }
  879. bool DGXMLScanner::scanStartTag(bool& gotData)
  880. {
  881.     //  Assume we will still have data until proven otherwise. It will only
  882.     //  ever be false if this is the root and its empty.
  883.     gotData = true;
  884.     //  Get the QName. In this case, we are not doing namespaces, so we just
  885.     //  use it as is and don't have to break it into parts.
  886.     if (!fReaderMgr.getName(fQNameBuf))
  887.     {
  888.         emitError(XMLErrs::ExpectedElementName);
  889.         fReaderMgr.skipToChar(chOpenAngle);
  890.         return false;
  891.     }
  892.     // Assume it won't be an empty tag
  893.     bool isEmpty = false;
  894.     // See if its the root element
  895.     const bool isRoot = fElemStack.isEmpty();
  896.     //  Lets try to look up the element in the validator's element decl pool
  897.     //  We can pass bogus values for the URI id and the base name. We know that
  898.     //  this can only be called if we are doing a DTD style validator and that
  899.     //  he will only look at the QName.
  900.     //
  901.     //  We tell him to fault in a decl if he does not find one.
  902.     bool wasAdded = false;
  903.     const XMLCh* qnameRawBuf = fQNameBuf.getRawBuffer();
  904.     XMLElementDecl* elemDecl = fGrammar->findOrAddElemDecl
  905.     (
  906.         fEmptyNamespaceId
  907.         , 0
  908.         , 0
  909.         , qnameRawBuf
  910.         , Grammar::TOP_LEVEL_SCOPE
  911.         , wasAdded
  912.     );
  913.     if (fValidate) {
  914.         if (wasAdded)
  915.         {
  916.             // This is to tell the reuse Validator that this element was
  917.             // faulted-in, was not an element in the validator pool originally
  918.             elemDecl->setCreateReason(XMLElementDecl::JustFaultIn);
  919.             fValidator->emitError
  920.             (
  921.                 XMLValid::ElementNotDefined
  922.                 , qnameRawBuf
  923.             );
  924.         }
  925.         // If its not marked declared, then emit an error
  926.         else if (!elemDecl->isDeclared())
  927.         {
  928.             fValidator->emitError
  929.             (
  930.                 XMLValid::ElementNotDefined
  931.                 , qnameRawBuf
  932.             );
  933.         }
  934.         fValidator->validateElement(elemDecl);
  935.     }
  936.     // Expand the element stack and add the new element
  937.     fElemStack.addLevel(elemDecl, fReaderMgr.getCurrentReaderNum());
  938.     //  If this is the first element and we are validating, check the root
  939.     //  element.
  940.     if (isRoot)
  941.     {
  942.         fRootGrammar = fGrammar;
  943.         if (fValidate)
  944.         {
  945.             //  If a DocType exists, then check if it matches the root name there.
  946.             if (fRootElemName && !XMLString::equals(qnameRawBuf, fRootElemName))
  947.                 fValidator->emitError(XMLValid::RootElemNotLikeDocType);
  948.             //  Some validators may also want to check the root, call the
  949.             //  XMLValidator::checkRootElement
  950.             if (fValidatorFromUser && !fValidator->checkRootElement(elemDecl->getId()))
  951.                 fValidator->emitError(XMLValid::RootElemNotLikeDocType);
  952.         }
  953.     }
  954.     else if (fValidate)
  955.     {
  956.         //  If the element stack is not empty, then add this element as a
  957.         //  child of the previous top element. If its empty, this is the root
  958.         //  elem and is not the child of anything.
  959.         fElemStack.addChild(elemDecl->getElementName(), true);
  960.     }
  961.     // Skip any whitespace after the name
  962.     fReaderMgr.skipPastSpaces();
  963.     //  We loop until we either see a /> or >, handling attribute/value
  964.     //  pairs until we get there.
  965.     unsigned int    attCount = 0;
  966.     unsigned int    curAttListSize = fAttrList->size();
  967.     while (true)
  968.     {
  969.         // And get the next non-space character
  970.         XMLCh nextCh = fReaderMgr.peekNextChar();
  971.         //  If the next character is not a slash or closed angle bracket,
  972.         //  then it must be whitespace, since whitespace is required
  973.         //  between the end of the last attribute and the name of the next
  974.         //  one.
  975.         if (attCount)
  976.         {
  977.             if ((nextCh != chForwardSlash) && (nextCh != chCloseAngle))
  978.             {
  979.                 if (fReaderMgr.getCurrentReader()->isWhitespace(nextCh))
  980.                 {
  981.                     // Ok, skip by them and peek another char
  982.                     fReaderMgr.skipPastSpaces();
  983.                     nextCh = fReaderMgr.peekNextChar();
  984.                 }
  985.                  else
  986.                 {
  987.                     // Emit the error but keep on going
  988.                     emitError(XMLErrs::ExpectedWhitespace);
  989.                 }
  990.             }
  991.         }
  992.         //  Ok, here we first check for any of the special case characters.
  993.         //  If its not one, then we do the normal case processing, which
  994.         //  assumes that we've hit an attribute value, Otherwise, we do all
  995.         //  the special case checks.
  996.         if (!fReaderMgr.getCurrentReader()->isSpecialStartTagChar(nextCh))
  997.         {
  998.             //  Assume its going to be an attribute, so get a name from
  999.             //  the input.
  1000.             if (!fReaderMgr.getName(fAttNameBuf))
  1001.             {
  1002.                 emitError(XMLErrs::ExpectedAttrName);
  1003.                 fReaderMgr.skipPastChar(chCloseAngle);
  1004.                 return false;
  1005.             }
  1006.             // And next must be an equal sign
  1007.             if (!scanEq())
  1008.             {
  1009.                 static const XMLCh tmpList[] =
  1010.                 {
  1011.                     chSingleQuote, chDoubleQuote, chCloseAngle
  1012.                     , chOpenAngle, chForwardSlash, chNull
  1013.                 };
  1014.                 emitError(XMLErrs::ExpectedEqSign);
  1015.                 //  Try to sync back up by skipping forward until we either
  1016.                 //  hit something meaningful.
  1017.                 const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList);
  1018.                 if ((chFound == chCloseAngle) || (chFound == chForwardSlash))
  1019.                 {
  1020.                     // Jump back to top for normal processing of these
  1021.                     continue;
  1022.                 }
  1023.                 else if ((chFound == chSingleQuote)
  1024.                       ||  (chFound == chDoubleQuote)
  1025.                       ||  fReaderMgr.getCurrentReader()->isWhitespace(chFound))
  1026.                 {
  1027.                     // Just fall through assuming that the value is to follow
  1028.                 }
  1029.                 else if (chFound == chOpenAngle)
  1030.                 {
  1031.                     // Assume a malformed tag and that new one is starting
  1032.                     emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName());
  1033.                     return false;
  1034.                 }
  1035.                 else
  1036.                 {
  1037.                     // Something went really wrong
  1038.                     return false;
  1039.                 }
  1040.             }
  1041.             //  See if this attribute is declared for this element. If we are
  1042.             //  not validating of course it will not be at first, but we will
  1043.             //  fault it into the pool (to avoid lots of redundant errors.)
  1044.             wasAdded = false;
  1045.             XMLAttDef* attDef = elemDecl->findAttr
  1046.             (
  1047.                 fAttNameBuf.getRawBuffer()
  1048.                 , 0
  1049.                 , 0
  1050.                 , 0
  1051.                 , XMLElementDecl::AddIfNotFound
  1052.                 , wasAdded
  1053.             );
  1054.             if (fValidate)
  1055.             {
  1056.                 if (wasAdded)
  1057.                 {
  1058.                     // This is to tell the Validator that this attribute was
  1059.                     // faulted-in, was not an attribute in the attdef originally
  1060.                     attDef->setCreateReason(XMLAttDef::JustFaultIn);
  1061.                     fValidator->emitError
  1062.                     (
  1063.                         XMLValid::AttNotDefinedForElement
  1064.                         , fAttNameBuf.getRawBuffer()
  1065.                         , qnameRawBuf
  1066.                     );
  1067.                 }
  1068.                 // If this attribute was faulted-in and first occurence,
  1069.                 // then emit an error
  1070.                 else if (attDef->getCreateReason() == XMLAttDef::JustFaultIn
  1071.                          && !attDef->getProvided())
  1072.                 {
  1073.                     fValidator->emitError
  1074.                     (
  1075.                         XMLValid::AttNotDefinedForElement
  1076.                         , fAttNameBuf.getRawBuffer()
  1077.                         , qnameRawBuf
  1078.                     );
  1079.                 }
  1080.             }
  1081.             //  If its already provided, then there are more than one of
  1082.             //  this attribute in this start tag, so emit an error.
  1083.             if (attDef->getProvided())
  1084.             {
  1085.                 emitError
  1086.                 (
  1087.                     XMLErrs::AttrAlreadyUsedInSTag
  1088.                     , attDef->getFullName()
  1089.                     , qnameRawBuf
  1090.                 );
  1091.             }
  1092.             else
  1093.             {
  1094.                 // Mark this one as already seen
  1095.                 attDef->setProvided(true);
  1096.             }
  1097.             //  Skip any whitespace before the value and then scan the att
  1098.             //  value. This will come back normalized with entity refs and
  1099.             //  char refs expanded.
  1100.             fReaderMgr.skipPastSpaces();
  1101.             if (!scanAttValue(attDef, fAttValueBuf))
  1102.             {
  1103.                 static const XMLCh tmpList[] =
  1104.                 {
  1105.                     chCloseAngle, chOpenAngle, chForwardSlash, chNull
  1106.                 };
  1107.                 emitError(XMLErrs::ExpectedAttrValue);
  1108.                 //  It failed, so lets try to get synced back up. We skip
  1109.                 //  forward until we find some whitespace or one of the
  1110.                 //  chars in our list.
  1111.                 const XMLCh chFound = fReaderMgr.skipUntilInOrWS(tmpList);
  1112.                 if ((chFound == chCloseAngle)
  1113.                 ||  (chFound == chForwardSlash)
  1114.                 ||  fReaderMgr.getCurrentReader()->isWhitespace(chFound))
  1115.                 {
  1116.                     //  Just fall through and process this attribute, though
  1117.                     //  the value will be "".
  1118.                 }
  1119.                 else if (chFound == chOpenAngle)
  1120.                 {
  1121.                     // Assume a malformed tag and that new one is starting
  1122.                     emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName());
  1123.                     return false;
  1124.                 }
  1125.                 else
  1126.                 {
  1127.                     // Something went really wrong
  1128.                     return false;
  1129.                 }
  1130.             }
  1131.             //  Now that its all stretched out, lets look at its type and
  1132.             //  determine if it has a valid value. It will output any needed
  1133.             //  errors, but we just keep going. We only need to do this if
  1134.             //  we are validating.
  1135.             if (!wasAdded && attDef->getCreateReason() != XMLAttDef::JustFaultIn)
  1136.             {
  1137.                 // Let the validator pass judgement on the attribute value
  1138.                 if (fValidate)
  1139.                 {
  1140.                     fValidator->validateAttrValue
  1141.                     (
  1142.                         attDef
  1143.                         , fAttValueBuf.getRawBuffer()
  1144.                         , false
  1145.                         , elemDecl
  1146.                     );
  1147.                 }
  1148.             }
  1149.             if (fDoNamespaces)
  1150.             {
  1151.                 //  Make sure that the name is basically well formed for namespace
  1152.                 //  enabled rules. It either has no colons, or it has one which
  1153.                 //  is neither the first or last char.
  1154.                 const int colonFirst = XMLString::indexOf(fAttNameBuf.getRawBuffer(), chColon);
  1155.                 if (colonFirst != -1)
  1156.                 {
  1157.                     const int colonLast = XMLString::lastIndexOf(fAttNameBuf.getRawBuffer(), chColon);
  1158.                     if (colonFirst != colonLast)
  1159.                     {
  1160.                         emitError(XMLErrs::TooManyColonsInName);
  1161.                         continue;
  1162.                     }
  1163.                     else if ((colonFirst == 0)
  1164.                           ||  (colonLast == (int)fAttNameBuf.getLen() - 1))
  1165.                     {
  1166.                         emitError(XMLErrs::InvalidColonPos);
  1167.                         continue;
  1168.                     }
  1169.                 }
  1170.             }
  1171.             //  Add this attribute to the attribute list that we use to
  1172.             //  pass them to the handler. We reuse its existing elements
  1173.             //  but expand it as required.
  1174.             XMLAttr* curAtt;
  1175.             if (attCount >= curAttListSize)
  1176.             {
  1177.                 if (fDoNamespaces) {
  1178.                     curAtt = new (fMemoryManager) XMLAttr
  1179.                     (
  1180.                         fEmptyNamespaceId
  1181.                         , fAttNameBuf.getRawBuffer()
  1182.                         , fAttValueBuf.getRawBuffer()
  1183.                         , attDef->getType()
  1184.                         , true
  1185.                         , fMemoryManager
  1186.                     );
  1187.                 }
  1188.                 else
  1189.                 {
  1190.                     curAtt = new (fMemoryManager) XMLAttr
  1191.                     (
  1192.                         -1
  1193.                         , fAttNameBuf.getRawBuffer()
  1194.                         , XMLUni::fgZeroLenString
  1195.                         , fAttValueBuf.getRawBuffer()
  1196.                         , attDef->getType()
  1197.                         , true
  1198.                         , fMemoryManager
  1199.                     );
  1200.                 }
  1201.                 fAttrList->addElement(curAtt);
  1202.             }
  1203.             else
  1204.             {
  1205.                 curAtt = fAttrList->elementAt(attCount);
  1206.                 if (fDoNamespaces)
  1207.                 {
  1208.                     curAtt->set
  1209.                     (
  1210.                         fEmptyNamespaceId
  1211.                         , fAttNameBuf.getRawBuffer()
  1212.                         , fAttValueBuf.getRawBuffer()
  1213.                         , attDef->getType()
  1214.                     );
  1215.                 }
  1216.                 else
  1217.                 {
  1218.                     curAtt->set
  1219.                     (
  1220.                         -1
  1221.                         , fAttNameBuf.getRawBuffer()
  1222.                         , XMLUni::fgZeroLenString
  1223.                         , fAttValueBuf.getRawBuffer()
  1224.                         , attDef->getType()
  1225.                     );
  1226.                 }
  1227.                 curAtt->setSpecified(true);
  1228.             }
  1229.             attCount++;
  1230.             // And jump back to the top of the loop
  1231.             continue;
  1232.         }
  1233.         //  It was some special case character so do all of the checks and
  1234.         //  deal with it.
  1235.         if (!nextCh)
  1236.             ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  1237.         if (nextCh == chForwardSlash)
  1238.         {
  1239.             fReaderMgr.getNextChar();
  1240.             isEmpty = true;
  1241.             if (!fReaderMgr.skippedChar(chCloseAngle))
  1242.                 emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName());
  1243.             break;
  1244.         }
  1245.         else if (nextCh == chCloseAngle)
  1246.         {
  1247.             fReaderMgr.getNextChar();
  1248.             break;
  1249.         }
  1250.         else if (nextCh == chOpenAngle)
  1251.         {
  1252.             //  Check for this one specially, since its going to be common
  1253.             //  and it is kind of auto-recovering since we've already hit the
  1254.             //  next open bracket, which is what we would have seeked to (and
  1255.             //  skipped this whole tag.)
  1256.             emitError(XMLErrs::UnterminatedStartTag, elemDecl->getFullName());
  1257.             break;
  1258.         }
  1259.         else if ((nextCh == chSingleQuote) || (nextCh == chDoubleQuote))
  1260.         {
  1261.             //  Check for this one specially, which is probably a missing
  1262.             //  attribute name, e.g. ="value". Just issue expected name
  1263.             //  error and eat the quoted string, then jump back to the
  1264.             //  top again.
  1265.             emitError(XMLErrs::ExpectedAttrName);
  1266.             fReaderMgr.getNextChar();
  1267.             fReaderMgr.skipQuotedString(nextCh);
  1268.             fReaderMgr.skipPastSpaces();
  1269.             continue;
  1270.         }
  1271.     }
  1272.     //  Make an initial pass through the list and find any xmlns attributes.
  1273.     if (fDoNamespaces && attCount)
  1274.       scanAttrListforNameSpaces(fAttrList, attCount);
  1275.     //  Now lets get the fAttrList filled in. This involves faulting in any
  1276.     //  defaulted and fixed attributes and normalizing the values of any that
  1277.     //  we got explicitly.
  1278.     //
  1279.     //  We update the attCount value with the total number of attributes, but
  1280.     //  it goes in with the number of values we got during the raw scan of
  1281.     //  explictly provided attrs above.
  1282.     attCount = buildAttList(attCount, elemDecl, *fAttrList);
  1283.     //  If we have a document handler, then tell it about this start tag. We
  1284.     //  don't have any URI id to send along, so send fEmptyNamespaceId. We also do not send
  1285.     //  any prefix since its just one big name if we are not doing namespaces.
  1286.     unsigned int uriId = fEmptyNamespaceId;
  1287.     if (fDocHandler)
  1288.     {
  1289.         if (fDoNamespaces)
  1290.         {
  1291.             uriId = resolvePrefix
  1292.             (
  1293.                 elemDecl->getElementName()->getPrefix()
  1294.                 , ElemStack::Mode_Element
  1295.             );
  1296.         }
  1297.         fDocHandler->startElement
  1298.         (
  1299.             *elemDecl
  1300.             , uriId
  1301.             , (fDoNamespaces) ? elemDecl->getElementName()->getPrefix() : 0
  1302.             , *fAttrList
  1303.             , attCount
  1304.             , false
  1305.             , isRoot
  1306.         );
  1307.     }
  1308.     //  If empty, validate content right now if we are validating and then
  1309.     //  pop the element stack top. Else, we have to update the current stack
  1310.     //  top's namespace mapping elements.
  1311.     if (isEmpty)
  1312.     {
  1313.         // If validating, then insure that its legal to have no content
  1314.         if (fValidate)
  1315.         {
  1316.             const int res = fValidator->checkContent(elemDecl, 0, 0);
  1317.             if (res >= 0)
  1318.             {
  1319.                 fValidator->emitError
  1320.                 (
  1321.                     XMLValid::ElementNotValidForContent
  1322.                     , qnameRawBuf
  1323.                     , elemDecl->getFormattedContentModel()
  1324.                 );
  1325.             }
  1326.         }
  1327.         // If we have a doc handler, tell it about the end tag
  1328.         if (fDocHandler)
  1329.         {
  1330.             fDocHandler->endElement
  1331.             (
  1332.                 *elemDecl
  1333.                 , uriId
  1334.                 , isRoot
  1335.                 , (fDoNamespaces) ? elemDecl->getElementName()->getPrefix()
  1336.                                   : XMLUni::fgZeroLenString
  1337.             );
  1338.         }
  1339.         // Pop the element stack back off since it'll never be used now
  1340.         fElemStack.popTop();
  1341.         // If the elem stack is empty, then it was an empty root
  1342.         if (isRoot)
  1343.             gotData = false;
  1344.     }
  1345.     return true;
  1346. }
  1347. unsigned int
  1348. DGXMLScanner::resolveQName(const   XMLCh* const qName
  1349.                            ,       XMLBuffer&   prefixBuf
  1350.                            , const short        mode
  1351.                            ,       int&         prefixColonPos)
  1352. {
  1353.     //  Lets split out the qName into a URI and name buffer first. The URI
  1354.     //  can be empty.
  1355.     prefixColonPos = XMLString::indexOf(qName, chColon);
  1356.     if (prefixColonPos == -1)
  1357.     {
  1358.         //  Its all name with no prefix, so put the whole thing into the name
  1359.         //  buffer. Then map the empty string to a URI, since the empty string
  1360.         //  represents the default namespace. This will either return some
  1361.         //  explicit URI which the default namespace is mapped to, or the
  1362.         //  the default global namespace.
  1363.         bool unknown = false;
  1364.         prefixBuf.reset();
  1365.         return fElemStack.mapPrefixToURI(XMLUni::fgZeroLenString, (ElemStack::MapModes) mode, unknown);
  1366.     }
  1367.     else
  1368.     {
  1369.         //  Copy the chars up to but not including the colon into the prefix
  1370.         //  buffer.
  1371.         prefixBuf.set(qName, prefixColonPos);
  1372.         //  Watch for the special namespace prefixes. We always map these to
  1373.         //  special URIs. 'xml' gets mapped to the official URI that its defined
  1374.         //  to map to by the NS spec. xmlns gets mapped to a special place holder
  1375.         //  URI that we define (so that it maps to something checkable.)
  1376.         const XMLCh* prefixRawBuf = prefixBuf.getRawBuffer();
  1377.         if (XMLString::equals(prefixRawBuf, XMLUni::fgXMLNSString)) {
  1378.             // if this is an element, it is an error to have xmlns as prefix
  1379.             if (mode == ElemStack::Mode_Element)
  1380.                 emitError(XMLErrs::NoXMLNSAsElementPrefix, qName);
  1381.             return fXMLNSNamespaceId;
  1382.         }
  1383.         else if (XMLString::equals(prefixRawBuf, XMLUni::fgXMLString)) {
  1384.             return  fXMLNamespaceId;
  1385.         }
  1386.         else
  1387.         {
  1388.             bool unknown = false;
  1389.             unsigned int uriId = fElemStack.mapPrefixToURI(prefixRawBuf, (ElemStack::MapModes) mode, unknown);
  1390.             if (unknown)
  1391.                 emitError(XMLErrs::UnknownPrefix, prefixRawBuf);
  1392.             return uriId;
  1393.         }
  1394.     }
  1395. }
  1396. // ---------------------------------------------------------------------------
  1397. //  DGXMLScanner: Grammar preparsing
  1398. // ---------------------------------------------------------------------------
  1399. Grammar* DGXMLScanner::loadGrammar(const   InputSource& src
  1400.                                    , const short        grammarType
  1401.                                    , const bool         toCache)
  1402. {
  1403.     Grammar* loadedGrammar = 0;
  1404.     try
  1405.     {
  1406.         fGrammarResolver->cacheGrammarFromParse(false);
  1407.         fGrammarResolver->useCachedGrammarInParse(false);
  1408.         fRootGrammar = 0;
  1409.         if (fValScheme == Val_Auto) {
  1410.             fValidate = true;
  1411.         }
  1412.         // Reset some status flags
  1413.         fInException = false;
  1414.         fStandalone = false;
  1415.         fErrorCount = 0;
  1416.         fHasNoDTD = true;
  1417.         if (grammarType == Grammar::DTDGrammarType) {
  1418.             loadedGrammar = loadDTDGrammar(src, toCache);
  1419.         }
  1420.         // Reset the reader manager to close all files, sockets, etc...
  1421.         fReaderMgr.reset();
  1422.     }
  1423.     //  NOTE:
  1424.     //
  1425.     //  In all of the error processing below, the emitError() call MUST come
  1426.     //  before the flush of the reader mgr, or it will fail because it tries
  1427.     //  to find out the position in the XML source of the error.
  1428.     catch(const XMLErrs::Codes)
  1429.     {
  1430.         // This is a 'first fatal error' type exit, so reset and fall through
  1431.         fReaderMgr.reset();
  1432.     }
  1433.     catch(const XMLValid::Codes)
  1434.     {
  1435.         // This is a 'first fatal error' type exit, so reset and fall through
  1436.         fReaderMgr.reset();
  1437.     }
  1438.     catch(const XMLException& excToCatch)
  1439.     {
  1440.         //  Emit the error and catch any user exception thrown from here. Make
  1441.         //  sure in all cases we flush the reader manager.
  1442.         fInException = true;
  1443.         try
  1444.         {
  1445.             if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
  1446.                 emitError
  1447.                 (
  1448.                     XMLErrs::DisplayErrorMessage
  1449.                     , excToCatch.getMessage()
  1450.                 );
  1451.             else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
  1452.                 emitError
  1453.                 (
  1454.                     XMLErrs::XMLException_Fatal
  1455.                     , excToCatch.getType()
  1456.                     , excToCatch.getMessage()
  1457.                 );
  1458.             else
  1459.                 emitError
  1460.                 (
  1461.                     XMLErrs::XMLException_Error
  1462.                     , excToCatch.getType()
  1463.                     , excToCatch.getMessage()
  1464.                 );
  1465.         }
  1466.         catch(...)
  1467.         {
  1468.             // Flush the reader manager and rethrow user's error
  1469.             fReaderMgr.reset();
  1470.             throw;
  1471.         }
  1472.         // If it returned, then reset the reader manager and fall through
  1473.         fReaderMgr.reset();
  1474.     }
  1475.     catch(...)
  1476.     {
  1477.         // Reset and rethrow
  1478.         fReaderMgr.reset();
  1479.         throw;
  1480.     }
  1481.     return loadedGrammar;
  1482. }
  1483. Grammar* DGXMLScanner::loadDTDGrammar(const InputSource& src,
  1484.                                       const bool toCache)
  1485. {
  1486.     // Reset the validators
  1487.     fDTDValidator->reset();
  1488.     if (fValidatorFromUser)
  1489.         fValidator->reset();
  1490.     fDTDGrammar = new (fMemoryManager) DTDGrammar(fMemoryManager);
  1491.     fGrammarResolver->putGrammar(XMLUni::fgDTDEntityString, fDTDGrammar);
  1492.     fGrammar = fDTDGrammar;
  1493.     fValidator->setGrammar(fGrammar);
  1494.     //  And for all installed handlers, send reset events. This gives them
  1495.     //  a chance to flush any cached data.
  1496.     if (fDocHandler)
  1497.         fDocHandler->resetDocument();
  1498.     if (fEntityHandler)
  1499.         fEntityHandler->resetEntities();
  1500.     if (fErrorReporter)
  1501.         fErrorReporter->resetErrors();
  1502.     // Clear out the id reference list
  1503.     fIDRefList->removeAll();
  1504.     if (toCache) {
  1505.         unsigned int sysId = fGrammarResolver->getStringPool()->addOrFind(src.getSystemId());
  1506.         const XMLCh* sysIdStr = fGrammarResolver->getStringPool()->getValueForId(sysId);
  1507.         fGrammarResolver->orphanGrammar(XMLUni::fgDTDEntityString);
  1508.         fGrammarResolver->putGrammar(sysIdStr, fGrammar);
  1509.     }
  1510.     //  Handle the creation of the XML reader object for this input source.
  1511.     //  This will provide us with transcoding and basic lexing services.
  1512.     XMLReader* newReader = fReaderMgr.createReader
  1513.     (
  1514.         src
  1515.         , false
  1516.         , XMLReader::RefFrom_NonLiteral
  1517.         , XMLReader::Type_General
  1518.         , XMLReader::Source_External
  1519.         , fCalculateSrcOfs
  1520.     );
  1521.     if (!newReader) {
  1522.         if (src.getIssueFatalErrorIfNotFound())
  1523.             ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId());
  1524.         else
  1525.             ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId());
  1526.     }
  1527.     //  In order to make the processing work consistently, we have to
  1528.     //  make this look like an external entity. So create an entity
  1529.     //  decl and fill it in and push it with the reader, as happens
  1530.     //  with an external entity. Put a janitor on it to insure it gets
  1531.     //  cleaned up. The reader manager does not adopt them.
  1532.     const XMLCh gDTDStr[] = { chLatin_D, chLatin_T, chLatin_D , chNull };
  1533.     DTDEntityDecl* declDTD = new (fMemoryManager) DTDEntityDecl(gDTDStr, false, fMemoryManager);
  1534.     declDTD->setSystemId(src.getSystemId());
  1535.     Janitor<DTDEntityDecl> janDecl(declDTD);
  1536.     // Mark this one as a throw at end
  1537.     newReader->setThrowAtEnd(true);
  1538.     // And push it onto the stack, with its pseudo name
  1539.     fReaderMgr.pushReader(newReader, declDTD);
  1540.     //  If we have a doc type handler and advanced callbacks are enabled,
  1541.     //  call the doctype event.
  1542.     if (fDocTypeHandler) {
  1543.         // Create a dummy root
  1544.         DTDElementDecl* rootDecl = new (fMemoryManager) DTDElementDecl
  1545.         (
  1546.             gDTDStr
  1547.             , fEmptyNamespaceId
  1548.             , DTDElementDecl::Any
  1549.             , fMemoryManager
  1550.         );
  1551.         rootDecl->setCreateReason(DTDElementDecl::AsRootElem);
  1552.         rootDecl->setExternalElemDeclaration(true);
  1553.         Janitor<DTDElementDecl> janSrc(rootDecl);
  1554.         fDocTypeHandler->doctypeDecl(*rootDecl, src.getPublicId(), src.getSystemId(), false, true);
  1555.     }
  1556.     // Create DTDScanner
  1557.     DTDScanner dtdScanner
  1558.     (
  1559.         (DTDGrammar*)fGrammar
  1560.         , fDocTypeHandler
  1561.         , fMemoryManager
  1562.     );
  1563.     dtdScanner.setScannerInfo(this, &fReaderMgr, &fBufMgr);
  1564.     // Tell it its not in an include section
  1565.     dtdScanner.scanExtSubsetDecl(false, true);
  1566.     if (fValidate) {
  1567.         //  validate the DTD scan so far
  1568.         fValidator->preContentValidation(false, true);
  1569.     }
  1570.     if (toCache)
  1571.         fGrammarResolver->cacheGrammars();
  1572.     return fDTDGrammar;
  1573. }
  1574. // ---------------------------------------------------------------------------
  1575. //  DGXMLScanner: Private helper methods
  1576. // ---------------------------------------------------------------------------
  1577. //  This method handles the common initialization, to avoid having to do
  1578. //  it redundantly in multiple constructors.
  1579. void DGXMLScanner::commonInit()
  1580. {
  1581.     //  And we need one for the raw attribute scan. This just stores key/
  1582.     //  value string pairs (prior to any processing.)
  1583.     fAttrNSList = new (fMemoryManager) ValueVectorOf<XMLAttr*>(8, fMemoryManager);
  1584.     //  Create the Validator and init them
  1585.     fDTDValidator = new (fMemoryManager) DTDValidator();
  1586.     initValidator(fDTDValidator);
  1587. }
  1588. void DGXMLScanner::cleanUp()
  1589. {
  1590.     delete fAttrNSList;
  1591.     delete fDTDValidator;
  1592. }
  1593. //  This method is called from scanStartTagNS() to build up the list of
  1594. //  XMLAttr objects that will be passed out in the start tag callout. We
  1595. //  get the key/value pairs from the raw scan of explicitly provided attrs,
  1596. //  which have not been normalized. And we get the element declaration from
  1597. //  which we will get any defaulted or fixed attribute defs and add those
  1598. //  in as well.
  1599. unsigned int
  1600. DGXMLScanner::buildAttList(const unsigned int           attCount
  1601.                           ,       XMLElementDecl*       elemDecl
  1602.                           ,       RefVectorOf<XMLAttr>& toFill)
  1603. {
  1604.     //  Ask the element to clear the 'provided' flag on all of the att defs
  1605.     //  that it owns, and to return us a boolean indicating whether it has
  1606.     //  any defs.
  1607.     const bool hasDefs = elemDecl->hasAttDefs();
  1608.     //  If there are no expliclitily provided attributes and there are no
  1609.     //  defined attributes for the element, the we don't have anything to do.
  1610.     //  So just return zero in this case.
  1611.     if (!hasDefs && !attCount)
  1612.         return 0;
  1613.     // Keep up with how many attrs we end up with total
  1614.     unsigned int retCount = attCount;
  1615.     //  And get the current size of the output vector. This lets us use
  1616.     //  existing elements until we fill it, then start adding new ones.
  1617.     const unsigned int curAttListSize = toFill.size();
  1618.     //  Ok, so lets get an enumerator for the attributes of this element
  1619.     //  and run through them for well formedness and validity checks. But
  1620.     //  make sure that we had any attributes before we do it, since the list
  1621.     //  would have have gotten faulted in anyway.
  1622.     if (hasDefs)
  1623.     {
  1624.         XMLAttDefList& attDefList = elemDecl->getAttDefList();
  1625.         while (attDefList.hasMoreElements())
  1626.         {
  1627.             // Get the current att def, for convenience and its def type
  1628.             XMLAttDef& curDef = attDefList.nextElement();
  1629.             if (!curDef.getProvided() && curDef.getCreateReason() != XMLAttDef::JustFaultIn)
  1630.             {
  1631.                 const XMLAttDef::DefAttTypes defType = curDef.getDefaultType();
  1632.                 if (fValidate)
  1633.                 {
  1634.                     // If we are validating and its required, then an error
  1635.                     if (defType == XMLAttDef::Required)
  1636.                     {
  1637.                         fValidator->emitError
  1638.                         (
  1639.                             XMLValid::RequiredAttrNotProvided
  1640.                             , curDef.getFullName()
  1641.                         );
  1642.                     }
  1643.                     else if ((defType == XMLAttDef::Default) ||
  1644.                        (defType == XMLAttDef::Fixed)  )
  1645.                     {
  1646.                         if (fStandalone && curDef.isExternal())
  1647.                         {
  1648.                             // XML 1.0 Section 2.9
  1649.                             // Document is standalone, so attributes must not be defaulted.
  1650.                             fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef.getFullName(), elemDecl->getFullName());
  1651.                         }
  1652.                     }
  1653.                 }
  1654.                 // Fault in the value if needed, and bump the att count
  1655.                 if ((defType == XMLAttDef::Default)
  1656.                 ||  (defType == XMLAttDef::Fixed))
  1657.                 {
  1658.                     // Let the validator pass judgement on the attribute value
  1659.                     if (fValidate)
  1660.                     {
  1661.                         fValidator->validateAttrValue
  1662.                         (
  1663.                             &curDef
  1664.                             , curDef.getValue()
  1665.                             , false
  1666.                             , elemDecl
  1667.                         );
  1668.                     }
  1669.                     XMLAttr* curAtt;
  1670.                     if (retCount >= curAttListSize)
  1671.                     {
  1672.                         if (fDoNamespaces)
  1673.                         {
  1674.                             curAtt = new (fMemoryManager) XMLAttr
  1675.                             (
  1676.                                 -1
  1677.                                 , curDef.getFullName()
  1678.                                 , XMLUni::fgZeroLenString
  1679.                                 , curDef.getValue()
  1680.                                 , curDef.getType()
  1681.                                 , false
  1682.                                 , fMemoryManager
  1683.                             );
  1684.                         }
  1685.                         else
  1686.                         {
  1687.                             curAtt = new (fMemoryManager) XMLAttr
  1688.                             (
  1689.                                 -1
  1690.                                 , curDef.getFullName()
  1691.                                 , XMLUni::fgZeroLenString
  1692.                                 , curDef.getValue()
  1693.                                 , curDef.getType()
  1694.                                 , false
  1695.                                 , fMemoryManager
  1696.                             );
  1697.                         }
  1698.                         fAttrList->addElement(curAtt);
  1699.                     }
  1700.                     else
  1701.                     {
  1702.                         curAtt = fAttrList->elementAt(retCount);
  1703.                         if (fDoNamespaces)
  1704.                         {
  1705.                             curAtt->set
  1706.                             (
  1707.                                 fEmptyNamespaceId
  1708.                                 , curDef.getFullName()
  1709.                                 , curDef.getValue()
  1710.                                 , curDef.getType()
  1711.                             );
  1712.                         }
  1713.                         else
  1714.                         {
  1715.                             curAtt->set
  1716.                             (
  1717.                                 -1
  1718.                                 , curDef.getFullName()
  1719.                                 , XMLUni::fgZeroLenString
  1720.                                 , curDef.getValue()
  1721.                                 , curDef.getType()
  1722.                             );
  1723.                         }
  1724.                         curAtt->setSpecified(false);
  1725.                     }
  1726.                     if (fDoNamespaces)
  1727.                     {
  1728.                         //  Map the new attribute's prefix to a URI id and store
  1729.                         //  that in the attribute object.
  1730.                         const XMLCh* attPrefix = curAtt->getPrefix();
  1731.                         if (attPrefix && *attPrefix) {
  1732.                             curAtt->setURIId
  1733.                             (
  1734.                                 resolvePrefix(attPrefix, ElemStack::Mode_Attribute)
  1735.                             );
  1736.                         }
  1737.                     }
  1738.                     retCount++;
  1739.                 }
  1740.             }
  1741.             else {
  1742.                 curDef.setProvided(false);
  1743.             }
  1744.         }
  1745.     }
  1746.     for (unsigned int i=0; i < fAttrNSList->size(); i++) {
  1747.         XMLAttr* providedAttr = fAttrNSList->elementAt(i);
  1748.         providedAttr->setURIId
  1749.         (
  1750.         resolvePrefix
  1751.             (
  1752.                 providedAttr->getPrefix(),
  1753.                 ElemStack::Mode_Attribute
  1754.             )
  1755.         );
  1756.     }
  1757.     fAttrNSList->removeAllElements();
  1758.     return retCount;
  1759. }
  1760. unsigned int
  1761. DGXMLScanner::resolvePrefix(  const   XMLCh* const        prefix
  1762.                               , const ElemStack::MapModes mode)
  1763. {
  1764.     //  Watch for the special namespace prefixes. We always map these to
  1765.     //  special URIs. 'xml' gets mapped to the official URI that its defined
  1766.     //  to map to by the NS spec. xmlns gets mapped to a special place holder
  1767.     //  URI that we define (so that it maps to something checkable.)
  1768.     if (XMLString::equals(prefix, XMLUni::fgXMLNSString))
  1769.         return fXMLNSNamespaceId;
  1770.     else if (XMLString::equals(prefix, XMLUni::fgXMLString))
  1771.         return fXMLNamespaceId;
  1772.     //  Ask the element stack to search up itself for a mapping for the
  1773.     //  passed prefix.
  1774.     bool unknown;
  1775.     unsigned int uriId = fElemStack.mapPrefixToURI(prefix, mode, unknown);
  1776.     // If it was unknown, then the URI was faked in but we have to issue an error
  1777.     if (unknown)
  1778.         emitError(XMLErrs::UnknownPrefix, prefix);
  1779.     return uriId;
  1780. }
  1781. //  This method will reset the scanner data structures, and related plugged
  1782. //  in stuff, for a new scan session. We get the input source for the primary
  1783. //  XML entity, create the reader for it, and push it on the stack so that
  1784. //  upon successful return from here we are ready to go.
  1785. void DGXMLScanner::scanReset(const InputSource& src)
  1786. {
  1787.     //  This call implicitly tells us that we are going to reuse the scanner
  1788.     //  if it was previously used. So tell the validator to reset itself.
  1789.     //
  1790.     //  But, if the fUseCacheGrammar flag is set, then don't reset it.
  1791.     //
  1792.     //  NOTE:   The ReaderMgr is flushed on the way out, because that is
  1793.     //          required to insure that files are closed.
  1794.     fGrammarResolver->cacheGrammarFromParse(fToCacheGrammar);
  1795.     fGrammarResolver->useCachedGrammarInParse(fUseCachedGrammar);
  1796.     fDTDGrammar = new (fMemoryManager) DTDGrammar(fMemoryManager);
  1797.     fGrammarResolver->putGrammar(XMLUni::fgDTDEntityString, fDTDGrammar);
  1798.     fGrammar = fDTDGrammar;
  1799.     fRootGrammar = 0;
  1800.     fValidator->setGrammar(fGrammar);
  1801.     // Reset validation
  1802.     fValidate = (fValScheme == Val_Always) ? true : false;
  1803.     //  And for all installed handlers, send reset events. This gives them
  1804.     //  a chance to flush any cached data.
  1805.     if (fDocHandler)
  1806.         fDocHandler->resetDocument();
  1807.     if (fEntityHandler)
  1808.         fEntityHandler->resetEntities();
  1809.     if (fErrorReporter)
  1810.         fErrorReporter->resetErrors();
  1811.     // Clear out the id reference list
  1812.     fIDRefList->removeAll();
  1813.     // Reset the Root Element Name
  1814.     fMemoryManager->deallocate(fRootElemName);//delete [] fRootElemName;
  1815.     fRootElemName = 0;
  1816.     //  Reset the element stack, and give it the latest ids for the special
  1817.     //  URIs it has to know about.
  1818.     fElemStack.reset
  1819.     (
  1820.         fEmptyNamespaceId
  1821.         , fUnknownNamespaceId
  1822.         , fXMLNamespaceId
  1823.         , fXMLNSNamespaceId
  1824.     );
  1825.     // Reset some status flags
  1826.     fInException = false;
  1827.     fStandalone = false;
  1828.     fErrorCount = 0;
  1829.     fHasNoDTD = true;
  1830.     // Reset the validators
  1831.     fDTDValidator->reset();
  1832.     fDTDValidator->setErrorReporter(fErrorReporter);
  1833.     if (fValidatorFromUser)
  1834.         fValidator->reset();
  1835.     //  Handle the creation of the XML reader object for this input source.
  1836.     //  This will provide us with transcoding and basic lexing services.
  1837.     XMLReader* newReader = fReaderMgr.createReader
  1838.     (
  1839.         src
  1840.         , true
  1841.         , XMLReader::RefFrom_NonLiteral
  1842.         , XMLReader::Type_General
  1843.         , XMLReader::Source_External
  1844.         , fCalculateSrcOfs
  1845.     );
  1846.     if (!newReader) {
  1847.         if (src.getIssueFatalErrorIfNotFound())
  1848.             ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId());
  1849.         else
  1850.             ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId());
  1851.     }
  1852.     // Push this read onto the reader manager
  1853.     fReaderMgr.pushReader(newReader, 0);
  1854.     // and reset security-related things if necessary:
  1855.     if(fSecurityManager != 0) 
  1856.     {
  1857.         fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit();
  1858.         fEntityExpansionCount = 0;
  1859.     }
  1860. }
  1861. //  This method is called between markup in content. It scans for character
  1862. //  data that is sent to the document handler. It watches for any markup
  1863. //  characters that would indicate that the character data has ended. It also
  1864. //  handles expansion of general and character entities.
  1865. //
  1866. //  sendData() is a local static helper for this method which handles some
  1867. //  code that must be done in three different places here.
  1868. void DGXMLScanner::sendCharData(XMLBuffer& toSend)
  1869. {
  1870.     // If no data in the buffer, then nothing to do
  1871.     if (toSend.isEmpty())
  1872.         return;
  1873.     //  We do different things according to whether we are validating or
  1874.     //  not. If not, its always just characters; else, it depends on the
  1875.     //  current element's content model.
  1876.     if (fValidate)
  1877.     {
  1878.         // Get the raw data we need for the callback
  1879.         const XMLCh* const rawBuf = toSend.getRawBuffer();
  1880.         const unsigned int len = toSend.getLen();
  1881.         // And see if the current element is a 'Children' style content model
  1882.         const ElemStack::StackElem* topElem = fElemStack.topElement();
  1883.         // Get the character data opts for the current element
  1884.         XMLElementDecl::CharDataOpts charOpts = topElem->fThisElement->getCharDataOpts();
  1885.         if (charOpts == XMLElementDecl::NoCharData)
  1886.         {
  1887.             // They definitely cannot handle any type of char data
  1888.             fValidator->emitError(XMLValid::NoCharDataInCM);
  1889.         }
  1890.         else if (fReaderMgr.getCurrentReader()->isAllSpaces(rawBuf, len))
  1891.         {
  1892.             //  Its all spaces. So, if they can take spaces, then send it
  1893.             //  as ignorable whitespace. If they can handle any char data
  1894.             //  send it as characters.
  1895.             if (charOpts == XMLElementDecl::SpacesOk) {
  1896.                 if (fDocHandler)
  1897.                     fDocHandler->ignorableWhitespace(rawBuf, len, false);
  1898.             }
  1899.             else if (charOpts == XMLElementDecl::AllCharData)
  1900.             {
  1901.                 if (fDocHandler)
  1902.                     fDocHandler->docCharacters(rawBuf, len, false);
  1903.             }
  1904.         }
  1905.         else
  1906.         {
  1907.             //  If they can take any char data, then send it. Otherwise, they
  1908.             //  can only handle whitespace and can't handle this stuff so
  1909.             //  issue an error.
  1910.             if (charOpts == XMLElementDecl::AllCharData)
  1911.             {
  1912.                 if (fDocHandler)
  1913.                     fDocHandler->docCharacters(rawBuf, len, false);
  1914.             }
  1915.             else
  1916.             {
  1917.                 fValidator->emitError(XMLValid::NoCharDataInCM);
  1918.             }
  1919.         }
  1920.     }
  1921.     else
  1922.     {
  1923.         // Always assume its just char data if not validating
  1924.         if (fDocHandler)
  1925.             fDocHandler->docCharacters(toSend.getRawBuffer(), toSend.getLen(), false);
  1926.     }
  1927.     // Reset buffer
  1928.     toSend.reset();
  1929. }
  1930. //  This method is called with a key/value string pair that represents an
  1931. //  xmlns="yyy" or xmlns:xxx="yyy" attribute. This method will update the
  1932. //  current top of the element stack based on this data. We know that when
  1933. //  we get here, that it is one of these forms, so we don't bother confirming
  1934. //  it.
  1935. //
  1936. //  But we have to ensure
  1937. //      1. xxx is not xmlns
  1938. //      2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa
  1939. //      3. yyy is not XMLUni::fgXMLNSURIName
  1940. //      4. if xxx is not null, then yyy cannot be an empty string.
  1941. void DGXMLScanner::updateNSMap(const    XMLCh* const attrPrefix
  1942.                                , const  XMLCh* const attrLocalName
  1943.                                , const  XMLCh* const attrValue)
  1944. {
  1945.     //  We either have the default prefix (""), or we point it into the attr
  1946.     //  name parameter. Note that the xmlns is not the prefix we care about
  1947.     //  here. To us, the 'prefix' is really the local part of the attrName
  1948.     //  parameter.
  1949.     //
  1950.     //  Check 1. xxx is not xmlns
  1951.     //        2. if xxx is xml, then yyy must match XMLUni::fgXMLURIName, and vice versa
  1952.     //        3. yyy is not XMLUni::fgXMLNSURIName
  1953.     //        4. if xxx is not null, then yyy cannot be an empty string.
  1954.     if (attrPrefix && *attrPrefix) {
  1955.         if (XMLString::equals(attrLocalName, XMLUni::fgXMLNSString))
  1956.             emitError(XMLErrs::NoUseOfxmlnsAsPrefix);
  1957.         else if (XMLString::equals(attrLocalName, XMLUni::fgXMLString)) {
  1958.             if (!XMLString::equals(attrValue, XMLUni::fgXMLURIName))
  1959.                 emitError(XMLErrs::PrefixXMLNotMatchXMLURI);
  1960.         }
  1961.         if (!attrValue)
  1962.             emitError(XMLErrs::NoEmptyStrNamespace, attrLocalName);
  1963.         else if(!*attrValue && fXMLVersion == XMLReader::XMLV1_0)
  1964.             emitError(XMLErrs::NoEmptyStrNamespace, attrLocalName);
  1965.     }
  1966.     if (XMLString::equals(attrValue, XMLUni::fgXMLNSURIName))
  1967.         emitError(XMLErrs::NoUseOfxmlnsURI);
  1968.     else if (XMLString::equals(attrValue, XMLUni::fgXMLURIName)) {
  1969.         if (!XMLString::equals(attrLocalName, XMLUni::fgXMLString))
  1970.             emitError(XMLErrs::XMLURINotMatchXMLPrefix);
  1971.     }
  1972.     //  Ok, we have to get the unique id for the attribute value, which is the
  1973.     //  URI that this value should be mapped to. The validator has the
  1974.     //  namespace string pool, so we ask him to find or add this new one. Then
  1975.     //  we ask the element stack to add this prefix to URI Id mapping.
  1976.     fElemStack.addPrefix
  1977.     (
  1978.         attrLocalName
  1979.         , fURIStringPool->addOrFind(attrValue)
  1980.     );
  1981. }
  1982. void DGXMLScanner::scanAttrListforNameSpaces(RefVectorOf<XMLAttr>* theAttrList, int attCount)
  1983. {
  1984.     //  Make an initial pass through the list and find any xmlns attributes or
  1985.     //  schema attributes.
  1986.     //  When we find one, send it off to be used to update the element stack's
  1987.     //  namespace mappings.
  1988.     for (int index = 0; index < attCount; index++)
  1989.     {
  1990.         // each attribute has the prefix:suffix="value"
  1991.         XMLAttr* curAttr = theAttrList->elementAt(index);
  1992.         const XMLCh* attPrefix = curAttr->getPrefix();
  1993.         const XMLCh* attLocalName = curAttr->getName();
  1994.         if (attPrefix && *attPrefix)
  1995.         {
  1996.             if (XMLString::equals(attPrefix, XMLUni::fgXMLString)) {
  1997.                 curAttr->setURIId(fXMLNamespaceId);
  1998.             }
  1999.             else if (XMLString::equals(attPrefix, XMLUni::fgXMLNSString)) {
  2000.                 curAttr->setURIId(fXMLNSNamespaceId);
  2001.                 updateNSMap(attPrefix, attLocalName, curAttr->getValue());
  2002.             }
  2003.             else {
  2004.                 fAttrNSList->addElement(curAttr);
  2005.             }
  2006.         }
  2007.         else if (XMLString::equals(XMLUni::fgXMLNSString, attLocalName))
  2008.         {
  2009.             updateNSMap(attPrefix, XMLUni::fgZeroLenString, curAttr->getValue());
  2010.         }
  2011.     }
  2012. }
  2013. InputSource* DGXMLScanner::resolveSystemId(const XMLCh* const sysId)
  2014. {
  2015.     // Create a buffer for expanding the system id
  2016.     XMLBufBid bbSys(&fBufMgr);
  2017.     XMLBuffer& expSysId = bbSys.getBuffer();
  2018.     //  Allow the entity handler to expand the system id if they choose
  2019.     //  to do so.
  2020.     InputSource* srcToFill = 0;
  2021.     if (fEntityHandler)
  2022.     {
  2023.         if (!fEntityHandler->expandSystemId(sysId, expSysId))
  2024.             expSysId.set(sysId);
  2025.         srcToFill = fEntityHandler->resolveEntity( XMLUni::fgZeroLenString
  2026.                                                  , expSysId.getRawBuffer());
  2027.     }
  2028.     else
  2029.     {
  2030.         expSysId.set(sysId);
  2031.     }
  2032.     //  If they didn't create a source via the entity handler, then we
  2033.     //  have to create one on our own.
  2034.     if (!srcToFill)
  2035.     {
  2036.         ReaderMgr::LastExtEntityInfo lastInfo;
  2037.         fReaderMgr.getLastExtEntityInfo(lastInfo);
  2038.         try
  2039.         {
  2040.             XMLURL urlTmp(lastInfo.systemId, expSysId.getRawBuffer());
  2041.             if (urlTmp.isRelative())
  2042.             {
  2043.                 ThrowXML
  2044.                 (
  2045.                     MalformedURLException
  2046.                     , XMLExcepts::URL_NoProtocolPresent
  2047.                 );
  2048.             }
  2049.             else {
  2050.                 if (fStandardUriConformant && urlTmp.hasInvalidChar())
  2051.                     ThrowXML(MalformedURLException, XMLExcepts::URL_MalformedURL);
  2052.                 srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
  2053.             }
  2054.         }
  2055.         catch(const MalformedURLException& e)
  2056.         {
  2057.             // Its not a URL, so lets assume its a local file name if non-standard uri is allowed
  2058.             if (!fStandardUriConformant)
  2059.                 srcToFill = new (fMemoryManager) LocalFileInputSource
  2060.                 (
  2061.                     lastInfo.systemId
  2062.                     , expSysId.getRawBuffer()
  2063.                     , fMemoryManager
  2064.                 );
  2065.             else
  2066.                 throw e;
  2067.         }
  2068.     }
  2069.     return srcToFill;
  2070. }
  2071. // ---------------------------------------------------------------------------
  2072. //  DGXMLScanner: Private parsing methods
  2073. // ---------------------------------------------------------------------------
  2074. bool DGXMLScanner::scanAttValue(  const   XMLAttDef* const    attDef
  2075.                                   ,       XMLBuffer&          toFill)
  2076. {
  2077.     enum States
  2078.     {
  2079.         InWhitespace
  2080.         , InContent
  2081.     };
  2082.     // Get the type and name
  2083.     const XMLAttDef::AttTypes type = attDef->getType();
  2084.     const XMLCh* const attrName = attDef->getFullName();
  2085.     // Reset the target buffer
  2086.     toFill.reset();
  2087.     // Get the next char which must be a single or double quote
  2088.     XMLCh quoteCh;
  2089.     if (!fReaderMgr.skipIfQuote(quoteCh))
  2090.         return false;
  2091.     //  We have to get the current reader because we have to ignore closing
  2092.     //  quotes until we hit the same reader again.
  2093.     const unsigned int curReader = fReaderMgr.getCurrentReaderNum();
  2094.     // Get attribute def - to check to see if it's declared externally or not
  2095.     bool  isAttExternal = attDef->isExternal();
  2096.     //  Loop until we get the attribute value. Note that we use a double
  2097.     //  loop here to avoid the setup/teardown overhead of the exception
  2098.     //  handler on every round.
  2099.     XMLCh   nextCh;
  2100.     XMLCh   secondCh = 0;
  2101.     States  curState = InContent;
  2102.     bool    firstNonWS = false;
  2103.     bool    gotLeadingSurrogate = false;
  2104.     bool    escaped;
  2105.     while (true)
  2106.     {
  2107.     try
  2108.     {
  2109.         while(true)
  2110.         {
  2111.             nextCh = fReaderMgr.getNextChar();
  2112.             if (!nextCh)
  2113.                 ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  2114.             // Check for our ending quote in the same entity
  2115.             if (nextCh == quoteCh)
  2116.             {
  2117.                 if (curReader == fReaderMgr.getCurrentReaderNum())
  2118.                     return true;
  2119.                 // Watch for spillover into a previous entity
  2120.                 if (curReader > fReaderMgr.getCurrentReaderNum())
  2121.                 {
  2122.                     emitError(XMLErrs::PartialMarkupInEntity);
  2123.                     return false;
  2124.                 }
  2125.             }
  2126.             //  Check for an entity ref now, before we let it affect our
  2127.             //  whitespace normalization logic below. We ignore the empty flag
  2128.             //  in this one.
  2129.             escaped = false;
  2130.             if (nextCh == chAmpersand)
  2131.             {
  2132.                 if (scanEntityRef(true, nextCh, secondCh, escaped) != EntityExp_Returned)
  2133.                 {
  2134.                     gotLeadingSurrogate = false;
  2135.                     continue;
  2136.                 }
  2137.             }
  2138.             else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
  2139.             {
  2140.                 // Deal with surrogate pairs
  2141.                 //  Its a leading surrogate. If we already got one, then
  2142.                 //  issue an error, else set leading flag to make sure that
  2143.                 //  we look for a trailing next time.
  2144.                 if (gotLeadingSurrogate)
  2145.                     emitError(XMLErrs::Expected2ndSurrogateChar);
  2146.                 else
  2147.                     gotLeadingSurrogate = true;
  2148.             }
  2149.             else
  2150.             {
  2151.                 //  If its a trailing surrogate, make sure that we are
  2152.                 //  prepared for that. Else, its just a regular char so make
  2153.                 //  sure that we were not expected a trailing surrogate.
  2154.                 if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF))
  2155.                 {
  2156.                     // Its trailing, so make sure we were expecting it
  2157.                     if (!gotLeadingSurrogate)
  2158.                         emitError(XMLErrs::Unexpected2ndSurrogateChar);
  2159.                 }
  2160.                 else
  2161.                 {
  2162.                     //  Its just a char, so make sure we were not expecting a
  2163.                     //  trailing surrogate.
  2164.                     if (gotLeadingSurrogate)
  2165.                         emitError(XMLErrs::Expected2ndSurrogateChar);
  2166.                     // Its got to at least be a valid XML character
  2167.                     if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh))
  2168.                     {
  2169.                         XMLCh tmpBuf[9];
  2170.                         XMLString::binToText
  2171.                         (
  2172.                             nextCh
  2173.                             , tmpBuf
  2174.                             , 8
  2175.                             , 16
  2176.                         );
  2177.                         emitError(XMLErrs::InvalidCharacterInAttrValue, attrName, tmpBuf);
  2178.                     }
  2179.                 }
  2180.                 gotLeadingSurrogate = false;
  2181.             }
  2182.             //  If its not escaped, then make sure its not a < character, which
  2183.             //  is not allowed in attribute values.
  2184.             if (!escaped && (nextCh == chOpenAngle))
  2185.                 emitError(XMLErrs::BracketInAttrValue, attrName);
  2186.             //  If the attribute is a CDATA type we do simple replacement of
  2187.             //  tabs and new lines with spaces, if the character is not escaped
  2188.             //  by way of a char ref.
  2189.             //
  2190.             //  Otherwise, we do the standard non-CDATA normalization of
  2191.             //  compressing whitespace to single spaces and getting rid of leading
  2192.             //  and trailing whitespace.
  2193.             if (type == XMLAttDef::CData)
  2194.             {
  2195.                 if (!escaped)
  2196.                 {
  2197.                     if ((nextCh == 0x09) || (nextCh == 0x0A) || (nextCh == 0x0D))
  2198.                     {
  2199.                         // Check Validity Constraint for Standalone document declaration
  2200.                         // XML 1.0, Section 2.9
  2201.                         if (fStandalone && fValidate && isAttExternal)
  2202.                         {
  2203.                              // Can't have a standalone document declaration of "yes" if  attribute
  2204.                              // values are subject to normalisation
  2205.                              fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName);
  2206.                         }
  2207.                         nextCh = chSpace;
  2208.                     }
  2209.                 }
  2210.             }
  2211.             else
  2212.             {
  2213.                 if (curState == InWhitespace)
  2214.                 {
  2215.                     if ((escaped && nextCh != chSpace) || !fReaderMgr.getCurrentReader()->isWhitespace(nextCh))
  2216.                     {
  2217.                         if (firstNonWS)
  2218.                             toFill.append(chSpace);
  2219.                         curState = InContent;
  2220.                         firstNonWS = true;
  2221.                     }
  2222.                     else
  2223.                     {
  2224.                         continue;
  2225.                     }
  2226.                 }
  2227.                 else if (curState == InContent)
  2228.                 {
  2229.                     if ((nextCh == chSpace) ||
  2230.                         (fReaderMgr.getCurrentReader()->isWhitespace(nextCh) && !escaped))
  2231.                     {
  2232.                         curState = InWhitespace;
  2233.                         // Check Validity Constraint for Standalone document declaration
  2234.                         // XML 1.0, Section 2.9
  2235.                         if (fStandalone && fValidate && isAttExternal)
  2236.                         {
  2237.                             if (!firstNonWS || (nextCh != chSpace) || (fReaderMgr.lookingAtSpace()))
  2238.                             {
  2239.                                  // Can't have a standalone document declaration of "yes" if  attribute
  2240.                                  // values are subject to normalisation
  2241.                                  fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName);
  2242.                             }
  2243.                         }
  2244.                         continue;
  2245.                     }
  2246.                     firstNonWS = true;
  2247.                 }
  2248.             }
  2249.             // Else add it to the buffer
  2250.             toFill.append(nextCh);
  2251.             if (secondCh)
  2252.                 toFill.append(secondCh);
  2253.         }
  2254.     }
  2255.     catch(const EndOfEntityException&)
  2256.     {
  2257.         // Just eat it and continue.
  2258.         gotLeadingSurrogate = false;
  2259.         escaped = false;
  2260.     }
  2261.     }
  2262.     return true;
  2263. }
  2264. //  This method scans a CDATA section. It collects the character into one
  2265. //  of the temp buffers and calls the document handler, if any, with the
  2266. //  characters. It assumes that the <![CDATA string has been scanned before
  2267. //  this call.
  2268. void DGXMLScanner::scanCDSection()
  2269. {
  2270.     //  This is the CDATA section opening sequence, minus the '<' character.
  2271.     //  We use this to watch for nested CDATA sections, which are illegal.
  2272.     static const XMLCh CDataPrefix[] =
  2273.     {
  2274.             chBang, chOpenSquare, chLatin_C, chLatin_D, chLatin_A
  2275.         ,   chLatin_T, chLatin_A, chOpenSquare, chNull
  2276.     };
  2277.     static const XMLCh CDataClose[] =
  2278.     {
  2279.             chCloseSquare, chCloseAngle, chNull
  2280.     };
  2281.     //  The next character should be the opening square bracket. If not
  2282.     //  issue an error, but then try to recover by skipping any whitespace
  2283.     //  and checking again.
  2284.     if (!fReaderMgr.skippedChar(chOpenSquare))
  2285.     {
  2286.         emitError(XMLErrs::ExpectedOpenSquareBracket);
  2287.         fReaderMgr.skipPastSpaces();
  2288.         // If we still don't find it, then give up, else keep going
  2289.         if (!fReaderMgr.skippedChar(chOpenSquare))
  2290.             return;
  2291.     }
  2292.     // Get a buffer for this
  2293.     XMLBufBid bbCData(&fBufMgr);
  2294.     //  We just scan forward until we hit the end of CDATA section sequence.
  2295.     //  CDATA is effectively a big escape mechanism so we don't treat markup
  2296.     //  characters specially here.
  2297.     bool            emittedError = false;
  2298.     bool     gotLeadingSurrogate = false;
  2299.     // Get the character data opts for the current element
  2300.     const ElemStack::StackElem* topElem = fElemStack.topElement();
  2301.     XMLElementDecl::CharDataOpts charOpts =  topElem->fThisElement->getCharDataOpts();
  2302.     while (true)
  2303.     {
  2304.         const XMLCh nextCh = fReaderMgr.getNextChar();
  2305.         // Watch for unexpected end of file
  2306.         if (!nextCh)
  2307.         {
  2308.             emitError(XMLErrs::UnterminatedCDATASection);
  2309.             ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  2310.         }
  2311.         if (fValidate && fStandalone && (fReaderMgr.getCurrentReader()->isWhitespace(nextCh)))
  2312.         {
  2313.             // This document is standalone; this ignorable CDATA whitespace is forbidden.
  2314.             // XML 1.0, Section 2.9
  2315.             // And see if the current element is a 'Children' style content model
  2316.             if (topElem->fThisElement->isExternal()) {
  2317.                 if (charOpts == XMLElementDecl::SpacesOk) // Element Content
  2318.                 {
  2319.                     // Error - standalone should have a value of "no" as whitespace detected in an
  2320.                     // element type with element content whose element declaration was external
  2321.                     fValidator->emitError(XMLValid::NoWSForStandalone);
  2322.                 }
  2323.             }
  2324.         }
  2325.         //  If this is a close square bracket it could be our closing
  2326.         //  sequence.
  2327.         if (nextCh == chCloseSquare && fReaderMgr.skippedString(CDataClose))
  2328.         {
  2329.             //  make sure we were not expecting a trailing surrogate.
  2330.             if (gotLeadingSurrogate)
  2331.                 emitError(XMLErrs::Expected2ndSurrogateChar);
  2332.             if (fValidate) {
  2333.                 if (charOpts != XMLElementDecl::AllCharData)
  2334.                 {
  2335.                     // They definitely cannot handle any type of char data
  2336.                     fValidator->emitError(XMLValid::NoCharDataInCM);
  2337.                 }
  2338.             }
  2339.             // If we have a doc handler, call it
  2340.             if (fDocHandler)
  2341.             {
  2342.                 fDocHandler->docCharacters
  2343.                     (
  2344.                     bbCData.getRawBuffer()
  2345.                     , bbCData.getLen()
  2346.                     , true
  2347.                     );
  2348.             }
  2349.             // And we are done
  2350.             break;
  2351.         }
  2352.         //  Make sure its a valid character. But if we've emitted an error
  2353.         //  already, don't bother with the overhead since we've already told
  2354.         //  them about it.
  2355.         if (!emittedError)
  2356.         {
  2357.             // Deal with surrogate pairs
  2358.             if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
  2359.             {
  2360.                 //  Its a leading surrogate. If we already got one, then
  2361.                 //  issue an error, else set leading flag to make sure that
  2362.                 //  we look for a trailing next time.
  2363.                 if (gotLeadingSurrogate)
  2364.                     emitError(XMLErrs::Expected2ndSurrogateChar);
  2365.                 else
  2366.                     gotLeadingSurrogate = true;
  2367.             }
  2368.             else
  2369.             {
  2370.                 //  If its a trailing surrogate, make sure that we are
  2371.                 //  prepared for that. Else, its just a regular char so make
  2372.                 //  sure that we were not expected a trailing surrogate.
  2373.                 if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF))
  2374.                 {
  2375.                     // Its trailing, so make sure we were expecting it
  2376.                     if (!gotLeadingSurrogate)
  2377.                         emitError(XMLErrs::Unexpected2ndSurrogateChar);
  2378.                 }
  2379.                 else
  2380.                 {
  2381.                     //  Its just a char, so make sure we were not expecting a
  2382.                     //  trailing surrogate.
  2383.                     if (gotLeadingSurrogate)
  2384.                         emitError(XMLErrs::Expected2ndSurrogateChar);
  2385.                     // Its got to at least be a valid XML character
  2386.                     else if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh))
  2387.                     {
  2388.                         XMLCh tmpBuf[9];
  2389.                         XMLString::binToText
  2390.                         (
  2391.                             nextCh
  2392.                             , tmpBuf
  2393.                             , 8
  2394.                             , 16
  2395.                         );
  2396.                         emitError(XMLErrs::InvalidCharacter, tmpBuf);
  2397.                         emittedError = true;
  2398.                     }
  2399.                 }
  2400.                 gotLeadingSurrogate = false;
  2401.             }
  2402.         }
  2403.         // Add it to the buffer
  2404.         bbCData.append(nextCh);
  2405.     }
  2406. }
  2407. void DGXMLScanner::scanCharData(XMLBuffer& toUse)
  2408. {
  2409.     //  We have to watch for the stupid ]]> sequence, which is illegal in
  2410.     //  character data. So this is a little state machine that handles that.
  2411.     enum States
  2412.     {
  2413.         State_Waiting
  2414.         , State_GotOne
  2415.         , State_GotTwo
  2416.     };
  2417.     // Reset the buffer before we start
  2418.     toUse.reset();
  2419.     // Turn on the 'throw at end' flag of the reader manager
  2420.     ThrowEOEJanitor jan(&fReaderMgr, true);
  2421.     //  In order to be more efficient we have to use kind of a deeply nested
  2422.     //  set of blocks here. The outer block puts on a try and catches end of
  2423.     //  entity exceptions. The inner loop is the per-character loop. If we
  2424.     //  put the try inside the inner loop, it would work but would require
  2425.     //  the exception handling code setup/teardown code to be invoked for
  2426.     //  each character.
  2427.     XMLCh   nextCh;
  2428.     XMLCh   secondCh = 0;
  2429.     States  curState = State_Waiting;
  2430.     bool    escaped = false;
  2431.     bool    gotLeadingSurrogate = false;
  2432.     bool    notDone = true;
  2433.     while (notDone)
  2434.     {
  2435.         try
  2436.         {
  2437.             while (true)
  2438.             {
  2439.                 //  Eat through as many plain content characters as possible without
  2440.                 //  needing special handling.  Moving most content characters here,
  2441.                 //  in this one call, rather than running the overall loop once
  2442.                 //  per content character, is a speed optimization.
  2443.                 if (curState == State_Waiting  &&  !gotLeadingSurrogate)
  2444.                 {
  2445.                      fReaderMgr.movePlainContentChars(toUse);
  2446.                 }
  2447.                 // Try to get another char from the source
  2448.                 //   The code from here on down covers all contengencies,
  2449.                 if (!fReaderMgr.getNextCharIfNot(chOpenAngle, nextCh))
  2450.                 {
  2451.                     // If we were waiting for a trailing surrogate, its an error
  2452.                     if (gotLeadingSurrogate)
  2453.                         emitError(XMLErrs::Expected2ndSurrogateChar);
  2454.                     notDone = false;
  2455.                     break;
  2456.                 }
  2457.                 //  Watch for a reference. Note that the escapement mechanism
  2458.                 //  is ignored in this content.
  2459.                 escaped = false;
  2460.                 if (nextCh == chAmpersand)
  2461.                 {
  2462.                     sendCharData(toUse);
  2463.                     // Turn off the throwing at the end of entity during this
  2464.                     ThrowEOEJanitor jan(&fReaderMgr, false);
  2465.                     if (scanEntityRef(false, nextCh, secondCh, escaped) != EntityExp_Returned)
  2466.                     {
  2467.                         gotLeadingSurrogate = false;
  2468.                         continue;
  2469.                     }
  2470.                 }
  2471.                 else if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
  2472.                 {
  2473.                     // Deal with surrogate pairs
  2474.                     //  Its a leading surrogate. If we already got one, then
  2475.                     //  issue an error, else set leading flag to make sure that
  2476.                     //  we look for a trailing next time.
  2477.                     if (gotLeadingSurrogate)
  2478.                         emitError(XMLErrs::Expected2ndSurrogateChar);
  2479.                     else
  2480.                         gotLeadingSurrogate = true;
  2481.                 }
  2482.                 else
  2483.                 {
  2484.                     //  If its a trailing surrogate, make sure that we are
  2485.                     //  prepared for that. Else, its just a regular char so make
  2486.                     //  sure that we were not expected a trailing surrogate.
  2487.                     if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF))
  2488.                     {
  2489.                         // Its trailing, so make sure we were expecting it
  2490.                         if (!gotLeadingSurrogate)
  2491.                             emitError(XMLErrs::Unexpected2ndSurrogateChar);
  2492.                     }
  2493.                     else
  2494.                     {
  2495.                         //  Its just a char, so make sure we were not expecting a
  2496.                         //  trailing surrogate.
  2497.                         if (gotLeadingSurrogate)
  2498.                             emitError(XMLErrs::Expected2ndSurrogateChar);
  2499.                         // Make sure the returned char is a valid XML char
  2500.                         if (!fReaderMgr.getCurrentReader()->isXMLChar(nextCh))
  2501.                         {
  2502.                             XMLCh tmpBuf[9];
  2503.                             XMLString::binToText
  2504.                             (
  2505.                                 nextCh
  2506.                                 , tmpBuf
  2507.                                 , 8
  2508.                                 , 16
  2509.                             );
  2510.                             emitError(XMLErrs::InvalidCharacter, tmpBuf);
  2511.                         }
  2512.                     }
  2513.                     gotLeadingSurrogate = false;
  2514.                 }
  2515.                  // Keep the state machine up to date
  2516.                 if (!escaped)
  2517.                 {
  2518.                     if (nextCh == chCloseSquare)
  2519.                     {
  2520.                         if (curState == State_Waiting)
  2521.                             curState = State_GotOne;
  2522.                         else if (curState == State_GotOne)
  2523.                             curState = State_GotTwo;
  2524.                     }
  2525.                     else if (nextCh == chCloseAngle)
  2526.                     {
  2527.                         if (curState == State_GotTwo)
  2528.                             emitError(XMLErrs::BadSequenceInCharData);
  2529.                         curState = State_Waiting;
  2530.                     }
  2531.                     else
  2532.                     {
  2533.                         curState = State_Waiting;
  2534.                     }
  2535.                 }
  2536.                 else
  2537.                 {
  2538.                     curState = State_Waiting;
  2539.                 }
  2540.                 // Add this char to the buffer
  2541.                 toUse.append(nextCh);
  2542.                 if (secondCh)
  2543.                     toUse.append(secondCh);
  2544.             }
  2545.         }
  2546.         catch(const EndOfEntityException& toCatch)
  2547.         {
  2548.             //  Some entity ended, so we have to send any accumulated
  2549.             //  chars and send an end of entity event.
  2550.             sendCharData(toUse);
  2551.             gotLeadingSurrogate = false;
  2552.             if (fDocHandler)
  2553.                 fDocHandler->endEntityReference(toCatch.getEntity());
  2554.         }
  2555.     }
  2556.     // Check the validity constraints as per XML 1.0 Section 2.9
  2557.     if (fValidate && fStandalone)
  2558.     {
  2559.         // See if the text contains whitespace
  2560.         // Get the raw data we need for the callback
  2561.         const XMLCh* rawBuf = toUse.getRawBuffer();
  2562.         const unsigned int len = toUse.getLen();
  2563.         const bool isSpaces = fReaderMgr.getCurrentReader()->containsWhiteSpace(rawBuf, len);
  2564.         if (isSpaces)
  2565.         {
  2566.             // And see if the current element is a 'Children' style content model
  2567.             const ElemStack::StackElem* topElem = fElemStack.topElement();
  2568.             if (topElem->fThisElement->isExternal()) {
  2569.                 // Get the character data opts for the current element
  2570.                 XMLElementDecl::CharDataOpts charOpts =  topElem->fThisElement->getCharDataOpts();
  2571.                 if (charOpts == XMLElementDecl::SpacesOk)  // => Element Content
  2572.                 {
  2573.                     // Error - standalone should have a value of "no" as whitespace detected in an
  2574.                     // element type with element content whose element declaration was external
  2575.                     //
  2576.                     fValidator->emitError(XMLValid::NoWSForStandalone);
  2577.                 }
  2578.             }
  2579.         }
  2580.     }
  2581.     // Send any char data that we accumulated into the buffer
  2582.     sendCharData(toUse);
  2583. }
  2584. //  This method will scan a general/character entity ref. It will either
  2585. //  expand a char ref and return it directly, or push a reader for a general
  2586. //  entity.
  2587. //
  2588. //  The return value indicates whether the char parameters hold the value
  2589. //  or whether the value was pushed as a reader, or that it failed.
  2590. //
  2591. //  The escaped flag tells the caller whether the returned parameter resulted
  2592. //  from a character reference, which escapes the character in some cases. It
  2593. //  only makes any difference if the return value indicates the value was
  2594. //  returned directly.
  2595. DGXMLScanner::EntityExpRes
  2596. DGXMLScanner::scanEntityRef(  const   bool    inAttVal
  2597.                             ,       XMLCh&  firstCh
  2598.                             ,       XMLCh&  secondCh
  2599.                             ,       bool&   escaped)
  2600. {
  2601.     // Assume no escape
  2602.     secondCh = 0;
  2603.     escaped = false;
  2604.     // We have to insure that its all in one entity
  2605.     const unsigned int curReader = fReaderMgr.getCurrentReaderNum();
  2606.     //  If the next char is a pound, then its a character reference and we
  2607.     //  need to expand it always.
  2608.     if (fReaderMgr.skippedChar(chPound))
  2609.     {
  2610.         //  Its a character reference, so scan it and get back the numeric
  2611.         //  value it represents.
  2612.         if (!scanCharRef(firstCh, secondCh))
  2613.             return EntityExp_Failed;
  2614.         escaped = true;
  2615.         if (curReader != fReaderMgr.getCurrentReaderNum())
  2616.             emitError(XMLErrs::PartialMarkupInEntity);
  2617.         return EntityExp_Returned;
  2618.     }
  2619.     // Expand it since its a normal entity ref
  2620.     XMLBufBid bbName(&fBufMgr);
  2621.     if (!fReaderMgr.getName(bbName.getBuffer()))
  2622.     {
  2623.         emitError(XMLErrs::ExpectedEntityRefName);
  2624.         return EntityExp_Failed;
  2625.     }
  2626.     //  Next char must be a semi-colon. But if its not, just emit
  2627.     //  an error and try to continue.
  2628.     if (!fReaderMgr.skippedChar(chSemiColon))
  2629.         emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer());
  2630.     // Make sure we ended up on the same entity reader as the & char
  2631.     if (curReader != fReaderMgr.getCurrentReaderNum())
  2632.         emitError(XMLErrs::PartialMarkupInEntity);
  2633.     // Look up the name in the general entity pool
  2634.     XMLEntityDecl* decl = fDTDGrammar->getEntityDecl(bbName.getRawBuffer());
  2635.     // If it does not exist, then obviously an error
  2636.     if (!decl)
  2637.     {
  2638.         // XML 1.0 Section 4.1
  2639.         // Well-formedness Constraint for entity not found:
  2640.         //   In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references,
  2641.         //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
  2642.         //      or a parameter entity
  2643.         //
  2644.         // Else it's Validity Constraint
  2645.         if (fStandalone || fHasNoDTD)
  2646.             emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer());
  2647.         else {
  2648.             if (fValidate)
  2649.                 fValidator->emitError(XMLValid::VC_EntityNotFound, bbName.getRawBuffer());
  2650.         }
  2651.         return EntityExp_Failed;
  2652.     }
  2653.     // XML 1.0 Section 4.1
  2654.     //  If we are a standalone document, then it has to have been declared
  2655.     //  in the internal subset.
  2656.     if (fStandalone && !decl->getDeclaredInIntSubset())
  2657.         emitError(XMLErrs::IllegalRefInStandalone, bbName.getRawBuffer());
  2658.     if (decl->isExternal())
  2659.     {
  2660.         // If its unparsed, then its not valid here
  2661.         if (decl->isUnparsed())
  2662.         {
  2663.             emitError(XMLErrs::NoUnparsedEntityRefs, bbName.getRawBuffer());
  2664.             return EntityExp_Failed;
  2665.         }
  2666.         // If we are in an attribute value, then not valid but keep going
  2667.         if (inAttVal)
  2668.             emitError(XMLErrs::NoExtRefsInAttValue);
  2669.         // And now create a reader to read this entity
  2670.         InputSource* srcUsed;
  2671.         XMLReader* reader = fReaderMgr.createReader
  2672.         (
  2673.             decl->getBaseURI()
  2674.             , decl->getSystemId()
  2675.             , decl->getPublicId()
  2676.             , false
  2677.             , XMLReader::RefFrom_NonLiteral
  2678.             , XMLReader::Type_General
  2679.             , XMLReader::Source_External
  2680.             , srcUsed
  2681.             , fCalculateSrcOfs
  2682.         );
  2683.         // Put a janitor on the source so it gets cleaned up on exit
  2684.         Janitor<InputSource> janSrc(srcUsed);
  2685.         //  If the creation failed, and its not because the source was empty,
  2686.         //  then emit an error and return.
  2687.         if (!reader)
  2688.             ThrowXML1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed->getSystemId());
  2689.         //  Push the reader. If its a recursive expansion, then emit an error
  2690.         //  and return an failure.
  2691.         if (!fReaderMgr.pushReader(reader, decl))
  2692.         {
  2693.             emitError(XMLErrs::RecursiveEntity, decl->getName());
  2694.             return EntityExp_Failed;
  2695.         }
  2696.         // here's where we need to check if there's a SecurityManager,
  2697.         // how many entity references we've had
  2698.         if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit) {
  2699.             XMLCh expLimStr[16];
  2700.             XMLString::binToText(fEntityExpansionLimit, expLimStr, 15, 10);
  2701.             emitError
  2702.             ( 
  2703.                 XMLErrs::EntityExpansionLimitExceeded
  2704.                 , expLimStr
  2705.             );
  2706.             // there seems nothing better to do than reset the entity expansion counter
  2707.             fEntityExpansionCount = 0;
  2708.         }
  2709.         //  Do a start entity reference event.
  2710.         //
  2711.         //  <TBD> For now, we supress them in att values. Later, when
  2712.         //  the stuff is in place to correctly allow DOM to handle them
  2713.         //  we'll turn this back on.
  2714.         if (fDocHandler && !inAttVal)
  2715.             fDocHandler->startEntityReference(*decl);
  2716.         // If it starts with the XML string, then parse a text decl
  2717.         if (checkXMLDecl(true))
  2718.             scanXMLDecl(Decl_Text);
  2719.     }
  2720.     else
  2721.     {
  2722.         //  If its one of the special char references, then we can return
  2723.         //  it as a character, and its considered escaped.
  2724.         if (decl->getIsSpecialChar())
  2725.         {
  2726.             firstCh = decl->getValue()[0];
  2727.             escaped = true;
  2728.             return EntityExp_Returned;
  2729.         }
  2730.         //  Create a reader over a memory stream over the entity value
  2731.         //  We force it to assume UTF-16 by passing in an encoding
  2732.         //  string. This way it won't both trying to predecode the
  2733.         //  first line, looking for an XML/TextDecl.
  2734.         XMLReader* valueReader = fReaderMgr.createIntEntReader
  2735.         (
  2736.             decl->getName()
  2737.             , XMLReader::RefFrom_NonLiteral
  2738.             , XMLReader::Type_General
  2739.             , decl->getValue()
  2740.             , decl->getValueLen()
  2741.             , false
  2742.         );
  2743.         //  Try to push the entity reader onto the reader manager stack,
  2744.         //  where it will become the subsequent input. If it fails, that
  2745.         //  means the entity is recursive, so issue an error. The reader
  2746.         //  will have just been discarded, but we just keep going.
  2747.         if (!fReaderMgr.pushReader(valueReader, decl))
  2748.             emitError(XMLErrs::RecursiveEntity, decl->getName());
  2749.         // here's where we need to check if there's a SecurityManager,
  2750.         // how many entity references we've had
  2751.         if(fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit) {
  2752.             XMLCh expLimStr[16];
  2753.             XMLString::binToText(fEntityExpansionLimit, expLimStr, 15, 10);
  2754.             emitError
  2755.             ( 
  2756.                 XMLErrs::EntityExpansionLimitExceeded
  2757.                 , expLimStr
  2758.             );
  2759.         }
  2760.         //  Do a start entity reference event.
  2761.         //
  2762.         //  <TBD> For now, we supress them in att values. Later, when
  2763.         //  the stuff is in place to correctly allow DOM to handle them
  2764.         //  we'll turn this back on.
  2765.         if (fDocHandler && !inAttVal)
  2766.             fDocHandler->startEntityReference(*decl);
  2767.         // If it starts with the XML string, then it's an error
  2768.         if (checkXMLDecl(true)) {
  2769.             emitError(XMLErrs::TextDeclNotLegalHere);
  2770.             fReaderMgr.skipPastChar(chCloseAngle);
  2771.         }
  2772.     }
  2773.     return EntityExp_Pushed;
  2774. }
  2775. XERCES_CPP_NAMESPACE_END