1//
2// ParserEngine.cpp
3//
4// Library: XML
5// Package: XML
6// Module: ParserEngine
7//
8// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
9// and Contributors.
10//
11// SPDX-License-Identifier: BSL-1.0
12//
13
14
15#include "Poco/XML/ParserEngine.h"
16#include "Poco/XML/NamespaceStrategy.h"
17#include "Poco/XML/XMLException.h"
18#include "Poco/SAX/EntityResolver.h"
19#include "Poco/SAX/EntityResolverImpl.h"
20#include "Poco/SAX/DTDHandler.h"
21#include "Poco/SAX/DeclHandler.h"
22#include "Poco/SAX/ContentHandler.h"
23#include "Poco/SAX/LexicalHandler.h"
24#include "Poco/SAX/ErrorHandler.h"
25#include "Poco/SAX/InputSource.h"
26#include "Poco/SAX/Locator.h"
27#include "Poco/SAX/LocatorImpl.h"
28#include "Poco/SAX/SAXException.h"
29#include "Poco/URI.h"
30#include <cstring>
31
32
33using Poco::URI;
34using Poco::TextEncoding;
35
36
37namespace Poco {
38namespace XML {
39
40
41class ContextLocator: public Locator
42{
43public:
44 ContextLocator(XML_Parser parser, const XMLString& publicId, const XMLString& systemId):
45 _parser(parser),
46 _publicId(publicId),
47 _systemId(systemId)
48 {
49 }
50
51 ~ContextLocator()
52 {
53 }
54
55 XMLString getPublicId() const
56 {
57 return _publicId;
58 }
59
60 XMLString getSystemId() const
61 {
62 return _systemId;
63 }
64
65 int getLineNumber() const
66 {
67 return XML_GetCurrentLineNumber(_parser);
68 }
69
70 int getColumnNumber() const
71 {
72 return XML_GetCurrentColumnNumber(_parser);
73 }
74
75private:
76 XML_Parser _parser;
77 XMLString _publicId;
78 XMLString _systemId;
79};
80
81
82const int ParserEngine::PARSE_BUFFER_SIZE = 4096;
83const XMLString ParserEngine::EMPTY_STRING;
84
85
86ParserEngine::ParserEngine():
87 _parser(0),
88 _pBuffer(0),
89 _encodingSpecified(false),
90 _expandInternalEntities(true),
91 _externalGeneralEntities(false),
92 _externalParameterEntities(false),
93 _enablePartialReads(false),
94 _pNamespaceStrategy(new NoNamespacesStrategy()),
95 _pEntityResolver(0),
96 _pDTDHandler(0),
97 _pDeclHandler(0),
98 _pContentHandler(0),
99 _pLexicalHandler(0),
100 _pErrorHandler(0)
101{
102}
103
104
105ParserEngine::ParserEngine(const XMLString& encoding):
106 _parser(0),
107 _pBuffer(0),
108 _encodingSpecified(true),
109 _encoding(encoding),
110 _expandInternalEntities(true),
111 _externalGeneralEntities(false),
112 _externalParameterEntities(false),
113 _enablePartialReads(false),
114 _pNamespaceStrategy(new NoNamespacesStrategy()),
115 _pEntityResolver(0),
116 _pDTDHandler(0),
117 _pDeclHandler(0),
118 _pContentHandler(0),
119 _pLexicalHandler(0),
120 _pErrorHandler(0)
121{
122}
123
124
125ParserEngine::~ParserEngine()
126{
127 resetContext();
128 if (_parser) XML_ParserFree(_parser);
129 delete [] _pBuffer;
130 delete _pNamespaceStrategy;
131}
132
133
134void ParserEngine::setEncoding(const XMLString& encoding)
135{
136 _encoding = encoding;
137 _encodingSpecified = true;
138}
139
140
141void ParserEngine::addEncoding(const XMLString& name, TextEncoding* pEncoding)
142{
143 poco_check_ptr (pEncoding);
144
145 if (_encodings.find(name) == _encodings.end())
146 _encodings[name] = pEncoding;
147 else
148 throw XMLException("Encoding already defined");
149}
150
151
152void ParserEngine::setNamespaceStrategy(NamespaceStrategy* pStrategy)
153{
154 poco_check_ptr (pStrategy);
155
156 delete _pNamespaceStrategy;
157 _pNamespaceStrategy = pStrategy;
158}
159
160
161void ParserEngine::setExpandInternalEntities(bool flag)
162{
163 _expandInternalEntities = flag;
164}
165
166
167void ParserEngine::setExternalGeneralEntities(bool flag)
168{
169 _externalGeneralEntities = flag;
170}
171
172
173void ParserEngine::setExternalParameterEntities(bool flag)
174{
175 _externalParameterEntities = flag;
176}
177
178
179void ParserEngine::setEntityResolver(EntityResolver* pResolver)
180{
181 _pEntityResolver = pResolver;
182}
183
184
185void ParserEngine::setDTDHandler(DTDHandler* pDTDHandler)
186{
187 _pDTDHandler = pDTDHandler;
188}
189
190
191void ParserEngine::setDeclHandler(DeclHandler* pDeclHandler)
192{
193 _pDeclHandler = pDeclHandler;
194}
195
196
197void ParserEngine::setContentHandler(ContentHandler* pContentHandler)
198{
199 _pContentHandler = pContentHandler;
200}
201
202
203void ParserEngine::setLexicalHandler(LexicalHandler* pLexicalHandler)
204{
205 _pLexicalHandler = pLexicalHandler;
206}
207
208
209void ParserEngine::setErrorHandler(ErrorHandler* pErrorHandler)
210{
211 _pErrorHandler = pErrorHandler;
212}
213
214
215void ParserEngine::setEnablePartialReads(bool flag)
216{
217 _enablePartialReads = flag;
218}
219
220
221void ParserEngine::parse(InputSource* pInputSource)
222{
223 init();
224 resetContext();
225 pushContext(_parser, pInputSource);
226 if (_pContentHandler) _pContentHandler->setDocumentLocator(this);
227 if (_pContentHandler) _pContentHandler->startDocument();
228 if (pInputSource->getCharacterStream())
229 parseCharInputStream(*pInputSource->getCharacterStream());
230 else if (pInputSource->getByteStream())
231 parseByteInputStream(*pInputSource->getByteStream());
232 else throw XMLException("Input source has no stream");
233 if (_pContentHandler) _pContentHandler->endDocument();
234 popContext();
235}
236
237
238void ParserEngine::parse(const char* pBuffer, std::size_t size)
239{
240 init();
241 resetContext();
242 InputSource src;
243 pushContext(_parser, &src);
244 if (_pContentHandler) _pContentHandler->setDocumentLocator(this);
245 if (_pContentHandler) _pContentHandler->startDocument();
246 std::size_t processed = 0;
247 while (processed < size)
248 {
249 const int bufferSize = processed + PARSE_BUFFER_SIZE < size ? PARSE_BUFFER_SIZE : static_cast<int>(size - processed);
250 if (!XML_Parse(_parser, pBuffer + processed, bufferSize, 0))
251 handleError(XML_GetErrorCode(_parser));
252 processed += bufferSize;
253 }
254 if (!XML_Parse(_parser, pBuffer+processed, 0, 1))
255 handleError(XML_GetErrorCode(_parser));
256 if (_pContentHandler) _pContentHandler->endDocument();
257 popContext();
258}
259
260
261void ParserEngine::parseByteInputStream(XMLByteInputStream& istr)
262{
263 std::streamsize n = readBytes(istr, _pBuffer, PARSE_BUFFER_SIZE);
264 while (n > 0)
265 {
266 if (!XML_Parse(_parser, _pBuffer, static_cast<int>(n), 0))
267 handleError(XML_GetErrorCode(_parser));
268 if (istr.good())
269 n = readBytes(istr, _pBuffer, PARSE_BUFFER_SIZE);
270 else
271 n = 0;
272 }
273 if (!XML_Parse(_parser, _pBuffer, 0, 1))
274 handleError(XML_GetErrorCode(_parser));
275}
276
277
278void ParserEngine::parseCharInputStream(XMLCharInputStream& istr)
279{
280 std::streamsize n = readChars(istr, reinterpret_cast<XMLChar*>(_pBuffer), PARSE_BUFFER_SIZE/sizeof(XMLChar));
281 while (n > 0)
282 {
283 if (!XML_Parse(_parser, _pBuffer, static_cast<int>(n*sizeof(XMLChar)), 0))
284 handleError(XML_GetErrorCode(_parser));
285 if (istr.good())
286 n = readChars(istr, reinterpret_cast<XMLChar*>(_pBuffer), PARSE_BUFFER_SIZE/sizeof(XMLChar));
287 else
288 n = 0;
289 }
290 if (!XML_Parse(_parser, _pBuffer, 0, 1))
291 handleError(XML_GetErrorCode(_parser));
292}
293
294
295void ParserEngine::parseExternal(XML_Parser extParser, InputSource* pInputSource)
296{
297 pushContext(extParser, pInputSource);
298 if (pInputSource->getCharacterStream())
299 parseExternalCharInputStream(extParser, *pInputSource->getCharacterStream());
300 else if (pInputSource->getByteStream())
301 parseExternalByteInputStream(extParser, *pInputSource->getByteStream());
302 else throw XMLException("Input source has no stream");
303 popContext();
304}
305
306
307void ParserEngine::parseExternalByteInputStream(XML_Parser extParser, XMLByteInputStream& istr)
308{
309 char *pBuffer = new char[PARSE_BUFFER_SIZE];
310 try
311 {
312 std::streamsize n = readBytes(istr, pBuffer, PARSE_BUFFER_SIZE);
313 while (n > 0)
314 {
315 if (!XML_Parse(extParser, pBuffer, static_cast<int>(n), 0))
316 handleError(XML_GetErrorCode(extParser));
317 if (istr.good())
318 n = readBytes(istr, pBuffer, PARSE_BUFFER_SIZE);
319 else
320 n = 0;
321 }
322 if (!XML_Parse(extParser, pBuffer, 0, 1))
323 handleError(XML_GetErrorCode(extParser));
324 }
325 catch (...)
326 {
327 delete [] pBuffer;
328 throw;
329 }
330 delete [] pBuffer;
331}
332
333
334void ParserEngine::parseExternalCharInputStream(XML_Parser extParser, XMLCharInputStream& istr)
335{
336 XMLChar *pBuffer = new XMLChar[PARSE_BUFFER_SIZE/sizeof(XMLChar)];
337 try
338 {
339 std::streamsize n = readChars(istr, pBuffer, PARSE_BUFFER_SIZE/sizeof(XMLChar));
340 while (n > 0)
341 {
342 if (!XML_Parse(extParser, reinterpret_cast<char*>(pBuffer), static_cast<int>(n*sizeof(XMLChar)), 0))
343 handleError(XML_GetErrorCode(extParser));
344 if (istr.good())
345 n = readChars(istr, pBuffer, static_cast<int>(PARSE_BUFFER_SIZE/sizeof(XMLChar)));
346 else
347 n = 0;
348 }
349 if (!XML_Parse(extParser, reinterpret_cast<char*>(pBuffer), 0, 1))
350 handleError(XML_GetErrorCode(extParser));
351 }
352 catch (...)
353 {
354 delete [] pBuffer;
355 throw;
356 }
357 delete [] pBuffer;
358}
359
360
361std::streamsize ParserEngine::readBytes(XMLByteInputStream& istr, char* pBuffer, std::streamsize bufferSize)
362{
363 if (_enablePartialReads)
364 {
365 istr.read(pBuffer, 1);
366 if (istr.gcount() == 1)
367 {
368 std::streamsize n = istr.readsome(pBuffer + 1, bufferSize - 1);
369 return n + 1;
370 }
371 else return 0;
372 }
373 else
374 {
375 istr.read(pBuffer, bufferSize);
376 return istr.gcount();
377 }
378}
379
380
381std::streamsize ParserEngine::readChars(XMLCharInputStream& istr, XMLChar* pBuffer, std::streamsize bufferSize)
382{
383 if (_enablePartialReads)
384 {
385 istr.read(pBuffer, 1);
386 if (istr.gcount() == 1)
387 {
388 std::streamsize n = istr.readsome(pBuffer + 1, bufferSize - 1);
389 return n + 1;
390 }
391 else return 0;
392 }
393 else
394 {
395 istr.read(pBuffer, bufferSize);
396 return istr.gcount();
397 }
398}
399
400
401XMLString ParserEngine::getPublicId() const
402{
403 return locator().getPublicId();
404}
405
406
407XMLString ParserEngine::getSystemId() const
408{
409 return locator().getSystemId();
410}
411
412
413int ParserEngine::getLineNumber() const
414{
415 return locator().getLineNumber();
416}
417
418
419int ParserEngine::getColumnNumber() const
420{
421 return locator().getColumnNumber();
422}
423
424
425namespace
426{
427 static LocatorImpl nullLocator;
428}
429
430
431const Locator& ParserEngine::locator() const
432{
433 if (_context.empty())
434 return nullLocator;
435 else
436 return *_context.back();
437}
438
439
440void ParserEngine::init()
441{
442 if (_parser)
443 XML_ParserFree(_parser);
444
445 if (!_pBuffer)
446 _pBuffer = new char[PARSE_BUFFER_SIZE];
447
448 if (dynamic_cast<NoNamespacePrefixesStrategy*>(_pNamespaceStrategy))
449 {
450 _parser = XML_ParserCreateNS(_encodingSpecified ? _encoding.c_str() : 0, '\t');
451 if (_parser)
452 {
453 XML_SetNamespaceDeclHandler(_parser, handleStartNamespaceDecl, handleEndNamespaceDecl);
454 }
455 }
456 else if (dynamic_cast<NamespacePrefixesStrategy*>(_pNamespaceStrategy))
457 {
458 _parser = XML_ParserCreateNS(_encodingSpecified ? _encoding.c_str() : 0, '\t');
459 if (_parser)
460 {
461 XML_SetReturnNSTriplet(_parser, 1);
462 XML_SetNamespaceDeclHandler(_parser, handleStartNamespaceDecl, handleEndNamespaceDecl);
463 }
464 }
465 else
466 {
467 _parser = XML_ParserCreate(_encodingSpecified ? _encoding.c_str() : 0);
468 }
469
470 if (!_parser) throw XMLException("Cannot create Expat parser");
471
472 XML_SetUserData(_parser, this);
473 XML_SetElementHandler(_parser, handleStartElement, handleEndElement);
474 XML_SetCharacterDataHandler(_parser, handleCharacterData);
475 XML_SetProcessingInstructionHandler(_parser, handleProcessingInstruction);
476 if (_expandInternalEntities)
477 XML_SetDefaultHandlerExpand(_parser, handleDefault);
478 else
479 XML_SetDefaultHandler(_parser, handleDefault);
480 XML_SetUnparsedEntityDeclHandler(_parser, handleUnparsedEntityDecl);
481 XML_SetNotationDeclHandler(_parser, handleNotationDecl);
482 XML_SetExternalEntityRefHandler(_parser, handleExternalEntityRef);
483 XML_SetCommentHandler(_parser, handleComment);
484 XML_SetCdataSectionHandler(_parser, handleStartCdataSection, handleEndCdataSection);
485 XML_SetDoctypeDeclHandler(_parser, handleStartDoctypeDecl, handleEndDoctypeDecl);
486 XML_SetEntityDeclHandler(_parser, handleEntityDecl);
487 XML_SetSkippedEntityHandler(_parser, handleSkippedEntity);
488 XML_SetParamEntityParsing(_parser, _externalParameterEntities ? XML_PARAM_ENTITY_PARSING_ALWAYS : XML_PARAM_ENTITY_PARSING_NEVER);
489 XML_SetUnknownEncodingHandler(_parser, handleUnknownEncoding, this);
490}
491
492
493void ParserEngine::handleError(int errorNo)
494{
495 try
496 {
497 switch (errorNo)
498 {
499 case XML_ERROR_NO_MEMORY:
500 throw XMLException("No memory");
501 case XML_ERROR_SYNTAX:
502 throw SAXParseException("Syntax error", locator());
503 case XML_ERROR_NO_ELEMENTS:
504 throw SAXParseException("No element found", locator());
505 case XML_ERROR_INVALID_TOKEN:
506 throw SAXParseException("Invalid token", locator());
507 case XML_ERROR_UNCLOSED_TOKEN:
508 throw SAXParseException("Unclosed token", locator());
509 case XML_ERROR_PARTIAL_CHAR:
510 throw SAXParseException("Partial character", locator());
511 case XML_ERROR_TAG_MISMATCH:
512 throw SAXParseException("Tag mismatch", locator());
513 case XML_ERROR_DUPLICATE_ATTRIBUTE:
514 throw SAXParseException("Duplicate attribute", locator());
515 case XML_ERROR_JUNK_AFTER_DOC_ELEMENT:
516 throw SAXParseException("Junk after document element", locator());
517 case XML_ERROR_PARAM_ENTITY_REF:
518 throw SAXParseException("Illegal parameter entity reference", locator());
519 case XML_ERROR_UNDEFINED_ENTITY:
520 throw SAXParseException("Undefined entity", locator());
521 case XML_ERROR_RECURSIVE_ENTITY_REF:
522 throw SAXParseException("Recursive entity reference", locator());
523 case XML_ERROR_ASYNC_ENTITY:
524 throw SAXParseException("Asynchronous entity", locator());
525 case XML_ERROR_BAD_CHAR_REF:
526 throw SAXParseException("Reference to invalid character number", locator());
527 case XML_ERROR_BINARY_ENTITY_REF:
528 throw SAXParseException("Reference to binary entity", locator());
529 case XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF:
530 throw SAXParseException("Reference to external entity in attribute", locator());
531 case XML_ERROR_MISPLACED_XML_PI:
532 throw SAXParseException("XML processing instruction not at start of external entity", locator());
533 case XML_ERROR_UNKNOWN_ENCODING:
534 throw SAXParseException("Unknown encoding", locator());
535 case XML_ERROR_INCORRECT_ENCODING:
536 throw SAXParseException("Encoding specified in XML declaration is incorrect", locator());
537 case XML_ERROR_UNCLOSED_CDATA_SECTION:
538 throw SAXParseException("Unclosed CDATA section", locator());
539 case XML_ERROR_EXTERNAL_ENTITY_HANDLING:
540 throw SAXParseException("Error in processing external entity reference", locator());
541 case XML_ERROR_NOT_STANDALONE:
542 throw SAXParseException("Document is not standalone", locator());
543 case XML_ERROR_UNEXPECTED_STATE:
544 throw SAXParseException("Unexpected parser state - please send a bug report", locator());
545 case XML_ERROR_ENTITY_DECLARED_IN_PE:
546 throw SAXParseException("Entity declared in parameter entity", locator());
547 case XML_ERROR_FEATURE_REQUIRES_XML_DTD:
548 throw SAXParseException("Requested feature requires XML_DTD support in Expat", locator());
549 case XML_ERROR_CANT_CHANGE_FEATURE_ONCE_PARSING:
550 throw SAXParseException("Cannot change setting once parsing has begun", locator());
551 case XML_ERROR_UNBOUND_PREFIX:
552 throw SAXParseException("Unbound prefix", locator());
553 case XML_ERROR_UNDECLARING_PREFIX:
554 throw SAXParseException("Must not undeclare prefix", locator());
555 case XML_ERROR_INCOMPLETE_PE:
556 throw SAXParseException("Incomplete markup in parameter entity", locator());
557 case XML_ERROR_XML_DECL:
558 throw SAXParseException("XML declaration not well-formed", locator());
559 case XML_ERROR_TEXT_DECL:
560 throw SAXParseException("Text declaration not well-formed", locator());
561 case XML_ERROR_PUBLICID:
562 throw SAXParseException("Illegal character(s) in public identifier", locator());
563 case XML_ERROR_SUSPENDED:
564 throw SAXParseException("Parser suspended", locator());
565 case XML_ERROR_NOT_SUSPENDED:
566 throw SAXParseException("Parser not suspended", locator());
567 case XML_ERROR_ABORTED:
568 throw SAXParseException("Parsing aborted", locator());
569 case XML_ERROR_FINISHED:
570 throw SAXParseException("Parsing finished", locator());
571 case XML_ERROR_SUSPEND_PE:
572 throw SAXParseException("Cannot suspend in external parameter entity", locator());
573 }
574 throw XMLException("Unknown Expat error code");
575 }
576 catch (SAXException& exc)
577 {
578 if (_pErrorHandler) _pErrorHandler->error(exc);
579 throw;
580 }
581 catch (Poco::Exception& exc)
582 {
583 if (_pErrorHandler) _pErrorHandler->fatalError(SAXParseException("Fatal error", locator(), exc));
584 throw;
585 }
586}
587
588
589void ParserEngine::pushContext(XML_Parser parser, InputSource* pInputSource)
590{
591 ContextLocator* pLocator = new ContextLocator(parser, pInputSource->getPublicId(), pInputSource->getSystemId());
592 _context.push_back(pLocator);
593}
594
595
596void ParserEngine::popContext()
597{
598 poco_assert (!_context.empty());
599 delete _context.back();
600 _context.pop_back();
601}
602
603
604void ParserEngine::resetContext()
605{
606 for (ContextStack::iterator it = _context.begin(); it != _context.end(); ++it)
607 {
608 delete *it;
609 }
610 _context.clear();
611}
612
613
614void ParserEngine::handleStartElement(void* userData, const XML_Char* name, const XML_Char** atts)
615{
616 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
617
618 if (pThis->_pContentHandler)
619 {
620 try
621 {
622 pThis->_pNamespaceStrategy->startElement(name, atts, XML_GetSpecifiedAttributeCount(pThis->_parser)/2, pThis->_pContentHandler);
623 }
624 catch (XMLException& exc)
625 {
626 throw SAXParseException(exc.message(), pThis->locator());
627 }
628 }
629}
630
631
632void ParserEngine::handleEndElement(void* userData, const XML_Char* name)
633{
634 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
635
636 if (pThis->_pContentHandler)
637 {
638 try
639 {
640 pThis->_pNamespaceStrategy->endElement(name, pThis->_pContentHandler);
641 }
642 catch (XMLException& exc)
643 {
644 throw SAXParseException(exc.message(), pThis->locator());
645 }
646 }
647}
648
649
650void ParserEngine::handleCharacterData(void* userData, const XML_Char* s, int len)
651{
652 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
653
654 if (pThis->_pContentHandler)
655 pThis->_pContentHandler->characters(s, 0, len);
656}
657
658
659void ParserEngine::handleProcessingInstruction(void* userData, const XML_Char* target, const XML_Char* data)
660{
661 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
662
663 if (pThis->_pContentHandler)
664 pThis->_pContentHandler->processingInstruction(target, data);
665}
666
667
668void ParserEngine::handleDefault(void* /*userData*/, const XML_Char* /*s*/, int /*len*/)
669{
670}
671
672
673void ParserEngine::handleUnparsedEntityDecl(void* userData, const XML_Char* entityName, const XML_Char* /*base*/, const XML_Char* systemId, const XML_Char* publicId, const XML_Char* notationName)
674{
675 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
676
677 XMLString pubId;
678 if (publicId) pubId.assign(publicId);
679 if (pThis->_pDTDHandler)
680 pThis->_pDTDHandler->unparsedEntityDecl(entityName, publicId ? &pubId : 0, systemId, notationName);
681}
682
683
684void ParserEngine::handleNotationDecl(void* userData, const XML_Char* notationName, const XML_Char* /*base*/, const XML_Char* systemId, const XML_Char* publicId)
685{
686 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
687
688 XMLString pubId;
689 if (publicId) pubId.assign(publicId);
690 XMLString sysId;
691 if (systemId) sysId.assign(systemId);
692 if (pThis->_pDTDHandler)
693 pThis->_pDTDHandler->notationDecl(notationName, publicId ? &pubId : 0, systemId ? &sysId : 0);
694}
695
696
697int ParserEngine::handleExternalEntityRef(XML_Parser parser, const XML_Char* context, const XML_Char* /*base*/, const XML_Char* systemId, const XML_Char* publicId)
698{
699 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(XML_GetUserData(parser));
700
701 if (!context && !pThis->_externalParameterEntities) return XML_STATUS_ERROR;
702 if (context && !pThis->_externalGeneralEntities) return XML_STATUS_ERROR;
703
704 InputSource* pInputSource = 0;
705 EntityResolver* pEntityResolver = 0;
706 EntityResolverImpl defaultResolver;
707
708 XMLString sysId(systemId);
709 XMLString pubId;
710 if (publicId) pubId.assign(publicId);
711
712 URI uri(fromXMLString(pThis->_context.back()->getSystemId()));
713 uri.resolve(fromXMLString(sysId));
714
715 if (pThis->_pEntityResolver)
716 {
717 pEntityResolver = pThis->_pEntityResolver;
718 pInputSource = pEntityResolver->resolveEntity(publicId ? &pubId : 0, toXMLString(uri.toString()));
719 }
720 if (!pInputSource && pThis->_externalGeneralEntities)
721 {
722 pEntityResolver = &defaultResolver;
723 pInputSource = pEntityResolver->resolveEntity(publicId ? &pubId : 0, toXMLString(uri.toString()));
724 }
725
726 if (pInputSource)
727 {
728 XML_Parser extParser = XML_ExternalEntityParserCreate(pThis->_parser, context, 0);
729 if (!extParser) throw XMLException("Cannot create external entity parser");
730
731 try
732 {
733 pThis->parseExternal(extParser, pInputSource);
734 }
735 catch (XMLException&)
736 {
737 pEntityResolver->releaseInputSource(pInputSource);
738 XML_ParserFree(extParser);
739 throw;
740 }
741 pEntityResolver->releaseInputSource(pInputSource);
742 XML_ParserFree(extParser);
743 return XML_STATUS_OK;
744 }
745 else return XML_STATUS_ERROR;
746}
747
748
749int ParserEngine::handleUnknownEncoding(void* encodingHandlerData, const XML_Char* name, XML_Encoding* info)
750{
751 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(encodingHandlerData);
752
753 XMLString encoding(name);
754 TextEncoding* knownEncoding = 0;
755
756 EncodingMap::const_iterator it = pThis->_encodings.find(encoding);
757 if (it != pThis->_encodings.end())
758 knownEncoding = it->second;
759 else
760 knownEncoding = Poco::TextEncoding::find(fromXMLString(encoding));
761
762 if (knownEncoding)
763 {
764 const TextEncoding::CharacterMap& map = knownEncoding->characterMap();
765 for (int i = 0; i < 256; ++i)
766 info->map[i] = map[i];
767
768 info->data = knownEncoding;
769 info->convert = &ParserEngine::convert;
770 info->release = 0;
771 return XML_STATUS_OK;
772 }
773 else return XML_STATUS_ERROR;
774}
775
776
777void ParserEngine::handleComment(void* userData, const XML_Char* data)
778{
779 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
780
781#if defined(XML_UNICODE_WCHAR_T)
782 if (pThis->_pLexicalHandler)
783 pThis->_pLexicalHandler->comment(data, 0, (int) std::wcslen(data));
784#else
785 if (pThis->_pLexicalHandler)
786 pThis->_pLexicalHandler->comment(data, 0, (int) std::strlen(data));
787#endif
788}
789
790
791void ParserEngine::handleStartCdataSection(void* userData)
792{
793 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
794
795 if (pThis->_pLexicalHandler)
796 pThis->_pLexicalHandler->startCDATA();
797}
798
799
800void ParserEngine::handleEndCdataSection(void* userData)
801{
802 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
803
804 if (pThis->_pLexicalHandler)
805 pThis->_pLexicalHandler->endCDATA();
806}
807
808
809void ParserEngine::handleStartNamespaceDecl(void* userData, const XML_Char* prefix, const XML_Char* uri)
810{
811 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
812
813 if (pThis->_pContentHandler)
814 pThis->_pContentHandler->startPrefixMapping((prefix ? XMLString(prefix) : EMPTY_STRING), (uri ? XMLString(uri) : EMPTY_STRING));
815}
816
817
818void ParserEngine::handleEndNamespaceDecl(void* userData, const XML_Char* prefix)
819{
820 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
821
822 if (pThis->_pContentHandler)
823 pThis->_pContentHandler->endPrefixMapping(prefix ? XMLString(prefix) : EMPTY_STRING);
824}
825
826
827void ParserEngine::handleStartDoctypeDecl(void* userData, const XML_Char* doctypeName, const XML_Char *systemId, const XML_Char* publicId, int /*hasInternalSubset*/)
828{
829 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
830
831 if (pThis->_pLexicalHandler)
832 {
833 XMLString sysId = systemId ? XMLString(systemId) : EMPTY_STRING;
834 XMLString pubId = publicId ? XMLString(publicId) : EMPTY_STRING;
835 pThis->_pLexicalHandler->startDTD(doctypeName, pubId, sysId);
836 }
837}
838
839
840void ParserEngine::handleEndDoctypeDecl(void* userData)
841{
842 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
843
844 if (pThis->_pLexicalHandler)
845 pThis->_pLexicalHandler->endDTD();
846}
847
848
849void ParserEngine::handleEntityDecl(void *userData, const XML_Char *entityName, int /*isParamEntity*/, const XML_Char *value, int valueLength,
850 const XML_Char *base, const XML_Char *systemId, const XML_Char *publicId, const XML_Char* /*notationName*/)
851{
852 if (value)
853 handleInternalParsedEntityDecl(userData, entityName, value, valueLength);
854 else
855 handleExternalParsedEntityDecl(userData, entityName, base, systemId, publicId);
856}
857
858
859void ParserEngine::handleExternalParsedEntityDecl(void* userData, const XML_Char* entityName, const XML_Char* /*base*/, const XML_Char* systemId, const XML_Char* publicId)
860{
861 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
862
863 XMLString pubId;
864 if (publicId) pubId.assign(publicId);
865 if (pThis->_pDeclHandler)
866 pThis->_pDeclHandler->externalEntityDecl(entityName, publicId ? &pubId : 0, systemId);
867}
868
869
870void ParserEngine::handleInternalParsedEntityDecl(void* userData, const XML_Char* entityName, const XML_Char* replacementText, int replacementTextLength)
871{
872 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
873
874 XMLString replText(replacementText, replacementTextLength);
875 if (pThis->_pDeclHandler)
876 pThis->_pDeclHandler->internalEntityDecl(entityName, replText);
877}
878
879
880void ParserEngine::handleSkippedEntity(void* userData, const XML_Char* entityName, int /*isParameterEntity*/)
881{
882 ParserEngine* pThis = reinterpret_cast<ParserEngine*>(userData);
883
884 if (pThis->_pContentHandler)
885 pThis->_pContentHandler->skippedEntity(entityName);
886}
887
888
889int ParserEngine::convert(void* data, const char* s)
890{
891 TextEncoding* pEncoding = reinterpret_cast<TextEncoding*>(data);
892 return pEncoding->convert((const unsigned char*) s);
893}
894
895
896} } // namespace Poco::XML
897