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 css::uno::Reference
< XLocator
> 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 rtl::Reference
<LocatorImpl
> pLoc
= new LocatorImpl( m_pImpl
.get() );
358 m_pImpl
->rDocumentLocator
= pLoc
;
360 // Performance-improvement; handing out the same object with every call of
361 // the startElement callback is allowed (see sax-specification):
362 m_pImpl
->rAttrList
= new comphelper::AttributeList
;
364 m_pImpl
->bExceptionWasThrown
= false;
365 m_pImpl
->bRTExceptionWasThrown
= false;
368 // css::lang::XInitialization:
370 SaxExpatParser::initialize(css::uno::Sequence
< css::uno::Any
> const& rArguments
)
372 // possible arguments: a string "DoSmeplease"
373 if (rArguments
.hasElements())
376 if ((rArguments
[0] >>= str
) && "DoSmeplease" == str
)
378 std::unique_lock
guard( m_pImpl
->aMutex
);
379 m_pImpl
->m_bEnableDoS
= true;
387 SaxExpatParser_Impl
& m_rParser
;
388 XML_Parser m_xmlParser
;
390 ParserCleanup(SaxExpatParser_Impl
& rParser
, XML_Parser xmlParser
)
392 , m_xmlParser(xmlParser
)
397 m_rParser
.popEntity();
398 //XML_ParserFree accepts a null arg
399 XML_ParserFree(m_xmlParser
);
405 * parseStream does Parser-startup initializations. The SaxExpatParser_Impl::parse() method does
406 * the file-specific initialization work. (During a parser run, external files may be opened)
409 void SaxExpatParser::parseStream( const InputSource
& structSource
)
411 // Only one text at one time
412 std::unique_lock
guard( m_pImpl
->aMutex
);
415 struct Entity entity
;
416 entity
.structSource
= structSource
;
418 if( ! entity
.structSource
.aInputStream
.is() )
420 throw SAXException("No input source",
421 css::uno::Reference
< css::uno::XInterface
> () , css::uno::Any() );
424 entity
.converter
.setInputStream( entity
.structSource
.aInputStream
);
425 if( !entity
.structSource
.sEncoding
.isEmpty() )
427 entity
.converter
.setEncoding(
428 OUStringToOString( entity
.structSource
.sEncoding
, RTL_TEXTENCODING_ASCII_US
) );
431 // create parser with proper encoding
432 entity
.pParser
= XML_ParserCreate( nullptr );
433 if( ! entity
.pParser
)
435 throw SAXException("Couldn't create parser",
436 css::uno::Reference
< css::uno::XInterface
> (), css::uno::Any() );
439 // set all necessary C-Callbacks
440 XML_SetUserData( entity
.pParser
, m_pImpl
.get() );
441 XML_SetElementHandler( entity
.pParser
,
442 call_callbackStartElement
,
443 call_callbackEndElement
);
444 XML_SetCharacterDataHandler( entity
.pParser
, call_callbackCharacters
);
445 XML_SetProcessingInstructionHandler(entity
.pParser
,
446 call_callbackProcessingInstruction
);
447 if (!m_pImpl
->m_bEnableDoS
)
449 XML_SetEntityDeclHandler(entity
.pParser
, call_callbackEntityDecl
);
451 XML_SetNotationDeclHandler( entity
.pParser
, call_callbackNotationDecl
);
452 XML_SetExternalEntityRefHandler( entity
.pParser
,
453 call_callbackExternalEntityRef
);
454 XML_SetUnknownEncodingHandler( entity
.pParser
, call_callbackUnknownEncoding
,nullptr);
456 if( m_pImpl
->rExtendedDocumentHandler
.is() ) {
458 // These handlers just delegate calls to the ExtendedHandler. If no extended handler is
459 // given, these callbacks can be ignored
460 XML_SetDefaultHandlerExpand( entity
.pParser
, call_callbackDefault
);
461 XML_SetCommentHandler( entity
.pParser
, call_callbackComment
);
462 XML_SetCdataSectionHandler( entity
.pParser
,
463 call_callbackStartCDATA
,
464 call_callbackEndCDATA
);
468 m_pImpl
->exception
= SAXParseException();
469 auto const xmlParser
= entity
.pParser
;
470 m_pImpl
->pushEntity( std::move(entity
) );
472 ParserCleanup
aEnsureFree(*m_pImpl
, xmlParser
);
474 // start the document
475 if( m_pImpl
->rDocumentHandler
.is() ) {
476 m_pImpl
->rDocumentHandler
->setDocumentLocator( m_pImpl
->rDocumentLocator
);
477 m_pImpl
->rDocumentHandler
->startDocument();
483 if( m_pImpl
->rDocumentHandler
.is() ) {
484 m_pImpl
->rDocumentHandler
->endDocument();
488 void SaxExpatParser::setDocumentHandler(const css::uno::Reference
< XDocumentHandler
> & xHandler
)
490 m_pImpl
->rDocumentHandler
= xHandler
;
491 m_pImpl
->rExtendedDocumentHandler
=
492 css::uno::Reference
< XExtendedDocumentHandler
>( xHandler
, css::uno::UNO_QUERY
);
495 void SaxExpatParser::setErrorHandler(const css::uno::Reference
< XErrorHandler
> & xHandler
)
497 m_pImpl
->rErrorHandler
= xHandler
;
500 void SaxExpatParser::setDTDHandler(const css::uno::Reference
< XDTDHandler
> & xHandler
)
502 m_pImpl
->rDTDHandler
= xHandler
;
505 void SaxExpatParser::setEntityResolver(const css::uno::Reference
< XEntityResolver
> & xResolver
)
507 m_pImpl
->rEntityResolver
= xResolver
;
511 void SaxExpatParser::setLocale( const Locale
& )
517 OUString
SaxExpatParser::getImplementationName()
519 return "com.sun.star.comp.extensions.xml.sax.ParserExpat";
523 sal_Bool
SaxExpatParser::supportsService(const OUString
& ServiceName
)
525 return cppu::supportsService(this, ServiceName
);
529 css::uno::Sequence
< OUString
> SaxExpatParser::getSupportedServiceNames()
531 return { "com.sun.star.xml.sax.Parser" };
535 /*---------------------------------------
537 * Helper functions and classes
540 *-------------------------------------------*/
541 OUString
getErrorMessage( XML_Error xmlE
, std::u16string_view sSystemId
, sal_Int32 nLine
)
544 if( XML_ERROR_NONE
== xmlE
) {
547 else if( XML_ERROR_NO_MEMORY
== xmlE
) {
548 Message
= "no memory";
550 else if( XML_ERROR_SYNTAX
== xmlE
) {
553 else if( XML_ERROR_NO_ELEMENTS
== xmlE
) {
554 Message
= "no elements";
556 else if( XML_ERROR_INVALID_TOKEN
== xmlE
) {
557 Message
= "invalid token";
559 else if( XML_ERROR_UNCLOSED_TOKEN
== xmlE
) {
560 Message
= "unclosed token";
562 else if( XML_ERROR_PARTIAL_CHAR
== xmlE
) {
563 Message
= "partial char";
565 else if( XML_ERROR_TAG_MISMATCH
== xmlE
) {
566 Message
= "tag mismatch";
568 else if( XML_ERROR_DUPLICATE_ATTRIBUTE
== xmlE
) {
569 Message
= "duplicate attribute";
571 else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT
== xmlE
) {
572 Message
= "junk after doc element";
574 else if( XML_ERROR_PARAM_ENTITY_REF
== xmlE
) {
575 Message
= "parameter entity reference";
577 else if( XML_ERROR_UNDEFINED_ENTITY
== xmlE
) {
578 Message
= "undefined entity";
580 else if( XML_ERROR_RECURSIVE_ENTITY_REF
== xmlE
) {
581 Message
= "recursive entity reference";
583 else if( XML_ERROR_ASYNC_ENTITY
== xmlE
) {
584 Message
= "async entity";
586 else if( XML_ERROR_BAD_CHAR_REF
== xmlE
) {
587 Message
= "bad char reference";
589 else if( XML_ERROR_BINARY_ENTITY_REF
== xmlE
) {
590 Message
= "binary entity reference";
592 else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF
== xmlE
) {
593 Message
= "attribute external entity reference";
595 else if( XML_ERROR_MISPLACED_XML_PI
== xmlE
) {
596 Message
= "misplaced xml processing instruction";
598 else if( XML_ERROR_UNKNOWN_ENCODING
== xmlE
) {
599 Message
= "unknown encoding";
601 else if( XML_ERROR_INCORRECT_ENCODING
== xmlE
) {
602 Message
= "incorrect encoding";
604 else if( XML_ERROR_UNCLOSED_CDATA_SECTION
== xmlE
) {
605 Message
= "unclosed cdata section";
607 else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING
== xmlE
) {
608 Message
= "external entity reference";
610 else if( XML_ERROR_NOT_STANDALONE
== xmlE
) {
611 Message
= "not standalone";
614 OUString str
= OUString::Concat("[") +
617 OUString::number( nLine
) +
626 // starts parsing with actual parser !
627 void SaxExpatParser_Impl::parse( )
629 const int nBufSize
= 16*1024;
631 int nRead
= nBufSize
;
632 css::uno::Sequence
< sal_Int8
> seqOut(nBufSize
);
635 nRead
= getEntity().converter
.readAndConvert( seqOut
, nBufSize
);
637 bool bContinue(false);
640 // last call - must return OK
641 XML_Status
const ret
= XML_Parse( getEntity().pParser
,
642 reinterpret_cast<const char *>(seqOut
.getConstArray()),
645 if (ret
== XML_STATUS_OK
) {
649 bContinue
= ( XML_Parse( getEntity().pParser
,
650 reinterpret_cast<const char *>(seqOut
.getConstArray()),
652 0 ) != XML_STATUS_ERROR
);
655 if( ! bContinue
|| bExceptionWasThrown
) {
657 if ( bRTExceptionWasThrown
)
660 // Error during parsing !
661 XML_Error xmlE
= XML_GetErrorCode( getEntity().pParser
);
662 OUString sSystemId
= rDocumentLocator
->getSystemId();
663 sal_Int32 nLine
= rDocumentLocator
->getLineNumber();
665 SAXParseException
aExcept(
666 getErrorMessage(xmlE
, sSystemId
, nLine
) ,
667 css::uno::Reference
< css::uno::XInterface
>(),
668 css::uno::Any( &exception
, cppu::UnoType
<decltype(exception
)>::get() ),
669 rDocumentLocator
->getPublicId(),
670 rDocumentLocator
->getSystemId(),
671 rDocumentLocator
->getLineNumber(),
672 rDocumentLocator
->getColumnNumber()
675 if( rErrorHandler
.is() ) {
677 // error handler is set, so the handler may throw the exception
680 rErrorHandler
->fatalError( a
);
683 // Error handler has not thrown an exception, but parsing cannot go on,
684 // so an exception MUST be thrown.
686 } // if( ! bContinue )
694 void SaxExpatParser_Impl::callbackStartElement( void *pvThis
,
695 const XML_Char
*pwName
,
696 const XML_Char
**awAttributes
)
698 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
700 if( !pImpl
->rDocumentHandler
.is() )
704 pImpl
->rAttrList
->Clear();
706 while( awAttributes
[i
] ) {
707 assert(awAttributes
[i
+1]);
708 pImpl
->rAttrList
->AddAttribute(
709 XML_CHAR_TO_OUSTRING( awAttributes
[i
] ) ,
710 XML_CHAR_TO_OUSTRING( awAttributes
[i
+1] ) );
714 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
716 rDocumentHandler
->startElement( XML_CHAR_TO_OUSTRING( pwName
) ,
717 pImpl
->rAttrList
) );
720 void SaxExpatParser_Impl::callbackEndElement( void *pvThis
, const XML_Char
*pwName
)
722 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
724 if( pImpl
->rDocumentHandler
.is() ) {
725 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl
,
726 rDocumentHandler
->endElement( XML_CHAR_TO_OUSTRING( pwName
) ) );
731 void SaxExpatParser_Impl::callbackCharacters( void *pvThis
, const XML_Char
*s
, int nLen
)
733 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
735 if( pImpl
->rDocumentHandler
.is() ) {
736 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl
,
737 rDocumentHandler
->characters( XML_CHAR_N_TO_USTRING(s
,nLen
) ) );
741 void SaxExpatParser_Impl::callbackProcessingInstruction( void *pvThis
,
742 const XML_Char
*sTarget
,
743 const XML_Char
*sData
)
745 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
746 if( pImpl
->rDocumentHandler
.is() ) {
747 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
749 rDocumentHandler
->processingInstruction( XML_CHAR_TO_OUSTRING( sTarget
),
750 XML_CHAR_TO_OUSTRING( sData
) ) );
755 void SaxExpatParser_Impl::callbackEntityDecl(
756 void *pvThis
, const XML_Char
*entityName
,
757 SAL_UNUSED_PARAMETER
int /*is_parameter_entity*/,
758 const XML_Char
*value
, SAL_UNUSED_PARAMETER
int /*value_length*/,
759 SAL_UNUSED_PARAMETER
const XML_Char
* /*base*/, const XML_Char
*systemId
,
760 const XML_Char
*publicId
, const XML_Char
*notationName
)
762 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
763 if (value
) { // value != 0 means internal entity
764 SAL_INFO("sax","SaxExpatParser: internal entity declaration, stopping");
765 XML_StopParser(pImpl
->getEntity().pParser
, XML_FALSE
);
766 pImpl
->exception
= SAXParseException(
767 "SaxExpatParser: internal entity declaration, stopping",
768 nullptr, css::uno::Any(),
769 pImpl
->rDocumentLocator
->getPublicId(),
770 pImpl
->rDocumentLocator
->getSystemId(),
771 pImpl
->rDocumentLocator
->getLineNumber(),
772 pImpl
->rDocumentLocator
->getColumnNumber() );
773 pImpl
->bExceptionWasThrown
= true;
775 if( pImpl
->rDTDHandler
.is() ) {
776 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
778 rDTDHandler
->unparsedEntityDecl(
779 XML_CHAR_TO_OUSTRING( entityName
),
780 XML_CHAR_TO_OUSTRING( publicId
) ,
781 XML_CHAR_TO_OUSTRING( systemId
) ,
782 XML_CHAR_TO_OUSTRING( notationName
) ) );
787 void SaxExpatParser_Impl::callbackNotationDecl(
788 void *pvThis
, const XML_Char
*notationName
,
789 SAL_UNUSED_PARAMETER
const XML_Char
* /*base*/, const XML_Char
*systemId
,
790 const XML_Char
*publicId
)
792 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
793 if( pImpl
->rDTDHandler
.is() ) {
794 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl
,
795 rDTDHandler
->notationDecl( XML_CHAR_TO_OUSTRING( notationName
) ,
796 XML_CHAR_TO_OUSTRING( publicId
) ,
797 XML_CHAR_TO_OUSTRING( systemId
) ) );
803 bool SaxExpatParser_Impl::callbackExternalEntityRef(
804 XML_Parser parser
, const XML_Char
*context
,
805 SAL_UNUSED_PARAMETER
const XML_Char
* /*base*/, const XML_Char
*systemId
,
806 const XML_Char
*publicId
)
809 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(XML_GetUserData( parser
));
811 struct Entity entity
;
813 if( pImpl
->rEntityResolver
.is() ) {
816 entity
.structSource
= pImpl
->rEntityResolver
->resolveEntity(
817 XML_CHAR_TO_OUSTRING( publicId
) ,
818 XML_CHAR_TO_OUSTRING( systemId
) );
820 catch( const SAXParseException
& e
)
822 pImpl
->exception
= e
;
825 catch( const SAXException
& e
)
827 pImpl
->exception
= SAXParseException(
828 e
.Message
, e
.Context
, e
.WrappedException
,
829 pImpl
->rDocumentLocator
->getPublicId(),
830 pImpl
->rDocumentLocator
->getSystemId(),
831 pImpl
->rDocumentLocator
->getLineNumber(),
832 pImpl
->rDocumentLocator
->getColumnNumber() );
837 if( entity
.structSource
.aInputStream
.is() ) {
838 entity
.pParser
= XML_ExternalEntityParserCreate( parser
, context
, nullptr );
839 if( ! entity
.pParser
)
844 entity
.converter
.setInputStream( entity
.structSource
.aInputStream
);
845 auto const xmlParser
= entity
.pParser
;
846 pImpl
->pushEntity( std::move(entity
) );
851 catch( const SAXParseException
& e
)
853 pImpl
->exception
= e
;
856 catch( const IOException
&e
)
858 pImpl
->exception
.WrappedException
<<= e
;
861 catch( const css::uno::RuntimeException
&e
)
863 pImpl
->exception
.WrappedException
<<=e
;
869 XML_ParserFree( xmlParser
);
875 int SaxExpatParser_Impl::callbackUnknownEncoding(
876 SAL_UNUSED_PARAMETER
void * /*encodingHandlerData*/,
877 SAL_UNUSED_PARAMETER
const XML_Char
* /*name*/,
878 SAL_UNUSED_PARAMETER XML_Encoding
* /*info*/)
883 void SaxExpatParser_Impl::callbackDefault( void *pvThis
, const XML_Char
*s
, int len
)
885 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
887 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl
,
888 rExtendedDocumentHandler
->unknown( XML_CHAR_N_TO_USTRING( s
,len
) ) );
891 void SaxExpatParser_Impl::callbackComment( void *pvThis
, const XML_Char
*s
)
893 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
894 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl
,
895 rExtendedDocumentHandler
->comment( XML_CHAR_TO_OUSTRING( s
) ) );
898 void SaxExpatParser_Impl::callbackStartCDATA( void *pvThis
)
900 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
902 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl
, rExtendedDocumentHandler
->startCDATA() );
906 void SaxExpatParser_Impl::callErrorHandler( SaxExpatParser_Impl
*pImpl
,
907 const SAXParseException
& e
)
911 if( pImpl
->rErrorHandler
.is() ) {
914 pImpl
->rErrorHandler
->error( a
);
917 pImpl
->exception
= e
;
918 pImpl
->bExceptionWasThrown
= true;
921 catch( const SAXParseException
& ex
) {
922 pImpl
->exception
= ex
;
923 pImpl
->bExceptionWasThrown
= true;
925 catch( const SAXException
& ex
) {
926 pImpl
->exception
= SAXParseException(
930 pImpl
->rDocumentLocator
->getPublicId(),
931 pImpl
->rDocumentLocator
->getSystemId(),
932 pImpl
->rDocumentLocator
->getLineNumber(),
933 pImpl
->rDocumentLocator
->getColumnNumber()
935 pImpl
->bExceptionWasThrown
= true;
939 void SaxExpatParser_Impl::callbackEndCDATA( void *pvThis
)
941 SaxExpatParser_Impl
*pImpl
= static_cast<SaxExpatParser_Impl
*>(pvThis
);
943 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pImpl
,rExtendedDocumentHandler
->endCDATA() );
948 extern "C" SAL_DLLPUBLIC_EXPORT
css::uno::XInterface
*
949 com_sun_star_comp_extensions_xml_sax_ParserExpat_get_implementation(
950 css::uno::XComponentContext
*,
951 css::uno::Sequence
<css::uno::Any
> const &)
953 return cppu::acquire(new SaxExpatParser
);
956 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */