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