Fix GNU C++ version check
[LibreOffice.git] / sax / source / expatwrap / sax_expat.cxx
blobf6e6cdb90f552a2423d97ddb212107462c6fb583
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <string.h>
21 #include <cassert>
22 #include <memory>
23 #include <mutex>
24 #include <utility>
25 #include <string_view>
26 #include <vector>
29 #include <com/sun/star/lang/XServiceInfo.hpp>
30 #include <com/sun/star/lang/XInitialization.hpp>
31 #include <com/sun/star/uno/XComponentContext.hpp>
32 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
33 #include <com/sun/star/xml/sax/XParser.hpp>
34 #include <com/sun/star/xml/sax/SAXParseException.hpp>
35 #include <com/sun/star/io/IOException.hpp>
36 #include <com/sun/star/io/XSeekable.hpp>
37 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
39 #include <comphelper/attributelist.hxx>
40 #include <cppuhelper/weak.hxx>
41 #include <cppuhelper/implbase.hxx>
42 #include <cppuhelper/supportsservice.hxx>
43 #include <rtl/ref.hxx>
44 #include <sal/log.hxx>
46 #include <expat.h>
47 #include <xml2utf.hxx>
49 using namespace ::cppu;
50 using namespace ::com::sun::star::lang;
51 using namespace ::com::sun::star::xml::sax;
52 using namespace ::com::sun::star::io;
55 namespace {
57 #define XML_CHAR_TO_OUSTRING(x) OUString(x , strlen( x ), RTL_TEXTENCODING_UTF8)
58 #define XML_CHAR_N_TO_USTRING(x,n) OUString(x,n, RTL_TEXTENCODING_UTF8 )
62 * The following macro encapsulates any call to an event handler.
63 * It ensures, that exceptions thrown by the event handler are
64 * treated properly.
66 #define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis,call) \
67 if( ! pThis->bExceptionWasThrown ) { \
68 try {\
69 pThis->call;\
71 catch( const SAXParseException &e ) {\
72 callErrorHandler( pThis , e );\
74 catch( const SAXException &e ) {\
75 callErrorHandler( pThis , SAXParseException(\
76 e.Message, \
77 e.Context, \
78 e.WrappedException,\
79 pThis->rDocumentLocator->getPublicId(),\
80 pThis->rDocumentLocator->getSystemId(),\
81 pThis->rDocumentLocator->getLineNumber(),\
82 pThis->rDocumentLocator->getColumnNumber()\
83 ) );\
85 catch( const css::uno::RuntimeException &e ) {\
86 pThis->bExceptionWasThrown = true; \
87 pThis->bRTExceptionWasThrown = true; \
88 pImpl->rtexception = e; \
90 catch( const css::uno::Exception &e ) {\
91 pThis->bExceptionWasThrown = true; \
92 pThis->bRTExceptionWasThrown = true; \
93 pImpl->rtexception = WrappedTargetRuntimeException(u"Non-runtime UNO exception caught during parse"_ustr, e.Context, css::uno::Any(e)); \
96 ((void)0)
99 class SaxExpatParser_Impl;
101 // This class implements the external Parser interface
102 class SaxExpatParser
103 : public WeakImplHelper< XInitialization
104 , XServiceInfo
105 , XParser >
108 public:
109 SaxExpatParser();
111 // css::lang::XInitialization:
112 virtual void SAL_CALL initialize(css::uno::Sequence<css::uno::Any> const& rArguments) override;
114 // The SAX-Parser-Interface
115 virtual void SAL_CALL parseStream( const InputSource& structSource) override;
116 virtual void SAL_CALL setDocumentHandler(const css::uno::Reference< XDocumentHandler > & xHandler) override;
118 virtual void SAL_CALL setErrorHandler(const css::uno::Reference< XErrorHandler > & xHandler) override;
119 virtual void SAL_CALL setDTDHandler(const css::uno::Reference < XDTDHandler > & xHandler) override;
120 virtual void SAL_CALL setEntityResolver(const css::uno::Reference< XEntityResolver >& xResolver) override;
122 virtual void SAL_CALL setLocale( const Locale &locale ) override;
124 public: // XServiceInfo
125 OUString SAL_CALL getImplementationName() override;
126 css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
127 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
129 private:
130 std::unique_ptr<SaxExpatParser_Impl> m_pImpl;
134 // Entity binds all information needed for a single file
135 struct Entity
137 InputSource structSource;
138 XML_Parser pParser;
139 sax_expatwrap::XMLFile2UTFConverter converter;
142 class LocatorImpl;
143 class SaxExpatParser_Impl
145 public: // module scope
146 std::mutex aMutex;
147 bool m_bEnableDoS; // fdo#60471 thank you Adobe Illustrator
149 css::uno::Reference< XDocumentHandler > rDocumentHandler;
150 css::uno::Reference< XExtendedDocumentHandler > rExtendedDocumentHandler;
152 css::uno::Reference< XErrorHandler > rErrorHandler;
153 css::uno::Reference< XDTDHandler > rDTDHandler;
154 css::uno::Reference< XEntityResolver > rEntityResolver;
155 rtl::Reference < LocatorImpl > rDocumentLocator;
158 rtl::Reference < comphelper::AttributeList > rAttrList;
160 // External entity stack
161 std::vector<struct Entity> vecEntity;
162 void pushEntity( Entity &&entity )
163 { vecEntity.push_back( std::move(entity) ); }
164 void popEntity()
165 { vecEntity.pop_back( ); }
166 struct Entity &getEntity()
167 { return vecEntity.back(); }
170 // Exception cannot be thrown through the C-XmlParser (possible resource leaks),
171 // therefore the exception must be saved somewhere.
172 SAXParseException exception;
173 css::uno::RuntimeException rtexception;
174 bool bExceptionWasThrown;
175 bool bRTExceptionWasThrown;
177 public:
178 SaxExpatParser_Impl()
179 : m_bEnableDoS(false)
180 , bExceptionWasThrown(false)
181 , bRTExceptionWasThrown(false)
185 // the C-Callbacks for the expat parser
186 void static callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts);
187 void static callbackEndElement(void *userData, const XML_Char *name);
188 void static callbackCharacters( void *userData , const XML_Char *s , int nLen );
189 void static callbackProcessingInstruction( void *userData ,
190 const XML_Char *sTarget ,
191 const XML_Char *sData );
193 void static callbackEntityDecl( void *userData ,
194 const XML_Char *entityName,
195 int is_parameter_entity,
196 const XML_Char *value,
197 int value_length,
198 const XML_Char *base,
199 const XML_Char *systemId,
200 const XML_Char *publicId,
201 const XML_Char *notationName);
203 void static callbackNotationDecl( void *userData,
204 const XML_Char *notationName,
205 const XML_Char *base,
206 const XML_Char *systemId,
207 const XML_Char *publicId);
209 bool static callbackExternalEntityRef( XML_Parser parser,
210 const XML_Char *openEntityNames,
211 const XML_Char *base,
212 const XML_Char *systemId,
213 const XML_Char *publicId);
215 int static callbackUnknownEncoding(void *encodingHandlerData,
216 const XML_Char *name,
217 XML_Encoding *info);
219 void static callbackDefault( void *userData, const XML_Char *s, int len);
221 void static callbackStartCDATA( void *userData );
222 void static callbackEndCDATA( void *userData );
223 void static callbackComment( void *userData , const XML_Char *s );
224 void static callErrorHandler( SaxExpatParser_Impl *pImpl , const SAXParseException &e );
226 public:
227 void parse();
230 extern "C"
232 static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
234 SaxExpatParser_Impl::callbackStartElement(userData,name,atts);
236 static void call_callbackEndElement(void *userData, const XML_Char *name)
238 SaxExpatParser_Impl::callbackEndElement(userData,name);
240 static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
242 SaxExpatParser_Impl::callbackCharacters(userData,s,nLen);
244 static void call_callbackProcessingInstruction(void *userData,const XML_Char *sTarget,const XML_Char *sData )
246 SaxExpatParser_Impl::callbackProcessingInstruction(userData,sTarget,sData );
248 static void call_callbackEntityDecl(void *userData ,
249 const XML_Char *entityName,
250 int is_parameter_entity,
251 const XML_Char *value,
252 int value_length,
253 const XML_Char *base,
254 const XML_Char *systemId,
255 const XML_Char *publicId,
256 const XML_Char *notationName)
258 SaxExpatParser_Impl::callbackEntityDecl(userData, entityName,
259 is_parameter_entity, value, value_length,
260 base, systemId, publicId, notationName);
262 static void call_callbackNotationDecl(void *userData,
263 const XML_Char *notationName,
264 const XML_Char *base,
265 const XML_Char *systemId,
266 const XML_Char *publicId)
268 SaxExpatParser_Impl::callbackNotationDecl(userData,notationName,base,systemId,publicId);
270 static int call_callbackExternalEntityRef(XML_Parser parser,
271 const XML_Char *openEntityNames,
272 const XML_Char *base,
273 const XML_Char *systemId,
274 const XML_Char *publicId)
276 return SaxExpatParser_Impl::callbackExternalEntityRef(parser,openEntityNames,base,systemId,publicId);
278 static int call_callbackUnknownEncoding(void *encodingHandlerData,
279 const XML_Char *name,
280 XML_Encoding *info)
282 return SaxExpatParser_Impl::callbackUnknownEncoding(encodingHandlerData,name,info);
284 static void call_callbackDefault( void *userData, const XML_Char *s, int len)
286 SaxExpatParser_Impl::callbackDefault(userData,s,len);
288 static void call_callbackStartCDATA( void *userData )
290 SaxExpatParser_Impl::callbackStartCDATA(userData);
292 static void call_callbackEndCDATA( void *userData )
294 SaxExpatParser_Impl::callbackEndCDATA(userData);
296 static void call_callbackComment( void *userData , const XML_Char *s )
298 SaxExpatParser_Impl::callbackComment(userData,s);
303 // LocatorImpl
305 class LocatorImpl :
306 public WeakImplHelper< XLocator, css::io::XSeekable >
307 // should use a different interface for stream positions!
309 public:
310 explicit LocatorImpl(SaxExpatParser_Impl *p)
311 : m_pParser(p)
315 public: //XLocator
316 virtual sal_Int32 SAL_CALL getColumnNumber() override
318 return XML_GetCurrentColumnNumber( m_pParser->getEntity().pParser );
320 virtual sal_Int32 SAL_CALL getLineNumber() override
322 return XML_GetCurrentLineNumber( m_pParser->getEntity().pParser );
324 virtual OUString SAL_CALL getPublicId() override
326 return m_pParser->getEntity().structSource.sPublicId;
328 virtual OUString SAL_CALL getSystemId() override
330 return m_pParser->getEntity().structSource.sSystemId;
333 // XSeekable (only for getPosition)
335 virtual void SAL_CALL seek( sal_Int64 ) override
338 virtual sal_Int64 SAL_CALL getPosition() override
340 return XML_GetCurrentByteIndex( m_pParser->getEntity().pParser );
342 virtual ::sal_Int64 SAL_CALL getLength() override
344 return 0;
347 private:
349 SaxExpatParser_Impl *m_pParser;
353 SaxExpatParser::SaxExpatParser( )
355 m_pImpl.reset( new SaxExpatParser_Impl );
357 m_pImpl->rDocumentLocator = new LocatorImpl( m_pImpl.get() );
359 // Performance-improvement; handing out the same object with every call of
360 // the startElement callback is allowed (see sax-specification):
361 m_pImpl->rAttrList = new comphelper::AttributeList;
363 m_pImpl->bExceptionWasThrown = false;
364 m_pImpl->bRTExceptionWasThrown = false;
367 // css::lang::XInitialization:
368 void SAL_CALL
369 SaxExpatParser::initialize(css::uno::Sequence< css::uno::Any > const& rArguments)
371 // possible arguments: a string "DoSmeplease"
372 if (rArguments.hasElements())
374 OUString str;
375 if ((rArguments[0] >>= str) && "DoSmeplease" == str)
377 std::unique_lock guard( m_pImpl->aMutex );
378 m_pImpl->m_bEnableDoS = true;
383 class ParserCleanup
385 private:
386 SaxExpatParser_Impl& m_rParser;
387 XML_Parser m_xmlParser;
388 public:
389 ParserCleanup(SaxExpatParser_Impl& rParser, XML_Parser xmlParser)
390 : m_rParser(rParser)
391 , m_xmlParser(xmlParser)
394 ~ParserCleanup()
396 m_rParser.popEntity();
397 //XML_ParserFree accepts a null arg
398 XML_ParserFree(m_xmlParser);
402 /***************
404 * parseStream does Parser-startup initializations. The SaxExpatParser_Impl::parse() method does
405 * the file-specific initialization work. (During a parser run, external files may be opened)
407 ****************/
408 void SaxExpatParser::parseStream( const InputSource& structSource)
410 // Only one text at one time
411 std::unique_lock guard( m_pImpl->aMutex );
414 struct Entity entity;
415 entity.structSource = structSource;
417 if( ! entity.structSource.aInputStream.is() )
419 throw SAXException(u"No input source"_ustr,
420 css::uno::Reference< css::uno::XInterface > () , css::uno::Any() );
423 entity.converter.setInputStream( entity.structSource.aInputStream );
424 if( !entity.structSource.sEncoding.isEmpty() )
426 entity.converter.setEncoding(
427 OUStringToOString( entity.structSource.sEncoding , RTL_TEXTENCODING_ASCII_US ) );
430 // create parser with proper encoding
431 entity.pParser = XML_ParserCreate( nullptr );
432 if( ! entity.pParser )
434 throw SAXException(u"Couldn't create parser"_ustr,
435 css::uno::Reference< css::uno::XInterface > (), css::uno::Any() );
438 // set all necessary C-Callbacks
439 XML_SetUserData( entity.pParser, m_pImpl.get() );
440 XML_SetElementHandler( entity.pParser ,
441 call_callbackStartElement ,
442 call_callbackEndElement );
443 XML_SetCharacterDataHandler( entity.pParser , call_callbackCharacters );
444 XML_SetProcessingInstructionHandler(entity.pParser ,
445 call_callbackProcessingInstruction );
446 if (!m_pImpl->m_bEnableDoS)
448 XML_SetEntityDeclHandler(entity.pParser, call_callbackEntityDecl);
450 XML_SetNotationDeclHandler( entity.pParser, call_callbackNotationDecl );
451 XML_SetExternalEntityRefHandler( entity.pParser,
452 call_callbackExternalEntityRef);
453 XML_SetUnknownEncodingHandler( entity.pParser, call_callbackUnknownEncoding ,nullptr);
455 if( m_pImpl->rExtendedDocumentHandler.is() ) {
457 // These handlers just delegate calls to the ExtendedHandler. If no extended handler is
458 // given, these callbacks can be ignored
459 XML_SetDefaultHandlerExpand( entity.pParser, call_callbackDefault );
460 XML_SetCommentHandler( entity.pParser, call_callbackComment );
461 XML_SetCdataSectionHandler( entity.pParser ,
462 call_callbackStartCDATA ,
463 call_callbackEndCDATA );
467 m_pImpl->exception = SAXParseException();
468 auto const xmlParser = entity.pParser;
469 m_pImpl->pushEntity( std::move(entity) );
471 ParserCleanup aEnsureFree(*m_pImpl, xmlParser);
473 // start the document
474 if( m_pImpl->rDocumentHandler.is() ) {
475 m_pImpl->rDocumentHandler->setDocumentLocator( m_pImpl->rDocumentLocator );
476 m_pImpl->rDocumentHandler->startDocument();
479 m_pImpl->parse();
481 // finish document
482 if( m_pImpl->rDocumentHandler.is() ) {
483 m_pImpl->rDocumentHandler->endDocument();
487 void SaxExpatParser::setDocumentHandler(const css::uno::Reference< XDocumentHandler > & xHandler)
489 m_pImpl->rDocumentHandler = xHandler;
490 m_pImpl->rExtendedDocumentHandler =
491 css::uno::Reference< XExtendedDocumentHandler >( xHandler , css::uno::UNO_QUERY );
494 void SaxExpatParser::setErrorHandler(const css::uno::Reference< XErrorHandler > & xHandler)
496 m_pImpl->rErrorHandler = xHandler;
499 void SaxExpatParser::setDTDHandler(const css::uno::Reference< XDTDHandler > & xHandler)
501 m_pImpl->rDTDHandler = xHandler;
504 void SaxExpatParser::setEntityResolver(const css::uno::Reference < XEntityResolver > & xResolver)
506 m_pImpl->rEntityResolver = xResolver;
510 void SaxExpatParser::setLocale( const Locale & )
512 // not implemented
515 // XServiceInfo
516 OUString SaxExpatParser::getImplementationName()
518 return u"com.sun.star.comp.extensions.xml.sax.ParserExpat"_ustr;
521 // XServiceInfo
522 sal_Bool SaxExpatParser::supportsService(const OUString& ServiceName)
524 return cppu::supportsService(this, ServiceName);
527 // XServiceInfo
528 css::uno::Sequence< OUString > SaxExpatParser::getSupportedServiceNames()
530 return { u"com.sun.star.xml.sax.Parser"_ustr };
534 /*---------------------------------------
536 * Helper functions and classes
539 *-------------------------------------------*/
540 OUString getErrorMessage( XML_Error xmlE, std::u16string_view sSystemId , sal_Int32 nLine )
542 OUString Message;
543 if( XML_ERROR_NONE == xmlE ) {
544 Message = "No";
546 else if( XML_ERROR_NO_MEMORY == xmlE ) {
547 Message = "no memory";
549 else if( XML_ERROR_SYNTAX == xmlE ) {
550 Message = "syntax";
552 else if( XML_ERROR_NO_ELEMENTS == xmlE ) {
553 Message = "no elements";
555 else if( XML_ERROR_INVALID_TOKEN == xmlE ) {
556 Message = "invalid token";
558 else if( XML_ERROR_UNCLOSED_TOKEN == xmlE ) {
559 Message = "unclosed token";
561 else if( XML_ERROR_PARTIAL_CHAR == xmlE ) {
562 Message = "partial char";
564 else if( XML_ERROR_TAG_MISMATCH == xmlE ) {
565 Message = "tag mismatch";
567 else if( XML_ERROR_DUPLICATE_ATTRIBUTE == xmlE ) {
568 Message = "duplicate attribute";
570 else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT == xmlE ) {
571 Message = "junk after doc element";
573 else if( XML_ERROR_PARAM_ENTITY_REF == xmlE ) {
574 Message = "parameter entity reference";
576 else if( XML_ERROR_UNDEFINED_ENTITY == xmlE ) {
577 Message = "undefined entity";
579 else if( XML_ERROR_RECURSIVE_ENTITY_REF == xmlE ) {
580 Message = "recursive entity reference";
582 else if( XML_ERROR_ASYNC_ENTITY == xmlE ) {
583 Message = "async entity";
585 else if( XML_ERROR_BAD_CHAR_REF == xmlE ) {
586 Message = "bad char reference";
588 else if( XML_ERROR_BINARY_ENTITY_REF == xmlE ) {
589 Message = "binary entity reference";
591 else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF == xmlE ) {
592 Message = "attribute external entity reference";
594 else if( XML_ERROR_MISPLACED_XML_PI == xmlE ) {
595 Message = "misplaced xml processing instruction";
597 else if( XML_ERROR_UNKNOWN_ENCODING == xmlE ) {
598 Message = "unknown encoding";
600 else if( XML_ERROR_INCORRECT_ENCODING == xmlE ) {
601 Message = "incorrect encoding";
603 else if( XML_ERROR_UNCLOSED_CDATA_SECTION == xmlE ) {
604 Message = "unclosed cdata section";
606 else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING == xmlE ) {
607 Message = "external entity reference";
609 else if( XML_ERROR_NOT_STANDALONE == xmlE ) {
610 Message = "not standalone";
613 OUString str = OUString::Concat("[") +
614 sSystemId +
615 " line " +
616 OUString::number( nLine ) +
617 "]: " +
618 Message +
619 "error";
621 return str;
625 // starts parsing with actual parser !
626 void SaxExpatParser_Impl::parse( )
628 const int nBufSize = 16*1024;
630 int nRead = nBufSize;
631 css::uno::Sequence< sal_Int8 > seqOut(nBufSize);
633 while( nRead ) {
634 nRead = getEntity().converter.readAndConvert( seqOut , nBufSize );
636 bool bContinue(false);
638 if( ! nRead ) {
639 // last call - must return OK
640 XML_Status const ret = XML_Parse( getEntity().pParser,
641 reinterpret_cast<const char *>(seqOut.getConstArray()),
643 1 );
644 if (ret == XML_STATUS_OK) {
645 break;
647 } else {
648 bContinue = ( XML_Parse( getEntity().pParser,
649 reinterpret_cast<const char *>(seqOut.getConstArray()),
650 nRead,
651 0 ) != XML_STATUS_ERROR );
654 if( ! bContinue || bExceptionWasThrown ) {
656 if ( bRTExceptionWasThrown )
657 throw rtexception;
659 // Error during parsing !
660 XML_Error xmlE = XML_GetErrorCode( getEntity().pParser );
661 OUString sSystemId = rDocumentLocator->getSystemId();
662 sal_Int32 nLine = rDocumentLocator->getLineNumber();
664 SAXParseException aExcept(
665 getErrorMessage(xmlE , sSystemId, nLine) ,
666 css::uno::Reference< css::uno::XInterface >(),
667 css::uno::Any( &exception , cppu::UnoType<decltype(exception)>::get() ),
668 rDocumentLocator->getPublicId(),
669 rDocumentLocator->getSystemId(),
670 rDocumentLocator->getLineNumber(),
671 rDocumentLocator->getColumnNumber()
674 if( rErrorHandler.is() ) {
676 // error handler is set, so the handler may throw the exception
677 css::uno::Any a;
678 a <<= aExcept;
679 rErrorHandler->fatalError( a );
682 // Error handler has not thrown an exception, but parsing cannot go on,
683 // so an exception MUST be thrown.
684 throw aExcept;
685 } // if( ! bContinue )
686 } // while
690 // The C-Callbacks
693 void SaxExpatParser_Impl::callbackStartElement( void *pvThis ,
694 const XML_Char *pwName ,
695 const XML_Char **awAttributes )
697 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
699 if( !pImpl->rDocumentHandler.is() )
700 return;
702 int i = 0;
703 pImpl->rAttrList->Clear();
705 while( awAttributes[i] ) {
706 assert(awAttributes[i+1]);
707 pImpl->rAttrList->AddAttribute(
708 XML_CHAR_TO_OUSTRING( awAttributes[i] ) ,
709 XML_CHAR_TO_OUSTRING( awAttributes[i+1] ) );
710 i +=2;
713 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
714 pImpl ,
715 rDocumentHandler->startElement( XML_CHAR_TO_OUSTRING( pwName ) ,
716 pImpl->rAttrList ) );
719 void SaxExpatParser_Impl::callbackEndElement( void *pvThis , const XML_Char *pwName )
721 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
723 if( pImpl->rDocumentHandler.is() ) {
724 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
725 rDocumentHandler->endElement( XML_CHAR_TO_OUSTRING( pwName ) ) );
730 void SaxExpatParser_Impl::callbackCharacters( void *pvThis , const XML_Char *s , int nLen )
732 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
734 if( pImpl->rDocumentHandler.is() ) {
735 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl ,
736 rDocumentHandler->characters( XML_CHAR_N_TO_USTRING(s,nLen) ) );
740 void SaxExpatParser_Impl::callbackProcessingInstruction( void *pvThis,
741 const XML_Char *sTarget ,
742 const XML_Char *sData )
744 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
745 if( pImpl->rDocumentHandler.is() ) {
746 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
747 pImpl ,
748 rDocumentHandler->processingInstruction( XML_CHAR_TO_OUSTRING( sTarget ),
749 XML_CHAR_TO_OUSTRING( sData ) ) );
754 void SaxExpatParser_Impl::callbackEntityDecl(
755 void *pvThis, const XML_Char *entityName,
756 SAL_UNUSED_PARAMETER int /*is_parameter_entity*/,
757 const XML_Char *value, SAL_UNUSED_PARAMETER int /*value_length*/,
758 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
759 const XML_Char *publicId, const XML_Char *notationName)
761 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
762 if (value) { // value != 0 means internal entity
763 SAL_INFO("sax","SaxExpatParser: internal entity declaration, stopping");
764 XML_StopParser(pImpl->getEntity().pParser, XML_FALSE);
765 pImpl->exception = SAXParseException(
766 u"SaxExpatParser: internal entity declaration, stopping"_ustr,
767 nullptr, css::uno::Any(),
768 pImpl->rDocumentLocator->getPublicId(),
769 pImpl->rDocumentLocator->getSystemId(),
770 pImpl->rDocumentLocator->getLineNumber(),
771 pImpl->rDocumentLocator->getColumnNumber() );
772 pImpl->bExceptionWasThrown = true;
773 } else {
774 if( pImpl->rDTDHandler.is() ) {
775 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
776 pImpl ,
777 rDTDHandler->unparsedEntityDecl(
778 XML_CHAR_TO_OUSTRING( entityName ),
779 XML_CHAR_TO_OUSTRING( publicId ) ,
780 XML_CHAR_TO_OUSTRING( systemId ) ,
781 XML_CHAR_TO_OUSTRING( notationName ) ) );
786 void SaxExpatParser_Impl::callbackNotationDecl(
787 void *pvThis, const XML_Char *notationName,
788 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
789 const XML_Char *publicId)
791 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
792 if( pImpl->rDTDHandler.is() ) {
793 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
794 rDTDHandler->notationDecl( XML_CHAR_TO_OUSTRING( notationName ) ,
795 XML_CHAR_TO_OUSTRING( publicId ) ,
796 XML_CHAR_TO_OUSTRING( systemId ) ) );
802 bool SaxExpatParser_Impl::callbackExternalEntityRef(
803 XML_Parser parser, const XML_Char *context,
804 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
805 const XML_Char *publicId)
807 bool bOK = true;
808 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(XML_GetUserData( parser ));
810 struct Entity entity;
812 if( pImpl->rEntityResolver.is() ) {
815 entity.structSource = pImpl->rEntityResolver->resolveEntity(
816 XML_CHAR_TO_OUSTRING( publicId ) ,
817 XML_CHAR_TO_OUSTRING( systemId ) );
819 catch( const SAXParseException & e )
821 pImpl->exception = e;
822 bOK = false;
824 catch( const SAXException & e )
826 pImpl->exception = SAXParseException(
827 e.Message , e.Context , e.WrappedException ,
828 pImpl->rDocumentLocator->getPublicId(),
829 pImpl->rDocumentLocator->getSystemId(),
830 pImpl->rDocumentLocator->getLineNumber(),
831 pImpl->rDocumentLocator->getColumnNumber() );
832 bOK = false;
836 if( entity.structSource.aInputStream.is() ) {
837 entity.pParser = XML_ExternalEntityParserCreate( parser , context, nullptr );
838 if( ! entity.pParser )
840 return false;
843 entity.converter.setInputStream( entity.structSource.aInputStream );
844 auto const xmlParser = entity.pParser;
845 pImpl->pushEntity( std::move(entity) );
848 pImpl->parse();
850 catch( const SAXParseException & e )
852 pImpl->exception = e;
853 bOK = false;
855 catch( const IOException &e )
857 pImpl->exception.WrappedException <<= e;
858 bOK = false;
860 catch( const css::uno::RuntimeException &e )
862 pImpl->exception.WrappedException <<=e;
863 bOK = false;
866 pImpl->popEntity();
868 XML_ParserFree( xmlParser );
871 return bOK;
874 int SaxExpatParser_Impl::callbackUnknownEncoding(
875 SAL_UNUSED_PARAMETER void * /*encodingHandlerData*/,
876 SAL_UNUSED_PARAMETER const XML_Char * /*name*/,
877 SAL_UNUSED_PARAMETER XML_Encoding * /*info*/)
879 return 0;
882 void SaxExpatParser_Impl::callbackDefault( void *pvThis, const XML_Char *s, int len)
884 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
886 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
887 rExtendedDocumentHandler->unknown( XML_CHAR_N_TO_USTRING( s ,len) ) );
890 void SaxExpatParser_Impl::callbackComment( void *pvThis , const XML_Char *s )
892 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
893 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
894 rExtendedDocumentHandler->comment( XML_CHAR_TO_OUSTRING( s ) ) );
897 void SaxExpatParser_Impl::callbackStartCDATA( void *pvThis )
899 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
901 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, rExtendedDocumentHandler->startCDATA() );
905 void SaxExpatParser_Impl::callErrorHandler( SaxExpatParser_Impl *pImpl ,
906 const SAXParseException & e )
910 if( pImpl->rErrorHandler.is() ) {
911 css::uno::Any a;
912 a <<= e;
913 pImpl->rErrorHandler->error( a );
915 else {
916 pImpl->exception = e;
917 pImpl->bExceptionWasThrown = true;
920 catch( const SAXParseException & ex ) {
921 pImpl->exception = ex;
922 pImpl->bExceptionWasThrown = true;
924 catch( const SAXException & ex ) {
925 pImpl->exception = SAXParseException(
926 ex.Message,
927 ex.Context,
928 ex.WrappedException,
929 pImpl->rDocumentLocator->getPublicId(),
930 pImpl->rDocumentLocator->getSystemId(),
931 pImpl->rDocumentLocator->getLineNumber(),
932 pImpl->rDocumentLocator->getColumnNumber()
934 pImpl->bExceptionWasThrown = true;
938 void SaxExpatParser_Impl::callbackEndCDATA( void *pvThis )
940 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
942 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pImpl,rExtendedDocumentHandler->endCDATA() );
945 } // namespace
947 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
948 com_sun_star_comp_extensions_xml_sax_ParserExpat_get_implementation(
949 css::uno::XComponentContext *,
950 css::uno::Sequence<css::uno::Any> const &)
952 return cppu::acquire(new SaxExpatParser);
955 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */