1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 
18 /*
19  * $Id: SchemaValidator.cpp 806488 2009-08-21 10:36:58Z amassari $
20  */
21 
22 // ---------------------------------------------------------------------------
23 //  Includes
24 // ---------------------------------------------------------------------------
25 #include <xercesc/util/Janitor.hpp>
26 #include <xercesc/framework/XMLDocumentHandler.hpp>
27 #include <xercesc/framework/XMLSchemaDescription.hpp>
28 #include <xercesc/framework/psvi/XSAnnotation.hpp>
29 #include <xercesc/internal/XMLReader.hpp>
30 #include <xercesc/internal/XMLScanner.hpp>
31 #include <xercesc/internal/ElemStack.hpp>
32 #include <xercesc/validators/datatype/DatatypeValidatorFactory.hpp>
33 #include <xercesc/validators/datatype/ListDatatypeValidator.hpp>
34 #include <xercesc/validators/datatype/UnionDatatypeValidator.hpp>
35 #include <xercesc/validators/datatype/ENTITYDatatypeValidator.hpp>
36 #include <xercesc/validators/datatype/IDDatatypeValidator.hpp>
37 #include <xercesc/validators/datatype/IDREFDatatypeValidator.hpp>
38 #include <xercesc/validators/schema/SchemaSymbols.hpp>
39 #include <xercesc/validators/schema/SchemaValidator.hpp>
40 #include <xercesc/validators/schema/SubstitutionGroupComparator.hpp>
41 #include <xercesc/validators/schema/XercesGroupInfo.hpp>
42 #include <xercesc/validators/schema/XSDLocator.hpp>
43 #include <xercesc/util/OutOfMemoryException.hpp>
44 
45 XERCES_CPP_NAMESPACE_BEGIN
46 
47 // ---------------------------------------------------------------------------
48 //  SchemaValidator: Constructors and Destructor
49 // ---------------------------------------------------------------------------
SchemaValidator(XMLErrorReporter * const errReporter,MemoryManager * const manager)50 SchemaValidator::SchemaValidator( XMLErrorReporter* const errReporter
51                                 , MemoryManager* const    manager) :
52 
53     XMLValidator(errReporter)
54     , fMemoryManager(manager)
55     , fSchemaGrammar(0)
56     , fGrammarResolver(0)
57     , fXsiType(0)
58     , fNil(false)
59     , fNilFound(false)
60     , fCurrentDatatypeValidator(0)
61     , fNotationBuf(0)
62     , fDatatypeBuffer(1023, manager)
63     , fTrailing(false)
64     , fSeenNonWhiteSpace(false)
65     , fSeenId(false)
66     , fTypeStack(0)
67     , fMostRecentAttrValidator(0)
68     , fErrorOccurred(false)
69     , fElemIsSpecified(false)
70 {
71     fTypeStack = new (fMemoryManager) ValueStackOf<ComplexTypeInfo*>(8, fMemoryManager);
72 }
73 
~SchemaValidator()74 SchemaValidator::~SchemaValidator()
75 {
76     delete fXsiType;
77     delete fTypeStack;
78 
79     if (fNotationBuf)
80         delete fNotationBuf;
81 }
82 
83 // ---------------------------------------------------------------------------
84 //  SchemaValidator: Implementation of the XMLValidator interface
85 // ---------------------------------------------------------------------------
checkContent(XMLElementDecl * const elemDecl,QName ** const children,XMLSize_t childCount,XMLSize_t * indexFailingChild)86 bool SchemaValidator::checkContent (XMLElementDecl* const elemDecl
87                                  , QName** const          children
88                                  , XMLSize_t              childCount
89                                  , XMLSize_t*             indexFailingChild)
90 {
91     fErrorOccurred = false;
92     fElemIsSpecified = false;
93 
94     //
95     //  Look up the element id in our element decl pool. This will get us
96     //  the element decl in our own way of looking at them.
97     //
98     if (!elemDecl)
99         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_InvalidElemId, fMemoryManager);
100 
101     //
102     //  Get the content spec type of this element. This will tell us what
103     //  to do to validate it.
104     //
105     // the top of the type stack always knows best...
106     ComplexTypeInfo* currType = fTypeStack->pop();
107 
108     const SchemaElementDecl::ModelTypes modelType = (currType)
109             ? (SchemaElementDecl::ModelTypes)(currType->getContentType())
110             : ((SchemaElementDecl*)elemDecl)->getModelType();
111 
112     if (modelType == SchemaElementDecl::Empty  ||
113         modelType == SchemaElementDecl::ElementOnlyEmpty)
114     {
115         //
116         //  We can do this one here. It cannot have any children. If it does
117         //  we return 0 as the index of the first bad child.
118         //
119         if (childCount) {
120             fErrorOccurred = true;
121             *indexFailingChild=0;
122             return false;
123         }
124     }
125     else if ((modelType == SchemaElementDecl::Mixed_Simple)
126          ||  (modelType == SchemaElementDecl::Mixed_Complex)
127          ||  (modelType == SchemaElementDecl::Children))
128     {
129         // if nillable, it's an error to have value
130         // XML Schema REC: Validation Rule: Element Locally Valid (Element)
131         // 3.2.1 The element information item must have no
132         // character or element information item [children].
133         //
134         if (fNil) {
135             if (childCount > 0 || !XMLString::equals(fDatatypeBuffer.getRawBuffer(), XMLUni::fgZeroLenString)) {
136                 emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
137                 fErrorOccurred = true;
138             }
139         }
140         else {
141             // Get the element's content model or fault it in
142             XMLContentModel* elemCM = (currType)
143                     ? currType->getContentModel()
144                     : ((SchemaElementDecl*)elemDecl)->getContentModel();
145 
146             // Ask it to validate and return its return
147             unsigned int emptyNS = getScanner()->getEmptyNamespaceId();
148             bool result = elemCM->validateContent(children, childCount, emptyNS, indexFailingChild, getScanner()->getMemoryManager());
149             if (!result) {
150                 result = elemCM->validateContentSpecial(children
151                                                       , childCount
152                                                       , emptyNS
153                                                       , fGrammarResolver
154                                                       , fGrammarResolver->getStringPool()
155                                                       , indexFailingChild
156 													  , getScanner()->getMemoryManager());
157             }
158 
159             if(!result) {
160                 fErrorOccurred = true;
161             }
162 
163             return result;
164         }
165     }
166     else if (modelType == SchemaElementDecl::Simple || modelType == SchemaElementDecl::Any)
167     {
168         // Normally for SchemaElementDecl::Any, We pass no judgement on it and anything goes
169         // but if there is a fXsiTypeValidator, we need to use it for validation
170         if (modelType == SchemaElementDecl::Simple && childCount > 0) {
171             emitError(XMLValid::SimpleTypeHasChild, elemDecl->getFullName());
172             fErrorOccurred = true;
173         }
174         else
175         {
176             XMLCh* value = fDatatypeBuffer.getRawBuffer();
177             XMLCh* elemDefaultValue = ((SchemaElementDecl*) elemDecl)->getDefaultValue();
178 
179             if (fNil)
180             {
181                 if ((!XMLString::equals(value, XMLUni::fgZeroLenString))
182                     || elemDefaultValue)
183                 {
184                     emitError(XMLValid::NilAttrNotEmpty, elemDecl->getFullName());
185                     fErrorOccurred = true;
186                 }
187             }
188 			else if (fCurrentDatatypeValidator)
189             {
190                 DatatypeValidator::ValidatorType eleDefDVType = fCurrentDatatypeValidator->getType();
191                 bool validateCanonical = false;
192                 if (eleDefDVType == DatatypeValidator::NOTATION)
193                 {
194                     // if notation, need to bind URI to notation first
195                     if (!fNotationBuf)
196                         fNotationBuf = new (fMemoryManager) XMLBuffer(1023, fMemoryManager);
197 
198                     //  Make sure that this value maps to one of the
199                     //  notation values in the enumList parameter. We don't have to
200                     //  look it up in the notation pool (if a notation) because we
201                     //  will look up the enumerated values themselves. If they are in
202                     //  the notation pool (after the Grammar is parsed), then obviously
203                     //  this value will be legal since it matches one of them.
204                     int colonPos = -1;
205                     unsigned int uriId = getScanner()->resolveQName(value, *fNotationBuf, ElemStack::Mode_Element, colonPos);
206 
207                     const XMLCh* uriText = getScanner()->getURIText(uriId);
208                     if (uriText && *uriText) {
209                         fNotationBuf->set(uriText);
210                         fNotationBuf->append(chColon);
211                         fNotationBuf->append(&value[colonPos + 1]);
212                         value = fNotationBuf->getRawBuffer();
213                     }
214                 }
215 
216                 if (elemDefaultValue)
217                 {
218                     if (XMLString::equals(value, XMLUni::fgZeroLenString))
219                     {
220                         fElemIsSpecified = true;
221                         // if this element didn't specified any value
222                         // use default value
223                         if (getScanner()->getDocHandler())
224                             getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false);
225 
226                         // Normally for default value, it has been validated already during TraverseSchema
227                         // But if there was a xsi:type and this validator is fXsiTypeValidator,
228                         // need to validate again
229                         // we determine this if the current content dataype validator
230                         // is neither the one in the element nor the one in the current
231                         // complex type (if any)
232                         if ((fCurrentDatatypeValidator != ((SchemaElementDecl*)elemDecl)->getDatatypeValidator())
233                             && (!fTypeStack->peek() || (fCurrentDatatypeValidator != fTypeStack->peek()->getDatatypeValidator()))) {
234                             value = elemDefaultValue;
235                             validateCanonical = true;
236                         }
237                         else
238                             value = 0;
239                     }
240                     else
241                     {
242                         // this element has specified some value
243                         // if the flag is FIXED, then this value must be same as default value
244                         if ((((SchemaElementDecl*)elemDecl)->getMiscFlags() & SchemaSymbols::XSD_FIXED) != 0)
245                         {
246                             if (fCurrentDatatypeValidator->compare(value, elemDefaultValue, fMemoryManager) != 0 )
247                             {
248                                 emitError(XMLValid::FixedDifferentFromActual, elemDecl->getFullName());
249                                 fErrorOccurred = true;
250                             }
251                         }
252                     }
253                 }
254 
255                 if ((!fErrorOccurred) && value)
256                 {
257                     try {
258                         fCurrentDatatypeValidator->validate(value, getScanner()->getValidationContext(), fMemoryManager);
259                         if (validateCanonical) {
260                             XMLCh* canonical = (XMLCh*) fCurrentDatatypeValidator->getCanonicalRepresentation(value, fMemoryManager);
261                             ArrayJanitor<XMLCh> tempCanonical(canonical, fMemoryManager);
262                             fCurrentDatatypeValidator->validate(canonical, getScanner()->getValidationContext(), fMemoryManager);
263                         }
264                     }
265                     catch (XMLException& idve)
266                     {
267                         emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
268                         fErrorOccurred = true;
269                     }
270                     catch(const OutOfMemoryException&) {
271                         throw;
272                     }
273                     catch (...)
274                     {
275                         emitError(XMLValid::GenericError);
276                         throw;
277                     }
278                 }
279             }
280             else if (modelType == SchemaElementDecl::Simple)
281             {
282                 emitError(XMLValid::NoDatatypeValidatorForSimpleType, elemDecl->getFullName());
283                 fErrorOccurred = true;
284             }
285             // modelType is any
286             else if (elemDefaultValue)
287             {
288                 if (XMLString::equals(value, XMLUni::fgZeroLenString))
289                 {
290                     fElemIsSpecified = true;
291                     // if this element didn't specified any value
292                     // use default value
293                     if (getScanner()->getDocHandler()) {
294                         getScanner()->getDocHandler()->docCharacters(elemDefaultValue, XMLString::stringLen(elemDefaultValue), false);
295                     }
296                 }
297             }
298         }
299     }
300     else
301     {
302         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::CM_UnknownCMType, fMemoryManager);
303     }
304 
305     // must rely on scanner to clear fDatatypeBuffer
306     // since it may need to query its contents after this method completes
307     fNil = false;
308     fNilFound = false;
309     fTrailing=false;
310     fSeenNonWhiteSpace = false;
311     fCurrentDatatypeValidator = 0;
312 
313     // Went ok, so return success
314     return true;
315 }
316 
faultInAttr(XMLAttr & toFill,const XMLAttDef & attDef) const317 void SchemaValidator::faultInAttr (XMLAttr&    toFill, const XMLAttDef&  attDef)   const
318 {
319     //
320     //  At this level, we cannot set the URI id. So we just set it to zero
321     //  and leave it at that. The scanner, who called us, will look at the
322     //  prefix we stored (if any), resolve it, and store the URL id if any.
323     //
324     SchemaAttDef* schemaAttDef = (SchemaAttDef*) &attDef;
325     QName* attName = schemaAttDef->getAttName();
326 
327     toFill.set
328     (
329           attName->getURI()
330         , attName->getLocalPart()
331         , attName->getPrefix()
332         , schemaAttDef->getValue()
333         , schemaAttDef->getType()
334     );
335 }
336 
reset()337 void SchemaValidator::reset()
338 {
339     fTrailing = false;
340     fSeenNonWhiteSpace = false;
341     fSeenId = false;
342 	fTypeStack->removeAllElements();
343     delete fXsiType;
344     fXsiType = 0;
345     fCurrentDatatypeValidator = 0;
346     fNil = false;
347     fNilFound = false;
348     fDatatypeBuffer.reset();
349     fErrorOccurred = false;
350 }
351 
requiresNamespaces() const352 bool SchemaValidator::requiresNamespaces() const
353 {
354     return true;
355 }
356 
validateAttrValue(const XMLAttDef * attDef,const XMLCh * const attrValue,bool preValidation,const XMLElementDecl * elemDecl)357 void SchemaValidator::validateAttrValue (const XMLAttDef*      attDef
358                                        , const XMLCh* const    attrValue
359                                        , bool                  preValidation
360                                        , const XMLElementDecl* elemDecl)
361 {
362     fErrorOccurred = false;
363 
364     //turn on IdRefList checking
365     getScanner()->getValidationContext()->toCheckIdRefList(true);
366 
367     //
368     //  Get quick refs to lot of the stuff in the passed objects in
369     //  order to simplify the code below, which will reference them very
370     //  often.
371     //
372     XMLAttDef::AttTypes            type      = attDef->getType();
373     const XMLAttDef::DefAttTypes   defType   = attDef->getDefaultType();
374 
375     //
376     //  If the default type is fixed, then make sure the passed value maps
377     //  to the fixed value.
378     //
379     //  If during preContentValidation, the value we are validating is the fixed value itself
380     //  so no need to compare.
381     //  Only need to do this for regular attribute value validation
382     //
383     if ((defType == XMLAttDef::Fixed || defType == XMLAttDef::Required_And_Fixed) && !preValidation)
384     {
385         const XMLCh* const valueText = attDef->getValue();
386         if (!XMLString::equals(attrValue, valueText)) {
387             emitError(XMLValid::NotSameAsFixedValue, attDef->getFullName(), attrValue, valueText);
388             fErrorOccurred = true;
389         }
390     }
391 
392     // An empty string cannot be valid for non_CDATA any of the other types
393     if (!attrValue[0] && type != XMLAttDef::Simple)
394     {
395         emitError(XMLValid::InvalidEmptyAttValue, attDef->getFullName());
396         // accords with original DOMTypeInfo implementation, but this does not feel right.
397         fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
398         fErrorOccurred = true;
399         return;
400     }
401 
402     DatatypeValidator* attDefDV = ((SchemaAttDef*) attDef)->getDatatypeValidator();
403     if (!attDefDV) {
404         emitError(XMLValid::NoDatatypeValidatorForAttribute, attDef->getFullName());
405         fErrorOccurred = true;
406     }
407     else {
408         DatatypeValidator::ValidatorType attDefDVType = attDefDV->getType();
409         ValidationContext *context = getScanner()->getValidationContext();
410         try {
411 
412             // first, if notation, need to bind URI to notation first
413             if (attDefDVType == DatatypeValidator::NOTATION)
414             {
415                 //
416                 //  Make sure that this value maps to one of the
417                 //  notation values in the enumList parameter. We don't have to
418                 //  look it up in the notation pool (if a notation) because we
419                 //  will look up the enumerated values themselves. If they are in
420                 //  the notation pool (after the Grammar is parsed), then obviously
421                 //  this value will be legal since it matches one of them.
422                 //
423                 XMLBuffer notationBuf(1023, fMemoryManager);
424                 int colonPos = -1;
425                 unsigned int uriId = getScanner()->resolveQName(attrValue, notationBuf, ElemStack::Mode_Element, colonPos);
426                 const XMLCh* uriText = getScanner()->getURIText(uriId);
427                 if (uriText && *uriText) {
428                     notationBuf.set(uriText);
429                     notationBuf.append(chColon);
430                     notationBuf.append(&attrValue[colonPos + 1]);
431                 }
432                 else {
433                     notationBuf.set(attrValue);
434                 }
435 
436                 attDefDV->validate(notationBuf.getRawBuffer()
437                                  , context
438                                  , fMemoryManager);
439             }
440             else {
441                 attDefDV->validate(attrValue
442                                  , context
443                                  , fMemoryManager);
444             }
445 
446         }
447         catch (XMLException& idve) {
448             fErrorOccurred = true;
449             emitError (XMLValid::DatatypeError, idve.getCode(), idve.getMessage());
450         }
451         catch(const OutOfMemoryException&)
452         {
453             throw;
454         }
455         catch (...) {
456             emitError(XMLValid::GenericError);
457             fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
458             fErrorOccurred = true;
459             throw;
460         }
461         fMostRecentAttrValidator = attDefDV;
462         // now we can look for ID's, entities, ...
463 
464         // set up the entitydeclpool in ENTITYDatatypeValidator
465         // and the idreflist in ID/IDREFDatatypeValidator
466 
467         // indicate if this attribute is of type ID
468         bool thisIsAnId = false;
469 
470         if (attDefDVType == DatatypeValidator::List) {
471             DatatypeValidator* itemDTV = ((ListDatatypeValidator*)attDefDV)->getItemTypeDTV();
472             DatatypeValidator::ValidatorType itemDTVType = itemDTV->getType();
473             if (itemDTVType == DatatypeValidator::ID) {
474                 thisIsAnId = true;
475             }
476             else if (itemDTVType == DatatypeValidator::IDREF) {
477                 // if in prevalidatoin, do not add attDef to IDREFList
478                 if (preValidation)
479                     //todo: when to setIdRefList back to non-null
480                     getScanner()->getValidationContext()->toCheckIdRefList(false);
481             }
482         }
483         else if (attDefDVType == DatatypeValidator::Union) {
484             DatatypeValidator *memberDTV = context->getValidatingMemberType();
485             // actual type for DOMTypeInfo is memberDTV
486             fMostRecentAttrValidator = memberDTV;
487             // no member datatype validator if there was an error
488             if(memberDTV)
489             {
490                 DatatypeValidator::ValidatorType memberDTVType = memberDTV->getType();
491                 if (memberDTVType == DatatypeValidator::ID) {
492                     thisIsAnId = true;
493                 }
494                 else if (memberDTVType == DatatypeValidator::IDREF) {
495                     // if in prevalidatoin, do not add attDef to IDREFList
496                     if (preValidation)
497                         getScanner()->getValidationContext()->toCheckIdRefList(false);
498                 }
499             }
500         }
501         else if (attDefDVType == DatatypeValidator::ID) {
502             thisIsAnId = true;
503         }
504         else if (attDefDVType == DatatypeValidator::IDREF) {
505             // if in prevalidation, do not add attDef to IDREFList
506             if (preValidation)
507                 getScanner()->getValidationContext()->toCheckIdRefList(false);
508         }
509         if (thisIsAnId) {
510             if (fSeenId) {
511                 emitError
512                 (
513                     XMLValid::MultipleIdAttrs
514                     , elemDecl->getFullName()
515                 );
516                 fErrorOccurred = true;
517             }
518             else
519                 fSeenId = true;
520         }
521 
522     }
523 
524     if(fErrorOccurred) {
525         fMostRecentAttrValidator = DatatypeValidatorFactory::getBuiltInRegistry()->get(SchemaSymbols::fgDT_ANYSIMPLETYPE);
526     }
527     fTrailing = false;
528     fSeenNonWhiteSpace = false;
529 }
530 
validateElement(const XMLElementDecl * elemDef)531 void SchemaValidator::validateElement(const   XMLElementDecl*  elemDef)
532 {
533     ComplexTypeInfo* elemTypeInfo = ((SchemaElementDecl*)elemDef)->getComplexTypeInfo();
534     fTypeStack->push(elemTypeInfo);
535     fCurrentDatatypeValidator = (elemTypeInfo)
536             ? elemTypeInfo->getDatatypeValidator()
537             : ((SchemaElementDecl*)elemDef)->getDatatypeValidator();
538 
539     fErrorOccurred = false;
540 
541     if (fXsiType) {
542         // handle "xsi:type" right here
543         DatatypeValidator *xsiTypeDV = 0;
544         unsigned int uri = fXsiType->getURI();
545         const XMLCh* localPart = fXsiType->getLocalPart();
546 
547         if (uri != XMLElementDecl::fgInvalidElemId &&
548             uri != XMLElementDecl::fgPCDataElemId &&
549             uri != XMLContentModel::gEpsilonFakeId &&
550             uri != XMLContentModel::gEOCFakeId) {
551 
552             // retrieve Grammar for the uri
553             const XMLCh* uriStr = getScanner()->getURIText(uri);
554             SchemaGrammar* sGrammar = (SchemaGrammar*) fGrammarResolver->getGrammar(uriStr);
555             if (!sGrammar) {
556 
557                 // Check built-in simple types
558                 if (XMLString::equals(uriStr, SchemaSymbols::fgURI_SCHEMAFORSCHEMA)) {
559 
560                     xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart);
561 
562                     if (!xsiTypeDV) {
563                         emitError(XMLValid::BadXsiType, fXsiType->getRawName());
564                         fErrorOccurred = true;
565                     }
566                     else {
567                         if (elemTypeInfo || (fCurrentDatatypeValidator
568                                 && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV))) {
569                             // the type is not derived from ancestor
570                             emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
571                             fErrorOccurred = true;
572                         }
573                         else if(fCurrentDatatypeValidator != xsiTypeDV)
574                         {
575                             // the type is derived from ancestor
576                             if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) {
577                                 emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
578                                 fErrorOccurred = true;
579                             }
580                             if (elemDef->hasAttDefs()) {
581                                 // if we have an attribute but xsi:type's type is simple, we have a problem...
582                                 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
583                                 fErrorOccurred = true;
584                             }
585                         }
586                         fCurrentDatatypeValidator = xsiTypeDV;
587                     }
588                 }
589                 else {
590                     // Grammar not found
591                     emitError(XMLValid::GrammarNotFound, uriStr);
592                     fErrorOccurred = true;
593                 }
594             }
595             else if (sGrammar->getGrammarType() != Grammar::SchemaGrammarType) {
596                 emitError(XMLValid::GrammarNotFound, uriStr);
597                 fErrorOccurred = true;
598             }
599             else {
600                 // retrieve complexType registry and DatatypeValidator registry
601                 RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar->getComplexTypeRegistry();
602                 if (!complexTypeRegistry) {
603                     emitError(XMLValid::BadXsiType, fXsiType->getRawName());
604                     fErrorOccurred = true;
605                 }
606                 else {
607 
608                     // retrieve the typeInfo specified in xsi:type
609                     XMLBuffer aBuffer(1023, fMemoryManager);
610                     aBuffer.set(uriStr);
611                     aBuffer.append(chComma);
612                     aBuffer.append(localPart);
613                     ComplexTypeInfo* typeInfo = complexTypeRegistry->get(aBuffer.getRawBuffer());
614 
615                     if (typeInfo) {
616                         // typeInfo is found
617                         if (typeInfo->getAbstract()) {
618                             emitError(XMLValid::NoAbstractInXsiType, aBuffer.getRawBuffer());
619                             fErrorOccurred = true;
620                         }
621                         else
622                         {
623                             if (elemTypeInfo)
624                             {
625                                 ComplexTypeInfo* tempType = typeInfo;
626                                 while (tempType) {
627                                     if (tempType == elemTypeInfo)
628                                         break;
629                                     tempType = tempType->getBaseComplexTypeInfo();
630                                 }
631 
632                                 if (!tempType) {
633                                     emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
634                                     fErrorOccurred = true;
635                                 }
636                                 else if(elemTypeInfo != typeInfo) {
637                                     // perform the check on the entire inheritance chain
638                                     ComplexTypeInfo* tempType = typeInfo;
639                                     while (tempType) {
640                                         if (tempType == elemTypeInfo)
641                                             break;
642                                         int derivationMethod = tempType->getDerivedBy();
643                                         if ((((SchemaElementDecl*)elemDef)->getBlockSet() & derivationMethod) != 0) {
644                                             emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
645                                             fErrorOccurred = true;
646                                         }
647                                         if ((elemTypeInfo->getBlockSet() & derivationMethod) != 0) {
648                                             emitError(XMLValid::TypeNoSubforBlock, elemTypeInfo->getTypeName());
649                                             fErrorOccurred = true;
650                                         }
651                                         tempType = tempType->getBaseComplexTypeInfo();
652                                     }
653                                 }
654                             }
655                             else
656                             {
657                                 // if the original type is a simple type, check derivation ok.
658                                 if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(typeInfo->getDatatypeValidator())) {
659                                     // the type is not derived from ancestor
660                                     emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
661                                     fErrorOccurred = true;
662                                 }
663                             }
664 
665                             if (!fErrorOccurred)
666                             {
667                                 fTypeStack->pop();
668                                 fTypeStack->push(typeInfo);
669                                 fCurrentDatatypeValidator = typeInfo->getDatatypeValidator();
670                             }
671                         }
672                     }
673                     else
674                     {
675                         // typeInfo not found
676                         xsiTypeDV = fGrammarResolver->getDatatypeValidator(uriStr, localPart);
677 
678                         if (!xsiTypeDV) {
679                             emitError(XMLValid::BadXsiType, fXsiType->getRawName());
680                             fErrorOccurred = true;
681                         }
682                         else {
683                             if (fCurrentDatatypeValidator && !fCurrentDatatypeValidator->isSubstitutableBy(xsiTypeDV)) {
684                                 // the type is not derived from ancestor
685                                 emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
686                                 fErrorOccurred = true;
687                             }
688                             else if(fCurrentDatatypeValidator != xsiTypeDV)
689                             {
690                                 DatatypeValidator::ValidatorType derivedType=xsiTypeDV->getType();
691                                 if((derivedType == DatatypeValidator::List || derivedType == DatatypeValidator::Union) && fCurrentDatatypeValidator==0)
692                                 {
693                                     // the substitution is always allowed if the type is list or union and the base type was xs:anySimpleType
694                                 }
695                                 else
696                                 {
697                                     // the type is derived from ancestor
698                                     if ((((SchemaElementDecl*)elemDef)->getBlockSet() & SchemaSymbols::XSD_RESTRICTION) != 0) {
699                                         emitError(XMLValid::ElemNoSubforBlock, elemDef->getFullName());
700                                         fErrorOccurred = true;
701                                     }
702                                     if (elemDef->hasAttDefs()) {
703                                         // if we have an attribute but xsi:type's type is simple, we have a problem...
704                                         emitError(XMLValid::NonDerivedXsiType, fXsiType->getRawName(), elemDef->getFullName());
705                                         fErrorOccurred = true;
706                                     }
707                                 }
708                             }
709 
710                             fCurrentDatatypeValidator = xsiTypeDV;
711                         }
712                     }
713                 }
714             }
715         }
716 
717         delete fXsiType;
718         fXsiType = 0;
719     }
720     else {
721         //
722         // xsi:type was not specified...
723         // If the corresponding type is abstract, detect an error
724         //
725         if (elemTypeInfo && elemTypeInfo->getAbstract()) {
726             emitError(XMLValid::NoUseAbstractType, elemDef->getFullName());
727             fErrorOccurred = true;
728         }
729     }
730 
731     //
732     // Check whether this element is abstract.  If so, an error
733     //
734     int miscFlags = ((SchemaElementDecl*)elemDef)->getMiscFlags();
735     if ((miscFlags & SchemaSymbols::XSD_ABSTRACT) != 0) {
736         emitError(XMLValid::NoDirectUseAbstractElement, elemDef->getFullName());
737         fErrorOccurred = true;
738     }
739 
740     //
741     // Check whether this element allows Nillable
742     //
743     if (fNilFound && (miscFlags & SchemaSymbols::XSD_NILLABLE) == 0 ) {
744         fNil = false;
745         fNilFound = false;
746         emitError(XMLValid::NillNotAllowed, elemDef->getFullName());
747         fErrorOccurred = true;
748     }
749 
750     fDatatypeBuffer.reset();
751     fTrailing = false;
752     fSeenNonWhiteSpace = false;
753     fSeenId = false;
754 }
755 
preContentValidation(bool,bool validateDefAttr)756 void SchemaValidator::preContentValidation(bool,
757                                            bool validateDefAttr)
758 {
759     //  Lets go through all the grammar in the GrammarResolver
760     //    and validate those that has not been validated yet
761     //
762     //  Lets enumerate all of the elements in the element decl pool
763     //    and put out an error for any that did not get declared.
764     //    We also check all of the attributes as well.
765     //
766     //  And enumerate all the complextype info in the grammar
767     //    and do Unique Particle Attribution Checking
768 
769     RefHashTableOfEnumerator<Grammar> grammarEnum = fGrammarResolver->getGrammarEnumerator();
770     while (grammarEnum.hasMoreElements())
771     {
772         SchemaGrammar& sGrammar = (SchemaGrammar&) grammarEnum.nextElement();
773         if (sGrammar.getGrammarType() != Grammar::SchemaGrammarType || sGrammar.getValidated())
774              continue;
775 
776         sGrammar.setValidated(true);
777 
778         RefHash3KeysIdPoolEnumerator<SchemaElementDecl> elemEnum = sGrammar.getElemEnumerator();
779 
780         while (elemEnum.hasMoreElements())
781         {
782             SchemaElementDecl& curElem = elemEnum.nextElement();
783 
784             //  First check if declared or not
785             //
786             //  See if this element decl was ever marked as declared. If
787             //  not, then put out an error. In some cases its just
788             //  a warning, such as being referenced in a content model.
789             //
790             const SchemaElementDecl::CreateReasons reason = curElem.getCreateReason();
791 
792             if (reason != XMLElementDecl::Declared)
793             {
794                 if (reason == XMLElementDecl::AttList)
795                 {
796                     getScanner()->emitError
797                     (
798                         XMLErrs::UndeclaredElemInAttList
799                         , curElem.getFullName()
800                     );
801                 }
802                  else if (reason == XMLElementDecl::AsRootElem)
803                 {
804                     emitError
805                     (
806                         XMLValid::UndeclaredElemInDocType
807                         , curElem.getFullName()
808                     );
809                 }
810                  else if (reason == XMLElementDecl::InContentModel)
811                 {
812                     getScanner()->emitError
813                     (
814                         XMLErrs::UndeclaredElemInCM
815                         , curElem.getFullName()
816                     );
817                 }
818                 else
819                 {
820                 }
821             }
822 
823             //
824             //  Then check all of the attributes of the current element.
825             //  We check for:
826             //
827             //  1) Multiple ID attributes
828             //  2) That all of the default values of attributes are
829             //      valid for their type.
830             //  3) That for any notation types, that their lists
831             //      of possible values refer to declared notations.
832             //
833             if (curElem.hasAttDefs()) {
834                 XMLAttDefList& attDefList = curElem.getAttDefList();
835                 bool seenId = false;
836 
837                 for(XMLSize_t i=0; i<attDefList.getAttDefCount(); i++)
838                 {
839                     const XMLAttDef& curAttDef = attDefList.getAttDef(i);
840 
841                     if (curAttDef.getType() == XMLAttDef::ID)
842                     {
843                         if (seenId)
844                         {
845                             emitError
846                             (
847                                 XMLValid::MultipleIdAttrs
848                                 , curElem.getFullName()
849                             );
850                             break;
851                         }
852 
853                         seenId = true;
854                     }
855                      else if (curAttDef.getType() == XMLAttDef::Notation && curAttDef.getEnumeration())
856                     {
857                         //
858                         //  We need to verify that all of its possible values
859                         //  (in the enum list) refer to valid notations.
860                         //
861                         XMLCh* list = XMLString::replicate(curAttDef.getEnumeration(), fMemoryManager);
862                         ArrayJanitor<XMLCh> janList(list, fMemoryManager);
863 
864                         //
865                         //  Search forward for a space or a null. If a null,
866                         //  we are done. If a space, cap it and look it up.
867                         //
868                         bool    breakFlag = false;
869                         XMLCh*  listPtr = list;
870                         XMLCh*  lastPtr = listPtr;
871                         while (true)
872                         {
873                             while (*listPtr && (*listPtr != chSpace))
874                                 listPtr++;
875 
876                             //
877                             //  If at the end, indicate we need to break after
878                             //  this one. Else, cap it off here.
879                             //
880                             if (!*listPtr)
881                                 breakFlag = true;
882                             else
883                                 *listPtr = chNull;
884 
885                             if (!sGrammar.getNotationDecl(lastPtr))
886                             {
887                                 emitError
888                                 (
889                                     XMLValid::UnknownNotRefAttr
890                                     , curAttDef.getFullName()
891                                     , lastPtr
892                                 );
893                             }
894 
895                             // Break out if we hit the end last time
896                             if (breakFlag)
897                                 break;
898 
899                             // Else move upwards and try again
900                             listPtr++;
901                             lastPtr = listPtr;
902                         }
903                     }
904 
905                     // If it has a default/fixed value, then validate it
906                     if (validateDefAttr && curAttDef.getValue())
907                     {
908                         validateAttrValue
909                         (
910                             &curAttDef
911                             , curAttDef.getValue()
912                             , true
913                             , &curElem
914                         );
915                     }
916                 }
917             }
918         }
919 
920         //  For each complex type info, check the Unique Particle Attribution
921         if (getScanner()->getValidationSchemaFullChecking()) {
922             RefHashTableOf<ComplexTypeInfo>* complexTypeRegistry = sGrammar.getComplexTypeRegistry();
923 
924             RefHashTableOfEnumerator<ComplexTypeInfo> complexTypeEnum(complexTypeRegistry, false, fMemoryManager);
925             while (complexTypeEnum.hasMoreElements())
926             {
927                 ComplexTypeInfo& curTypeInfo = complexTypeEnum.nextElement();
928                 curTypeInfo.checkUniqueParticleAttribution(&sGrammar, fGrammarResolver, fGrammarResolver->getStringPool(), this);
929                 checkParticleDerivation(&sGrammar, &curTypeInfo);
930                 checkRefElementConsistency(&sGrammar, &curTypeInfo);
931             }
932 
933             RefHashTableOf<XercesGroupInfo>* groupInfoRegistry = sGrammar.getGroupInfoRegistry();
934             RefHashTableOfEnumerator<XercesGroupInfo> groupEnum(groupInfoRegistry, false, fMemoryManager);
935 
936             while (groupEnum.hasMoreElements()) {
937 
938                 XercesGroupInfo& curGroup = groupEnum.nextElement();
939                 XercesGroupInfo* baseGroup = curGroup.getBaseGroup();
940 
941                 if (baseGroup) {
942                     try {
943                         checkParticleDerivationOk(&sGrammar, curGroup.getContentSpec(), curGroup.getScope(),
944                                                   baseGroup->getContentSpec(), baseGroup->getScope());
945                     }
946                     catch (const XMLException& excep) {
947                         fSchemaErrorReporter.emitError(excep, curGroup.getLocator());
948 					}
949                 }
950 
951                 if (curGroup.getCheckElementConsistency())
952                     checkRefElementConsistency(&sGrammar, 0, &curGroup);
953             }
954         }
955     }
956 }
957 
postParseValidation()958 void SchemaValidator::postParseValidation()
959 {
960     //
961     //  At this time, there is nothing to do here. The scanner itself handles
962     //  ID/IDREF validation, since that is the same no matter what kind of
963     //  validator.
964     //
965 }
966 
967 // ---------------------------------------------------------------------------
968 //  SchemaValidator: Validator method
969 // ---------------------------------------------------------------------------
970 // Do Schema Normalization depends on the WhiteSpace Facet
971 // preserve : No normalization is done
972 // replace  : All occurrences of #x9 (tab), #xA (linefeed) and #xD (carriage return)
973 //            are replaced with #x20 (space).
974 // collapse : Subsequent to the replacements specified above under replace,
975 //            contiguous sequences of #x20s are collapsed to a single #x20,
976 //            and initial and/or final #x20s are deleted.
977 //
normalizeWhiteSpace(DatatypeValidator * dV,const XMLCh * const value,XMLBuffer & toFill,bool bStandalone)978 void SchemaValidator::normalizeWhiteSpace(DatatypeValidator* dV, const XMLCh* const value, XMLBuffer& toFill, bool bStandalone /*= false*/)
979 {
980     toFill.reset();
981 
982     //empty string
983     if (!*value)
984         return;
985 
986     if(bStandalone)
987         fTrailing = fSeenNonWhiteSpace = false;
988 
989     short wsFacet = dV->getWSFacet();
990 
991     //  Loop through the chars of the source value and normalize it
992     //  according to the whitespace facet
993     XMLCh nextCh;
994     const XMLCh* srcPtr = value;
995     XMLReader* fCurReader = getReaderMgr()->getCurrentReader();
996 
997     if (wsFacet == DatatypeValidator::REPLACE)
998     {
999         while (*srcPtr)
1000         {
1001             nextCh = *srcPtr++;
1002             if (fCurReader->isWhitespace(nextCh))
1003                 nextCh = chSpace;
1004             // Add this char to the target buffer
1005             toFill.append(nextCh);
1006         }
1007     }
1008     else // COLLAPSE
1009     {
1010         enum States
1011         {
1012             InWhitespace
1013             , InContent
1014         };
1015 
1016         States curState = fTrailing ? InWhitespace : InContent;
1017         while (*srcPtr)
1018         {
1019             nextCh = *srcPtr++;
1020             if (curState == InContent)
1021             {
1022                 if (fCurReader->isWhitespace(nextCh))
1023                 {
1024                     curState = InWhitespace;
1025                     continue;
1026                 }
1027                 fSeenNonWhiteSpace = true;
1028             }
1029             else if (curState == InWhitespace)
1030             {
1031                 if (fCurReader->isWhitespace(nextCh))
1032                     continue;
1033                 if (fSeenNonWhiteSpace)
1034                     toFill.append(chSpace);
1035                 curState = InContent;
1036                 fSeenNonWhiteSpace = true;
1037             }
1038             // Add this char to the target buffer
1039             toFill.append(nextCh);
1040         }
1041 
1042         if (fCurReader->isWhitespace(*(srcPtr-1)))
1043           fTrailing = true;
1044         else
1045           fTrailing = false;
1046     }
1047     if(bStandalone)
1048         fTrailing = fSeenNonWhiteSpace = false;
1049 }
1050 
1051 
1052 // ---------------------------------------------------------------------------
1053 //  SchemaValidator: Particle Derivation Checking
1054 // ---------------------------------------------------------------------------
checkRefElementConsistency(SchemaGrammar * const currentGrammar,const ComplexTypeInfo * const curTypeInfo,const XercesGroupInfo * const curGroup)1055 void SchemaValidator::checkRefElementConsistency(SchemaGrammar* const currentGrammar,
1056                                                  const ComplexTypeInfo* const curTypeInfo,
1057                                                  const XercesGroupInfo* const curGroup) {
1058 
1059     XMLSize_t elemCount = (curTypeInfo) ? curTypeInfo->elementCount() : curGroup->elementCount();
1060     int elemScope = (curTypeInfo) ? curTypeInfo->getScopeDefined() : curGroup->getScope();
1061     XSDLocator* typeInfoLocator = (curTypeInfo) ? curTypeInfo->getLocator() : curGroup->getLocator();
1062 
1063     for (XMLSize_t i=0; i < elemCount; i++) {
1064 
1065         const SchemaElementDecl* elemDecl = (curTypeInfo) ? curTypeInfo->elementAt(i) : curGroup->elementAt(i);
1066 
1067         if (elemDecl->isGlobalDecl()) {
1068 
1069             unsigned int elemURI = elemDecl->getURI();
1070             const XMLCh* elemName = elemDecl->getBaseName();
1071             const SchemaElementDecl* other = (SchemaElementDecl*)
1072                 currentGrammar->getElemDecl(elemURI, elemName, 0, elemScope);
1073 
1074             if (other
1075                 && (elemDecl->getComplexTypeInfo() != other->getComplexTypeInfo() ||
1076                     elemDecl->getDatatypeValidator() != other->getDatatypeValidator())) {
1077                 fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration,
1078                                                XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager);
1079                 continue;
1080             }
1081 
1082             RefHash2KeysTableOf<ElemVector>* validSubsGroups = currentGrammar->getValidSubstitutionGroups();
1083             ValueVectorOf<SchemaElementDecl*>* subsElements = validSubsGroups->get(elemName, elemURI);
1084 
1085             if (subsElements) {
1086 
1087                 XMLSize_t subsElemSize = subsElements->size();
1088 
1089                 for (XMLSize_t j=0; j < subsElemSize; j++) {
1090 
1091                     SchemaElementDecl* subsElem = subsElements->elementAt(j);
1092                     const XMLCh* subsElemName = subsElem->getBaseName();
1093                     other = (SchemaElementDecl*)
1094                         currentGrammar->getElemDecl(subsElem->getURI(), subsElemName, 0, elemScope);
1095 
1096                     if (other
1097                         && (subsElem->getComplexTypeInfo() != other->getComplexTypeInfo()
1098                             || subsElem->getDatatypeValidator() != other->getDatatypeValidator())) {
1099                         fSchemaErrorReporter.emitError(XMLErrs::DuplicateElementDeclaration,
1100                                                        XMLUni::fgXMLErrDomain, typeInfoLocator, elemName, 0, 0, 0, fMemoryManager);
1101                     }
1102                 }
1103             }
1104         }
1105     }
1106 }
1107 
1108 // ---------------------------------------------------------------------------
1109 //  SchemaValidator: Particle Derivation Checking
1110 // ---------------------------------------------------------------------------
checkParticleDerivation(SchemaGrammar * const currentGrammar,const ComplexTypeInfo * const curTypeInfo)1111 void SchemaValidator::checkParticleDerivation(SchemaGrammar* const currentGrammar,
1112                                               const ComplexTypeInfo* const curTypeInfo) {
1113 
1114     ComplexTypeInfo* baseTypeInfo = 0;
1115     ContentSpecNode* curSpecNode = 0;
1116 
1117     if (curTypeInfo->getDerivedBy() == SchemaSymbols::XSD_RESTRICTION
1118         && ((baseTypeInfo = curTypeInfo->getBaseComplexTypeInfo()) != 0)
1119         && ((curSpecNode = curTypeInfo->getContentSpec()) != 0)) {
1120 
1121         try {
1122             checkParticleDerivationOk(currentGrammar, curSpecNode,
1123                                       curTypeInfo->getScopeDefined(),
1124                                       baseTypeInfo->getContentSpec(),
1125                                       baseTypeInfo->getScopeDefined(), baseTypeInfo);
1126         }
1127         catch (const XMLException& excep) {
1128             fSchemaErrorReporter.emitError(excep, curTypeInfo->getLocator());
1129         }
1130     }
1131 }
1132 
getNonUnaryGroup(ContentSpecNode * const pNode)1133 ContentSpecNode* SchemaValidator::getNonUnaryGroup(ContentSpecNode* const pNode) {
1134 
1135     int pNodeType = (pNode->getType() & 0x0f);
1136     if (pNodeType == ContentSpecNode::Leaf
1137         || pNodeType == ContentSpecNode::Any
1138         || pNodeType == ContentSpecNode::Any_Other
1139         || pNodeType == ContentSpecNode::Any_NS)
1140         return pNode;
1141 
1142     if (pNode->getMinOccurs() == 1 && pNode->getMaxOccurs() == 1
1143         && pNode->getFirst() && !pNode->getSecond())
1144         return getNonUnaryGroup(pNode->getFirst());
1145 
1146     return pNode;
1147 }
1148 
checkParticleDerivationOk(SchemaGrammar * const aGrammar,ContentSpecNode * const curNode,const int derivedScope,ContentSpecNode * const baseNode,const int baseScope,const ComplexTypeInfo * const baseInfo,const bool toCheckOccurence)1149 void SchemaValidator::checkParticleDerivationOk(SchemaGrammar* const aGrammar,
1150                                                 ContentSpecNode* const curNode,
1151                                                 const int derivedScope,
1152                                                 ContentSpecNode* const baseNode,
1153                                                 const int baseScope,
1154                                                 const ComplexTypeInfo* const baseInfo,
1155                                                 const bool toCheckOccurence) {
1156 
1157     // Check for pointless occurrences of all, choice, sequence.  The result is
1158     // the contentspec which is not pointless. If the result is a non-pointless
1159     // group, Vector is filled  in with the children of interest
1160     if (curNode && !baseNode)
1161         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_EmptyBase, fMemoryManager);
1162 
1163     if (!curNode)
1164         return;
1165 
1166     ContentSpecNode* curSpecNode = getNonUnaryGroup(curNode);
1167     ContentSpecNode* baseSpecNode = getNonUnaryGroup(baseNode);
1168     ValueVectorOf<ContentSpecNode*> curVector(8, fMemoryManager);
1169     ValueVectorOf<ContentSpecNode*> baseVector(8, fMemoryManager);
1170     ContentSpecNode::NodeTypes curNodeType = curSpecNode->getType();
1171     ContentSpecNode::NodeTypes baseNodeType = baseSpecNode->getType();
1172 
1173     if ((curNodeType & 0x0f) == ContentSpecNode::Sequence ||
1174         (curNodeType & 0x0f) == ContentSpecNode::Choice ||
1175         curNodeType == ContentSpecNode::All) {
1176         curSpecNode = checkForPointlessOccurrences(curSpecNode, curNodeType, &curVector);
1177     }
1178 
1179     if ((baseNodeType & 0x0f) == ContentSpecNode::Sequence ||
1180         (baseNodeType & 0x0f) == ContentSpecNode::Choice ||
1181         baseNodeType == ContentSpecNode::All) {
1182         baseSpecNode = checkForPointlessOccurrences(baseSpecNode, baseNodeType, &baseVector);
1183     }
1184 
1185     curNodeType = curSpecNode->getType();
1186     baseNodeType = baseSpecNode->getType();
1187 
1188     switch (curNodeType & 0x0f) {
1189     case ContentSpecNode::Leaf:
1190         {
1191             switch (baseNodeType & 0x0f) {
1192             case ContentSpecNode::Leaf:
1193                 {
1194                     checkNameAndTypeOK(aGrammar, curSpecNode, derivedScope, baseSpecNode, baseScope, baseInfo);
1195                     return;
1196                 }
1197             case ContentSpecNode::Any:
1198             case ContentSpecNode::Any_Other:
1199             case ContentSpecNode::Any_NS:
1200                 {
1201                     checkNSCompat(curSpecNode, baseSpecNode, toCheckOccurence);
1202                     return;
1203                 }
1204             case ContentSpecNode::Choice:
1205             case ContentSpecNode::Sequence:
1206             case ContentSpecNode::All:
1207                 {
1208                     checkRecurseAsIfGroup(aGrammar, curSpecNode, derivedScope,
1209                                           baseSpecNode, baseScope, &baseVector, baseInfo);
1210                     return;
1211                 }
1212             default:
1213                 {
1214                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1215                 }
1216             }
1217         }
1218     case ContentSpecNode::Any:
1219     case ContentSpecNode::Any_Other:
1220     case ContentSpecNode::Any_NS:
1221         {
1222             switch (baseNodeType & 0x0f) {
1223             case ContentSpecNode::Any:
1224             case ContentSpecNode::Any_Other:
1225             case ContentSpecNode::Any_NS:
1226                 {
1227                      checkNSSubset(curSpecNode, baseSpecNode);
1228                      return;
1229                 }
1230             case ContentSpecNode::Choice:
1231             case ContentSpecNode::Sequence:
1232             case ContentSpecNode::All:
1233             case ContentSpecNode::Leaf:
1234                 {
1235                     if (baseNodeType == ContentSpecNode::Any_NS_Choice) {
1236                         if (checkNSSubsetChoiceRoot(curSpecNode, baseSpecNode)) {
1237                             return;
1238                         }
1239                     }
1240 
1241                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes1, fMemoryManager);
1242                 }
1243             default:
1244                 {
1245                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1246                 }
1247             }
1248         }
1249     case ContentSpecNode::All:
1250         {
1251             switch (baseNodeType & 0x0f) {
1252             case ContentSpecNode::Any:
1253             case ContentSpecNode::Any_Other:
1254             case ContentSpecNode::Any_NS:
1255                 {
1256                     checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
1257                     return;
1258                 }
1259             case ContentSpecNode::All:
1260                 {
1261                     checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
1262                                  baseSpecNode, baseScope, &baseVector, baseInfo);
1263                     return;
1264                 }
1265             case ContentSpecNode::Choice:
1266             case ContentSpecNode::Sequence:
1267             case ContentSpecNode::Leaf:
1268                 {
1269                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes2, fMemoryManager);
1270                 }
1271             default:
1272                 {
1273                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1274                 }
1275             }
1276         }
1277     case ContentSpecNode::Choice:
1278         {
1279             switch (baseNodeType & 0x0f) {
1280             case ContentSpecNode::Any:
1281             case ContentSpecNode::Any_Other:
1282             case ContentSpecNode::Any_NS:
1283                 {
1284                     checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
1285                     return;
1286                 }
1287             case ContentSpecNode::Choice:
1288                 {
1289                     checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
1290                                  baseSpecNode, baseScope, &baseVector, baseInfo, true);
1291                     return;
1292                 }
1293             case ContentSpecNode::All:
1294             case ContentSpecNode::Sequence:
1295             case ContentSpecNode::Leaf:
1296                 {
1297                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes3, fMemoryManager);
1298                 }
1299             default:
1300                 {
1301                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1302                 }
1303             }
1304         }
1305     case ContentSpecNode::Sequence:
1306         {
1307             switch (baseNodeType & 0x0f) {
1308             case ContentSpecNode::Any:
1309             case ContentSpecNode::Any_Other:
1310             case ContentSpecNode::Any_NS:
1311                 {
1312                     checkNSRecurseCheckCardinality(aGrammar, curSpecNode, &curVector, derivedScope, baseSpecNode, toCheckOccurence);
1313                     return;
1314                 }
1315             case ContentSpecNode::All:
1316                 {
1317                     checkRecurseUnordered(aGrammar, curSpecNode, &curVector, derivedScope,
1318                                           baseSpecNode, &baseVector, baseScope, baseInfo);
1319                     return;
1320                 }
1321             case ContentSpecNode::Sequence:
1322                 {
1323                     checkRecurse(aGrammar, curSpecNode, derivedScope, &curVector,
1324                                  baseSpecNode, baseScope, &baseVector, baseInfo);
1325                     return;
1326                 }
1327             case ContentSpecNode::Choice:
1328                 {
1329                     checkMapAndSum(aGrammar, curSpecNode, &curVector, derivedScope,
1330                                    baseSpecNode, &baseVector, baseScope, baseInfo);
1331                     return;
1332                 }
1333             case ContentSpecNode::Leaf:
1334                 {
1335                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_ForbiddenRes4, fMemoryManager);
1336                 }
1337             default:
1338                 {
1339                     ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_InvalidContentType, fMemoryManager);
1340                 }
1341             }
1342         }
1343     }
1344 }
1345 
1346 ContentSpecNode*
checkForPointlessOccurrences(ContentSpecNode * const specNode,const ContentSpecNode::NodeTypes nodeType,ValueVectorOf<ContentSpecNode * > * const nodes)1347 SchemaValidator::checkForPointlessOccurrences(ContentSpecNode* const specNode,
1348                                               const ContentSpecNode::NodeTypes nodeType,
1349                                               ValueVectorOf<ContentSpecNode*>* const nodes) {
1350 
1351     ContentSpecNode* rightNode = specNode->getSecond();
1352     int min = specNode->getMinOccurs();
1353     int max = specNode->getMaxOccurs();
1354 
1355     if (!rightNode) {
1356 
1357          gatherChildren(nodeType, specNode->getFirst(), nodes);
1358 
1359          if (nodes->size() == 1 && min == 1 && max == 1) {
1360             return nodes->elementAt(0);
1361         }
1362 
1363         return specNode;
1364     }
1365 
1366     gatherChildren(nodeType, specNode->getFirst(), nodes);
1367     gatherChildren(nodeType, rightNode, nodes);
1368 
1369     return specNode;
1370 }
1371 
gatherChildren(const ContentSpecNode::NodeTypes parentNodeType,ContentSpecNode * const specNode,ValueVectorOf<ContentSpecNode * > * const nodes)1372 void SchemaValidator::gatherChildren(const ContentSpecNode::NodeTypes parentNodeType,
1373                                     ContentSpecNode* const specNode,
1374                                     ValueVectorOf<ContentSpecNode*>* const nodes) {
1375 
1376     if (!specNode) {
1377         return;
1378     }
1379 
1380     int min = specNode->getMinOccurs();
1381     int max = specNode->getMaxOccurs();
1382     ContentSpecNode::NodeTypes nodeType = specNode->getType();
1383     ContentSpecNode* rightNode = specNode->getSecond();
1384 
1385     if (nodeType == ContentSpecNode::Leaf ||
1386         (nodeType & 0x0f) == ContentSpecNode::Any ||
1387         (nodeType & 0x0f) == ContentSpecNode::Any_NS ||
1388         (nodeType & 0x0f) == ContentSpecNode::Any_Other) {
1389         nodes->addElement(specNode);
1390     }
1391     else if (min !=1 || max != 1) {
1392         nodes->addElement(specNode);
1393     }
1394     else if (!rightNode) {
1395         gatherChildren(nodeType, specNode->getFirst(), nodes);
1396     }
1397     else if ((parentNodeType & 0x0f) == (nodeType & 0x0f)) {
1398 
1399         gatherChildren(nodeType, specNode->getFirst(), nodes);
1400         gatherChildren(nodeType, rightNode, nodes);
1401     }
1402     else {
1403         nodes->addElement(specNode);
1404     }
1405 }
1406 
1407 void
checkNSCompat(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode,const bool toCheckOccurence)1408 SchemaValidator::checkNSCompat(const ContentSpecNode* const derivedSpecNode,
1409                                const ContentSpecNode* const baseSpecNode,
1410                                const bool toCheckOccurence) {
1411 
1412     // check Occurrence ranges
1413     if (toCheckOccurence &&
1414         !isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1415                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1416         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE,
1417                   derivedSpecNode->getElement()->getLocalPart(), fMemoryManager);
1418     }
1419 
1420     // check wildcard subset
1421     if (!wildcardEltAllowsNamespace(baseSpecNode, derivedSpecNode->getElement()->getURI())) {
1422         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NSCompat1,
1423                   derivedSpecNode->getElement()->getLocalPart(), fMemoryManager);
1424     }
1425 }
1426 
1427 bool
wildcardEltAllowsNamespace(const ContentSpecNode * const baseSpecNode,const unsigned int derivedURI)1428 SchemaValidator::wildcardEltAllowsNamespace(const ContentSpecNode* const baseSpecNode,
1429                                             const unsigned int derivedURI) {
1430 
1431     ContentSpecNode::NodeTypes nodeType = baseSpecNode->getType();
1432 
1433     if ((nodeType & 0x0f) == ContentSpecNode::Any) {
1434         return true;
1435     }
1436 
1437     unsigned int baseURI = baseSpecNode->getElement()->getURI();
1438 
1439     if ((nodeType & 0x0f) == ContentSpecNode::Any_NS) {
1440         if (derivedURI == baseURI) {
1441            return true;
1442         }
1443     }
1444     else { // must be ANY_OTHER
1445         if (derivedURI != baseURI && derivedURI != getScanner()->getEmptyNamespaceId()) {
1446             return true;
1447         }
1448     }
1449 
1450     return false;
1451 }
1452 
1453 void
checkNameAndTypeOK(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,const int derivedScope,const ContentSpecNode * const baseSpecNode,const int baseScope,const ComplexTypeInfo * const baseInfo)1454 SchemaValidator::checkNameAndTypeOK(SchemaGrammar* const currentGrammar,
1455                                     const ContentSpecNode* const derivedSpecNode,
1456                                     const int derivedScope,
1457                                     const ContentSpecNode* const baseSpecNode,
1458                                     const int baseScope,
1459                                     const ComplexTypeInfo* const baseInfo) {
1460 
1461     if (derivedSpecNode->getMaxOccurs() == 0)
1462         return;
1463 
1464     unsigned int derivedURI = derivedSpecNode->getElement()->getURI();
1465 
1466     // case of mixed complex types with attributes only
1467     if (derivedURI == XMLElementDecl::fgPCDataElemId) {
1468         return;
1469     }
1470 
1471     SchemaGrammar* dGrammar = currentGrammar;
1472 
1473     if (derivedURI != getScanner()->getEmptyNamespaceId())
1474     {
1475         const XMLCh* dURI = fGrammarResolver->getStringPool()->getValueForId(derivedURI);
1476         dGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(dURI);
1477     }
1478 
1479     if (!dGrammar) { //something is wrong
1480         return;
1481     }
1482 
1483     const XMLCh* derivedName = derivedSpecNode->getElement()->getLocalPart();
1484 
1485     SchemaElementDecl* derivedElemDecl = findElement(derivedScope, derivedURI, derivedName, dGrammar);
1486 
1487     if (!derivedElemDecl) {
1488         return;
1489     }
1490 
1491     const XMLCh* baseName = baseSpecNode->getElement()->getLocalPart();
1492     unsigned int baseURI = baseSpecNode->getElement()->getURI();
1493     bool subsGroup = false;
1494 
1495     if (!XMLString::equals(derivedName, baseName) || derivedURI != baseURI) {
1496         // Check if derived is substitutable for base.
1497         //
1498         SchemaElementDecl* e = derivedElemDecl->getSubstitutionGroupElem ();
1499 
1500         for (; e != 0; e = e->getSubstitutionGroupElem ()) {
1501             if (XMLString::equals(e->getBaseName (), baseName) && e->getURI () == baseURI) {
1502                 break;
1503             }
1504         }
1505 
1506         if (e == 0) {
1507             ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NameTypeOK1, fMemoryManager);
1508         }
1509 
1510         subsGroup = true;
1511     }
1512 
1513     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1514                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1515         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_OccurRangeE, derivedName, fMemoryManager);
1516     }
1517 
1518     // Find the schema grammar for the base element using the base type as
1519     // a reference if it is available (it is unavailable if we are checking
1520     // element group restriction which happens in redefine).
1521     //
1522     SchemaGrammar* bGrammar = dGrammar;
1523 
1524     if (baseInfo)
1525     {
1526         const XMLCh* baseTypeURI = baseInfo->getTypeUri ();
1527 
1528         if (baseTypeURI != 0 && *baseTypeURI != 0) // Non-empty namespace.
1529             bGrammar= (SchemaGrammar*) fGrammarResolver->getGrammar(baseTypeURI);
1530 
1531         if (!bGrammar) { //something is wrong
1532             return;
1533         }
1534     }
1535 
1536     SchemaElementDecl* baseElemDecl =
1537         findElement(baseScope, baseURI, baseName, bGrammar, baseInfo);
1538 
1539     if (!baseElemDecl) {
1540         return;
1541     }
1542 
1543     int derivedFlags = derivedElemDecl->getMiscFlags();
1544     int baseFlags = baseElemDecl->getMiscFlags();
1545 
1546     if (((baseFlags & SchemaSymbols::XSD_NILLABLE) == 0) &&
1547 		((derivedFlags & SchemaSymbols::XSD_NILLABLE) != 0)) {
1548         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK2, derivedName, fMemoryManager);
1549     }
1550 
1551     const XMLCh* derivedDefVal = derivedElemDecl->getDefaultValue();
1552     const XMLCh* baseDefVal = baseElemDecl->getDefaultValue();
1553 
1554     if (baseDefVal && (baseFlags & SchemaSymbols::XSD_FIXED) != 0 &&
1555         ((derivedFlags & SchemaSymbols::XSD_FIXED) == 0 ||
1556          !XMLString::equals(derivedDefVal, baseDefVal))) {
1557         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK3, derivedName, fMemoryManager);
1558     }
1559 
1560     int derivedBlockSet = derivedElemDecl->getBlockSet();
1561     int baseBlockSet = baseElemDecl->getBlockSet();
1562 
1563     if ((derivedBlockSet & baseBlockSet) != baseBlockSet) {
1564         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK4, derivedName, fMemoryManager);
1565     }
1566 
1567     // check identity constraints
1568     checkICRestriction(derivedElemDecl, baseElemDecl, derivedName, baseName);
1569 
1570     // check that the derived element's type is derived from the base's.
1571     if (!subsGroup)
1572         checkTypesOK(derivedElemDecl, baseElemDecl, derivedName);
1573 }
1574 
1575 SchemaElementDecl*
findElement(const int scope,const unsigned int uriIndex,const XMLCh * const name,SchemaGrammar * const grammar,const ComplexTypeInfo * const typeInfo)1576 SchemaValidator::findElement(const int scope, const unsigned int uriIndex,
1577                              const XMLCh* const name,
1578                              SchemaGrammar* const grammar,
1579                              const ComplexTypeInfo* const typeInfo) {
1580 
1581     // check for element at given scope first
1582     SchemaElementDecl* elemDecl = (SchemaElementDecl*) grammar->getElemDecl(uriIndex, name, 0, scope);
1583 
1584     // if not found, check at global scope
1585     if (!elemDecl) {
1586 
1587         elemDecl = (SchemaElementDecl*)
1588             grammar->getElemDecl(uriIndex, name, 0, Grammar::TOP_LEVEL_SCOPE);
1589 
1590         // if still not found, and base is specified, look it up there
1591         if (!elemDecl && typeInfo) {
1592 
1593             const ComplexTypeInfo* baseInfo = typeInfo;
1594 
1595             while (baseInfo) {
1596 
1597                 elemDecl = (SchemaElementDecl*)
1598                     grammar->getElemDecl(uriIndex, name, 0, baseInfo->getScopeDefined());
1599 
1600                 if (elemDecl) {
1601                    break;
1602                 }
1603 
1604                 baseInfo = baseInfo->getBaseComplexTypeInfo();
1605             }
1606         }
1607     }
1608 
1609     return elemDecl;
1610 }
1611 
1612 void
checkICRestriction(const SchemaElementDecl * const derivedElemDecl,const SchemaElementDecl * const baseElemDecl,const XMLCh * const derivedElemName,const XMLCh * const baseElemName)1613 SchemaValidator::checkICRestriction(const SchemaElementDecl* const derivedElemDecl,
1614                                    const SchemaElementDecl* const baseElemDecl,
1615                                    const XMLCh* const derivedElemName,
1616                                    const XMLCh* const baseElemName) {
1617 
1618     // REVIST - need to get more clarification
1619     XMLSize_t derivedICCount = derivedElemDecl->getIdentityConstraintCount();
1620     XMLSize_t baseICCount = baseElemDecl->getIdentityConstraintCount();
1621 
1622     if (derivedICCount > baseICCount) {
1623         ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK6, derivedElemName, baseElemName, fMemoryManager);
1624     }
1625 
1626     for (XMLSize_t i=0; i < derivedICCount; i++) {
1627 
1628         bool found = false;
1629         IdentityConstraint* ic= derivedElemDecl->getIdentityConstraintAt(i);
1630 
1631         for (XMLSize_t j=0; j < baseICCount; j++) {
1632             if (*ic == *(baseElemDecl->getIdentityConstraintAt(j))) {
1633 
1634                 found = true;
1635                 break;
1636             }
1637         }
1638 
1639         if (!found) {
1640             ThrowXMLwithMemMgr2(RuntimeException, XMLExcepts::PD_NameTypeOK7, derivedElemName, baseElemName, fMemoryManager);
1641         }
1642     }
1643 }
1644 
1645 void
checkTypesOK(const SchemaElementDecl * const derivedElemDecl,const SchemaElementDecl * const baseElemDecl,const XMLCh * const derivedElemName)1646 SchemaValidator::checkTypesOK(const SchemaElementDecl* const derivedElemDecl,
1647                               const SchemaElementDecl* const baseElemDecl,
1648                               const XMLCh* const derivedElemName) {
1649 
1650     SchemaElementDecl::ModelTypes baseType = baseElemDecl->getModelType();
1651 
1652     if (baseType == SchemaElementDecl::Any) {
1653         return;
1654     }
1655 
1656     ComplexTypeInfo* rInfo = derivedElemDecl->getComplexTypeInfo();
1657     ComplexTypeInfo* bInfo = baseElemDecl->getComplexTypeInfo();
1658 
1659     if (derivedElemDecl->getModelType() == SchemaElementDecl::Simple) {
1660 
1661         if (baseType != SchemaElementDecl::Simple) {
1662             ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
1663         }
1664 
1665         if (!rInfo) {
1666 
1667             DatatypeValidator* bDV = baseElemDecl->getDatatypeValidator();
1668 
1669             if (bInfo || bDV == 0 ||
1670 				!bDV->isSubstitutableBy(derivedElemDecl->getDatatypeValidator())) {
1671                 ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
1672             }
1673 
1674             return;
1675         }
1676     }
1677 
1678     if (rInfo == bInfo)
1679         return;
1680 
1681     for (; rInfo && rInfo != bInfo; rInfo = rInfo->getBaseComplexTypeInfo()) {
1682         if (rInfo->getDerivedBy() != SchemaSymbols::XSD_RESTRICTION) {
1683 
1684             rInfo = 0;
1685             break;
1686         }
1687     }
1688 
1689     if (!rInfo) {
1690         ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::PD_NameTypeOK5, derivedElemName, fMemoryManager);
1691     }
1692 }
1693 
1694 void
checkRecurseAsIfGroup(SchemaGrammar * const currentGrammar,ContentSpecNode * const derivedSpecNodeIn,const int derivedScope,const ContentSpecNode * const baseSpecNode,const int baseScope,ValueVectorOf<ContentSpecNode * > * const baseNodes,const ComplexTypeInfo * const baseInfo)1695 SchemaValidator::checkRecurseAsIfGroup(SchemaGrammar* const currentGrammar,
1696                                        ContentSpecNode* const derivedSpecNodeIn,
1697                                        const int derivedScope,
1698                                        const ContentSpecNode* const baseSpecNode,
1699                                        const int baseScope,
1700                                        ValueVectorOf<ContentSpecNode*>* const baseNodes,
1701                                        const ComplexTypeInfo* const baseInfo) {
1702 
1703     ContentSpecNode::NodeTypes baseType = baseSpecNode->getType();
1704     bool toLax = false;
1705 
1706     //Treat the element as if it were in a group of the same variety as base
1707     ContentSpecNode derivedGroupNode(baseType, derivedSpecNodeIn, 0, false, true, fMemoryManager);
1708     const ContentSpecNode* const derivedSpecNode = &derivedGroupNode;
1709 
1710     if ((baseSpecNode->getType() & 0x0f) == ContentSpecNode::Choice) {
1711         toLax = true;
1712     }
1713 
1714     // Instead of calling this routine, inline it
1715     // checkRecurse(currentGrammar, &derivedGroupNode, derivedScope, &derivedNodes,
1716     //             baseSpecNode, baseScope, baseNodes, baseInfo, toLax);
1717 
1718     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1719                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1720         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
1721     }
1722 
1723     // check for mapping of children
1724     XMLExcepts::Codes codeToThrow = XMLExcepts::NoError;
1725     XMLSize_t count2= baseNodes->size();
1726     XMLSize_t current = 0;
1727 
1728     {
1729         bool matched = false;
1730 
1731         for (XMLSize_t j = current; j < count2; j++) {
1732 
1733             ContentSpecNode* baseNode = baseNodes->elementAt(j);
1734             current++;
1735 
1736             bool bDoBreak=false;    // workaround for Borland bug with 'break' in 'catch'
1737             try {
1738 
1739                 checkParticleDerivationOk(currentGrammar, derivedSpecNodeIn,
1740                                           derivedScope, baseNode, baseScope, baseInfo);
1741                 matched = true;
1742                 break;
1743             }
1744             catch(const XMLException&) {
1745                 if (!toLax && baseNode->getMinTotalRange()) {
1746                     bDoBreak=true;
1747                 }
1748             }
1749             if(bDoBreak)
1750                 break;
1751         }
1752 
1753         // did not find a match
1754         if (!matched) {
1755             codeToThrow = XMLExcepts::PD_Recurse2;
1756         }
1757     }
1758 
1759     // Now, see if there are some elements in the base we didn't match up
1760     // in case of Sequence or All
1761     if (!toLax && codeToThrow == XMLExcepts::NoError) {
1762         for (XMLSize_t j = current; j < count2; j++) {
1763             if (baseNodes->elementAt(j)->getMinTotalRange() * baseSpecNode->getMinOccurs()) { //!emptiable
1764                 codeToThrow =  XMLExcepts::PD_Recurse2;
1765                 break;
1766             }
1767         }
1768     }
1769 
1770     if (codeToThrow != XMLExcepts::NoError) {
1771         ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
1772     }
1773 }
1774 
1775 void
checkRecurse(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,const int derivedScope,ValueVectorOf<ContentSpecNode * > * const derivedNodes,const ContentSpecNode * const baseSpecNode,const int baseScope,ValueVectorOf<ContentSpecNode * > * const baseNodes,const ComplexTypeInfo * const baseInfo,const bool toLax)1776 SchemaValidator::checkRecurse(SchemaGrammar* const currentGrammar,
1777                               const ContentSpecNode* const derivedSpecNode,
1778                               const int derivedScope,
1779                               ValueVectorOf<ContentSpecNode*>* const derivedNodes,
1780                               const ContentSpecNode* const baseSpecNode,
1781                               const int baseScope,
1782                               ValueVectorOf<ContentSpecNode*>* const baseNodes,
1783                               const ComplexTypeInfo* const baseInfo,
1784                               const bool toLax) {
1785 
1786     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1787                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1788         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
1789     }
1790 
1791     // check for mapping of children
1792     XMLExcepts::Codes codeToThrow = XMLExcepts::NoError;
1793     XMLSize_t count1= derivedNodes->size();
1794     XMLSize_t count2= baseNodes->size();
1795     XMLSize_t current = 0;
1796 
1797     for (XMLSize_t i=0; i<count1; i++) {
1798 
1799         bool matched = false;
1800 
1801         for (XMLSize_t j = current; j < count2; j++) {
1802 
1803             ContentSpecNode* baseNode = baseNodes->elementAt(j);
1804             current++;
1805 
1806             bool bDoBreak=false;    // workaround for Borland bug with 'break' in 'catch'
1807             try {
1808 
1809                 checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i),
1810                                           derivedScope, baseNode, baseScope, baseInfo);
1811                 matched = true;
1812                 break;
1813             }
1814             catch(const XMLException&) {
1815                 if (!toLax && baseNode->getMinTotalRange()) {
1816                     bDoBreak=true;
1817                 }
1818             }
1819             if(bDoBreak)
1820                 break;
1821         }
1822 
1823         // did not find a match
1824         if (!matched) {
1825 
1826             codeToThrow = XMLExcepts::PD_Recurse2;
1827             break;
1828         }
1829     }
1830 
1831     // Now, see if there are some elements in the base we didn't match up
1832     // in case of Sequence or All
1833     if (!toLax && codeToThrow == XMLExcepts::NoError) {
1834         for (XMLSize_t j = current; j < count2; j++) {
1835             if (baseNodes->elementAt(j)->getMinTotalRange()) { //!emptiable
1836                 codeToThrow =  XMLExcepts::PD_Recurse2;
1837                 break;
1838             }
1839         }
1840     }
1841 
1842     if (codeToThrow != XMLExcepts::NoError) {
1843         ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
1844     }
1845 }
1846 
checkNSSubset(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode)1847 void SchemaValidator::checkNSSubset(const ContentSpecNode* const derivedSpecNode,
1848                                     const ContentSpecNode* const baseSpecNode) {
1849 
1850     // check Occurrence ranges
1851     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1852                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1853         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset1, fMemoryManager);
1854     }
1855 
1856     if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) {
1857         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSSubset2, fMemoryManager);
1858     }
1859 }
1860 
checkNSSubsetChoiceRoot(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode)1861 bool SchemaValidator::checkNSSubsetChoiceRoot(const ContentSpecNode* const derivedSpecNode,
1862                                     const ContentSpecNode* const baseSpecNode) {
1863     bool found = false;
1864 
1865     if (baseSpecNode->getType() == ContentSpecNode::Any_NS_Choice) {
1866         const ContentSpecNode* first = baseSpecNode->getFirst();
1867         const ContentSpecNode* second = baseSpecNode->getSecond();
1868 
1869         if (first) {
1870             found = checkNSSubsetChoiceRoot(derivedSpecNode, first);
1871             if (found) return true;
1872         }
1873         if (second) {
1874             found = checkNSSubsetChoiceRoot(derivedSpecNode, second);
1875             if (found) return true;
1876         }
1877     }
1878     else { // should be Any_NS
1879         found = checkNSSubsetChoice(derivedSpecNode, baseSpecNode);
1880     }
1881 
1882     return found;
1883 }
1884 
checkNSSubsetChoice(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode)1885 bool SchemaValidator::checkNSSubsetChoice(const ContentSpecNode* const derivedSpecNode,
1886                                     const ContentSpecNode* const baseSpecNode) {
1887 
1888     // check Occurrence ranges
1889     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1890                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1891         return false;
1892     }
1893 
1894     if (!isWildCardEltSubset(derivedSpecNode, baseSpecNode)) {
1895         return false;
1896     }
1897     return true;
1898 }
1899 
1900 bool
isWildCardEltSubset(const ContentSpecNode * const derivedSpecNode,const ContentSpecNode * const baseSpecNode)1901 SchemaValidator::isWildCardEltSubset(const ContentSpecNode* const derivedSpecNode,
1902                                      const ContentSpecNode* const baseSpecNode) {
1903 
1904     ContentSpecNode::NodeTypes baseType = baseSpecNode->getType();
1905 
1906     if ((baseType & 0x0f) == ContentSpecNode::Any) {
1907         return true;
1908     }
1909 
1910     ContentSpecNode::NodeTypes derivedType = derivedSpecNode->getType();
1911     unsigned int baseURI = baseSpecNode->getElement()->getURI();
1912     unsigned int derivedURI = derivedSpecNode->getElement()->getURI();
1913 
1914     // Below we assume that empty string has id 1.
1915     //
1916     if (((derivedType & 0x0f) == ContentSpecNode::Any_Other) &&
1917         ((baseType & 0x0f) == ContentSpecNode::Any_Other) &&
1918         (baseURI == derivedURI || baseURI == 1)) {
1919         return true;
1920     }
1921 
1922     if ((derivedType & 0x0f) == ContentSpecNode::Any_NS) {
1923 
1924         if (((baseType & 0x0f) == ContentSpecNode::Any_NS) &&
1925             baseURI == derivedURI) {
1926             return true;
1927         }
1928 
1929         if (((baseType & 0x0f) == ContentSpecNode::Any_Other) &&
1930             (derivedURI == 1 || baseURI != derivedURI)) {
1931             return true;
1932         }
1933     }
1934 
1935     return false;
1936 }
1937 
1938 void
checkNSRecurseCheckCardinality(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,ValueVectorOf<ContentSpecNode * > * const derivedNodes,const int derivedScope,ContentSpecNode * const baseSpecNode,const bool toCheckOccurence)1939 SchemaValidator::checkNSRecurseCheckCardinality(SchemaGrammar* const currentGrammar,
1940                                                 const ContentSpecNode* const derivedSpecNode,
1941                                                 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
1942                                                 const int derivedScope,
1943                                                 ContentSpecNode* const baseSpecNode,
1944                                                 const bool toCheckOccurence) {
1945 
1946     // Implement total range check
1947     int derivedMin = derivedSpecNode->getMinTotalRange();
1948     int derivedMax = derivedSpecNode->getMaxTotalRange();
1949 
1950     // check Occurrence ranges
1951     if (toCheckOccurence &&
1952         !isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(),
1953                               baseSpecNode->getMaxOccurs())) {
1954         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_NSRecurseCheckCardinality1, fMemoryManager);
1955     }
1956 
1957     // Check that each member of the group is a valid restriction of the wildcard
1958     XMLSize_t nodesCount = derivedNodes->size();
1959 
1960     for (XMLSize_t i = 0; i < nodesCount; i++) {
1961         checkParticleDerivationOk(currentGrammar, derivedNodes->elementAt(i), derivedScope, baseSpecNode, -1, 0, false);
1962     }
1963 }
1964 
1965 void
checkRecurseUnordered(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,ValueVectorOf<ContentSpecNode * > * const derivedNodes,const int derivedScope,ContentSpecNode * const baseSpecNode,ValueVectorOf<ContentSpecNode * > * const baseNodes,const int baseScope,const ComplexTypeInfo * const baseInfo)1966 SchemaValidator::checkRecurseUnordered(SchemaGrammar* const currentGrammar,
1967                                        const ContentSpecNode* const derivedSpecNode,
1968                                        ValueVectorOf<ContentSpecNode*>* const derivedNodes,
1969                                        const int derivedScope,
1970                                        ContentSpecNode* const baseSpecNode,
1971                                        ValueVectorOf<ContentSpecNode*>* const baseNodes,
1972                                        const int baseScope,
1973                                        const ComplexTypeInfo* const baseInfo) {
1974 
1975     // check Occurrence ranges
1976     if (!isOccurrenceRangeOK(derivedSpecNode->getMinOccurs(), derivedSpecNode->getMaxOccurs(),
1977                              baseSpecNode->getMinOccurs(), baseSpecNode->getMaxOccurs())) {
1978         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
1979     }
1980 
1981     XMLExcepts::Codes  codeToThrow = XMLExcepts::NoError;
1982     XMLSize_t          derivedCount= derivedNodes->size();
1983     XMLSize_t          baseCount = baseNodes->size();
1984     bool*              foundIt = (bool*) fMemoryManager->allocate
1985     (
1986         baseCount * sizeof(bool)
1987     );//new bool[baseCount];
1988     ArrayJanitor<bool> janFoundIt(foundIt, fMemoryManager);
1989 
1990     for (XMLSize_t k=0; k < baseCount; k++) {
1991         foundIt[k] = false;
1992     }
1993 
1994     // check for mapping of children
1995     for (XMLSize_t i = 0; i < derivedCount; i++) {
1996 
1997         ContentSpecNode* derivedNode = derivedNodes->elementAt(i);
1998         bool matched = false;
1999 
2000         for (XMLSize_t j = 0; j < baseCount; j++) {
2001 
2002             try {
2003 
2004                 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope,
2005                                           baseNodes->elementAt(j), baseScope, baseInfo);
2006 
2007                 if (foundIt[j]) {
2008                     break;
2009                 }
2010 
2011                 foundIt[j] = true;
2012                 matched = true;
2013                 break;
2014             }
2015             catch (const XMLException&) {
2016             }
2017         }
2018 
2019         // didn't find a match.
2020         if (!matched) {
2021 
2022 	        codeToThrow = XMLExcepts::PD_RecurseUnordered;
2023             break;
2024         }
2025     }
2026 
2027     // For all unmapped particles in base, check to see it it's emptiable or not
2028     if (codeToThrow == XMLExcepts::NoError) {
2029         for (XMLSize_t j=0; j < baseCount; j++) {
2030             if (!foundIt[j] && baseNodes->elementAt(j)->getMinTotalRange()) {
2031 
2032 	            codeToThrow = XMLExcepts::PD_RecurseUnordered;
2033                 break;
2034             }
2035         }
2036     }
2037 
2038     if (codeToThrow != XMLExcepts::NoError) {
2039         ThrowXMLwithMemMgr(RuntimeException, codeToThrow, fMemoryManager);
2040     }
2041 }
2042 
2043 void
checkMapAndSum(SchemaGrammar * const currentGrammar,const ContentSpecNode * const derivedSpecNode,ValueVectorOf<ContentSpecNode * > * const derivedNodes,const int derivedScope,ContentSpecNode * const baseSpecNode,ValueVectorOf<ContentSpecNode * > * const baseNodes,const int baseScope,const ComplexTypeInfo * const baseInfo)2044 SchemaValidator::checkMapAndSum(SchemaGrammar* const currentGrammar,
2045                                 const ContentSpecNode* const derivedSpecNode,
2046                                 ValueVectorOf<ContentSpecNode*>* const derivedNodes,
2047                                 const int derivedScope,
2048                                 ContentSpecNode* const baseSpecNode,
2049                                 ValueVectorOf<ContentSpecNode*>* const baseNodes,
2050                                 const int baseScope,
2051                                 const ComplexTypeInfo* const baseInfo) {
2052 
2053     // check Occurrence ranges
2054     XMLSize_t derivedCount = derivedNodes->size();
2055     XMLSize_t baseCount = baseNodes->size();
2056     int derivedMin = derivedSpecNode->getMinOccurs() * (unsigned int)derivedCount;
2057     int derivedMax = derivedSpecNode->getMaxOccurs();
2058 
2059     if (derivedMax != SchemaSymbols::XSD_UNBOUNDED) {
2060         derivedMax *= (unsigned int)derivedCount;
2061     }
2062 
2063     if (!isOccurrenceRangeOK(derivedMin, derivedMax, baseSpecNode->getMinOccurs(),
2064                              baseSpecNode->getMaxOccurs())) {
2065         ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_Recurse1, fMemoryManager);
2066     }
2067 
2068     // check for mapping of children
2069     for (XMLSize_t i = 0; i < derivedCount; i++) {
2070 
2071         ContentSpecNode* derivedNode = derivedNodes->elementAt(i);
2072         bool matched = false;
2073 
2074         for (XMLSize_t j = 0; j < baseCount && !matched; j++) {
2075 
2076             try {
2077 
2078                 checkParticleDerivationOk(currentGrammar, derivedNode, derivedScope,
2079                                           baseNodes->elementAt(j), baseScope, baseInfo);
2080                 matched = true;
2081             }
2082             catch (const XMLException&) {
2083             }
2084         }
2085 
2086         // didn't find a match.
2087         if (!matched) {
2088 	        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::PD_MapAndSum, fMemoryManager);
2089         }
2090     }
2091 
2092 }
2093 
2094 XERCES_CPP_NAMESPACE_END
2095