source: icXML/icXML-devel/src/icxercesc/internal/IGXMLScanner2.cpp @ 3157

Last change on this file since 3157 was 3157, checked in by cameron, 6 years ago

Fixes for icXML 0.9

File size: 32.9 KB
Line 
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: IGXMLScanner2.cpp 925236 2010-03-19 14:29:47Z borisk $
20 */
21
22// ---------------------------------------------------------------------------
23//  This file holds some of the grunt work methods of IGXMLScanner.cpp to keep
24//  it a little more readable.
25// ---------------------------------------------------------------------------
26
27// ---------------------------------------------------------------------------
28//  Includes
29// ---------------------------------------------------------------------------
30#include <icxercesc/internal/IGXMLScanner.hpp>
31#include <xercesc/util/UnexpectedEOFException.hpp>
32#include <xercesc/util/XMLUri.hpp>
33#include <xercesc/framework/LocalFileInputSource.hpp>
34#include <xercesc/framework/URLInputSource.hpp>
35#include <icxercesc/framework/XMLDocumentHandler.hpp>
36#include <xercesc/framework/XMLEntityHandler.hpp>
37#include <xercesc/framework/XMLPScanToken.hpp>
38#include <xercesc/framework/XMLRefInfo.hpp>
39#include <icxercesc/framework/XMLGrammarPool.hpp>
40#include <xercesc/framework/psvi/XSAnnotation.hpp>
41#include <xercesc/validators/common/ContentLeafNameTypeVector.hpp>
42#include <xercesc/validators/DTD/XMLDTDDescriptionImpl.hpp>
43#include <xercesc/validators/datatype/DatatypeValidator.hpp>
44#include <xercesc/validators/schema/XMLSchemaDescriptionImpl.hpp>
45#include <icxercesc/validators/schema/TraverseSchema.hpp>
46#include <icxercesc/validators/schema/SubstitutionGroupComparator.hpp>
47#include <icxercesc/validators/schema/XSDDOMParser.hpp>
48#include <icxercesc/validators/schema/identity/IdentityConstraintHandler.hpp>
49#include <xercesc/validators/schema/identity/ValueStore.hpp>
50#include <icxmlc/XMLParallelTokenizer.hpp>
51
52XERCES_CPP_NAMESPACE_BEGIN
53
54//  This method will reset the scanner data structures, and related plugged
55//  in stuff, for a new scan session. We get the input source for the primary
56//  XML entity, create the reader for it, and push it on the stack so that
57//  upon successful return from here we are ready to go.
58void IGXMLScanner::scanReset(const InputSource& src)
59{
60        //  This call implicitly tells us that we are going to reuse the scanner
61        //  if it was previously used. So tell the validator to reset itself.
62        //
63        //  But, if the fUseCacheGrammar flag is set, then don't reset it.
64        //
65        //  NOTE:   The ReaderMgr is flushed on the way out, because that is
66        //          required to insure that files are closed.
67        fGrammarResolver->cacheGrammarFromParse(fToCacheGrammar);
68        fGrammarResolver->useCachedGrammarInParse(fUseCachedGrammar);
69
70        // Clear transient schema info list.
71        //
72        fSchemaInfoList->removeAll();
73
74        // fModel may need updating, as fGrammarResolver could have cleaned it
75        if (fModel && getPSVIHandler())
76        {
77                fModel = fGrammarResolver->getXSModel();
78        }
79
80        do
81        {
82                XMLDTDDescriptionImpl theDTDDescription(XMLUni::fgDTDEntityString, fMemoryManager);
83                fDTDGrammar = (DTDGrammar*) fGrammarResolver->getGrammar(&theDTDDescription);
84        } while (0);
85
86        if (!fDTDGrammar)
87        {
88                fDTDGrammar = new (fGrammarPoolMemoryManager) DTDGrammar(fGrammarPoolMemoryManager);
89                fGrammarResolver->putGrammar(fDTDGrammar);
90        }
91        else
92        {
93                fDTDGrammar->reset();
94        }
95        fGrammar = fDTDGrammar;
96        fGrammarType = fGrammar->getGrammarType();
97        fRootGrammar = 0;
98
99        if (fValidatorFromUser)
100        {
101                if (fValidator->handlesDTD())
102                {
103                        fValidator->setGrammar(fGrammar);
104                }
105                else if (fValidator->handlesSchema())
106                {
107                        fSchemaValidator->setErrorReporter(fErrorReporter);
108                        fSchemaValidator->setGrammarResolver(fGrammarResolver);
109                        fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
110                }
111        }
112        else
113        {
114                // set fValidator as fDTDValidator
115                fValidator = fDTDValidator;
116                fValidator->setGrammar(fGrammar);
117        }
118
119        // Reset validation
120        fValidate = (fValScheme == Val_Always) ? true : false;
121
122        // Ignore skipDTDValidation flag if no schema processing is taking place */
123        fSkipDTDValidation = fSkipDTDValidation && fDoSchema;
124
125        //  And for all installed handlers, send reset events. This gives them
126        //  a chance to flush any cached data.
127        if (fDocHandler)
128                fDocHandler->resetDocument();
129        if (fEntityHandler)
130                fEntityHandler->resetEntities();
131        if (fErrorReporter)
132                fErrorReporter->resetErrors();
133
134        // Clear out the id reference list
135        resetValidationContext();
136
137        // Reset the Root Element Name
138    setRootElemName(0);
139
140        // Reset IdentityConstraints
141        if (fICHandler)
142                fICHandler->reset();
143
144        // Reset some status flags
145        fInException = false;
146        fStandalone = false;
147        fErrorCount = 0;
148        fHasNoDTD = true;
149
150        // Reset PSVI context
151        // note that we always need this around for DOMTypeInfo
152        if (!fPSVIElement)
153                fPSVIElement = new (fMemoryManager) PSVIElement(fMemoryManager);
154
155        if (!fErrorStack)
156        {
157                fErrorStack = new (fMemoryManager) ValueStackOf<bool>(8, fMemoryManager);
158        }
159        else
160        {
161                fErrorStack->removeAllElements();
162        }
163
164        resetPSVIElemContext();
165
166        // Reset the validators
167        fDTDValidator->reset();
168        fDTDValidator->setErrorReporter(fErrorReporter);
169        fSchemaValidator->reset();
170        fSchemaValidator->setErrorReporter(fErrorReporter);
171        fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
172        fSchemaValidator->setGrammarResolver(fGrammarResolver);
173        if (fValidatorFromUser)
174                fValidator->reset();
175
176        //  Handle the creation of the XML reader object for this input source.
177        //  This will provide us with transcoding and basic lexing services.
178        XMLReader* newReader = fReaderMgr.createReader
179        (
180                src
181                , true
182                , XMLReader::RefFrom_NonLiteral
183                , XMLReader::Type_General
184                , XMLReader::Source_External
185                , fCalculateSrcOfs
186                , fLowWaterMark
187        );
188
189        if (!newReader)
190        {
191                if (src.getIssueFatalErrorIfNotFound())
192                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource, src.getSystemId(), fMemoryManager);
193                else
194                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Scan_CouldNotOpenSource_Warning, src.getSystemId(), fMemoryManager);
195        }
196
197        // Push this read onto the reader manager
198        fReaderMgr.pushReader(newReader, 0);
199
200        // and reset security-related things if necessary:
201        if(fSecurityManager != 0)
202        {
203                fEntityExpansionLimit = fSecurityManager->getEntityExpansionLimit();
204                fEntityExpansionCount = 0;
205        }
206        fDTDElemNonDeclPool->removeAll();
207}
208
209void IGXMLScanner::parseSchemaLocation
210(
211    const XMLCh* const      schemaLocationStr
212    , const XMLSize_t       schemaLocationStrLen
213    , bool                  ignoreLoadSchema
214)
215{
216        XMLCh * locStr = XMLString::replicate(schemaLocationStr, schemaLocationStrLen, fMemoryManager);
217        ArrayJanitor<XMLCh> janLoc(locStr, fMemoryManager);
218        XMLParallelTokenizer locationPairs(locStr, schemaLocationStrLen);
219        locationPairs.scanWhitespace();
220        const XMLSize_t size = locationPairs.size();
221
222        if ((size & 1) == 0)
223        {
224                // We need a buffer to normalize the attribute value into
225                for(XMLSize_t i = 0; i < size; i += 2)
226                {
227                        resolveSchemaGrammar
228                        (
229                                locationPairs[i + 1]
230                                , locationPairs[i]
231                                , ignoreLoadSchema
232                        );
233                }
234        }
235        else
236        {
237                emitError(XMLErrs::BadSchemaLocation);
238        }
239}
240
241void IGXMLScanner::resolveSchemaGrammar
242(
243    const XMLCh* const          loc
244    , const XMLCh* const        uri
245    , bool                      ignoreLoadSchema
246)
247{
248        Grammar* grammar = 0;
249
250        DEBUG_GRAMMAR_MESSAGE("IGXMLScanner::resolveSchemaGrammar(" << loc << ',' << uri << ',' << ignoreLoadSchema << ')');
251
252        XMLSchemaDescriptionImpl theSchemaDescription(uri, fMemoryManager);
253        theSchemaDescription.setLocationHints(loc);
254        grammar = fGrammarResolver->getGrammar(&theSchemaDescription);
255
256        // If multi-import is enabled, make sure the existing grammar came
257        // from the import directive. Otherwise we may end up reloading
258        // the same schema that came from the external grammar pool. Ideally,
259        // we would move fSchemaInfoList to XMLGrammarPool so that it survives
260        // the destruction of the scanner in which case we could rely on the
261        // same logic we use to weed out duplicate schemas below.
262        //
263        if (!grammar ||
264                 grammar->getGrammarType() == Grammar::DTDGrammarType ||
265                 (getHandleMultipleImports() &&
266                 ((XMLSchemaDescription*)grammar->getGrammarDescription())->getContextType() == XMLSchemaDescription::CONTEXT_IMPORT))
267        {
268                if (fLoadSchema || ignoreLoadSchema)
269                {
270                        XSDDOMParser parser(0, fMemoryManager, 0);
271                        parser.getScanner()->setUriResolver(getUriResolver());
272                        parser.setValidationScheme(XercesDOMParser::Val_Never);
273                        parser.setDoNamespaces(true);
274                        parser.setUserEntityHandler(fEntityHandler);
275                        parser.setUserErrorReporter(fErrorReporter);
276
277                        const XMLCh* normalizedURI = loc;
278
279                        // Create a buffer for expanding the system id
280                        XMLBufBid bbSys(&fBufMgr);
281                        XMLBuffer& expSysId = bbSys.getBuffer();
282
283                        //  Allow the entity handler to expand the system id if they choose
284                        //  to do so.
285                        InputSource* srcToFill = 0;
286                        if (fEntityHandler)
287                        {
288                                if (!fEntityHandler->expandSystemId(normalizedURI, expSysId))
289                                {
290                                        expSysId.set(normalizedURI);
291                                }
292
293                                ReaderMgr::LastExtEntityInfo lastInfo;
294                                fReaderMgr.getLastExtEntityInfo(lastInfo);
295                                XMLResourceIdentifier resourceIdentifier
296                                (
297                                        XMLResourceIdentifier::SchemaGrammar
298                                        , expSysId.getRawBuffer()
299                                        , uri
300                                        , XMLUni::fgZeroLenString
301                                        , lastInfo.systemId
302                                        , &fReaderMgr
303                                );
304                                srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier);
305                        }
306                        else
307                        {
308                                expSysId.set(normalizedURI);
309                        }
310
311                        //  If they didn't create a source via the entity handler, then we
312                        //  have to create one on our own.
313                        if (!srcToFill)
314                        {
315                                if (fDisableDefaultEntityResolution)
316                                        return;
317
318                                ReaderMgr::LastExtEntityInfo lastInfo;
319                                fReaderMgr.getLastExtEntityInfo(lastInfo);
320
321                                XMLURL urlTmp(fMemoryManager);
322                                if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) || urlTmp.isRelative())
323                                {
324                                        if (!fStandardUriConformant)
325                                        {
326                                                XMLBufBid  ddSys(&fBufMgr);
327                                                XMLBuffer& resolvedSysId = ddSys.getBuffer();
328                                                XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId);
329
330                                                srcToFill = new (fMemoryManager) LocalFileInputSource
331                                                (
332                                                        lastInfo.systemId
333                                                        , resolvedSysId.getRawBuffer()
334                                                        , fMemoryManager
335                                                );
336                                        }
337                                        else
338                                        {
339                                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
340                                        }
341                                }
342                                else
343                                {
344                                        if (fStandardUriConformant && urlTmp.hasInvalidChar())
345                                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
346                                        srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
347                                }
348                        }
349
350                        // Put a janitor on the input source
351                        Janitor<InputSource> janSrc(srcToFill);
352
353                        // Check if this exact schema has already been seen.
354                        //
355                        const XMLCh* sysId = srcToFill->getSystemId();
356                        unsigned int uriId = fUriResolver->resolveUriId(uri);
357                        SchemaInfo* importSchemaInfo = 0;
358
359                        if (fUseCachedGrammar)
360                                importSchemaInfo = fCachedSchemaInfoList->get(sysId, uriId);
361
362                        if (!importSchemaInfo && !fToCacheGrammar)
363                                importSchemaInfo = fSchemaInfoList->get(sysId, uriId);
364
365                        if (importSchemaInfo)
366                        {
367                                // We haven't added any new grammars so it is safe to just
368                                // return.
369                                return;
370                        }
371
372                        // Should just issue warning if the schema is not found
373                        bool flag = srcToFill->getIssueFatalErrorIfNotFound();
374                        srcToFill->setIssueFatalErrorIfNotFound(false);
375
376                        parser.parse(*srcToFill);
377
378                        // Reset the InputSource
379                        srcToFill->setIssueFatalErrorIfNotFound(flag);
380
381                        if (parser.getSawFatal() && fExitOnFirstFatal)
382                                emitError(XMLErrs::SchemaScanFatalError);
383
384                        DOMDocument* document = parser.getDocument(); //Our Grammar
385
386                        if (document)
387                        {
388                                DOMElement * root = document->getDocumentElement(); // This is what we pass to TraverserSchema
389
390                                if (root)
391                                {
392                                        const XMLCh* newUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
393                                        bool newGrammar = false;
394
395                                        if (!XMLString::equals(newUri, uri))
396                                        {
397                                                if (fValidate || fValScheme == Val_Auto)
398                                                {
399                                                        fValidator->emitError(XMLValid::WrongTargetNamespace, loc, uri);
400                                                }
401
402                                                grammar = fGrammarResolver->getGrammar(newUri);
403                                                newGrammar = true;
404                                        }
405
406                                        if (!grammar ||
407                                                grammar->getGrammarType() == Grammar::DTDGrammarType ||
408                                                (getHandleMultipleImports() &&
409                                                 ((XMLSchemaDescription*)grammar->getGrammarDescription())->
410                                                 getContextType () == XMLSchemaDescription::CONTEXT_IMPORT))
411                                        {
412
413                                                // If we switched namespace URI, recheck the schema info.
414                                                //
415                                                if (newGrammar)
416                                                {
417                                                        if (fUseCachedGrammar)
418                                                        {
419                                importSchemaInfo = fCachedSchemaInfoList->get(sysId, fUriResolver->resolveUriId(newUri));
420                                                        }
421                                                        if (!importSchemaInfo && !fToCacheGrammar)
422                            {
423                                importSchemaInfo = fSchemaInfoList->get(sysId, fUriResolver->resolveUriId(newUri));
424                            }
425                                                        if (importSchemaInfo)
426                                                                return;
427                                                }
428
429                                                //  Since we have seen a grammar, set our validation flag
430                                                //  at this point if the validation scheme is auto
431                                                if (fValScheme == Val_Auto && !fValidate)
432                                                {
433                                                        fValidate = true;
434                                                        #ifdef __GNUC__
435                                                        #warning "This should probably call fElemStack.setValidationFlag(true) but we will not be at the correct element in the stack"
436                                                        #endif
437                                                }
438
439
440                                                // we have seen a schema, so set up the fValidator as fSchemaValidator
441                                                if (!fValidator->handlesSchema())
442                                                {
443                                                        if (fValidatorFromUser)
444                                                        {
445                                                                // the fValidator is from user
446                                                                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
447                                                        }
448                                                        else
449                                                        {
450                                                                fValidator = fSchemaValidator;
451                                                        }
452                                                }
453
454                                                const bool grammarFound =
455                                                         grammar && grammar->getGrammarType() == Grammar::SchemaGrammarType;
456
457                                                SchemaGrammar * schemaGrammar;
458
459                                                if (grammarFound)
460                                                {
461                                                        schemaGrammar = (SchemaGrammar*)grammar;
462                                                }
463                                                else
464                                                {
465                                                        assert (fGrammarPoolMemoryManager != NULL);
466                                                        schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager);
467                                                }
468
469                                                XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription();
470
471                                                gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE);
472                                                gramDesc->setLocationHints(sysId);
473
474                        DEBUG_GRAMMAR_MESSAGE("######################################################################");
475                        DEBUG_GRAMMAR_MESSAGE("TRAVERSE SCHEMA");
476                        DEBUG_GRAMMAR_MESSAGE("######################################################################");
477
478                                                TraverseSchema traverseSchema
479                                                (
480                                                        root
481                                                        , NULL
482                                                        , schemaGrammar
483                                                        , fGrammarResolver
484                                                        , fUseCachedGrammar ? fCachedSchemaInfoList : fSchemaInfoList
485                                                        , fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList
486                                                        , this
487                                                        , sysId
488                                                        , fEntityHandler
489                                                        , fErrorReporter
490                                                        , fMemoryManager
491                                                        , grammarFound
492                                                );
493
494                                                // Reset the now invalid schema roots in the collected
495                                                // schema info entries.
496                                                RefHash2KeysTableOfEnumerator<SchemaInfo> i
497                                                (
498                                                        fToCacheGrammar ? fCachedSchemaInfoList : fSchemaInfoList
499                                                );
500
501                                                while (i.hasMoreElements())
502                                                {
503                                                        i.nextElement().resetRoot();
504                                                }
505
506                                                if (fGrammarType == Grammar::DTDGrammarType)
507                                                {
508                                                        fGrammar = schemaGrammar;
509                                                        fGrammarType = Grammar::SchemaGrammarType;
510                                                        fValidator->setGrammar(fGrammar);
511                                                }
512
513                                                if (fValidate)
514                                                {
515                                                        // validate the Schema scan so far
516                                                        fValidator->preContentValidation(false);
517                                                }
518                                        }
519                                }
520                        }
521                }
522        }
523        else
524        {
525                //  Since we have seen a grammar, set our validation flag
526                //  at this point if the validation scheme is auto
527                if (fValScheme == Val_Auto && !fValidate)
528                {
529                        fValidate = true;
530                        #ifdef __GNUC__
531                        #warning "This should probably call fElemStack.setValidationFlag(true) but we will not be at the correct element in the stack"
532                        #endif
533                }
534
535                // we have seen a schema, so set up the fValidator as fSchemaValidator
536                if (!fValidator->handlesSchema())
537                {
538                        if (fValidatorFromUser)
539                        {
540                                // the fValidator is from user
541                                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
542                        }
543                        else
544                        {
545                                fValidator = fSchemaValidator;                         
546                        }
547                }
548
549                if (fGrammarType == Grammar::DTDGrammarType)
550                {
551                        fGrammar = grammar;
552                        fGrammarType = Grammar::SchemaGrammarType;
553                        fValidator->setGrammar(fGrammar);
554                }
555        }
556
557        // fModel may need updating:
558        if (getPSVIHandler())
559        {
560                fModel = fGrammarResolver->getXSModel();
561        }
562}
563
564InputSource* IGXMLScanner::resolveSystemId(const XMLCh* const sysId
565                                                                                  ,const XMLCh* const pubId)
566{
567        DEBUG_GRAMMAR_MESSAGE("IGXMLScanner::resolveSystemId(" << sysId << ',' << pubId << ')');
568
569        //Normalize sysId
570        XMLBufBid nnSys(&fBufMgr);
571        XMLBuffer& normalizedSysId = nnSys.getBuffer();
572        XMLString::removeChar(sysId, 0xFFFF, normalizedSysId);
573        const XMLCh* normalizedURI = normalizedSysId.getRawBuffer();
574
575        // Create a buffer for expanding the system id
576        XMLBufBid bbSys(&fBufMgr);
577        XMLBuffer& expSysId = bbSys.getBuffer();
578
579        //  Allow the entity handler to expand the system id if they choose
580        //  to do so.
581        InputSource* srcToFill = 0;
582        if (fEntityHandler)
583        {
584                if (!fEntityHandler->expandSystemId(normalizedURI, expSysId))
585                        expSysId.set(normalizedURI);
586
587                ReaderMgr::LastExtEntityInfo lastInfo;
588                fReaderMgr.getLastExtEntityInfo(lastInfo);
589                XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity,
590                                                          expSysId.getRawBuffer(), 0, pubId, lastInfo.systemId,
591                                                          &fReaderMgr);
592                srcToFill = fEntityHandler->resolveEntity(&resourceIdentifier);
593        }
594        else
595        {
596                expSysId.set(normalizedURI);
597        }
598
599        //  If they didn't create a source via the entity handler, then we
600        //  have to create one on our own.
601        if (!srcToFill)
602        {
603                if (fDisableDefaultEntityResolution)
604                        return srcToFill;
605
606                ReaderMgr::LastExtEntityInfo lastInfo;
607                fReaderMgr.getLastExtEntityInfo(lastInfo);
608
609                XMLURL urlTmp(fMemoryManager);
610                if ((!urlTmp.setURL(lastInfo.systemId, expSysId.getRawBuffer(), urlTmp)) ||
611                        (urlTmp.isRelative()))
612                {
613                        if (!fStandardUriConformant)
614                        {
615                                XMLBufBid  ddSys(&fBufMgr);
616                                XMLBuffer& resolvedSysId = ddSys.getBuffer();
617                                XMLUri::normalizeURI(expSysId.getRawBuffer(), resolvedSysId);
618
619                                srcToFill = new (fMemoryManager) LocalFileInputSource
620                                (
621                                        lastInfo.systemId
622                                        , resolvedSysId.getRawBuffer()
623                                        , fMemoryManager
624                                );
625                        }
626                        else
627                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
628                }
629                else
630                {
631                        if (fStandardUriConformant && urlTmp.hasInvalidChar())
632                                ThrowXMLwithMemMgr(MalformedURLException, XMLExcepts::URL_MalformedURL, fMemoryManager);
633                        srcToFill = new (fMemoryManager) URLInputSource(urlTmp, fMemoryManager);
634                }
635        }
636
637        return srcToFill;
638}
639
640
641// ---------------------------------------------------------------------------
642//  IGXMLScanner: Private grammar preparsing methods
643// ---------------------------------------------------------------------------
644Grammar* IGXMLScanner::loadXMLSchemaGrammar(const InputSource& src,
645                                                                                        const bool toCache)
646{
647        // Reset the validators
648        fSchemaValidator->reset();
649        fSchemaValidator->setErrorReporter(fErrorReporter);
650        fSchemaValidator->setExitOnFirstFatal(fExitOnFirstFatal);
651        fSchemaValidator->setGrammarResolver(fGrammarResolver);
652
653        if (fValidatorFromUser)
654                fValidator->reset();
655
656        if (!fValidator->handlesSchema())
657        {
658                if (fValidatorFromUser && fValidate)
659                        ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Gen_NoSchemaValidator, fMemoryManager);
660                else
661                {
662                        fValidator = fSchemaValidator;
663                }
664        }
665
666        XSDDOMParser parser(0, fMemoryManager, 0);
667
668        parser.setValidationScheme(XercesDOMParser::Val_Never);
669        parser.setDoNamespaces(true);
670        parser.setUserEntityHandler(fEntityHandler);
671        parser.setUserErrorReporter(fErrorReporter);
672
673        // Should just issue warning if the schema is not found
674        bool flag = src.getIssueFatalErrorIfNotFound();
675        ((InputSource&) src).setIssueFatalErrorIfNotFound(false);
676
677        parser.parse(src);
678
679        // Reset the InputSource
680        ((InputSource&) src).setIssueFatalErrorIfNotFound(flag);
681
682        if (parser.getSawFatal() && fExitOnFirstFatal)
683                emitError(XMLErrs::SchemaScanFatalError);
684
685        DOMDocument* document = parser.getDocument(); //Our Grammar
686
687        if (document != 0)
688        {
689                DOMElement* root = document->getDocumentElement(); // This is what we pass to TraverserSchema
690                if (root != 0)
691                {
692                        const XMLCh* nsUri = root->getAttribute(SchemaSymbols::fgATT_TARGETNAMESPACE);
693                        Grammar* grammar = fGrammarResolver->getGrammar(nsUri);
694
695                        // Check if this exact schema has already been seen.
696                        //
697                        const XMLCh* sysId = src.getSystemId();
698                        SchemaInfo* importSchemaInfo = 0;
699
700                        if (grammar)
701                        {
702                                if (nsUri && *nsUri)
703                                        importSchemaInfo = fCachedSchemaInfoList->get(sysId, fUriResolver->resolveUriId(nsUri));
704                                else
705                    importSchemaInfo = fCachedSchemaInfoList->get(sysId, fUriResolver->getUriIdForPrefix(XMLNamespaceResolver::fEmptyUriId, fContextId));
706                        }
707
708                        if (!importSchemaInfo)
709                        {
710                                bool grammarFound = grammar &&
711                                                                        grammar->getGrammarType() == Grammar::SchemaGrammarType &&
712                                                                        getHandleMultipleImports();
713
714                                SchemaGrammar* schemaGrammar;
715
716                                if (grammarFound)
717                                        schemaGrammar = (SchemaGrammar*) grammar;
718                                else
719                                        schemaGrammar = new (fGrammarPoolMemoryManager) SchemaGrammar(fGrammarPoolMemoryManager);
720
721                                XMLSchemaDescription* gramDesc = (XMLSchemaDescription*) schemaGrammar->getGrammarDescription();
722                                gramDesc->setContextType(XMLSchemaDescription::CONTEXT_PREPARSE);
723                                gramDesc->setLocationHints(sysId);
724
725                                TraverseSchema traverseSchema
726                                (
727                                        root
728                                        , NULL
729                                        , schemaGrammar
730                                        , fGrammarResolver
731                                        , fCachedSchemaInfoList
732                                        , toCache ? fCachedSchemaInfoList : fSchemaInfoList
733                                        , this
734                                        , sysId
735                                        , fEntityHandler
736                                        , fErrorReporter
737                                        , fMemoryManager
738                                        , grammarFound
739                                );
740
741                                grammar = schemaGrammar;
742
743                                // Reset the now invalid schema roots in the collected
744                                // schema info entries.
745                                //
746                                RefHash2KeysTableOfEnumerator<SchemaInfo> i
747                                (
748                                                toCache ? fCachedSchemaInfoList : fSchemaInfoList
749                                );
750
751                                while (i.hasMoreElements ())
752                                {
753                                        i.nextElement().resetRoot ();
754                                }
755                        }
756
757                        if (fValidate)
758                        {
759                                //  validate the Schema scan so far
760                                fValidator->setGrammar(grammar);
761                                fValidator->preContentValidation(false);
762                        }
763
764                        if (toCache)
765                        {
766                                fGrammarResolver->cacheGrammars();
767                        }
768
769                        if (getPSVIHandler())
770                        {
771                                fModel = fGrammarResolver->getXSModel();
772                        }
773                        return grammar;
774                }
775        }
776
777        return 0;
778}
779
780
781
782// ---------------------------------------------------------------------------
783//  IGXMLScanner: Private parsing methods
784// ---------------------------------------------------------------------------
785
786// check if there is an AnyAttribute, and if so, see if we should lax or skip
787// if skip - no validation
788// if lax - validate only if the attribute if found
789bool IGXMLScanner::anyAttributeValidation(SchemaAttDef* attWildCard, unsigned int uriId, bool & skipThisOne, bool & laxThisOne)
790{
791        XMLAttDef::AttTypes wildCardType = attWildCard->getType();
792        bool anyEncountered = false;
793        skipThisOne = false;
794        laxThisOne = false;
795        if (wildCardType == XMLAttDef::Any_Any)
796        {
797                anyEncountered = true;
798        }
799        else if (wildCardType == XMLAttDef::Any_Other)
800        {
801                anyEncountered = (attWildCard->getAttName()->getURI() != uriId) && (uriId != XMLNamespaceResolver::fEmptyUriId);
802        }
803        else if (wildCardType == XMLAttDef::Any_List)
804        {
805                ValueVectorOf<unsigned int>* nameURIList = attWildCard->getNamespaceList();
806                if (nameURIList)
807                {
808                        for (XMLSize_t i=0; i < nameURIList->size(); i++)
809                        {
810                                if (nameURIList->elementAt(i) == uriId)
811                                {
812                                        anyEncountered = true;
813                                        break;
814                                }
815                        }
816                }
817        }
818
819        if (anyEncountered)
820        {
821                XMLAttDef::DefAttTypes   defType   = attWildCard->getDefaultType();
822                if (defType == XMLAttDef::ProcessContents_Skip)
823                {
824                        // attribute should just be bypassed,
825                        skipThisOne = true;
826                }
827                else if (defType == XMLAttDef::ProcessContents_Lax)
828                {
829                        laxThisOne = true;
830                }
831        }
832
833        return anyEncountered;
834}
835
836IGXMLScanner::EntityExpRes
837IGXMLScanner::scanEntityRef( const   bool   /* inAttVal */
838                                                        ,       XMLCh&  firstCh
839                                                        ,       XMLCh&  secondCh
840                                                        ,       bool&   escaped)
841{
842        // Assume no escape
843        secondCh = 0;
844        escaped = false;
845
846        // We have to insure that its all in one entity
847        const XMLSize_t curReader = fReaderMgr.getCurrentReaderNum();
848
849        //  If the next char is a pound, then its a character reference and we
850        //  need to expand it always.
851        if (fReaderMgr.skippedChar(chPound))
852        {
853                //  Its a character reference, so scan it and get back the numeric
854                //  value it represents.
855                if (!scanCharRef(firstCh, secondCh))
856                        return EntityExp_Failed;
857
858                escaped = true;
859
860                if (curReader != fReaderMgr.getCurrentReaderNum())
861                        emitError(XMLErrs::PartialMarkupInEntity);
862
863                return EntityExp_Returned;
864        }
865
866        // Expand it since its a normal entity ref
867        XMLBufBid bbName(&fBufMgr);
868        int  colonPosition;
869        bool validName = fDoNamespaces ? fReaderMgr.getQName(bbName.getBuffer(), &colonPosition) :
870                                                                         fReaderMgr.getName(bbName.getBuffer());
871        if (!validName)
872        {
873                if (bbName.isEmpty())
874                        emitError(XMLErrs::ExpectedEntityRefName);
875                else
876                        emitError(XMLErrs::InvalidEntityRefName, bbName.getRawBuffer());
877                return EntityExp_Failed;
878        }
879
880        //  Next char must be a semi-colon. But if its not, just emit
881        //  an error and try to continue.
882        if (!fReaderMgr.skippedChar(chSemiColon))
883                emitError(XMLErrs::UnterminatedEntityRef, bbName.getRawBuffer());
884
885        // Make sure we ended up on the same entity reader as the & char
886        if (curReader != fReaderMgr.getCurrentReaderNum())
887                emitError(XMLErrs::PartialMarkupInEntity);
888
889        // Look up the name in the general entity pool
890        XMLEntityDecl* decl = fDTDGrammar->getEntityDecl(bbName.getRawBuffer());
891
892        // If it does not exist, then obviously an error
893        if (!decl)
894        {
895                // XML 1.0 Section 4.1
896                // Well-formedness Constraint for entity not found:
897                //   In a document without any DTD, a document with only an internal DTD subset which contains no parameter entity references,
898                //      or a document with "standalone='yes'", for an entity reference that does not occur within the external subset
899                //      or a parameter entity
900                //
901                // Else it's Validity Constraint
902                if (fStandalone || fHasNoDTD)
903                        emitError(XMLErrs::EntityNotFound, bbName.getRawBuffer());
904                else {
905                        if (fValidate)
906                                fValidator->emitError(XMLValid::VC_EntityNotFound, bbName.getRawBuffer());
907                }
908
909                return EntityExp_Failed;
910        }
911
912        // XML 1.0 Section 4.1
913        //  If we are a standalone document, then it has to have been declared
914        //  in the internal subset.
915        if (fStandalone && !decl->getDeclaredInIntSubset())
916                emitError(XMLErrs::IllegalRefInStandalone, bbName.getRawBuffer());
917
918        if (decl->isExternal())
919        {
920                // If its unparsed, then its not valid here
921                if (decl->isUnparsed())
922                {
923                        emitError(XMLErrs::NoUnparsedEntityRefs, bbName.getRawBuffer());
924                        return EntityExp_Failed;
925                }
926
927//              // If we are in an attribute value, then not valid but keep going
928//              if (inAttVal)
929//                      emitError(XMLErrs::NoExtRefsInAttValue);
930
931                // And now create a reader to read this entity
932                InputSource* srcUsed;
933                XMLReader* reader = fReaderMgr.createReader
934                (
935                        decl->getBaseURI()
936                        , decl->getSystemId()
937                        , decl->getPublicId()
938                        , false
939                        , XMLReader::RefFrom_NonLiteral
940                        , XMLReader::Type_General
941                        , XMLReader::Source_External
942                        , srcUsed
943                        , fCalculateSrcOfs
944                        , fLowWaterMark
945                        , fDisableDefaultEntityResolution
946                );
947
948                // Put a janitor on the source so it gets cleaned up on exit
949                Janitor<InputSource> janSrc(srcUsed);
950
951                //  If the creation failed, and its not because the source was empty,
952                //  then emit an error and return.
953                if (!reader)
954                        ThrowXMLwithMemMgr1(RuntimeException, XMLExcepts::Gen_CouldNotOpenExtEntity, srcUsed ? srcUsed->getSystemId() : decl->getSystemId(), fMemoryManager);
955
956                //  Push the reader. If its a recursive expansion, then emit an error
957                //  and return an failure.
958                if (!fReaderMgr.pushReader(reader, decl))
959                {
960                        emitError(XMLErrs::RecursiveEntity, decl->getName());
961                        return EntityExp_Failed;
962                }
963
964                // here's where we need to check if there's a SecurityManager,
965                // how many entity references we've had
966                if (fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit)
967                {
968                        XMLCh expLimStr[32];
969                        XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
970                        emitError
971                        (
972                                XMLErrs::EntityExpansionLimitExceeded
973                                , expLimStr
974                        );
975                        // there seems nothing  better to be done than to reset the entity expansion counter
976                        fEntityExpansionCount = 0;
977                }
978
979                // If it starts with the XML string, then parse a text decl
980                if (checkXMLDecl(true))
981                        scanXMLDecl(Decl_Text);
982        }
983        else
984        {
985                //  If its one of the special char references, then we can return
986                //  it as a character, and its considered escaped.
987                if (decl->getIsSpecialChar())
988                {
989                        firstCh = decl->getValue()[0];
990                        escaped = true;
991                        return EntityExp_Returned;
992                }
993
994                //  Create a reader over a memory stream over the entity value
995                //  We force it to assume UTF-16 by passing in an encoding
996                //  string. This way it won't both trying to predecode the
997                //  first line, looking for an XML/TextDecl.
998                XMLReader* valueReader = fReaderMgr.createIntEntReader
999                (
1000                        decl->getName()
1001                        , XMLReader::RefFrom_NonLiteral
1002                        , XMLReader::Type_General
1003                        , decl->getValue()
1004                        , decl->getValueLen()
1005                        , false
1006                );
1007
1008                //  Try to push the entity reader onto the reader manager stack,
1009                //  where it will become the subsequent input. If it fails, that
1010                //  means the entity is recursive, so issue an error. The reader
1011                //  will have just been discarded, but we just keep going.
1012                if (!fReaderMgr.pushReader(valueReader, decl))
1013                {
1014                        emitError(XMLErrs::RecursiveEntity, decl->getName());
1015                }
1016
1017                // here's where we need to check if there's a SecurityManager,
1018                // how many entity references we've had
1019                if (fSecurityManager != 0 && ++fEntityExpansionCount > fEntityExpansionLimit)
1020                {
1021                        XMLCh expLimStr[32];
1022                        XMLString::sizeToText(fEntityExpansionLimit, expLimStr, 31, 10, fMemoryManager);
1023                        emitError
1024                        (
1025                                XMLErrs::EntityExpansionLimitExceeded
1026                                , expLimStr
1027                        );
1028                }
1029
1030                // If it starts with the XML string, then it's an error
1031                if (checkXMLDecl(true))
1032                {
1033                        emitError(XMLErrs::TextDeclNotLegalHere);
1034                        fReaderMgr.skipPastChar(chCloseAngle);
1035                }
1036        }
1037        return EntityExp_Pushed;
1038}
1039
1040// ----------------------------------------------------------------------------------------------------
1041// DEPRECATED FUNCTIONS KEPT FOR DLL COMPATIBILITY
1042// ----------------------------------------------------------------------------------------------------
1043
1044void IGXMLScanner::updateNSMap( const QName* const, const XMLCh* const )
1045{
1046        DEPRECATED_FEATURE_IN_ICXML;
1047}
1048
1049void IGXMLScanner::updateNSMap( const XMLCh* const, const XMLCh* const, const int)
1050{
1051        DEPRECATED_FEATURE_IN_ICXML;
1052}
1053
1054void IGXMLScanner::processSchemaLocation(XMLCh* const )
1055{
1056        DEPRECATED_FEATURE_IN_ICXML;
1057}
1058
1059void IGXMLScanner::scanCDSection()
1060{
1061        DEPRECATED_FEATURE_IN_ICXML;
1062}
1063
1064void IGXMLScanner::sendCharData(XMLBuffer& toSend)
1065{
1066        DEPRECATED_FEATURE_IN_ICXML;
1067}
1068
1069void IGXMLScanner::scanCharData(XMLBuffer& toUse)
1070{
1071        DEPRECATED_FEATURE_IN_ICXML;
1072}
1073
1074bool IGXMLScanner::basicAttrValueScan(const XMLCh* const , XMLBuffer& )
1075{
1076        DEPRECATED_FEATURE_IN_ICXML;
1077}
1078
1079XMLSize_t IGXMLScanner::rawAttrScan(const  XMLCh* const, RefVectorOf<KVStringPair>&, bool& )
1080{
1081        DEPRECATED_FEATURE_IN_ICXML;
1082}
1083
1084bool IGXMLScanner::scanAttValue( const XMLAttDef* const
1085                                                           , const XMLCh* const
1086                                                           ,       XMLBuffer& )
1087{
1088        DEPRECATED_FEATURE_IN_ICXML;
1089}
1090
1091XMLSize_t IGXMLScanner::buildAttList( const RefVectorOf<KVStringPair>&, const XMLSize_t, XMLElementDecl*, RefVectorOf<XMLAttr>& )
1092{
1093        DEPRECATED_FEATURE_IN_ICXML;
1094}
1095
1096void IGXMLScanner::updateNSMap(const   XMLCh* const, const XMLCh* const)
1097{
1098        DEPRECATED_FEATURE_IN_ICXML;
1099}
1100
1101bool IGXMLScanner::normalizeAttValue
1102(
1103        const   XMLAttDef* const
1104        , const XMLCh* const
1105        , const XMLCh* const
1106        ,       XMLBuffer&
1107)
1108{
1109        DEPRECATED_FEATURE_IN_ICXML;
1110}
1111
1112bool IGXMLScanner::normalizeAttRawValue
1113(
1114        const   XMLCh* const
1115        , const XMLCh* const
1116        ,       XMLBuffer&
1117)
1118{
1119        DEPRECATED_FEATURE_IN_ICXML;
1120}
1121
1122void IGXMLScanner::resizeRawAttrColonList()
1123{
1124        DEPRECATED_FEATURE_IN_ICXML;
1125}
1126
1127void IGXMLScanner::scanRawAttrListforNameSpaces(XMLSize_t)
1128{
1129        DEPRECATED_FEATURE_IN_ICXML;
1130}
1131
1132void IGXMLScanner::parseSchemaLocation(const XMLCh* const, bool)
1133{
1134        DEPRECATED_FEATURE_IN_ICXML;
1135}
1136
1137void IGXMLScanner::scanEndTag(bool &)
1138{
1139        DEPRECATED_FEATURE_IN_ICXML;
1140}
1141
1142bool IGXMLScanner::scanStartTag(bool&)
1143{
1144        DEPRECATED_FEATURE_IN_ICXML;
1145}
1146
1147bool IGXMLScanner::scanStartTagNS(bool&)
1148{
1149        DEPRECATED_FEATURE_IN_ICXML;
1150}
1151
1152bool IGXMLScanner::scanContent()
1153{
1154        DEPRECATED_FEATURE_IN_ICXML;
1155}
1156
1157bool IGXMLScanner::laxElementValidation(QName*, ContentLeafNameTypeVector*, const XMLContentModel* const, const XMLSize_t)
1158{
1159    DEPRECATED_FEATURE_IN_ICXML;
1160}
1161
1162XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.