LibreOffice Module sax (master) 1
sax_expat.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
20#include <string.h>
21#include <cassert>
22#include <memory>
23#include <mutex>
24#include <utility>
25#include <string_view>
26#include <vector>
27
28
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>
38
40#include <cppuhelper/weak.hxx>
43#include <rtl/ref.hxx>
44#include <sal/log.hxx>
45
46#include <expat.h>
47
48using namespace ::osl;
49using namespace ::cppu;
50using namespace ::com::sun::star::lang;
51using namespace ::com::sun::star::xml::sax;
52using namespace ::com::sun::star::io;
53
54#include <xml2utf.hxx>
55
56namespace {
57
58#define XML_CHAR_TO_OUSTRING(x) OUString(x , strlen( x ), RTL_TEXTENCODING_UTF8)
59#define XML_CHAR_N_TO_USTRING(x,n) OUString(x,n, RTL_TEXTENCODING_UTF8 )
60
61
62/*
63* The following macro encapsulates any call to an event handler.
64* It ensures, that exceptions thrown by the event handler are
65* treated properly.
66*/
67#define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis,call) \
68 if( ! pThis->bExceptionWasThrown ) { \
69 try {\
70 pThis->call;\
71 }\
72 catch( const SAXParseException &e ) {\
73 callErrorHandler( pThis , e );\
74 }\
75 catch( const SAXException &e ) {\
76 callErrorHandler( pThis , SAXParseException(\
77 e.Message, \
78 e.Context, \
79 e.WrappedException,\
80 pThis->rDocumentLocator->getPublicId(),\
81 pThis->rDocumentLocator->getSystemId(),\
82 pThis->rDocumentLocator->getLineNumber(),\
83 pThis->rDocumentLocator->getColumnNumber()\
84 ) );\
85 }\
86 catch( const css::uno::RuntimeException &e ) {\
87 pThis->bExceptionWasThrown = true; \
88 pThis->bRTExceptionWasThrown = true; \
89 pImpl->rtexception = e; \
90 }\
91 catch( const css::uno::Exception &e ) {\
92 pThis->bExceptionWasThrown = true; \
93 pThis->bRTExceptionWasThrown = true; \
94 pImpl->rtexception = WrappedTargetRuntimeException("Non-runtime UNO exception caught during parse", e.Context, css::uno::Any(e)); \
95 }\
96 }\
97 ((void)0)
98
99
100class SaxExpatParser_Impl;
101
102// This class implements the external Parser interface
103class SaxExpatParser
104 : public WeakImplHelper< XInitialization
105 , XServiceInfo
106 , XParser >
107{
108
109public:
110 SaxExpatParser();
111
112 // css::lang::XInitialization:
113 virtual void SAL_CALL initialize(css::uno::Sequence<css::uno::Any> const& rArguments) override;
114
115 // The SAX-Parser-Interface
116 virtual void SAL_CALL parseStream( const InputSource& structSource) override;
117 virtual void SAL_CALL setDocumentHandler(const css::uno::Reference< XDocumentHandler > & xHandler) override;
118
119 virtual void SAL_CALL setErrorHandler(const css::uno::Reference< XErrorHandler > & xHandler) override;
120 virtual void SAL_CALL setDTDHandler(const css::uno::Reference < XDTDHandler > & xHandler) override;
121 virtual void SAL_CALL setEntityResolver(const css::uno::Reference< XEntityResolver >& xResolver) override;
122
123 virtual void SAL_CALL setLocale( const Locale &locale ) override;
124
125public: // XServiceInfo
126 OUString SAL_CALL getImplementationName() override;
127 css::uno::Sequence< OUString > SAL_CALL getSupportedServiceNames() override;
128 sal_Bool SAL_CALL supportsService(const OUString& ServiceName) override;
129
130private:
131 std::unique_ptr<SaxExpatParser_Impl> m_pImpl;
132};
133
134
135// Entity binds all information needed for a single file
136struct Entity
137{
138 InputSource structSource;
139 XML_Parser pParser;
141};
142
143
144class SaxExpatParser_Impl
145{
146public: // module scope
147 std::mutex aMutex;
148 bool m_bEnableDoS; // fdo#60471 thank you Adobe Illustrator
149
150 css::uno::Reference< XDocumentHandler > rDocumentHandler;
151 css::uno::Reference< XExtendedDocumentHandler > rExtendedDocumentHandler;
152
153 css::uno::Reference< XErrorHandler > rErrorHandler;
154 css::uno::Reference< XDTDHandler > rDTDHandler;
155 css::uno::Reference< XEntityResolver > rEntityResolver;
156 css::uno::Reference < XLocator > rDocumentLocator;
157
158
160
161 // External entity stack
162 std::vector<struct Entity> vecEntity;
163 void pushEntity( Entity &&entity )
164 { vecEntity.push_back( std::move(entity) ); }
165 void popEntity()
166 { vecEntity.pop_back( ); }
167 struct Entity &getEntity()
168 { return vecEntity.back(); }
169
170
171 // Exception cannot be thrown through the C-XmlParser (possible resource leaks),
172 // therefore the exception must be saved somewhere.
173 SAXParseException exception;
174 css::uno::RuntimeException rtexception;
175 bool bExceptionWasThrown;
176 bool bRTExceptionWasThrown;
177
178public:
179 SaxExpatParser_Impl()
180 : m_bEnableDoS(false)
181 , bExceptionWasThrown(false)
182 , bRTExceptionWasThrown(false)
183 {
184 }
185
186 // the C-Callbacks for the expat parser
187 void static callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts);
188 void static callbackEndElement(void *userData, const XML_Char *name);
189 void static callbackCharacters( void *userData , const XML_Char *s , int nLen );
190 void static callbackProcessingInstruction( void *userData ,
191 const XML_Char *sTarget ,
192 const XML_Char *sData );
193
194 void static callbackEntityDecl( void *userData ,
195 const XML_Char *entityName,
196 int is_parameter_entity,
197 const XML_Char *value,
198 int value_length,
199 const XML_Char *base,
200 const XML_Char *systemId,
201 const XML_Char *publicId,
202 const XML_Char *notationName);
203
204 void static callbackNotationDecl( void *userData,
205 const XML_Char *notationName,
206 const XML_Char *base,
207 const XML_Char *systemId,
208 const XML_Char *publicId);
209
210 bool static callbackExternalEntityRef( XML_Parser parser,
211 const XML_Char *openEntityNames,
212 const XML_Char *base,
213 const XML_Char *systemId,
214 const XML_Char *publicId);
215
216 int static callbackUnknownEncoding(void *encodingHandlerData,
217 const XML_Char *name,
218 XML_Encoding *info);
219
220 void static callbackDefault( void *userData, const XML_Char *s, int len);
221
222 void static callbackStartCDATA( void *userData );
223 void static callbackEndCDATA( void *userData );
224 void static callbackComment( void *userData , const XML_Char *s );
225 void static callErrorHandler( SaxExpatParser_Impl *pImpl , const SAXParseException &e );
226
227public:
228 void parse();
229};
230
231extern "C"
232{
233 static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
234 {
235 SaxExpatParser_Impl::callbackStartElement(userData,name,atts);
236 }
237 static void call_callbackEndElement(void *userData, const XML_Char *name)
238 {
239 SaxExpatParser_Impl::callbackEndElement(userData,name);
240 }
241 static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
242 {
243 SaxExpatParser_Impl::callbackCharacters(userData,s,nLen);
244 }
245 static void call_callbackProcessingInstruction(void *userData,const XML_Char *sTarget,const XML_Char *sData )
246 {
247 SaxExpatParser_Impl::callbackProcessingInstruction(userData,sTarget,sData );
248 }
249 static void call_callbackEntityDecl(void *userData ,
250 const XML_Char *entityName,
251 int is_parameter_entity,
252 const XML_Char *value,
253 int value_length,
254 const XML_Char *base,
255 const XML_Char *systemId,
256 const XML_Char *publicId,
257 const XML_Char *notationName)
258 {
259 SaxExpatParser_Impl::callbackEntityDecl(userData, entityName,
260 is_parameter_entity, value, value_length,
261 base, systemId, publicId, notationName);
262 }
263 static void call_callbackNotationDecl(void *userData,
264 const XML_Char *notationName,
265 const XML_Char *base,
266 const XML_Char *systemId,
267 const XML_Char *publicId)
268 {
269 SaxExpatParser_Impl::callbackNotationDecl(userData,notationName,base,systemId,publicId);
270 }
271 static int call_callbackExternalEntityRef(XML_Parser parser,
272 const XML_Char *openEntityNames,
273 const XML_Char *base,
274 const XML_Char *systemId,
275 const XML_Char *publicId)
276 {
277 return SaxExpatParser_Impl::callbackExternalEntityRef(parser,openEntityNames,base,systemId,publicId);
278 }
279 static int call_callbackUnknownEncoding(void *encodingHandlerData,
280 const XML_Char *name,
281 XML_Encoding *info)
282 {
283 return SaxExpatParser_Impl::callbackUnknownEncoding(encodingHandlerData,name,info);
284 }
285 static void call_callbackDefault( void *userData, const XML_Char *s, int len)
286 {
287 SaxExpatParser_Impl::callbackDefault(userData,s,len);
288 }
289 static void call_callbackStartCDATA( void *userData )
290 {
291 SaxExpatParser_Impl::callbackStartCDATA(userData);
292 }
293 static void call_callbackEndCDATA( void *userData )
294 {
295 SaxExpatParser_Impl::callbackEndCDATA(userData);
296 }
297 static void call_callbackComment( void *userData , const XML_Char *s )
298 {
299 SaxExpatParser_Impl::callbackComment(userData,s);
300 }
301}
302
303
304// LocatorImpl
305
306class LocatorImpl :
307 public WeakImplHelper< XLocator, css::io::XSeekable >
308 // should use a different interface for stream positions!
309{
310public:
311 explicit LocatorImpl(SaxExpatParser_Impl *p)
312 : m_pParser(p)
313 {
314 }
315
316public: //XLocator
317 virtual sal_Int32 SAL_CALL getColumnNumber() override
318 {
319 return XML_GetCurrentColumnNumber( m_pParser->getEntity().pParser );
320 }
321 virtual sal_Int32 SAL_CALL getLineNumber() override
322 {
323 return XML_GetCurrentLineNumber( m_pParser->getEntity().pParser );
324 }
325 virtual OUString SAL_CALL getPublicId() override
326 {
327 return m_pParser->getEntity().structSource.sPublicId;
328 }
329 virtual OUString SAL_CALL getSystemId() override
330 {
331 return m_pParser->getEntity().structSource.sSystemId;
332 }
333
334 // XSeekable (only for getPosition)
335
336 virtual void SAL_CALL seek( sal_Int64 ) override
337 {
338 }
339 virtual sal_Int64 SAL_CALL getPosition() override
340 {
341 return XML_GetCurrentByteIndex( m_pParser->getEntity().pParser );
342 }
343 virtual ::sal_Int64 SAL_CALL getLength() override
344 {
345 return 0;
346 }
347
348private:
349
350 SaxExpatParser_Impl *m_pParser;
351};
352
353
354SaxExpatParser::SaxExpatParser( )
355{
356 m_pImpl.reset( new SaxExpatParser_Impl );
357
358 rtl::Reference<LocatorImpl> pLoc = new LocatorImpl( m_pImpl.get() );
359 m_pImpl->rDocumentLocator = pLoc;
360
361 // Performance-improvement; handing out the same object with every call of
362 // the startElement callback is allowed (see sax-specification):
363 m_pImpl->rAttrList = new comphelper::AttributeList;
364
365 m_pImpl->bExceptionWasThrown = false;
366 m_pImpl->bRTExceptionWasThrown = false;
367}
368
369// css::lang::XInitialization:
370void SAL_CALL
371SaxExpatParser::initialize(css::uno::Sequence< css::uno::Any > const& rArguments)
372{
373 // possible arguments: a string "DoSmeplease"
374 if (rArguments.hasElements())
375 {
376 OUString str;
377 if ((rArguments[0] >>= str) && "DoSmeplease" == str)
378 {
379 std::unique_lock guard( m_pImpl->aMutex );
380 m_pImpl->m_bEnableDoS = true;
381 }
382 }
383}
384
385class ParserCleanup
386{
387private:
388 SaxExpatParser_Impl& m_rParser;
389 XML_Parser m_xmlParser;
390public:
391 ParserCleanup(SaxExpatParser_Impl& rParser, XML_Parser xmlParser)
392 : m_rParser(rParser)
393 , m_xmlParser(xmlParser)
394 {
395 }
396 ~ParserCleanup()
397 {
398 m_rParser.popEntity();
399 //XML_ParserFree accepts a null arg
400 XML_ParserFree(m_xmlParser);
401 }
402};
403
404/***************
405*
406* parseStream does Parser-startup initializations. The SaxExpatParser_Impl::parse() method does
407* the file-specific initialization work. (During a parser run, external files may be opened)
408*
409****************/
410void SaxExpatParser::parseStream( const InputSource& structSource)
411{
412 // Only one text at one time
413 std::unique_lock guard( m_pImpl->aMutex );
414
415
416 struct Entity entity;
417 entity.structSource = structSource;
418
419 if( ! entity.structSource.aInputStream.is() )
420 {
421 throw SAXException("No input source",
422 css::uno::Reference< css::uno::XInterface > () , css::uno::Any() );
423 }
424
425 entity.converter.setInputStream( entity.structSource.aInputStream );
426 if( !entity.structSource.sEncoding.isEmpty() )
427 {
428 entity.converter.setEncoding(
429 OUStringToOString( entity.structSource.sEncoding , RTL_TEXTENCODING_ASCII_US ) );
430 }
431
432 // create parser with proper encoding
433 entity.pParser = XML_ParserCreate( nullptr );
434 if( ! entity.pParser )
435 {
436 throw SAXException("Couldn't create parser",
437 css::uno::Reference< css::uno::XInterface > (), css::uno::Any() );
438 }
439
440 // set all necessary C-Callbacks
441 XML_SetUserData( entity.pParser, m_pImpl.get() );
442 XML_SetElementHandler( entity.pParser ,
443 call_callbackStartElement ,
444 call_callbackEndElement );
445 XML_SetCharacterDataHandler( entity.pParser , call_callbackCharacters );
446 XML_SetProcessingInstructionHandler(entity.pParser ,
447 call_callbackProcessingInstruction );
448 if (!m_pImpl->m_bEnableDoS)
449 {
450 XML_SetEntityDeclHandler(entity.pParser, call_callbackEntityDecl);
451 }
452 XML_SetNotationDeclHandler( entity.pParser, call_callbackNotationDecl );
453 XML_SetExternalEntityRefHandler( entity.pParser,
454 call_callbackExternalEntityRef);
455 XML_SetUnknownEncodingHandler( entity.pParser, call_callbackUnknownEncoding ,nullptr);
456
457 if( m_pImpl->rExtendedDocumentHandler.is() ) {
458
459 // These handlers just delegate calls to the ExtendedHandler. If no extended handler is
460 // given, these callbacks can be ignored
461 XML_SetDefaultHandlerExpand( entity.pParser, call_callbackDefault );
462 XML_SetCommentHandler( entity.pParser, call_callbackComment );
463 XML_SetCdataSectionHandler( entity.pParser ,
464 call_callbackStartCDATA ,
465 call_callbackEndCDATA );
466 }
467
468
469 m_pImpl->exception = SAXParseException();
470 auto const xmlParser = entity.pParser;
471 m_pImpl->pushEntity( std::move(entity) );
472
473 ParserCleanup aEnsureFree(*m_pImpl, xmlParser);
474
475 // start the document
476 if( m_pImpl->rDocumentHandler.is() ) {
477 m_pImpl->rDocumentHandler->setDocumentLocator( m_pImpl->rDocumentLocator );
478 m_pImpl->rDocumentHandler->startDocument();
479 }
480
481 m_pImpl->parse();
482
483 // finish document
484 if( m_pImpl->rDocumentHandler.is() ) {
485 m_pImpl->rDocumentHandler->endDocument();
486 }
487}
488
489void SaxExpatParser::setDocumentHandler(const css::uno::Reference< XDocumentHandler > & xHandler)
490{
491 m_pImpl->rDocumentHandler = xHandler;
492 m_pImpl->rExtendedDocumentHandler =
493 css::uno::Reference< XExtendedDocumentHandler >( xHandler , css::uno::UNO_QUERY );
494}
495
496void SaxExpatParser::setErrorHandler(const css::uno::Reference< XErrorHandler > & xHandler)
497{
498 m_pImpl->rErrorHandler = xHandler;
499}
500
501void SaxExpatParser::setDTDHandler(const css::uno::Reference< XDTDHandler > & xHandler)
502{
503 m_pImpl->rDTDHandler = xHandler;
504}
505
506void SaxExpatParser::setEntityResolver(const css::uno::Reference < XEntityResolver > & xResolver)
507{
508 m_pImpl->rEntityResolver = xResolver;
509}
510
511
512void SaxExpatParser::setLocale( const Locale & )
513{
514 // not implemented
515}
516
517// XServiceInfo
518OUString SaxExpatParser::getImplementationName()
519{
520 return "com.sun.star.comp.extensions.xml.sax.ParserExpat";
521}
522
523// XServiceInfo
524sal_Bool SaxExpatParser::supportsService(const OUString& ServiceName)
525{
526 return cppu::supportsService(this, ServiceName);
527}
528
529// XServiceInfo
530css::uno::Sequence< OUString > SaxExpatParser::getSupportedServiceNames()
531{
532 return { "com.sun.star.xml.sax.Parser" };
533}
534
535
536/*---------------------------------------
537*
538* Helper functions and classes
539*
540*
541*-------------------------------------------*/
542OUString getErrorMessage( XML_Error xmlE, std::u16string_view sSystemId , sal_Int32 nLine )
543{
544 OUString Message;
545 if( XML_ERROR_NONE == xmlE ) {
546 Message = "No";
547 }
548 else if( XML_ERROR_NO_MEMORY == xmlE ) {
549 Message = "no memory";
550 }
551 else if( XML_ERROR_SYNTAX == xmlE ) {
552 Message = "syntax";
553 }
554 else if( XML_ERROR_NO_ELEMENTS == xmlE ) {
555 Message = "no elements";
556 }
557 else if( XML_ERROR_INVALID_TOKEN == xmlE ) {
558 Message = "invalid token";
559 }
560 else if( XML_ERROR_UNCLOSED_TOKEN == xmlE ) {
561 Message = "unclosed token";
562 }
563 else if( XML_ERROR_PARTIAL_CHAR == xmlE ) {
564 Message = "partial char";
565 }
566 else if( XML_ERROR_TAG_MISMATCH == xmlE ) {
567 Message = "tag mismatch";
568 }
569 else if( XML_ERROR_DUPLICATE_ATTRIBUTE == xmlE ) {
570 Message = "duplicate attribute";
571 }
572 else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT == xmlE ) {
573 Message = "junk after doc element";
574 }
575 else if( XML_ERROR_PARAM_ENTITY_REF == xmlE ) {
576 Message = "parameter entity reference";
577 }
578 else if( XML_ERROR_UNDEFINED_ENTITY == xmlE ) {
579 Message = "undefined entity";
580 }
581 else if( XML_ERROR_RECURSIVE_ENTITY_REF == xmlE ) {
582 Message = "recursive entity reference";
583 }
584 else if( XML_ERROR_ASYNC_ENTITY == xmlE ) {
585 Message = "async entity";
586 }
587 else if( XML_ERROR_BAD_CHAR_REF == xmlE ) {
588 Message = "bad char reference";
589 }
590 else if( XML_ERROR_BINARY_ENTITY_REF == xmlE ) {
591 Message = "binary entity reference";
592 }
593 else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF == xmlE ) {
594 Message = "attribute external entity reference";
595 }
596 else if( XML_ERROR_MISPLACED_XML_PI == xmlE ) {
597 Message = "misplaced xml processing instruction";
598 }
599 else if( XML_ERROR_UNKNOWN_ENCODING == xmlE ) {
600 Message = "unknown encoding";
601 }
602 else if( XML_ERROR_INCORRECT_ENCODING == xmlE ) {
603 Message = "incorrect encoding";
604 }
605 else if( XML_ERROR_UNCLOSED_CDATA_SECTION == xmlE ) {
606 Message = "unclosed cdata section";
607 }
608 else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING == xmlE ) {
609 Message = "external entity reference";
610 }
611 else if( XML_ERROR_NOT_STANDALONE == xmlE ) {
612 Message = "not standalone";
613 }
614
615 OUString str = OUString::Concat("[") +
616 sSystemId +
617 " line " +
618 OUString::number( nLine ) +
619 "]: " +
620 Message +
621 "error";
622
623 return str;
624}
625
626
627// starts parsing with actual parser !
628void SaxExpatParser_Impl::parse( )
629{
630 const int nBufSize = 16*1024;
631
632 int nRead = nBufSize;
633 css::uno::Sequence< sal_Int8 > seqOut(nBufSize);
634
635 while( nRead ) {
636 nRead = getEntity().converter.readAndConvert( seqOut , nBufSize );
637
638 bool bContinue(false);
639
640 if( ! nRead ) {
641 // last call - must return OK
642 XML_Status const ret = XML_Parse( getEntity().pParser,
643 reinterpret_cast<const char *>(seqOut.getConstArray()),
644 0 ,
645 1 );
646 if (ret == XML_STATUS_OK) {
647 break;
648 }
649 } else {
650 bContinue = ( XML_Parse( getEntity().pParser,
651 reinterpret_cast<const char *>(seqOut.getConstArray()),
652 nRead,
653 0 ) != XML_STATUS_ERROR );
654 }
655
656 if( ! bContinue || bExceptionWasThrown ) {
657
658 if ( bRTExceptionWasThrown )
659 throw rtexception;
660
661 // Error during parsing !
662 XML_Error xmlE = XML_GetErrorCode( getEntity().pParser );
663 OUString sSystemId = rDocumentLocator->getSystemId();
664 sal_Int32 nLine = rDocumentLocator->getLineNumber();
665
666 SAXParseException aExcept(
667 getErrorMessage(xmlE , sSystemId, nLine) ,
668 css::uno::Reference< css::uno::XInterface >(),
669 css::uno::Any( &exception , cppu::UnoType<decltype(exception)>::get() ),
670 rDocumentLocator->getPublicId(),
671 rDocumentLocator->getSystemId(),
672 rDocumentLocator->getLineNumber(),
673 rDocumentLocator->getColumnNumber()
674 );
675
676 if( rErrorHandler.is() ) {
677
678 // error handler is set, so the handler may throw the exception
679 css::uno::Any a;
680 a <<= aExcept;
681 rErrorHandler->fatalError( a );
682 }
683
684 // Error handler has not thrown an exception, but parsing cannot go on,
685 // so an exception MUST be thrown.
686 throw aExcept;
687 } // if( ! bContinue )
688 } // while
689}
690
691
692// The C-Callbacks
693
694
695void SaxExpatParser_Impl::callbackStartElement( void *pvThis ,
696 const XML_Char *pwName ,
697 const XML_Char **awAttributes )
698{
699 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
700
701 if( !pImpl->rDocumentHandler.is() )
702 return;
703
704 int i = 0;
705 pImpl->rAttrList->Clear();
706
707 while( awAttributes[i] ) {
708 assert(awAttributes[i+1]);
709 pImpl->rAttrList->AddAttribute(
710 XML_CHAR_TO_OUSTRING( awAttributes[i] ) ,
711 XML_CHAR_TO_OUSTRING( awAttributes[i+1] ) );
712 i +=2;
713 }
714
716 pImpl ,
717 rDocumentHandler->startElement( XML_CHAR_TO_OUSTRING( pwName ) ,
718 pImpl->rAttrList ) );
719}
720
721void SaxExpatParser_Impl::callbackEndElement( void *pvThis , const XML_Char *pwName )
722{
723 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
724
725 if( pImpl->rDocumentHandler.is() ) {
727 rDocumentHandler->endElement( XML_CHAR_TO_OUSTRING( pwName ) ) );
728 }
729}
730
731
732void SaxExpatParser_Impl::callbackCharacters( void *pvThis , const XML_Char *s , int nLen )
733{
734 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
735
736 if( pImpl->rDocumentHandler.is() ) {
738 rDocumentHandler->characters( XML_CHAR_N_TO_USTRING(s,nLen) ) );
739 }
740}
741
742void SaxExpatParser_Impl::callbackProcessingInstruction( void *pvThis,
743 const XML_Char *sTarget ,
744 const XML_Char *sData )
745{
746 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
747 if( pImpl->rDocumentHandler.is() ) {
749 pImpl ,
750 rDocumentHandler->processingInstruction( XML_CHAR_TO_OUSTRING( sTarget ),
751 XML_CHAR_TO_OUSTRING( sData ) ) );
752 }
753}
754
755
756void SaxExpatParser_Impl::callbackEntityDecl(
757 void *pvThis, const XML_Char *entityName,
758 SAL_UNUSED_PARAMETER int /*is_parameter_entity*/,
759 const XML_Char *value, SAL_UNUSED_PARAMETER int /*value_length*/,
760 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
761 const XML_Char *publicId, const XML_Char *notationName)
762{
763 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
764 if (value) { // value != 0 means internal entity
765 SAL_INFO("sax","SaxExpatParser: internal entity declaration, stopping");
766 XML_StopParser(pImpl->getEntity().pParser, XML_FALSE);
767 pImpl->exception = SAXParseException(
768 "SaxExpatParser: internal entity declaration, stopping",
769 nullptr, css::uno::Any(),
770 pImpl->rDocumentLocator->getPublicId(),
771 pImpl->rDocumentLocator->getSystemId(),
772 pImpl->rDocumentLocator->getLineNumber(),
773 pImpl->rDocumentLocator->getColumnNumber() );
774 pImpl->bExceptionWasThrown = true;
775 } else {
776 if( pImpl->rDTDHandler.is() ) {
778 pImpl ,
779 rDTDHandler->unparsedEntityDecl(
780 XML_CHAR_TO_OUSTRING( entityName ),
781 XML_CHAR_TO_OUSTRING( publicId ) ,
782 XML_CHAR_TO_OUSTRING( systemId ) ,
783 XML_CHAR_TO_OUSTRING( notationName ) ) );
784 }
785 }
786}
787
788void SaxExpatParser_Impl::callbackNotationDecl(
789 void *pvThis, const XML_Char *notationName,
790 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
791 const XML_Char *publicId)
792{
793 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
794 if( pImpl->rDTDHandler.is() ) {
796 rDTDHandler->notationDecl( XML_CHAR_TO_OUSTRING( notationName ) ,
797 XML_CHAR_TO_OUSTRING( publicId ) ,
798 XML_CHAR_TO_OUSTRING( systemId ) ) );
799 }
800
801}
802
803
804bool SaxExpatParser_Impl::callbackExternalEntityRef(
805 XML_Parser parser, const XML_Char *context,
806 SAL_UNUSED_PARAMETER const XML_Char * /*base*/, const XML_Char *systemId,
807 const XML_Char *publicId)
808{
809 bool bOK = true;
810 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(XML_GetUserData( parser ));
811
812 struct Entity entity;
813
814 if( pImpl->rEntityResolver.is() ) {
815 try
816 {
817 entity.structSource = pImpl->rEntityResolver->resolveEntity(
818 XML_CHAR_TO_OUSTRING( publicId ) ,
819 XML_CHAR_TO_OUSTRING( systemId ) );
820 }
821 catch( const SAXParseException & e )
822 {
823 pImpl->exception = e;
824 bOK = false;
825 }
826 catch( const SAXException & e )
827 {
828 pImpl->exception = SAXParseException(
829 e.Message , e.Context , e.WrappedException ,
830 pImpl->rDocumentLocator->getPublicId(),
831 pImpl->rDocumentLocator->getSystemId(),
832 pImpl->rDocumentLocator->getLineNumber(),
833 pImpl->rDocumentLocator->getColumnNumber() );
834 bOK = false;
835 }
836 }
837
838 if( entity.structSource.aInputStream.is() ) {
839 entity.pParser = XML_ExternalEntityParserCreate( parser , context, nullptr );
840 if( ! entity.pParser )
841 {
842 return false;
843 }
844
845 entity.converter.setInputStream( entity.structSource.aInputStream );
846 auto const xmlParser = entity.pParser;
847 pImpl->pushEntity( std::move(entity) );
848 try
849 {
850 pImpl->parse();
851 }
852 catch( const SAXParseException & e )
853 {
854 pImpl->exception = e;
855 bOK = false;
856 }
857 catch( const IOException &e )
858 {
859 pImpl->exception.WrappedException <<= e;
860 bOK = false;
861 }
862 catch( const css::uno::RuntimeException &e )
863 {
864 pImpl->exception.WrappedException <<=e;
865 bOK = false;
866 }
867
868 pImpl->popEntity();
869
870 XML_ParserFree( xmlParser );
871 }
872
873 return bOK;
874}
875
876int SaxExpatParser_Impl::callbackUnknownEncoding(
877 SAL_UNUSED_PARAMETER void * /*encodingHandlerData*/,
878 SAL_UNUSED_PARAMETER const XML_Char * /*name*/,
879 SAL_UNUSED_PARAMETER XML_Encoding * /*info*/)
880{
881 return 0;
882}
883
884void SaxExpatParser_Impl::callbackDefault( void *pvThis, const XML_Char *s, int len)
885{
886 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
887
889 rExtendedDocumentHandler->unknown( XML_CHAR_N_TO_USTRING( s ,len) ) );
890}
891
892void SaxExpatParser_Impl::callbackComment( void *pvThis , const XML_Char *s )
893{
894 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
896 rExtendedDocumentHandler->comment( XML_CHAR_TO_OUSTRING( s ) ) );
897}
898
899void SaxExpatParser_Impl::callbackStartCDATA( void *pvThis )
900{
901 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
902
903 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, rExtendedDocumentHandler->startCDATA() );
904}
905
906
907void SaxExpatParser_Impl::callErrorHandler( SaxExpatParser_Impl *pImpl ,
908 const SAXParseException & e )
909{
910 try
911 {
912 if( pImpl->rErrorHandler.is() ) {
913 css::uno::Any a;
914 a <<= e;
915 pImpl->rErrorHandler->error( a );
916 }
917 else {
918 pImpl->exception = e;
919 pImpl->bExceptionWasThrown = true;
920 }
921 }
922 catch( const SAXParseException & ex ) {
923 pImpl->exception = ex;
924 pImpl->bExceptionWasThrown = true;
925 }
926 catch( const SAXException & ex ) {
927 pImpl->exception = SAXParseException(
928 ex.Message,
929 ex.Context,
930 ex.WrappedException,
931 pImpl->rDocumentLocator->getPublicId(),
932 pImpl->rDocumentLocator->getSystemId(),
933 pImpl->rDocumentLocator->getLineNumber(),
934 pImpl->rDocumentLocator->getColumnNumber()
935 );
936 pImpl->bExceptionWasThrown = true;
937 }
938}
939
940void SaxExpatParser_Impl::callbackEndCDATA( void *pvThis )
941{
942 SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
943
944 CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pImpl,rExtendedDocumentHandler->endCDATA() );
945}
946
947} // namespace
948
949extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface *
951 css::uno::XComponentContext *,
952 css::uno::Sequence<css::uno::Any> const &)
953{
954 return cppu::acquire(new SaxExpatParser);
955}
956
957/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
::std::unique_ptr< XmlIdRegistry_Impl > m_pImpl
FastSaxParserImpl & m_rParser
Definition: fastparser.cxx:765
void * p
uno_Any a
#define SAL_INFO(area, stream)
double getLength(const B2DPolygon &rCandidate)
void setLocale(const LanguageTag &languageTag)
css::uno::Sequence< OUString > getSupportedServiceNames()
OUString getImplementationName()
bool CPPUHELPER_DLLPUBLIC supportsService(css::lang::XServiceInfo *implementation, rtl::OUString const &name)
int i
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
bool parse(OUString const &uri, SourceProviderScannerData *data)
std::mutex aMutex
#define XML_CHAR_N_TO_USTRING(x, n)
Definition: sax_expat.cxx:59
#define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis, call)
Definition: sax_expat.cxx:67
SAL_DLLPUBLIC_EXPORT css::uno::XInterface * com_sun_star_comp_extensions_xml_sax_ParserExpat_get_implementation(css::uno::XComponentContext *, css::uno::Sequence< css::uno::Any > const &)
Definition: sax_expat.cxx:950
#define XML_CHAR_TO_OUSTRING(x)
Definition: sax_expat.cxx:58
unsigned char sal_Bool