1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 // MARKER(update_precomp.py): autogen include statement, do not remove 30 #include "precompiled_svx.hxx" 31 #include <com/sun/star/xml/sax/XDocumentHandler.hpp> 32 #include <com/sun/star/xml/sax/InputSource.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/IOException.hpp> 36 #include <cppuhelper/implbase1.hxx> 37 #include <comphelper/processfactory.hxx> 38 #include <unotools/ucbstreamhelper.hxx> 39 #include <unotools/streamwrap.hxx> 40 #include <tools/debug.hxx> 41 #include "comphelper/anytostring.hxx" 42 #include "cppuhelper/exc_hlp.hxx" 43 #include "rtl/ref.hxx" 44 45 #include <svx/msdffimp.hxx> 46 47 #include "xmlconfig.hxx" 48 49 #include <stdio.h> 50 #include <ctype.h> 51 #include <stack> 52 53 using ::rtl::OUString; 54 using ::com::sun::star::io::XInputStream; 55 using ::com::sun::star::io::IOException; 56 57 using namespace ::com::sun::star::uno; 58 using namespace ::com::sun::star::xml::sax; 59 60 /////////////////////////////////////////////////////////////////////// 61 62 AtomConfigMap gAtomConfigMap; 63 64 /////////////////////////////////////////////////////////////////////// 65 66 class ConfigHandler : public ::cppu::WeakAggImplHelper1<XDocumentHandler> 67 { 68 public: 69 // XDocumentHandler 70 virtual void SAL_CALL startDocument(void) throw( SAXException, RuntimeException ); 71 virtual void SAL_CALL endDocument(void) throw( SAXException, RuntimeException ); 72 virtual void SAL_CALL startElement(const OUString& aName, const Reference< XAttributeList > & xAttribs) throw( SAXException, RuntimeException ); 73 virtual void SAL_CALL endElement(const OUString& aName) throw( SAXException, RuntimeException ); 74 virtual void SAL_CALL characters(const OUString& aChars) throw( SAXException, RuntimeException ); 75 virtual void SAL_CALL ignorableWhitespace(const OUString& aWhitespaces) throw( SAXException, RuntimeException ); 76 virtual void SAL_CALL processingInstruction(const OUString& aTarget, const OUString& aData) throw( SAXException, RuntimeException ); 77 virtual void SAL_CALL setDocumentLocator(const Reference< XLocator > & xLocator) throw( SAXException, RuntimeException ); 78 79 private: 80 void errorThrow( const OUString& rErrorMessage ) throw (SAXException ); 81 ElementConfigType parseType( const OUString& rErrorMessage ) throw ( SAXException ); 82 void addElement( ElementConfigPtr& rElementConfig ) throw ( SAXException ); 83 OUString getAttribute( const Reference< XAttributeList > & xAttribs, const sal_Char* pName ) throw( SAXException ); 84 85 ElementConfigPtr importAtomConfig( const Reference< XAttributeList > & xAttribs, bool bIsContainer ) throw( SAXException ); 86 ElementConfigPtr importElementConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException ); 87 ElementConfigPtr importSwitchConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException ); 88 ElementConfigPtr importCaseConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException ); 89 ElementConfigPtr importValueElementConfig( const Reference< XAttributeList > & xAttribs ) throw( SAXException ); 90 91 std::stack< ElementConfigPtr > maElementStack; 92 }; 93 94 void ConfigHandler::errorThrow( const OUString& rErrorMessage ) throw (SAXException ) 95 { 96 Reference< XInterface > aContext; 97 Any aWrappedException; 98 throw SAXException(rErrorMessage, aContext, aWrappedException); 99 } 100 101 ElementConfigType ConfigHandler::parseType( const OUString& sType ) throw (SAXException ) 102 { 103 if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("uint") ) ) 104 { 105 return ECT_UINT; 106 } 107 else if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("byte") ) ) 108 { 109 return ECT_BYTE; 110 } 111 else if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("unistring") ) ) 112 { 113 return ECT_UNISTRING; 114 } 115 else if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("float") ) ) 116 { 117 return ETC_FLOAT; 118 } 119 else if( sType.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM("hexdump") ) ) 120 { 121 } 122 else 123 { 124 OUString aMessage( RTL_CONSTASCII_USTRINGPARAM( "unknown type: " ) ); 125 aMessage += sType; 126 errorThrow( aMessage ); 127 } 128 129 return ECT_HEXDUMP; 130 } 131 132 void ConfigHandler::addElement( ElementConfigPtr& rElementConfig ) throw ( SAXException ) 133 { 134 ElementConfigContainer* pParent = dynamic_cast< ElementConfigContainer* >( maElementStack.top().get() ); 135 136 if( !pParent ) 137 errorThrow( OUString( RTL_CONSTASCII_USTRINGPARAM( "illegal parent for element" ) ) ); 138 139 140 pParent->addElementConfig( rElementConfig ); 141 } 142 143 OUString ConfigHandler::getAttribute( const Reference< XAttributeList > & xAttribs, const sal_Char* pName ) throw( SAXException ) 144 { 145 OUString aName( OUString::createFromAscii( pName ) ); 146 147 const sal_Int16 nAttrCount = xAttribs.is() ? xAttribs->getLength() : 0; 148 sal_Int16 i; 149 for(i=0; i < nAttrCount; i++) 150 { 151 if( xAttribs->getNameByIndex( i ) == aName ) 152 return xAttribs->getValueByIndex( i ); 153 } 154 155 OUString aMessage( RTL_CONSTASCII_USTRINGPARAM( "missing required attribute: ") ); 156 aMessage += aName; 157 errorThrow( aMessage ); 158 159 return OUString(); 160 } 161 162 void SAL_CALL ConfigHandler::startDocument(void) throw( SAXException, RuntimeException ) 163 { 164 } 165 166 void SAL_CALL ConfigHandler::endDocument(void) throw( SAXException, RuntimeException ) 167 { 168 } 169 170 void SAL_CALL ConfigHandler::startElement(const OUString& aName, const Reference< XAttributeList > & xAttribs) throw( SAXException, RuntimeException ) 171 { 172 ElementConfigPtr pElement; 173 174 if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "config" ) ) ) 175 { 176 return; 177 } 178 179 if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "container" ) ) ) 180 { 181 pElement = importAtomConfig( xAttribs, true ); 182 } 183 else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "atom" ) ) ) 184 { 185 pElement = importAtomConfig( xAttribs, false ); 186 } 187 else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "element" ) ) ) 188 { 189 pElement = importElementConfig( xAttribs ); 190 } 191 else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "value" ) ) ) 192 { 193 pElement = importValueElementConfig( xAttribs ); 194 } 195 else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "switch" ) ) ) 196 { 197 pElement = importSwitchConfig( xAttribs ); 198 } 199 else if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "case" ) ) ) 200 { 201 pElement = importCaseConfig( xAttribs ); 202 } 203 204 if( !pElement.get() ) 205 { 206 OUString aMessage( OUString( RTL_CONSTASCII_USTRINGPARAM("unknown config element: ")) ); 207 aMessage += aName; 208 errorThrow( aMessage ); 209 } 210 211 maElementStack.push( pElement ); 212 } 213 214 sal_Int32 toInt( const OUString& rText ) 215 { 216 if( rText.compareToAscii("0x",2) == 0) 217 { 218 sal_Int32 nValue = 0; 219 const sal_Unicode *p = rText; 220 p += 2; 221 sal_Int32 nLength = rText.getLength() - 2; 222 while( (nLength--) > 0 ) 223 { 224 nValue <<= 4; 225 if( *p >= '0' && *p <= '9' ) 226 { 227 nValue += *p - '0'; 228 } 229 else if( *p >= 'a' && *p <= 'f' ) 230 { 231 nValue += *p - ('a' - 10); 232 } 233 else if( *p >= 'A' && *p <= 'F' ) 234 { 235 nValue += *p - ('A' - 10 ); 236 } 237 p++; 238 } 239 240 return nValue; 241 } 242 else 243 { 244 return rText.toInt32(); 245 } 246 } 247 248 ElementConfigPtr ConfigHandler::importAtomConfig( const Reference< XAttributeList > & xAttribs, bool bIsContainer ) throw (SAXException) 249 { 250 if( !maElementStack.empty() ) 251 errorThrow( OUString( RTL_CONSTASCII_USTRINGPARAM("atom elements must be root" ) ) ); 252 253 ElementConfigPtr aPtr( new AtomConfig( getAttribute(xAttribs,"name"), bIsContainer ) ); 254 gAtomConfigMap[ (UINT16)toInt(getAttribute(xAttribs,"id"))] = aPtr; 255 return aPtr; 256 } 257 258 ElementConfigPtr ConfigHandler::importElementConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException) 259 { 260 ElementConfigType nType = parseType( getAttribute( xAttribs, "type" ) ); 261 ElementConfigPtr pElementConfig( new ElementConfigContainer( getAttribute( xAttribs, "name" ), nType ) ); 262 addElement( pElementConfig ); 263 return pElementConfig; 264 } 265 266 ElementConfigPtr ConfigHandler::importValueElementConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException) 267 { 268 ElementConfigPtr pElementConfig( new ElementValueConfig( getAttribute( xAttribs, "name" ), getAttribute( xAttribs, "value" ) ) ); 269 addElement( pElementConfig ); 270 return pElementConfig; 271 } 272 273 ElementConfigPtr ConfigHandler::importSwitchConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException) 274 { 275 ElementConfigType nType = parseType( getAttribute( xAttribs, "type" ) ); 276 ElementConfigPtr pElementConfig( new SwitchElementConfig( nType ) ); 277 addElement( pElementConfig ); 278 return pElementConfig; 279 } 280 281 ElementConfigPtr ConfigHandler::importCaseConfig( const Reference< XAttributeList > & xAttribs ) throw (SAXException) 282 { 283 ElementConfigPtr pElementConfig( new CaseElementConfig( getAttribute( xAttribs, "value" ) ) ); 284 addElement( pElementConfig ); 285 return pElementConfig; 286 } 287 288 void SAL_CALL ConfigHandler::endElement(const OUString& aName) throw( SAXException, RuntimeException ) 289 { 290 if( aName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "config" ) ) ) 291 { 292 return; 293 } 294 295 maElementStack.pop(); 296 } 297 298 void SAL_CALL ConfigHandler::characters(const OUString& aChars) throw( SAXException, RuntimeException ) 299 { 300 } 301 302 void SAL_CALL ConfigHandler::ignorableWhitespace(const OUString& aWhitespaces) throw( SAXException, RuntimeException ) 303 { 304 } 305 306 void SAL_CALL ConfigHandler::processingInstruction(const OUString& aTarget, const OUString& aData) throw( SAXException, RuntimeException ) 307 { 308 } 309 310 void SAL_CALL ConfigHandler::setDocumentLocator(const Reference< XLocator > & xLocator) throw( SAXException, RuntimeException ) 311 { 312 } 313 314 void load_config( const OUString& rPath ) 315 { 316 try 317 { 318 // create stream 319 SvStream* pIStm = ::utl::UcbStreamHelper::CreateStream( rPath, STREAM_READ ); 320 Reference<XInputStream> xInputStream( new utl::OInputStreamWrapper( pIStm, sal_True ) ); 321 322 // prepare ParserInputSrouce 323 InputSource aParserInput; 324 aParserInput.sSystemId = rPath; 325 aParserInput.aInputStream = xInputStream; 326 327 // get parser 328 Reference< XParser > xParser( 329 comphelper::getProcessServiceFactory()->createInstance( 330 OUString::createFromAscii("com.sun.star.xml.sax.Parser") ), 331 UNO_QUERY_THROW ); 332 333 // get filter 334 ConfigHandler* pConfigHandler = new ConfigHandler(); 335 Reference< XDocumentHandler > xFilter( pConfigHandler ); 336 337 // connect parser and filter 338 xParser->setDocumentHandler( xFilter ); 339 340 // finally, parser the stream 341 xParser->parseStream( aParserInput ); 342 } 343 catch( Exception& r ) 344 { 345 DBG_ERROR( 346 (rtl::OString("load_config(), " 347 "exception caught: ") + 348 rtl::OUStringToOString( 349 comphelper::anyToString( cppu::getCaughtException() ), 350 RTL_TEXTENCODING_UTF8 )).getStr() ); 351 352 (void)r; 353 } 354 } 355 356 /////////////////////////////////////////////////////////////////////// 357 358 rtl::OUString ElementConfig::format( SvStream& rStream, sal_Size& nLength ) const 359 { 360 OUString aRet; 361 if( maName.getLength() ) 362 { 363 aRet += maName; 364 aRet += OUString( RTL_CONSTASCII_USTRINGPARAM( " = " ) ); 365 } 366 367 switch( mnType ) 368 { 369 case ECT_BYTE: aRet += dump_byte( rStream, nLength ); break; 370 case ECT_UINT: aRet += dump_uint( rStream, nLength ); break; 371 case ECT_UNISTRING: aRet += dump_unistring( rStream, nLength ); break; 372 case ETC_FLOAT: aRet += dump_float( rStream, nLength ); break; 373 case ECT_HEXDUMP: 374 default: aRet += dump_hex( rStream, nLength ); break; 375 } 376 377 return aRet; 378 } 379 380 rtl::OUString ElementConfig::dump_hex( SvStream& rStream, sal_Size& nLength ) 381 { 382 char buffer[128]; 383 OUString aOut, aEmpty; 384 OUString aHex, aAscii; 385 sal_Char c; 386 int nRow = 0; 387 while( nLength && (rStream.GetError() == 0) ) 388 { 389 rStream >> c; 390 nLength--; 391 392 unsigned int i = c; 393 i &= 0xff; 394 sprintf( buffer, "%02x ", i ); 395 aHex += OUString::createFromAscii( buffer ); 396 397 if( !isprint( c ) ) 398 c = '.'; 399 400 aAscii += OUString( (sal_Unicode) c ); 401 nRow++; 402 403 if( (nRow == 16) || (nLength==0) ) 404 { 405 while( aHex.getLength() < (16*3) ) 406 aHex += OUString( RTL_CONSTASCII_USTRINGPARAM(" ") ); 407 aOut += aHex; 408 aOut += aAscii; 409 aOut += OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\r" ) ); 410 aHex = aEmpty; 411 aAscii = aEmpty; 412 nRow = 0; 413 } 414 } 415 416 aOut += aHex; 417 aOut += aAscii; 418 419 return aOut; 420 } 421 422 rtl::OUString ElementConfig::dump_byte( SvStream& rStream, sal_Size& nLength ) 423 { 424 OUString aRet; 425 if( nLength >= sizeof(sal_Char) ) 426 { 427 sal_Char c; 428 rStream >> c; 429 430 char buffer[128]; 431 sprintf( buffer, "%u", (int)c ); 432 aRet += OUString::createFromAscii( buffer ); 433 nLength -= sizeof(sal_Char); 434 } 435 436 return aRet; 437 } 438 439 rtl::OUString ElementConfig::dump_uint( SvStream& rStream, sal_Size& nLength ) 440 { 441 OUString aRet; 442 if( nLength >= sizeof( sal_uInt32 ) ) 443 { 444 sal_uInt32 c; 445 rStream >> c; 446 447 char buffer[128]; 448 sprintf( buffer, "%u", c ); 449 aRet += OUString::createFromAscii( buffer ); 450 nLength-= sizeof( sal_uInt32 ); 451 } 452 453 return aRet; 454 } 455 456 rtl::OUString ElementConfig::dump_unistring( SvStream& rStream, sal_Size& nLength ) 457 { 458 String aString; 459 SvxMSDffManager::MSDFFReadZString( rStream, aString, nLength, sal_True ); 460 nLength = 0; 461 return aString; 462 } 463 464 rtl::OUString ElementConfig::dump_float( SvStream& rStream, sal_Size& nLength ) 465 { 466 OUString aRet; 467 if( nLength >= sizeof( float ) ) 468 { 469 float c; 470 rStream >> c; 471 472 char buffer[128]; 473 sprintf( buffer, "%g", (double)c ); 474 aRet += OUString::createFromAscii( buffer ); 475 nLength-= sizeof( float ); 476 } 477 478 return aRet; 479 } 480 481 /////////////////////////////////////////////////////////////////////// 482 483 rtl::OUString ElementConfigContainer::format( SvStream& rStream, sal_Size& nLength ) const 484 { 485 OUString aRet; 486 487 if( getType() == ETC_CONTAINER ) 488 { 489 490 ElementConfigList::const_iterator aIter( maElementConfigList.begin() ); 491 const ElementConfigList::const_iterator aEnd( maElementConfigList.end() ); 492 while( (aIter != aEnd) && (nLength > 0) ) 493 { 494 aRet += (*aIter++)->format( rStream, nLength ); 495 if( (aIter != aEnd) || (nLength != 0) ) 496 aRet += OUString( RTL_CONSTASCII_USTRINGPARAM( "\n\r" ) ); 497 } 498 499 if( nLength ) 500 aRet += ElementConfig::dump_hex( rStream, nLength ); 501 } 502 else 503 { 504 aRet = getName(); 505 if( aRet.getLength() ) 506 aRet += OUString( RTL_CONSTASCII_USTRINGPARAM( " = " ) ); 507 508 OUString aValue; 509 switch( getType() ) 510 { 511 case ECT_BYTE: aValue = dump_byte( rStream, nLength ); break; 512 case ECT_UINT: aValue = dump_uint( rStream, nLength ); break; 513 case ECT_UNISTRING: aValue = dump_unistring( rStream, nLength ); break; 514 case ETC_FLOAT: aValue = dump_float( rStream, nLength ); break; 515 case ECT_HEXDUMP: 516 default: aValue = dump_hex( rStream, nLength ); break; 517 } 518 519 if( aValue.getLength() ) 520 { 521 if( !maElementConfigList.empty() ) 522 { 523 ElementConfigList::const_iterator aIter( maElementConfigList.begin() ); 524 const ElementConfigList::const_iterator aEnd( maElementConfigList.end() ); 525 while( (aIter != aEnd) && (nLength > 0) ) 526 { 527 ElementValueConfig* pValue = dynamic_cast< ElementValueConfig* >( (*aIter++).get() ); 528 if( pValue && pValue->getValue() == aValue ) 529 { 530 aValue = pValue->getName(); 531 break; 532 } 533 } 534 } 535 } 536 else 537 { 538 aValue = OUString( RTL_CONSTASCII_USTRINGPARAM("<empty!?>") ); 539 } 540 541 aRet += aValue; 542 } 543 544 return aRet; 545 } 546 547 /////////////////////////////////////////////////////////////////////// 548 549 rtl::OUString SwitchElementConfig::format( SvStream& rStream, sal_Size& nLength ) const 550 { 551 OUString aValue; 552 553 switch( getType() ) 554 { 555 case ECT_BYTE: aValue = dump_byte( rStream, nLength ); break; 556 case ECT_UINT: aValue = dump_uint( rStream, nLength ); break; 557 case ETC_FLOAT: aValue = dump_float( rStream, nLength ); break; 558 case ECT_UNISTRING: aValue = dump_unistring( rStream, nLength ); break; 559 } 560 561 if( aValue.getLength() ) 562 { 563 ElementConfigList::const_iterator aIter( maElementConfigList.begin() ); 564 const ElementConfigList::const_iterator aEnd( maElementConfigList.end() ); 565 while( (aIter != aEnd) && (nLength > 0) ) 566 { 567 CaseElementConfig* pCase = dynamic_cast< CaseElementConfig* >( (*aIter++).get() ); 568 if( pCase && pCase->getValue() == aValue ) 569 return pCase->format( rStream, nLength ); 570 } 571 } 572 573 return ElementConfig::dump_hex( rStream, nLength ); 574 } 575 576