fix baseline build (old cairo) - 'cairo_rectangle_int_t' does not name a type
[LibreOffice.git] / sax / source / expatwrap / sax_expat.cxx
blob8bbfd24fee66bbfbe5c2326e421a9fbe92daf35a
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 .
19 #include <stdlib.h>
20 #include <string.h>
21 #include <sal/alloca.h>
22 #include <cassert>
23 #include <vector>
25 #include <osl/diagnose.h>
27 #include <com/sun/star/lang/XServiceInfo.hpp>
28 #include <com/sun/star/lang/XInitialization.hpp>
29 #include <com/sun/star/uno/XComponentContext.hpp>
30 #include <com/sun/star/xml/sax/XExtendedDocumentHandler.hpp>
31 #include <com/sun/star/xml/sax/XParser.hpp>
32 #include <com/sun/star/xml/sax/SAXParseException.hpp>
33 #include <com/sun/star/io/XSeekable.hpp>
34 #include <com/sun/star/lang/WrappedTargetRuntimeException.hpp>
36 #include <cppuhelper/weak.hxx>
37 #include <cppuhelper/implbase3.hxx>
38 #include <cppuhelper/supportsservice.hxx>
39 #include <rtl/ref.hxx>
40 #include <sal/log.hxx>
42 #include <expat.h>
44 using namespace ::std;
45 using namespace ::osl;
46 using namespace ::cppu;
47 using namespace ::com::sun::star::lang;
48 using namespace ::com::sun::star::xml::sax;
49 using namespace ::com::sun::star::io;
51 #include "attrlistimpl.hxx"
52 #include "xml2utf.hxx"
54 namespace {
56 // Useful macros for correct String conversion depending on the chosen expat-mode
57 #ifdef XML_UNICODE
58 OUString XmlNChar2OUString( const XML_Char *p , int nLen )
60 if( p ) {
61 if( sizeof( sal_Unicode ) == sizeof( XML_Char ) )
63 return OUString( (sal_Unicode*)p,nLen);
65 else
67 sal_Unicode *pWchar = (sal_Unicode *)alloca( sizeof( sal_Unicode ) * nLen );
68 for( int n = 0 ; n < nLen ; n++ ) {
69 pWchar[n] = (sal_Unicode) p[n];
71 return OUString( pWchar , nLen );
74 else {
75 return OUString();
79 OUString XmlChar2OUString( const XML_Char *p )
81 if( p ) {
82 int nLen;
83 for( nLen = 0 ; p[nLen] ; nLen ++ )
85 return XmlNChar2OUString( p , nLen );
87 else return OUString();
91 #define XML_CHAR_TO_OUSTRING(x) XmlChar2OUString(x)
92 #define XML_CHAR_N_TO_USTRING(x,n) XmlNChar2OUString(x,n)
93 #else
94 #define XML_CHAR_TO_OUSTRING(x) OUString(x , strlen( x ), RTL_TEXTENCODING_UTF8)
95 #define XML_CHAR_N_TO_USTRING(x,n) OUString(x,n, RTL_TEXTENCODING_UTF8 )
96 #endif
100 * The following macro encapsulates any call to an event handler.
101 * It ensures, that exceptions thrown by the event handler are
102 * treated properly.
104 #define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis,call) \
105 if( ! pThis->bExceptionWasThrown ) { \
106 try {\
107 pThis->call;\
109 catch( const SAXParseException &e ) {\
110 callErrorHandler( pThis , e );\
112 catch( const SAXException &e ) {\
113 callErrorHandler( pThis , SAXParseException(\
114 e.Message, \
115 e.Context, \
116 e.WrappedException,\
117 pThis->rDocumentLocator->getPublicId(),\
118 pThis->rDocumentLocator->getSystemId(),\
119 pThis->rDocumentLocator->getLineNumber(),\
120 pThis->rDocumentLocator->getColumnNumber()\
121 ) );\
123 catch( const com::sun::star::uno::RuntimeException &e ) {\
124 pThis->bExceptionWasThrown = true; \
125 pThis->bRTExceptionWasThrown = true; \
126 pImpl->rtexception = e; \
128 catch( const com::sun::star::uno::Exception &e ) {\
129 pThis->bExceptionWasThrown = true; \
130 pThis->bRTExceptionWasThrown = true; \
131 pImpl->rtexception = WrappedTargetRuntimeException("Non-runtime UNO exception caught during parse", e.Context, makeAny(e)); \
134 ((void)0)
137 class SaxExpatParser_Impl;
139 // This class implements the external Parser interface
140 class SaxExpatParser
141 : public WeakImplHelper3< XInitialization
142 , XServiceInfo
143 , XParser >
146 public:
147 SaxExpatParser();
148 virtual ~SaxExpatParser();
150 // ::com::sun::star::lang::XInitialization:
151 virtual void SAL_CALL initialize(css::uno::Sequence<css::uno::Any> const& rArguments)
152 throw (css::uno::RuntimeException, css::uno::Exception, std::exception) SAL_OVERRIDE;
154 // The SAX-Parser-Interface
155 virtual void SAL_CALL parseStream( const InputSource& structSource)
156 throw ( SAXException,
157 IOException,
158 css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
159 virtual void SAL_CALL setDocumentHandler(const css::uno::Reference< XDocumentHandler > & xHandler)
160 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
162 virtual void SAL_CALL setErrorHandler(const css::uno::Reference< XErrorHandler > & xHandler)
163 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
164 virtual void SAL_CALL setDTDHandler(const css::uno::Reference < XDTDHandler > & xHandler)
165 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
166 virtual void SAL_CALL setEntityResolver(const css::uno::Reference< XEntityResolver >& xResolver)
167 throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
169 virtual void SAL_CALL setLocale( const Locale &locale ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
171 public: // XServiceInfo
172 OUString SAL_CALL getImplementationName() throw (std::exception) SAL_OVERRIDE;
173 css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (std::exception) SAL_OVERRIDE;
174 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) throw (std::exception) SAL_OVERRIDE;
176 private:
178 SaxExpatParser_Impl *m_pImpl;
183 // Entity binds all information neede for a single file
184 struct Entity
186 InputSource structSource;
187 XML_Parser pParser;
188 sax_expatwrap::XMLFile2UTFConverter converter;
192 class SaxExpatParser_Impl
194 public: // module scope
195 Mutex aMutex;
196 OUString sCDATA;
197 bool m_bEnableDoS; // fdo#60471 thank you Adobe Illustrator
199 css::uno::Reference< XDocumentHandler > rDocumentHandler;
200 css::uno::Reference< XExtendedDocumentHandler > rExtendedDocumentHandler;
202 css::uno::Reference< XErrorHandler > rErrorHandler;
203 css::uno::Reference< XDTDHandler > rDTDHandler;
204 css::uno::Reference< XEntityResolver > rEntityResolver;
205 css::uno::Reference < XLocator > rDocumentLocator;
208 rtl::Reference < sax_expatwrap::AttributeList > rAttrList;
210 // External entity stack
211 vector<struct Entity> vecEntity;
212 void pushEntity( const struct Entity &entity )
213 { vecEntity.push_back( entity ); }
214 void popEntity()
215 { vecEntity.pop_back( ); }
216 struct Entity &getEntity()
217 { return vecEntity.back(); }
220 // Exception cannot be thrown through the C-XmlParser (possible resource leaks),
221 // therefore the exception must be saved somewhere.
222 SAXParseException exception;
223 css::uno::RuntimeException rtexception;
224 bool bExceptionWasThrown;
225 bool bRTExceptionWasThrown;
227 Locale locale;
229 public:
230 SaxExpatParser_Impl()
231 : sCDATA("CDATA")
232 , m_bEnableDoS(false)
233 , bExceptionWasThrown(false)
234 , bRTExceptionWasThrown(false)
238 // the C-Callbacks for the expat parser
239 void static callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts);
240 void static callbackEndElement(void *userData, const XML_Char *name);
241 void static callbackCharacters( void *userData , const XML_Char *s , int nLen );
242 void static callbackProcessingInstruction( void *userData ,
243 const XML_Char *sTarget ,
244 const XML_Char *sData );
246 void static callbackEntityDecl( void *userData ,
247 const XML_Char *entityName,
248 int is_parameter_entity,
249 const XML_Char *value,
250 int value_length,
251 const XML_Char *base,
252 const XML_Char *systemId,
253 const XML_Char *publicId,
254 const XML_Char *notationName);
256 void static callbackNotationDecl( void *userData,
257 const XML_Char *notationName,
258 const XML_Char *base,
259 const XML_Char *systemId,
260 const XML_Char *publicId);
262 bool static callbackExternalEntityRef( XML_Parser parser,
263 const XML_Char *openEntityNames,
264 const XML_Char *base,
265 const XML_Char *systemId,
266 const XML_Char *publicId);
268 int static callbackUnknownEncoding(void *encodingHandlerData,
269 const XML_Char *name,
270 XML_Encoding *info);
272 void static callbackDefault( void *userData, const XML_Char *s, int len);
274 void static callbackStartCDATA( void *userData );
275 void static callbackEndCDATA( void *userData );
276 void static callbackComment( void *userData , const XML_Char *s );
277 void static callErrorHandler( SaxExpatParser_Impl *pImpl , const SAXParseException &e );
279 public:
280 void parse();
283 extern "C"
285 static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
287 SaxExpatParser_Impl::callbackStartElement(userData,name,atts);
289 static void call_callbackEndElement(void *userData, const XML_Char *name)
291 SaxExpatParser_Impl::callbackEndElement(userData,name);
293 static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
295 SaxExpatParser_Impl::callbackCharacters(userData,s,nLen);
297 static void call_callbackProcessingInstruction(void *userData,const XML_Char *sTarget,const XML_Char *sData )
299 SaxExpatParser_Impl::callbackProcessingInstruction(userData,sTarget,sData );
301 static void call_callbackEntityDecl(void *userData ,
302 const XML_Char *entityName,
303 int is_parameter_entity,
304 const XML_Char *value,
305 int value_length,
306 const XML_Char *base,
307 const XML_Char *systemId,
308 const XML_Char *publicId,
309 const XML_Char *notationName)
311 SaxExpatParser_Impl::callbackEntityDecl(userData, entityName,
312 is_parameter_entity, value, value_length,
313 base, systemId, publicId, notationName);
315 static void call_callbackNotationDecl(void *userData,
316 const XML_Char *notationName,
317 const XML_Char *base,
318 const XML_Char *systemId,
319 const XML_Char *publicId)
321 SaxExpatParser_Impl::callbackNotationDecl(userData,notationName,base,systemId,publicId);
323 static int call_callbackExternalEntityRef(XML_Parser parser,
324 const XML_Char *openEntityNames,
325 const XML_Char *base,
326 const XML_Char *systemId,
327 const XML_Char *publicId)
329 return SaxExpatParser_Impl::callbackExternalEntityRef(parser,openEntityNames,base,systemId,publicId);
331 static int call_callbackUnknownEncoding(void *encodingHandlerData,
332 const XML_Char *name,
333 XML_Encoding *info)
335 return SaxExpatParser_Impl::callbackUnknownEncoding(encodingHandlerData,name,info);
337 static void call_callbackDefault( void *userData, const XML_Char *s, int len)
339 SaxExpatParser_Impl::callbackDefault(userData,s,len);
341 static void call_callbackStartCDATA( void *userData )
343 SaxExpatParser_Impl::callbackStartCDATA(userData);
345 static void call_callbackEndCDATA( void *userData )
347 SaxExpatParser_Impl::callbackEndCDATA(userData);
349 static void call_callbackComment( void *userData , const XML_Char *s )
351 SaxExpatParser_Impl::callbackComment(userData,s);
357 // LocatorImpl
359 class LocatorImpl :
360 public WeakImplHelper2< XLocator, com::sun::star::io::XSeekable >
361 // should use a different interface for stream positions!
363 public:
364 explicit LocatorImpl(SaxExpatParser_Impl *p)
365 : m_pParser(p)
369 public: //XLocator
370 virtual sal_Int32 SAL_CALL getColumnNumber() throw (std::exception) SAL_OVERRIDE
372 return XML_GetCurrentColumnNumber( m_pParser->getEntity().pParser );
374 virtual sal_Int32 SAL_CALL getLineNumber() throw (std::exception) SAL_OVERRIDE
376 return XML_GetCurrentLineNumber( m_pParser->getEntity().pParser );
378 virtual OUString SAL_CALL getPublicId() throw (std::exception) SAL_OVERRIDE
380 return m_pParser->getEntity().structSource.sPublicId;
382 virtual OUString SAL_CALL getSystemId() throw (std::exception) SAL_OVERRIDE
384 return m_pParser->getEntity().structSource.sSystemId;
387 // XSeekable (only for getPosition)
389 virtual void SAL_CALL seek( sal_Int64 ) throw(std::exception) SAL_OVERRIDE
392 virtual sal_Int64 SAL_CALL getPosition() throw(std::exception) SAL_OVERRIDE
394 return XML_GetCurrentByteIndex( m_pParser->getEntity().pParser );
396 virtual ::sal_Int64 SAL_CALL getLength() throw(std::exception) SAL_OVERRIDE
398 return 0;
401 private:
403 SaxExpatParser_Impl *m_pParser;
409 SaxExpatParser::SaxExpatParser( )
411 m_pImpl = new SaxExpatParser_Impl;
413 LocatorImpl *pLoc = new LocatorImpl( m_pImpl );
414 m_pImpl->rDocumentLocator = css::uno::Reference< XLocator > ( pLoc );
416 // Performance-improvement; handing out the same object with every call of
417 // the startElement callback is allowed (see sax-specification):
418 m_pImpl->rAttrList = new sax_expatwrap::AttributeList;
420 m_pImpl->bExceptionWasThrown = false;
421 m_pImpl->bRTExceptionWasThrown = false;
424 SaxExpatParser::~SaxExpatParser()
426 delete m_pImpl;
429 // ::com::sun::star::lang::XInitialization:
430 void SAL_CALL
431 SaxExpatParser::initialize(css::uno::Sequence< css::uno::Any > const& rArguments)
432 throw (css::uno::RuntimeException, css::uno::Exception, std::exception)
434 // possible arguments: a string "DoSmeplease"
435 if (rArguments.getLength())
437 OUString str;
438 if ((rArguments[0] >>= str) && "DoSmeplease" == str)
440 MutexGuard guard( m_pImpl->aMutex );
441 m_pImpl->m_bEnableDoS = true;
446 /***************
448 * parseStream does Parser-startup initializations. The SaxExpatParser_Impl::parse() method does
449 * the file-specific initialization work. (During a parser run, external files may be opened)
451 ****************/
452 void SaxExpatParser::parseStream( const InputSource& structSource)
453 throw (SAXException,
454 IOException,
455 css::uno::RuntimeException, std::exception)
457 // Only one text at one time
458 MutexGuard guard( m_pImpl->aMutex );
461 struct Entity entity;
462 entity.structSource = structSource;
464 if( ! entity.structSource.aInputStream.is() )
466 throw SAXException("No input source",
467 css::uno::Reference< css::uno::XInterface > () , css::uno::Any() );
470 entity.converter.setInputStream( entity.structSource.aInputStream );
471 if( !entity.structSource.sEncoding.isEmpty() )
473 entity.converter.setEncoding(
474 OUStringToOString( entity.structSource.sEncoding , RTL_TEXTENCODING_ASCII_US ) );
477 // create parser with proper encoding
478 entity.pParser = XML_ParserCreate( 0 );
479 if( ! entity.pParser )
481 throw SAXException("Couldn't create parser",
482 css::uno::Reference< css::uno::XInterface > (), css::uno::Any() );
485 // set all necessary C-Callbacks
486 XML_SetUserData( entity.pParser , m_pImpl );
487 XML_SetElementHandler( entity.pParser ,
488 call_callbackStartElement ,
489 call_callbackEndElement );
490 XML_SetCharacterDataHandler( entity.pParser , call_callbackCharacters );
491 XML_SetProcessingInstructionHandler(entity.pParser ,
492 call_callbackProcessingInstruction );
493 if (!m_pImpl->m_bEnableDoS)
495 XML_SetEntityDeclHandler(entity.pParser, call_callbackEntityDecl);
497 XML_SetNotationDeclHandler( entity.pParser, call_callbackNotationDecl );
498 XML_SetExternalEntityRefHandler( entity.pParser,
499 call_callbackExternalEntityRef);
500 XML_SetUnknownEncodingHandler( entity.pParser, call_callbackUnknownEncoding ,0);
502 if( m_pImpl->rExtendedDocumentHandler.is() ) {
504 // These handlers just delegate calls to the ExtendedHandler. If no extended handler is
505 // given, these callbacks can be ignored
506 XML_SetDefaultHandlerExpand( entity.pParser, call_callbackDefault );
507 XML_SetCommentHandler( entity.pParser, call_callbackComment );
508 XML_SetCdataSectionHandler( entity.pParser ,
509 call_callbackStartCDATA ,
510 call_callbackEndCDATA );
514 m_pImpl->exception = SAXParseException();
515 m_pImpl->pushEntity( entity );
518 // start the document
519 if( m_pImpl->rDocumentHandler.is() ) {
520 m_pImpl->rDocumentHandler->setDocumentLocator( m_pImpl->rDocumentLocator );
521 m_pImpl->rDocumentHandler->startDocument();
524 m_pImpl->parse();
526 // finish document
527 if( m_pImpl->rDocumentHandler.is() ) {
528 m_pImpl->rDocumentHandler->endDocument();
531 // catch( SAXParseException &e )
532 // {
533 // m_pImpl->popEntity();
534 // XML_ParserFree( entity.pParser );
535 // css::uno::Any aAny;
536 // aAny <<= e;
537 // throw SAXException( e.Message, e.Context, aAny );
538 // }
539 catch( SAXException & )
541 m_pImpl->popEntity();
542 XML_ParserFree( entity.pParser );
543 throw;
545 catch( IOException & )
547 m_pImpl->popEntity();
548 XML_ParserFree( entity.pParser );
549 throw;
551 catch( css::uno::RuntimeException & )
553 m_pImpl->popEntity();
554 XML_ParserFree( entity.pParser );
555 throw;
558 m_pImpl->popEntity();
559 XML_ParserFree( entity.pParser );
562 void SaxExpatParser::setDocumentHandler(const css::uno::Reference< XDocumentHandler > & xHandler)
563 throw (css::uno::RuntimeException, std::exception)
565 m_pImpl->rDocumentHandler = xHandler;
566 m_pImpl->rExtendedDocumentHandler =
567 css::uno::Reference< XExtendedDocumentHandler >( xHandler , css::uno::UNO_QUERY );
570 void SaxExpatParser::setErrorHandler(const css::uno::Reference< XErrorHandler > & xHandler)
571 throw (css::uno::RuntimeException, std::exception)
573 m_pImpl->rErrorHandler = xHandler;
576 void SaxExpatParser::setDTDHandler(const css::uno::Reference< XDTDHandler > & xHandler)
577 throw (css::uno::RuntimeException, std::exception)
579 m_pImpl->rDTDHandler = xHandler;
582 void SaxExpatParser::setEntityResolver(const css::uno::Reference < XEntityResolver > & xResolver)
583 throw (css::uno::RuntimeException, std::exception)
585 m_pImpl->rEntityResolver = xResolver;
589 void SaxExpatParser::setLocale( const Locale & locale ) throw (css::uno::RuntimeException, std::exception)
591 m_pImpl->locale = locale;
594 // XServiceInfo
595 OUString SaxExpatParser::getImplementationName() throw (std::exception)
597 return OUString("com.sun.star.comp.extensions.xml.sax.ParserExpat");
600 // XServiceInfo
601 sal_Bool SaxExpatParser::supportsService(const OUString& ServiceName) throw (std::exception)
603 return cppu::supportsService(this, ServiceName);
606 // XServiceInfo
607 css::uno::Sequence< OUString > SaxExpatParser::getSupportedServiceNames() throw (std::exception)
609 css::uno::Sequence<OUString> seq(1);
610 seq[0] = "com.sun.star.xml.sax.Parser";
611 return seq;
615 /*---------------------------------------
617 * Helper functions and classes
620 *-------------------------------------------*/
621 OUString getErrorMessage( XML_Error xmlE, const OUString& sSystemId , sal_Int32 nLine )
623 OUString Message;
624 if( XML_ERROR_NONE == xmlE ) {
625 Message = "No";
627 else if( XML_ERROR_NO_MEMORY == xmlE ) {
628 Message = "no memory";
630 else if( XML_ERROR_SYNTAX == xmlE ) {
631 Message = "syntax";
633 else if( XML_ERROR_NO_ELEMENTS == xmlE ) {
634 Message = "no elements";
636 else if( XML_ERROR_INVALID_TOKEN == xmlE ) {
637 Message = "invalid token";
639 else if( XML_ERROR_UNCLOSED_TOKEN == xmlE ) {
640 Message = "unclosed token";
642 else if( XML_ERROR_PARTIAL_CHAR == xmlE ) {
643 Message = "partial char";
645 else if( XML_ERROR_TAG_MISMATCH == xmlE ) {
646 Message = "tag mismatch";
648 else if( XML_ERROR_DUPLICATE_ATTRIBUTE == xmlE ) {
649 Message = "duplicate attribute";
651 else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT == xmlE ) {
652 Message = "junk after doc element";
654 else if( XML_ERROR_PARAM_ENTITY_REF == xmlE ) {
655 Message = "parameter entity reference";
657 else if( XML_ERROR_UNDEFINED_ENTITY == xmlE ) {
658 Message = "undefined entity";
660 else if( XML_ERROR_RECURSIVE_ENTITY_REF == xmlE ) {
661 Message = "recursive entity reference";
663 else if( XML_ERROR_ASYNC_ENTITY == xmlE ) {
664 Message = "async entity";
666 else if( XML_ERROR_BAD_CHAR_REF == xmlE ) {
667 Message = "bad char reference";
669 else if( XML_ERROR_BINARY_ENTITY_REF == xmlE ) {
670 Message = "binary entity reference";
672 else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF == xmlE ) {
673 Message = "attribute external entity reference";
675 else if( XML_ERROR_MISPLACED_XML_PI == xmlE ) {
676 Message = "misplaced xml processing instruction";
678 else if( XML_ERROR_UNKNOWN_ENCODING == xmlE ) {
679 Message = "unknown encoding";
681 else if( XML_ERROR_INCORRECT_ENCODING == xmlE ) {
682 Message = "incorrect encoding";
684 else if( XML_ERROR_UNCLOSED_CDATA_SECTION == xmlE ) {
685 Message = "unclosed cdata section";
687 else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING == xmlE ) {
688 Message = "external entity reference";
690 else if( XML_ERROR_NOT_STANDALONE == xmlE ) {
691 Message = "not standalone";
694 OUString str("[");
695 str += sSystemId;
696 str += " line ";
697 str += OUString::number( nLine );
698 str += "]: ";
699 str += Message;
700 str += "error";
702 return str;
706 // starts parsing with actual parser !
707 void SaxExpatParser_Impl::parse( )
709 const int nBufSize = 16*1024;
711 int nRead = nBufSize;
712 css::uno::Sequence< sal_Int8 > seqOut(nBufSize);
714 while( nRead ) {
715 nRead = getEntity().converter.readAndConvert( seqOut , nBufSize );
717 if( ! nRead ) {
718 XML_Parse( getEntity().pParser ,
719 reinterpret_cast<const char *>(seqOut.getConstArray()),
721 1 );
722 break;
725 bool bContinue = ( XML_Parse( getEntity().pParser ,
726 reinterpret_cast<const char *>(seqOut.getConstArray()),
727 nRead,
728 0 ) != XML_STATUS_ERROR );
730 if( ! bContinue || this->bExceptionWasThrown ) {
732 if ( this->bRTExceptionWasThrown )
733 throw rtexception;
735 // Error during parsing !
736 XML_Error xmlE = XML_GetErrorCode( getEntity().pParser );
737 OUString sSystemId = rDocumentLocator->getSystemId();
738 sal_Int32 nLine = rDocumentLocator->getLineNumber();
740 SAXParseException aExcept(
741 getErrorMessage(xmlE , sSystemId, nLine) ,
742 css::uno::Reference< css::uno::XInterface >(),
743 css::uno::Any( &exception , cppu::UnoType<decltype(exception)>::get() ),
744 rDocumentLocator->getPublicId(),
745 rDocumentLocator->getSystemId(),
746 rDocumentLocator->getLineNumber(),
747 rDocumentLocator->getColumnNumber()
750 if( rErrorHandler.is() ) {
752 // error handler is set, so the handler may throw the exception
753 css::uno::Any a;
754 a <<= aExcept;
755 rErrorHandler->fatalError( a );
758 // Error handler has not thrown an exception, but parsing cannot go on,
759 // so an exception MUST be thrown.
760 throw aExcept;
761 } // if( ! bContinue )
762 } // while
767 // The C-Callbacks
770 void SaxExpatParser_Impl::callbackStartElement( void *pvThis ,
771 const XML_Char *pwName ,
772 const XML_Char **awAttributes )
774 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
776 if( pImpl->rDocumentHandler.is() ) {
778 int i = 0;
779 pImpl->rAttrList->clear();
781 while( awAttributes[i] ) {
782 assert(awAttributes[i+1]);
783 pImpl->rAttrList->addAttribute(
784 XML_CHAR_TO_OUSTRING( awAttributes[i] ) ,
785 pImpl->sCDATA, // expat doesn't know types
786 XML_CHAR_TO_OUSTRING( awAttributes[i+1] ) );
787 i +=2;
790 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
791 pImpl ,
792 rDocumentHandler->startElement( XML_CHAR_TO_OUSTRING( pwName ) ,
793 pImpl->rAttrList.get() ) );
797 void SaxExpatParser_Impl::callbackEndElement( void *pvThis , const XML_Char *pwName )
799 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
801 if( pImpl->rDocumentHandler.is() ) {
802 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
803 rDocumentHandler->endElement( XML_CHAR_TO_OUSTRING( pwName ) ) );
808 void SaxExpatParser_Impl::callbackCharacters( void *pvThis , const XML_Char *s , int nLen )
810 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
812 if( pImpl->rDocumentHandler.is() ) {
813 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl ,
814 rDocumentHandler->characters( XML_CHAR_N_TO_USTRING(s,nLen) ) );
818 void SaxExpatParser_Impl::callbackProcessingInstruction( void *pvThis,
819 const XML_Char *sTarget ,
820 const XML_Char *sData )
822 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
823 if( pImpl->rDocumentHandler.is() ) {
824 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
825 pImpl ,
826 rDocumentHandler->processingInstruction( XML_CHAR_TO_OUSTRING( sTarget ),
827 XML_CHAR_TO_OUSTRING( sData ) ) );
832 void SaxExpatParser_Impl::callbackEntityDecl(
833 void *pvThis, const XML_Char *entityName,
834 SAL_UNUSED_PARAMETER int /*is_parameter_entity*/,
835 const XML_Char *value, SAL_UNUSED_PARAMETER int /*value_length*/,
836 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
837 const XML_Char *publicId, const XML_Char *notationName)
839 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
840 if (value) { // value != 0 means internal entity
841 SAL_INFO("sax","SaxExpatParser: internal entity declaration, stopping");
842 XML_StopParser(pImpl->getEntity().pParser, XML_FALSE);
843 pImpl->exception = SAXParseException(
844 "SaxExpatParser: internal entity declaration, stopping",
845 0, css::uno::Any(),
846 pImpl->rDocumentLocator->getPublicId(),
847 pImpl->rDocumentLocator->getSystemId(),
848 pImpl->rDocumentLocator->getLineNumber(),
849 pImpl->rDocumentLocator->getColumnNumber() );
850 pImpl->bExceptionWasThrown = true;
851 } else {
852 if( pImpl->rDTDHandler.is() ) {
853 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
854 pImpl ,
855 rDTDHandler->unparsedEntityDecl(
856 XML_CHAR_TO_OUSTRING( entityName ),
857 XML_CHAR_TO_OUSTRING( publicId ) ,
858 XML_CHAR_TO_OUSTRING( systemId ) ,
859 XML_CHAR_TO_OUSTRING( notationName ) ) );
864 void SaxExpatParser_Impl::callbackNotationDecl(
865 void *pvThis, const XML_Char *notationName,
866 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
867 const XML_Char *publicId)
869 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
870 if( pImpl->rDTDHandler.is() ) {
871 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
872 rDTDHandler->notationDecl( XML_CHAR_TO_OUSTRING( notationName ) ,
873 XML_CHAR_TO_OUSTRING( publicId ) ,
874 XML_CHAR_TO_OUSTRING( systemId ) ) );
881 bool SaxExpatParser_Impl::callbackExternalEntityRef(
882 XML_Parser parser, const XML_Char *context,
883 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
884 const XML_Char *publicId)
886 bool bOK = true;
887 InputSource source;
888 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(XML_GetUserData( parser ));
890 struct Entity entity;
892 if( pImpl->rEntityResolver.is() ) {
895 entity.structSource = pImpl->rEntityResolver->resolveEntity(
896 XML_CHAR_TO_OUSTRING( publicId ) ,
897 XML_CHAR_TO_OUSTRING( systemId ) );
899 catch( const SAXParseException & e )
901 pImpl->exception = e;
902 bOK = false;
904 catch( const SAXException & e )
906 pImpl->exception = SAXParseException(
907 e.Message , e.Context , e.WrappedException ,
908 pImpl->rDocumentLocator->getPublicId(),
909 pImpl->rDocumentLocator->getSystemId(),
910 pImpl->rDocumentLocator->getLineNumber(),
911 pImpl->rDocumentLocator->getColumnNumber() );
912 bOK = false;
916 if( entity.structSource.aInputStream.is() ) {
917 entity.pParser = XML_ExternalEntityParserCreate( parser , context, 0 );
918 if( ! entity.pParser )
920 return false;
923 entity.converter.setInputStream( entity.structSource.aInputStream );
924 pImpl->pushEntity( entity );
927 pImpl->parse();
929 catch( const SAXParseException & e )
931 pImpl->exception = e;
932 bOK = false;
934 catch( const IOException &e )
936 pImpl->exception.WrappedException <<= e;
937 bOK = false;
939 catch( const css::uno::RuntimeException &e )
941 pImpl->exception.WrappedException <<=e;
942 bOK = false;
945 pImpl->popEntity();
947 XML_ParserFree( entity.pParser );
950 return bOK;
953 int SaxExpatParser_Impl::callbackUnknownEncoding(
954 SAL_UNUSED_PARAMETER void * /*encodingHandlerData*/,
955 SAL_UNUSED_PARAMETER const XML_Char * /*name*/,
956 SAL_UNUSED_PARAMETER XML_Encoding * /*info*/)
958 return 0;
961 void SaxExpatParser_Impl::callbackDefault( void *pvThis, const XML_Char *s, int len)
963 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
965 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
966 rExtendedDocumentHandler->unknown( XML_CHAR_N_TO_USTRING( s ,len) ) );
969 void SaxExpatParser_Impl::callbackComment( void *pvThis , const XML_Char *s )
971 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
972 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
973 rExtendedDocumentHandler->comment( XML_CHAR_TO_OUSTRING( s ) ) );
976 void SaxExpatParser_Impl::callbackStartCDATA( void *pvThis )
978 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
980 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, rExtendedDocumentHandler->startCDATA() );
984 void SaxExpatParser_Impl::callErrorHandler( SaxExpatParser_Impl *pImpl ,
985 const SAXParseException & e )
989 if( pImpl->rErrorHandler.is() ) {
990 css::uno::Any a;
991 a <<= e;
992 pImpl->rErrorHandler->error( a );
994 else {
995 pImpl->exception = e;
996 pImpl->bExceptionWasThrown = true;
999 catch( const SAXParseException & ex ) {
1000 pImpl->exception = ex;
1001 pImpl->bExceptionWasThrown = true;
1003 catch( const SAXException & ex ) {
1004 pImpl->exception = SAXParseException(
1005 ex.Message,
1006 ex.Context,
1007 ex.WrappedException,
1008 pImpl->rDocumentLocator->getPublicId(),
1009 pImpl->rDocumentLocator->getSystemId(),
1010 pImpl->rDocumentLocator->getLineNumber(),
1011 pImpl->rDocumentLocator->getColumnNumber()
1013 pImpl->bExceptionWasThrown = true;
1017 void SaxExpatParser_Impl::callbackEndCDATA( void *pvThis )
1019 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
1021 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pImpl,rExtendedDocumentHandler->endCDATA() );
1024 } // namespace
1026 extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1027 com_sun_star_comp_extensions_xml_sax_ParserExpat_get_implementation(
1028 css::uno::XComponentContext *,
1029 css::uno::Sequence<css::uno::Any> const &)
1031 return cppu::acquire(new SaxExpatParser);
1034 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */