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 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 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 //--------------------------------------- 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 192 OUString SaxExpatParser::getImplementationName_Static() throw () 193 { 194 return OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.comp.extensions.xml.sax.ParserExpat" ) ); 195 } 196 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; 238 void pushEntity( const struct Entity &entity ) 239 { vecEntity.push_back( entity ); } 240 void popEntity() 241 { vecEntity.pop_back( ); } 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 { 300 static void call_callbackStartElement(void *userData, const XML_Char *name , const XML_Char **atts) 301 { 302 SaxExpatParser_Impl::callbackStartElement(userData,name,atts); 303 } 304 static void call_callbackEndElement(void *userData, const XML_Char *name) 305 { 306 SaxExpatParser_Impl::callbackEndElement(userData,name); 307 } 308 static void call_callbackCharacters( void *userData , const XML_Char *s , int nLen ) 309 { 310 SaxExpatParser_Impl::callbackCharacters(userData,s,nLen); 311 } 312 static void call_callbackProcessingInstruction(void *userData,const XML_Char *sTarget,const XML_Char *sData ) 313 { 314 SaxExpatParser_Impl::callbackProcessingInstruction(userData,sTarget,sData ); 315 } 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 } 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 } 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 } 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 } 347 static void call_callbackDefault( void *userData, const XML_Char *s, int len) 348 { 349 SaxExpatParser_Impl::callbackDefault(userData,s,len); 350 } 351 static void call_callbackStartCDATA( void *userData ) 352 { 353 SaxExpatParser_Impl::callbackStartCDATA(userData); 354 } 355 static void call_callbackEndCDATA( void *userData ) 356 { 357 SaxExpatParser_Impl::callbackEndCDATA(userData); 358 } 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: 374 LocatorImpl( SaxExpatParser_Impl *p ) 375 { 376 m_pParser = p; 377 } 378 379 public: //XLocator 380 virtual sal_Int32 SAL_CALL getColumnNumber(void) throw () 381 { 382 return XML_GetCurrentColumnNumber( m_pParser->getEntity().pParser ); 383 } 384 virtual sal_Int32 SAL_CALL getLineNumber(void) throw () 385 { 386 return XML_GetCurrentLineNumber( m_pParser->getEntity().pParser ); 387 } 388 virtual OUString SAL_CALL getPublicId(void) throw () 389 { 390 return m_pParser->getEntity().structSource.sPublicId; 391 } 392 virtual OUString SAL_CALL getSystemId(void) throw () 393 { 394 return m_pParser->getEntity().structSource.sSystemId; 395 } 396 397 // XSeekable (only for getPosition) 398 399 virtual void SAL_CALL seek( sal_Int64 ) throw() 400 { 401 } 402 virtual sal_Int64 SAL_CALL getPosition() throw() 403 { 404 return XML_GetCurrentByteIndex( m_pParser->getEntity().pParser ); 405 } 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 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 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 ****************/ 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 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 559 void SaxExpatParser::setErrorHandler(const Reference< XErrorHandler > & xHandler) 560 { 561 m_pImpl->rErrorHandler = xHandler; 562 } 563 564 void SaxExpatParser::setDTDHandler(const Reference< XDTDHandler > & xHandler) 565 { 566 m_pImpl->rDTDHandler = xHandler; 567 } 568 569 void SaxExpatParser::setEntityResolver(const Reference < XEntityResolver > & xResolver) 570 { 571 m_pImpl->rEntityResolver = xResolver; 572 } 573 574 575 void SaxExpatParser::setLocale( const Locale & locale ) 576 { 577 m_pImpl->locale = locale; 578 } 579 580 // XServiceInfo 581 OUString SaxExpatParser::getImplementationName() throw () 582 { 583 return getImplementationName_Static(); 584 } 585 586 // XServiceInfo 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 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 *-------------------------------------------*/ 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 ! 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 //----------------------------------------- 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 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 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 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 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 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 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 937 int SaxExpatParser_Impl::callbackUnknownEncoding(void * /*encodingHandlerData*/, 938 const XML_Char * /*name*/, 939 XML_Encoding * /*info*/) 940 { 941 return 0; 942 } 943 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 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 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 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 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 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 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