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