Extended loplugin:ostr manual changes
[LibreOffice.git] / sax / source / expatwrap / sax_expat.cxx
blobf004b94eadcb44aa4e48cd80995f700d525c5502
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;
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 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) ); }
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 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:
369 void SAL_CALL
370 SaxExpatParser::initialize(css::uno::Sequence< css::uno::Any > const& rArguments)
372 // possible arguments: a string "DoSmeplease"
373 if (rArguments.hasElements())
375 OUString str;
376 if ((rArguments[0] >>= str) && "DoSmeplease" == str)
378 std::unique_lock guard( m_pImpl->aMutex );
379 m_pImpl->m_bEnableDoS = true;
384 class ParserCleanup
386 private:
387 SaxExpatParser_Impl& m_rParser;
388 XML_Parser m_xmlParser;
389 public:
390 ParserCleanup(SaxExpatParser_Impl& rParser, XML_Parser xmlParser)
391 : m_rParser(rParser)
392 , m_xmlParser(xmlParser)
395 ~ParserCleanup()
397 m_rParser.popEntity();
398 //XML_ParserFree accepts a null arg
399 XML_ParserFree(m_xmlParser);
403 /***************
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)
408 ****************/
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();
480 m_pImpl->parse();
482 // finish document
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 & )
513 // not implemented
516 // XServiceInfo
517 OUString SaxExpatParser::getImplementationName()
519 return "com.sun.star.comp.extensions.xml.sax.ParserExpat";
522 // XServiceInfo
523 sal_Bool SaxExpatParser::supportsService(const OUString& ServiceName)
525 return cppu::supportsService(this, ServiceName);
528 // XServiceInfo
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 )
543 OUString Message;
544 if( XML_ERROR_NONE == xmlE ) {
545 Message = "No";
547 else if( XML_ERROR_NO_MEMORY == xmlE ) {
548 Message = "no memory";
550 else if( XML_ERROR_SYNTAX == xmlE ) {
551 Message = "syntax";
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("[") +
615 sSystemId +
616 " line " +
617 OUString::number( nLine ) +
618 "]: " +
619 Message +
620 "error";
622 return str;
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);
634 while( nRead ) {
635 nRead = getEntity().converter.readAndConvert( seqOut , nBufSize );
637 bool bContinue(false);
639 if( ! nRead ) {
640 // last call - must return OK
641 XML_Status const ret = XML_Parse( getEntity().pParser,
642 reinterpret_cast<const char *>(seqOut.getConstArray()),
644 1 );
645 if (ret == XML_STATUS_OK) {
646 break;
648 } else {
649 bContinue = ( XML_Parse( getEntity().pParser,
650 reinterpret_cast<const char *>(seqOut.getConstArray()),
651 nRead,
652 0 ) != XML_STATUS_ERROR );
655 if( ! bContinue || bExceptionWasThrown ) {
657 if ( bRTExceptionWasThrown )
658 throw rtexception;
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
678 css::uno::Any a;
679 a <<= aExcept;
680 rErrorHandler->fatalError( a );
683 // Error handler has not thrown an exception, but parsing cannot go on,
684 // so an exception MUST be thrown.
685 throw aExcept;
686 } // if( ! bContinue )
687 } // while
691 // The C-Callbacks
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() )
701 return;
703 int i = 0;
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] ) );
711 i +=2;
714 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
715 pImpl ,
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(
748 pImpl ,
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;
774 } else {
775 if( pImpl->rDTDHandler.is() ) {
776 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
777 pImpl ,
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)
808 bool bOK = true;
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;
823 bOK = false;
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() );
833 bOK = false;
837 if( entity.structSource.aInputStream.is() ) {
838 entity.pParser = XML_ExternalEntityParserCreate( parser , context, nullptr );
839 if( ! entity.pParser )
841 return false;
844 entity.converter.setInputStream( entity.structSource.aInputStream );
845 auto const xmlParser = entity.pParser;
846 pImpl->pushEntity( std::move(entity) );
849 pImpl->parse();
851 catch( const SAXParseException & e )
853 pImpl->exception = e;
854 bOK = false;
856 catch( const IOException &e )
858 pImpl->exception.WrappedException <<= e;
859 bOK = false;
861 catch( const css::uno::RuntimeException &e )
863 pImpl->exception.WrappedException <<=e;
864 bOK = false;
867 pImpl->popEntity();
869 XML_ParserFree( xmlParser );
872 return bOK;
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*/)
880 return 0;
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() ) {
912 css::uno::Any a;
913 a <<= e;
914 pImpl->rErrorHandler->error( a );
916 else {
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(
927 ex.Message,
928 ex.Context,
929 ex.WrappedException,
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() );
946 } // namespace
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: */