1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 .
25 #include <string_view>
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>
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
;
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
66 #define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis,call) \
67 if( ! pThis->bExceptionWasThrown ) { \
71 catch( const SAXParseException &e ) {\
72 callErrorHandler( pThis , e );\
74 catch( const SAXException &e ) {\
75 callErrorHandler( pThis , SAXParseException(\
79 pThis->rDocumentLocator->getPublicId(),\
80 pThis->rDocumentLocator->getSystemId(),\
81 pThis->rDocumentLocator->getLineNumber(),\
82 pThis->rDocumentLocator->getColumnNumber()\
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)); \
99 class SaxExpatParser_Impl
;
101 // This class implements the external Parser interface
103 : public WeakImplHelper
< XInitialization
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
;
130 std::unique_ptr
<SaxExpatParser_Impl
> m_pImpl
;
134 // Entity binds all information needed for a single file
137 InputSource structSource
;
139 sax_expatwrap::XMLFile2UTFConverter converter
;
143 class SaxExpatParser_Impl
145 public: // module scope
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
) ); }
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
;
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
,
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
,
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
);
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
,
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
,
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
);
306 public WeakImplHelper
< XLocator
, css::io::XSeekable
>
307 // should use a different interface for stream positions!
310 explicit LocatorImpl(SaxExpatParser_Impl
*p
)
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
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:
369 SaxExpatParser::initialize(css::uno::Sequence
< css::uno::Any
> const& rArguments
)
371 // possible arguments: a string "DoSmeplease"
372 if (rArguments
.hasElements())
375 if ((rArguments
[0] >>= str
) && "DoSmeplease" == str
)
377 std::unique_lock
guard( m_pImpl
->aMutex
);
378 m_pImpl
->m_bEnableDoS
= true;
386 SaxExpatParser_Impl
& m_rParser
;
387 XML_Parser m_xmlParser
;
389 ParserCleanup(SaxExpatParser_Impl
& rParser
, XML_Parser xmlParser
)
391 , m_xmlParser(xmlParser
)
396 m_rParser
.popEntity();
397 //XML_ParserFree accepts a null arg
398 XML_ParserFree(m_xmlParser
);
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)
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();
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
& )
516 OUString
SaxExpatParser::getImplementationName()
518 return u
"com.sun.star.comp.extensions.xml.sax.ParserExpat"_ustr
;
522 sal_Bool
SaxExpatParser::supportsService(const OUString
& ServiceName
)
524 return cppu::supportsService(this, ServiceName
);
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
)
543 if( XML_ERROR_NONE
== xmlE
) {
546 else if( XML_ERROR_NO_MEMORY
== xmlE
) {
547 Message
= "no memory";
549 else if( XML_ERROR_SYNTAX
== xmlE
) {
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("[") +
616 OUString::number( nLine
) +
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
);
634 nRead
= getEntity().converter
.readAndConvert( seqOut
, nBufSize
);
636 bool bContinue(false);
639 // last call - must return OK
640 XML_Status
const ret
= XML_Parse( getEntity().pParser
,
641 reinterpret_cast<const char *>(seqOut
.getConstArray()),
644 if (ret
== XML_STATUS_OK
) {
648 bContinue
= ( XML_Parse( getEntity().pParser
,
649 reinterpret_cast<const char *>(seqOut
.getConstArray()),
651 0 ) != XML_STATUS_ERROR
);
654 if( ! bContinue
|| bExceptionWasThrown
) {
656 if ( bRTExceptionWasThrown
)
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
679 rErrorHandler
->fatalError( a
);
682 // Error handler has not thrown an exception, but parsing cannot go on,
683 // so an exception MUST be thrown.
685 } // if( ! bContinue )
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() )
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] ) );
713 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
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(
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;
774 if( pImpl
->rDTDHandler
.is() ) {
775 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
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
)
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
;
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() );
836 if( entity
.structSource
.aInputStream
.is() ) {
837 entity
.pParser
= XML_ExternalEntityParserCreate( parser
, context
, nullptr );
838 if( ! entity
.pParser
)
843 entity
.converter
.setInputStream( entity
.structSource
.aInputStream
);
844 auto const xmlParser
= entity
.pParser
;
845 pImpl
->pushEntity( std::move(entity
) );
850 catch( const SAXParseException
& e
)
852 pImpl
->exception
= e
;
855 catch( const IOException
&e
)
857 pImpl
->exception
.WrappedException
<<= e
;
860 catch( const css::uno::RuntimeException
&e
)
862 pImpl
->exception
.WrappedException
<<=e
;
868 XML_ParserFree( xmlParser
);
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*/)
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() ) {
913 pImpl
->rErrorHandler
->error( a
);
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(
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() );
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: */