source: icXML/icXML-devel/src/icxercesc/internal/XMLScanner.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: 61.0 KB
RevLine 
[2720]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: XMLScanner.cpp 882548 2009-11-20 13:44:14Z borisk $
20 */
21
22
23// ---------------------------------------------------------------------------
24//  Includes
25// ---------------------------------------------------------------------------
[2721]26#include <icxercesc/internal/XMLScanner.hpp>
27#include <icxercesc/internal/ValidationContextImpl.hpp>
[2720]28#include <xercesc/util/Janitor.hpp>
29#include <xercesc/util/Mutexes.hpp>
30#include <xercesc/util/RuntimeException.hpp>
31#include <xercesc/util/UnexpectedEOFException.hpp>
32#include <xercesc/util/XMLMsgLoader.hpp>
33#include <xercesc/util/XMLInitializer.hpp>
34#include <xercesc/framework/LocalFileInputSource.hpp>
35#include <xercesc/framework/URLInputSource.hpp>
[3104]36#include <icxercesc/framework/XMLDocumentHandler.hpp>
[2720]37#include <xercesc/framework/XMLEntityHandler.hpp>
38#include <xercesc/framework/XMLPScanToken.hpp>
[2721]39#include <icxercesc/framework/XMLValidator.hpp>
[2720]40#include <xercesc/validators/DTD/DocTypeHandler.hpp>
[2721]41#include <icxercesc/validators/common/GrammarResolver.hpp>
[2720]42#include <xercesc/util/OutOfMemoryException.hpp>
[3103]43#include <icxmlc/XMLNameChars.hpp>
[2720]44#include <xercesc/util/XMLResourceIdentifier.hpp>
45
46XERCES_CPP_NAMESPACE_BEGIN
47
48// ---------------------------------------------------------------------------
49//  Local static data
50// ---------------------------------------------------------------------------
51static XMLUInt32       gScannerId = 0;
52static XMLMutex*       sScannerMutex = 0;
53static XMLMsgLoader*   gMsgLoader = 0;
54
55void XMLInitializer::initializeXMLScanner()
56{
57        gMsgLoader = XMLPlatformUtils::loadMsgSet(XMLUni::fgXMLErrDomain);
58
59        if (!gMsgLoader)
60          XMLPlatformUtils::panic(PanicHandler::Panic_CantLoadMsgDomain);
61
62        sScannerMutex = new XMLMutex(XMLPlatformUtils::fgMemoryManager);
63}
64
65void XMLInitializer::terminateXMLScanner()
66{
67        delete gMsgLoader;
68        gMsgLoader = 0;
69
70        delete sScannerMutex;
71        sScannerMutex = 0;
72}
73
74//
75//
76typedef JanitorMemFunCall<XMLScanner>   CleanupType;
77typedef JanitorMemFunCall<ReaderMgr>    ReaderMgrResetType;
78
79
80// ---------------------------------------------------------------------------
81//  XMLScanner: Constructors and Destructor
82// ---------------------------------------------------------------------------
83XMLScanner::XMLScanner
84(       XMLValidator* const valToAdopt
85        , GrammarResolver* const grammarResolver
86        , MemoryManager* const manager
87)
88        : fLowWaterMark (100)
89        , fStandardUriConformant(false)
90        , fCalculateSrcOfs(false)
91        , fDoNamespaces(false)
92        , fExitOnFirstFatal(true)
93        , fValidationConstraintFatal(false)
94        , fInException(false)
95        , fStandalone(false)
96        , fHasNoDTD(true)
[3103]97    , fHasInternalOrExternalDTD(false)
[2720]98        , fValidate(false)
99        , fValidatorFromUser(false)
100        , fDoSchema(false)
101        , fSchemaFullChecking(false)
102        , fIdentityConstraintChecking(true)
103        , fToCacheGrammar(false)
104        , fUseCachedGrammar(false)
105        , fLoadExternalDTD(true)
106        , fLoadSchema(true)
107        , fNormalizeData(true)
108        , fGenerateSyntheticAnnotations(false)
109        , fValidateAnnotations(false)
110        , fIgnoreCachedDTD(false)
111        , fIgnoreAnnotations(false)
112        , fDisableDefaultEntityResolution(false)
113        , fSkipDTDValidation(false)
114        , fHandleMultipleImports(false)
115        , fErrorCount(0)
116        , fEntityExpansionLimit(0)
117        , fEntityExpansionCount(0)
118        , fScannerId(0)
[3103]119        , fSequenceId(0)       
[2720]120        , fDocHandler(0)
121        , fDocTypeHandler(0)
122        , fEntityHandler(0)
123        , fErrorReporter(0)
124        , fErrorHandler(0)
125        , fPSVIHandler(0)
126        , fValidationContext(0)
127        , fEntityDeclPoolRetrieved(false)
128        , fReaderMgr(manager)
129        , fValidator(valToAdopt)
130        , fValScheme(Val_Never)
131        , fGrammarResolver(grammarResolver)
132        , fGrammarPoolMemoryManager(grammarResolver->getGrammarPoolMemoryManager())
133        , fGrammar(0)
134        , fRootGrammar(0)
135        , fRootElemName(0)
136        , fExternalSchemaLocation(0)
137        , fExternalNoNamespaceSchemaLocation(0)
138        , fSecurityManager(0)
139        , fXMLVersion(XMLReader::XMLV1_0)
140        , fMemoryManager(manager)
141        , fBufMgr(manager)
142        , fElemStack(manager)
143        , fUriResolver(0)
144{
145        CleanupType cleanup(this, &XMLScanner::cleanUp);
146
147        try
148        {
149                commonInit();
150        }
151        catch(const OutOfMemoryException&)
152        {
153                // Don't cleanup when out of memory, since executing the
154                // code can cause problems.
155                cleanup.release();
156
157                throw;
158        }
159
160        cleanup.release();
161}
162
163XMLScanner::XMLScanner
164(
165        XMLDocumentHandler* const  docHandler
166        , DocTypeHandler* const    docTypeHandler
167        , XMLEntityHandler* const  entityHandler
168        , XMLErrorReporter* const  errHandler
169        , XMLValidator* const      valToAdopt
170        , GrammarResolver* const   grammarResolver
171        , MemoryManager* const     manager
172)
173        : fLowWaterMark (100)
174        , fStandardUriConformant(false)
175        , fCalculateSrcOfs(false)
176        , fDoNamespaces(false)
177        , fExitOnFirstFatal(true)
178        , fValidationConstraintFatal(false)
179        , fInException(false)
180        , fStandalone(false)
181        , fHasNoDTD(true)
[3103]182    , fHasInternalOrExternalDTD(false)
[2720]183        , fValidate(false)
184        , fValidatorFromUser(false)
185        , fDoSchema(false)
186        , fSchemaFullChecking(false)
187        , fIdentityConstraintChecking(true)
188        , fToCacheGrammar(false)
189        , fUseCachedGrammar(false)
190        , fLoadExternalDTD(true)
191        , fLoadSchema(true)
192        , fNormalizeData(true)
193        , fGenerateSyntheticAnnotations(false)
194        , fValidateAnnotations(false)
195        , fIgnoreCachedDTD(false)
196        , fIgnoreAnnotations(false)
197        , fDisableDefaultEntityResolution(false)
198        , fSkipDTDValidation(false)
199        , fHandleMultipleImports(false)
200        , fErrorCount(0)
201        , fEntityExpansionLimit(0)
202        , fEntityExpansionCount(0)
203        , fScannerId(0)
204        , fSequenceId(0)
205        , fDocHandler(docHandler)
206        , fDocTypeHandler(docTypeHandler)
207        , fEntityHandler(entityHandler)
208        , fErrorReporter(errHandler)
209        , fErrorHandler(0)
210        , fPSVIHandler(0)
211        , fValidationContext(0)
212        , fEntityDeclPoolRetrieved(false)
213        , fReaderMgr(manager)
214        , fValidator(valToAdopt)
215        , fValScheme(Val_Never)
216        , fGrammarResolver(grammarResolver)
217        , fGrammarPoolMemoryManager(grammarResolver->getGrammarPoolMemoryManager())
218        , fGrammar(0)
219        , fRootGrammar(0)
220        , fRootElemName(0)
221        , fExternalSchemaLocation(0)
222        , fExternalNoNamespaceSchemaLocation(0)
223        , fSecurityManager(0)
224        , fXMLVersion(XMLReader::XMLV1_0)
225        , fMemoryManager(manager)
226        , fBufMgr(manager)
227        , fElemStack(manager)
228{
229        CleanupType cleanup(this, &XMLScanner::cleanUp);
230
231        try
232        {
233                commonInit();
234        }
235        catch(const OutOfMemoryException&)
236        {
237                // Don't cleanup when out of memory, since executing the
238                // code can cause problems.
239                cleanup.release();
240
241                throw;
242        }
243
244        cleanup.release();
245}
246
247XMLScanner::~XMLScanner()
248{
249        cleanUp();
250}
251
252void XMLScanner::resetCachedGrammar ()
253{
254}
255
256void XMLScanner::setValidator(XMLValidator* const valToAdopt)
257{
258        if (fValidatorFromUser)
259                delete fValidator;
260        fValidator = valToAdopt;
261        fValidatorFromUser = true;
262        initValidator(fValidator);
263}
264
265// ---------------------------------------------------------------------------
266//  XMLScanner: Main entry point to scan a document
267// ---------------------------------------------------------------------------
268void XMLScanner::scanDocument(  const   XMLCh* const    systemId)
269{
270        //  First we try to parse it as a URL. If that fails, we assume its
271        //  a file and try it that way.
272        InputSource* srcToUse = 0;
273        try
274        {
275                //  Create a temporary URL. Since this is the primary document,
276                //  it has to be fully qualified. If not, then assume we are just
277                //  mistaking a file for a URL.
278                XMLURL tmpURL(fMemoryManager);
279
280                if (XMLURL::parse(systemId, tmpURL))
281                {
282                        if (tmpURL.isRelative())
283                        {
284                                if (!fStandardUriConformant)
285                                        srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
286                                else {
287                                        // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
288                                        // emit the error directly
289                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
290                                        fInException = true;
291                                        emitError
292                                        (
293                                                XMLErrs::XMLException_Fatal
294                                                , e.getCode()
295                                                , e.getMessage()
296                                        );
297                                        return;
298                                }
299                        }
300                        else
301                        {
302                                if (fStandardUriConformant && tmpURL.hasInvalidChar()) {
303                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager);
304                                        fInException = true;
305                                        emitError
306                                        (
307                                                XMLErrs::XMLException_Fatal
308                                                , e.getCode()
309                                                , e.getMessage()
310                                        );
311                                        return;
312                                }
313                                srcToUse = new (fMemoryManager) URLInputSource(tmpURL, fMemoryManager);
314                        }
315                }
[3157]316        else
317        {
[2720]318                        if (!fStandardUriConformant)
319                                srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
320                        else {
321                                // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
322                                // emit the error directly
323                                // lazy bypass ... since all MalformedURLException are fatal, no need to check the type
324                                MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager);
325                                fInException = true;
326                                emitError
327                                (
328                                        XMLErrs::XMLException_Fatal
329                                        , e.getCode()
330                                        , e.getMessage()
331                                );
332                                return;
333                        }
334                }
335        }
336        catch(const XMLException& excToCatch)
337        {
338                //  For any other XMLException,
339                //  emit the error and catch any user exception thrown from here.
340                fInException = true;
341                if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
342                        emitError
343                        (
344                                XMLErrs::XMLException_Warning
345                                , excToCatch.getCode()
346                                , excToCatch.getMessage()
347                        );
348                else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
349                        emitError
350                        (
351                                XMLErrs::XMLException_Fatal
352                                , excToCatch.getCode()
353                                , excToCatch.getMessage()
354                        );
355                else
356                        emitError
357                        (
358                                XMLErrs::XMLException_Error
359                                , excToCatch.getCode()
360                                , excToCatch.getMessage()
361                        );
362                return;
363        }
364
365        Janitor<InputSource> janSrc(srcToUse);
366        scanDocument(*srcToUse);
367
368}
369
370void XMLScanner::scanDocument(  const   char* const systemId)
371{
372        // We just delegate this to the XMLCh version after transcoding
373        XMLCh* tmpBuf = XMLString::transcode(systemId, fMemoryManager);
374        ArrayJanitor<XMLCh> janBuf(tmpBuf, fMemoryManager);
375        scanDocument(tmpBuf);
376
377}
378
379
380//  This method begins a progressive parse. It scans through the prolog and
381//  returns a token to be used on subsequent scanNext() calls. If the return
382//  value is true, then the token is legal and ready for further use. If it
383//  returns false, then the scan of the prolog failed and the token is not
384//  going to work on subsequent scanNext() calls.
385//  This method begins a progressive parse. It scans through the prolog and
386//  returns a token to be used on subsequent scanNext() calls. If the return
387//  value is true, then the token is legal and ready for further use. If it
388//  returns false, then the scan of the prolog failed and the token is not
389//  going to work on subsequent scanNext() calls.
390bool XMLScanner::scanFirst( const   XMLCh* const    systemId
391                                                        ,       XMLPScanToken&  toFill)
392{
393        //  First we try to parse it as a URL. If that fails, we assume its
394        //  a file and try it that way.
395        InputSource* srcToUse = 0;
396        try
397        {
398                //  Create a temporary URL. Since this is the primary document,
399                //  it has to be fully qualified. If not, then assume we are just
400                //  mistaking a file for a URL.
401                XMLURL tmpURL(fMemoryManager);
402                if (XMLURL::parse(systemId, tmpURL)) {
403                        if (tmpURL.isRelative()) {
404                                if (!fStandardUriConformant)
405                                        srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
406                                else {
407                                        // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
408                                        // emit the error directly
409                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
410                                        fInException = true;
411                                        emitError
412                                        (
413                                                XMLErrs::XMLException_Fatal
414                                                , e.getCode()
415                                                , e.getMessage()
416                                        );
417                                        return false;
418                                }
419                        }
420                        else
421                        {
422                                if (fStandardUriConformant && tmpURL.hasInvalidChar()) {
423                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager);
424                                        fInException = true;
425                                        emitError
426                                        (
427                                                XMLErrs::XMLException_Fatal
428                                                , e.getCode()
429                                                , e.getMessage()
430                                        );
431                                        return false;
432                                }
433                                srcToUse = new (fMemoryManager) URLInputSource(tmpURL, fMemoryManager);
434                        }
435                }
436                else {
437                        if (!fStandardUriConformant)
438                                srcToUse = new (fMemoryManager) LocalFileInputSource(systemId,  fMemoryManager);
439                        else {
440                                // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
441                                // emit the error directly
442                                // lazy bypass ... since all MalformedURLException are fatal, no need to check the type
443                                MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL);
444                                fInException = true;
445                                emitError
446                                (
447                                        XMLErrs::XMLException_Fatal
448                                        , e.getCode()
449                                        , e.getMessage()
450                                );
451                                return false;
452                        }
453                }
454        }
455        catch(const XMLException& excToCatch)
456        {
457                //  For any other XMLException,
458                //  emit the error and catch any user exception thrown from here.
459                fInException = true;
460                if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
461                        emitError
462                        (
463                                XMLErrs::XMLException_Warning
464                                , excToCatch.getCode()
465                                , excToCatch.getMessage()
466                        );
467                else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
468                        emitError
469                        (
470                                XMLErrs::XMLException_Fatal
471                                , excToCatch.getCode()
472                                , excToCatch.getMessage()
473                        );
474                else
475                        emitError
476                        (
477                                XMLErrs::XMLException_Error
478                                , excToCatch.getCode()
479                                , excToCatch.getMessage()
480                        );
481                return false;
482        }
483
484        Janitor<InputSource> janSrc(srcToUse);
485        return scanFirst(*srcToUse, toFill);
486}
487
488bool XMLScanner::scanFirst( const   char* const     systemId
489                                                        ,       XMLPScanToken&  toFill)
490{
491        // We just delegate this to the XMLCh version after transcoding
492        XMLCh* tmpBuf = XMLString::transcode(systemId, fMemoryManager);
493        ArrayJanitor<XMLCh> janBuf(tmpBuf, fMemoryManager);
494        return scanFirst(tmpBuf, toFill);
495}
496
497bool XMLScanner::scanFirst( const   InputSource&    src
498                                                   ,       XMLPScanToken&  toFill)
499{
500        //  Bump up the sequence id for this new scan cycle. This will invalidate
501        //  any previous tokens we've returned.
502        fSequenceId++;
503
504        ReaderMgrResetType  resetReaderMgr(&fReaderMgr, &ReaderMgr::reset);
505
506   // Reset the scanner and its plugged in stuff for a new run.  This
507        // resets all the data structures, creates the initial reader and
508        // pushes it on the stack, and sets up the base document path
509        scanReset(src);
510
511        // If we have a document handler, then call the start document
512        if (fDocHandler)
513                fDocHandler->startDocument();
514
515        try
516        {
517                //  Scan the prolog part, which is everything before the root element
518                //  including the DTD subsets. This is all that is done on the scan
519                //  first.
[3150]520        scanFirst();
[2720]521        }
522        //  NOTE:
523        //
524        //  In all of the error processing below, the emitError() call MUST come
525        //  before the flush of the reader mgr, or it will fail because it tries
526        //  to find out the position in the XML source of the error.
527        catch(const XMLErrs::Codes)
528        {
529                // This is a 'first failure' exception so return failure
530                return false;
531        }
532        catch(const XMLValid::Codes)
533        {
534                // This is a 'first fatal error' type exit, return failure
535                return false;
536        }
537        catch(const XMLException& excToCatch)
538        {
539                //  Emit the error and catch any user exception thrown from here. Make
540                //  sure in all cases we flush the reader manager.
541                fInException = true;
542                try
543                {
544                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
545                                emitError
546                                (
547                                        XMLErrs::XMLException_Warning
548                                        , excToCatch.getCode()
549                                        , excToCatch.getMessage()
550                                );
551                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
552                                emitError
553                                (
554                                        XMLErrs::XMLException_Fatal
555                                        , excToCatch.getCode()
556                                        , excToCatch.getMessage()
557                                );
558                        else
559                                emitError
560                                (
561                                        XMLErrs::XMLException_Error
562                                        , excToCatch.getCode()
563                                        , excToCatch.getMessage()
564                                );
565                }
566                catch(const OutOfMemoryException&)
567                {
568                        // This is a special case for out-of-memory
569                        // conditions, because resetting the ReaderMgr
570                        // can be problematic.
571                        resetReaderMgr.release();
572
573                        throw;
574                }
575
576                return false;
577        }
578        catch(const OutOfMemoryException&)
579        {
580                // This is a special case for out-of-memory
581                // conditions, because resetting the ReaderMgr
582                // can be problematic.
583                resetReaderMgr.release();
584
585                throw;
586        }
587
588        // Fill in the caller's token to make it legal and return success
589        toFill.set(fScannerId, fSequenceId);
590
591        // Release the object that will reset the ReaderMgr, since there's
592        // more to scan.
593        resetReaderMgr.release();
594
595        return true;
596}
597
598
599
600
601void XMLScanner::scanReset(XMLPScanToken& token)
602{
603        // Make sure this token is still legal
604        if (!isLegalToken(token))
605                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Scan_BadPScanToken, fMemoryManager);
606
607        // Reset the reader manager
608        fReaderMgr.reset();
609
610        // And invalidate any tokens by bumping our sequence number
611        fSequenceId++;
612
613        // Reset our error count
614        fErrorCount = 0;
615
616}
617
618void XMLScanner::setParseSettings(XMLScanner* const refScanner)
619{
620        setDocHandler(refScanner->getDocHandler());
621        setDocTypeHandler(refScanner->getDocTypeHandler());
622        setErrorHandler(refScanner->getErrorHandler());
623        setErrorReporter(refScanner->getErrorReporter());
624        setEntityHandler(refScanner->getEntityHandler());
625        setDoNamespaces(refScanner->getDoNamespaces());
626        setDoSchema(refScanner->getDoSchema());
627        setCalculateSrcOfs(refScanner->getCalculateSrcOfs());
628        setStandardUriConformant(refScanner->getStandardUriConformant());
629        setExitOnFirstFatal(refScanner->getExitOnFirstFatal());
630        setValidationConstraintFatal(refScanner->getValidationConstraintFatal());
631        setIdentityConstraintChecking(refScanner->getIdentityConstraintChecking());
632        setValidationSchemaFullChecking(refScanner->getValidationSchemaFullChecking());
633        cacheGrammarFromParse(refScanner->isCachingGrammarFromParse());
634        useCachedGrammarInParse(refScanner->isUsingCachedGrammarInParse());
635        setLoadExternalDTD(refScanner->getLoadExternalDTD());
636        setLoadSchema(refScanner->getLoadSchema());
637        setNormalizeData(refScanner->getNormalizeData());
638        setExternalSchemaLocation(refScanner->getExternalSchemaLocation());
639        setExternalNoNamespaceSchemaLocation(refScanner->getExternalNoNamespaceSchemaLocation());
640        setValidationScheme(refScanner->getValidationScheme());
641        setSecurityManager(refScanner->getSecurityManager());
642        setPSVIHandler(refScanner->getPSVIHandler());
643}
644
645// ---------------------------------------------------------------------------
646//  XMLScanner: Private helper methods.
647// ---------------------------------------------------------------------------
648
649//  This method handles the common initialization, to avoid having to do
650//  it redundantly in multiple constructors.
651void XMLScanner::commonInit()
652{
653        //  We have to do a little init that involves statics, so we have to
654        //  use the mutex to protect it.
655        {
656                XMLMutexLock lockInit(sScannerMutex);
657
658                // And assign ourselves the next available scanner id
659                fScannerId = ++gScannerId;
660        }
661
662        //  Create the id ref list. This is used to enforce XML 1.0 ID ref
663        //  semantics, i.e. all id refs must refer to elements that exist
664        fValidationContext = new (fMemoryManager) ValidationContextImpl(fMemoryManager);
665        fValidationContext->setScanner(this);
666
667        //  Create the GrammarResolver
668        //fGrammarResolver = new GrammarResolver();
669
670/*
671        // Register self as handler for XMLBufferFull events on the CDATA buffer
672        fCDataBuf.setFullHandler(this, fBufferSize);
673*/
674   if (fValidator)
675        {
676           fValidatorFromUser = true;
677           initValidator(fValidator);
678   }
679}
680
681void XMLScanner::cleanUp()
682{
[3157]683    delete fValidationContext; fValidationContext = 0;
684    fMemoryManager->deallocate(fExternalSchemaLocation); fExternalSchemaLocation = 0;
685    fMemoryManager->deallocate(fExternalNoNamespaceSchemaLocation); fExternalNoNamespaceSchemaLocation = 0;
686    fMemoryManager->deallocate(fRootElemName); fRootElemName = 0;
[2720]687}
688
689void XMLScanner::initValidator(XMLValidator* theValidator)
690{
691        //  Tell the validator about the stuff it needs to know in order to do its work.
692        theValidator->setScannerInfo(this, &fReaderMgr, &fBufMgr);
693        theValidator->setErrorReporter(fErrorReporter);
694}
695
696// ---------------------------------------------------------------------------
697//  XMLScanner: Error emitting methods
698// ---------------------------------------------------------------------------
699
700//  These methods are called whenever the scanner wants to emit an error.
701//  It handles getting the message loaded, doing token replacement, etc...
702//  and then calling the error handler, if its installed.
703bool XMLScanner::emitErrorWillThrowException(const XMLErrs::Codes toEmit)
704{
705        if (XMLErrs::isFatal(toEmit) && fExitOnFirstFatal && !fInException)
706                return true;
707        return false;
708}
709
710void XMLScanner::emitError(const XMLErrs::Codes toEmit)
711{
712        // Bump the error count if it is not a warning
713        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
714                incrementErrorCount();
715
716        if (fErrorReporter)
717        {
718                // Load the message into a local for display
719                const XMLSize_t msgSize = 1023;
720                XMLCh errText[msgSize + 1];
721
722                if (!gMsgLoader->loadMsg(toEmit, errText, msgSize))
723                {
724                                // <TBD> Probably should load a default msg here
725                }
726
727                //  Create a LastExtEntityInfo structure and get the reader manager
728                //  to fill it in for us. This will give us the information about
729                //  the last reader on the stack that was an external entity of some
730                //  sort (i.e. it will ignore internal entities.
731                ReaderMgr::LastExtEntityInfo lastInfo;
732                fReaderMgr.getLastExtEntityInfo(lastInfo);
733
734                fErrorReporter->error
735                (
736                        toEmit
737                        , XMLUni::fgXMLErrDomain
738                        , XMLErrs::errorType(toEmit)
739                        , errText
740                        , lastInfo.systemId
741                        , lastInfo.publicId
742                        , lastInfo.lineNumber
743                        , lastInfo.colNumber
744                );
745        }
746
747        // Bail out if its fatal an we are to give up on the first fatal error
748        if (emitErrorWillThrowException(toEmit))
749                throw toEmit;
750}
751
752void XMLScanner::emitError(const XMLErrs::Codes toEmit, const XMLFileLoc line, const XMLFileLoc col)
753{
754        // Bump the error count if it is not a warning
755        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
756                incrementErrorCount();
757
758        if (fErrorReporter)
759        {
760                // Load the message into a local for display
761                const XMLSize_t msgSize = 1023;
762                XMLCh errText[msgSize + 1];
763
764                if (!gMsgLoader->loadMsg(toEmit, errText, msgSize))
765                {
766                                // <TBD> Probably should load a default msg here
767                }
768
[3103]769        // We have at least one entity so get the data
770        const XMLEntityDecl* theEntity;
771        const XMLReader* theReader = fReaderMgr.getLastExtEntity(theEntity);
772
[2720]773                fErrorReporter->error
774                (
775                        toEmit
776                        , XMLUni::fgXMLErrDomain
777                        , XMLErrs::errorType(toEmit)
778                        , errText
[3103]779            , theReader->getSystemId()
780            , theReader->getPublicId()
[2720]781                        , line
782                        , col
783                );
784        }
785
786        // Bail out if its fatal an we are to give up on the first fatal error
787        if (emitErrorWillThrowException(toEmit))
788                throw toEmit;
789}
790
791
792void XMLScanner::emitError( const   XMLErrs::Codes    toEmit
793                                                        , const XMLCh* const        text1
794                                                        , const XMLCh* const        text2
795                                                        , const XMLCh* const        text3
796                                                        , const XMLCh* const        text4)
797{
798        // Bump the error count if it is not a warning
799        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
800                incrementErrorCount();
801
802        if (fErrorReporter)
803        {
804                //  Load the message into alocal and replace any tokens found in
805                //  the text.
806                const XMLSize_t maxChars = 2047;
807                XMLCh errText[maxChars + 1];
808
809                if (!gMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fMemoryManager))
810                {
811                        // <TBD> Should probably load a default message here
812                }
813
814                //  Create a LastExtEntityInfo structure and get the reader manager
815                //  to fill it in for us. This will give us the information about
816                //  the last reader on the stack that was an external entity of some
817                //  sort (i.e. it will ignore internal entities.
818                ReaderMgr::LastExtEntityInfo lastInfo;
819                fReaderMgr.getLastExtEntityInfo(lastInfo);
820
821                fErrorReporter->error
822                (
823                        toEmit
824                        , XMLUni::fgXMLErrDomain
825                        , XMLErrs::errorType(toEmit)
826                        , errText
827                        , lastInfo.systemId
828                        , lastInfo.publicId
829                        , lastInfo.lineNumber
830                        , lastInfo.colNumber
831                );
832        }
833
834        // Bail out if its fatal an we are to give up on the first fatal error
835        if (emitErrorWillThrowException(toEmit))
836                throw toEmit;
837}
838
839void XMLScanner::emitError( const   XMLErrs::Codes    toEmit
840                                                        , const char* const         text1
841                                                        , const char* const         text2
842                                                        , const char* const         text3
843                                                        , const char* const         text4)
844{
845        // Bump the error count if it is not a warning
846        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
847                incrementErrorCount();
848
849        if (fErrorReporter)
850        {
851                //  Load the message into alocal and replace any tokens found in
852                //  the text.
853                const XMLSize_t maxChars = 2047;
854                XMLCh errText[maxChars + 1];
855
856                if (!gMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fMemoryManager))
857                {
858                                // <TBD> Should probably load a default message here
859                }
860
861                //  Create a LastExtEntityInfo structure and get the reader manager
862                //  to fill it in for us. This will give us the information about
863                //  the last reader on the stack that was an external entity of some
864                //  sort (i.e. it will ignore internal entities.
865                ReaderMgr::LastExtEntityInfo lastInfo;
866                fReaderMgr.getLastExtEntityInfo(lastInfo);
867
868                fErrorReporter->error
869                (
870                        toEmit
871                        , XMLUni::fgXMLErrDomain
872                        , XMLErrs::errorType(toEmit)
873                        , errText
874                        , lastInfo.systemId
875                        , lastInfo.publicId
876                        , lastInfo.lineNumber
877                        , lastInfo.colNumber
878                );
879        }
880
881        // Bail out if its fatal an we are to give up on the first fatal error
882        if (emitErrorWillThrowException(toEmit))
883                throw toEmit;
884}
885
886void XMLScanner::emitError( const   XMLErrs::Codes      toEmit
887                                                        , const XMLExcepts::Codes   originalExceptCode
888                                                        , const XMLCh* const        text1
889                                                        , const XMLCh* const        text2
890                                                        , const XMLCh* const        text3
891                                                        , const XMLCh* const        text4)
892{
893        // Bump the error count if it is not a warning
894        if (XMLErrs::errorType(toEmit) != XMLErrorReporter::ErrType_Warning)
895                incrementErrorCount();
896
897        if (fErrorReporter)
898        {
899                //  Load the message into alocal and replace any tokens found in
900                //  the text.
901                const XMLSize_t maxChars = 2047;
902                XMLCh errText[maxChars + 1];
903
904                if (!gMsgLoader->loadMsg(toEmit, errText, maxChars, text1, text2, text3, text4, fMemoryManager))
905                {
906                                // <TBD> Should probably load a default message here
907                }
908
909                //  Create a LastExtEntityInfo structure and get the reader manager
910                //  to fill it in for us. This will give us the information about
911                //  the last reader on the stack that was an external entity of some
912                //  sort (i.e. it will ignore internal entities.
913                ReaderMgr::LastExtEntityInfo lastInfo;
914                fReaderMgr.getLastExtEntityInfo(lastInfo);
915
916                fErrorReporter->error
917                (
918                        originalExceptCode
919                        , XMLUni::fgExceptDomain    //fgXMLErrDomain
920                        , XMLErrs::errorType(toEmit)
921                        , errText
922                        , lastInfo.systemId
923                        , lastInfo.publicId
924                        , lastInfo.lineNumber
925                        , lastInfo.colNumber
926                );
927        }
928
929        // Bail out if its fatal an we are to give up on the first fatal error
930        if (emitErrorWillThrowException(toEmit))
931                throw toEmit;
932}
933
934// --------------------------------------------------------------------------------------------------------
935
936//  Scans the <?xml .... ?> line. This stuff is all sequential so we don't
937//  do any state machine loop here. We just bull straight through it. It ends
938//  past the closing bracket. If there is a document handler, then its called
939//  on the XMLDecl callback.
940//
941//  On entry, the <?xml has been scanned, and we pick it up from there.
942//
943//  NOTE: In order to provide good recovery from bad XML here, we try to be
944//  very flexible. No matter what order the stuff is in, we'll keep going
945//  though we'll issue errors.
946//
947//  The parameter tells us which type of decl we should expect, Text or XML.
948//    [23] XMLDecl ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
949//    [77] TextDecl::= '<?xml' VersionInfo? EncodingDecl S? '?>'
950void XMLScanner::scanXMLDecl(const DeclTypes type)
951{
952        // Get us some buffers to use
953        XMLBufBid bbVersion(&fBufMgr);
954        XMLBufBid bbEncoding(&fBufMgr);
955        XMLBufBid bbStand(&fBufMgr);
956        XMLBufBid bbDummy(&fBufMgr);
957        XMLBufBid bbName(&fBufMgr);
958
959        //  We use this little enum and array to keep up with what we found
960        //  and what order we found them in. This lets us get them free form
961        //  without too much overhead, but still know that they were in the
962        //  wrong order.
963        enum Strings
964        {
965                VersionString
966                , EncodingString
967                , StandaloneString
968                , UnknownString
969
970                , StringCount
971        };
972        int flags[StringCount] = { -1, -1, -1, -1 };
973
974        //  Also set up a list of buffers in the right order so that we know
975        //  where to put stuff.
976        XMLBuffer* buffers[StringCount] ;
977        buffers[0] = &bbVersion.getBuffer();
978        buffers[1] = &bbEncoding.getBuffer();
979        buffers[2] = &bbStand.getBuffer();
980        buffers[3] = &bbDummy.getBuffer();
981
982        int curCount = 0;
983        Strings curString;
984        XMLBuffer& nameBuf = bbName.getBuffer();
985        while (true)
986        {
987                // Skip any spaces
988                bool skippedSomething;
989                fReaderMgr.skipPastSpaces(skippedSomething, true);
990
991                // If we are looking at a question mark, then break out
992                if (fReaderMgr.lookingAtChar(chQuestion))
993                {
994                        break;
995                }
996
997                // If this is not the first string, then we require the spaces
998                if (!skippedSomething && curCount)
999                {
1000                        emitError(XMLErrs::ExpectedWhitespace);
1001                }
1002
1003                //  Get characters up to the next whitespace or equal's sign.
1004                if (!scanUpToWSOr(nameBuf, chEqual))
1005                {
1006                        emitError(XMLErrs::ExpectedDeclString);
1007                }
1008
1009                // See if it matches any of our expected strings
1010                if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgVersionString))
1011                {
1012                        curString = VersionString;
1013                }
1014                else if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgEncodingString))
1015                {
1016                        curString = EncodingString;
1017                }
1018                else if (XMLString::equals(nameBuf.getRawBuffer(), XMLUni::fgStandaloneString))
1019                {
1020                        curString = StandaloneString;
1021                }
1022                else
1023                {
1024                        curString = UnknownString;
1025                }
1026
1027                //  If its an unknown string, then give that error. Else check to
1028                //  see if this one has been done already and give that error.
1029                if (curString == UnknownString)
1030                        emitError(XMLErrs::ExpectedDeclString, nameBuf.getRawBuffer());
1031                else if (flags[curString] != -1)
1032                        emitError(XMLErrs::DeclStringRep, nameBuf.getRawBuffer());
1033                else if (flags[curString] == -1)
1034                        flags[curString] = ++curCount;
1035
1036                //  Scan for an equal's sign. If we don't find it, issue an error
1037                //  but keep trying to go on.
1038                if (!scanEq(true))
1039                        emitError(XMLErrs::ExpectedEqSign);
1040
1041                //  Get a quote string into the buffer for the string that we are
1042                //  currently working on.
1043                if (!getQuotedString(*buffers[curString]))
1044                {
1045                        emitError(XMLErrs::ExpectedQuotedString);
1046                        fReaderMgr.skipPastChar(chCloseAngle);
1047                        return;
1048                }
1049
1050                // And validate the value according which one it was
1051                const XMLCh* rawValue = buffers[curString]->getRawBuffer();
1052                if (curString == VersionString)
[3103]1053        {
1054
1055//            4.3.4 Version Information in Entities
1056
1057//            Each entity, including the document entity, can be separately declared as XML 1.0 or XML 1.1. The version declaration appearing in the document entity determines
1058//            the version of the document as a whole. An XML 1.1 document may invoke XML 1.0 external entities, so that otherwise duplicated versions of external entities, particularly
1059//            DTD external subsets, need not be maintained. However, in such a case the rules of XML 1.1 are applied to the entire document.
1060
1061
[2720]1062                        if (XMLString::equals(rawValue, XMLUni::fgVersion1_0))
1063                        {
[3103]1064                if (type == Decl_XML)
1065                {
1066                    fXMLVersion = XMLReader::XMLV1_0;
1067                    fReaderMgr.setXMLVersion(XMLReader::XMLV1_0);
1068                }
[2720]1069                        }
1070                        else if (XMLString::equals(rawValue, XMLUni::fgVersion1_1))
[3103]1071            {
1072                if (type == Decl_XML)
1073                {
1074                    fXMLVersion = XMLReader::XMLV1_1;
1075                    fReaderMgr.setXMLVersion(XMLReader::XMLV1_1);
1076                }
1077                else if (unlikely(fXMLVersion != XMLReader::XMLV1_1))
1078                {
1079                    emitError(XMLErrs::UnsupportedXMLVersion, rawValue);
1080                }
[2720]1081                        }
1082                        else
[3103]1083            {
[2720]1084                                emitError(XMLErrs::UnsupportedXMLVersion, rawValue);
[3103]1085            }
1086
1087            DEBUG_MESSAGE("fXMLVersion=" << fXMLVersion);
[2720]1088                }
1089                else if (curString == EncodingString)
1090                {
1091                        if (!XMLString::isValidEncName(rawValue))
1092                                emitError(XMLErrs::BadXMLEncoding, rawValue);
1093                }
1094                 else if (curString == StandaloneString)
1095                {
1096                        if (XMLString::equals(rawValue, XMLUni::fgYesString))
1097                                fStandalone = true;
1098                        else if (XMLString::equals(rawValue, XMLUni::fgNoString))
1099                                fStandalone = false;
1100                        else
1101                        {
1102                                emitError(XMLErrs::BadStandalone);
1103                                //if (!XMLString::compareIString(rawValue, XMLUni::fgYesString))
1104                                //else if (!XMLString::compareIString(rawValue, XMLUni::fgNoString))
1105                                if (buffers[curString]->getLen() == 3 &&
1106                                        (((rawValue[0] == chLatin_y) || (rawValue[0] == chLatin_Y)) &&
1107                                         ((rawValue[1] == chLatin_e) || (rawValue[1] == chLatin_E)) &&
1108                                         ((rawValue[2] == chLatin_s) || (rawValue[2] == chLatin_S))))
1109                                        fStandalone = true;
1110                                else if (buffers[curString]->getLen() == 2 &&
1111                                        (((rawValue[0] == chLatin_n) || (rawValue[0] == chLatin_N)) &&
1112                                         ((rawValue[1] == chLatin_o) || (rawValue[1] == chLatin_O))))
1113                                        fStandalone = false;
1114                        }
1115                }
1116        }
1117
1118        //  Make sure that the strings present are in order. We don't care about
1119        //  which ones are present at this point, just that any there are in the
1120        //  right order.
1121        int curTop = 0;
1122        for (int index = VersionString; index < StandaloneString; index++)
1123        {
1124                if (flags[index] != -1)
1125                {
1126                        if (flags[index] !=  curTop + 1)
1127                        {
1128                                emitError(XMLErrs::DeclStringsInWrongOrder);
1129                                break;
1130                        }
1131                        curTop = flags[index];
1132                }
1133        }
1134
1135        //  If its an XML decl, the version must be present.
1136        //  If its a Text decl, then encoding must be present AND standalone must not be present.
1137        if ((type == Decl_XML) && (flags[VersionString] == -1))
[3103]1138    {
[2720]1139                emitError(XMLErrs::XMLVersionRequired);
[3103]1140    }
1141    else if (type == Decl_Text)
1142    {
[2720]1143                if (flags[StandaloneString] != -1)
1144                        emitError(XMLErrs::StandaloneNotLegal);
1145                if (flags[EncodingString] == -1)
1146                        emitError(XMLErrs::EncodingRequired);
1147        }
1148
1149        if (!fReaderMgr.skippedChar(chQuestion))
1150        {
1151                emitError(XMLErrs::UnterminatedXMLDecl);
1152                fReaderMgr.skipPastChar(chCloseAngle);
1153        }
1154        else if (!fReaderMgr.skippedChar(chCloseAngle))
1155        {
1156                emitError(XMLErrs::UnterminatedXMLDecl);
1157                fReaderMgr.skipPastChar(chCloseAngle);
1158        }
1159
1160        //  Do this before we possibly update the reader with the
1161        //  actual encoding string. Otherwise, we will pass the wrong thing
1162        //  for the last parameter!
1163        const XMLCh* actualEnc = fReaderMgr.getCurrentEncodingStr();
1164
1165        //  Ok, we've now seen the real encoding string, if there was one, so
1166        //  lets call back on the current reader and tell it what the real
1167        //  encoding string was. If it fails, that's because it represents some
1168        //  sort of contradiction with the autosensed format, and it keeps the
1169        //  original encoding.
1170        //
1171        //  NOTE: This can fail for a number of reasons, such as a bogus encoding
1172        //  name or because its in flagrant contradiction of the auto-sensed
1173        //  format.
1174        if (flags[EncodingString] != -1)
1175        {
1176                if (!fReaderMgr.getCurrentReader()->setEncoding(bbEncoding.getRawBuffer()))
1177                        emitError(XMLErrs::ContradictoryEncoding, bbEncoding.getRawBuffer());
1178                else
1179                        actualEnc = bbEncoding.getRawBuffer();
1180        }
1181
1182        //  If we have a document handler then call the XML Decl callback.
1183        if (type == Decl_XML)
1184        {
1185                if (fDocHandler)
1186                        fDocHandler->XMLDecl
1187                        (
1188                                bbVersion.getRawBuffer()
1189                                , bbEncoding.getRawBuffer()
1190                                , bbStand.getRawBuffer()
1191                                , actualEnc
1192                        );
1193        }
1194        else if (type == Decl_Text)
1195        {
1196                if (fDocTypeHandler)
1197                        fDocTypeHandler->TextDecl
1198                        (
1199                                bbVersion.getRawBuffer()
1200                                , bbEncoding.getRawBuffer()
1201                        );
1202        }
1203}
1204
1205bool XMLScanner::checkXMLDecl(bool startWithAngle)
1206{
1207        // [23] XMLDecl     ::= '<?xml' VersionInfo EncodingDecl? SDDecl? S? '?>'
1208        // [24] VersionInfo ::= S 'version' Eq ("'" VersionNum "'" | '"' VersionNum '"')
1209        //
1210        // [3]  S           ::= (#x20 | #x9 | #xD | #xA)+
[3103]1211
1212    bool found = false;
1213
1214    XMLReader * reader = fReaderMgr.getCurrentReader();
1215
[2720]1216        if (startWithAngle)
1217        {
[3103]1218        if (reader->peekString(XMLUni::fgXMLDeclStringSpace, 5, true))
1219        {
1220            found = true;
1221        }
1222        else if (unlikely(reader->peekString(XMLUni::fgXMLDeclStringSpaceU, 5, true)))
1223        {
1224            emitError(XMLErrs::XMLDeclMustBeLowerCase);
1225            found = true;
1226        }
1227        if (found)
1228        {
1229            reader->skipChars(6);
1230        }
[2720]1231        }
1232        else
1233        {
[3103]1234        if (reader->peekString(XMLUni::fgXMLStringSpace, 3, true))
1235        {
1236            found = true;
1237        }
1238        else if (unlikely(reader->peekString(XMLUni::fgXMLStringSpaceU, 3, true)))
1239        {
1240            emitError(XMLErrs::XMLDeclMustBeLowerCase);
1241            found = true;
1242        }
1243        if (found)
1244        {
1245            reader->skipChars(4);
1246        }
[2720]1247        }
1248
[3103]1249    return found;
[2720]1250}
1251
1252
1253// ---------------------------------------------------------------------------
1254//  XMLScanner: Grammar preparsing
1255// ---------------------------------------------------------------------------
1256Grammar* XMLScanner::loadGrammar(const   XMLCh* const systemId
1257                                                                 , const short        grammarType
1258                                                                 , const bool         toCache)
1259{
1260        InputSource* srcToUse = 0;
1261
1262        if (fEntityHandler){
1263                ReaderMgr::LastExtEntityInfo lastInfo;
1264                fReaderMgr.getLastExtEntityInfo(lastInfo);
1265                XMLResourceIdentifier resourceIdentifier(XMLResourceIdentifier::ExternalEntity,
1266                                                        systemId, 0, XMLUni::fgZeroLenString, lastInfo.systemId,
1267                                                        &fReaderMgr);
1268                srcToUse = fEntityHandler->resolveEntity(&resourceIdentifier);
1269        }
1270
1271        //  First we try to parse it as a URL. If that fails, we assume its
1272        //  a file and try it that way.
1273        if (!srcToUse) {
1274                if (fDisableDefaultEntityResolution)
1275                        return 0;
1276
1277                try
1278                {
1279                        //  Create a temporary URL. Since this is the primary document,
1280                        //  it has to be fully qualified. If not, then assume we are just
1281                        //  mistaking a file for a URL.
1282                        XMLURL tmpURL(fMemoryManager);
1283
1284                        if (XMLURL::parse(systemId, tmpURL)) {
1285
1286                                if (tmpURL.isRelative())
1287                                {
1288                                        if (!fStandardUriConformant)
1289                                                srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
1290                                        else {
1291                                                // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
1292                                                // emit the error directly
1293                                                MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_NoProtocolPresent, fMemoryManager);
1294                                                fInException = true;
1295                                                emitError
1296                                                (
1297                                                        XMLErrs::XMLException_Fatal
1298                                                        , e.getCode()
1299                                                        , e.getMessage()
1300                                                );
1301                                                return 0;
1302                                        }
1303                                }
1304                                else
1305                                {
1306                                        if (fStandardUriConformant && tmpURL.hasInvalidChar()) {
1307                                                MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL, fMemoryManager);
1308                                                fInException = true;
1309                                                emitError
1310                                                (
1311                                                        XMLErrs::XMLException_Fatal
1312                                                        , e.getCode()
1313                                                        , e.getMessage()
1314                                                );
1315                                                return 0;
1316                                        }
1317                                        srcToUse = new (fMemoryManager) URLInputSource(tmpURL, fMemoryManager);
1318                                }
1319                        }
1320                        else
1321                        {
1322                                if (!fStandardUriConformant)
1323                                        srcToUse = new (fMemoryManager) LocalFileInputSource(systemId, fMemoryManager);
1324                                else {
1325                                        // since this is the top of the try/catch, cannot call ThrowXMLwithMemMgr
1326                                        // emit the error directly
1327                                        // lazy bypass ... since all MalformedURLException are fatal, no need to check the type
1328                                        MalformedURLException e(__FILE__, __LINE__, XMLExcepts::URL_MalformedURL);
1329                                        fInException = true;
1330                                        emitError
1331                                        (
1332                                                XMLErrs::XMLException_Fatal
1333                                                , e.getCode()
1334                                                , e.getMessage()
1335                                        );
1336                                        return 0;
1337                                }
1338                        }
1339                }
1340                catch(const XMLException& excToCatch)
1341                {
1342                        //  For any other XMLException,
1343                        //  emit the error and catch any user exception thrown from here.
1344                        fInException = true;
1345                        if (excToCatch.getErrorType() == XMLErrorReporter::ErrType_Warning)
1346                                emitError
1347                                (
1348                                        XMLErrs::XMLException_Warning
1349                                        , excToCatch.getCode()
1350                                        , excToCatch.getMessage()
1351                                );
1352                        else if (excToCatch.getErrorType() >= XMLErrorReporter::ErrType_Fatal)
1353                                emitError
1354                                (
1355                                        XMLErrs::XMLException_Fatal
1356                                        , excToCatch.getCode()
1357                                        , excToCatch.getMessage()
1358                                );
1359                        else
1360                                emitError
1361                                (
1362                                        XMLErrs::XMLException_Error
1363                                        , excToCatch.getCode()
1364                                        , excToCatch.getMessage()
1365                                );
1366                                return 0;
1367                }
1368        }
1369
1370        Janitor<InputSource> janSrc(srcToUse);
1371        return loadGrammar(*srcToUse, grammarType, toCache);
1372}
1373
1374Grammar* XMLScanner::loadGrammar(const   char* const systemId
1375                                                                 , const short       grammarType
1376                                                                 , const bool        toCache)
1377{
1378        // We just delegate this to the XMLCh version after transcoding
1379        XMLCh* tmpBuf = XMLString::transcode(systemId, fMemoryManager);
1380        ArrayJanitor<XMLCh> janBuf(tmpBuf, fMemoryManager);
1381        return loadGrammar(tmpBuf, grammarType, toCache);
1382}
1383
1384// ---------------------------------------------------------------------------
[3103]1385//  XMLScanner: Error handling methods
1386// ---------------------------------------------------------------------------
1387
1388void XMLScanner::reportUndefinedAttribute(unsigned int uriId, const QName * attributeName, const XMLElementDecl & element)
1389{
1390    XMLBuffer bufMsg(1023, fMemoryManager);
1391    if (uriId != XMLNamespaceResolver::fEmptyUriId)
1392    {
1393        bufMsg.append(chOpenCurly);
1394        bufMsg.append(fUriResolver->getUriForId(uriId));
1395        bufMsg.append(chCloseCurly);
1396    }
1397    bufMsg.append(attributeName->getLocalPart());
1398
1399    fValidator->emitError(XMLValid::AttNotDefinedForElement, bufMsg.getRawBuffer(), element.getBaseName());
1400}
1401
1402// ---------------------------------------------------------------------------
[2720]1403//  XMLScanner: Private helper methods
1404// ---------------------------------------------------------------------------
1405
1406/***
1407 * In reusing grammars (cacheing grammar from parse, or use cached grammar), internal
1408 * dtd is allowed conditionally.
1409 *
1410 * In the case of cacheing grammar from parse, it is NOT allowed.
1411 *
1412 * In the case of use cached grammar,
1413 *   if external dtd is present and it is parsed before, then it is not allowed,
1414 *   otherwise it is allowed.
1415 *
1416 ***/
1417void XMLScanner::checkInternalDTD(bool hasExtSubset
1418                                                                 ,const XMLCh* const sysId
1419                                                                 ,const XMLCh* const pubId)
1420{
1421        if (fToCacheGrammar)
1422                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_CantHaveIntSS, fMemoryManager);
1423
1424        if (fUseCachedGrammar && hasExtSubset && !fIgnoreCachedDTD)
1425        {
1426                InputSource* sysIdSrc = resolveSystemId(sysId, pubId);
[3103]1427        if (sysIdSrc)
1428        {
[2720]1429                        Janitor<InputSource> janSysIdSrc(sysIdSrc);
1430                        Grammar* grammar = fGrammarResolver->getGrammar(sysIdSrc->getSystemId());
1431
1432                        if (grammar && grammar->getGrammarType() == Grammar::DTDGrammarType)
1433                        {
1434                                ThrowXMLwithMemMgr(RuntimeException, XMLExcepts::Val_CantHaveIntSS, fMemoryManager);
1435                        }
1436                }
1437        }
1438
1439}
1440
1441//  This method is called after the content scan to insure that all the
1442//  ID/IDREF attributes match up (i.e. that all IDREFs refer to IDs.) This is
1443//  an XML 1.0 rule, so we can do here in the core.
1444
1445void XMLScanner::checkIDRefs()
1446{
1447        //  Iterate the id ref list. If we find any entries here which are used
1448        //  but not declared, then that's an error.
1449        RefHashTableOfEnumerator<XMLRefInfo> refEnum(fValidationContext->getIdRefList(), false, fMemoryManager);
1450        while (refEnum.hasMoreElements())
1451        {
1452                // Get a ref to the current element
1453                const XMLRefInfo& curRef = refEnum.nextElement();
1454
1455                // If its used but not declared, then its an error
1456                if (!curRef.getDeclared() && curRef.getUsed() && fValidate)
1457                        fValidator->emitError(XMLValid::IDNotDeclared, curRef.getRefName());
1458        }
1459}
1460
1461
1462//  This just does a simple check that the passed progressive scan token is
1463//  legal for this scanner.
1464bool XMLScanner::isLegalToken(const XMLPScanToken& toCheck)
1465{
1466        return ((fScannerId == toCheck.fScannerId) && (fSequenceId == toCheck.fSequenceId));
1467}
1468
1469//  Scans a PI and calls the appropriate callbacks. At entry we have just
1470//  scanned the <? part, and need to now start on the PI target name.
1471void XMLScanner::scanPI()
1472{
1473#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
1474        const XMLCh* namePtr = 0;
1475        const XMLCh* targetPtr = 0;
1476
1477        //  If there are any spaces here, then warn about it. If we aren't in
1478        //  'first error' mode, then we'll come back and can easily pick up
1479        //  again by just skipping them.
1480        if (fReaderMgr.lookingAtSpace())
1481        {
1482                emitError(XMLErrs::PINameExpected);
1483                fReaderMgr.skipPastSpaces();
1484        }
1485
1486        // Get a buffer for the PI name and scan it in
1487        XMLBufBid bbName(&fBufMgr);
1488        if (!fReaderMgr.getName(bbName.getBuffer()))
1489        {
1490                emitError(XMLErrs::PINameExpected);
1491                fReaderMgr.skipPastChar(chCloseAngle);
1492                return;
1493        }
1494
1495        // Point the name pointer at the raw data
1496        namePtr = bbName.getRawBuffer();
1497
1498        // See if it is some form of 'xml' and emit a warning
1499        //if (!XMLString::compareIString(namePtr, XMLUni::fgXMLString))
1500        if (bbName.getLen() == 3 &&
1501                (((namePtr[0] == chLatin_x) || (namePtr[0] == chLatin_X)) &&
1502                 ((namePtr[1] == chLatin_m) || (namePtr[1] == chLatin_M)) &&
1503                 ((namePtr[2] == chLatin_l) || (namePtr[2] == chLatin_L))))
1504                emitError(XMLErrs::NoPIStartsWithXML);
1505
1506        // If namespaces are enabled, then no colons allowed
1507        if (fDoNamespaces)
1508        {
1509                if (XMLString::indexOf(namePtr, chColon) != -1)
1510                        emitError(XMLErrs::ColonNotLegalWithNS);
1511        }
1512
1513        //  If we don't hit a space next, then the PI has no target. If we do
1514        //  then get out the target. Get a buffer for it as well
1515        XMLBufBid bbTarget(&fBufMgr);
1516        if (fReaderMgr.skippedSpace())
1517        {
1518                // Skip any leading spaces
1519                fReaderMgr.skipPastSpaces();
1520
1521                bool gotLeadingSurrogate = false;
1522
1523                // It does have a target, so lets move on to deal with that.
1524                while (1)
1525                {
1526                        const XMLCh nextCh = fReaderMgr.getNextChar();
1527
1528                        // Watch for an end of file, which is always bad here
1529                        if (!nextCh)
1530                        {
1531                                emitError(XMLErrs::UnterminatedPI);
1532                                ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager);
1533                        }
1534
1535                        // Watch for potential terminating character
1536                        if (nextCh == chQuestion)
1537                        {
1538                                // It must be followed by '>' to be a termination of the target
1539                                if (fReaderMgr.skippedChar(chCloseAngle))
1540                                        break;
1541                        }
1542
1543                        // Check for correct surrogate pairs
[3103]1544            if (unlikely((nextCh >= 0xD800) && (nextCh <= 0xDBFF)))
[2720]1545                        {
1546                                if (gotLeadingSurrogate)
1547                                        emitError(XMLErrs::Expected2ndSurrogateChar);
1548                                else
1549                                        gotLeadingSurrogate = true;
1550                        }
[3103]1551            else
[2720]1552                        {
[3103]1553                if (unlikely(gotLeadingSurrogate))
[2720]1554                                {
1555                                        if ((nextCh < 0xDC00) || (nextCh > 0xDFFF))
1556                                                emitError(XMLErrs::Expected2ndSurrogateChar);
[3103]1557                    gotLeadingSurrogate = false;
[2720]1558                                }
[3103]1559                // Its got to at least be a valid XML character
1560                else if (!XMLNameChar::isXMLChar(nextCh, (getXMLVersion() == XMLReader::XMLV1_0)))
1561                {
[2720]1562
[3103]1563                    XMLCh tmpBuf[9];
1564                    XMLString::binToText
1565                    (
1566                        nextCh
1567                        , tmpBuf
1568                        , 8
1569                        , 16
1570                        , fMemoryManager
1571                    );
1572                    emitError(XMLErrs::InvalidCharacter, tmpBuf);
1573                }
[2720]1574                        }
1575
1576                        bbTarget.append(nextCh);
1577                }
1578        }
1579        else
1580        {
1581                // No target, but make sure its terminated ok
1582                if (!fReaderMgr.skippedChar(chQuestion))
1583                {
1584                        emitError(XMLErrs::UnterminatedPI);
1585                        fReaderMgr.skipPastChar(chCloseAngle);
1586                        return;
1587                }
1588
1589                if (!fReaderMgr.skippedChar(chCloseAngle))
1590                {
1591                        emitError(XMLErrs::UnterminatedPI);
1592                        fReaderMgr.skipPastChar(chCloseAngle);
1593                        return;
1594                }
1595        }
1596
1597        // Point the target pointer at the raw data
[3103]1598    targetPtr = bbTarget.getRawBuffer();
[2720]1599
1600        // If we have a handler, then call it
1601        if (fDocHandler)
1602        {
1603                fDocHandler->docPI
1604                (
1605                        namePtr
1606                        , targetPtr
1607           );
1608        }
1609
[3103]1610    DEBUG_MESSAGE("scanPI(" << namePtr << ',' << targetPtr << ')');
1611
[2720]1612        //mark PI is seen within the current element
1613        if (! fElemStack.isEmpty())
1614                fElemStack.setCommentOrPISeen();
1615#else
1616        DEPRECATED_FEATURE_IN_ICXML;
1617#endif
1618}
1619
1620//  We get here after the '<!--' part of the comment. We scan past the
1621//  terminating '-->' It will calls the appropriate handler with the comment
1622//  text, if one is provided. A comment can be in either the document or
1623//  the DTD, so the fInDocument flag is used to know which handler to send
1624//  it to.
1625void XMLScanner::scanComment()
1626{
1627#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
1628
1629        enum States
1630        {
1631                InText
1632                , OneDash
1633                , TwoDashes
1634        };
1635
1636        // Get a buffer for this
1637        XMLBufBid bbComment(&fBufMgr);
1638
1639        //  Get the comment text into a temp buffer. Be sure to use temp buffer
1640        //  two here, since its to be used for stuff that is potentially longer
1641        //  than just a name.
1642        States curState = InText;
1643        bool gotLeadingSurrogate = false;
1644        while (true)
1645        {
1646                // Get the next character
1647                const XMLCh nextCh = fReaderMgr.getNextChar();
1648
1649                //  Watch for an end of file
1650                if (!nextCh)
1651                {
1652                        emitError(XMLErrs::UnterminatedComment);
1653                        ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager);
1654                }
1655
1656                // Check for correct surrogate pairs
1657                if ((nextCh >= 0xD800) && (nextCh <= 0xDBFF))
1658                {
1659                        if (gotLeadingSurrogate)
1660                                emitError(XMLErrs::Expected2ndSurrogateChar);
1661                        else
1662                                gotLeadingSurrogate = true;
1663                }
1664                else
1665                {
1666                        if (gotLeadingSurrogate)
1667                        {
1668                                if ((nextCh < 0xDC00) || (nextCh > 0xDFFF))
1669                                        emitError(XMLErrs::Expected2ndSurrogateChar);
1670                        }
1671                        // Its got to at least be a valid XML character
[3103]1672            else if (!XMLNameChar::isXMLChar(nextCh, (getXMLVersion() == XMLReader::XMLV1_0))) {
[2720]1673
1674                                XMLCh tmpBuf[9];
1675                                XMLString::binToText
1676                                (
1677                                        nextCh
1678                                        , tmpBuf
1679                                        , 8
1680                                        , 16
1681                                        , fMemoryManager
1682                                );
1683                                emitError(XMLErrs::InvalidCharacter, tmpBuf);
1684                        }
1685
1686                        gotLeadingSurrogate = false;
1687                }
1688
1689                if (curState == InText)
1690                {
1691                        // If its a dash, go to OneDash state. Otherwise take as text
1692                        if (nextCh == chDash)
1693                                curState = OneDash;
1694                        else
1695                                bbComment.append(nextCh);
1696                }
1697                else if (curState == OneDash)
1698                {
1699                        //  If its another dash, then we change to the two dashes states.
1700                        //  Otherwise, we have to put in the deficit dash and the new
1701                        //  character and go back to InText.
1702                        if (nextCh == chDash)
1703                        {
1704                                curState = TwoDashes;
1705                        }
1706                        else
1707                        {
1708                                bbComment.append(chDash);
1709                                bbComment.append(nextCh);
1710                                curState = InText;
1711                        }
1712                }
1713                else if (curState == TwoDashes)
1714                {
1715                        // The next character must be the closing bracket
1716                        if (nextCh != chCloseAngle)
1717                        {
1718                                emitError(XMLErrs::IllegalSequenceInComment);
1719                                fReaderMgr.skipPastChar(chCloseAngle);
1720                                return;
1721                        }
1722                        break;
1723                }
1724        }
1725
1726        // If we have an available handler, call back with the comment.
1727        if (fDocHandler)
1728        {
1729                fDocHandler->docComment
1730                (
1731                        bbComment.getRawBuffer()
1732                );
1733        }
1734
1735        DEBUG_MESSAGE("scanComment(" << bbComment.getRawBuffer() << ')');
1736
1737        //mark comment is seen within the current element
1738        if (! fElemStack.isEmpty())
1739                fElemStack.setCommentOrPISeen();
1740#else
1741        DEPRECATED_FEATURE_IN_ICXML;
1742#endif
1743}
1744
1745
1746//  Scans all the input from the start of the file to the root element.
1747//  There does not have to be anything in the prolog necessarily, but usually
1748//  there is at least an XMLDecl.
1749//
1750//  On exit from here we are either at the end of the file or about to read
1751//  the opening < of the root element.
1752void XMLScanner::scanProlog()
1753{
[3103]1754    DEBUG_MESSAGE("XMLScanner::scanProlog()")
1755
[2720]1756        bool sawDocTypeDecl = false;
[3103]1757    bool seenAnything = false;
[2720]1758        // Get a buffer for whitespace processing
1759        XMLBufBid bbCData(&fBufMgr);
1760
1761        //  Loop through the prolog. If there is no content, this could go all
1762        //  the way to the end of the file.
1763
[3103]1764    for (;;)
1765    {
1766        const XMLCh nextCh = fReaderMgr.peekNextChar();
[2720]1767
[3103]1768        if (nextCh == chOpenAngle)
1769        {
1770            //  Ok, it could be the xml decl, a comment, the doc type line,
1771            //  or the start of the root element.
1772            if (checkXMLDecl(true))
1773            {
1774                // There shall be at lease --ONE-- space in between
1775                // the tag '<?xml' and the VersionInfo.
1776                //
1777                //  If we are not at line 1, col 6, then the decl was not
1778                //  the first text, so its invalid.
1779                if (seenAnything)
1780                {
1781                    emitError(XMLErrs::XMLDeclMustBeFirst);
1782                }
[2720]1783
[3103]1784                scanXMLDecl(Decl_XML);
1785            }
1786            else if (fReaderMgr.skippedString(XMLUni::fgPIString))
1787            {
1788                scanPI();
1789                seenAnything = true;
1790            }
1791            else if (fReaderMgr.skippedString(XMLUni::fgCommentString))
1792            {
1793                scanComment();
1794                seenAnything = true;
1795            }
1796            else if (fReaderMgr.skippedString(XMLUni::fgDocTypeString))
1797            {
1798                if (sawDocTypeDecl)
1799                {
1800                    emitError(XMLErrs::DuplicateDocTypeDecl);
1801                }
1802                scanDocTypeDecl();
1803                sawDocTypeDecl = true;
1804                seenAnything = true;
1805                // if reusing grammar, this has been validated already in first scan
1806                // skip for performance
1807                if (fValidate && fGrammar && !fGrammar->getValidated())
1808                {
1809                    //  validate the DTD scan so far
1810                    fValidator->preContentValidation(fUseCachedGrammar, true);
1811                }
1812            }
1813            else
1814            {
1815                // Assume its the start of the root element
[3150]1816
1817                //  If we got to the end of input, then its not a valid XML file.
1818                //  Else, go on to scan the content.
1819                if (fReaderMgr.atEOF())
1820                {
1821                    emitError(XMLErrs::EmptyMainEntity);
1822                }
[3103]1823                break;
1824            }
1825        }
[3150]1826        else if (XMLNameChar::isWhitespace(nextCh, true))
[3103]1827        {
1828            //  If we have a document handler then gather up the
1829            //  whitespace and call back. Otherwise just skip over spaces.
1830            if (fDocHandler)
1831            {
1832                fReaderMgr.getSpaces(bbCData.getBuffer());
[3150]1833                fDocHandler->ignorableWhitespace(bbCData.getRawBuffer(), bbCData.getLen(), false);
[3103]1834            }
1835            else
1836            {
1837                fReaderMgr.skipPastSpaces();
1838            }
1839        }
1840        else
1841        {
1842            emitError(XMLErrs::InvalidDocumentStructure);
[2720]1843
[3103]1844            // Watch for end of file and break out
1845            if (!nextCh)
1846                break;
1847            else
1848                fReaderMgr.skipPastChar(chCloseAngle);
1849        }
1850
1851    }
1852
[2720]1853}
1854
1855
1856// ---------------------------------------------------------------------------
1857//  XMLScanner: Private parsing methods
1858// ---------------------------------------------------------------------------
1859
1860//  This guy just scans out a single or double quoted string of characters.
1861//  It does not pass any judgement on the contents and assumes that it is
1862//  illegal to have another quote of the same kind inside the string's
1863//  contents.
1864//
1865//  NOTE: This is for simple stuff like the strings in the XMLDecl which
1866//  cannot have any entities inside them. So this guy does not handle any
1867//  end of entity stuff.
1868bool XMLScanner::getQuotedString(XMLBuffer& toFill)
1869{
1870#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
1871        // Reset the target buffer
1872        toFill.reset();
1873
1874        // Get the next char which must be a single or double quote
1875        XMLCh quoteCh;
1876        if (!fReaderMgr.skipIfQuote(quoteCh))
1877                return false;
1878
1879                XMLCh nextCh;
1880        // Get another char and see if it matches the starting quote char
1881        while ((nextCh=fReaderMgr.getNextChar())!=quoteCh)
1882        {
1883                //  We should never get either an end of file null char here. If we
1884                //  do, just fail. It will be handled more gracefully in the higher
1885                //  level code that called us.
1886                if (!nextCh)
1887                        return false;
1888
1889                // Else add it to the buffer
1890                toFill.append(nextCh);
1891        }
1892        return true;
1893#else
1894        DEPRECATED_FEATURE_IN_ICXML;
1895#endif
1896}
1897
[3103]1898bool XMLScanner::expandEntityReference
1899(
1900    const XMLCh *                   /* entityReference */
1901    , const XMLSize_t               /* length */
1902    , const bool                    /* inAttributeValue */
1903    , XMLBuffer &                   /* toFill */
1904    , bool      &                   /* isPredefined */
[3150]1905    , bool      &                   /* isExternal */
[3103]1906    , XMLFileLoc &                  /* line */
1907    , XMLFileLoc &                  /* column */
1908)
1909{
1910    return 0;
1911}
1912
[2720]1913//  This method scans a character reference and returns the character that
1914//  was refered to. It assumes that we've already scanned the &# characters
1915//  that prefix the numeric code.
1916bool XMLScanner::scanCharRef(XMLBuffer & toFill)
1917{
1918        bool gotOne = false;
1919        unsigned int value = 0;
1920
1921        //  Set the radix. Its supposed to be a lower case x if hex. But, in
1922        //  order to recover well, we check for an upper and put out an error
1923        //  for that.
1924        unsigned int radix = 10;
1925        if (fReaderMgr.skippedChar(chLatin_x))
1926        {
1927                radix = 16;
1928        }
1929        else if (fReaderMgr.skippedChar(chLatin_X))
1930        {
1931                emitError(XMLErrs::HexRadixMustBeLowerCase);
1932                radix = 16;
1933        }
1934
1935        while (true)
1936        {
1937                const XMLCh nextCh = fReaderMgr.peekNextChar();
1938
1939                // Watch for EOF
[3157]1940        if (unlikely(nextCh == 0))
1941        {
[2720]1942                        ThrowXMLwithMemMgr(UnexpectedEOFException, XMLExcepts::Gen_UnexpectedEOF, fMemoryManager);
[3157]1943        }
[2720]1944                // Break out on the terminating semicolon
1945                if (nextCh == chSemiColon)
1946                {
1947                        fReaderMgr.getNextChar();
1948                        break;
1949                }
1950
1951                //  Convert this char to a binary value, or bail out if its not
1952                //  one.
1953                unsigned int nextVal;
1954                if ((nextCh >= chDigit_0) && (nextCh <= chDigit_9))
1955                        nextVal = (unsigned int)(nextCh - chDigit_0);
1956                else if ((nextCh >= chLatin_A) && (nextCh <= chLatin_F))
1957                        nextVal= (unsigned int)(10 + (nextCh - chLatin_A));
1958                else if ((nextCh >= chLatin_a) && (nextCh <= chLatin_f))
1959                        nextVal = (unsigned int)(10 + (nextCh - chLatin_a));
1960                else
1961                {
1962                        //  If we got at least a sigit, then do an unterminated ref error.
1963                        //  Else, do an expected a numerical ref thing.
1964                        if (gotOne)
1965                                emitError(XMLErrs::UnterminatedCharRef);
1966                        else
1967                                emitError(XMLErrs::ExpectedNumericalCharRef);
1968                        // Return failure
1969                        return false;
1970                }
1971
1972                //  Make sure its valid for the radix. If not, then just eat the
1973                //  digit and go on after issueing an error. Else, update the
1974                //  running value with this new digit.
1975                if (nextVal >= radix)
1976                {
1977                        XMLCh tmpStr[2];
1978                        tmpStr[0] = nextCh;
1979                        tmpStr[1] = chNull;
1980                        emitError(XMLErrs::BadDigitForRadix, tmpStr);
1981                }
1982                else
1983                {
1984                        value = (value * radix) + nextVal;
1985                        // Guard against overflow.
1986                        if (value > 0x10FFFF)
1987                        {
1988                                // Character reference was not in the valid range
1989                                emitError(XMLErrs::InvalidCharacterRef);
1990                                return false;
1991                        }
1992                }
1993
1994                // Indicate that we got at least one good digit
1995                gotOne = true;
1996
1997                // And eat the last char
1998                fReaderMgr.getNextChar();
1999        }
2000
2001        // Return the char (or chars)
2002        // And check if the character expanded is valid or not
2003        if (value >= 0x10000 && value <= 0x10FFFF)
2004        {
2005                value -= 0x10000;
2006                toFill.append(XMLCh((value >> 10) + 0xD800));
2007                toFill.append(XMLCh((value & 0x3FF) + 0xDC00));
2008        }
2009        else if (value <= 0xFFFD)
2010        {
2011                XMLCh Char = XMLCh(value);
[3103]2012                toFill.append(Char);       
2013        if (!XMLNameChar::isXMLChar(Char, (getXMLVersion() == XMLReader::XMLV1_0)))
[2720]2014                {
2015                        // Character reference was not in the valid range
2016                        emitError(XMLErrs::InvalidCharacterRef);
2017                        return false;
2018                }
2019        }
2020        else
2021        {
2022                // Character reference was not in the valid range
2023                emitError(XMLErrs::InvalidCharacterRef);
2024                return false;
2025        }
2026
2027        return true;
2028}
2029
[3157]2030const XMLCh* XMLScanner::getURIText(const unsigned int uriId) const
2031{
2032    return (*fUriResolver)[uriId];
2033}
2034
[2720]2035//  Most equal signs can have white space around them, so this little guy
2036//  just makes the calling code cleaner by eating whitespace.
2037bool XMLScanner::scanEq(bool inDecl)
2038{
2039#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
2040        if (inDecl)
2041        {
2042                bool skippedSomething;
2043                fReaderMgr.skipPastSpaces(skippedSomething, inDecl);
2044                if (fReaderMgr.skippedChar(chEqual))
2045                {
2046                        fReaderMgr.skipPastSpaces(skippedSomething, inDecl);
2047                        return true;
2048                }
2049        }
2050        else
2051        {
2052                fReaderMgr.skipPastSpaces();
2053                if (fReaderMgr.skippedChar(chEqual))
2054                {
2055                        fReaderMgr.skipPastSpaces();
2056                        return true;
2057                }
2058        }
2059        return false;
2060#else
2061        DEPRECATED_FEATURE_IN_ICXML;
2062#endif
2063}
2064
2065XMLSize_t
2066XMLScanner::scanUpToWSOr(XMLBuffer& toFill, const XMLCh chEndChar)
2067{
2068#ifndef EXCLUDE_TRADITIONAL_XERCES_FUNCTIONS_AND_VARIABLES
2069        fReaderMgr.getUpToCharOrWS(toFill, chEndChar);
2070        return toFill.getLen();
2071#else
2072        DEPRECATED_FEATURE_IN_ICXML;
2073#endif
2074}
2075
2076/******************************************************************************************************
2077  ICXML - DEPRECATED FUNCTIONS
2078 ******************************************************************************************************/
2079unsigned int XMLScanner::resolvePrefix(const XMLCh* const, const ElemStack::MapModes)
2080{
2081        DEPRECATED_FEATURE_IN_ICXML;
2082}
2083
2084unsigned int *XMLScanner::getNewUIntPtr()
2085{
2086        DEPRECATED_FEATURE_IN_ICXML;
2087}
2088
2089void XMLScanner::resetUIntPool()
2090{
2091        DEPRECATED_FEATURE_IN_ICXML;
2092}
2093
2094void XMLScanner::recreateUIntPool()
2095{
2096        DEPRECATED_FEATURE_IN_ICXML;
2097}
2098
2099void XMLScanner::setURIStringPool(XMLStringPool* const)
2100{
2101        DEPRECATED_FEATURE_IN_ICXML;
2102}
2103
2104bool XMLScanner::getURIText(const unsigned int, XMLBuffer &) const
2105{
2106        DEPRECATED_FEATURE_IN_ICXML;
2107}
2108
2109bool XMLScanner::scanCharRef(XMLCh &, XMLCh &)
2110{
2111        DEPRECATED_FEATURE_IN_ICXML;
2112}
2113
[3103]2114XMLScanner::XMLTokens XMLScanner::senseNextToken(XMLSize_t&)
2115{
2116    DEPRECATED_FEATURE_IN_ICXML;
2117}
2118
[3157]2119unsigned int XMLScanner::resolveQName(const XMLCh* const, XMLBuffer& , const ElemStack::MapModes, int&)
2120{
2121    DEPRECATED_FEATURE_IN_ICXML;
2122}
[3103]2123
[3157]2124unsigned int XMLScanner::resolveQNameWithColon(const XMLCh* const, XMLBuffer&, const ElemStack::MapModes, const int)
2125{
2126    DEPRECATED_FEATURE_IN_ICXML;
2127}
2128
2129void XMLScanner::scanMiscellaneous()
2130{
2131    DEPRECATED_FEATURE_IN_ICXML;
2132}
2133
[2720]2134XERCES_CPP_NAMESPACE_END
Note: See TracBrowser for help on using the repository browser.