xref: /trunk/main/sax/source/expatwrap/sax_expat.cxx (revision b63233d8)
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