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