XMLScanner2.cpp
上传用户:huihehuasu
上传日期:2007-01-10
资源大小:6948k
文件大小:107k
源码类别:

xml/soap/webservice

开发平台:

C/C++

  1. /*
  2.  * The Apache Software License, Version 1.1
  3.  *
  4.  * Copyright (c) 1999-2001 The Apache Software Foundation.  All rights
  5.  * reserved.
  6.  *
  7.  * Redistribution and use in source and binary forms, with or without
  8.  * modification, are permitted provided that the following conditions
  9.  * are met:
  10.  *
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  *
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in
  16.  *    the documentation and/or other materials provided with the
  17.  *    distribution.
  18.  *
  19.  * 3. The end-user documentation included with the redistribution,
  20.  *    if any, must include the following acknowledgment:
  21.  *       "This product includes software developed by the
  22.  *        Apache Software Foundation (http://www.apache.org/)."
  23.  *    Alternately, this acknowledgment may appear in the software itself,
  24.  *    if and wherever such third-party acknowledgments normally appear.
  25.  *
  26.  * 4. The names "Xerces" and "Apache Software Foundation" must
  27.  *    not be used to endorse or promote products derived from this
  28.  *    software without prior written permission. For written
  29.  *    permission, please contact apache@apache.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "Apache",
  32.  *    nor may "Apache" appear in their name, without prior written
  33.  *    permission of the Apache Software Foundation.
  34.  *
  35.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  36.  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  37.  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  38.  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  39.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  40.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  41.  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  42.  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  43.  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  44.  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  45.  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  46.  * SUCH DAMAGE.
  47.  * ====================================================================
  48.  *
  49.  * This software consists of voluntary contributions made by many
  50.  * individuals on behalf of the Apache Software Foundation, and was
  51.  * originally based on software copyright (c) 1999, International
  52.  * Business Machines, Inc., http://www.ibm.com .  For more information
  53.  * on the Apache Software Foundation, please see
  54.  * <http://www.apache.org/>.
  55.  */
  56. /*
  57.  * $Id: XMLScanner2.cpp,v 1.75 2001/12/06 22:05:52 knoaman Exp $
  58.  */
  59. // ---------------------------------------------------------------------------
  60. //  This file holds some of the grunt work methods of XMLScanner.cpp to keep
  61. //  it a little more readable.
  62. // ---------------------------------------------------------------------------
  63. // ---------------------------------------------------------------------------
  64. //  Includes
  65. // ---------------------------------------------------------------------------
  66. #include <util/BinMemInputStream.hpp>
  67. #include <util/Janitor.hpp>
  68. #include <util/PlatformUtils.hpp>
  69. #include <util/TransService.hpp>
  70. #include <util/UnexpectedEOFException.hpp>
  71. #include <util/XMLUniDefs.hpp>
  72. #include <util/XMLUni.hpp>
  73. #include <util/XMLURL.hpp>
  74. #include <sax/InputSource.hpp>
  75. #include <framework/LocalFileInputSource.hpp>
  76. #include <framework/URLInputSource.hpp>
  77. #include <framework/XMLErrorReporter.hpp>
  78. #include <framework/XMLDocumentHandler.hpp>
  79. #include <framework/XMLEntityHandler.hpp>
  80. #include <framework/XMLPScanToken.hpp>
  81. #include <framework/XMLRefInfo.hpp>
  82. #include <framework/XMLValidator.hpp>
  83. #include <internal/XMLScanner.hpp>
  84. #include <internal/EndOfEntityException.hpp>
  85. #include <internal/XMLInternalErrorHandler.hpp>
  86. #include <parsers/DOMParser.hpp>
  87. #include <dom/DOM_DOMException.hpp>
  88. #include <sax/EntityResolver.hpp>
  89. #include <validators/common/ContentLeafNameTypeVector.hpp>
  90. #include <validators/datatype/DatatypeValidator.hpp>
  91. #include <validators/schema/SchemaSymbols.hpp>
  92. #include <validators/schema/SchemaGrammar.hpp>
  93. #include <validators/schema/TraverseSchema.hpp>
  94. #include <validators/schema/SubstitutionGroupComparator.hpp>
  95. #include <validators/schema/identity/XPathMatcherStack.hpp>
  96. // ---------------------------------------------------------------------------
  97. //  XMLScanner: Private helper methods
  98. // ---------------------------------------------------------------------------
  99. //
  100. //  This method is called from scanStartTagNS() to build up the list of
  101. //  XMLAttr objects that will be passed out in the start tag callout. We
  102. //  get the key/value pairs from the raw scan of explicitly provided attrs,
  103. //  which have not been normalized. And we get the element declaration from
  104. //  which we will get any defaulted or fixed attribute defs and add those
  105. //  in as well.
  106. //
  107. unsigned int
  108. XMLScanner::buildAttList(const  RefVectorOf<KVStringPair>&  providedAttrs
  109.                         , const unsigned int                attCount
  110.                         ,       XMLElementDecl*             elemDecl
  111.                         ,       RefVectorOf<XMLAttr>&       toFill)
  112. {
  113.     //
  114.     //  Ask the element to clear the 'provided' flag on all of the att defs
  115.     //  that it owns, and to return us a boolean indicating whether it has
  116.     //  any defs.
  117.     //
  118.     const bool hasDefs = elemDecl->resetDefs();
  119.     //
  120.     //  If there are no expliclitily provided attributes and there are no
  121.     //  defined attributes for the element, the we don't have anything to do.
  122.     //  So just return zero in this case.
  123.     //
  124.     if (!hasDefs && !attCount)
  125.         return 0;
  126.     // Keep up with how many attrs we end up with total
  127.     unsigned int retCount = 0;
  128.     //
  129.     //  And get the current size of the output vector. This lets us use
  130.     //  existing elements until we fill it, then start adding new ones.
  131.     //
  132.     const unsigned int curAttListSize = toFill.size();
  133.     //
  134.     //  We need a buffer into which raw scanned attribute values will be
  135.     //  normalized.
  136.     //
  137.     XMLBufBid bbNormal(&fBufMgr);
  138.     XMLBuffer& normBuf = bbNormal.getBuffer();
  139.     //
  140.     //  Loop through our explicitly provided attributes, which are in the raw
  141.     //  scanned form, and build up XMLAttr objects.
  142.     //
  143.     unsigned int index;
  144.     for (index = 0; index < attCount; index++)
  145.     {
  146.         const KVStringPair* curPair = providedAttrs.elementAt(index);
  147.         //
  148.         //  We have to split the name into its prefix and name parts. Then
  149.         //  we map the prefix to its URI.
  150.         //
  151.         const XMLCh* const namePtr = curPair->getKey();
  152.         ArrayJanitor<XMLCh> janName(0);
  153.         // use a stack-based buffer when possible.
  154.         XMLCh tempBuffer[100];
  155.         const int colonInd = XMLString::indexOf(namePtr, chColon);
  156.         const XMLCh* prefPtr = XMLUni::fgZeroLenString;
  157.         const XMLCh* suffPtr = XMLUni::fgZeroLenString;
  158.         if (colonInd != -1)
  159.         {
  160.             // We have to split the string, so make a copy.
  161.              if (XMLString::stringLen(namePtr) < sizeof(tempBuffer) / sizeof(tempBuffer[0]))
  162.             {
  163.                 XMLString::copyString(tempBuffer, namePtr);
  164.                 tempBuffer[colonInd] = chNull;
  165.                 prefPtr = tempBuffer;
  166.             }
  167.             else
  168.             {
  169.                 janName.reset(XMLString::replicate(namePtr));
  170.                 janName[colonInd] = chNull;
  171.                 prefPtr = janName.get();
  172.             }
  173.             suffPtr = prefPtr + colonInd + 1;
  174.         }
  175.          else
  176.         {
  177.             // No colon, so we just have a name with no prefix
  178.             suffPtr = namePtr;
  179.         }
  180.         //
  181.         //  Map the prefix to a URI id. We tell him that we are mapping an
  182.         //  attr prefix, so any xmlns attrs at this level will not affect it.
  183.         //
  184.         const unsigned int uriId = resolvePrefix(prefPtr, ElemStack::Mode_Attribute);
  185.         //
  186.         //  If the uri comes back as the xmlns or xml URI or its just a name
  187.         //  and that name is 'xmlns', then we handle it specially. So set a
  188.         //  boolean flag that lets us quickly below know which we are dealing
  189.         //  with.
  190.         //
  191.         const bool isNSAttr = (uriId == fXMLNSNamespaceId)
  192.                               || (uriId == fXMLNamespaceId)
  193.                               || !XMLString::compareString(suffPtr, XMLUni::fgXMLNSString)
  194.                               || !XMLString::compareString(getURIText(uriId), SchemaSymbols::fgURI_XSI);
  195.         //
  196.         //  If its not a special case namespace attr of some sort, then we
  197.         //  do normal checking and processing.
  198.         //
  199.         XMLAttDef::AttTypes attType;
  200.         if (!isNSAttr || fGrammarType == Grammar::DTDGrammarType)
  201.         {
  202.             // Some checking for attribute wild card first (for schema)
  203.             bool laxThisOne = false;
  204.             bool skipThisOne = false;
  205.             XMLAttDef* attDefForWildCard = 0;
  206.             XMLAttDef*  attDef = 0;
  207.             if (fGrammarType == Grammar::SchemaGrammarType) {
  208.                 ComplexTypeInfo* typeInfo = ((SchemaElementDecl*)elemDecl)->getComplexTypeInfo();
  209.                 if (typeInfo) {
  210.                     SchemaAttDef* attWildCard = typeInfo->getAttWildCard();
  211.                     if (attWildCard) {
  212.                         //if schema, see if we should lax or skip the validation of this attribute
  213.                         if (anyAttributeValidation(attWildCard, uriId, skipThisOne, laxThisOne)) {
  214.                             SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(getURIText(uriId));
  215.                             if (sGrammar && sGrammar->getGrammarType() == Grammar::SchemaGrammarType) {
  216.                                 RefHashTableOf<XMLAttDef>* attRegistry = sGrammar->getAttributeDeclRegistry();
  217.                                 if (attRegistry) {
  218.                                     attDefForWildCard = attRegistry->get(suffPtr);
  219.                                 }
  220.                             }
  221.                         }
  222.                     }
  223.                 }
  224.                 //retrieve the att def
  225.                 attDef = ((SchemaElementDecl*)elemDecl)->getAttDef(suffPtr, uriId);
  226.                 if (!attDef) {
  227.                     // not find, see if the attDef should be qualified or not
  228.                     if (uriId == fEmptyNamespaceId) {
  229.                         attDef = ((SchemaElementDecl*)elemDecl)->getAttDef(suffPtr, fURIStringPool->getId(fGrammar->getTargetNamespace()));
  230.                         if (fValidate
  231.                             && attDef
  232.                             && !attDefForWildCard
  233.                             && !skipThisOne
  234.                             && !laxThisOne
  235.                             && attDef->getCreateReason() != XMLAttDef::JustFaultIn) {
  236.                             // the attribute should be qualified
  237.                             fValidator->emitError
  238.                             (
  239.                                 XMLValid::AttributeNotQualified
  240.                                 , attDef->getFullName()
  241.                             );
  242.                         }
  243.                     }
  244.                     else {
  245.                         attDef = ((SchemaElementDecl*)elemDecl)->getAttDef(suffPtr, fEmptyNamespaceId);
  246.                         if (fValidate
  247.                             && attDef
  248.                             && !attDefForWildCard
  249.                             && !skipThisOne
  250.                             && !laxThisOne
  251.                             && attDef->getCreateReason() != XMLAttDef::JustFaultIn) {
  252.                             // the attribute should be qualified
  253.                             fValidator->emitError
  254.                             (
  255.                                 XMLValid::AttributeNotUnQualified
  256.                                 , attDef->getFullName()
  257.                             );
  258.                         }
  259.                     }
  260.                 }
  261.             }
  262.             //
  263.             //  Find this attribute within the parent element. We pass both
  264.             //  the uriID/name and the raw QName buffer, since we don't know
  265.             //  how the derived validator and its elements store attributes.
  266.             //
  267.             bool wasAdded = false;
  268.             if (!attDef) {
  269.                 attDef = elemDecl->findAttr
  270.                 (
  271.                     curPair->getKey()
  272.                     , uriId
  273.                     , suffPtr
  274.                     , prefPtr
  275.                     , XMLElementDecl::AddIfNotFound
  276.                     , wasAdded
  277.                 );
  278.             }
  279.             if (wasAdded)
  280.             {
  281.                 // This is to tell the Validator that this attribute was
  282.                 // faulted-in, was not an attribute in the attdef originally
  283.                 attDef->setCreateReason(XMLAttDef::JustFaultIn);
  284.             }
  285.             if (!attDefForWildCard) {
  286.                 if (wasAdded)
  287.                 {
  288.                     if (fValidate && !skipThisOne && !laxThisOne)
  289.                     {
  290.                         //
  291.                         //  Its not valid for this element, so issue an error if we are
  292.                         //  validating.
  293.                         //
  294.                         XMLBufBid bbURI(&fBufMgr);
  295.                         XMLBuffer& bufURI = bbURI.getBuffer();
  296.                         getURIText(uriId, bufURI);
  297.                         XMLBufBid bbMsg(&fBufMgr);
  298.                         XMLBuffer& bufMsg = bbMsg.getBuffer();
  299.                         bufMsg.append(chOpenCurly);
  300.                         bufMsg.append(bufURI.getRawBuffer());
  301.                         bufMsg.append(chCloseCurly);
  302.                         bufMsg.append(suffPtr);
  303.                         fValidator->emitError
  304.                         (
  305.                             XMLValid::AttNotDefinedForElement
  306.                             , bufMsg.getRawBuffer()
  307.                             , elemDecl->getFullName()
  308.                         );
  309.                     }
  310.                 }
  311.                 else
  312.                 {
  313.                     // If this attribute was faulted-in and first occurence,
  314.                     // then emit an error
  315.                     if (fValidate
  316.                         && attDef->getCreateReason() == XMLAttDef::JustFaultIn
  317.                         && !attDef->getProvided()
  318.                         && !skipThisOne
  319.                         && !laxThisOne)
  320.                     {
  321.                         XMLBufBid bbURI(&fBufMgr);
  322.                         XMLBuffer& bufURI = bbURI.getBuffer();
  323.                         getURIText(uriId, bufURI);
  324.                         XMLBufBid bbMsg(&fBufMgr);
  325.                         XMLBuffer& bufMsg = bbMsg.getBuffer();
  326.                         bufMsg.append(chOpenCurly);
  327.                         bufMsg.append(bufURI.getRawBuffer());
  328.                         bufMsg.append(chCloseCurly);
  329.                         bufMsg.append(suffPtr);
  330.                         fValidator->emitError
  331.                         (
  332.                             XMLValid::AttNotDefinedForElement
  333.                             , bufMsg.getRawBuffer()
  334.                             , elemDecl->getFullName()
  335.                         );
  336.                     }
  337.                 }
  338.             }
  339.             //
  340.             //  If its already provided, then there are more than one of
  341.             //  this attribute in this start tag, so emit an error.
  342.             //
  343.             if (attDef->getProvided())
  344.             {
  345.                 emitError
  346.                 (
  347.                     XMLErrs::AttrAlreadyUsedInSTag
  348.                     , attDef->getFullName()
  349.                     , elemDecl->getFullName()
  350.                 );
  351.             }
  352.              else
  353.             {
  354.                 attDef->setProvided(true);
  355.             }
  356.             //
  357.             //  Now normalize the raw value since we have the attribute type. We
  358.             //  don't care about the return status here. If it failed, an error
  359.             //  was issued, which is all we care about.
  360.             //
  361.             if (attDefForWildCard && (wasAdded || (!wasAdded && attDef->getCreateReason() != XMLAttDef::JustFaultIn))) {
  362.                 normalizeAttValue
  363.                 (
  364.                     attDefForWildCard
  365.                     , curPair->getValue()
  366.                     , normBuf
  367.                 );
  368.                 //
  369.                 //  If we found an attdef for this one, then lets validate it.
  370.                 //
  371.                 if (fValidate && !skipThisOne)
  372.                 {
  373.                     // normalize the attribute according to schema whitespace facet
  374.                     XMLBufBid bbtemp(&fBufMgr);
  375.                     XMLBuffer& tempBuf = bbtemp.getBuffer();
  376.                     DatatypeValidator* tempDV = ((SchemaAttDef*) attDefForWildCard)->getDatatypeValidator();
  377.                     ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, normBuf.getRawBuffer(), tempBuf);
  378.                     normBuf.set(tempBuf.getRawBuffer());
  379.                     fValidator->validateAttrValue
  380.                     (
  381.                         attDefForWildCard
  382.                         , normBuf.getRawBuffer()
  383.                     );
  384.                 }
  385.                 // Save the type for later use
  386.                 attType = attDefForWildCard->getType();
  387.             }
  388.             else {
  389.                 normalizeAttValue
  390.                 (
  391.                     attDef
  392.                     , curPair->getValue()
  393.                     , normBuf
  394.                 );
  395.                 //
  396.                 //  If we found an attdef for this one, then lets validate it.
  397.                 //
  398.                 if (!wasAdded && attDef->getCreateReason() != XMLAttDef::JustFaultIn)
  399.                 {
  400.                     if (fValidate && !skipThisOne)
  401.                     {
  402.                         if (fGrammarType == Grammar::SchemaGrammarType)
  403.                         {
  404.                             // normalize the attribute according to schema whitespace facet
  405.                             XMLBufBid bbtemp(&fBufMgr);
  406.                             XMLBuffer& tempBuf = bbtemp.getBuffer();
  407.                             DatatypeValidator* tempDV = ((SchemaAttDef*) attDef)->getDatatypeValidator();
  408.                             ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, normBuf.getRawBuffer(), tempBuf);
  409.                             normBuf.set(tempBuf.getRawBuffer());
  410.                         }
  411.                         fValidator->validateAttrValue
  412.                         (
  413.                             attDef
  414.                             , normBuf.getRawBuffer()
  415.                         );
  416.                     }
  417.                 }
  418.                 // Save the type for later use
  419.                 attType = attDef->getType();
  420.             }
  421.         }
  422.          else
  423.         {
  424.             // Just normalize as CDATA
  425.             attType = XMLAttDef::CData;
  426.             normalizeAttRawValue
  427.             (
  428.                 curPair->getKey()
  429.                 , curPair->getValue()
  430.                 , normBuf
  431.             );
  432.         }
  433.         //
  434.         //  Add this attribute to the attribute list that we use to pass them
  435.         //  to the handler. We reuse its existing elements but expand it as
  436.         //  required.
  437.         //
  438.         XMLAttr* curAttr;
  439.         if (retCount >= curAttListSize)
  440.         {
  441.             curAttr = new XMLAttr
  442.             (
  443.                 uriId
  444.                 , suffPtr
  445.                 , prefPtr
  446.                 , normBuf.getRawBuffer()
  447.                 , attType
  448.                 , true
  449.             );
  450.             toFill.addElement(curAttr);
  451.         }
  452.          else
  453.         {
  454.             curAttr = toFill.elementAt(retCount);
  455.             curAttr->set
  456.             (
  457.                 uriId
  458.                 , suffPtr
  459.                 , prefPtr
  460.                 , normBuf.getRawBuffer()
  461.                 , attType
  462.             );
  463.             curAttr->setSpecified(true);
  464.         }
  465.         // Bump the count of attrs in the list
  466.         retCount++;
  467.     }
  468.     //
  469.     //  Now, if there are any attributes declared by this element, let's
  470.     //  go through them and make sure that any required ones are provided,
  471.     //  and fault in any fixed ones and defaulted ones that are not provided
  472.     //  literally.
  473.     //
  474.     if (hasDefs && fValidate)
  475.     {
  476.         //
  477.         // Check after all specified attrs are scanned
  478.         // (1) report error for REQUIRED attrs that are missing (V_TAGc)
  479.         // (2) add default attrs if missing (FIXED and NOT_FIXED)
  480.         //
  481.         XMLAttDefList& attDefList = elemDecl->getAttDefList();
  482.         while (attDefList.hasMoreElements())
  483.         {
  484.             // Get the current att def, for convenience and its def type
  485.             const XMLAttDef& curDef = attDefList.nextElement();
  486.             const XMLAttDef::DefAttTypes defType = curDef.getDefaultType();
  487.             if (!curDef.getProvided())
  488.             {
  489.                 //the attributes is not provided
  490.                 if (fValidate)
  491.                 {
  492.                     // If we are validating and its required, then an error
  493.                     if ((defType == XMLAttDef::Required) ||
  494.                         (defType == XMLAttDef::Required_And_Fixed)  )
  495.                     {
  496.                         fValidator->emitError
  497.                         (
  498.                             XMLValid::RequiredAttrNotProvided
  499.                             , curDef.getFullName()
  500.                         );
  501.                     }
  502.                     else if ((defType == XMLAttDef::Default) ||
  503.                              (defType == XMLAttDef::Fixed)  )
  504.                     {
  505.                         if (fStandalone && curDef.isExternal())
  506.                         {
  507.                             //
  508.                             // XML 1.0 Section 2.9
  509.                             // Document is standalone, so attributes must not be defaulted.
  510.                             //
  511.                             fValidator->emitError(XMLValid::NoDefAttForStandalone, curDef.getFullName(), elemDecl->getFullName());
  512.                         }
  513.                     }
  514.                 }
  515.                 //
  516.                 //  Fault in the value if needed, and bump the att count.
  517.                 //  We have to
  518.                 //
  519.                 if ((defType == XMLAttDef::Default)
  520.                 ||  (defType == XMLAttDef::Fixed))
  521.                 {
  522.                     XMLAttr* curAtt;
  523.                     if (retCount >= curAttListSize)
  524.                     {
  525.                         curAtt = new XMLAttr;
  526.                         fValidator->faultInAttr(*curAtt, curDef);
  527.                         fAttrList->addElement(curAtt);
  528.                     }
  529.                     else
  530.                     {
  531.                         curAtt = fAttrList->elementAt(retCount);
  532.                         fValidator->faultInAttr(*curAtt, curDef);
  533.                     }
  534.                     if (fGrammarType == Grammar::DTDGrammarType)
  535.                     {
  536.                         //
  537.                         //  Map the new attribute's prefix to a URI id and store
  538.                         //  that in the attribute object.
  539.                         //
  540.                         curAtt->setURIId
  541.                         (
  542.                             resolvePrefix(curAtt->getPrefix(), ElemStack::Mode_Attribute)
  543.                         );
  544.                     }
  545.                     // Indicate it was not explicitly specified and bump count
  546.                     curAtt->setSpecified(false);
  547.                     retCount++;
  548.                 }
  549.             }
  550.             else
  551.             {
  552.                 //attribute is provided
  553.                 // (schema) report error for PROHIBITED attrs that are present (V_TAGc)
  554.                 if (defType == XMLAttDef::Prohibited && fValidate)
  555.                     fValidator->emitError
  556.                     (
  557.                         XMLValid::ProhibitedAttributePresent
  558.                         , curDef.getFullName()
  559.                     );
  560.             }
  561.         }
  562.     }
  563.     return retCount;
  564. }
  565. //
  566. //  This method is called after the content scan to insure that all the
  567. //  ID/IDREF attributes match up (i.e. that all IDREFs refer to IDs.) This is
  568. //  an XML 1.0 rule, so we can do here in the core.
  569. //
  570. void XMLScanner::checkIDRefs()
  571. {
  572.     //
  573.     //
  574.     //  Iterate the id ref list. If we find any entries here which are used
  575.     //  but not declared, then that's an error.
  576.     //
  577.     RefHashTableOfEnumerator<XMLRefInfo> refEnum(fIDRefList);
  578.     while (refEnum.hasMoreElements())
  579.     {
  580.         // Get a ref to the current element
  581.         const XMLRefInfo& curRef = refEnum.nextElement();
  582.         // If its used but not declared, then its an error
  583.         if (!curRef.getDeclared() && curRef.getUsed() && fValidate)
  584.             fValidator->emitError(XMLValid::IDNotDeclared, curRef.getRefName());
  585.     }
  586. }
  587. //
  588. //  This just does a simple check that the passed progressive scan token is
  589. //  legal for this scanner.
  590. //
  591. bool XMLScanner::isLegalToken(const XMLPScanToken& toCheck)
  592. {
  593.     return ((fScannerId == toCheck.fScannerId)
  594.     &&      (fSequenceId == toCheck.fSequenceId));
  595. }
  596. //
  597. //  This method will take a raw attribute value and normalize it according to
  598. //  the rules of the attribute type. It will put the resulting value into the
  599. //  passed buffer.
  600. //
  601. //  This code assumes that escaped characters in the original value (via char
  602. //  refs) are prefixed by a 0xFFFF character. This is because some characters
  603. //  are legal if escaped only. And some escape chars are not subject to
  604. //  normalization rules.
  605. //
  606. bool XMLScanner::normalizeAttValue( const   XMLAttDef* const    attDef
  607.                                     , const XMLCh* const        value
  608.                                     ,       XMLBuffer&          toFill)
  609. {
  610.     // A simple state value for a whitespace processing state machine
  611.     enum States
  612.     {
  613.         InWhitespace
  614.         , InContent
  615.     };
  616.     // Get the type and name
  617.     const XMLAttDef::AttTypes type = attDef->getType();
  618.     const XMLCh* const attrName = attDef->getFullName();
  619.     // Assume its going to go fine, and empty the target buffer in preperation
  620.     bool retVal = true;
  621.     toFill.reset();
  622.     //
  623.     // Get attribute def - to check to see if it's declared externally or not
  624.     //
  625.     bool  isAttExternal = attDef->isExternal();
  626.     //
  627.     //  Loop through the chars of the source value and normalize it according
  628.     //  to the type.
  629.     //
  630.     States curState = InContent;
  631.     bool escaped;
  632.     bool firstNonWS = false;
  633.     XMLCh nextCh;
  634.     const XMLCh* srcPtr = value;
  635.     while (*srcPtr)
  636.     {
  637.         //
  638.         //  Get the next character from the source. We have to watch for
  639.         //  escaped characters (which are indicated by a 0xFFFF value followed
  640.         //  by the char that was escaped.)
  641.         //
  642.         nextCh = *srcPtr;
  643.         escaped = (nextCh == 0xFFFF);
  644.         if (escaped)
  645.             nextCh = *++srcPtr;
  646.         //
  647.         //  If its not escaped, then make sure its not a < character, which is
  648.         //  not allowed in attribute values.
  649.         //
  650.         if (!escaped && (*srcPtr == chOpenAngle))
  651.         {
  652.             emitError(XMLErrs::BracketInAttrValue, attrName);
  653.             retVal = false;
  654.         }
  655.         if (type == XMLAttDef::CData)
  656.         {
  657.             if (!escaped)
  658.             {
  659.                 if ((nextCh == 0x09) || (nextCh == 0x0A) || (nextCh == 0x0D))
  660.                 {
  661.                     //
  662.                     // Check Validity Constraint for Standalone document declaration
  663.                     // XML 1.0, Section 2.9
  664.                     //
  665.                     if (fStandalone && fValidate && isAttExternal)
  666.                     {
  667.                          //
  668.                          // Can't have a standalone document declaration of "yes" if  attribute
  669.                          // values are subject to normalisation
  670.                          //
  671.                          fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName);
  672.                     }
  673.                     nextCh = chSpace;
  674.                 }
  675.             }
  676.         }
  677.          else
  678.         {
  679.             if (curState == InWhitespace)
  680.             {
  681.                 if (!XMLReader::isWhitespace(nextCh))
  682.                 {
  683.                     if (firstNonWS)
  684.                         toFill.append(chSpace);
  685.                     curState = InContent;
  686.                     firstNonWS = true;
  687.                 }
  688.                  else
  689.                 {
  690.                     srcPtr++;
  691.                     continue;
  692.                 }
  693.             }
  694.              else if (curState == InContent)
  695.             {
  696.                 if (XMLReader::isWhitespace(nextCh))
  697.                 {
  698.                     curState = InWhitespace;
  699.                     srcPtr++;
  700.                     //
  701.                     // Check Validity Constraint for Standalone document declaration
  702.                     // XML 1.0, Section 2.9
  703.                     //
  704.                     if (fStandalone && fValidate && isAttExternal)
  705.                     {
  706.                         if (!firstNonWS || (nextCh != chSpace) || (fReaderMgr.lookingAtSpace()))
  707.                         {
  708.                              //
  709.                              // Can't have a standalone document declaration of "yes" if  attribute
  710.                              // values are subject to normalisation
  711.                              //
  712.                              fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName);
  713.                         }
  714.                     }
  715.                     continue;
  716.                 }
  717.                 firstNonWS = true;
  718.             }
  719.         }
  720.         // Add this char to the target buffer
  721.         toFill.append(nextCh);
  722.         // And move up to the next character in the source
  723.         srcPtr++;
  724.     }
  725.     return retVal;
  726. }
  727. //
  728. //  This method will just normalize the input value as CDATA without
  729. //  any standalone checking.
  730. //
  731. bool XMLScanner::normalizeAttRawValue( const   XMLCh* const        attrName
  732.                                     , const XMLCh* const        value
  733.                                     ,       XMLBuffer&          toFill)
  734. {
  735.     // A simple state value for a whitespace processing state machine
  736.     enum States
  737.     {
  738.         InWhitespace
  739.         , InContent
  740.     };
  741.     // Assume its going to go fine, and empty the target buffer in preperation
  742.     bool retVal = true;
  743.     toFill.reset();
  744.     //
  745.     //  Loop through the chars of the source value and normalize it according
  746.     //  to the type.
  747.     //
  748.     States curState = InContent;
  749.     bool escaped;
  750.     bool firstNonWS = false;
  751.     XMLCh nextCh;
  752.     const XMLCh* srcPtr = value;
  753.     while (*srcPtr)
  754.     {
  755.         //
  756.         //  Get the next character from the source. We have to watch for
  757.         //  escaped characters (which are indicated by a 0xFFFF value followed
  758.         //  by the char that was escaped.)
  759.         //
  760.         nextCh = *srcPtr;
  761.         escaped = (nextCh == 0xFFFF);
  762.         if (escaped)
  763.             nextCh = *++srcPtr;
  764.         //
  765.         //  If its not escaped, then make sure its not a < character, which is
  766.         //  not allowed in attribute values.
  767.         //
  768.         if (!escaped && (*srcPtr == chOpenAngle))
  769.         {
  770.             emitError(XMLErrs::BracketInAttrValue, attrName);
  771.             retVal = false;
  772.         }
  773.         if (!escaped)
  774.         {
  775.             //
  776.             //  NOTE: Yes this is a little redundant in that a 0x20 is
  777.             //  replaced with an 0x20. But its faster to do this (I think)
  778.             //  than checking for 9, A, and D separately.
  779.             //
  780.             if (XMLReader::isWhitespace(nextCh))
  781.                 nextCh = chSpace;
  782.         }
  783.         // Add this char to the target buffer
  784.         toFill.append(nextCh);
  785.         // And move up to the next character in the source
  786.         srcPtr++;
  787.     }
  788.     return retVal;
  789. }
  790. unsigned int
  791. XMLScanner::resolvePrefix(  const   XMLCh* const        prefix
  792.                             , const ElemStack::MapModes mode)
  793. {
  794.     //
  795.     //  Watch for the special namespace prefixes. We always map these to
  796.     //  special URIs. 'xml' gets mapped to the official URI that its defined
  797.     //  to map to by the NS spec. xmlns gets mapped to a special place holder
  798.     //  URI that we define (so that it maps to something checkable.)
  799.     //
  800.     if (!XMLString::compareString(prefix, XMLUni::fgXMLNSString))
  801.         return fXMLNSNamespaceId;
  802.     else if (!XMLString::compareString(prefix, XMLUni::fgXMLString))
  803.         return fXMLNamespaceId;
  804.     //
  805.     //  Ask the element stack to search up itself for a mapping for the
  806.     //  passed prefix.
  807.     //
  808.     bool unknown;
  809.     unsigned int uriId = fElemStack.mapPrefixToURI(prefix, mode, unknown);
  810.     // If it was unknown, then the URI was faked in but we have to issue an error
  811.     if (unknown)
  812.         emitError(XMLErrs::UnknownPrefix, prefix);
  813.     return uriId;
  814. }
  815. unsigned int
  816. XMLScanner::resolvePrefix(  const   XMLCh* const        prefix
  817.                             ,       XMLBuffer&          bufToFill
  818.                             , const ElemStack::MapModes mode)
  819. {
  820.     //
  821.     //  Watch for the special namespace prefixes. We always map these to
  822.     //  special URIs. 'xml' gets mapped to the official URI that its defined
  823.     //  to map to by the NS spec. xmlns gets mapped to a special place holder
  824.     //  URI that we define (so that it maps to something checkable.)
  825.     //
  826.     if (!XMLString::compareString(prefix, XMLUni::fgXMLNSString))
  827.         return fXMLNSNamespaceId;
  828.     else if (!XMLString::compareString(prefix, XMLUni::fgXMLString))
  829.         return fXMLNamespaceId;
  830.     //
  831.     //  Ask the element stack to search up itself for a mapping for the
  832.     //  passed prefix.
  833.     //
  834.     bool unknown;
  835.     unsigned int uriId = fElemStack.mapPrefixToURI(prefix, mode, unknown);
  836.     // If it was unknown, then the URI was faked in but we have to issue an error
  837.     if (unknown)
  838.         emitError(XMLErrs::UnknownPrefix, prefix);
  839.     getURIText(uriId,bufToFill);
  840.     return uriId;
  841. }
  842. //
  843. //  This method will reset the scanner data structures, and related plugged
  844. //  in stuff, for a new scan session. We get the input source for the primary
  845. //  XML entity, create the reader for it, and push it on the stack so that
  846. //  upon successful return from here we are ready to go.
  847. //
  848. void XMLScanner::scanReset(const InputSource& src)
  849. {
  850.     //
  851.     //  This call implicitly tells us that we are going to reuse the scanner
  852.     //  if it was previously used. So tell the validator to reset itself.
  853.     //
  854.     //  But, if the fReuseGrammar flag is set, then don't reset it.
  855.     //
  856.     //  NOTE:   The ReaderMgr is flushed on the way out, because that is
  857.     //          required to insure that files are closed.
  858.     //
  859.     if (!fReuseGrammar) {
  860.         fGrammarResolver->reset();
  861.         resetEntityDeclPool();
  862.         if (fDoNamespaces)
  863.             resetURIStringPool();
  864.         // create a default grammar first
  865.         fGrammar = new DTDGrammar();
  866.         //
  867.         if (fValidatorFromUser) {
  868.             if (fValidator->handlesDTD())
  869.                 fValidator->setGrammar(fGrammar);
  870.         }
  871.         else {
  872.             // set fValidator as fDTDValidator
  873.             fValidator = fDTDValidator;
  874.             fValidator->setGrammar(fGrammar);
  875.         }
  876.         fGrammarType = fGrammar->getGrammarType();
  877.         fGrammarResolver->putGrammar(XMLUni::fgZeroLenString, fGrammar);
  878.         if (fValScheme == Val_Auto) {
  879.             fValidate = false;
  880.         }
  881.     }
  882.     else {
  883.         // reusing grammar, thus the fGrammar must pre-exist already
  884.         // make sure the validator handles this reuse grammar type
  885.         if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) {
  886.             if (fValidatorFromUser)
  887.                 ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  888.             else {
  889.                 fValidator = fSchemaValidator;
  890.             }
  891.         }
  892.         else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) {
  893.             if (fValidatorFromUser)
  894.                 ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  895.             else {
  896.                 fValidator = fDTDValidator;
  897.             }
  898.         }
  899.         if (!fValidator->getGrammar())
  900.             fValidator->setGrammar(fGrammar);
  901.     }
  902.     //
  903.     //  And for all installed handlers, send reset events. This gives them
  904.     //  a chance to flush any cached data.
  905.     //
  906.     if (fDocHandler)
  907.         fDocHandler->resetDocument();
  908.     if (fEntityHandler)
  909.         fEntityHandler->resetEntities();
  910.     if (fErrorReporter)
  911.         fErrorReporter->resetErrors();
  912.     // Clear out the id reference list
  913.     fIDRefList->removeAll();
  914.     // Reset the Root Element Name
  915.     delete [] fRootElemName;
  916.     fRootElemName = 0;
  917.     // Reset IdentityConstraints
  918.     fMatcherStack->clear();
  919.     //
  920.     //  Reset the element stack, and give it the latest ids for the special
  921.     //  URIs it has to know about.
  922.     //
  923.     fElemStack.reset
  924.     (
  925.         fEmptyNamespaceId
  926.         , fUnknownNamespaceId
  927.         , fXMLNamespaceId
  928.         , fXMLNSNamespaceId
  929.     );
  930.     // Reset some status flags
  931.     fInException = false;
  932.     fStandalone = false;
  933.     fErrorCount = 0;
  934.     fHasNoDTD = true;
  935.     fSeeXsi = false;
  936.     // Reset the validators
  937.     fDTDValidator->reset();
  938.     fSchemaValidator->reset();
  939.     if (fValidatorFromUser)
  940.         fValidator->reset();
  941.     //
  942.     //  Handle the creation of the XML reader object for this input source.
  943.     //  This will provide us with transcoding and basic lexing services.
  944.     //
  945.     XMLReader* newReader = fReaderMgr.createReader
  946.     (
  947.         src
  948.         , true
  949.         , XMLReader::RefFrom_NonLiteral
  950.         , XMLReader::Type_General
  951.         , XMLReader::Source_External
  952.     );
  953.     if (!newReader) {
  954.         if (src.getIssueFatalErrorIfNotFound())
  955.             ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId());
  956.         else
  957.             ThrowXML1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId());
  958.     }
  959.     // Push this read onto the reader manager
  960.     fReaderMgr.pushReader(newReader, 0);
  961. }
  962. //
  963. //  This method is called between markup in content. It scans for character
  964. //  data that is sent to the document handler. It watches for any markup
  965. //  characters that would indicate that the character data has ended. It also
  966. //  handles expansion of general and character entities.
  967. //
  968. //  sendData() is a local static helper for this method which handles some
  969. //  code that must be done in three different places here.
  970. //
  971. void XMLScanner::sendCharData(XMLBuffer& toSend)
  972. {
  973.     // If no data in the buffer, then nothing to do
  974.     if (toSend.isEmpty())
  975.         return;
  976.     //
  977.     //  We do different things according to whether we are validating or
  978.     //  not. If not, its always just characters; else, it depends on the
  979.     //  current element's content model.
  980.     //
  981.     if (fValidate)
  982.     {
  983.         // Get the raw data we need for the callback
  984.         const XMLCh* const rawBuf = toSend.getRawBuffer();
  985.         const unsigned int len = toSend.getLen();
  986.         // And see if the current element is a 'Children' style content model
  987.         const ElemStack::StackElem* topElem = fElemStack.topElement();
  988.         // Get the character data opts for the current element
  989.         XMLElementDecl::CharDataOpts charOpts = topElem->fThisElement->getCharDataOpts();
  990.         if (charOpts == XMLElementDecl::NoCharData)
  991.         {
  992.             // They definitely cannot handle any type of char data
  993.             fValidator->emitError(XMLValid::NoCharDataInCM);
  994.         }
  995.          else if (XMLReader::isAllSpaces(rawBuf, len))
  996.         {
  997.             //
  998.             //  Its all spaces. So, if they can take spaces, then send it
  999.             //  as ignorable whitespace. If they can handle any char data
  1000.             //  send it as characters.
  1001.             //
  1002.             if (charOpts == XMLElementDecl::SpacesOk) {
  1003.                 if (fDocHandler)
  1004.                     fDocHandler->ignorableWhitespace(rawBuf, len, false);
  1005.             }
  1006.             else if (charOpts == XMLElementDecl::AllCharData)
  1007.             {
  1008.                 if (fGrammarType != Grammar::SchemaGrammarType)
  1009.                 {
  1010.                     if (fDocHandler)
  1011.                         fDocHandler->docCharacters(rawBuf, len, false);
  1012.                 }
  1013.                 else
  1014.                 {
  1015.                     // The normalized data can only be as large as the
  1016.                     // original size, so this will avoid allocating way
  1017.                     // too much or too little memory.
  1018.                     XMLBuffer toFill(len+1);
  1019.                     // normalize the character according to schema whitespace facet
  1020.                     DatatypeValidator* tempDV = ((SchemaElementDecl*) topElem->fThisElement)->getDatatypeValidator();
  1021.                     ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, rawBuf, toFill);
  1022.                     // call all active identity constraints
  1023.                     unsigned int count = fMatcherStack->getMatcherCount();
  1024.                     for (unsigned int i = 0; i < count; i++) {
  1025.                         fMatcherStack->getMatcherAt(i)->docCharacters(toFill.getRawBuffer(), toFill.getLen());
  1026.                     }
  1027.                     if (fDocHandler)
  1028.                         fDocHandler->docCharacters(toFill.getRawBuffer(), toFill.getLen(), false);
  1029.                 }
  1030.             }
  1031.         }
  1032.          else
  1033.         {
  1034.             //
  1035.             //  If they can take any char data, then send it. Otherwise, they
  1036.             //  can only handle whitespace and can't handle this stuff so
  1037.             //  issue an error.
  1038.             //
  1039.             if (charOpts == XMLElementDecl::AllCharData)
  1040.             {
  1041.                 if (fGrammarType != Grammar::SchemaGrammarType)
  1042.                 {
  1043.                     if (fDocHandler)
  1044.                         fDocHandler->docCharacters(rawBuf, len, false);
  1045.                 }
  1046.                 else
  1047.                 {
  1048.                     // The normalized data can only be as large as the
  1049.                     // original size, so this will avoid allocating way
  1050.                     // too much or too little memory.
  1051.                     XMLBuffer toFill(len+1);
  1052.                     // normalize the character according to schema whitespace facet
  1053.                     DatatypeValidator* tempDV = ((SchemaElementDecl*) topElem->fThisElement)->getDatatypeValidator();
  1054.                     ((SchemaValidator*) fValidator)->normalizeWhiteSpace(tempDV, rawBuf, toFill);
  1055.                     // call all active identity constraints
  1056.                     unsigned int count = fMatcherStack->getMatcherCount();
  1057.                     for (unsigned int i = 0; i < count; i++) {
  1058.                         fMatcherStack->getMatcherAt(i)->docCharacters(toFill.getRawBuffer(), toFill.getLen());
  1059.                     }
  1060.                     if (fDocHandler)
  1061.                         fDocHandler->docCharacters(toFill.getRawBuffer(), toFill.getLen(), false);
  1062.                 }
  1063.             }
  1064.              else
  1065.             {
  1066.                 fValidator->emitError(XMLValid::NoCharDataInCM);
  1067.             }
  1068.         }
  1069.     }
  1070.      else
  1071.     {
  1072.         // call all active identity constraints
  1073.         if (fGrammarType == Grammar::SchemaGrammarType) {
  1074.             unsigned int count = fMatcherStack->getMatcherCount();
  1075.             for (unsigned int i = 0; i < count; i++) {
  1076.                 fMatcherStack->getMatcherAt(i)->docCharacters(toSend.getRawBuffer(), toSend.getLen());
  1077.             }
  1078.         }
  1079.         // Always assume its just char data if not validating
  1080.         if (fDocHandler)
  1081.             fDocHandler->docCharacters(toSend.getRawBuffer(), toSend.getLen(), false);
  1082.     }
  1083.     // Reset buffer
  1084.     toSend.reset();
  1085. }
  1086. //
  1087. //  This method will handle figuring out what the next top level token is
  1088. //  in the input stream. It will return an enumerated value that indicates
  1089. //  what it believes the next XML level token must be. It will eat as many
  1090. //  chars are required to figure out what is next.
  1091. //
  1092. XMLScanner::XMLTokens XMLScanner::senseNextToken(unsigned int& orgReader)
  1093. {
  1094.     //
  1095.     //  Get the next character and use it to guesstimate what the next token
  1096.     //  is going to be. We turn on end of entity exceptions when we do this
  1097.     //  in order to catch the scenario where the current entity ended at
  1098.     //  the > of some markup.
  1099.     //
  1100.     XMLCh nextCh;
  1101.     {
  1102.         ThrowEOEJanitor janMgr(&fReaderMgr, true);
  1103.         nextCh = fReaderMgr.peekNextChar();
  1104.     }
  1105.     //
  1106.     //  Check for special chars. Start with the most
  1107.     //  obvious end of file, which should be legal here at top level.
  1108.     //
  1109.     if (!nextCh)
  1110.         return Token_EOF;
  1111.     //
  1112.     //  If it's not a '<' we must be in content.
  1113.     //
  1114.     //  This includes entity references '&' of some sort. These must
  1115.     //  be character data because that's the only place a reference can
  1116.     //  occur in content.
  1117.     //
  1118.     if (nextCh != chOpenAngle)
  1119.         return Token_CharData;
  1120.     //
  1121.     //
  1122.     //  Ok it had to have been a '<' character. So get it out of the reader
  1123.     //  and store the reader number where we saw it, passing it back to the
  1124.     //  caller.
  1125.     //
  1126.     fReaderMgr.getNextChar();
  1127.     orgReader = fReaderMgr.getCurrentReaderNum();
  1128.     //
  1129.     //  Ok, so lets go through the things that it could be at this point which
  1130.     //  are all some form of markup.
  1131.     //
  1132.     nextCh = fReaderMgr.peekNextChar();
  1133.     if (nextCh == chForwardSlash)
  1134.     {
  1135.         fReaderMgr.getNextChar();
  1136.         return Token_EndTag;
  1137.     }
  1138.     else if (nextCh == chBang)
  1139.     {
  1140.         static const XMLCh gCDATAStr[] =
  1141.         {
  1142.                 chBang, chOpenSquare, chLatin_C, chLatin_D, chLatin_A
  1143.             ,   chLatin_T, chLatin_A, chNull
  1144.         };
  1145.         static const XMLCh gCommentString[] =
  1146.         {
  1147.             chBang, chDash, chDash, chNull
  1148.         };
  1149.         if (fReaderMgr.skippedString(gCDATAStr))
  1150.             return Token_CData;
  1151.         if (fReaderMgr.skippedString(gCommentString))
  1152.             return Token_Comment;
  1153.         emitError(XMLErrs::ExpectedCommentOrCDATA);
  1154.         return Token_Unknown;
  1155.     }
  1156.      else if (nextCh == chQuestion)
  1157.     {
  1158.         // It must be a PI
  1159.         fReaderMgr.getNextChar();
  1160.         return Token_PI;
  1161.     }
  1162.     //
  1163.     //  Assume its an element name, so return with a start tag token. If it
  1164.     //  turns out not to be, then it will fail when it cannot get a valid tag.
  1165.     //
  1166.     return Token_StartTag;
  1167. }
  1168. //
  1169. //  This method is called with a key/value string pair that represents an
  1170. //  xmlns="xxx" or xmlns:xxx="yyy" attribute. This method will update the
  1171. //  current top of the element stack based on this data. We know that when
  1172. //  we get here, that it is one of these forms, so we don't bother confirming
  1173. //  it.
  1174. //
  1175. void XMLScanner::updateNSMap(const  XMLCh* const    attrName
  1176.                             , const XMLCh* const    attrValue)
  1177. {
  1178.     // We need a buffer to normalize the attribute value into
  1179.     XMLBufBid bbNormal(&fBufMgr);
  1180.     XMLBuffer& normalBuf = bbNormal.getBuffer();
  1181.     //  We either have the default prefix (""), or we point it into the attr
  1182.     //  name parameter. Note that the xmlns is not the prefix we care about
  1183.     //  here. To us, the 'prefix' is really the local part of the attrName
  1184.     //  parameter.
  1185.     //
  1186.     const XMLCh* prefPtr = XMLUni::fgZeroLenString;
  1187.     const unsigned int colonOfs = XMLString::indexOf(attrName, chColon);
  1188.     if (colonOfs != -1)
  1189.         prefPtr = &attrName[colonOfs + 1];
  1190.     //
  1191.     //  Normalize the value into the passed buffer. In this case, we don't
  1192.     //  care about the return value. An error was issued for the error, which
  1193.     //  is all we care about here.
  1194.     //
  1195.     normalizeAttRawValue(attrName, attrValue, normalBuf);
  1196.     //
  1197.     //  Ok, we have to get the unique id for the attribute value, which is the
  1198.     //  URI that this value should be mapped to. The validator has the
  1199.     //  namespace string pool, so we ask him to find or add this new one. Then
  1200.     //  we ask the element stack to add this prefix to URI Id mapping.
  1201.     //
  1202.     fElemStack.addPrefix
  1203.     (
  1204.         prefPtr
  1205.         , fURIStringPool->addOrFind(normalBuf.getRawBuffer())
  1206.     );
  1207. }
  1208. void XMLScanner::scanRawAttrListforNameSpaces(const RefVectorOf<KVStringPair>* theRawAttrList, int attCount) {
  1209.     //  Schema Xsi Type yyyy (e.g. xsi:type="yyyyy")
  1210.     XMLBufBid bbXsi(&fBufMgr);
  1211.     XMLBuffer& fXsiType = bbXsi.getBuffer();
  1212.     //
  1213.     //  Make an initial pass through the list and find any xmlns attributes or
  1214.     //  schema attributes.
  1215.     //  When we find one, send it off to be used to update the element stack's
  1216.     //  namespace mappings.
  1217.     //
  1218.     int index = 0;
  1219.     for (index = 0; index < attCount; index++)
  1220.     {
  1221.         // each attribute has the prefix:suffix="value"
  1222.         const KVStringPair* curPair = fRawAttrList->elementAt(index);
  1223.         const XMLCh* valuePtr = curPair->getValue();
  1224.         const XMLCh* rawPtr = curPair->getKey();
  1225.         QName attName(rawPtr, fEmptyNamespaceId);
  1226.         const XMLCh* suffPtr = attName.getLocalPart();
  1227.         //  If either the key begins with "xmlns:" or its just plain
  1228.         //  "xmlns", then use it to update the map.
  1229.         //
  1230.         if (!XMLString::compareNString(rawPtr, XMLUni::fgXMLNSColonString, 6)
  1231.         ||  !XMLString::compareString(rawPtr, XMLUni::fgXMLNSString))
  1232.         {
  1233.             updateNSMap(rawPtr, valuePtr);
  1234.             // if the schema URI is seen in the the valuePtr, set the boolean seeXsi
  1235.             if (!XMLString::compareString(valuePtr, SchemaSymbols::fgURI_XSI)) {
  1236.                 fSeeXsi = true;
  1237.             }
  1238.         }
  1239.     }
  1240.     // walk through the list again to deal with "xsi:...."
  1241.     if (fDoSchema && fSeeXsi)
  1242.     {
  1243.         for (index = 0; index < attCount; index++)
  1244.         {
  1245.             // each attribute has the prefix:suffix="value"
  1246.             const KVStringPair* curPair = fRawAttrList->elementAt(index);
  1247.             const XMLCh* valuePtr = curPair->getValue();
  1248.             const XMLCh* rawPtr = curPair->getKey();
  1249.             QName attName(rawPtr, fEmptyNamespaceId);
  1250.             const XMLCh* prefPtr = attName.getPrefix();
  1251.             const XMLCh* suffPtr = attName.getLocalPart();
  1252.             // if schema URI has been seen, scan for the schema location and uri
  1253.             // and resolve the schema grammar; or scan for schema type
  1254.             if (resolvePrefix(prefPtr, ElemStack::Mode_Attribute) == fSchemaNamespaceId) {
  1255.                 if (!fReuseGrammar) {
  1256.                     if (!XMLString::compareString(suffPtr, SchemaSymbols::fgXSI_SCHEMALOCACTION))
  1257.                         parseSchemaLocation(valuePtr);
  1258.                     else if (!XMLString::compareString(suffPtr, SchemaSymbols::fgXSI_NONAMESPACESCHEMALOCACTION))
  1259.                         resolveSchemaGrammar(valuePtr, XMLUni::fgZeroLenString);
  1260.                 }
  1261.                 if (!XMLString::compareString(suffPtr, SchemaSymbols::fgXSI_TYPE)) {
  1262.                         fXsiType.set(valuePtr);
  1263.                 }
  1264.                 else if (!XMLString::compareString(suffPtr, SchemaSymbols::fgATT_NILL)
  1265.                          && fValidator && fValidator->handlesSchema()
  1266.                          && !XMLString::compareString(valuePtr, SchemaSymbols::fgATTVAL_TRUE)) {
  1267.                             ((SchemaValidator*)fValidator)->setNillable(true);
  1268.                 }
  1269.             }
  1270.         }
  1271.         if (fValidator && fValidator->handlesSchema()) {
  1272.             if (!fXsiType.isEmpty()) {
  1273.                 unsigned int uriId = resolveQName (
  1274.                       fXsiType.getRawBuffer()
  1275.                     , fNameBuf
  1276.                     , fPrefixBuf
  1277.                     , ElemStack::Mode_Element
  1278.                 );
  1279.                 ((SchemaValidator*)fValidator)->setXsiType(fPrefixBuf.getRawBuffer(), fNameBuf.getRawBuffer(), uriId);
  1280.             }
  1281.         }
  1282.     }
  1283. }
  1284. void XMLScanner::parseSchemaLocation(const XMLCh* const schemaLocationStr)
  1285. {
  1286.     RefVectorOf<XMLCh>* schemaLocation = XMLString::tokenizeString(schemaLocationStr);
  1287.     unsigned int size = schemaLocation->size();
  1288.     if (size % 2 != 0 ) {
  1289.         emitError(XMLErrs::BadSchemaLocation);
  1290.     } else {
  1291.         for(unsigned int i=0; i<size; i=i+2) {
  1292.             resolveSchemaGrammar(schemaLocation->elementAt(i+1), schemaLocation->elementAt(i));
  1293.         }
  1294.     }
  1295.     delete schemaLocation;
  1296. }
  1297. void XMLScanner::resolveSchemaGrammar(const XMLCh* const loc, const XMLCh* const uri) {
  1298.     Grammar* grammar = fGrammarResolver->getGrammar(uri);
  1299.     if (!grammar || grammar->getGrammarType() == Grammar::DTDGrammarType) {
  1300.         DOMParser parser;
  1301.         XMLInternalErrorHandler internalErrorHandler(fErrorHandler);
  1302.         parser.setValidationScheme(DOMParser::Val_Never);
  1303.         parser.setDoNamespaces(true);
  1304.         parser.setErrorHandler((ErrorHandler*) &internalErrorHandler);
  1305.         parser.setEntityResolver(fEntityResolver);
  1306.         // Create a buffer for expanding the system id
  1307.         XMLBufBid bbSys(&fBufMgr);
  1308.         XMLBuffer& expSysId = bbSys.getBuffer();
  1309.         //
  1310.         //  Allow the entity handler to expand the system id if they choose
  1311.         //  to do so.
  1312.         //
  1313.         if (fEntityHandler)
  1314.         {
  1315.             if (!fEntityHandler->expandSystemId(loc, expSysId))
  1316.                 expSysId.set(loc);
  1317.         }
  1318.          else
  1319.         {
  1320.             expSysId.set(loc);
  1321.         }
  1322.         // Call the entity resolver interface to get an input source
  1323.         InputSource* srcToFill = 0;
  1324.         if (fEntityResolver)
  1325.         {
  1326.             srcToFill = fEntityResolver->resolveEntity
  1327.             (
  1328.                 XMLUni::fgZeroLenString
  1329.                 , expSysId.getRawBuffer()
  1330.             );
  1331.         }
  1332.         //
  1333.         //  If they didn't create a source via the entity resolver, then we
  1334.         //  have to create one on our own.
  1335.         //
  1336.         if (!srcToFill)
  1337.         {
  1338.             ReaderMgr::LastExtEntityInfo lastInfo;
  1339.             fReaderMgr.getLastExtEntityInfo(lastInfo);
  1340.             try
  1341.             {
  1342.                 XMLURL urlTmp(lastInfo.systemId, expSysId.getRawBuffer());
  1343.                 if (urlTmp.isRelative())
  1344.                 {
  1345.                     ThrowXML
  1346.                     (
  1347.                         MalformedURLException
  1348.                         , XMLExcepts::URL_NoProtocolPresent
  1349.                     );
  1350.                 }
  1351.                 srcToFill = new URLInputSource(urlTmp);
  1352.             }
  1353.             catch(const MalformedURLException&)
  1354.             {
  1355.                 // Its not a URL, so lets assume its a local file name.
  1356.                 srcToFill = new LocalFileInputSource
  1357.                 (
  1358.                     lastInfo.systemId
  1359.                     , expSysId.getRawBuffer()
  1360.                 );
  1361.             }
  1362.         }
  1363.         // Put a janitor on the input source
  1364.         Janitor<InputSource> janSrc(srcToFill);
  1365.         // Should just issue warning if the schema is not found
  1366.         const bool flag = srcToFill->getIssueFatalErrorIfNotFound();
  1367.         srcToFill->setIssueFatalErrorIfNotFound(false);
  1368.         parser.parse(*srcToFill) ;
  1369.         // Reset the InputSource
  1370.         srcToFill->setIssueFatalErrorIfNotFound(flag);
  1371.         if (internalErrorHandler.getSawFatal() && fExitOnFirstFatal)
  1372.             emitError(XMLErrs::SchemaScanFatalError);
  1373.         DOM_Document  document = parser.getDocument(); //Our Grammar
  1374.         if (!document.isNull()) {
  1375.             DOM_Element root = document.getDocumentElement();// This is what we pass to TraverserSchema
  1376.             if (!root.isNull())
  1377.             {
  1378.                 const XMLCh* newUri = root.getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE).rawBuffer();
  1379.                 if (XMLString::compareString(newUri, uri)) {
  1380.                     if (fValidate)
  1381.                         fValidator->emitError(XMLValid::WrongTargetNamespace, loc, uri);
  1382.                     grammar = fGrammarResolver->getGrammar(newUri);
  1383.                 }
  1384.                 if (!grammar || grammar->getGrammarType() == Grammar::DTDGrammarType) {
  1385.                     //
  1386.                     //  Since we have seen a grammar, set our validation flag
  1387.                     //  at this point if the validation scheme is auto
  1388.                     //
  1389.                     if (fValScheme == Val_Auto && !fValidate) {
  1390.                         fValidate = true;
  1391.                         fElemStack.setValidationFlag(fValidate);
  1392.                     }
  1393.                     // we have seen a schema, so set up the fValidator as fSchemaValidator
  1394.                     if (!fValidator->handlesSchema())
  1395.                     {
  1396.                         if (fValidatorFromUser) {
  1397.                             // the fValidator is from user
  1398.                             ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  1399.                         }
  1400.                         else {
  1401.                             fValidator = fSchemaValidator;
  1402.                         }
  1403.                     }
  1404.                     grammar = new SchemaGrammar();
  1405.                     TraverseSchema traverseSchema(root, fURIStringPool, (SchemaGrammar*) grammar, fGrammarResolver, this, fValidator, srcToFill->getSystemId(), fEntityResolver, fErrorHandler);
  1406.                     if (fGrammarType == Grammar::DTDGrammarType) {
  1407.                         fGrammar = grammar;
  1408.                         fGrammarType = Grammar::SchemaGrammarType;
  1409.                         fValidator->setGrammar(fGrammar);
  1410.                     }
  1411.                     if (!fReuseGrammar && fValidate) {
  1412.                         //  validate the Schema scan so far
  1413.                         fValidator->preContentValidation(fReuseGrammar);
  1414.                     }
  1415.                 }
  1416.             }
  1417.         }
  1418.     }
  1419.     else {
  1420.         //
  1421.         //  Since we have seen a grammar, set our validation flag
  1422.         //  at this point if the validation scheme is auto
  1423.         //
  1424.         if (fValScheme == Val_Auto && !fValidate) {
  1425.             fValidate = true;
  1426.             fElemStack.setValidationFlag(fValidate);
  1427.         }
  1428.         // we have seen a schema, so set up the fValidator as fSchemaValidator
  1429.         if (!fValidator->handlesSchema())
  1430.         {
  1431.             if (fValidatorFromUser) {
  1432.                 // the fValidator is from user
  1433.                 ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  1434.             }
  1435.             else {
  1436.                 fValidator = fSchemaValidator;
  1437.             }
  1438.         }
  1439.         if (fGrammarType == Grammar::DTDGrammarType) {
  1440.             fGrammar = grammar;
  1441.             fGrammarType = Grammar::SchemaGrammarType;
  1442.             fValidator->setGrammar(fGrammar);
  1443.         }
  1444.     }
  1445. }
  1446. // ---------------------------------------------------------------------------
  1447. //  XMLScanner: Private parsing methods
  1448. // ---------------------------------------------------------------------------
  1449. //
  1450. //  This guy just scans out a single or double quoted string of characters.
  1451. //  It does not pass any judgement on the contents and assumes that it is
  1452. //  illegal to have another quote of the same kind inside the string's
  1453. //  contents.
  1454. //
  1455. //  NOTE: This is for simple stuff like the strings in the XMLDecl which
  1456. //  cannot have any entities inside them. So this guy does not handle any
  1457. //  end of entity stuff.
  1458. //
  1459. bool XMLScanner::getQuotedString(XMLBuffer& toFill)
  1460. {
  1461.     // Reset the target buffer
  1462.     toFill.reset();
  1463.     // Get the next char which must be a single or double quote
  1464.     XMLCh quoteCh;
  1465.     if (!fReaderMgr.skipIfQuote(quoteCh))
  1466.         return false;
  1467.     while (true)
  1468.     {
  1469.         // Get another char
  1470.         const XMLCh nextCh = fReaderMgr.getNextChar();
  1471.         // See if it matches the starting quote char
  1472.         if (nextCh == quoteCh)
  1473.             break;
  1474.         //
  1475.         //  We should never get either an end of file null char here. If we
  1476.         //  do, just fail. It will be handled more gracefully in the higher
  1477.         //  level code that called us.
  1478.         //
  1479.         if (!nextCh)
  1480.             return false;
  1481.         // Else add it to the buffer
  1482.         toFill.append(nextCh);
  1483.     }
  1484.     return true;
  1485. }
  1486. //
  1487. //  This method is called to do a raw scan of an attribute value. It does not
  1488. //  do normalization (since we don't know their types yet.) It just scans the
  1489. //  value and does entity expansion.
  1490. //
  1491. //  End of entity's must be dealt with here. During DTD scan, they can come
  1492. //  from external entities. During content, they can come from any entity.
  1493. //  We just eat the end of entity and continue with our scan until we come
  1494. //  to the closing quote. If an unterminated value causes us to go through
  1495. //  subsequent entities, that will cause errors back in the calling code,
  1496. //  but there's little we can do about it here.
  1497. //
  1498. bool XMLScanner::basicAttrValueScan(const XMLCh* const attrName, XMLBuffer& toFill)
  1499. {
  1500.     // Reset the target buffer
  1501.     toFill.reset();
  1502.     // Get the next char which must be a single or double quote
  1503.     XMLCh quoteCh;
  1504.     if (!fReaderMgr.skipIfQuote(quoteCh))
  1505.         return false;
  1506.     //
  1507.     //  We have to get the current reader because we have to ignore closing
  1508.     //  quotes until we hit the same reader again.
  1509.     //
  1510.     const unsigned int curReader = fReaderMgr.getCurrentReaderNum();
  1511.     //
  1512.     //  Loop until we get the attribute value. Note that we use a double
  1513.     //  loop here to avoid the setup/teardown overhead of the exception
  1514.     //  handler on every round.
  1515.     //
  1516.     XMLCh   nextCh;
  1517.     XMLCh   secondCh = 0;
  1518.     bool    gotLeadingSurrogate = false;
  1519.     bool    escaped;
  1520.     while (true)
  1521.     {
  1522.         try
  1523.         {
  1524.             while(true)
  1525.             {
  1526.                 // Get another char. Use second char if one is waiting
  1527.                 if (secondCh)
  1528.                 {
  1529.                     nextCh = secondCh;
  1530.                     secondCh = 0;
  1531.                 }
  1532.                  else
  1533.                 {
  1534.                     nextCh = fReaderMgr.getNextChar();
  1535.                 }
  1536.                 if (!nextCh)
  1537.                     ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  1538.                 //
  1539.                 //  Check for our ending quote. It has to be in the same entity
  1540.                 //  as where we started. Quotes in nested entities are ignored.
  1541.                 //
  1542.                 if (nextCh == quoteCh)
  1543.                 {
  1544.                     if (curReader == fReaderMgr.getCurrentReaderNum())
  1545.                         return true;
  1546.                     // Watch for spillover into a previous entity
  1547.                     if (curReader > fReaderMgr.getCurrentReaderNum())
  1548.                     {
  1549.                         emitError(XMLErrs::PartialMarkupInEntity);
  1550.                         return false;
  1551.                     }
  1552.                 }
  1553.                 //
  1554.                 //  Check for an entity ref . We ignore the empty flag in
  1555.                 //  this one.
  1556.                 //
  1557.                 escaped = false;
  1558.                 if (nextCh == chAmpersand)
  1559.                 {
  1560.                     // If it was not returned directly, then jump back up
  1561.                     if (scanEntityRef(true, nextCh, secondCh, escaped) != EntityExp_Returned)
  1562.                     {
  1563.                         gotLeadingSurrogate = false;
  1564.                         continue;
  1565.                     }
  1566.                 }
  1567.                 // Deal with surrogate pairs
  1568.                 if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
  1569.                 {
  1570.                     //
  1571.                     //  Its a leading surrogate. If we already got one, then
  1572.                     //  issue an error, else set leading flag to make sure that
  1573.                     //  we look for a trailing next time.
  1574.                     //
  1575.                     if (gotLeadingSurrogate)
  1576.                     {
  1577.                         emitError(XMLErrs::Expected2ndSurrogateChar);
  1578.                     }
  1579.                      else
  1580.                     {
  1581.                         // Its got to at least be a valid XML character
  1582.                         if (!XMLReader::isXMLChar(nextCh))
  1583.                         {
  1584.                             XMLCh tmpBuf[9];
  1585.                             XMLString::binToText
  1586.                             (
  1587.                                 nextCh
  1588.                                 , tmpBuf
  1589.                                 , 8
  1590.                                 , 16
  1591.                             );
  1592.                             emitError(XMLErrs::InvalidCharacterInAttrValue, attrName, tmpBuf);
  1593.                         }
  1594.                         gotLeadingSurrogate = true;
  1595.                     }
  1596.                 }
  1597.                  else
  1598.                 {
  1599.                     //
  1600.                     //  If its a trailing surrogate, make sure that we are
  1601.                     //  prepared for that. Else, its just a regular char so make
  1602.                     //  sure that we were not expected a trailing surrogate.
  1603.                     //
  1604.                     if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF))
  1605.                     {
  1606.                         // Its trailing, so make sure we were expecting it
  1607.                         if (!gotLeadingSurrogate)
  1608.                             emitError(XMLErrs::Unexpected2ndSurrogateChar);
  1609.                     }
  1610.                      else
  1611.                     {
  1612.                         //
  1613.                         //  Its just a char, so make sure we were not expecting a
  1614.                         //  trailing surrogate.
  1615.                         //
  1616.                         if (gotLeadingSurrogate)
  1617.                             emitError(XMLErrs::Expected2ndSurrogateChar);
  1618.                     }
  1619.                     gotLeadingSurrogate = false;
  1620.                 }
  1621.                 //
  1622.                 //  If it was escaped, then put in a 0xFFFF value. This will
  1623.                 //  be used later during validation and normalization of the
  1624.                 //  value to know that the following character was via an
  1625.                 //  escape char.
  1626.                 //
  1627.                 if (escaped)
  1628.                     toFill.append(0xFFFF);
  1629.                 // Else add it to the buffer
  1630.                 toFill.append(nextCh);
  1631.             }
  1632.         }
  1633.         catch(const EndOfEntityException&)
  1634.         {
  1635.             // Just eat it and continue.
  1636.             gotLeadingSurrogate = false;
  1637.             escaped = false;
  1638.         }
  1639.     }
  1640.     return true;
  1641. }
  1642. bool XMLScanner::scanAttValue(  const   XMLAttDef* const    attDef
  1643.                                 ,       XMLBuffer&          toFill)
  1644. {
  1645.     enum States
  1646.     {
  1647.         InWhitespace
  1648.         , InContent
  1649.     };
  1650.     // Get the type and name
  1651.     const XMLAttDef::AttTypes type = attDef->getType();
  1652.     const XMLCh* const attrName = attDef->getFullName();
  1653.     // Reset the target buffer
  1654.     toFill.reset();
  1655.     // Get the next char which must be a single or double quote
  1656.     XMLCh quoteCh;
  1657.     if (!fReaderMgr.skipIfQuote(quoteCh))
  1658.         return false;
  1659.     //
  1660.     //  We have to get the current reader because we have to ignore closing
  1661.     //  quotes until we hit the same reader again.
  1662.     //
  1663.     const unsigned int curReader = fReaderMgr.getCurrentReaderNum();
  1664.     //
  1665.     // Get attribute def - to check to see if it's declared externally or not
  1666.     //
  1667.     bool  isAttExternal = attDef->isExternal();
  1668.     //
  1669.     //  Loop until we get the attribute value. Note that we use a double
  1670.     //  loop here to avoid the setup/teardown overhead of the exception
  1671.     //  handler on every round.
  1672.     //
  1673.     XMLCh   nextCh;
  1674.     XMLCh   secondCh = 0;
  1675.     States  curState = InContent;
  1676.     bool    firstNonWS = false;
  1677.     bool    gotLeadingSurrogate = false;
  1678.     bool    escaped;
  1679.     while (true)
  1680.     {
  1681.     try
  1682.     {
  1683.         while(true)
  1684.         {
  1685.             // Get another char. Use second char if one is waiting
  1686.             if (secondCh)
  1687.             {
  1688.                 nextCh = secondCh;
  1689.                 secondCh = 0;
  1690.             }
  1691.              else
  1692.             {
  1693.                 nextCh = fReaderMgr.getNextChar();
  1694.             }
  1695.             if (!nextCh)
  1696.                 ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  1697.             // Check for our ending quote in the same entity
  1698.             if (nextCh == quoteCh)
  1699.             {
  1700.                 if (curReader == fReaderMgr.getCurrentReaderNum())
  1701.                     return true;
  1702.                 // Watch for spillover into a previous entity
  1703.                 if (curReader > fReaderMgr.getCurrentReaderNum())
  1704.                 {
  1705.                     emitError(XMLErrs::PartialMarkupInEntity);
  1706.                     return false;
  1707.                 }
  1708.             }
  1709.             //
  1710.             //  Check for an entity ref now, before we let it affect our
  1711.             //  whitespace normalization logic below. We ignore the empty flag
  1712.             //  in this one.
  1713.             //
  1714.             escaped = false;
  1715.             if (nextCh == chAmpersand)
  1716.             {
  1717.                 if (scanEntityRef(true, nextCh, secondCh, escaped) != EntityExp_Returned)
  1718.                 {
  1719.                     gotLeadingSurrogate = false;
  1720.                     continue;
  1721.                 }
  1722.             }
  1723.             // Deal with surrogate pairs
  1724.             if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
  1725.             {
  1726.                 //
  1727.                 //  Its a leading surrogate. If we already got one, then
  1728.                 //  issue an error, else set leading flag to make sure that
  1729.                 //  we look for a trailing next time.
  1730.                 //
  1731.                 if (gotLeadingSurrogate)
  1732.                     emitError(XMLErrs::Expected2ndSurrogateChar);
  1733.                  else
  1734.                     gotLeadingSurrogate = true;
  1735.             }
  1736.              else
  1737.             {
  1738.                 //
  1739.                 //  If its a trailing surrogate, make sure that we are
  1740.                 //  prepared for that. Else, its just a regular char so make
  1741.                 //  sure that we were not expected a trailing surrogate.
  1742.                 //
  1743.                 if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF))
  1744.                 {
  1745.                     // Its trailing, so make sure we were expecting it
  1746.                     if (!gotLeadingSurrogate)
  1747.                         emitError(XMLErrs::Unexpected2ndSurrogateChar);
  1748.                 }
  1749.                  else
  1750.                 {
  1751.                     //
  1752.                     //  Its just a char, so make sure we were not expecting a
  1753.                     //  trailing surrogate.
  1754.                     //
  1755.                     if (gotLeadingSurrogate)
  1756.                         emitError(XMLErrs::Expected2ndSurrogateChar);
  1757.                     // Its got to at least be a valid XML character
  1758.                     if (!XMLReader::isXMLChar(nextCh))
  1759.                     {
  1760.                         XMLCh tmpBuf[9];
  1761.                         XMLString::binToText
  1762.                         (
  1763.                             nextCh
  1764.                             , tmpBuf
  1765.                             , 8
  1766.                             , 16
  1767.                         );
  1768.                         emitError(XMLErrs::InvalidCharacterInAttrValue, attrName, tmpBuf);
  1769.                     }
  1770.                 }
  1771.                 gotLeadingSurrogate = false;
  1772.             }
  1773.             //
  1774.             //  If its not escaped, then make sure its not a < character, which
  1775.             //  is not allowed in attribute values.
  1776.             //
  1777.             if (!escaped && (nextCh == chOpenAngle))
  1778.                 emitError(XMLErrs::BracketInAttrValue, attrName);
  1779.             //
  1780.             //  If the attribute is a CDATA type we do simple replacement of
  1781.             //  tabs and new lines with spaces, if the character is not escaped
  1782.             //  by way of a char ref.
  1783.             //
  1784.             //  Otherwise, we do the standard non-CDATA normalization of
  1785.             //  compressing whitespace to single spaces and getting rid of leading
  1786.             //  and trailing whitespace.
  1787.             //
  1788.             if (type == XMLAttDef::CData)
  1789.             {
  1790.                 if (!escaped)
  1791.                 {
  1792.                     if ((nextCh == 0x09) || (nextCh == 0x0A) || (nextCh == 0x0D))
  1793.                     {
  1794.                         //
  1795.                         // Check Validity Constraint for Standalone document declaration
  1796.                         // XML 1.0, Section 2.9
  1797.                         //
  1798.                         if (fStandalone && fValidate && isAttExternal)
  1799.                         {
  1800.                              //
  1801.                              // Can't have a standalone document declaration of "yes" if  attribute
  1802.                              // values are subject to normalisation
  1803.                              //
  1804.                              fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName);
  1805.                         }
  1806.                         nextCh = chSpace;
  1807.                     }
  1808.                 }
  1809.             }
  1810.              else
  1811.             {
  1812.                 if (curState == InWhitespace)
  1813.                 {
  1814.                     if ((escaped && nextCh != chSpace) || !XMLReader::isWhitespace(nextCh))
  1815.                     {
  1816.                         if (firstNonWS)
  1817.                             toFill.append(chSpace);
  1818.                         curState = InContent;
  1819.                         firstNonWS = true;
  1820.                     }
  1821.                      else
  1822.                     {
  1823.                         continue;
  1824.                     }
  1825.                 }
  1826.                  else if (curState == InContent)
  1827.                 {
  1828.                     if ((nextCh == chSpace) ||
  1829.                         (XMLReader::isWhitespace(nextCh) && !escaped))
  1830.                     {
  1831.                         curState = InWhitespace;
  1832.                         //
  1833.                         // Check Validity Constraint for Standalone document declaration
  1834.                         // XML 1.0, Section 2.9
  1835.                         //
  1836.                         if (fStandalone && fValidate && isAttExternal)
  1837.                         {
  1838.                             if (!firstNonWS || (nextCh != chSpace) || (fReaderMgr.lookingAtSpace()))
  1839.                             {
  1840.                                  //
  1841.                                  // Can't have a standalone document declaration of "yes" if  attribute
  1842.                                  // values are subject to normalisation
  1843.                                  //
  1844.                                  fValidator->emitError(XMLValid::NoAttNormForStandalone, attrName);
  1845.                             }
  1846.                         }
  1847.                         continue;
  1848.                     }
  1849.                     firstNonWS = true;
  1850.                 }
  1851.             }
  1852.             // Else add it to the buffer
  1853.             toFill.append(nextCh);
  1854.         }
  1855.     }
  1856.     catch(const EndOfEntityException&)
  1857.     {
  1858.         // Just eat it and continue.
  1859.         gotLeadingSurrogate = false;
  1860.         escaped = false;
  1861.     }
  1862.     }
  1863.     return true;
  1864. }
  1865. //
  1866. //  This method scans a CDATA section. It collects the character into one
  1867. //  of the temp buffers and calls the document handler, if any, with the
  1868. //  characters. It assumes that the <![CDATA string has been scanned before
  1869. //  this call.
  1870. //
  1871. void XMLScanner::scanCDSection()
  1872. {
  1873.     //
  1874.     //  This is the CDATA section opening sequence, minus the '<' character.
  1875.     //  We use this to watch for nested CDATA sections, which are illegal.
  1876.     //
  1877.     static const XMLCh CDataPrefix[] =
  1878.     {
  1879.             chBang, chOpenSquare, chLatin_C, chLatin_D, chLatin_A
  1880.         ,   chLatin_T, chLatin_A, chOpenSquare, chNull
  1881.     };
  1882.     static const XMLCh CDataClose[] =
  1883.     {
  1884.             chCloseSquare, chCloseAngle, chNull
  1885.     };
  1886.     //
  1887.     //  The next character should be the opening square bracket. If not
  1888.     //  issue an error, but then try to recover by skipping any whitespace
  1889.     //  and checking again.
  1890.     //
  1891.     if (!fReaderMgr.skippedChar(chOpenSquare))
  1892.     {
  1893.         emitError(XMLErrs::ExpectedOpenSquareBracket);
  1894.         fReaderMgr.skipPastSpaces();
  1895.         // If we still don't find it, then give up, else keep going
  1896.         if (!fReaderMgr.skippedChar(chOpenSquare))
  1897.             return;
  1898.     }
  1899.     // Get a buffer for this
  1900.     XMLBufBid bbCData(&fBufMgr);
  1901.     //
  1902.     //  We just scan forward until we hit the end of CDATA section sequence.
  1903.     //  CDATA is effectively a big escape mechanism so we don't treat markup
  1904.     //  characters specially here.
  1905.     //
  1906.     bool            emittedError = false;
  1907.     while (true)
  1908.     {
  1909.         const XMLCh nextCh = fReaderMgr.getNextChar();
  1910.         // Watch for unexpected end of file
  1911.         if (!nextCh)
  1912.         {
  1913.             emitError(XMLErrs::UnterminatedCDATASection);
  1914.             ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  1915.         }
  1916.         if (fValidate && fStandalone && (XMLReader::isWhitespace(nextCh)))
  1917.         {
  1918.             //
  1919.             // This document is standalone; this ignorable CDATA whitespace is forbidden.
  1920.             // XML 1.0, Section 2.9
  1921.             //
  1922.             // And see if the current element is a 'Children' style content model
  1923.             const ElemStack::StackElem* topElem = fElemStack.topElement();
  1924.             if (topElem->fThisElement->isExternal()) {
  1925.                 // Get the character data opts for the current element
  1926.                 XMLElementDecl::CharDataOpts charOpts =  topElem->fThisElement->getCharDataOpts();
  1927.                 if (charOpts == XMLElementDecl::SpacesOk) // Element Content
  1928.                 {
  1929.                     // Error - standalone should have a value of "no" as whitespace detected in an
  1930.                     // element type with element content whose element declaration was external
  1931.                     //
  1932.                     fValidator->emitError(XMLValid::NoWSForStandalone);
  1933.                 }
  1934.             }
  1935.         }
  1936.         //
  1937.         //  If this is a close square bracket it could be our closing
  1938.         //  sequence.
  1939.         //
  1940.         if (nextCh == chCloseSquare && fReaderMgr.skippedString(CDataClose))
  1941.         {
  1942.             if (fGrammarType == Grammar::SchemaGrammarType) {
  1943.                 // call all active identity constraints
  1944.                 unsigned int count = fMatcherStack->getMatcherCount();
  1945.                 for (unsigned int i = 0; i < count; i++) {
  1946.                     fMatcherStack->getMatcherAt(i)->docCharacters(bbCData.getRawBuffer(), bbCData.getLen());
  1947.                 }
  1948.             }
  1949.             // If we have a doc handler, call it
  1950.             if (fDocHandler)
  1951.             {
  1952.                 fDocHandler->docCharacters
  1953.                     (
  1954.                     bbCData.getRawBuffer()
  1955.                     , bbCData.getLen()
  1956.                     , true
  1957.                     );
  1958.             }
  1959.             // And we are done
  1960.             break;
  1961.         }
  1962.         //
  1963.         //  Make sure its a valid character. But if we've emitted an error
  1964.         //  already, don't bother with the overhead since we've already told
  1965.         //  them about it.
  1966.         //
  1967.         if (!emittedError)
  1968.         {
  1969.             if (!XMLReader::isXMLChar(nextCh))
  1970.             {
  1971.                 XMLCh tmpBuf[9];
  1972.                 XMLString::binToText
  1973.                 (
  1974.                     nextCh
  1975.                     , tmpBuf
  1976.                     , 8
  1977.                     , 16
  1978.                 );
  1979.                 emitError(XMLErrs::InvalidCharacter, tmpBuf);
  1980.                 emittedError = true;
  1981.             }
  1982.         }
  1983.         // Add it to the buffer
  1984.         bbCData.append(nextCh);
  1985.     }
  1986. }
  1987. void XMLScanner::scanCharData(XMLBuffer& toUse)
  1988. {
  1989.     //
  1990.     //  We have to watch for the stupid ]]> sequence, which is illegal in
  1991.     //  character data. So this is a little state machine that handles that.
  1992.     //
  1993.     enum States
  1994.     {
  1995.         State_Waiting
  1996.         , State_GotOne
  1997.         , State_GotTwo
  1998.     };
  1999.     // Reset the buffer before we start
  2000.     toUse.reset();
  2001.     // Turn on the 'throw at end' flag of the reader manager
  2002.     ThrowEOEJanitor jan(&fReaderMgr, true);
  2003.     //
  2004.     //  In order to be more efficient we have to use kind of a deeply nested
  2005.     //  set of blocks here. The outer block puts on a try and catches end of
  2006.     //  entity exceptions. The inner loop is the per-character loop. If we
  2007.     //  put the try inside the inner loop, it would work but would require
  2008.     //  the exception handling code setup/teardown code to be invoked for
  2009.     //  each character.
  2010.     //
  2011.     XMLCh   nextCh;
  2012.     XMLCh   secondCh = 0;
  2013.     States  curState = State_Waiting;
  2014.     bool    escaped = false;
  2015.     bool    gotLeadingSurrogate = false;
  2016.     bool    notDone = true;
  2017.     while (notDone)
  2018.     {
  2019.         try
  2020.         {
  2021.             while (true)
  2022.             {
  2023.                 if (secondCh)
  2024.                 {
  2025.                     nextCh = secondCh;
  2026.                     secondCh = 0;
  2027.                 }
  2028.                  else
  2029.                 {
  2030.                      //  Eat through as many plain content characters as possible without
  2031.                      //  needing special handling.  Moving most content characters here,
  2032.                      //  in this one call, rather than running the overall loop once
  2033.                      //  per content character, is a speed optimization.
  2034.                      //
  2035.                     if (curState == State_Waiting  &&  !gotLeadingSurrogate)
  2036.                     {
  2037.                          fReaderMgr.movePlainContentChars(toUse);
  2038.                     }
  2039.                     // Try to get another char from the source
  2040.                     //   The code from here on down covers all contengencies,
  2041.                     //
  2042.                     if (!fReaderMgr.getNextCharIfNot(chOpenAngle, nextCh))
  2043.                     {
  2044.                         // If we were waiting for a trailing surrogate, its an error
  2045.                         if (gotLeadingSurrogate)
  2046.                             emitError(XMLErrs::Expected2ndSurrogateChar);
  2047.                         notDone = false;
  2048.                         break;
  2049.                     }
  2050.                 }
  2051.                 //
  2052.                 //  Watch for a reference. Note that the escapement mechanism
  2053.                 //  is ignored in this content.
  2054.                 //
  2055.                 if (nextCh == chAmpersand)
  2056.                 {
  2057.                     sendCharData(toUse);
  2058.                     // Turn off the throwing at the end of entity during this
  2059.                     ThrowEOEJanitor jan(&fReaderMgr, false);
  2060.                     if (scanEntityRef(false, nextCh, secondCh, escaped) != EntityExp_Returned)
  2061.                     {
  2062.                         gotLeadingSurrogate = false;
  2063.                         continue;
  2064.                     }
  2065.                 }
  2066.                  else
  2067.                 {
  2068.                     escaped = false;
  2069.                 }
  2070.                  // Keep the state machine up to date
  2071.                 if (!escaped)
  2072.                 {
  2073.                     if (nextCh == chCloseSquare)
  2074.                     {
  2075.                         if (curState == State_Waiting)
  2076.                             curState = State_GotOne;
  2077.                         else if (curState == State_GotOne)
  2078.                             curState = State_GotTwo;
  2079.                     }
  2080.                      else if (nextCh == chCloseAngle)
  2081.                     {
  2082.                         if (curState == State_GotTwo)
  2083.                             emitError(XMLErrs::BadSequenceInCharData);
  2084.                         curState = State_Waiting;
  2085.                     }
  2086.                      else
  2087.                     {
  2088.                         curState = State_Waiting;
  2089.                     }
  2090.                 }
  2091.                  else
  2092.                 {
  2093.                     curState = State_Waiting;
  2094.                 }
  2095.                 // Deal with surrogate pairs
  2096.                 if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
  2097.                 {
  2098.                     //
  2099.                     //  Its a leading surrogate. If we already got one, then
  2100.                     //  issue an error, else set leading flag to make sure that
  2101.                     //  we look for a trailing next time.
  2102.                     //
  2103.                     if (gotLeadingSurrogate)
  2104.                         emitError(XMLErrs::Expected2ndSurrogateChar);
  2105.                     else
  2106.                         gotLeadingSurrogate = true;
  2107.                 }
  2108.                  else
  2109.                 {
  2110.                     //
  2111.                     //  If its a trailing surrogate, make sure that we are
  2112.                     //  prepared for that. Else, its just a regular char so make
  2113.                     //  sure that we were not expected a trailing surrogate.
  2114.                     //
  2115.                     if ((nextCh >= 0xDC00) && (nextCh <= 0xDFFF))
  2116.                     {
  2117.                         // Its trailing, so make sure we were expecting it
  2118.                         if (!gotLeadingSurrogate)
  2119.                             emitError(XMLErrs::Unexpected2ndSurrogateChar);
  2120.                     }
  2121.                      else
  2122.                     {
  2123.                         //
  2124.                         //  Its just a char, so make sure we were not expecting a
  2125.                         //  trailing surrogate.
  2126.                         //
  2127.                         if (gotLeadingSurrogate)
  2128.                             emitError(XMLErrs::Expected2ndSurrogateChar);
  2129.                         // Make sure the returned char is a valid XML char
  2130.                         if (!XMLReader::isXMLChar(nextCh))
  2131.                         {
  2132.                             XMLCh tmpBuf[9];
  2133.                             XMLString::binToText
  2134.                             (
  2135.                                 nextCh
  2136.                                 , tmpBuf
  2137.                                 , 8
  2138.                                 , 16
  2139.                             );
  2140.                             emitError(XMLErrs::InvalidCharacter, tmpBuf);
  2141.                         }
  2142.                     }
  2143.                     gotLeadingSurrogate = false;
  2144.                 }
  2145.                 // Add this char to the buffer
  2146.                 toUse.append(nextCh);
  2147.             }
  2148.         }
  2149.         catch(const EndOfEntityException& toCatch)
  2150.         {
  2151.             //
  2152.             //  Some entity ended, so we have to send any accumulated
  2153.             //  chars and send an end of entity event.
  2154.             //
  2155.             sendCharData(toUse);
  2156.             gotLeadingSurrogate = false;
  2157.             if (fDocHandler)
  2158.                 fDocHandler->endEntityReference(toCatch.getEntity());
  2159.         }
  2160.     }
  2161.     //
  2162.     // Check the validity constraints as per XML 1.0 Section 2.9
  2163.     //
  2164.     const XMLCh* rawBuf = toUse.getRawBuffer();
  2165.     const unsigned int len = toUse.getLen();
  2166.     if (fValidate && fStandalone)
  2167.     {
  2168.         // See if the text contains whitespace
  2169.         // Get the raw data we need for the callback
  2170.         const bool isSpaces = XMLReader::containsWhiteSpace(rawBuf, len);
  2171.         if (isSpaces)
  2172.         {
  2173.             // And see if the current element is a 'Children' style content model
  2174.             const ElemStack::StackElem* topElem = fElemStack.topElement();
  2175.             if (topElem->fThisElement->isExternal()) {
  2176.                 // Get the character data opts for the current element
  2177.                 XMLElementDecl::CharDataOpts charOpts =  topElem->fThisElement->getCharDataOpts();
  2178.                 if (charOpts == XMLElementDecl::SpacesOk)  // => Element Content
  2179.                 {
  2180.                     // Error - standalone should have a value of "no" as whitespace detected in an
  2181.                     // element type with element content whose element declaration was external
  2182.                     //
  2183.                     fValidator->emitError(XMLValid::NoWSForStandalone);
  2184.                 }
  2185.             }
  2186.         }
  2187.     }
  2188.     // Send any char data that we accumulated into the buffer
  2189.     sendCharData(toUse);
  2190. }
  2191. //
  2192. //  This method scans a character reference and returns the character that
  2193. //  was refered to. It assumes that we've already scanned the &# characters
  2194. //  that prefix the numeric code.
  2195. //
  2196. bool XMLScanner::scanCharRef(XMLCh& toFill, XMLCh& second)
  2197. {
  2198.     bool gotOne = false;
  2199.     unsigned int value = 0;
  2200.     //
  2201.     //  Set the radix. Its supposed to be a lower case x if hex. But, in
  2202.     //  order to recover well, we check for an upper and put out an error
  2203.     //  for that.
  2204.     //
  2205.     unsigned int radix = 10;
  2206.     if (fReaderMgr.skippedChar(chLatin_x))
  2207.     {
  2208.         radix = 16;
  2209.     }
  2210.      else if (fReaderMgr.skippedChar(chLatin_X))
  2211.     {
  2212.         emitError(XMLErrs::HexRadixMustBeLowerCase);
  2213.         radix = 16;
  2214.     }
  2215.     while (true)
  2216.     {
  2217.         const XMLCh nextCh = fReaderMgr.peekNextChar();
  2218.         // Watch for EOF
  2219.         if (!nextCh)
  2220.             ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  2221.         // Break out on the terminating semicolon
  2222.         if (nextCh == chSemiColon)
  2223.         {
  2224.             fReaderMgr.getNextChar();
  2225.             break;
  2226.         }
  2227.         //
  2228.         //  Convert this char to a binary value, or bail out if its not
  2229.         //  one.
  2230.         //
  2231.         unsigned int nextVal;
  2232.         if ((nextCh >= chDigit_0) && (nextCh <= chDigit_9))
  2233.             nextVal = (unsigned int)(nextCh - chDigit_0);
  2234.          else if ((nextCh >= chLatin_A) && (nextCh <= chLatin_F))
  2235.             nextVal= (unsigned int)(10 + (nextCh - chLatin_A));
  2236.          else if ((nextCh >= chLatin_a) && (nextCh <= chLatin_f))
  2237.             nextVal = (unsigned int)(10 + (nextCh - chLatin_a));
  2238.          else
  2239.         {
  2240.             // Return a zero
  2241.             toFill = 0;
  2242.             //
  2243.             //  If we got at least a sigit, then do an unterminated ref error.
  2244.             //  Else, do an expected a numerical ref thing.
  2245.             //
  2246.             if (gotOne)
  2247.                 emitError(XMLErrs::UnterminatedCharRef);
  2248.             else
  2249.                 emitError(XMLErrs::ExpectedNumericalCharRef);
  2250.             // Return failure
  2251.             return false;
  2252.         }
  2253.         //
  2254.         //  Make sure its valid for the radix. If not, then just eat the
  2255.         //  digit and go on after issueing an error. Else, update the
  2256.         //  running value with this new digit.
  2257.         //
  2258.         if (nextVal >= radix)
  2259.         {
  2260.             XMLCh tmpStr[2];
  2261.             tmpStr[0] = nextCh;
  2262.             tmpStr[1] = chNull;
  2263.             emitError(XMLErrs::BadDigitForRadix, tmpStr);
  2264.         }
  2265.          else
  2266.         {
  2267.             value = (value * radix) + nextVal;
  2268.         }
  2269.         // Indicate that we got at least one good digit
  2270.         gotOne = true;
  2271.         // And eat the last char
  2272.         fReaderMgr.getNextChar();
  2273.     }
  2274.     //
  2275.     //  [2] Char ::= #x9 | #xA | #xD | [#x20-#xD7FF]        // any Unicode character, excluding the
  2276.     //               | [#xE000-#xFFFD] | [#x10000-#x10FFFF] // surrogate blocks, FFFE, and FFFF.
  2277.     //
  2278.     bool validChar = false;
  2279.     if (value < 0x20)
  2280.     {
  2281.       if (value == 0x09 || value == 0x0A || value == 0x0D)
  2282.       {
  2283.           validChar = true;
  2284.       }
  2285.     }
  2286.     else if (value <= 0xD7FF || (value >= 0xE000 && (value <= 0xFFFD || (value >= 0x10000 && value <= 0x10FFFF))))
  2287.     {
  2288.           validChar = true;
  2289.     }
  2290.     if (!validChar)
  2291.     {
  2292.       //
  2293.       // Character reference was not in the valid range
  2294.       emitError(XMLErrs::InvalidCharacterRef);
  2295.       return false;
  2296.       }
  2297.     // Return the char (or chars)
  2298.     if (value >= 0x10000)
  2299.     {
  2300.         value -= 0x10000;
  2301.         toFill = XMLCh((value >> 10) + 0xD800);
  2302.         second = XMLCh((value & 0x3FF) + 0xDC00);
  2303.     }
  2304.      else
  2305.     {
  2306.         toFill = XMLCh(value);
  2307.         second = 0;
  2308.     }
  2309.     return true;
  2310. }
  2311. //
  2312. //  We get here after the '<!--' part of the comment. We scan past the
  2313. //  terminating '-->' It will calls the appropriate handler with the comment
  2314. //  text, if one is provided. A comment can be in either the document or
  2315. //  the DTD, so the fInDocument flag is used to know which handler to send
  2316. //  it to.
  2317. //
  2318. void XMLScanner::scanComment()
  2319. {
  2320.     enum States
  2321.     {
  2322.         InText
  2323.         , OneDash
  2324.         , TwoDashes
  2325.     };
  2326.     // Get a buffer for this
  2327.     XMLBufBid bbComment(&fBufMgr);
  2328.     //
  2329.     //  Get the comment text into a temp buffer. Be sure to use temp buffer
  2330.     //  two here, since its to be used for stuff that is potentially longer
  2331.     //  than just a name.
  2332.     //
  2333.     States curState = InText;
  2334.     while (true)
  2335.     {
  2336.         // Get the next character
  2337.         const XMLCh nextCh = fReaderMgr.getNextChar();
  2338.         //  Watch for an end of file
  2339.         if (!nextCh)
  2340.         {
  2341.             emitError(XMLErrs::UnterminatedComment);
  2342.             ThrowXML(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF);
  2343.         }
  2344.         // Make sure its a valid XML character
  2345.         if (!XMLReader::isXMLChar(nextCh))
  2346.         {
  2347.             XMLCh tmpBuf[9];
  2348.             XMLString::binToText
  2349.             (
  2350.                 nextCh
  2351.                 , tmpBuf
  2352.                 , 8
  2353.                 , 16
  2354.             );
  2355.             emitError(XMLErrs::InvalidCharacter, tmpBuf);
  2356.         }
  2357.         if (curState == InText)
  2358.         {
  2359.             // If its a dash, go to OneDash state. Otherwise take as text
  2360.             if (nextCh == chDash)
  2361.                 curState = OneDash;
  2362.             else
  2363.                 bbComment.append(nextCh);
  2364.         }
  2365.          else if (curState == OneDash)
  2366.         {
  2367.             //
  2368.             //  If its another dash, then we change to the two dashes states.
  2369.             //  Otherwise, we have to put in the deficit dash and the new
  2370.             //  character and go back to InText.
  2371.             //
  2372.             if (nextCh == chDash)
  2373.             {
  2374.                 curState = TwoDashes;
  2375.             }
  2376.              else
  2377.             {
  2378.                 bbComment.append(chDash);
  2379.                 bbComment.append(nextCh);
  2380.                 curState = InText;
  2381.             }
  2382.         }
  2383.          else if (curState == TwoDashes)
  2384.         {
  2385.             // The next character must be the closing bracket
  2386.             if (nextCh != chCloseAngle)
  2387.             {
  2388.                 emitError(XMLErrs::IllegalSequenceInComment);
  2389.                 fReaderMgr.skipPastChar(chCloseAngle);
  2390.                 return;
  2391.             }
  2392.             break;
  2393.         }
  2394.     }
  2395.     // If we have an available handler, call back with the comment.
  2396.     if (fDocHandler)
  2397.     {
  2398.         fDocHandler->docComment
  2399.         (
  2400.             bbComment.getRawBuffer()
  2401.         );
  2402.     }
  2403. }
  2404. //
  2405. //  Most equal signs can have white space around them, so this little guy
  2406. //  just makes the calling code cleaner by eating whitespace.
  2407. //
  2408. bool XMLScanner::scanEq()
  2409. {
  2410.     fReaderMgr.skipPastSpaces();
  2411.     if (fReaderMgr.skippedChar(chEqual))
  2412.     {
  2413.         fReaderMgr.skipPastSpaces();
  2414.         return true;
  2415.     }
  2416.     return false;
  2417. }
  2418. //
  2419. //  This method will scan a general/character entity ref. It will either
  2420. //  expand a char ref and return it directly, or push a reader for a general
  2421. //  entity.
  2422. //
  2423. //  The return value indicates whether the char parameters hold the value
  2424. //  or whether the value was pushed as a reader, or that it failed.
  2425. //
  2426. //  The escaped flag tells the caller whether the returned parameter resulted
  2427. //  from a character reference, which escapes the character in some cases. It
  2428. //  only makes any difference if the return value indicates the value was
  2429. //  returned directly.
  2430. //
  2431. XMLScanner::EntityExpRes
  2432. XMLScanner::scanEntityRef(  const   bool    inAttVal
  2433.                             ,       XMLCh&  firstCh
  2434.                             ,       XMLCh&  secondCh
  2435.                             ,       bool&   escaped)
  2436. {
  2437.     // Assume no escape
  2438.     secondCh = 0;
  2439.     escaped = false;
  2440.     // We have to insure that its all in one entity
  2441.     const unsigned int curReader = fReaderMgr.getCurrentReaderNum();
  2442.     //
  2443.     //  If the next char is a pound, then its a character reference and we
  2444.     //  need to expand it always.
  2445.     //
  2446.     if (fReaderMgr.skippedChar(chPound))
  2447.     {
  2448.         //
  2449.         //  Its a character reference, so scan it and get back the numeric
  2450.         //  value it represents.
  2451.         //
  2452.         if (!scanCharRef(firstCh, secondCh))
  2453.             return EntityExp_Failed;
  2454.         escaped = true;
  2455.         if (curReader != fReaderMgr.getCurrentReaderNum())
  2456.             emitError(XMLErrs::PartialMarkupInEntity);
  2457.         return EntityExp_Returned;
  2458.     }
  2459.     // Expand it since its a normal entity ref
  2460.     XMLBufBid bbName(&fBufMgr);
  2461.     if (!fReaderMgr.getName(bbName.getBuffer()))
  2462.     {
  2463.         emitError(XMLErrs::ExpectedEntityRefName);
  2464.         return EntityExp_Failed;
  2465.     }
  2466.     //
  2467.     //  Next char must be a semi-colon. But if its not, just emit
  2468.     //  an error and try to continue.
  2469.     //
  2470.     if (!fReaderMgr.skippedChar(chSemiColon))
  2471.         emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer());
  2472.     // Make sure we ended up on the same entity reader as the & char
  2473.     if (curReader != fReaderMgr.getCurrentReaderNum())
  2474.         emitError(XMLErrs::PartialMarkupInEntity);
  2475.     // Look up the name in the general entity pool
  2476.     XMLEntityDecl* decl = fEntityDeclPool->getByKey(bbName.getRawBuffer());
  2477.     // If it does not exist, then obviously an error
  2478.     if (!decl)
  2479.     {
  2480.         // XML 1.0 Section 4.1
  2481.         // Well-formedness Constraint for entity not found:
  2482.         //   In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references,
  2483.         //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
  2484.         //      or a parameter entity
  2485.         //
  2486.         // Else it's Validity Constraint
  2487.         //
  2488.         if (fStandalone || fHasNoDTD)
  2489.             emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer());
  2490.         else {
  2491.             if (fValidate)
  2492.                 fValidator->emitError(XMLValid::VC_EntityNotFound, bbName.getRawBuffer());
  2493.         }
  2494.         return EntityExp_Failed;
  2495.     }
  2496.     //
  2497.     // XML 1.0 Section 2.9
  2498.     //  If we are a standalone document, then it has to have been declared
  2499.     //  in the internal subset. Keep going though.
  2500.     //
  2501.     if (fStandalone && !decl->getDeclaredInIntSubset() && fValidate)
  2502.         fValidator->emitError(XMLValid::IllegalRefInStandalone, bbName.getRawBuffer());
  2503.     if (decl->isExternal())
  2504.     {
  2505.         // If its unparsed, then its not valid here
  2506.         if (decl->isUnparsed())
  2507.         {
  2508.             emitError(XMLErrs::NoUnparsedEntityRefs, bbName.getRawBuffer());
  2509.             return EntityExp_Failed;
  2510.         }
  2511.         // If we are in an attribute value, then not valid but keep going
  2512.         if (inAttVal)
  2513.             emitError(XMLErrs::NoExtRefsInAttValue);
  2514.         // And now create a reader to read this entity
  2515.         InputSource* srcUsed;
  2516.         XMLReader* reader = fReaderMgr.createReader
  2517.         (
  2518.             decl->getSystemId()
  2519.             , decl->getPublicId()
  2520.             , false
  2521.             , XMLReader::RefFrom_NonLiteral
  2522.             , XMLReader::Type_General
  2523.             , XMLReader::Source_External
  2524.             , srcUsed
  2525.         );
  2526.         // Put a janitor on the source so it gets cleaned up on exit
  2527.         Janitor<InputSource> janSrc(srcUsed);
  2528.         //
  2529.         //  If the creation failed, and its not because the source was empty,
  2530.         //  then emit an error and return.
  2531.         //
  2532.         if (!reader)
  2533.             ThrowXML1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed->getSystemId());
  2534.         //
  2535.         //  Push the reader. If its a recursive expansion, then emit an error
  2536.         //  and return an failure.
  2537.         //
  2538.         if (!fReaderMgr.pushReader(reader, decl))
  2539.         {
  2540.             emitError(XMLErrs::RecursiveEntity, decl->getName());
  2541.             return EntityExp_Failed;
  2542.         }
  2543.         //
  2544.         //  Do a start entity reference event.
  2545.         //
  2546.         //  <TBD> For now, we supress them in att values. Later, when
  2547.         //  the stuff is in place to correctly allow DOM to handle them
  2548.         //  we'll turn this back on.
  2549.         //
  2550.         if (fDocHandler && !inAttVal)
  2551.             fDocHandler->startEntityReference(*decl);
  2552.         // If it starts with the XML string, then parse a text decl
  2553.         if (checkXMLDecl(true))
  2554.             scanXMLDecl(Decl_Text);
  2555.     }
  2556.      else
  2557.     {
  2558.         //
  2559.         //  If its one of the special char references, then we can return
  2560.         //  it as a character, and its considered escaped.
  2561.         //
  2562.         if (decl->getIsSpecialChar())
  2563.         {
  2564.             firstCh = decl->getValue()[0];
  2565.             escaped = true;
  2566.             return EntityExp_Returned;
  2567.         }
  2568.         //
  2569.         //  Create a reader over a memory stream over the entity value
  2570.         //  We force it to assume UTF-16 by passing in an encoding
  2571.         //  string. This way it won't both trying to predecode the
  2572.         //  first line, looking for an XML/TextDecl.
  2573.         //
  2574.         XMLReader* valueReader = fReaderMgr.createIntEntReader
  2575.         (
  2576.             decl->getName()
  2577.             , XMLReader::RefFrom_NonLiteral
  2578.             , XMLReader::Type_General
  2579.             , decl->getValue()
  2580.             , decl->getValueLen()
  2581.             , false
  2582.         );
  2583.         //
  2584.         //  Try to push the entity reader onto the reader manager stack,
  2585.         //  where it will become the subsequent input. If it fails, that
  2586.         //  means the entity is recursive, so issue an error. The reader
  2587.         //  will have just been discarded, but we just keep going.
  2588.         //
  2589.         if (!fReaderMgr.pushReader(valueReader, decl))
  2590.             emitError(XMLErrs::RecursiveEntity, decl->getName());
  2591.         //
  2592.         //  Do a start entity reference event.
  2593.         //
  2594.         //  <TBD> For now, we supress them in att values. Later, when
  2595.         //  the stuff is in place to correctly allow DOM to handle them
  2596.         //  we'll turn this back on.
  2597.         //
  2598.         if (fDocHandler && !inAttVal)
  2599.             fDocHandler->startEntityReference(*decl);
  2600.         // If it starts with the XML string, then it's an error
  2601.         if (checkXMLDecl(true)) {
  2602.             emitError(XMLErrs::TextDeclNotLegalHere);
  2603.             fReaderMgr.skipPastChar(chCloseAngle);
  2604.         }
  2605.     }
  2606.     return EntityExp_Pushed;
  2607. }
  2608. unsigned int
  2609. XMLScanner::scanUpToWSOr(XMLBuffer& toFill, const XMLCh chEndChar)
  2610. {
  2611.     fReaderMgr.getUpToCharOrWS(toFill, chEndChar);
  2612.     return toFill.getLen();
  2613. }
  2614. bool XMLScanner::switchGrammar(unsigned int newGrammarNameSpaceIndex)
  2615. {
  2616.     XMLBufBid bbURI(&fBufMgr);
  2617.     XMLBuffer& bufURI = bbURI.getBuffer();
  2618.     getURIText(newGrammarNameSpaceIndex, bufURI);
  2619.     Grammar* tempGrammar = fGrammarResolver->getGrammar(bufURI.getRawBuffer());
  2620.     if (!tempGrammar) {
  2621.         // This is a case where namespaces is on with a DTD grammar.
  2622.         tempGrammar = fGrammarResolver->getGrammar(XMLUni::fgZeroLenString);
  2623.     }
  2624.     if (!tempGrammar)
  2625.         return false;
  2626.     else {
  2627.         fGrammar = tempGrammar;
  2628.         fGrammarType = fGrammar->getGrammarType();
  2629.         if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) {
  2630.             if (fValidatorFromUser)
  2631.                 ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  2632.             else {
  2633.                 fValidator = fSchemaValidator;
  2634.             }
  2635.         }
  2636.         else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) {
  2637.             if (fValidatorFromUser)
  2638.                 ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  2639.             else {
  2640.                 fValidator = fDTDValidator;
  2641.             }
  2642.         }
  2643.         fValidator->setGrammar(fGrammar);
  2644.         return true;
  2645.     }
  2646. }
  2647. bool XMLScanner::switchGrammar(const XMLCh* const newGrammarNameSpace)
  2648. {
  2649.     Grammar* tempGrammar = fGrammarResolver->getGrammar(newGrammarNameSpace);
  2650.     if (!tempGrammar) {
  2651.         // This is a case where namespaces is on with a DTD grammar.
  2652.         tempGrammar = fGrammarResolver->getGrammar(XMLUni::fgZeroLenString);
  2653.     }
  2654.     if (!tempGrammar)
  2655.         return false;
  2656.     else {
  2657.         fGrammar = tempGrammar;
  2658.         fGrammarType = fGrammar->getGrammarType();
  2659.         if (fGrammarType == Grammar::SchemaGrammarType && !fValidator->handlesSchema()) {
  2660.             if (fValidatorFromUser)
  2661.                 ThrowXML(RuntimeException, XMLExcepts::Gen_NoSchemaValidator);
  2662.             else {
  2663.                 fValidator = fSchemaValidator;
  2664.             }
  2665.         }
  2666.         else if (fGrammarType == Grammar::DTDGrammarType && !fValidator->handlesDTD()) {
  2667.             if (fValidatorFromUser)
  2668.                 ThrowXML(RuntimeException, XMLExcepts::Gen_NoDTDValidator);
  2669.             else {
  2670.                 fValidator = fDTDValidator;
  2671.             }
  2672.         }
  2673.         fValidator->setGrammar(fGrammar);
  2674.         return true;
  2675.     }
  2676. }
  2677. // check if we should skip or lax the validation of the element
  2678. // if skip - no validation
  2679. // if lax - validate only if the element if found
  2680. bool XMLScanner::laxElementValidation(QName* element, ContentLeafNameTypeVector* cv,
  2681.                                       const XMLContentModel* const cm,
  2682.                                       const unsigned int parentElemDepth)
  2683. {
  2684.     bool skipThisOne = false;
  2685.     bool laxThisOne = false;
  2686.     unsigned int elementURI = element->getURI();
  2687.     unsigned int currState = fElemState[parentElemDepth];
  2688.     if (currState == XMLContentModel::gInvalidTrans) {
  2689.         return laxThisOne;
  2690.     }
  2691.     SubstitutionGroupComparator comparator(fGrammarResolver, fURIStringPool);
  2692.     if (cv) {
  2693.         unsigned int i = 0;
  2694.         unsigned int leafCount = cv->getLeafCount();
  2695.         for (; i < leafCount; i++) {
  2696.             QName* fElemMap = cv->getLeafNameAt(i);
  2697.             unsigned int uri = fElemMap->getURI();
  2698.             unsigned int nextState;
  2699.             bool anyEncountered = false;
  2700.             ContentSpecNode::NodeTypes type = cv->getLeafTypeAt(i);
  2701.             if (type == ContentSpecNode::Leaf) {
  2702.                 if (((uri == elementURI)
  2703.                       && !XMLString::compareString(fElemMap->getLocalPart(), element->getLocalPart()))
  2704.                     || comparator.isEquivalentTo(element, fElemMap)) {
  2705.                     nextState = cm->getNextState(currState, i);
  2706.                     if (nextState != XMLContentModel::gInvalidTrans) {
  2707.                         fElemState[parentElemDepth] = nextState;
  2708.                         break;
  2709.                     }
  2710.                 }
  2711.             } else if ((type & 0x0f) == ContentSpecNode::Any) {
  2712.                 anyEncountered = true;
  2713.             }
  2714.             else if ((type & 0x0f) == ContentSpecNode::Any_Other) {
  2715.                 if (uri != elementURI) {
  2716.                     anyEncountered = true;
  2717.                 }
  2718.             }
  2719.             else if ((type & 0x0f) == ContentSpecNode::Any_NS) {
  2720.                 if (uri == elementURI) {
  2721.                     anyEncountered = true;
  2722.                 }
  2723.             }
  2724.             if (anyEncountered) {
  2725.                 nextState = cm->getNextState(currState, i);
  2726.                 if (nextState != XMLContentModel::gInvalidTrans) {
  2727.                     fElemState[parentElemDepth] = nextState;
  2728.                     if (type == ContentSpecNode::Any_Skip ||
  2729.                         type == ContentSpecNode::Any_NS_Skip ||
  2730.                         type == ContentSpecNode::Any_Other_Skip) {
  2731.                         skipThisOne = true;
  2732.                     }
  2733.                     else if (type == ContentSpecNode::Any_Lax ||
  2734.                              type == ContentSpecNode::Any_NS_Lax ||
  2735.                              type == ContentSpecNode::Any_Other_Lax) {
  2736.                         laxThisOne = true;
  2737.                     }
  2738.                     break;
  2739.                 }
  2740.             }
  2741.         } // for
  2742.         if (i == leafCount) { // no match
  2743.             fElemState[parentElemDepth] = XMLContentModel::gInvalidTrans;
  2744.             return laxThisOne;
  2745.         }
  2746.     } // if
  2747.     if (skipThisOne) {
  2748.         fValidate = false;
  2749.         fElemStack.setValidationFlag(fValidate);
  2750.     }
  2751.     return laxThisOne;
  2752. }
  2753. // check if there is an AnyAttribute, and if so, see if we should lax or skip
  2754. // if skip - no validation
  2755. // if lax - validate only if the attribute if found
  2756. bool XMLScanner::anyAttributeValidation(SchemaAttDef* attWildCard, unsigned int uriId, bool& skipThisOne, bool& laxThisOne)
  2757. {
  2758.     XMLAttDef::AttTypes wildCardType = attWildCard->getType();
  2759.     bool anyEncountered = false;
  2760.     skipThisOne = false;
  2761.     laxThisOne = false;
  2762.     if (wildCardType == XMLAttDef::Any_Any)
  2763.         anyEncountered = true;
  2764.     else if (wildCardType == XMLAttDef::Any_Other) {
  2765.         if (attWildCard->getAttName()->getURI() != uriId)
  2766.             anyEncountered = true;
  2767.     }
  2768.     else if (wildCardType == XMLAttDef::Any_List) {
  2769.         ValueVectorOf<unsigned int>* nameURIList = attWildCard->getNamespaceList();
  2770.         unsigned int listSize = (nameURIList) ? nameURIList->size() : 0;
  2771.         if (listSize) {
  2772.             for (unsigned int i=0; i < listSize; i++) {
  2773.                 if (nameURIList->elementAt(i) == uriId)
  2774.                     anyEncountered = true;
  2775.             }
  2776.         }
  2777.     }
  2778.     if (anyEncountered) {
  2779.         XMLAttDef::DefAttTypes   defType   = attWildCard->getDefaultType();
  2780.         if (defType == XMLAttDef::ProcessContents_Skip) {
  2781.             // attribute should just be bypassed,
  2782.             skipThisOne = true;
  2783.         }
  2784.         else if (defType == XMLAttDef::ProcessContents_Lax) {
  2785.             laxThisOne = true;
  2786.         }
  2787.     }
  2788.     return anyEncountered;
  2789. }