Line data Source code
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 : #include <stdlib.h>
20 : #include <string.h>
21 : #include <sal/alloca.h>
22 : #include <cassert>
23 : #include <vector>
24 :
25 : #include <osl/diagnose.h>
26 :
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>
35 :
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>
41 :
42 : #include <expat.h>
43 :
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;
50 :
51 : #include "attrlistimpl.hxx"
52 : #include "xml2utf.hxx"
53 :
54 : namespace {
55 :
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 )
59 : {
60 : if( p ) {
61 : if( sizeof( sal_Unicode ) == sizeof( XML_Char ) )
62 : {
63 : return OUString( (sal_Unicode*)p,nLen);
64 : }
65 : else
66 : {
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];
70 : }
71 : return OUString( pWchar , nLen );
72 : }
73 : }
74 : else {
75 : return OUString();
76 : }
77 : }
78 :
79 : OUString XmlChar2OUString( const XML_Char *p )
80 : {
81 : if( p ) {
82 : int nLen;
83 : for( nLen = 0 ; p[nLen] ; nLen ++ )
84 : ;
85 : return XmlNChar2OUString( p , nLen );
86 : }
87 : else return OUString();
88 : }
89 :
90 :
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
97 :
98 :
99 : /*
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.
103 : */
104 : #define CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pThis,call) \
105 : if( ! pThis->bExceptionWasThrown ) { \
106 : try {\
107 : pThis->call;\
108 : }\
109 : catch( const SAXParseException &e ) {\
110 : callErrorHandler( pThis , e );\
111 : }\
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 : ) );\
122 : }\
123 : catch( const com::sun::star::uno::RuntimeException &e ) {\
124 : pThis->bExceptionWasThrown = true; \
125 : pThis->bRTExceptionWasThrown = true; \
126 : pImpl->rtexception = e; \
127 : }\
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)); \
132 : }\
133 : }\
134 : ((void)0)
135 :
136 :
137 : class SaxExpatParser_Impl;
138 :
139 : // This class implements the external Parser interface
140 : class SaxExpatParser
141 : : public WeakImplHelper3< XInitialization
142 : , XServiceInfo
143 : , XParser >
144 : {
145 :
146 : public:
147 : SaxExpatParser();
148 : virtual ~SaxExpatParser();
149 :
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;
153 :
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;
161 :
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;
168 :
169 : virtual void SAL_CALL setLocale( const Locale &locale ) throw (css::uno::RuntimeException, std::exception) SAL_OVERRIDE;
170 :
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;
175 :
176 : private:
177 :
178 : SaxExpatParser_Impl *m_pImpl;
179 :
180 : };
181 :
182 :
183 : // Entity binds all information neede for a single file
184 83654 : struct Entity
185 : {
186 : InputSource structSource;
187 : XML_Parser pParser;
188 : sax_expatwrap::XMLFile2UTFConverter converter;
189 : };
190 :
191 :
192 26233 : class SaxExpatParser_Impl
193 : {
194 : public: // module scope
195 : Mutex aMutex;
196 : OUString sCDATA;
197 : bool m_bEnableDoS; // fdo#60471 thank you Adobe Illustrator
198 :
199 : css::uno::Reference< XDocumentHandler > rDocumentHandler;
200 : css::uno::Reference< XExtendedDocumentHandler > rExtendedDocumentHandler;
201 :
202 : css::uno::Reference< XErrorHandler > rErrorHandler;
203 : css::uno::Reference< XDTDHandler > rDTDHandler;
204 : css::uno::Reference< XEntityResolver > rEntityResolver;
205 : css::uno::Reference < XLocator > rDocumentLocator;
206 :
207 :
208 : rtl::Reference < sax_expatwrap::AttributeList > rAttrList;
209 :
210 : // External entity stack
211 : vector<struct Entity> vecEntity;
212 20738 : void pushEntity( const struct Entity &entity )
213 20738 : { vecEntity.push_back( entity ); }
214 20738 : void popEntity()
215 20738 : { vecEntity.pop_back( ); }
216 84501 : struct Entity &getEntity()
217 84501 : { return vecEntity.back(); }
218 :
219 :
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;
226 :
227 : Locale locale;
228 :
229 : public:
230 26233 : SaxExpatParser_Impl()
231 : : sCDATA("CDATA")
232 : , m_bEnableDoS(false)
233 : , bExceptionWasThrown(false)
234 26233 : , bRTExceptionWasThrown(false)
235 : {
236 26233 : }
237 :
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 );
245 :
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);
255 :
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);
261 :
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);
267 :
268 : int static callbackUnknownEncoding(void *encodingHandlerData,
269 : const XML_Char *name,
270 : XML_Encoding *info);
271 :
272 : void static callbackDefault( void *userData, const XML_Char *s, int len);
273 :
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 );
278 :
279 : public:
280 : void parse();
281 : };
282 :
283 : extern "C"
284 : {
285 453046 : static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts)
286 : {
287 453046 : SaxExpatParser_Impl::callbackStartElement(userData,name,atts);
288 453046 : }
289 453046 : static void call_callbackEndElement(void *userData, const XML_Char *name)
290 : {
291 453046 : SaxExpatParser_Impl::callbackEndElement(userData,name);
292 453046 : }
293 449218 : static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen )
294 : {
295 449218 : SaxExpatParser_Impl::callbackCharacters(userData,s,nLen);
296 449218 : }
297 0 : static void call_callbackProcessingInstruction(void *userData,const XML_Char *sTarget,const XML_Char *sData )
298 : {
299 0 : SaxExpatParser_Impl::callbackProcessingInstruction(userData,sTarget,sData );
300 0 : }
301 0 : 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)
310 : {
311 : SaxExpatParser_Impl::callbackEntityDecl(userData, entityName,
312 : is_parameter_entity, value, value_length,
313 0 : base, systemId, publicId, notationName);
314 0 : }
315 0 : 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)
320 : {
321 0 : SaxExpatParser_Impl::callbackNotationDecl(userData,notationName,base,systemId,publicId);
322 0 : }
323 0 : 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)
328 : {
329 0 : return SaxExpatParser_Impl::callbackExternalEntityRef(parser,openEntityNames,base,systemId,publicId);
330 : }
331 0 : static int call_callbackUnknownEncoding(void *encodingHandlerData,
332 : const XML_Char *name,
333 : XML_Encoding *info)
334 : {
335 0 : return SaxExpatParser_Impl::callbackUnknownEncoding(encodingHandlerData,name,info);
336 : }
337 8337 : static void call_callbackDefault( void *userData, const XML_Char *s, int len)
338 : {
339 8337 : SaxExpatParser_Impl::callbackDefault(userData,s,len);
340 8337 : }
341 0 : static void call_callbackStartCDATA( void *userData )
342 : {
343 0 : SaxExpatParser_Impl::callbackStartCDATA(userData);
344 0 : }
345 0 : static void call_callbackEndCDATA( void *userData )
346 : {
347 0 : SaxExpatParser_Impl::callbackEndCDATA(userData);
348 0 : }
349 534 : static void call_callbackComment( void *userData , const XML_Char *s )
350 : {
351 534 : SaxExpatParser_Impl::callbackComment(userData,s);
352 534 : }
353 : }
354 :
355 :
356 :
357 : // LocatorImpl
358 :
359 52466 : class LocatorImpl :
360 : public WeakImplHelper2< XLocator, com::sun::star::io::XSeekable >
361 : // should use a different interface for stream positions!
362 : {
363 : public:
364 26233 : explicit LocatorImpl(SaxExpatParser_Impl *p)
365 26233 : : m_pParser(p)
366 : {
367 26233 : }
368 :
369 : public: //XLocator
370 154 : virtual sal_Int32 SAL_CALL getColumnNumber() throw (std::exception) SAL_OVERRIDE
371 : {
372 154 : return XML_GetCurrentColumnNumber( m_pParser->getEntity().pParser );
373 : }
374 159 : virtual sal_Int32 SAL_CALL getLineNumber() throw (std::exception) SAL_OVERRIDE
375 : {
376 159 : return XML_GetCurrentLineNumber( m_pParser->getEntity().pParser );
377 : }
378 154 : virtual OUString SAL_CALL getPublicId() throw (std::exception) SAL_OVERRIDE
379 : {
380 154 : return m_pParser->getEntity().structSource.sPublicId;
381 : }
382 159 : virtual OUString SAL_CALL getSystemId() throw (std::exception) SAL_OVERRIDE
383 : {
384 159 : return m_pParser->getEntity().structSource.sSystemId;
385 : }
386 :
387 : // XSeekable (only for getPosition)
388 :
389 0 : virtual void SAL_CALL seek( sal_Int64 ) throw(std::exception) SAL_OVERRIDE
390 : {
391 0 : }
392 580 : virtual sal_Int64 SAL_CALL getPosition() throw(std::exception) SAL_OVERRIDE
393 : {
394 580 : return XML_GetCurrentByteIndex( m_pParser->getEntity().pParser );
395 : }
396 0 : virtual ::sal_Int64 SAL_CALL getLength() throw(std::exception) SAL_OVERRIDE
397 : {
398 0 : return 0;
399 : }
400 :
401 : private:
402 :
403 : SaxExpatParser_Impl *m_pParser;
404 : };
405 :
406 :
407 :
408 :
409 26233 : SaxExpatParser::SaxExpatParser( )
410 : {
411 26233 : m_pImpl = new SaxExpatParser_Impl;
412 :
413 26233 : LocatorImpl *pLoc = new LocatorImpl( m_pImpl );
414 26233 : m_pImpl->rDocumentLocator = css::uno::Reference< XLocator > ( pLoc );
415 :
416 : // Performance-improvement; handing out the same object with every call of
417 : // the startElement callback is allowed (see sax-specification):
418 26233 : m_pImpl->rAttrList = new sax_expatwrap::AttributeList;
419 :
420 26233 : m_pImpl->bExceptionWasThrown = false;
421 26233 : m_pImpl->bRTExceptionWasThrown = false;
422 26233 : }
423 :
424 78699 : SaxExpatParser::~SaxExpatParser()
425 : {
426 26233 : delete m_pImpl;
427 52466 : }
428 :
429 : // ::com::sun::star::lang::XInitialization:
430 : void SAL_CALL
431 299 : SaxExpatParser::initialize(css::uno::Sequence< css::uno::Any > const& rArguments)
432 : throw (css::uno::RuntimeException, css::uno::Exception, std::exception)
433 : {
434 : // possible arguments: a string "DoSmeplease"
435 299 : if (rArguments.getLength())
436 : {
437 299 : OUString str;
438 299 : if ((rArguments[0] >>= str) && "DoSmeplease" == str)
439 : {
440 299 : MutexGuard guard( m_pImpl->aMutex );
441 299 : m_pImpl->m_bEnableDoS = true;
442 299 : }
443 : }
444 299 : }
445 :
446 : /***************
447 : *
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)
450 : *
451 : ****************/
452 21089 : void SaxExpatParser::parseStream( const InputSource& structSource)
453 : throw (SAXException,
454 : IOException,
455 : css::uno::RuntimeException, std::exception)
456 : {
457 : // Only one text at one time
458 21089 : MutexGuard guard( m_pImpl->aMutex );
459 :
460 :
461 42178 : struct Entity entity;
462 21089 : entity.structSource = structSource;
463 :
464 21089 : if( ! entity.structSource.aInputStream.is() )
465 : {
466 : throw SAXException("No input source",
467 351 : css::uno::Reference< css::uno::XInterface > () , css::uno::Any() );
468 : }
469 :
470 20738 : entity.converter.setInputStream( entity.structSource.aInputStream );
471 20738 : if( !entity.structSource.sEncoding.isEmpty() )
472 : {
473 : entity.converter.setEncoding(
474 0 : OUStringToOString( entity.structSource.sEncoding , RTL_TEXTENCODING_ASCII_US ) );
475 : }
476 :
477 : // create parser with proper encoding
478 20738 : entity.pParser = XML_ParserCreate( 0 );
479 20738 : if( ! entity.pParser )
480 : {
481 : throw SAXException("Couldn't create parser",
482 0 : css::uno::Reference< css::uno::XInterface > (), css::uno::Any() );
483 : }
484 :
485 : // set all necessary C-Callbacks
486 20738 : XML_SetUserData( entity.pParser , m_pImpl );
487 : XML_SetElementHandler( entity.pParser ,
488 : call_callbackStartElement ,
489 20738 : call_callbackEndElement );
490 20738 : XML_SetCharacterDataHandler( entity.pParser , call_callbackCharacters );
491 : XML_SetProcessingInstructionHandler(entity.pParser ,
492 20738 : call_callbackProcessingInstruction );
493 20738 : if (!m_pImpl->m_bEnableDoS)
494 : {
495 20439 : XML_SetEntityDeclHandler(entity.pParser, call_callbackEntityDecl);
496 : }
497 20738 : XML_SetNotationDeclHandler( entity.pParser, call_callbackNotationDecl );
498 : XML_SetExternalEntityRefHandler( entity.pParser,
499 20738 : call_callbackExternalEntityRef);
500 20738 : XML_SetUnknownEncodingHandler( entity.pParser, call_callbackUnknownEncoding ,0);
501 :
502 20738 : if( m_pImpl->rExtendedDocumentHandler.is() ) {
503 :
504 : // These handlers just delegate calls to the ExtendedHandler. If no extended handler is
505 : // given, these callbacks can be ignored
506 2659 : XML_SetDefaultHandlerExpand( entity.pParser, call_callbackDefault );
507 2659 : XML_SetCommentHandler( entity.pParser, call_callbackComment );
508 : XML_SetCdataSectionHandler( entity.pParser ,
509 : call_callbackStartCDATA ,
510 2659 : call_callbackEndCDATA );
511 : }
512 :
513 :
514 20738 : m_pImpl->exception = SAXParseException();
515 20738 : m_pImpl->pushEntity( entity );
516 : try
517 : {
518 : // start the document
519 20738 : if( m_pImpl->rDocumentHandler.is() ) {
520 20734 : m_pImpl->rDocumentHandler->setDocumentLocator( m_pImpl->rDocumentLocator );
521 20734 : m_pImpl->rDocumentHandler->startDocument();
522 : }
523 :
524 20738 : m_pImpl->parse();
525 :
526 : // finish document
527 20733 : if( m_pImpl->rDocumentHandler.is() ) {
528 20729 : m_pImpl->rDocumentHandler->endDocument();
529 : }
530 : }
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 10 : catch( SAXException & )
540 : {
541 5 : m_pImpl->popEntity();
542 5 : XML_ParserFree( entity.pParser );
543 5 : throw;
544 : }
545 0 : catch( IOException & )
546 : {
547 0 : m_pImpl->popEntity();
548 0 : XML_ParserFree( entity.pParser );
549 0 : throw;
550 : }
551 0 : catch( css::uno::RuntimeException & )
552 : {
553 0 : m_pImpl->popEntity();
554 0 : XML_ParserFree( entity.pParser );
555 0 : throw;
556 : }
557 :
558 20733 : m_pImpl->popEntity();
559 41822 : XML_ParserFree( entity.pParser );
560 20733 : }
561 :
562 36109 : void SaxExpatParser::setDocumentHandler(const css::uno::Reference< XDocumentHandler > & xHandler)
563 : throw (css::uno::RuntimeException, std::exception)
564 : {
565 36109 : m_pImpl->rDocumentHandler = xHandler;
566 72218 : m_pImpl->rExtendedDocumentHandler =
567 36109 : css::uno::Reference< XExtendedDocumentHandler >( xHandler , css::uno::UNO_QUERY );
568 36109 : }
569 :
570 0 : void SaxExpatParser::setErrorHandler(const css::uno::Reference< XErrorHandler > & xHandler)
571 : throw (css::uno::RuntimeException, std::exception)
572 : {
573 0 : m_pImpl->rErrorHandler = xHandler;
574 0 : }
575 :
576 0 : void SaxExpatParser::setDTDHandler(const css::uno::Reference< XDTDHandler > & xHandler)
577 : throw (css::uno::RuntimeException, std::exception)
578 : {
579 0 : m_pImpl->rDTDHandler = xHandler;
580 0 : }
581 :
582 245 : void SaxExpatParser::setEntityResolver(const css::uno::Reference < XEntityResolver > & xResolver)
583 : throw (css::uno::RuntimeException, std::exception)
584 : {
585 245 : m_pImpl->rEntityResolver = xResolver;
586 245 : }
587 :
588 :
589 0 : void SaxExpatParser::setLocale( const Locale & locale ) throw (css::uno::RuntimeException, std::exception)
590 : {
591 0 : m_pImpl->locale = locale;
592 0 : }
593 :
594 : // XServiceInfo
595 1 : OUString SaxExpatParser::getImplementationName() throw (std::exception)
596 : {
597 1 : return OUString("com.sun.star.comp.extensions.xml.sax.ParserExpat");
598 : }
599 :
600 : // XServiceInfo
601 0 : sal_Bool SaxExpatParser::supportsService(const OUString& ServiceName) throw (std::exception)
602 : {
603 0 : return cppu::supportsService(this, ServiceName);
604 : }
605 :
606 : // XServiceInfo
607 1 : css::uno::Sequence< OUString > SaxExpatParser::getSupportedServiceNames() throw (std::exception)
608 : {
609 1 : css::uno::Sequence<OUString> seq(1);
610 1 : seq[0] = "com.sun.star.xml.sax.Parser";
611 1 : return seq;
612 : }
613 :
614 :
615 : /*---------------------------------------
616 : *
617 : * Helper functions and classes
618 : *
619 : *
620 : *-------------------------------------------*/
621 5 : OUString getErrorMessage( XML_Error xmlE, const OUString& sSystemId , sal_Int32 nLine )
622 : {
623 5 : OUString Message;
624 5 : if( XML_ERROR_NONE == xmlE ) {
625 0 : Message = "No";
626 : }
627 5 : else if( XML_ERROR_NO_MEMORY == xmlE ) {
628 0 : Message = "no memory";
629 : }
630 5 : else if( XML_ERROR_SYNTAX == xmlE ) {
631 0 : Message = "syntax";
632 : }
633 5 : else if( XML_ERROR_NO_ELEMENTS == xmlE ) {
634 0 : Message = "no elements";
635 : }
636 5 : else if( XML_ERROR_INVALID_TOKEN == xmlE ) {
637 5 : Message = "invalid token";
638 : }
639 0 : else if( XML_ERROR_UNCLOSED_TOKEN == xmlE ) {
640 0 : Message = "unclosed token";
641 : }
642 0 : else if( XML_ERROR_PARTIAL_CHAR == xmlE ) {
643 0 : Message = "partial char";
644 : }
645 0 : else if( XML_ERROR_TAG_MISMATCH == xmlE ) {
646 0 : Message = "tag mismatch";
647 : }
648 0 : else if( XML_ERROR_DUPLICATE_ATTRIBUTE == xmlE ) {
649 0 : Message = "duplicate attribute";
650 : }
651 0 : else if( XML_ERROR_JUNK_AFTER_DOC_ELEMENT == xmlE ) {
652 0 : Message = "junk after doc element";
653 : }
654 0 : else if( XML_ERROR_PARAM_ENTITY_REF == xmlE ) {
655 0 : Message = "parameter entity reference";
656 : }
657 0 : else if( XML_ERROR_UNDEFINED_ENTITY == xmlE ) {
658 0 : Message = "undefined entity";
659 : }
660 0 : else if( XML_ERROR_RECURSIVE_ENTITY_REF == xmlE ) {
661 0 : Message = "recursive entity reference";
662 : }
663 0 : else if( XML_ERROR_ASYNC_ENTITY == xmlE ) {
664 0 : Message = "async entity";
665 : }
666 0 : else if( XML_ERROR_BAD_CHAR_REF == xmlE ) {
667 0 : Message = "bad char reference";
668 : }
669 0 : else if( XML_ERROR_BINARY_ENTITY_REF == xmlE ) {
670 0 : Message = "binary entity reference";
671 : }
672 0 : else if( XML_ERROR_ATTRIBUTE_EXTERNAL_ENTITY_REF == xmlE ) {
673 0 : Message = "attribute external entity reference";
674 : }
675 0 : else if( XML_ERROR_MISPLACED_XML_PI == xmlE ) {
676 0 : Message = "misplaced xml processing instruction";
677 : }
678 0 : else if( XML_ERROR_UNKNOWN_ENCODING == xmlE ) {
679 0 : Message = "unknown encoding";
680 : }
681 0 : else if( XML_ERROR_INCORRECT_ENCODING == xmlE ) {
682 0 : Message = "incorrect encoding";
683 : }
684 0 : else if( XML_ERROR_UNCLOSED_CDATA_SECTION == xmlE ) {
685 0 : Message = "unclosed cdata section";
686 : }
687 0 : else if( XML_ERROR_EXTERNAL_ENTITY_HANDLING == xmlE ) {
688 0 : Message = "external entity reference";
689 : }
690 0 : else if( XML_ERROR_NOT_STANDALONE == xmlE ) {
691 0 : Message = "not standalone";
692 : }
693 :
694 5 : OUString str("[");
695 5 : str += sSystemId;
696 5 : str += " line ";
697 5 : str += OUString::number( nLine );
698 5 : str += "]: ";
699 5 : str += Message;
700 5 : str += "error";
701 :
702 5 : return str;
703 : }
704 :
705 :
706 : // starts parsing with actual parser !
707 20738 : void SaxExpatParser_Impl::parse( )
708 : {
709 20738 : const int nBufSize = 16*1024;
710 :
711 20738 : int nRead = nBufSize;
712 20738 : css::uno::Sequence< sal_Int8 > seqOut(nBufSize);
713 :
714 62383 : while( nRead ) {
715 41645 : nRead = getEntity().converter.readAndConvert( seqOut , nBufSize );
716 :
717 41645 : if( ! nRead ) {
718 20733 : XML_Parse( getEntity().pParser ,
719 20733 : reinterpret_cast<const char *>(seqOut.getConstArray()),
720 : 0 ,
721 20733 : 1 );
722 20733 : break;
723 : }
724 :
725 20912 : bool bContinue = ( XML_Parse( getEntity().pParser ,
726 20912 : reinterpret_cast<const char *>(seqOut.getConstArray()),
727 : nRead,
728 20912 : 0 ) != XML_STATUS_ERROR );
729 :
730 20912 : if( ! bContinue || this->bExceptionWasThrown ) {
731 :
732 5 : if ( this->bRTExceptionWasThrown )
733 0 : throw rtexception;
734 :
735 : // Error during parsing !
736 5 : XML_Error xmlE = XML_GetErrorCode( getEntity().pParser );
737 5 : OUString sSystemId = rDocumentLocator->getSystemId();
738 5 : sal_Int32 nLine = rDocumentLocator->getLineNumber();
739 :
740 : SAXParseException aExcept(
741 : getErrorMessage(xmlE , sSystemId, nLine) ,
742 : css::uno::Reference< css::uno::XInterface >(),
743 5 : css::uno::Any( &exception , cppu::UnoType<decltype(exception)>::get() ),
744 5 : rDocumentLocator->getPublicId(),
745 5 : rDocumentLocator->getSystemId(),
746 5 : rDocumentLocator->getLineNumber(),
747 5 : rDocumentLocator->getColumnNumber()
748 30 : );
749 :
750 5 : if( rErrorHandler.is() ) {
751 :
752 : // error handler is set, so the handler may throw the exception
753 0 : css::uno::Any a;
754 0 : a <<= aExcept;
755 0 : rErrorHandler->fatalError( a );
756 : }
757 :
758 : // Error handler has not thrown an exception, but parsing cannot go on,
759 : // so an exception MUST be thrown.
760 10 : throw aExcept;
761 : } // if( ! bContinue )
762 20738 : } // while
763 20733 : }
764 :
765 :
766 :
767 : // The C-Callbacks
768 :
769 :
770 453046 : void SaxExpatParser_Impl::callbackStartElement( void *pvThis ,
771 : const XML_Char *pwName ,
772 : const XML_Char **awAttributes )
773 : {
774 453046 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
775 :
776 453046 : if( pImpl->rDocumentHandler.is() ) {
777 :
778 452875 : int i = 0;
779 452875 : pImpl->rAttrList->clear();
780 :
781 1846052 : while( awAttributes[i] ) {
782 : assert(awAttributes[i+1]);
783 : pImpl->rAttrList->addAttribute(
784 1880604 : XML_CHAR_TO_OUSTRING( awAttributes[i] ) ,
785 : pImpl->sCDATA, // expat doesn't know types
786 2820906 : XML_CHAR_TO_OUSTRING( awAttributes[i+1] ) );
787 940302 : i +=2;
788 : }
789 :
790 452875 : CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
791 : pImpl ,
792 : rDocumentHandler->startElement( XML_CHAR_TO_OUSTRING( pwName ) ,
793 : pImpl->rAttrList.get() ) );
794 : }
795 453046 : }
796 :
797 453046 : void SaxExpatParser_Impl::callbackEndElement( void *pvThis , const XML_Char *pwName )
798 : {
799 453046 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
800 :
801 453046 : if( pImpl->rDocumentHandler.is() ) {
802 452875 : CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
803 : rDocumentHandler->endElement( XML_CHAR_TO_OUSTRING( pwName ) ) );
804 : }
805 453046 : }
806 :
807 :
808 449218 : void SaxExpatParser_Impl::callbackCharacters( void *pvThis , const XML_Char *s , int nLen )
809 : {
810 449218 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
811 :
812 449218 : if( pImpl->rDocumentHandler.is() ) {
813 449133 : CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl ,
814 : rDocumentHandler->characters( XML_CHAR_N_TO_USTRING(s,nLen) ) );
815 : }
816 449218 : }
817 :
818 0 : void SaxExpatParser_Impl::callbackProcessingInstruction( void *pvThis,
819 : const XML_Char *sTarget ,
820 : const XML_Char *sData )
821 : {
822 0 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
823 0 : if( pImpl->rDocumentHandler.is() ) {
824 0 : CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(
825 : pImpl ,
826 : rDocumentHandler->processingInstruction( XML_CHAR_TO_OUSTRING( sTarget ),
827 : XML_CHAR_TO_OUSTRING( sData ) ) );
828 : }
829 0 : }
830 :
831 :
832 0 : 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)
838 : {
839 0 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
840 0 : if (value) { // value != 0 means internal entity
841 : SAL_INFO("sax","SaxExpatParser: internal entity declaration, stopping");
842 0 : XML_StopParser(pImpl->getEntity().pParser, XML_FALSE);
843 0 : pImpl->exception = SAXParseException(
844 : "SaxExpatParser: internal entity declaration, stopping",
845 : 0, css::uno::Any(),
846 0 : pImpl->rDocumentLocator->getPublicId(),
847 0 : pImpl->rDocumentLocator->getSystemId(),
848 0 : pImpl->rDocumentLocator->getLineNumber(),
849 0 : pImpl->rDocumentLocator->getColumnNumber() );
850 0 : pImpl->bExceptionWasThrown = true;
851 : } else {
852 0 : if( pImpl->rDTDHandler.is() ) {
853 0 : 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 ) ) );
860 : }
861 : }
862 0 : }
863 :
864 0 : 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)
868 : {
869 0 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
870 0 : if( pImpl->rDTDHandler.is() ) {
871 0 : 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 ) ) );
875 : }
876 :
877 0 : }
878 :
879 :
880 :
881 0 : 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)
885 : {
886 0 : bool bOK = true;
887 0 : InputSource source;
888 0 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(XML_GetUserData( parser ));
889 :
890 0 : struct Entity entity;
891 :
892 0 : if( pImpl->rEntityResolver.is() ) {
893 : try
894 : {
895 0 : entity.structSource = pImpl->rEntityResolver->resolveEntity(
896 0 : XML_CHAR_TO_OUSTRING( publicId ) ,
897 0 : XML_CHAR_TO_OUSTRING( systemId ) );
898 : }
899 0 : catch( const SAXParseException & e )
900 : {
901 0 : pImpl->exception = e;
902 0 : bOK = false;
903 : }
904 0 : catch( const SAXException & e )
905 : {
906 0 : pImpl->exception = SAXParseException(
907 : e.Message , e.Context , e.WrappedException ,
908 0 : pImpl->rDocumentLocator->getPublicId(),
909 0 : pImpl->rDocumentLocator->getSystemId(),
910 0 : pImpl->rDocumentLocator->getLineNumber(),
911 0 : pImpl->rDocumentLocator->getColumnNumber() );
912 0 : bOK = false;
913 : }
914 : }
915 :
916 0 : if( entity.structSource.aInputStream.is() ) {
917 0 : entity.pParser = XML_ExternalEntityParserCreate( parser , context, 0 );
918 0 : if( ! entity.pParser )
919 : {
920 0 : return false;
921 : }
922 :
923 0 : entity.converter.setInputStream( entity.structSource.aInputStream );
924 0 : pImpl->pushEntity( entity );
925 : try
926 : {
927 0 : pImpl->parse();
928 : }
929 0 : catch( const SAXParseException & e )
930 : {
931 0 : pImpl->exception = e;
932 0 : bOK = false;
933 : }
934 0 : catch( const IOException &e )
935 : {
936 0 : pImpl->exception.WrappedException <<= e;
937 0 : bOK = false;
938 : }
939 0 : catch( const css::uno::RuntimeException &e )
940 : {
941 0 : pImpl->exception.WrappedException <<=e;
942 0 : bOK = false;
943 : }
944 :
945 0 : pImpl->popEntity();
946 :
947 0 : XML_ParserFree( entity.pParser );
948 : }
949 :
950 0 : return bOK;
951 : }
952 :
953 0 : 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*/)
957 : {
958 0 : return 0;
959 : }
960 :
961 8337 : void SaxExpatParser_Impl::callbackDefault( void *pvThis, const XML_Char *s, int len)
962 : {
963 8337 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
964 :
965 8337 : CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
966 : rExtendedDocumentHandler->unknown( XML_CHAR_N_TO_USTRING( s ,len) ) );
967 8337 : }
968 :
969 534 : void SaxExpatParser_Impl::callbackComment( void *pvThis , const XML_Char *s )
970 : {
971 534 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
972 534 : CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl,
973 : rExtendedDocumentHandler->comment( XML_CHAR_TO_OUSTRING( s ) ) );
974 534 : }
975 :
976 0 : void SaxExpatParser_Impl::callbackStartCDATA( void *pvThis )
977 : {
978 0 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
979 :
980 0 : CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS( pImpl, rExtendedDocumentHandler->startCDATA() );
981 0 : }
982 :
983 :
984 0 : void SaxExpatParser_Impl::callErrorHandler( SaxExpatParser_Impl *pImpl ,
985 : const SAXParseException & e )
986 : {
987 : try
988 : {
989 0 : if( pImpl->rErrorHandler.is() ) {
990 0 : css::uno::Any a;
991 0 : a <<= e;
992 0 : pImpl->rErrorHandler->error( a );
993 : }
994 : else {
995 0 : pImpl->exception = e;
996 0 : pImpl->bExceptionWasThrown = true;
997 : }
998 : }
999 0 : catch( const SAXParseException & ex ) {
1000 0 : pImpl->exception = ex;
1001 0 : pImpl->bExceptionWasThrown = true;
1002 : }
1003 0 : catch( const SAXException & ex ) {
1004 0 : pImpl->exception = SAXParseException(
1005 : ex.Message,
1006 : ex.Context,
1007 : ex.WrappedException,
1008 0 : pImpl->rDocumentLocator->getPublicId(),
1009 0 : pImpl->rDocumentLocator->getSystemId(),
1010 0 : pImpl->rDocumentLocator->getLineNumber(),
1011 0 : pImpl->rDocumentLocator->getColumnNumber()
1012 0 : );
1013 0 : pImpl->bExceptionWasThrown = true;
1014 : }
1015 0 : }
1016 :
1017 0 : void SaxExpatParser_Impl::callbackEndCDATA( void *pvThis )
1018 : {
1019 0 : SaxExpatParser_Impl *pImpl = static_cast<SaxExpatParser_Impl*>(pvThis);
1020 :
1021 0 : CALL_ELEMENT_HANDLER_AND_CARE_FOR_EXCEPTIONS(pImpl,rExtendedDocumentHandler->endCDATA() );
1022 0 : }
1023 :
1024 : } // namespace
1025 :
1026 : extern "C" SAL_DLLPUBLIC_EXPORT css::uno::XInterface * SAL_CALL
1027 26233 : com_sun_star_comp_extensions_xml_sax_ParserExpat_get_implementation(
1028 : css::uno::XComponentContext *,
1029 : css::uno::Sequence<css::uno::Any> const &)
1030 : {
1031 26233 : return cppu::acquire(new SaxExpatParser);
1032 : }
1033 :
1034 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|