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