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