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 #include "oox/dump/dumperbase.hxx" 29 30 #include <algorithm> 31 #include <com/sun/star/lang/XMultiServiceFactory.hpp> 32 #include <com/sun/star/io/XActiveDataSource.hpp> 33 #include <com/sun/star/io/XTextOutputStream.hpp> 34 #include <com/sun/star/ucb/XSimpleFileAccess.hpp> 35 #include <comphelper/docpasswordhelper.hxx> 36 #include <osl/file.hxx> 37 #include <rtl/math.hxx> 38 #include <rtl/tencinfo.h> 39 #include "oox/core/filterbase.hxx" 40 #include "oox/helper/binaryoutputstream.hxx" 41 #include "oox/helper/textinputstream.hxx" 42 #include "oox/xls/biffhelper.hxx" 43 44 #if OOX_INCLUDE_DUMPER 45 46 namespace oox { 47 namespace dump { 48 49 // ============================================================================ 50 51 using namespace ::com::sun::star::beans; 52 using namespace ::com::sun::star::io; 53 using namespace ::com::sun::star::lang; 54 using namespace ::com::sun::star::ucb; 55 using namespace ::com::sun::star::uno; 56 using namespace ::com::sun::star::util; 57 58 using ::comphelper::MediaDescriptor; 59 using ::oox::core::FilterBase; 60 using ::rtl::OString; 61 using ::rtl::OStringBuffer; 62 using ::rtl::OStringToOUString; 63 using ::rtl::OUString; 64 using ::rtl::OUStringBuffer; 65 using ::rtl::OUStringToOString; 66 67 // ============================================================================ 68 69 namespace { 70 71 const sal_Unicode OOX_DUMP_BOM = 0xFEFF; 72 const sal_Int32 OOX_DUMP_MAXSTRLEN = 80; 73 const sal_Int32 OOX_DUMP_INDENT = 2; 74 const sal_Unicode OOX_DUMP_BINDOT = '.'; 75 const sal_Unicode OOX_DUMP_CFG_LISTSEP = ','; 76 const sal_Unicode OOX_DUMP_CFG_QUOTE = '\''; 77 const sal_Unicode OOX_DUMP_LF = '\n'; 78 const sal_Unicode OOX_DUMP_ITEMSEP = '='; 79 const sal_Int32 OOX_DUMP_BYTESPERLINE = 16; 80 const sal_Int64 OOX_DUMP_MAXARRAY = 16; 81 82 } // namespace 83 84 // ============================================================================ 85 // ============================================================================ 86 87 // file names ----------------------------------------------------------------- 88 89 OUString InputOutputHelper::convertFileNameToUrl( const OUString& rFileName ) 90 { 91 OUString aFileUrl; 92 if( ::osl::FileBase::getFileURLFromSystemPath( rFileName, aFileUrl ) == ::osl::FileBase::E_None ) 93 return aFileUrl; 94 return OUString(); 95 } 96 97 sal_Int32 InputOutputHelper::getFileNamePos( const OUString& rFileUrl ) 98 { 99 sal_Int32 nSepPos = rFileUrl.lastIndexOf( '/' ); 100 return (nSepPos < 0) ? 0 : (nSepPos + 1); 101 } 102 103 OUString InputOutputHelper::getFileNameExtension( const OUString& rFileUrl ) 104 { 105 sal_Int32 nNamePos = getFileNamePos( rFileUrl ); 106 sal_Int32 nExtPos = rFileUrl.lastIndexOf( '.' ); 107 if( nExtPos >= nNamePos ) 108 return rFileUrl.copy( nExtPos + 1 ); 109 return OUString(); 110 } 111 112 // input streams -------------------------------------------------------------- 113 114 Reference< XInputStream > InputOutputHelper::openInputStream( 115 const Reference< XComponentContext >& rxContext, const OUString& rFileName ) 116 { 117 Reference< XInputStream > xInStrm; 118 if( rxContext.is() ) try 119 { 120 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); 121 Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); 122 xInStrm = xFileAccess->openFileRead( rFileName ); 123 } 124 catch( Exception& ) 125 { 126 } 127 return xInStrm; 128 } 129 130 // output streams ------------------------------------------------------------- 131 132 Reference< XOutputStream > InputOutputHelper::openOutputStream( 133 const Reference< XComponentContext >& rxContext, const OUString& rFileName ) 134 { 135 Reference< XOutputStream > xOutStrm; 136 if( rxContext.is() ) try 137 { 138 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); 139 Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); 140 xOutStrm = xFileAccess->openFileWrite( rFileName ); 141 } 142 catch( Exception& ) 143 { 144 } 145 return xOutStrm; 146 } 147 148 Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream( 149 const Reference< XComponentContext >& rxContext, const Reference< XOutputStream >& rxOutStrm, rtl_TextEncoding eTextEnc ) 150 { 151 Reference< XTextOutputStream > xTextOutStrm; 152 const char* pcCharset = rtl_getMimeCharsetFromTextEncoding( eTextEnc ); 153 if( rxContext.is() && rxOutStrm.is() && pcCharset ) try 154 { 155 Reference< XMultiServiceFactory > xFactory( rxContext->getServiceManager(), UNO_QUERY_THROW ); 156 Reference< XActiveDataSource > xDataSource( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.io.TextOutputStream" ) ), UNO_QUERY_THROW ); 157 xDataSource->setOutputStream( rxOutStrm ); 158 xTextOutStrm.set( xDataSource, UNO_QUERY_THROW ); 159 xTextOutStrm->setEncoding( OUString::createFromAscii( pcCharset ) ); 160 } 161 catch( Exception& ) 162 { 163 } 164 return xTextOutStrm; 165 } 166 167 Reference< XTextOutputStream > InputOutputHelper::openTextOutputStream( 168 const Reference< XComponentContext >& rxContext, const OUString& rFileName, rtl_TextEncoding eTextEnc ) 169 { 170 return openTextOutputStream( rxContext, openOutputStream( rxContext, rFileName ), eTextEnc ); 171 } 172 173 // ============================================================================ 174 // ============================================================================ 175 176 ItemFormat::ItemFormat() : 177 meDataType( DATATYPE_VOID ), 178 meFmtType( FORMATTYPE_NONE ) 179 { 180 } 181 182 void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName ) 183 { 184 meDataType = eDataType; 185 meFmtType = eFmtType; 186 maItemName = rItemName; 187 maListName = OUString(); 188 } 189 190 void ItemFormat::set( DataType eDataType, FormatType eFmtType, const OUString& rItemName, const OUString& rListName ) 191 { 192 set( eDataType, eFmtType, rItemName ); 193 maListName = rListName; 194 } 195 196 OUStringVector::const_iterator ItemFormat::parse( const OUStringVector& rFormatVec ) 197 { 198 set( DATATYPE_VOID, FORMATTYPE_NONE, OUString() ); 199 200 OUStringVector::const_iterator aIt = rFormatVec.begin(), aEnd = rFormatVec.end(); 201 OUString aDataType, aFmtType; 202 if( aIt != aEnd ) aDataType = *aIt++; 203 if( aIt != aEnd ) aFmtType = *aIt++; 204 if( aIt != aEnd ) maItemName = *aIt++; 205 if( aIt != aEnd ) maListName = *aIt++; 206 207 meDataType = StringHelper::convertToDataType( aDataType ); 208 meFmtType = StringHelper::convertToFormatType( aFmtType ); 209 210 if( meFmtType == FORMATTYPE_NONE ) 211 { 212 if( aFmtType.equalsAscii( "unused" ) ) 213 set( meDataType, FORMATTYPE_HEX, CREATE_OUSTRING( OOX_DUMP_UNUSED ) ); 214 else if( aFmtType.equalsAscii( "unknown" ) ) 215 set( meDataType, FORMATTYPE_HEX, CREATE_OUSTRING( OOX_DUMP_UNKNOWN ) ); 216 } 217 218 return aIt; 219 } 220 221 OUStringVector ItemFormat::parse( const OUString& rFormatStr ) 222 { 223 OUStringVector aFormatVec; 224 StringHelper::convertStringToStringList( aFormatVec, rFormatStr, false ); 225 OUStringVector::const_iterator aIt = parse( aFormatVec ); 226 return OUStringVector( aIt, const_cast< const OUStringVector& >( aFormatVec ).end() ); 227 } 228 229 // ============================================================================ 230 // ============================================================================ 231 232 // append string to string ---------------------------------------------------- 233 234 void StringHelper::appendChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount ) 235 { 236 for( sal_Int32 nIndex = 0; nIndex < nCount; ++nIndex ) 237 rStr.append( cChar ); 238 } 239 240 void StringHelper::appendString( OUStringBuffer& rStr, const OUString& rData, sal_Int32 nWidth, sal_Unicode cFill ) 241 { 242 appendChar( rStr, cFill, nWidth - rData.getLength() ); 243 rStr.append( rData ); 244 } 245 246 // append decimal ------------------------------------------------------------- 247 248 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt8 nData, sal_Int32 nWidth, sal_Unicode cFill ) 249 { 250 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill ); 251 } 252 253 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int8 nData, sal_Int32 nWidth, sal_Unicode cFill ) 254 { 255 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill ); 256 } 257 258 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt16 nData, sal_Int32 nWidth, sal_Unicode cFill ) 259 { 260 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill ); 261 } 262 263 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int16 nData, sal_Int32 nWidth, sal_Unicode cFill ) 264 { 265 appendString( rStr, OUString::valueOf( static_cast< sal_Int32 >( nData ) ), nWidth, cFill ); 266 } 267 268 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt32 nData, sal_Int32 nWidth, sal_Unicode cFill ) 269 { 270 appendString( rStr, OUString::valueOf( static_cast< sal_Int64 >( nData ) ), nWidth, cFill ); 271 } 272 273 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int32 nData, sal_Int32 nWidth, sal_Unicode cFill ) 274 { 275 appendString( rStr, OUString::valueOf( nData ), nWidth, cFill ); 276 } 277 278 void StringHelper::appendDec( OUStringBuffer& rStr, sal_uInt64 nData, sal_Int32 nWidth, sal_Unicode cFill ) 279 { 280 /* Values greater than biggest signed 64bit integer will change to 281 negative when converting to sal_Int64. Therefore, the trailing digit 282 will be written separately. */ 283 OUStringBuffer aBuffer; 284 if( nData > 9 ) 285 aBuffer.append( OUString::valueOf( static_cast< sal_Int64 >( nData / 10 ) ) ); 286 aBuffer.append( static_cast< sal_Unicode >( '0' + (nData % 10) ) ); 287 appendString( rStr, aBuffer.makeStringAndClear(), nWidth, cFill ); 288 } 289 290 void StringHelper::appendDec( OUStringBuffer& rStr, sal_Int64 nData, sal_Int32 nWidth, sal_Unicode cFill ) 291 { 292 appendString( rStr, OUString::valueOf( nData ), nWidth, cFill ); 293 } 294 295 void StringHelper::appendDec( OUStringBuffer& rStr, double fData, sal_Int32 nWidth, sal_Unicode cFill ) 296 { 297 appendString( rStr, ::rtl::math::doubleToUString( fData, rtl_math_StringFormat_G, 15, '.', true ), nWidth, cFill ); 298 } 299 300 // append hexadecimal --------------------------------------------------------- 301 302 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix ) 303 { 304 static const sal_Unicode spcHexDigits[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; 305 if( bPrefix ) 306 rStr.appendAscii( "0x" ); 307 rStr.append( spcHexDigits[ (nData >> 4) & 0x0F ] ).append( spcHexDigits[ nData & 0x0F ] ); 308 } 309 310 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix ) 311 { 312 appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix ); 313 } 314 315 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix ) 316 { 317 appendHex( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bPrefix ); 318 appendHex( rStr, static_cast< sal_uInt8 >( nData ), false ); 319 } 320 321 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix ) 322 { 323 appendHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix ); 324 } 325 326 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix ) 327 { 328 appendHex( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bPrefix ); 329 appendHex( rStr, static_cast< sal_uInt16 >( nData ), false ); 330 } 331 332 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix ) 333 { 334 appendHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix ); 335 } 336 337 void StringHelper::appendHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix ) 338 { 339 appendHex( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bPrefix ); 340 appendHex( rStr, static_cast< sal_uInt32 >( nData ), false ); 341 } 342 343 void StringHelper::appendHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix ) 344 { 345 appendHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix ); 346 } 347 348 void StringHelper::appendHex( OUStringBuffer& rStr, double fData, bool bPrefix ) 349 { 350 appendHex( rStr, *reinterpret_cast< const sal_uInt64* >( &fData ), bPrefix ); 351 } 352 353 // append shortened hexadecimal ----------------------------------------------- 354 355 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt8 nData, bool bPrefix ) 356 { 357 appendHex( rStr, nData, bPrefix ); 358 } 359 360 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int8 nData, bool bPrefix ) 361 { 362 appendHex( rStr, nData, bPrefix ); 363 } 364 365 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt16 nData, bool bPrefix ) 366 { 367 if( nData > SAL_MAX_UINT8 ) 368 appendHex( rStr, nData, bPrefix ); 369 else 370 appendHex( rStr, static_cast< sal_uInt8 >( nData ), bPrefix ); 371 } 372 373 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int16 nData, bool bPrefix ) 374 { 375 appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix ); 376 } 377 378 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt32 nData, bool bPrefix ) 379 { 380 if( nData > SAL_MAX_UINT16 ) 381 appendHex( rStr, nData, bPrefix ); 382 else 383 appendShortHex( rStr, static_cast< sal_uInt16 >( nData ), bPrefix ); 384 } 385 386 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int32 nData, bool bPrefix ) 387 { 388 appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix ); 389 } 390 391 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_uInt64 nData, bool bPrefix ) 392 { 393 if( nData > SAL_MAX_UINT32 ) 394 appendHex( rStr, nData, bPrefix ); 395 else 396 appendShortHex( rStr, static_cast< sal_uInt32 >( nData ), bPrefix ); 397 } 398 399 void StringHelper::appendShortHex( OUStringBuffer& rStr, sal_Int64 nData, bool bPrefix ) 400 { 401 appendShortHex( rStr, static_cast< sal_uInt64 >( nData ), bPrefix ); 402 } 403 404 void StringHelper::appendShortHex( OUStringBuffer& rStr, double fData, bool bPrefix ) 405 { 406 appendHex( rStr, fData, bPrefix ); 407 } 408 409 // append binary -------------------------------------------------------------- 410 411 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt8 nData, bool bDots ) 412 { 413 for( sal_uInt8 nMask = 0x80; nMask != 0; (nMask >>= 1) &= 0x7F ) 414 { 415 rStr.append( static_cast< sal_Unicode >( (nData & nMask) ? '1' : '0' ) ); 416 if( bDots && (nMask == 0x10) ) 417 rStr.append( OOX_DUMP_BINDOT ); 418 } 419 } 420 421 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int8 nData, bool bDots ) 422 { 423 appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots ); 424 } 425 426 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt16 nData, bool bDots ) 427 { 428 appendBin( rStr, static_cast< sal_uInt8 >( nData >> 8 ), bDots ); 429 if( bDots ) 430 rStr.append( OOX_DUMP_BINDOT ); 431 appendBin( rStr, static_cast< sal_uInt8 >( nData ), bDots ); 432 } 433 434 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int16 nData, bool bDots ) 435 { 436 appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots ); 437 } 438 439 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt32 nData, bool bDots ) 440 { 441 appendBin( rStr, static_cast< sal_uInt16 >( nData >> 16 ), bDots ); 442 if( bDots ) 443 rStr.append( OOX_DUMP_BINDOT ); 444 appendBin( rStr, static_cast< sal_uInt16 >( nData ), bDots ); 445 } 446 447 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int32 nData, bool bDots ) 448 { 449 appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots ); 450 } 451 452 void StringHelper::appendBin( OUStringBuffer& rStr, sal_uInt64 nData, bool bDots ) 453 { 454 appendBin( rStr, static_cast< sal_uInt32 >( nData >> 32 ), bDots ); 455 if( bDots ) 456 rStr.append( OOX_DUMP_BINDOT ); 457 appendBin( rStr, static_cast< sal_uInt32 >( nData ), bDots ); 458 } 459 460 void StringHelper::appendBin( OUStringBuffer& rStr, sal_Int64 nData, bool bDots ) 461 { 462 appendBin( rStr, static_cast< sal_uInt64 >( nData ), bDots ); 463 } 464 465 void StringHelper::appendBin( OUStringBuffer& rStr, double fData, bool bDots ) 466 { 467 appendBin( rStr, *reinterpret_cast< const sal_uInt64* >( &fData ), bDots ); 468 } 469 470 // append formatted value ----------------------------------------------------- 471 472 void StringHelper::appendBool( OUStringBuffer& rStr, bool bData ) 473 { 474 rStr.appendAscii( bData ? "true" : "false" ); 475 } 476 477 // append columns, rows, addresses -------------------------------------------- 478 479 void StringHelper::appendAddrCol( OUStringBuffer& rStr, sal_Int32 nCol, bool bRel ) 480 { 481 if( !bRel ) rStr.append( OOX_DUMP_ADDRABS ); 482 sal_Int32 nPos = rStr.getLength(); 483 for( sal_Int32 nTemp = nCol; nTemp >= 0; (nTemp /= 26) -= 1 ) 484 rStr.insert( nPos, static_cast< sal_Unicode >( 'A' + (nTemp % 26) ) ); 485 } 486 487 void StringHelper::appendAddrRow( OUStringBuffer& rStr, sal_Int32 nRow, bool bRel ) 488 { 489 if( !bRel ) rStr.append( OOX_DUMP_ADDRABS ); 490 appendDec( rStr, nRow + 1 ); 491 } 492 493 void StringHelper::appendAddrName( OUStringBuffer& rStr, sal_Unicode cPrefix, sal_Int32 nColRow, bool bRel ) 494 { 495 rStr.append( cPrefix ); 496 if( bRel && (nColRow != 0) ) 497 { 498 rStr.append( OOX_DUMP_R1C1OPEN ); 499 appendDec( rStr, nColRow ); 500 rStr.append( OOX_DUMP_R1C1CLOSE ); 501 } 502 else if( !bRel ) 503 appendDec( rStr, nColRow + 1 ); 504 } 505 506 void StringHelper::appendAddress( OUStringBuffer& rStr, const Address& rPos ) 507 { 508 appendAddrCol( rStr, rPos.mnCol, true ); 509 appendAddrRow( rStr, rPos.mnRow, true ); 510 } 511 512 void StringHelper::appendRange( OUStringBuffer& rStr, const Range& rRange ) 513 { 514 appendAddress( rStr, rRange.maFirst ); 515 rStr.append( OOX_DUMP_RANGESEP ); 516 appendAddress( rStr, rRange.maLast ); 517 } 518 519 void StringHelper::appendRangeList( OUStringBuffer& rStr, const RangeList& rRanges ) 520 { 521 OUStringBuffer aData; 522 for( RangeList::const_iterator aIt = rRanges.begin(), aEnd = rRanges.end(); aIt != aEnd; ++aIt ) 523 { 524 OUStringBuffer aRange; 525 appendRange( aRange, *aIt ); 526 appendToken( aData, aRange.makeStringAndClear(), OOX_DUMP_LISTSEP ); 527 } 528 rStr.append( aData.makeStringAndClear() ); 529 } 530 531 void StringHelper::appendAddress( OUStringBuffer& rStr, const TokenAddress& rPos, bool bR1C1 ) 532 { 533 if( bR1C1 && (rPos.mbRelCol || rPos.mbRelRow) ) 534 { 535 appendAddrName( rStr, OOX_DUMP_R1C1ROW, rPos.mnRow, rPos.mbRelRow ); 536 appendAddrName( rStr, OOX_DUMP_R1C1COL, rPos.mnCol, rPos.mbRelCol ); 537 } 538 else 539 { 540 appendAddrCol( rStr, rPos.mnCol, rPos.mbRelCol ); 541 appendAddrRow( rStr, rPos.mnRow, rPos.mbRelRow ); 542 } 543 } 544 545 void StringHelper::appendRange( OUStringBuffer& rStr, const TokenRange& rRange, bool bR1C1 ) 546 { 547 appendAddress( rStr, rRange.maFirst, bR1C1 ); 548 rStr.append( OOX_DUMP_RANGESEP ); 549 appendAddress( rStr, rRange.maLast, bR1C1 ); 550 } 551 552 // encoded text output -------------------------------------------------------- 553 554 void StringHelper::appendCChar( OUStringBuffer& rStr, sal_Unicode cChar, bool bPrefix ) 555 { 556 if( cChar > 0x00FF ) 557 { 558 if( bPrefix ) 559 rStr.appendAscii( "\\u" ); 560 appendHex( rStr, static_cast< sal_uInt16 >( cChar ), false ); 561 } 562 else 563 { 564 if( bPrefix ) 565 rStr.appendAscii( "\\x" ); 566 appendHex( rStr, static_cast< sal_uInt8 >( cChar ), false ); 567 } 568 } 569 570 void StringHelper::appendEncChar( OUStringBuffer& rStr, sal_Unicode cChar, sal_Int32 nCount, bool bPrefix ) 571 { 572 if( cChar < 0x0020 ) 573 { 574 // C-style hex code 575 OUStringBuffer aCode; 576 appendCChar( aCode, cChar, bPrefix ); 577 for( sal_Int32 nIdx = 0; nIdx < nCount; ++nIdx ) 578 rStr.append( aCode ); 579 } 580 else 581 { 582 appendChar( rStr, cChar, nCount ); 583 } 584 } 585 586 void StringHelper::appendEncString( OUStringBuffer& rStr, const OUString& rData, bool bPrefix ) 587 { 588 sal_Int32 nBeg = 0; 589 sal_Int32 nIdx = 0; 590 sal_Int32 nEnd = rData.getLength(); 591 while( nIdx < nEnd ) 592 { 593 // find next character that needs encoding 594 while( (nIdx < nEnd) && (rData[ nIdx ] >= 0x20) ) ++nIdx; 595 // append portion 596 if( nBeg < nIdx ) 597 { 598 if( (nBeg == 0) && (nIdx == nEnd) ) 599 rStr.append( rData ); 600 else 601 rStr.append( rData.copy( nBeg, nIdx - nBeg ) ); 602 } 603 // append characters to be encoded 604 while( (nIdx < nEnd) && (rData[ nIdx ] < 0x20) ) 605 { 606 appendCChar( rStr, rData[ nIdx ], bPrefix ); 607 ++nIdx; 608 } 609 // adjust limits 610 nBeg = nIdx; 611 } 612 } 613 614 // token list ----------------------------------------------------------------- 615 616 void StringHelper::appendToken( OUStringBuffer& rStr, const OUString& rToken, sal_Unicode cSep ) 617 { 618 if( (rStr.getLength() > 0) && (rToken.getLength() > 0) ) 619 rStr.append( cSep ); 620 rStr.append( rToken ); 621 } 622 623 void StringHelper::appendToken( OUStringBuffer& rStr, sal_Int64 nToken, sal_Unicode cSep ) 624 { 625 OUStringBuffer aToken; 626 appendDec( aToken, nToken ); 627 appendToken( rStr, aToken.makeStringAndClear(), cSep ); 628 } 629 630 void StringHelper::prependToken( OUStringBuffer& rStr, const OUString& rToken, sal_Unicode cSep ) 631 { 632 if( (rStr.getLength() > 0) && (rToken.getLength() > 0) ) 633 rStr.insert( 0, cSep ); 634 rStr.insert( 0, rToken ); 635 } 636 637 void StringHelper::prependToken( OUStringBuffer& rStr, sal_Int64 nToken, sal_Unicode cSep ) 638 { 639 OUStringBuffer aToken; 640 appendDec( aToken, nToken ); 641 prependToken( rStr, aToken.makeStringAndClear(), cSep ); 642 } 643 644 void StringHelper::appendIndex( OUStringBuffer& rStr, const OUString& rIdx ) 645 { 646 rStr.append( sal_Unicode( '[' ) ).append( rIdx ).append( sal_Unicode( ']' ) ); 647 } 648 649 void StringHelper::appendIndex( OUStringBuffer& rStr, sal_Int64 nIdx ) 650 { 651 OUStringBuffer aToken; 652 appendDec( aToken, nIdx ); 653 appendIndex( rStr, aToken.makeStringAndClear() ); 654 } 655 656 void StringHelper::appendIndexedText( OUStringBuffer& rStr, const OUString& rData, const OUString& rIdx ) 657 { 658 rStr.append( rData ); 659 appendIndex( rStr, rIdx ); 660 } 661 662 void StringHelper::appendIndexedText( OUStringBuffer& rStr, const OUString& rData, sal_Int64 nIdx ) 663 { 664 rStr.append( rData ); 665 appendIndex( rStr, nIdx ); 666 } 667 668 OUString StringHelper::getToken( const OUString& rData, sal_Int32& rnPos, sal_Unicode cSep ) 669 { 670 return trimSpaces( rData.getToken( 0, cSep, rnPos ) ); 671 } 672 673 void StringHelper::enclose( OUStringBuffer& rStr, sal_Unicode cOpen, sal_Unicode cClose ) 674 { 675 rStr.insert( 0, cOpen ).append( cClose ? cClose : cOpen ); 676 } 677 678 // string conversion ---------------------------------------------------------- 679 680 namespace { 681 682 sal_Int32 lclIndexOf( const OUString& rStr, sal_Unicode cChar, sal_Int32 nStartPos ) 683 { 684 sal_Int32 nIndex = rStr.indexOf( cChar, nStartPos ); 685 return (nIndex < 0) ? rStr.getLength() : nIndex; 686 } 687 688 OUString lclTrimQuotedStringList( const OUString& rStr ) 689 { 690 OUStringBuffer aBuffer; 691 sal_Int32 nPos = 0; 692 sal_Int32 nLen = rStr.getLength(); 693 while( nPos < nLen ) 694 { 695 if( rStr[ nPos ] == OOX_DUMP_CFG_QUOTE ) 696 { 697 // quoted string, skip leading quote character 698 ++nPos; 699 // process quoted text and ambedded literal quote characters 700 OUStringBuffer aToken; 701 do 702 { 703 // seek to next quote character and add text portion to token buffer 704 sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_QUOTE, nPos ); 705 aToken.append( rStr.copy( nPos, nEnd - nPos ) ); 706 // process literal quotes 707 while( (nEnd + 1 < nLen) && (rStr[ nEnd ] == OOX_DUMP_CFG_QUOTE) && (rStr[ nEnd + 1 ] == OOX_DUMP_CFG_QUOTE) ) 708 { 709 aToken.append( OOX_DUMP_CFG_QUOTE ); 710 nEnd += 2; 711 } 712 // nEnd is start of possible next text portion 713 nPos = nEnd; 714 } 715 while( (nPos < nLen) && (rStr[ nPos ] != OOX_DUMP_CFG_QUOTE) ); 716 // add token, seek to list separator, ignore text following closing quote 717 aBuffer.append( aToken.makeStringAndClear() ); 718 nPos = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos ); 719 if( nPos < nLen ) 720 aBuffer.append( OOX_DUMP_LF ); 721 // set current position behind list separator 722 ++nPos; 723 } 724 else 725 { 726 // find list separator, add token text to buffer 727 sal_Int32 nEnd = lclIndexOf( rStr, OOX_DUMP_CFG_LISTSEP, nPos ); 728 aBuffer.append( rStr.copy( nPos, nEnd - nPos ) ); 729 if( nEnd < nLen ) 730 aBuffer.append( OOX_DUMP_LF ); 731 // set current position behind list separator 732 nPos = nEnd + 1; 733 } 734 } 735 736 return aBuffer.makeStringAndClear(); 737 } 738 739 } // namespace 740 741 OUString StringHelper::trimSpaces( const OUString& rStr ) 742 { 743 sal_Int32 nBeg = 0; 744 while( (nBeg < rStr.getLength()) && ((rStr[ nBeg ] == ' ') || (rStr[ nBeg ] == '\t')) ) 745 ++nBeg; 746 sal_Int32 nEnd = rStr.getLength(); 747 while( (nEnd > nBeg) && ((rStr[ nEnd - 1 ] == ' ') || (rStr[ nEnd - 1 ] == '\t')) ) 748 --nEnd; 749 return rStr.copy( nBeg, nEnd - nBeg ); 750 } 751 752 OUString StringHelper::trimTrailingNul( const OUString& rStr ) 753 { 754 sal_Int32 nLastPos = rStr.getLength() - 1; 755 if( (nLastPos >= 0) && (rStr[ nLastPos ] == 0) ) 756 return rStr.copy( 0, nLastPos ); 757 return rStr; 758 } 759 760 OString StringHelper::convertToUtf8( const OUString& rStr ) 761 { 762 return OUStringToOString( rStr, RTL_TEXTENCODING_UTF8 ); 763 } 764 765 DataType StringHelper::convertToDataType( const OUString& rStr ) 766 { 767 DataType eType = DATATYPE_VOID; 768 if( rStr.equalsAscii( "int8" ) ) 769 eType = DATATYPE_INT8; 770 else if( rStr.equalsAscii( "uint8" ) ) 771 eType = DATATYPE_UINT8; 772 else if( rStr.equalsAscii( "int16" ) ) 773 eType = DATATYPE_INT16; 774 else if( rStr.equalsAscii( "uint16" ) ) 775 eType = DATATYPE_UINT16; 776 else if( rStr.equalsAscii( "int32" ) ) 777 eType = DATATYPE_INT32; 778 else if( rStr.equalsAscii( "uint32" ) ) 779 eType = DATATYPE_UINT32; 780 else if( rStr.equalsAscii( "int64" ) ) 781 eType = DATATYPE_INT64; 782 else if( rStr.equalsAscii( "uint64" ) ) 783 eType = DATATYPE_UINT64; 784 else if( rStr.equalsAscii( "float" ) ) 785 eType = DATATYPE_FLOAT; 786 else if( rStr.equalsAscii( "double" ) ) 787 eType = DATATYPE_DOUBLE; 788 return eType; 789 } 790 791 FormatType StringHelper::convertToFormatType( const OUString& rStr ) 792 { 793 FormatType eType = FORMATTYPE_NONE; 794 if( rStr.equalsAscii( "dec" ) ) 795 eType = FORMATTYPE_DEC; 796 else if( rStr.equalsAscii( "hex" ) ) 797 eType = FORMATTYPE_HEX; 798 else if( rStr.equalsAscii( "shorthex" ) ) 799 eType = FORMATTYPE_SHORTHEX; 800 else if( rStr.equalsAscii( "bin" ) ) 801 eType = FORMATTYPE_BIN; 802 else if( rStr.equalsAscii( "fix" ) ) 803 eType = FORMATTYPE_FIX; 804 else if( rStr.equalsAscii( "bool" ) ) 805 eType = FORMATTYPE_BOOL; 806 return eType; 807 } 808 809 bool StringHelper::convertFromDec( sal_Int64& ornData, const OUString& rData ) 810 { 811 sal_Int32 nPos = 0; 812 sal_Int32 nLen = rData.getLength(); 813 bool bNeg = false; 814 if( (nLen > 0) && (rData[ 0 ] == '-') ) 815 { 816 bNeg = true; 817 ++nPos; 818 } 819 ornData = 0; 820 for( ; nPos < nLen; ++nPos ) 821 { 822 sal_Unicode cChar = rData[ nPos ]; 823 if( (cChar < '0') || (cChar > '9') ) 824 return false; 825 (ornData *= 10) += (cChar - '0'); 826 } 827 if( bNeg ) 828 ornData *= -1; 829 return true; 830 } 831 832 bool StringHelper::convertFromHex( sal_Int64& ornData, const OUString& rData ) 833 { 834 ornData = 0; 835 for( sal_Int32 nPos = 0, nLen = rData.getLength(); nPos < nLen; ++nPos ) 836 { 837 sal_Unicode cChar = rData[ nPos ]; 838 if( ('0' <= cChar) && (cChar <= '9') ) 839 cChar -= '0'; 840 else if( ('A' <= cChar) && (cChar <= 'F') ) 841 cChar -= ('A' - 10); 842 else if( ('a' <= cChar) && (cChar <= 'f') ) 843 cChar -= ('a' - 10); 844 else 845 return false; 846 (ornData <<= 4) += cChar; 847 } 848 return true; 849 } 850 851 bool StringHelper::convertStringToInt( sal_Int64& ornData, const OUString& rData ) 852 { 853 if( (rData.getLength() > 2) && (rData[ 0 ] == '0') && ((rData[ 1 ] == 'X') || (rData[ 1 ] == 'x')) ) 854 return convertFromHex( ornData, rData.copy( 2 ) ); 855 return convertFromDec( ornData, rData ); 856 } 857 858 bool StringHelper::convertStringToDouble( double& orfData, const OUString& rData ) 859 { 860 rtl_math_ConversionStatus eStatus = rtl_math_ConversionStatus_Ok; 861 sal_Int32 nSize = 0; 862 orfData = rtl::math::stringToDouble( rData, '.', '\0', &eStatus, &nSize ); 863 return (eStatus == rtl_math_ConversionStatus_Ok) && (nSize == rData.getLength()); 864 } 865 866 bool StringHelper::convertStringToBool( const OUString& rData ) 867 { 868 if( rData.equalsAscii( "true" ) ) 869 return true; 870 if( rData.equalsAscii( "false" ) ) 871 return false; 872 sal_Int64 nData; 873 return convertStringToInt( nData, rData ) && (nData != 0); 874 } 875 876 OUStringPair StringHelper::convertStringToPair( const OUString& rString, sal_Unicode cSep ) 877 { 878 OUStringPair aPair; 879 if( rString.getLength() > 0 ) 880 { 881 sal_Int32 nEqPos = rString.indexOf( cSep ); 882 if( nEqPos < 0 ) 883 { 884 aPair.first = rString; 885 } 886 else 887 { 888 aPair.first = StringHelper::trimSpaces( rString.copy( 0, nEqPos ) ); 889 aPair.second = StringHelper::trimSpaces( rString.copy( nEqPos + 1 ) ); 890 } 891 } 892 return aPair; 893 } 894 895 void StringHelper::convertStringToStringList( OUStringVector& orVec, const OUString& rData, bool bIgnoreEmpty ) 896 { 897 orVec.clear(); 898 OUString aUnquotedData = lclTrimQuotedStringList( rData ); 899 sal_Int32 nPos = 0; 900 sal_Int32 nLen = aUnquotedData.getLength(); 901 while( (0 <= nPos) && (nPos < nLen) ) 902 { 903 OUString aToken = getToken( aUnquotedData, nPos, OOX_DUMP_LF ); 904 if( !bIgnoreEmpty || (aToken.getLength() > 0) ) 905 orVec.push_back( aToken ); 906 } 907 } 908 909 void StringHelper::convertStringToIntList( Int64Vector& orVec, const OUString& rData, bool bIgnoreEmpty ) 910 { 911 orVec.clear(); 912 OUString aUnquotedData = lclTrimQuotedStringList( rData ); 913 sal_Int32 nPos = 0; 914 sal_Int32 nLen = aUnquotedData.getLength(); 915 sal_Int64 nData; 916 while( (0 <= nPos) && (nPos < nLen) ) 917 { 918 bool bOk = convertStringToInt( nData, getToken( aUnquotedData, nPos, OOX_DUMP_LF ) ); 919 if( !bIgnoreEmpty || bOk ) 920 orVec.push_back( bOk ? nData : 0 ); 921 } 922 } 923 924 // ============================================================================ 925 // ============================================================================ 926 927 FormulaStack::FormulaStack() : 928 mbError( false ) 929 { 930 } 931 932 void FormulaStack::pushOperand( const String& rOp, const OUString& rTokClass ) 933 { 934 maFmlaStack.push( rOp ); 935 maClassStack.push( rTokClass ); 936 } 937 938 void FormulaStack::pushOperand( const String& rOp ) 939 { 940 pushOperand( rOp, OUString( OOX_DUMP_BASECLASS ) ); 941 } 942 943 void FormulaStack::pushUnaryOp( const String& rLOp, const String& rROp ) 944 { 945 pushUnaryOp( maFmlaStack, rLOp, rROp ); 946 pushUnaryOp( maClassStack, rLOp, rROp ); 947 } 948 949 void FormulaStack::pushBinaryOp( const String& rOp ) 950 { 951 pushBinaryOp( maFmlaStack, rOp ); 952 pushBinaryOp( maClassStack, rOp ); 953 } 954 955 void FormulaStack::pushFuncOp( const String& rFunc, const OUString& rTokClass, sal_uInt8 nParamCount ) 956 { 957 pushFuncOp( maFmlaStack, rFunc, nParamCount ); 958 pushFuncOp( maClassStack, rTokClass, nParamCount ); 959 } 960 961 void FormulaStack::replaceOnTop( const OUString& rOld, const OUString& rNew ) 962 { 963 if( !maFmlaStack.empty() ) 964 { 965 sal_Int32 nPos = maFmlaStack.top().indexOf( rOld ); 966 if( nPos >= 0 ) 967 maFmlaStack.top() = maFmlaStack.top().copy( 0, nPos ) + rNew + maFmlaStack.top().copy( nPos + rOld.getLength() ); 968 } 969 } 970 971 const OUString& FormulaStack::getString( const StringStack& rStack ) const 972 { 973 static const OUString saStackError = OOX_DUMP_ERRSTRING( "stack" ); 974 return (mbError || rStack.empty()) ? saStackError : rStack.top(); 975 } 976 977 void FormulaStack::pushUnaryOp( StringStack& rStack, const OUString& rLOp, const OUString& rROp ) 978 { 979 if( check( !rStack.empty() ) ) 980 rStack.top() = rLOp + rStack.top() + rROp; 981 } 982 983 void FormulaStack::pushBinaryOp( StringStack& rStack, const OUString& rOp ) 984 { 985 OUString aSecond; 986 if( check( !rStack.empty() ) ) 987 { 988 aSecond = rStack.top(); 989 rStack.pop(); 990 } 991 if( check( !rStack.empty() ) ) 992 rStack.top() = rStack.top() + rOp + aSecond; 993 } 994 995 void FormulaStack::pushFuncOp( StringStack& rStack, const OUString& rOp, sal_uInt8 nParamCount ) 996 { 997 OUStringBuffer aFunc; 998 for( sal_uInt8 nParam = 0; (nParam < nParamCount) && check( !rStack.empty() ); ++nParam ) 999 { 1000 StringHelper::prependToken( aFunc, rStack.top(), OOX_DUMP_FUNCSEP ); 1001 rStack.pop(); 1002 } 1003 StringHelper::enclose( aFunc, '(', ')' ); 1004 aFunc.insert( 0, rOp ); 1005 rStack.push( aFunc.makeStringAndClear() ); 1006 } 1007 1008 // ============================================================================ 1009 // ============================================================================ 1010 1011 Base::~Base() 1012 { 1013 } 1014 1015 // ============================================================================ 1016 // ============================================================================ 1017 1018 ConfigItemBase::~ConfigItemBase() 1019 { 1020 } 1021 1022 void ConfigItemBase::readConfigBlock( TextInputStream& rStrm ) 1023 { 1024 readConfigBlockContents( rStrm ); 1025 } 1026 1027 void ConfigItemBase::implProcessConfigItemStr( 1028 TextInputStream& /*rStrm*/, const OUString& /*rKey*/, const OUString& /*rData*/ ) 1029 { 1030 } 1031 1032 void ConfigItemBase::implProcessConfigItemInt( 1033 TextInputStream& /*rStrm*/, sal_Int64 /*nKey*/, const OUString& /*rData*/ ) 1034 { 1035 } 1036 1037 void ConfigItemBase::readConfigBlockContents( TextInputStream& rStrm ) 1038 { 1039 bool bLoop = true; 1040 while( bLoop && !rStrm.isEof() ) 1041 { 1042 OUString aKey, aData; 1043 switch( readConfigLine( rStrm, aKey, aData ) ) 1044 { 1045 case LINETYPE_DATA: 1046 processConfigItem( rStrm, aKey, aData ); 1047 break; 1048 case LINETYPE_END: 1049 bLoop = false; 1050 break; 1051 } 1052 } 1053 } 1054 1055 ConfigItemBase::LineType ConfigItemBase::readConfigLine( 1056 TextInputStream& rStrm, OUString& orKey, OUString& orData ) const 1057 { 1058 OUString aLine; 1059 while( !rStrm.isEof() && (aLine.getLength() == 0) ) 1060 { 1061 aLine = rStrm.readLine(); 1062 if( (aLine.getLength() > 0) && (aLine[ 0 ] == OOX_DUMP_BOM) ) 1063 aLine = aLine.copy( 1 ); 1064 aLine = StringHelper::trimSpaces( aLine ); 1065 if( aLine.getLength() > 0 ) 1066 { 1067 // ignore comments (starting with hash or semicolon) 1068 sal_Unicode cChar = aLine[ 0 ]; 1069 if( (cChar == '#') || (cChar == ';') ) 1070 aLine = OUString(); 1071 } 1072 } 1073 1074 OUStringPair aPair = StringHelper::convertStringToPair( aLine ); 1075 orKey = aPair.first; 1076 orData = aPair.second; 1077 return ((orKey.getLength() > 0) && ((orData.getLength() > 0) || !orKey.equalsAscii( "end" ))) ? 1078 LINETYPE_DATA : LINETYPE_END; 1079 } 1080 1081 ConfigItemBase::LineType ConfigItemBase::readConfigLine( TextInputStream& rStrm ) const 1082 { 1083 OUString aKey, aData; 1084 return readConfigLine( rStrm, aKey, aData ); 1085 } 1086 1087 void ConfigItemBase::processConfigItem( 1088 TextInputStream& rStrm, const OUString& rKey, const OUString& rData ) 1089 { 1090 sal_Int64 nKey; 1091 if( StringHelper::convertStringToInt( nKey, rKey ) ) 1092 implProcessConfigItemInt( rStrm, nKey, rData ); 1093 else 1094 implProcessConfigItemStr( rStrm, rKey, rData ); 1095 } 1096 1097 // ============================================================================ 1098 1099 NameListBase::~NameListBase() 1100 { 1101 } 1102 1103 void NameListBase::setName( sal_Int64 nKey, const String& rName ) 1104 { 1105 implSetName( nKey, rName ); 1106 } 1107 1108 void NameListBase::includeList( const NameListRef& rxList ) 1109 { 1110 if( rxList.get() ) 1111 { 1112 for( const_iterator aIt = rxList->begin(), aEnd = rxList->end(); aIt != aEnd; ++aIt ) 1113 maMap[ aIt->first ] = aIt->second; 1114 implIncludeList( *rxList ); 1115 } 1116 } 1117 1118 bool NameListBase::implIsValid() const 1119 { 1120 return true; 1121 } 1122 1123 void NameListBase::implProcessConfigItemStr( 1124 TextInputStream& rStrm, const OUString& rKey, const OUString& rData ) 1125 { 1126 if( rKey.equalsAscii( "include" ) ) 1127 include( rData ); 1128 else if( rKey.equalsAscii( "exclude" ) ) 1129 exclude( rData ); 1130 else 1131 ConfigItemBase::implProcessConfigItemStr( rStrm, rKey, rData ); 1132 } 1133 1134 void NameListBase::implProcessConfigItemInt( 1135 TextInputStream& /*rStrm*/, sal_Int64 nKey, const OUString& rData ) 1136 { 1137 implSetName( nKey, rData ); 1138 } 1139 1140 void NameListBase::insertRawName( sal_Int64 nKey, const OUString& rName ) 1141 { 1142 maMap[ nKey ] = rName; 1143 } 1144 1145 const OUString* NameListBase::findRawName( sal_Int64 nKey ) const 1146 { 1147 const_iterator aIt = maMap.find( nKey ); 1148 return (aIt == end()) ? 0 : &aIt->second; 1149 } 1150 1151 void NameListBase::include( const OUString& rListKeys ) 1152 { 1153 OUStringVector aVec; 1154 StringHelper::convertStringToStringList( aVec, rListKeys, true ); 1155 for( OUStringVector::const_iterator aIt = aVec.begin(), aEnd = aVec.end(); aIt != aEnd; ++aIt ) 1156 includeList( mrCfgData.getNameList( *aIt ) ); 1157 } 1158 1159 void NameListBase::exclude( const OUString& rKeys ) 1160 { 1161 Int64Vector aVec; 1162 StringHelper::convertStringToIntList( aVec, rKeys, true ); 1163 for( Int64Vector::const_iterator aIt = aVec.begin(), aEnd = aVec.end(); aIt != aEnd; ++aIt ) 1164 maMap.erase( *aIt ); 1165 } 1166 1167 // ============================================================================ 1168 1169 void ItemFormatMap::insertFormats( const NameListRef& rxNameList ) 1170 { 1171 if( Base::isValid( rxNameList ) ) 1172 for( NameListBase::const_iterator aIt = rxNameList->begin(), aEnd = rxNameList->end(); aIt != aEnd; ++aIt ) 1173 (*this)[ aIt->first ].parse( aIt->second ); 1174 } 1175 1176 // ============================================================================ 1177 1178 ConstList::ConstList( const SharedConfigData& rCfgData ) : 1179 NameListBase( rCfgData ), 1180 maDefName( OOX_DUMP_ERR_NONAME ), 1181 mbQuoteNames( false ) 1182 { 1183 } 1184 1185 void ConstList::implProcessConfigItemStr( 1186 TextInputStream& rStrm, const OUString& rKey, const OUString& rData ) 1187 { 1188 if( rKey.equalsAscii( "default" ) ) 1189 setDefaultName( rData ); 1190 else if( rKey.equalsAscii( "quote-names" ) ) 1191 setQuoteNames( StringHelper::convertStringToBool( rData ) ); 1192 else 1193 NameListBase::implProcessConfigItemStr( rStrm, rKey, rData ); 1194 } 1195 1196 void ConstList::implSetName( sal_Int64 nKey, const OUString& rName ) 1197 { 1198 insertRawName( nKey, rName ); 1199 } 1200 1201 OUString ConstList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const 1202 { 1203 const OUString* pName = findRawName( nKey ); 1204 OUString aName = pName ? *pName : maDefName; 1205 if( mbQuoteNames ) 1206 { 1207 OUStringBuffer aBuffer( aName ); 1208 StringHelper::enclose( aBuffer, OOX_DUMP_STRQUOTE ); 1209 aName = aBuffer.makeStringAndClear(); 1210 } 1211 return aName; 1212 } 1213 1214 OUString ConstList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const 1215 { 1216 return OUString(); 1217 } 1218 1219 void ConstList::implIncludeList( const NameListBase& rList ) 1220 { 1221 if( const ConstList* pConstList = dynamic_cast< const ConstList* >( &rList ) ) 1222 { 1223 maDefName = pConstList->maDefName; 1224 mbQuoteNames = pConstList->mbQuoteNames; 1225 } 1226 } 1227 1228 // ============================================================================ 1229 1230 MultiList::MultiList( const SharedConfigData& rCfgData ) : 1231 ConstList( rCfgData ), 1232 mbIgnoreEmpty( true ) 1233 { 1234 } 1235 1236 void MultiList::setNamesFromVec( sal_Int64 nStartKey, const OUStringVector& rNames ) 1237 { 1238 sal_Int64 nKey = nStartKey; 1239 for( OUStringVector::const_iterator aIt = rNames.begin(), aEnd = rNames.end(); aIt != aEnd; ++aIt, ++nKey ) 1240 if( !mbIgnoreEmpty || (aIt->getLength() > 0) ) 1241 insertRawName( nKey, *aIt ); 1242 } 1243 1244 void MultiList::implProcessConfigItemStr( 1245 TextInputStream& rStrm, const OUString& rKey, const OUString& rData ) 1246 { 1247 if( rKey.equalsAscii( "ignore-empty" ) ) 1248 mbIgnoreEmpty = StringHelper::convertStringToBool( rData ); 1249 else 1250 ConstList::implProcessConfigItemStr( rStrm, rKey, rData ); 1251 } 1252 1253 void MultiList::implSetName( sal_Int64 nKey, const OUString& rName ) 1254 { 1255 OUStringVector aNames; 1256 StringHelper::convertStringToStringList( aNames, rName, false ); 1257 setNamesFromVec( nKey, aNames ); 1258 } 1259 1260 // ============================================================================ 1261 1262 FlagsList::FlagsList( const SharedConfigData& rCfgData ) : 1263 NameListBase( rCfgData ), 1264 mnIgnore( 0 ) 1265 { 1266 } 1267 1268 void FlagsList::implProcessConfigItemStr( 1269 TextInputStream& rStrm, const OUString& rKey, const OUString& rData ) 1270 { 1271 if( rKey.equalsAscii( "ignore" ) ) 1272 { 1273 sal_Int64 nIgnore; 1274 if( StringHelper::convertStringToInt( nIgnore, rData ) ) 1275 setIgnoreFlags( nIgnore ); 1276 } 1277 else 1278 { 1279 NameListBase::implProcessConfigItemStr( rStrm, rKey, rData ); 1280 } 1281 } 1282 1283 void FlagsList::implSetName( sal_Int64 nKey, const OUString& rName ) 1284 { 1285 if( (nKey != 0) && ((nKey & (nKey - 1)) == 0) ) // only a single bit set? 1286 insertRawName( nKey, rName ); 1287 } 1288 1289 OUString FlagsList::implGetName( const Config& /*rCfg*/, sal_Int64 nKey ) const 1290 { 1291 sal_Int64 nFound = mnIgnore; 1292 OUStringBuffer aName; 1293 // add known flags 1294 for( const_iterator aIt = begin(), aEnd = end(); aIt != aEnd; ++aIt ) 1295 { 1296 sal_Int64 nMask = aIt->first; 1297 setFlag( nFound, nMask ); 1298 if( !getFlag( mnIgnore, nMask ) ) 1299 { 1300 const OUString& rFlagName = aIt->second; 1301 bool bOnOff = (rFlagName.getLength() > 0) && (rFlagName[ 0 ] == ':'); 1302 bool bFlag = getFlag( nKey, nMask ); 1303 if( bOnOff ) 1304 { 1305 StringHelper::appendToken( aName, rFlagName.copy( 1 ) ); 1306 aName.appendAscii( bFlag ? ":on" : ":off" ); 1307 } 1308 else 1309 { 1310 bool bNegated = (rFlagName.getLength() > 0) && (rFlagName[ 0 ] == '!'); 1311 sal_Int32 nBothSep = bNegated ? rFlagName.indexOf( '!', 1 ) : -1; 1312 if( bFlag ) 1313 { 1314 if( !bNegated ) 1315 StringHelper::appendToken( aName, rFlagName ); 1316 else if( nBothSep > 0 ) 1317 StringHelper::appendToken( aName, rFlagName.copy( nBothSep + 1 ) ); 1318 } 1319 else if( bNegated ) 1320 { 1321 if( nBothSep > 0 ) 1322 StringHelper::appendToken( aName, rFlagName.copy( 1, nBothSep - 1 ) ); 1323 else 1324 StringHelper::appendToken( aName, rFlagName.copy( 1 ) ); 1325 } 1326 } 1327 } 1328 } 1329 // add unknown flags 1330 setFlag( nKey, nFound, false ); 1331 if( nKey != 0 ) 1332 { 1333 OUStringBuffer aUnknown( CREATE_OUSTRING( OOX_DUMP_UNKNOWN ) ); 1334 aUnknown.append( OOX_DUMP_ITEMSEP ); 1335 StringHelper::appendShortHex( aUnknown, nKey, true ); 1336 StringHelper::enclose( aUnknown, '(', ')' ); 1337 StringHelper::appendToken( aName, aUnknown.makeStringAndClear() ); 1338 } 1339 return aName.makeStringAndClear(); 1340 } 1341 1342 OUString FlagsList::implGetNameDbl( const Config& /*rCfg*/, double /*fValue*/ ) const 1343 { 1344 return OUString(); 1345 } 1346 1347 void FlagsList::implIncludeList( const NameListBase& rList ) 1348 { 1349 if( const FlagsList* pFlagsList = dynamic_cast< const FlagsList* >( &rList ) ) 1350 mnIgnore = pFlagsList->mnIgnore; 1351 } 1352 1353 // ============================================================================ 1354 1355 bool CombiList::ExtItemFormatKey::operator<( const ExtItemFormatKey& rRight ) const 1356 { 1357 return (mnKey < rRight.mnKey) || ((mnKey == rRight.mnKey) && (maFilter < rRight.maFilter)); 1358 } 1359 1360 CombiList::CombiList( const SharedConfigData& rCfgData ) : 1361 FlagsList( rCfgData ) 1362 { 1363 } 1364 1365 void CombiList::implSetName( sal_Int64 nKey, const OUString& rName ) 1366 { 1367 if( (nKey & (nKey - 1)) != 0 ) // more than a single bit set? 1368 { 1369 typedef ::std::set< ExtItemFormatKey > ExtItemFormatKeySet; 1370 ::std::set< ExtItemFormatKey > aItemKeys; 1371 ExtItemFormat aItemFmt; 1372 OUStringVector aRemain = aItemFmt.parse( rName ); 1373 for( OUStringVector::iterator aIt = aRemain.begin(), aEnd = aRemain.end(); aIt != aEnd; ++aIt ) 1374 { 1375 OUStringPair aPair = StringHelper::convertStringToPair( *aIt ); 1376 if( aPair.first.equalsAscii( "noshift" ) ) 1377 { 1378 aItemFmt.mbShiftValue = StringHelper::convertStringToBool( aPair.second ); 1379 } 1380 else if( aPair.first.equalsAscii( "filter" ) ) 1381 { 1382 OUStringPair aFilter = StringHelper::convertStringToPair( aPair.second, '~' ); 1383 ExtItemFormatKey aKey( nKey ); 1384 if( (aFilter.first.getLength() > 0) && StringHelper::convertStringToInt( aKey.maFilter.first, aFilter.first ) && 1385 (aFilter.second.getLength() > 0) && StringHelper::convertStringToInt( aKey.maFilter.second, aFilter.second ) ) 1386 { 1387 if( aKey.maFilter.first == 0 ) 1388 aKey.maFilter.second = 0; 1389 aItemKeys.insert( aKey ); 1390 } 1391 } 1392 } 1393 if( aItemKeys.empty() ) 1394 aItemKeys.insert( ExtItemFormatKey( nKey ) ); 1395 for( ExtItemFormatKeySet::iterator aIt = aItemKeys.begin(), aEnd = aItemKeys.end(); aIt != aEnd; ++aIt ) 1396 maFmtMap[ *aIt ] = aItemFmt; 1397 } 1398 else 1399 { 1400 FlagsList::implSetName( nKey, rName ); 1401 } 1402 } 1403 1404 OUString CombiList::implGetName( const Config& rCfg, sal_Int64 nKey ) const 1405 { 1406 sal_Int64 nFound = 0; 1407 OUStringBuffer aName; 1408 // add known flag fields 1409 for( ExtItemFormatMap::const_iterator aIt = maFmtMap.begin(), aEnd = maFmtMap.end(); aIt != aEnd; ++aIt ) 1410 { 1411 const ExtItemFormatKey& rMapKey = aIt->first; 1412 sal_Int64 nMask = rMapKey.mnKey; 1413 if( (nMask != 0) && ((nKey & rMapKey.maFilter.first) == rMapKey.maFilter.second) ) 1414 { 1415 const ExtItemFormat& rItemFmt = aIt->second; 1416 1417 sal_uInt64 nUFlags = static_cast< sal_uInt64 >( nKey ); 1418 sal_uInt64 nUMask = static_cast< sal_uInt64 >( nMask ); 1419 if( rItemFmt.mbShiftValue ) 1420 while( (nUMask & 1) == 0 ) { nUFlags >>= 1; nUMask >>= 1; } 1421 1422 sal_uInt64 nUValue = nUFlags & nUMask; 1423 sal_Int64 nSValue = static_cast< sal_Int64 >( nUValue ); 1424 if( getFlag< sal_uInt64 >( nUValue, (nUMask + 1) >> 1 ) ) 1425 setFlag( nSValue, static_cast< sal_Int64 >( ~nUMask ) ); 1426 1427 OUStringBuffer aItem( rItemFmt.maItemName ); 1428 OUStringBuffer aValue; 1429 switch( rItemFmt.meDataType ) 1430 { 1431 case DATATYPE_INT8: StringHelper::appendValue( aValue, static_cast< sal_Int8 >( nSValue ), rItemFmt.meFmtType ); break; 1432 case DATATYPE_UINT8: StringHelper::appendValue( aValue, static_cast< sal_uInt8 >( nUValue ), rItemFmt.meFmtType ); break; 1433 case DATATYPE_INT16: StringHelper::appendValue( aValue, static_cast< sal_Int16 >( nSValue ), rItemFmt.meFmtType ); break; 1434 case DATATYPE_UINT16: StringHelper::appendValue( aValue, static_cast< sal_uInt16 >( nUValue ), rItemFmt.meFmtType ); break; 1435 case DATATYPE_INT32: StringHelper::appendValue( aValue, static_cast< sal_Int32 >( nSValue ), rItemFmt.meFmtType ); break; 1436 case DATATYPE_UINT32: StringHelper::appendValue( aValue, static_cast< sal_uInt32 >( nUValue ), rItemFmt.meFmtType ); break; 1437 case DATATYPE_INT64: StringHelper::appendValue( aValue, nSValue, rItemFmt.meFmtType ); break; 1438 case DATATYPE_UINT64: StringHelper::appendValue( aValue, nUValue, rItemFmt.meFmtType ); break; 1439 case DATATYPE_FLOAT: StringHelper::appendValue( aValue, static_cast< float >( nSValue ), rItemFmt.meFmtType ); break; 1440 case DATATYPE_DOUBLE: StringHelper::appendValue( aValue, static_cast< double >( nSValue ), rItemFmt.meFmtType ); break; 1441 default:; 1442 } 1443 StringHelper::appendToken( aItem, aValue.makeStringAndClear(), OOX_DUMP_ITEMSEP ); 1444 if( rItemFmt.maListName.getLength() > 0 ) 1445 { 1446 OUString aValueName = rCfg.getName( rItemFmt.maListName, static_cast< sal_Int64 >( nUValue ) ); 1447 StringHelper::appendToken( aItem, aValueName, OOX_DUMP_ITEMSEP ); 1448 } 1449 StringHelper::enclose( aItem, '(', ')' ); 1450 StringHelper::appendToken( aName, aItem.makeStringAndClear() ); 1451 setFlag( nFound, nMask ); 1452 } 1453 } 1454 setFlag( nKey, nFound, false ); 1455 StringHelper::appendToken( aName, FlagsList::implGetName( rCfg, nKey ) ); 1456 return aName.makeStringAndClear(); 1457 } 1458 1459 void CombiList::implIncludeList( const NameListBase& rList ) 1460 { 1461 if( const CombiList* pCombiList = dynamic_cast< const CombiList* >( &rList ) ) 1462 maFmtMap = pCombiList->maFmtMap; 1463 FlagsList::implIncludeList( rList ); 1464 } 1465 1466 // ============================================================================ 1467 1468 UnitConverter::UnitConverter( const SharedConfigData& rCfgData ) : 1469 NameListBase( rCfgData ), 1470 mfFactor( 1.0 ) 1471 { 1472 } 1473 1474 void UnitConverter::implSetName( sal_Int64 /*nKey*/, const OUString& /*rName*/ ) 1475 { 1476 // nothing to do 1477 } 1478 1479 OUString UnitConverter::implGetName( const Config& rCfg, sal_Int64 nKey ) const 1480 { 1481 return implGetNameDbl( rCfg, static_cast< double >( nKey ) ); 1482 } 1483 1484 OUString UnitConverter::implGetNameDbl( const Config& /*rCfg*/, double fValue ) const 1485 { 1486 OUStringBuffer aValue; 1487 StringHelper::appendDec( aValue, mfFactor * fValue ); 1488 aValue.append( maUnitName ); 1489 return aValue.makeStringAndClear(); 1490 } 1491 1492 void UnitConverter::implIncludeList( const NameListBase& /*rList*/ ) 1493 { 1494 } 1495 1496 // ============================================================================ 1497 1498 NameListRef NameListWrapper::getNameList( const Config& rCfg ) const 1499 { 1500 return mxList.get() ? mxList : (mxList = rCfg.getNameList( maName )); 1501 } 1502 1503 // ============================================================================ 1504 // ============================================================================ 1505 1506 SharedConfigData::SharedConfigData( const OUString& rFileName, 1507 const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, 1508 const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) : 1509 mxContext( rxContext ), 1510 mxRootStrg( rxRootStrg ), 1511 maSysFileName( rSysFileName ), 1512 mrMediaDesc( rMediaDesc ), 1513 mbLoaded( false ), 1514 mbPwCancelled( false ) 1515 { 1516 OUString aFileUrl = InputOutputHelper::convertFileNameToUrl( rFileName ); 1517 if( aFileUrl.getLength() > 0 ) 1518 { 1519 sal_Int32 nNamePos = InputOutputHelper::getFileNamePos( aFileUrl ); 1520 maConfigPath = aFileUrl.copy( 0, nNamePos ); 1521 mbLoaded = readConfigFile( aFileUrl ); 1522 } 1523 } 1524 1525 SharedConfigData::~SharedConfigData() 1526 { 1527 } 1528 1529 void SharedConfigData::setOption( const OUString& rKey, const OUString& rData ) 1530 { 1531 maConfigData[ rKey ] = rData; 1532 } 1533 1534 const OUString* SharedConfigData::getOption( const OUString& rKey ) const 1535 { 1536 ConfigDataMap::const_iterator aIt = maConfigData.find( rKey ); 1537 return (aIt == maConfigData.end()) ? 0 : &aIt->second; 1538 } 1539 1540 void SharedConfigData::setNameList( const OUString& rListName, const NameListRef& rxList ) 1541 { 1542 if( rListName.getLength() > 0 ) 1543 maNameLists[ rListName ] = rxList; 1544 } 1545 1546 void SharedConfigData::eraseNameList( const OUString& rListName ) 1547 { 1548 maNameLists.erase( rListName ); 1549 } 1550 1551 NameListRef SharedConfigData::getNameList( const OUString& rListName ) const 1552 { 1553 NameListRef xList; 1554 NameListMap::const_iterator aIt = maNameLists.find( rListName ); 1555 if( aIt != maNameLists.end() ) 1556 xList = aIt->second; 1557 return xList; 1558 } 1559 1560 Sequence< NamedValue > SharedConfigData::requestEncryptionData( ::comphelper::IDocPasswordVerifier& rVerifier ) 1561 { 1562 Sequence< NamedValue > aEncryptionData; 1563 if( !mbPwCancelled ) 1564 { 1565 ::std::vector< OUString > aDefaultPasswords; 1566 aDefaultPasswords.push_back( CREATE_OUSTRING( "VelvetSweatshop" ) ); 1567 aEncryptionData = ::comphelper::DocPasswordHelper::requestAndVerifyDocPassword( 1568 rVerifier, mrMediaDesc, ::comphelper::DocPasswordRequestType_MS, &aDefaultPasswords ); 1569 mbPwCancelled = !aEncryptionData.hasElements(); 1570 } 1571 return aEncryptionData; 1572 } 1573 1574 bool SharedConfigData::implIsValid() const 1575 { 1576 return mbLoaded && mxContext.is() && mxRootStrg.get() && (maSysFileName.getLength() > 0); 1577 } 1578 1579 void SharedConfigData::implProcessConfigItemStr( 1580 TextInputStream& rStrm, const OUString& rKey, const OUString& rData ) 1581 { 1582 if( rKey.equalsAscii( "include-config-file" ) ) 1583 readConfigFile( maConfigPath + rData ); 1584 else if( rKey.equalsAscii( "constlist" ) ) 1585 readNameList< ConstList >( rStrm, rData ); 1586 else if( rKey.equalsAscii( "multilist" ) ) 1587 readNameList< MultiList >( rStrm, rData ); 1588 else if( rKey.equalsAscii( "flagslist" ) ) 1589 readNameList< FlagsList >( rStrm, rData ); 1590 else if( rKey.equalsAscii( "combilist" ) ) 1591 readNameList< CombiList >( rStrm, rData ); 1592 else if( rKey.equalsAscii( "shortlist" ) ) 1593 createShortList( rData ); 1594 else if( rKey.equalsAscii( "unitconverter" ) ) 1595 createUnitConverter( rData ); 1596 else 1597 setOption( rKey, rData ); 1598 } 1599 1600 bool SharedConfigData::readConfigFile( const OUString& rFileUrl ) 1601 { 1602 bool bLoaded = maConfigFiles.count( rFileUrl ) > 0; 1603 if( !bLoaded ) 1604 { 1605 Reference< XInputStream > xInStrm = InputOutputHelper::openInputStream( mxContext, rFileUrl ); 1606 TextInputStream aTxtStrm( mxContext, xInStrm, RTL_TEXTENCODING_UTF8 ); 1607 if( !aTxtStrm.isEof() ) 1608 { 1609 maConfigFiles.insert( rFileUrl ); 1610 readConfigBlockContents( aTxtStrm ); 1611 bLoaded = true; 1612 } 1613 } 1614 return bLoaded; 1615 } 1616 1617 void SharedConfigData::createShortList( const OUString& rData ) 1618 { 1619 OUStringVector aDataVec; 1620 StringHelper::convertStringToStringList( aDataVec, rData, false ); 1621 if( aDataVec.size() >= 3 ) 1622 { 1623 sal_Int64 nStartKey; 1624 if( StringHelper::convertStringToInt( nStartKey, aDataVec[ 1 ] ) ) 1625 { 1626 ::boost::shared_ptr< MultiList > xList = createNameList< MultiList >( aDataVec[ 0 ] ); 1627 if( xList.get() ) 1628 { 1629 aDataVec.erase( aDataVec.begin(), aDataVec.begin() + 2 ); 1630 xList->setNamesFromVec( nStartKey, aDataVec ); 1631 } 1632 } 1633 } 1634 } 1635 1636 void SharedConfigData::createUnitConverter( const OUString& rData ) 1637 { 1638 OUStringVector aDataVec; 1639 StringHelper::convertStringToStringList( aDataVec, rData, false ); 1640 if( aDataVec.size() >= 2 ) 1641 { 1642 OUString aFactor = aDataVec[ 1 ]; 1643 bool bRecip = (aFactor.getLength() > 0) && (aFactor[ 0 ] == '/'); 1644 if( bRecip ) 1645 aFactor = aFactor.copy( 1 ); 1646 double fFactor; 1647 if( StringHelper::convertStringToDouble( fFactor, aFactor ) && (fFactor != 0.0) ) 1648 { 1649 ::boost::shared_ptr< UnitConverter > xList = createNameList< UnitConverter >( aDataVec[ 0 ] ); 1650 if( xList.get() ) 1651 { 1652 xList->setFactor( bRecip ? (1.0 / fFactor) : fFactor ); 1653 if( aDataVec.size() >= 3 ) 1654 xList->setUnitName( aDataVec[ 2 ] ); 1655 } 1656 } 1657 } 1658 } 1659 1660 // ============================================================================ 1661 1662 Config::Config( const Config& rParent ) : 1663 Base() // c'tor needs to be called explicitly to avoid compiler warning 1664 { 1665 construct( rParent ); 1666 } 1667 1668 Config::Config( const sal_Char* pcEnvVar, const FilterBase& rFilter ) 1669 { 1670 construct( pcEnvVar, rFilter ); 1671 } 1672 1673 Config::Config( const sal_Char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) 1674 { 1675 construct( pcEnvVar, rxContext, rxRootStrg, rSysFileName, rMediaDesc ); 1676 } 1677 1678 Config::~Config() 1679 { 1680 } 1681 1682 void Config::construct( const Config& rParent ) 1683 { 1684 *this = rParent; 1685 } 1686 1687 void Config::construct( const sal_Char* pcEnvVar, const FilterBase& rFilter ) 1688 { 1689 if( rFilter.getFileUrl().getLength() > 0 ) 1690 construct( pcEnvVar, rFilter.getComponentContext(), rFilter.getStorage(), rFilter.getFileUrl(), rFilter.getMediaDescriptor() ); 1691 } 1692 1693 void Config::construct( const sal_Char* pcEnvVar, const Reference< XComponentContext >& rxContext, const StorageRef& rxRootStrg, const OUString& rSysFileName, MediaDescriptor& rMediaDesc ) 1694 { 1695 if( pcEnvVar && rxRootStrg.get() && (rSysFileName.getLength() > 0) ) 1696 if( const sal_Char* pcFileName = ::getenv( pcEnvVar ) ) 1697 mxCfgData.reset( new SharedConfigData( OUString::createFromAscii( pcFileName ), rxContext, rxRootStrg, rSysFileName, rMediaDesc ) ); 1698 } 1699 1700 void Config::setStringOption( const String& rKey, const String& rData ) 1701 { 1702 mxCfgData->setOption( rKey, rData ); 1703 } 1704 1705 const OUString& Config::getStringOption( const String& rKey, const OUString& rDefault ) const 1706 { 1707 const OUString* pData = implGetOption( rKey ); 1708 return pData ? *pData : rDefault; 1709 } 1710 1711 bool Config::getBoolOption( const String& rKey, bool bDefault ) const 1712 { 1713 const OUString* pData = implGetOption( rKey ); 1714 return pData ? StringHelper::convertStringToBool( *pData ) : bDefault; 1715 } 1716 1717 bool Config::isDumperEnabled() const 1718 { 1719 return getBoolOption( "enable-dumper", false ); 1720 } 1721 1722 bool Config::isImportEnabled() const 1723 { 1724 return getBoolOption( "enable-import", true ); 1725 } 1726 1727 void Config::setNameList( const String& rListName, const NameListRef& rxList ) 1728 { 1729 mxCfgData->setNameList( rListName, rxList ); 1730 } 1731 1732 void Config::eraseNameList( const String& rListName ) 1733 { 1734 mxCfgData->eraseNameList( rListName ); 1735 } 1736 1737 NameListRef Config::getNameList( const String& rListName ) const 1738 { 1739 return implGetNameList( rListName ); 1740 } 1741 1742 Sequence< NamedValue > Config::requestEncryptionData( ::comphelper::IDocPasswordVerifier& rVerifier ) 1743 { 1744 return mxCfgData->requestEncryptionData( rVerifier ); 1745 } 1746 1747 bool Config::isPasswordCancelled() const 1748 { 1749 return mxCfgData->isPasswordCancelled(); 1750 } 1751 1752 bool Config::implIsValid() const 1753 { 1754 return isValid( mxCfgData ); 1755 } 1756 1757 const OUString* Config::implGetOption( const OUString& rKey ) const 1758 { 1759 return mxCfgData->getOption( rKey ); 1760 } 1761 1762 NameListRef Config::implGetNameList( const OUString& rListName ) const 1763 { 1764 return mxCfgData->getNameList( rListName ); 1765 } 1766 1767 // ============================================================================ 1768 // ============================================================================ 1769 1770 Output::Output( const Reference< XComponentContext >& rxContext, const OUString& rFileName ) : 1771 mxStrm( InputOutputHelper::openTextOutputStream( rxContext, rFileName, RTL_TEXTENCODING_UTF8 ) ), 1772 mnCol( 0 ), 1773 mnItemLevel( 0 ), 1774 mnMultiLevel( 0 ), 1775 mnItemIdx( 0 ), 1776 mnLastItem( 0 ) 1777 { 1778 if( mxStrm.is() ) 1779 mxStrm->writeString( OUString( OOX_DUMP_BOM ) ); 1780 } 1781 1782 // ---------------------------------------------------------------------------- 1783 1784 void Output::newLine() 1785 { 1786 if( maLine.getLength() > 0 ) 1787 { 1788 mxStrm->writeString( maIndent ); 1789 maLine.append( sal_Unicode( '\n' ) ); 1790 mxStrm->writeString( maLine.makeStringAndClear() ); 1791 mnCol = 0; 1792 mnLastItem = 0; 1793 } 1794 } 1795 1796 void Output::emptyLine( size_t nCount ) 1797 { 1798 for( size_t nIdx = 0; nIdx < nCount; ++nIdx ) 1799 mxStrm->writeString( OUString( sal_Unicode( '\n' ) ) ); 1800 } 1801 1802 void Output::incIndent() 1803 { 1804 OUStringBuffer aBuffer( maIndent ); 1805 StringHelper::appendChar( aBuffer, ' ', OOX_DUMP_INDENT ); 1806 maIndent = aBuffer.makeStringAndClear(); 1807 } 1808 1809 void Output::decIndent() 1810 { 1811 if( maIndent.getLength() >= OOX_DUMP_INDENT ) 1812 maIndent = maIndent.copy( OOX_DUMP_INDENT ); 1813 } 1814 1815 void Output::resetIndent() 1816 { 1817 maIndent = OUString(); 1818 } 1819 1820 void Output::startTable( sal_Int32 nW1 ) 1821 { 1822 startTable( 1, &nW1 ); 1823 } 1824 1825 void Output::startTable( sal_Int32 nW1, sal_Int32 nW2 ) 1826 { 1827 sal_Int32 pnColWidths[ 2 ]; 1828 pnColWidths[ 0 ] = nW1; 1829 pnColWidths[ 1 ] = nW2; 1830 startTable( 2, pnColWidths ); 1831 } 1832 1833 void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3 ) 1834 { 1835 sal_Int32 pnColWidths[ 3 ]; 1836 pnColWidths[ 0 ] = nW1; 1837 pnColWidths[ 1 ] = nW2; 1838 pnColWidths[ 2 ] = nW3; 1839 startTable( 3, pnColWidths ); 1840 } 1841 1842 void Output::startTable( sal_Int32 nW1, sal_Int32 nW2, sal_Int32 nW3, sal_Int32 nW4 ) 1843 { 1844 sal_Int32 pnColWidths[ 4 ]; 1845 pnColWidths[ 0 ] = nW1; 1846 pnColWidths[ 1 ] = nW2; 1847 pnColWidths[ 2 ] = nW3; 1848 pnColWidths[ 3 ] = nW4; 1849 startTable( 4, pnColWidths ); 1850 } 1851 1852 void Output::startTable( size_t nColCount, const sal_Int32* pnColWidths ) 1853 { 1854 maColPos.clear(); 1855 maColPos.push_back( 0 ); 1856 sal_Int32 nColPos = 0; 1857 for( size_t nCol = 0; nCol < nColCount; ++nCol ) 1858 { 1859 nColPos = nColPos + pnColWidths[ nCol ]; 1860 maColPos.push_back( nColPos ); 1861 } 1862 } 1863 1864 void Output::tab() 1865 { 1866 tab( mnCol + 1 ); 1867 } 1868 1869 void Output::tab( size_t nCol ) 1870 { 1871 mnCol = nCol; 1872 if( mnCol < maColPos.size() ) 1873 { 1874 sal_Int32 nColPos = maColPos[ mnCol ]; 1875 if( maLine.getLength() >= nColPos ) 1876 maLine.setLength( ::std::max< sal_Int32 >( nColPos - 1, 0 ) ); 1877 StringHelper::appendChar( maLine, ' ', nColPos - maLine.getLength() ); 1878 } 1879 else 1880 { 1881 StringHelper::appendChar( maLine, ' ', 2 ); 1882 } 1883 } 1884 1885 void Output::endTable() 1886 { 1887 maColPos.clear(); 1888 } 1889 1890 void Output::resetItemIndex( sal_Int64 nIdx ) 1891 { 1892 mnItemIdx = nIdx; 1893 } 1894 1895 void Output::startItem( const String& rItemName ) 1896 { 1897 if( mnItemLevel == 0 ) 1898 { 1899 if( (mnMultiLevel > 0) && (maLine.getLength() > 0) ) 1900 tab(); 1901 if( rItemName.has() ) 1902 { 1903 writeItemName( rItemName ); 1904 writeChar( OOX_DUMP_ITEMSEP ); 1905 } 1906 } 1907 ++mnItemLevel; 1908 mnLastItem = maLine.getLength(); 1909 } 1910 1911 void Output::contItem() 1912 { 1913 if( mnItemLevel > 0 ) 1914 { 1915 if( (maLine.getLength() == 0) || (maLine[ maLine.getLength() - 1 ] != OOX_DUMP_ITEMSEP) ) 1916 writeChar( OOX_DUMP_ITEMSEP ); 1917 mnLastItem = maLine.getLength(); 1918 } 1919 } 1920 1921 void Output::endItem() 1922 { 1923 if( mnItemLevel > 0 ) 1924 { 1925 maLastItem = OUString( maLine.getStr() + mnLastItem ); 1926 if( (maLastItem.getLength() == 0) && (mnLastItem > 0) && (maLine[ mnLastItem - 1 ] == OOX_DUMP_ITEMSEP) ) 1927 maLine.setLength( mnLastItem - 1 ); 1928 --mnItemLevel; 1929 } 1930 if( mnItemLevel == 0 ) 1931 { 1932 if( mnMultiLevel == 0 ) 1933 newLine(); 1934 } 1935 else 1936 contItem(); 1937 } 1938 1939 void Output::startMultiItems() 1940 { 1941 ++mnMultiLevel; 1942 } 1943 1944 void Output::endMultiItems() 1945 { 1946 if( mnMultiLevel > 0 ) 1947 --mnMultiLevel; 1948 if( mnMultiLevel == 0 ) 1949 newLine(); 1950 } 1951 1952 // ---------------------------------------------------------------------------- 1953 1954 void Output::writeChar( sal_Unicode cChar, sal_Int32 nCount ) 1955 { 1956 StringHelper::appendEncChar( maLine, cChar, nCount ); 1957 } 1958 1959 void Output::writeAscii( const sal_Char* pcStr ) 1960 { 1961 if( pcStr ) 1962 maLine.appendAscii( pcStr ); 1963 } 1964 1965 void Output::writeString( const OUString& rStr ) 1966 { 1967 StringHelper::appendEncString( maLine, rStr ); 1968 } 1969 1970 void Output::writeArray( const sal_uInt8* pnData, sal_Size nSize, sal_Unicode cSep ) 1971 { 1972 const sal_uInt8* pnEnd = pnData ? (pnData + nSize) : 0; 1973 for( const sal_uInt8* pnByte = pnData; pnByte < pnEnd; ++pnByte ) 1974 { 1975 if( pnByte > pnData ) 1976 writeChar( cSep ); 1977 writeHex( *pnByte, false ); 1978 } 1979 } 1980 1981 void Output::writeBool( bool bData ) 1982 { 1983 StringHelper::appendBool( maLine, bData ); 1984 } 1985 1986 void Output::writeColorABGR( sal_Int32 nColor ) 1987 { 1988 writeChar( 'a' ); 1989 writeDec( static_cast< sal_uInt8 >( nColor >> 24 ) ); 1990 writeAscii( ",r" ); 1991 writeDec( static_cast< sal_uInt8 >( nColor ) ); 1992 writeAscii( ",g" ); 1993 writeDec( static_cast< sal_uInt8 >( nColor >> 8 ) ); 1994 writeAscii( ",b" ); 1995 writeDec( static_cast< sal_uInt8 >( nColor >> 16 ) ); 1996 } 1997 1998 void Output::writeDateTime( const DateTime& rDateTime ) 1999 { 2000 writeDec( rDateTime.Year, 4, '0' ); 2001 writeChar( '-' ); 2002 writeDec( rDateTime.Month, 2, '0' ); 2003 writeChar( '-' ); 2004 writeDec( rDateTime.Day, 2, '0' ); 2005 writeChar( 'T' ); 2006 writeDec( rDateTime.Hours, 2, '0' ); 2007 writeChar( ':' ); 2008 writeDec( rDateTime.Minutes, 2, '0' ); 2009 writeChar( ':' ); 2010 writeDec( rDateTime.Seconds, 2, '0' ); 2011 } 2012 2013 void Output::writeColIndex( sal_Int32 nCol ) 2014 { 2015 StringHelper::appendAddrCol( maLine, nCol, true ); 2016 } 2017 2018 void Output::writeRowIndex( sal_Int32 nRow ) 2019 { 2020 StringHelper::appendAddrRow( maLine, nRow, true ); 2021 } 2022 2023 void Output::writeColRowRange( sal_Int32 nColRow1, sal_Int32 nColRow2 ) 2024 { 2025 writeDec( nColRow1 ); 2026 writeChar( OOX_DUMP_RANGESEP ); 2027 writeDec( nColRow2 ); 2028 } 2029 2030 void Output::writeColRange( sal_Int32 nCol1, sal_Int32 nCol2 ) 2031 { 2032 writeColIndex( nCol1 ); 2033 writeChar( OOX_DUMP_RANGESEP ); 2034 writeColIndex( nCol2 ); 2035 } 2036 2037 void Output::writeRowRange( sal_Int32 nRow1, sal_Int32 nRow2 ) 2038 { 2039 writeRowIndex( nRow1 ); 2040 writeChar( OOX_DUMP_RANGESEP ); 2041 writeRowIndex( nRow2 ); 2042 } 2043 2044 void Output::writeAddress( const Address& rPos ) 2045 { 2046 StringHelper::appendAddress( maLine, rPos ); 2047 } 2048 2049 void Output::writeRange( const Range& rRange ) 2050 { 2051 StringHelper::appendRange( maLine, rRange ); 2052 } 2053 2054 void Output::writeRangeList( const RangeList& rRanges ) 2055 { 2056 StringHelper::appendRangeList( maLine, rRanges ); 2057 } 2058 2059 // ---------------------------------------------------------------------------- 2060 2061 bool Output::implIsValid() const 2062 { 2063 return mxStrm.is(); 2064 } 2065 2066 void Output::writeItemName( const String& rItemName ) 2067 { 2068 if( rItemName.has() && (rItemName[ 0 ] == '#') ) 2069 { 2070 writeString( rItemName.copy( 1 ) ); 2071 StringHelper::appendIndex( maLine, mnItemIdx++ ); 2072 } 2073 else 2074 writeString( rItemName ); 2075 } 2076 2077 // ============================================================================ 2078 2079 StorageIterator::StorageIterator( const StorageRef& rxStrg ) : 2080 mxStrg( rxStrg ) 2081 { 2082 if( mxStrg.get() ) 2083 mxStrg->getElementNames( maNames ); 2084 maIt = maNames.begin(); 2085 } 2086 2087 StorageIterator::~StorageIterator() 2088 { 2089 } 2090 2091 size_t StorageIterator::getElementCount() const 2092 { 2093 return maNames.size(); 2094 } 2095 2096 StorageIterator& StorageIterator::operator++() 2097 { 2098 if( maIt != maNames.end() ) 2099 ++maIt; 2100 return *this; 2101 } 2102 2103 OUString StorageIterator::getName() const 2104 { 2105 OUString aName; 2106 if( maIt != maNames.end() ) 2107 aName = *maIt; 2108 return aName; 2109 } 2110 2111 bool StorageIterator::isStream() const 2112 { 2113 return isValid() && mxStrg->openInputStream( *maIt ).is(); 2114 } 2115 2116 bool StorageIterator::isStorage() const 2117 { 2118 if( !isValid() ) 2119 return false; 2120 StorageRef xStrg = mxStrg->openSubStorage( *maIt, false ); 2121 return xStrg.get() && xStrg->isStorage(); 2122 } 2123 2124 bool StorageIterator::implIsValid() const 2125 { 2126 return mxStrg.get() && mxStrg->isStorage() && (maIt != maNames.end()); 2127 } 2128 2129 // ============================================================================ 2130 // ============================================================================ 2131 2132 ObjectBase::~ObjectBase() 2133 { 2134 } 2135 2136 void ObjectBase::construct( const ConfigRef& rxConfig ) 2137 { 2138 mxConfig = rxConfig; 2139 } 2140 2141 void ObjectBase::construct( const ObjectBase& rParent ) 2142 { 2143 *this = rParent; 2144 } 2145 2146 void ObjectBase::dump() 2147 { 2148 if( isValid() ) 2149 implDump(); 2150 } 2151 2152 bool ObjectBase::implIsValid() const 2153 { 2154 return isValid( mxConfig ); 2155 } 2156 2157 void ObjectBase::implDump() 2158 { 2159 } 2160 2161 void ObjectBase::reconstructConfig( const ConfigRef& rxConfig ) 2162 { 2163 if( isValid( rxConfig ) ) 2164 mxConfig = rxConfig; 2165 } 2166 2167 // ============================================================================ 2168 // ============================================================================ 2169 2170 void StorageObjectBase::construct( const ObjectBase& rParent, const StorageRef& rxStrg, const OUString& rSysPath ) 2171 { 2172 ObjectBase::construct( rParent ); 2173 mxStrg = rxStrg; 2174 maSysPath = rSysPath; 2175 } 2176 2177 void StorageObjectBase::construct( const ObjectBase& rParent ) 2178 { 2179 ObjectBase::construct( rParent ); 2180 if( ObjectBase::implIsValid() ) 2181 { 2182 mxStrg = cfg().getRootStorage(); 2183 maSysPath = cfg().getSysFileName(); 2184 } 2185 } 2186 2187 bool StorageObjectBase::implIsValid() const 2188 { 2189 return mxStrg.get() && (maSysPath.getLength() > 0) && ObjectBase::implIsValid(); 2190 } 2191 2192 void StorageObjectBase::implDump() 2193 { 2194 bool bIsStrg = mxStrg->isStorage(); 2195 bool bIsRoot = mxStrg->isRootStorage(); 2196 Reference< XInputStream > xBaseStrm; 2197 if( !bIsStrg ) 2198 xBaseStrm = mxStrg->openInputStream( OUString() ); 2199 2200 OUString aSysOutPath = maSysPath; 2201 if( bIsRoot ) try 2202 { 2203 aSysOutPath += OOX_DUMP_DUMPEXT; 2204 Reference< XMultiServiceFactory > xFactory( getContext()->getServiceManager(), UNO_QUERY_THROW ); 2205 Reference< XSimpleFileAccess > xFileAccess( xFactory->createInstance( CREATE_OUSTRING( "com.sun.star.ucb.SimpleFileAccess" ) ), UNO_QUERY_THROW ); 2206 xFileAccess->kill( aSysOutPath ); 2207 } 2208 catch( Exception& ) 2209 { 2210 } 2211 2212 if( bIsStrg ) 2213 { 2214 extractStorage( mxStrg, OUString(), aSysOutPath ); 2215 } 2216 else if( xBaseStrm.is() ) 2217 { 2218 BinaryInputStreamRef xInStrm( new BinaryXInputStream( xBaseStrm, false ) ); 2219 xInStrm->seekToStart(); 2220 implDumpBaseStream( xInStrm, aSysOutPath ); 2221 } 2222 } 2223 2224 void StorageObjectBase::implDumpStream( const Reference< XInputStream >&, const OUString&, const OUString&, const OUString& ) 2225 { 2226 } 2227 2228 void StorageObjectBase::implDumpStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath ) 2229 { 2230 extractStorage( rxStrg, rStrgPath, rSysPath ); 2231 } 2232 2233 void StorageObjectBase::implDumpBaseStream( const BinaryInputStreamRef&, const OUString& ) 2234 { 2235 } 2236 2237 void StorageObjectBase::addPreferredStream( const String& rStrmName ) 2238 { 2239 if( rStrmName.has() ) 2240 maPreferred.push_back( PreferredItem( rStrmName, false ) ); 2241 } 2242 2243 void StorageObjectBase::addPreferredStorage( const String& rStrgPath ) 2244 { 2245 if( rStrgPath.has() ) 2246 maPreferred.push_back( PreferredItem( rStrgPath, true ) ); 2247 } 2248 2249 OUString StorageObjectBase::getSysFileName( const OUString& rStrmName, const OUString& rSysOutPath ) 2250 { 2251 // encode all characters < 0x20 2252 OUStringBuffer aBuffer; 2253 StringHelper::appendEncString( aBuffer, rStrmName, false ); 2254 2255 // replace all characters reserved in file system 2256 OUString aFileName = aBuffer.makeStringAndClear(); 2257 static const sal_Unicode spcReserved[] = { '/', '\\', ':', '*', '?', '<', '>', '|' }; 2258 for( const sal_Unicode* pcChar = spcReserved; pcChar < STATIC_ARRAY_END( spcReserved ); ++pcChar ) 2259 aFileName = aFileName.replace( *pcChar, '_' ); 2260 2261 // build full path 2262 return rSysOutPath + OUString( sal_Unicode( '/' ) ) + aFileName; 2263 } 2264 2265 void StorageObjectBase::extractStream( StorageBase& rStrg, const OUString& rStrgPath, const OUString& rStrmName, const OUString& rSysFileName ) 2266 { 2267 BinaryXInputStream aInStrm( rStrg.openInputStream( rStrmName ), true ); 2268 if( !aInStrm.isEof() ) 2269 { 2270 BinaryXOutputStream aOutStrm( InputOutputHelper::openOutputStream( getContext(), rSysFileName ), true ); 2271 if( !aOutStrm.isEof() ) 2272 aInStrm.copyToStream( aOutStrm ); 2273 } 2274 Reference< XInputStream > xDumpStrm = InputOutputHelper::openInputStream( getContext(), rSysFileName ); 2275 if( xDumpStrm.is() ) 2276 implDumpStream( xDumpStrm, rStrgPath, rStrmName, rSysFileName ); 2277 } 2278 2279 void StorageObjectBase::extractStorage( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rSysPath ) 2280 { 2281 // create directory in file system 2282 ::osl::FileBase::RC eRes = ::osl::Directory::create( rSysPath ); 2283 if( (eRes != ::osl::FileBase::E_None) && (eRes != ::osl::FileBase::E_EXIST) ) 2284 return; 2285 2286 // process preferred storages and streams in root storage first 2287 if( rStrgPath.getLength() == 0 ) 2288 for( PreferredItemVector::iterator aIt = maPreferred.begin(), aEnd = maPreferred.end(); aIt != aEnd; ++aIt ) 2289 extractItem( rxStrg, rStrgPath, aIt->maName, rSysPath, aIt->mbStorage, !aIt->mbStorage ); 2290 2291 // process children of the storage 2292 for( StorageIterator aIt( rxStrg ); aIt.isValid(); ++aIt ) 2293 { 2294 // skip processed preferred items 2295 OUString aItemName = aIt.getName(); 2296 bool bFound = false; 2297 if( rStrgPath.getLength() == 0 ) 2298 for( PreferredItemVector::iterator aIIt = maPreferred.begin(), aIEnd = maPreferred.end(); !bFound && (aIIt != aIEnd); ++aIIt ) 2299 bFound = aIIt->maName == aItemName; 2300 if( !bFound ) 2301 extractItem( rxStrg, rStrgPath, aItemName, rSysPath, aIt.isStorage(), aIt.isStream() ); 2302 } 2303 } 2304 2305 void StorageObjectBase::extractItem( const StorageRef& rxStrg, const OUString& rStrgPath, const OUString& rItemName, const OUString& rSysPath, bool bIsStrg, bool bIsStrm ) 2306 { 2307 OUString aSysFileName = getSysFileName( rItemName, rSysPath ); 2308 if( bIsStrg ) 2309 { 2310 OUStringBuffer aStrgPath( rStrgPath ); 2311 StringHelper::appendToken( aStrgPath, rItemName, '/' ); 2312 implDumpStorage( rxStrg->openSubStorage( rItemName, false ), aStrgPath.makeStringAndClear(), aSysFileName ); 2313 } 2314 else if( bIsStrm ) 2315 { 2316 extractStream( *rxStrg, rStrgPath, rItemName, aSysFileName ); 2317 } 2318 } 2319 2320 // ============================================================================ 2321 // ============================================================================ 2322 2323 OutputObjectBase::~OutputObjectBase() 2324 { 2325 } 2326 2327 void OutputObjectBase::construct( const ObjectBase& rParent, const OUString& rSysFileName ) 2328 { 2329 ObjectBase::construct( rParent ); 2330 if( ObjectBase::implIsValid() ) 2331 { 2332 maSysFileName = rSysFileName; 2333 mxOut.reset( new Output( getContext(), rSysFileName + OOX_DUMP_DUMPEXT ) ); 2334 } 2335 } 2336 2337 void OutputObjectBase::construct( const OutputObjectBase& rParent ) 2338 { 2339 *this = rParent; 2340 } 2341 2342 bool OutputObjectBase::implIsValid() const 2343 { 2344 return isValid( mxOut ) && ObjectBase::implIsValid(); 2345 } 2346 2347 void OutputObjectBase::writeEmptyItem( const String& rName ) 2348 { 2349 ItemGuard aItem( mxOut, rName ); 2350 } 2351 2352 void OutputObjectBase::writeInfoItem( const String& rName, const String& rData ) 2353 { 2354 ItemGuard aItem( mxOut, rName ); 2355 mxOut->writeString( rData ); 2356 } 2357 2358 void OutputObjectBase::writeCharItem( const String& rName, sal_Unicode cData ) 2359 { 2360 ItemGuard aItem( mxOut, rName ); 2361 mxOut->writeChar( OOX_DUMP_STRQUOTE ); 2362 mxOut->writeChar( cData ); 2363 mxOut->writeChar( OOX_DUMP_STRQUOTE ); 2364 } 2365 2366 void OutputObjectBase::writeStringItem( const String& rName, const OUString& rData ) 2367 { 2368 ItemGuard aItem( mxOut, rName ); 2369 mxOut->writeAscii( "(len=" ); 2370 mxOut->writeDec( rData.getLength() ); 2371 mxOut->writeAscii( ")," ); 2372 OUStringBuffer aValue( rData.copy( 0, ::std::min( rData.getLength(), OOX_DUMP_MAXSTRLEN ) ) ); 2373 StringHelper::enclose( aValue, OOX_DUMP_STRQUOTE ); 2374 mxOut->writeString( aValue.makeStringAndClear() ); 2375 if( rData.getLength() > OOX_DUMP_MAXSTRLEN ) 2376 mxOut->writeAscii( ",cut" ); 2377 } 2378 2379 void OutputObjectBase::writeArrayItem( const String& rName, const sal_uInt8* pnData, sal_Size nSize, sal_Unicode cSep ) 2380 { 2381 ItemGuard aItem( mxOut, rName ); 2382 mxOut->writeArray( pnData, nSize, cSep ); 2383 } 2384 2385 void OutputObjectBase::writeBoolItem( const String& rName, bool bData ) 2386 { 2387 ItemGuard aItem( mxOut, rName ); 2388 mxOut->writeBool( bData ); 2389 } 2390 2391 double OutputObjectBase::writeRkItem( const String& rName, sal_Int32 nRk ) 2392 { 2393 MultiItemsGuard aMultiGuard( mxOut ); 2394 writeHexItem( rName, static_cast< sal_uInt32 >( nRk ), "RK-FLAGS" ); 2395 double fValue = ::oox::xls::BiffHelper::calcDoubleFromRk( nRk ); 2396 writeDecItem( "decoded", fValue ); 2397 return fValue; 2398 } 2399 2400 void OutputObjectBase::writeColorABGRItem( const String& rName, sal_Int32 nColor ) 2401 { 2402 ItemGuard aItem( mxOut, rName ); 2403 writeHexItem( rName, nColor ); 2404 mxOut->writeColorABGR( nColor ); 2405 } 2406 2407 void OutputObjectBase::writeDateTimeItem( const String& rName, const DateTime& rDateTime ) 2408 { 2409 ItemGuard aItem( mxOut, rName ); 2410 mxOut->writeDateTime( rDateTime ); 2411 } 2412 2413 void OutputObjectBase::writeGuidItem( const String& rName, const OUString& rGuid ) 2414 { 2415 ItemGuard aItem( mxOut, rName ); 2416 mxOut->writeString( rGuid ); 2417 aItem.cont(); 2418 mxOut->writeString( cfg().getStringOption( rGuid, OUString() ) ); 2419 } 2420 2421 void OutputObjectBase::writeColIndexItem( const String& rName, sal_Int32 nCol ) 2422 { 2423 ItemGuard aItem( mxOut, rName ); 2424 mxOut->writeDec( nCol ); 2425 aItem.cont(); 2426 mxOut->writeColIndex( nCol ); 2427 } 2428 2429 void OutputObjectBase::writeRowIndexItem( const String& rName, sal_Int32 nRow ) 2430 { 2431 ItemGuard aItem( mxOut, rName ); 2432 mxOut->writeDec( nRow ); 2433 aItem.cont(); 2434 mxOut->writeRowIndex( nRow ); 2435 } 2436 2437 void OutputObjectBase::writeColRangeItem( const String& rName, sal_Int32 nCol1, sal_Int32 nCol2 ) 2438 { 2439 ItemGuard aItem( mxOut, rName ); 2440 mxOut->writeColRowRange( nCol1, nCol2 ); 2441 aItem.cont(); 2442 mxOut->writeColRange( nCol1, nCol2 ); 2443 } 2444 2445 void OutputObjectBase::writeRowRangeItem( const String& rName, sal_Int32 nRow1, sal_Int32 nRow2 ) 2446 { 2447 ItemGuard aItem( mxOut, rName ); 2448 mxOut->writeColRowRange( nRow1, nRow2 ); 2449 aItem.cont(); 2450 mxOut->writeRowRange( nRow1, nRow2 ); 2451 } 2452 2453 void OutputObjectBase::writeAddressItem( const String& rName, const Address& rPos ) 2454 { 2455 ItemGuard aItem( mxOut, rName ); 2456 StringHelper::appendAddress( mxOut->getLine(), rPos ); 2457 } 2458 2459 void OutputObjectBase::writeRangeItem( const String& rName, const Range& rRange ) 2460 { 2461 ItemGuard aItem( mxOut, rName ); 2462 StringHelper::appendRange( mxOut->getLine(), rRange ); 2463 } 2464 2465 void OutputObjectBase::writeRangeListItem( const String& rName, const RangeList& rRanges ) 2466 { 2467 MultiItemsGuard aMultiGuard( mxOut ); 2468 writeEmptyItem( rName ); 2469 writeDecItem( "count", static_cast< sal_uInt16 >( rRanges.size() ) ); 2470 ItemGuard aItem( mxOut, "ranges" ); 2471 StringHelper::appendRangeList( mxOut->getLine(), rRanges ); 2472 } 2473 2474 void OutputObjectBase::writeTokenAddressItem( const String& rName, const TokenAddress& rPos, bool bNameMode ) 2475 { 2476 ItemGuard aItem( mxOut, rName ); 2477 StringHelper::appendAddress( mxOut->getLine(), rPos, bNameMode ); 2478 } 2479 2480 void OutputObjectBase::writeTokenAddress3dItem( const String& rName, const OUString& rRef, const TokenAddress& rPos, bool bNameMode ) 2481 { 2482 ItemGuard aItem( mxOut, rName ); 2483 mxOut->writeString( rRef ); 2484 StringHelper::appendAddress( mxOut->getLine(), rPos, bNameMode ); 2485 } 2486 2487 void OutputObjectBase::writeTokenRangeItem( const String& rName, const TokenRange& rRange, bool bNameMode ) 2488 { 2489 ItemGuard aItem( mxOut, rName ); 2490 StringHelper::appendRange( mxOut->getLine(), rRange, bNameMode ); 2491 } 2492 2493 void OutputObjectBase::writeTokenRange3dItem( const String& rName, const OUString& rRef, const TokenRange& rRange, bool bNameMode ) 2494 { 2495 ItemGuard aItem( mxOut, rName ); 2496 mxOut->writeString( rRef ); 2497 StringHelper::appendRange( mxOut->getLine(), rRange, bNameMode ); 2498 } 2499 2500 // ============================================================================ 2501 // ============================================================================ 2502 2503 InputObjectBase::~InputObjectBase() 2504 { 2505 } 2506 2507 void InputObjectBase::construct( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName ) 2508 { 2509 OutputObjectBase::construct( rParent, rSysFileName ); 2510 mxStrm = rxStrm; 2511 } 2512 2513 void InputObjectBase::construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm ) 2514 { 2515 OutputObjectBase::construct( rParent ); 2516 mxStrm = rxStrm; 2517 } 2518 2519 void InputObjectBase::construct( const InputObjectBase& rParent ) 2520 { 2521 *this = rParent; 2522 } 2523 2524 bool InputObjectBase::implIsValid() const 2525 { 2526 return mxStrm.get() && OutputObjectBase::implIsValid(); 2527 } 2528 2529 void InputObjectBase::skipBlock( sal_Int64 nBytes, bool bShowSize ) 2530 { 2531 sal_Int64 nEndPos = ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() ); 2532 if( mxStrm->tell() < nEndPos ) 2533 { 2534 if( bShowSize ) 2535 writeDecItem( "skipped-data-size", static_cast< sal_uInt64 >( nEndPos - mxStrm->tell() ) ); 2536 mxStrm->seek( nEndPos ); 2537 } 2538 } 2539 2540 void InputObjectBase::dumpRawBinary( sal_Int64 nBytes, bool bShowOffset, bool bStream ) 2541 { 2542 TableGuard aTabGuard( mxOut, 2543 bShowOffset ? 12 : 0, 2544 3 * OOX_DUMP_BYTESPERLINE / 2 + 1, 2545 3 * OOX_DUMP_BYTESPERLINE / 2 + 1, 2546 OOX_DUMP_BYTESPERLINE / 2 + 1 ); 2547 2548 sal_Int64 nMaxShowSize = cfg().getIntOption< sal_Int64 >( 2549 bStream ? "max-binary-stream-size" : "max-binary-data-size", SAL_MAX_INT64 ); 2550 2551 bool bSeekable = mxStrm->size() >= 0; 2552 sal_Int64 nEndPos = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nBytes, mxStrm->size() ) : 0; 2553 sal_Int64 nDumpEnd = bSeekable ? ::std::min< sal_Int64 >( mxStrm->tell() + nMaxShowSize, nEndPos ) : nMaxShowSize; 2554 sal_Int64 nPos = bSeekable ? mxStrm->tell() : 0; 2555 bool bLoop = true; 2556 2557 while( bLoop && (nPos < nDumpEnd) ) 2558 { 2559 mxOut->writeHex( static_cast< sal_uInt32 >( nPos ) ); 2560 mxOut->tab(); 2561 2562 sal_uInt8 pnLineData[ OOX_DUMP_BYTESPERLINE ]; 2563 sal_Int32 nLineSize = bSeekable ? ::std::min( static_cast< sal_Int32 >( nDumpEnd - mxStrm->tell() ), OOX_DUMP_BYTESPERLINE ) : OOX_DUMP_BYTESPERLINE; 2564 sal_Int32 nReadSize = mxStrm->readMemory( pnLineData, nLineSize ); 2565 bLoop = nReadSize == nLineSize; 2566 nPos += nReadSize; 2567 2568 if( nReadSize > 0 ) 2569 { 2570 const sal_uInt8* pnByte = 0; 2571 const sal_uInt8* pnEnd = 0; 2572 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte ) 2573 { 2574 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) mxOut->tab(); 2575 mxOut->writeHex( *pnByte, false ); 2576 mxOut->writeChar( ' ' ); 2577 } 2578 2579 aTabGuard.tab( 3 ); 2580 for( pnByte = pnLineData, pnEnd = pnLineData + nReadSize; pnByte != pnEnd; ++pnByte ) 2581 { 2582 if( (pnByte - pnLineData) == (OOX_DUMP_BYTESPERLINE / 2) ) mxOut->tab(); 2583 mxOut->writeChar( static_cast< sal_Unicode >( (*pnByte < 0x20) ? '.' : *pnByte ) ); 2584 } 2585 mxOut->newLine(); 2586 } 2587 } 2588 2589 // skip undumped data 2590 if( bSeekable ) 2591 skipBlock( nEndPos - mxStrm->tell() ); 2592 } 2593 2594 void InputObjectBase::dumpBinary( const String& rName, sal_Int64 nBytes, bool bShowOffset ) 2595 { 2596 { 2597 MultiItemsGuard aMultiGuard( mxOut ); 2598 writeEmptyItem( rName ); 2599 writeDecItem( "size", nBytes ); 2600 } 2601 IndentGuard aIndGuard( mxOut ); 2602 dumpRawBinary( nBytes, bShowOffset ); 2603 } 2604 2605 void InputObjectBase::dumpRemaining( sal_Int64 nBytes ) 2606 { 2607 if( nBytes > 0 ) 2608 { 2609 if( cfg().getBoolOption( "show-trailing-unknown", true ) ) 2610 dumpBinary( "remaining-data", nBytes, false ); 2611 else 2612 skipBlock( nBytes ); 2613 } 2614 } 2615 2616 void InputObjectBase::dumpRemainingTo( sal_Int64 nPos ) 2617 { 2618 if( mxStrm->isEof() || (mxStrm->tell() > nPos) ) 2619 writeInfoItem( "stream-state", OOX_DUMP_ERR_STREAM ); 2620 else 2621 dumpRemaining( nPos - mxStrm->tell() ); 2622 mxStrm->seek( nPos ); 2623 } 2624 2625 void InputObjectBase::dumpRemainingStream() 2626 { 2627 dumpRemainingTo( mxStrm->size() ); 2628 } 2629 2630 void InputObjectBase::dumpArray( const String& rName, sal_Int32 nBytes, sal_Unicode cSep ) 2631 { 2632 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nBytes ); 2633 if( nDumpSize > OOX_DUMP_MAXARRAY ) 2634 { 2635 dumpBinary( rName, nBytes, false ); 2636 } 2637 else if( nDumpSize > 1 ) 2638 { 2639 sal_uInt8 pnData[ OOX_DUMP_MAXARRAY ]; 2640 mxStrm->readMemory( pnData, nDumpSize ); 2641 writeArrayItem( rName, pnData, nDumpSize, cSep ); 2642 } 2643 else if( nDumpSize == 1 ) 2644 dumpHex< sal_uInt8 >( rName ); 2645 } 2646 2647 sal_Unicode InputObjectBase::dumpChar( const String& rName, rtl_TextEncoding eTextEnc ) 2648 { 2649 sal_uInt8 nChar; 2650 *mxStrm >> nChar; 2651 OUString aChar = OStringToOUString( OString( static_cast< sal_Char >( nChar ) ), eTextEnc ); 2652 sal_Unicode cChar = (aChar.getLength() > 0) ? aChar[ 0 ] : 0; 2653 writeCharItem( rName( "char" ), cChar ); 2654 return cChar; 2655 } 2656 2657 sal_Unicode InputObjectBase::dumpUnicode( const String& rName ) 2658 { 2659 sal_uInt16 nChar; 2660 *mxStrm >> nChar; 2661 sal_Unicode cChar = static_cast< sal_Unicode >( nChar ); 2662 writeCharItem( rName( "char" ), cChar ); 2663 return cChar; 2664 } 2665 2666 OUString InputObjectBase::dumpCharArray( const String& rName, sal_Int32 nLen, rtl_TextEncoding eTextEnc, bool bHideTrailingNul ) 2667 { 2668 sal_Int32 nDumpSize = getLimitedValue< sal_Int32, sal_Int64 >( mxStrm->size() - mxStrm->tell(), 0, nLen ); 2669 OUString aString; 2670 if( nDumpSize > 0 ) 2671 { 2672 ::std::vector< sal_Char > aBuffer( static_cast< sal_Size >( nLen ) + 1 ); 2673 sal_Int32 nCharsRead = mxStrm->readMemory( &aBuffer.front(), nLen ); 2674 aBuffer[ nCharsRead ] = 0; 2675 aString = OStringToOUString( OString( &aBuffer.front() ), eTextEnc ); 2676 } 2677 if( bHideTrailingNul ) 2678 aString = StringHelper::trimTrailingNul( aString ); 2679 writeStringItem( rName( "text" ), aString ); 2680 return aString; 2681 } 2682 2683 OUString InputObjectBase::dumpUnicodeArray( const String& rName, sal_Int32 nLen, bool bHideTrailingNul ) 2684 { 2685 OUStringBuffer aBuffer; 2686 for( sal_Int32 nIndex = 0; !mxStrm->isEof() && (nIndex < nLen); ++nIndex ) 2687 aBuffer.append( static_cast< sal_Unicode >( mxStrm->readuInt16() ) ); 2688 OUString aString = aBuffer.makeStringAndClear(); 2689 if( bHideTrailingNul ) 2690 aString = StringHelper::trimTrailingNul( aString ); 2691 writeStringItem( rName( "text" ), aString ); 2692 return aString; 2693 } 2694 2695 OUString InputObjectBase::dumpNullCharArray( const String& rName, rtl_TextEncoding eTextEnc ) 2696 { 2697 OStringBuffer aBuffer; 2698 sal_uInt8 nChar; 2699 for( *mxStrm >> nChar; !mxStrm->isEof() && (nChar > 0); *mxStrm >> nChar ) 2700 aBuffer.append( static_cast< sal_Char >( nChar ) ); 2701 OUString aString = OStringToOUString( aBuffer.makeStringAndClear(), eTextEnc ); 2702 writeStringItem( rName( "text" ), aString ); 2703 return aString; 2704 } 2705 2706 OUString InputObjectBase::dumpNullUnicodeArray( const String& rName ) 2707 { 2708 OUStringBuffer aBuffer; 2709 sal_uInt16 nChar; 2710 for( *mxStrm >> nChar; !mxStrm->isEof() && (nChar > 0); *mxStrm >> nChar ) 2711 aBuffer.append( static_cast< sal_Unicode >( nChar ) ); 2712 OUString aString = aBuffer.makeStringAndClear(); 2713 writeStringItem( rName( "text" ), aString ); 2714 return aString; 2715 } 2716 2717 double InputObjectBase::dumpRk( const String& rName ) 2718 { 2719 sal_Int32 nRk; 2720 *mxStrm >> nRk; 2721 return writeRkItem( rName( "rk-value" ), nRk ); 2722 } 2723 2724 sal_Int32 InputObjectBase::dumpColorABGR( const String& rName ) 2725 { 2726 sal_Int32 nColor; 2727 *mxStrm >> nColor; 2728 writeColorABGRItem( rName( "color" ), nColor ); 2729 return nColor; 2730 } 2731 2732 DateTime InputObjectBase::dumpFileTime( const String& rName ) 2733 { 2734 DateTime aDateTime; 2735 2736 ItemGuard aItem( mxOut, rName( "file-time" ) ); 2737 sal_Int64 nFileTime = dumpDec< sal_Int64 >( EMPTY_STRING ); 2738 // file time is in 10^-7 seconds (100 nanoseconds), convert to 1/100 seconds 2739 nFileTime /= 100000; 2740 // entire days 2741 sal_Int64 nDays = nFileTime / sal_Int64( 360000 * 24 ); 2742 // number of entire years 2743 sal_Int64 nYears = (nDays - (nDays / (4 * 365)) + (nDays / (100 * 365)) - (nDays / (400 * 365))) / 365; 2744 // remaining days in the year 2745 sal_Int64 nDaysInYear = nDays - (nYears * 365 + nYears / 4 - nYears / 100 + nYears / 400); 2746 // the year (file dates start from 1601-01-01) 2747 aDateTime.Year = static_cast< sal_uInt16 >( 1601 + nYears ); 2748 // leap year? 2749 bool bLeap = ((aDateTime.Year % 4 == 0) && (aDateTime.Year % 100 != 0)) || (aDateTime.Year % 400 == 0); 2750 // static arrays with number of days in month 2751 static const sal_Int64 spnDaysInMonth[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 2752 static const sal_Int64 spnDaysInMonthL[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; 2753 const sal_Int64* pnDaysInMonth = bLeap ? spnDaysInMonthL : spnDaysInMonth; 2754 // the month 2755 aDateTime.Month = 1; 2756 while( nDaysInYear >= *pnDaysInMonth ) 2757 { 2758 nDaysInYear -= *pnDaysInMonth++; 2759 ++aDateTime.Month; 2760 } 2761 // the day 2762 aDateTime.Day = static_cast< sal_uInt16 >( nDaysInYear + 1 ); 2763 // number of 1/100 seconds in the day 2764 sal_Int64 nTimeInDay = nFileTime % sal_Int64( 360000 * 24 ); 2765 // 1/100 seconds 2766 aDateTime.HundredthSeconds = static_cast< sal_uInt16 >( nTimeInDay % 100 ); 2767 nTimeInDay /= 100; 2768 // seconds 2769 aDateTime.Seconds = static_cast< sal_uInt16 >( nTimeInDay % 60 ); 2770 nTimeInDay /= 60; 2771 // minutes 2772 aDateTime.Minutes = static_cast< sal_uInt16 >( nTimeInDay % 60 ); 2773 nTimeInDay /= 60; 2774 // hours 2775 aDateTime.Hours = static_cast< sal_uInt16 >( nTimeInDay ); 2776 2777 writeDateTimeItem( EMPTY_STRING, aDateTime ); 2778 return aDateTime; 2779 } 2780 2781 OUString InputObjectBase::dumpGuid( const String& rName ) 2782 { 2783 OUStringBuffer aBuffer; 2784 sal_uInt32 nData32; 2785 sal_uInt16 nData16; 2786 sal_uInt8 nData8; 2787 2788 *mxStrm >> nData32; 2789 StringHelper::appendHex( aBuffer, nData32, false ); 2790 aBuffer.append( sal_Unicode( '-' ) ); 2791 *mxStrm >> nData16; 2792 StringHelper::appendHex( aBuffer, nData16, false ); 2793 aBuffer.append( sal_Unicode( '-' ) ); 2794 *mxStrm >> nData16; 2795 StringHelper::appendHex( aBuffer, nData16, false ); 2796 aBuffer.append( sal_Unicode( '-' ) ); 2797 *mxStrm >> nData8; 2798 StringHelper::appendHex( aBuffer, nData8, false ); 2799 *mxStrm >> nData8; 2800 StringHelper::appendHex( aBuffer, nData8, false ); 2801 aBuffer.append( sal_Unicode( '-' ) ); 2802 for( int nIndex = 0; nIndex < 6; ++nIndex ) 2803 { 2804 *mxStrm >> nData8; 2805 StringHelper::appendHex( aBuffer, nData8, false ); 2806 } 2807 StringHelper::enclose( aBuffer, '{', '}' ); 2808 OUString aGuid = aBuffer.makeStringAndClear(); 2809 writeGuidItem( rName( "guid" ), aGuid ); 2810 return aGuid; 2811 } 2812 2813 void InputObjectBase::dumpItem( const ItemFormat& rItemFmt ) 2814 { 2815 switch( rItemFmt.meDataType ) 2816 { 2817 case DATATYPE_VOID: break; 2818 case DATATYPE_INT8: dumpValue< sal_Int8 >( rItemFmt ); break; 2819 case DATATYPE_UINT8: dumpValue< sal_uInt8 >( rItemFmt ); break; 2820 case DATATYPE_INT16: dumpValue< sal_Int16 >( rItemFmt ); break; 2821 case DATATYPE_UINT16: dumpValue< sal_uInt16 >( rItemFmt ); break; 2822 case DATATYPE_INT32: dumpValue< sal_Int32 >( rItemFmt ); break; 2823 case DATATYPE_UINT32: dumpValue< sal_uInt32 >( rItemFmt ); break; 2824 case DATATYPE_INT64: dumpValue< sal_Int64 >( rItemFmt ); break; 2825 case DATATYPE_UINT64: dumpValue< sal_uInt64 >( rItemFmt ); break; 2826 case DATATYPE_FLOAT: dumpValue< float >( rItemFmt ); break; 2827 case DATATYPE_DOUBLE: dumpValue< double >( rItemFmt ); break; 2828 default:; 2829 } 2830 } 2831 2832 // ============================================================================ 2833 // ============================================================================ 2834 2835 BinaryStreamObject::BinaryStreamObject( const ObjectBase& rParent, const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName ) 2836 { 2837 InputObjectBase::construct( rParent, rxStrm, rSysFileName ); 2838 } 2839 2840 BinaryStreamObject::BinaryStreamObject( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm ) 2841 { 2842 InputObjectBase::construct( rParent, rxStrm ); 2843 } 2844 2845 void BinaryStreamObject::dumpBinaryStream( bool bShowOffset ) 2846 { 2847 mxStrm->seekToStart(); 2848 dumpRawBinary( mxStrm->size(), bShowOffset, true ); 2849 mxOut->emptyLine(); 2850 } 2851 2852 void BinaryStreamObject::implDump() 2853 { 2854 dumpBinaryStream(); 2855 } 2856 2857 // ============================================================================ 2858 // ============================================================================ 2859 2860 void TextStreamObjectBase::construct( const ObjectBase& rParent, 2861 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName ) 2862 { 2863 InputObjectBase::construct( rParent, rxStrm, rSysFileName ); 2864 constructTextStrmObj( eTextEnc ); 2865 } 2866 2867 void TextStreamObjectBase::construct( const OutputObjectBase& rParent, 2868 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc ) 2869 { 2870 InputObjectBase::construct( rParent, rxStrm ); 2871 constructTextStrmObj( eTextEnc ); 2872 } 2873 2874 void TextStreamObjectBase::construct( const InputObjectBase& rParent, rtl_TextEncoding eTextEnc ) 2875 { 2876 InputObjectBase::construct( rParent ); 2877 constructTextStrmObj( eTextEnc ); 2878 } 2879 2880 bool TextStreamObjectBase::implIsValid() const 2881 { 2882 return InputObjectBase::implIsValid() && mxTextStrm.get(); 2883 } 2884 2885 void TextStreamObjectBase::implDump() 2886 { 2887 implDumpText( *mxTextStrm ); 2888 } 2889 2890 void TextStreamObjectBase::constructTextStrmObj( rtl_TextEncoding eTextEnc ) 2891 { 2892 if( mxStrm.get() ) 2893 mxTextStrm.reset( new TextInputStream( getContext(), *mxStrm, eTextEnc ) ); 2894 } 2895 2896 // ============================================================================ 2897 2898 TextLineStreamObject::TextLineStreamObject( const ObjectBase& rParent, 2899 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc, const OUString& rSysFileName ) 2900 { 2901 TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc, rSysFileName ); 2902 } 2903 2904 TextLineStreamObject::TextLineStreamObject( const OutputObjectBase& rParent, 2905 const BinaryInputStreamRef& rxStrm, rtl_TextEncoding eTextEnc ) 2906 { 2907 TextStreamObjectBase::construct( rParent, rxStrm, eTextEnc ); 2908 } 2909 2910 void TextLineStreamObject::implDumpText( TextInputStream& rTextStrm ) 2911 { 2912 sal_uInt32 nLine = 0; 2913 while( !rTextStrm.isEof() ) 2914 { 2915 OUString aLine = rTextStrm.readLine(); 2916 if( !rTextStrm.isEof() || (aLine.getLength() > 0) ) 2917 implDumpLine( aLine, ++nLine ); 2918 } 2919 } 2920 2921 void TextLineStreamObject::implDumpLine( const OUString& rLine, sal_uInt32 nLine ) 2922 { 2923 TableGuard aTabGuard( mxOut, 8 ); 2924 mxOut->writeDec( nLine, 6 ); 2925 mxOut->tab(); 2926 mxOut->writeString( rLine ); 2927 mxOut->newLine(); 2928 } 2929 2930 // ============================================================================ 2931 2932 XmlStreamObject::XmlStreamObject( const ObjectBase& rParent, 2933 const BinaryInputStreamRef& rxStrm, const OUString& rSysFileName ) 2934 { 2935 TextStreamObjectBase::construct( rParent, rxStrm, RTL_TEXTENCODING_UTF8, rSysFileName ); 2936 } 2937 2938 XmlStreamObject::XmlStreamObject( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxStrm ) 2939 { 2940 TextStreamObjectBase::construct( rParent, rxStrm, RTL_TEXTENCODING_UTF8 ); 2941 } 2942 2943 void XmlStreamObject::implDumpText( TextInputStream& rTextStrm ) 2944 { 2945 /* Buffers a start element and the following element text. Needed to dump 2946 matching start/end elements and the element text on the same line. */ 2947 OUStringBuffer aOldStartElem; 2948 // special handling for VML 2949 bool bIsVml = InputOutputHelper::getFileNameExtension( maSysFileName ).equalsIgnoreAsciiCaseAscii( "vml" ); 2950 2951 while( !rTextStrm.isEof() ) 2952 { 2953 // get the next element and the following element text from text stream 2954 OUString aElem = rTextStrm.readToChar( '>', true ).trim(); 2955 OUString aText = rTextStrm.readToChar( '<', false ); 2956 2957 // remove multiple whitespace from element 2958 sal_Int32 nPos = 0; 2959 while( nPos < aElem.getLength() ) 2960 { 2961 while( (nPos < aElem.getLength()) && (aElem[ nPos ] >= 32) ) ++nPos; 2962 if( nPos < aElem.getLength() ) 2963 aElem = OUStringBuffer( aElem.copy( 0, nPos ) ).append( sal_Unicode( ' ' ) ).append( aElem.copy( nPos ).trim() ).makeStringAndClear(); 2964 ++nPos; 2965 } 2966 2967 sal_Int32 nElemLen = aElem.getLength(); 2968 if( (nElemLen >= 2) && (aElem[ 0 ] == '<') && (aElem[ nElemLen - 1 ] == '>') ) 2969 { 2970 // determine type of the element 2971 bool bSimpleElem = (aElem[ 1 ] == '!') || (aElem[ 1 ] == '?') || (aElem[ nElemLen - 2 ] == '/') || 2972 (bIsVml && (nElemLen == 4) && (aElem[ 1 ] == 'b') && (aElem[ 2 ] == 'r')); 2973 bool bStartElem = !bSimpleElem && (aElem[ 1 ] != '/'); 2974 bool bEndElem = !bSimpleElem && !bStartElem; 2975 2976 /* Start element or simple element: flush old start element and 2977 its text from previous iteration, and start a new indentation 2978 level for the new element. Trim whitespace and line breaks from 2979 the text of the old start element. */ 2980 if( (bSimpleElem || bStartElem) && (aOldStartElem.getLength() > 0) ) 2981 { 2982 mxOut->writeString( aOldStartElem.makeStringAndClear().trim() ); 2983 mxOut->newLine(); 2984 mxOut->incIndent(); 2985 } 2986 2987 /* Start element: remember it and its text, to be able to print the 2988 matching end element on the same line in the next iteration. */ 2989 if( bStartElem ) 2990 { 2991 aOldStartElem.append( aElem ).append( aText ); 2992 } 2993 else 2994 { 2995 /* End element: if a start element has been remembered in the 2996 previous iteration, write it out here untrimmed, to show 2997 all whitespace in the element text, and without trailing 2998 line break. Code below will add the end element right after 2999 it. Otherwise, return to previous indentation level. */ 3000 if( bEndElem ) 3001 { 3002 if( aOldStartElem.getLength() == 0 ) 3003 mxOut->decIndent(); 3004 else 3005 mxOut->writeString( aOldStartElem.makeStringAndClear() ); 3006 } 3007 3008 /* Write the element. Write following element text in a new 3009 line, but only, if it does not contain of white space 3010 entirely. */ 3011 mxOut->writeString( aElem ); 3012 mxOut->newLine(); 3013 if( aText.trim().getLength() > 0 ) 3014 { 3015 mxOut->writeString( aText ); 3016 mxOut->newLine(); 3017 } 3018 } 3019 } 3020 } 3021 } 3022 3023 // ============================================================================ 3024 // ============================================================================ 3025 3026 void RecordObjectBase::construct( const ObjectBase& rParent, 3027 const BinaryInputStreamRef& rxBaseStrm, const OUString& rSysFileName, 3028 const BinaryInputStreamRef& rxRecStrm, const String& rRecNames, const String& rSimpleRecs ) 3029 { 3030 InputObjectBase::construct( rParent, rxRecStrm, rSysFileName ); 3031 constructRecObjBase( rxBaseStrm, rRecNames, rSimpleRecs ); 3032 } 3033 3034 void RecordObjectBase::construct( const OutputObjectBase& rParent, const BinaryInputStreamRef& rxBaseStrm, 3035 const BinaryInputStreamRef& rxRecStrm, const String& rRecNames, const String& rSimpleRecs ) 3036 { 3037 InputObjectBase::construct( rParent, rxRecStrm ); 3038 constructRecObjBase( rxBaseStrm, rRecNames, rSimpleRecs ); 3039 } 3040 3041 bool RecordObjectBase::implIsValid() const 3042 { 3043 return mxBaseStrm.get() && InputObjectBase::implIsValid(); 3044 } 3045 3046 void RecordObjectBase::implDump() 3047 { 3048 NameListRef xRecNames = getRecNames(); 3049 ItemFormatMap aSimpleRecs( maSimpleRecs.getNameList( cfg() ) ); 3050 3051 while( implStartRecord( *mxBaseStrm, mnRecPos, mnRecId, mnRecSize ) ) 3052 { 3053 // record header 3054 mxOut->emptyLine(); 3055 writeHeader(); 3056 implWriteExtHeader(); 3057 IndentGuard aIndGuard( mxOut ); 3058 sal_Int64 nRecPos = mxStrm->tell(); 3059 3060 // record body 3061 if( !mbBinaryOnly && cfg().hasName( xRecNames, mnRecId ) ) 3062 { 3063 ItemFormatMap::const_iterator aIt = aSimpleRecs.find( mnRecId ); 3064 if( aIt != aSimpleRecs.end() ) 3065 dumpItem( aIt->second ); 3066 else 3067 implDumpRecordBody(); 3068 } 3069 3070 // remaining undumped data 3071 if( !mxStrm->isEof() && (mxStrm->tell() == nRecPos) ) 3072 dumpRawBinary( mnRecSize, false ); 3073 else 3074 dumpRemainingTo( nRecPos + mnRecSize ); 3075 } 3076 } 3077 3078 void RecordObjectBase::implWriteExtHeader() 3079 { 3080 } 3081 3082 void RecordObjectBase::implDumpRecordBody() 3083 { 3084 } 3085 3086 void RecordObjectBase::constructRecObjBase( const BinaryInputStreamRef& rxBaseStrm, const String& rRecNames, const String& rSimpleRecs ) 3087 { 3088 mxBaseStrm = rxBaseStrm; 3089 maRecNames = rRecNames; 3090 maSimpleRecs = rSimpleRecs; 3091 mnRecPos = mnRecId = mnRecSize = 0; 3092 mbBinaryOnly = false; 3093 if( InputObjectBase::implIsValid() ) 3094 mbShowRecPos = cfg().getBoolOption( "show-record-position", true ); 3095 } 3096 3097 void RecordObjectBase::writeHeader() 3098 { 3099 MultiItemsGuard aMultiGuard( mxOut ); 3100 writeEmptyItem( "REC" ); 3101 if( mbShowRecPos && mxBaseStrm->isSeekable() ) 3102 writeShortHexItem( "pos", mnRecPos, "CONV-DEC" ); 3103 writeShortHexItem( "size", mnRecSize, "CONV-DEC" ); 3104 ItemGuard aItem( mxOut, "id" ); 3105 mxOut->writeShortHex( mnRecId ); 3106 addNameToItem( mnRecId, "CONV-DEC" ); 3107 addNameToItem( mnRecId, maRecNames ); 3108 } 3109 3110 // ============================================================================ 3111 3112 void SequenceRecordObjectBase::construct( const ObjectBase& rParent, 3113 const BinaryInputStreamRef& rxBaseStrm, const ::rtl::OUString& rSysFileName, 3114 const String& rRecNames, const String& rSimpleRecs ) 3115 { 3116 BinaryInputStreamRef xRecStrm( new SequenceInputStream( *mxRecData ) ); 3117 RecordObjectBase::construct( rParent, rxBaseStrm, rSysFileName, xRecStrm, rRecNames, rSimpleRecs ); 3118 } 3119 3120 void SequenceRecordObjectBase::construct( const OutputObjectBase& rParent, 3121 const BinaryInputStreamRef& rxBaseStrm, const String& rRecNames, const String& rSimpleRecs ) 3122 { 3123 BinaryInputStreamRef xRecStrm( new SequenceInputStream( *mxRecData ) ); 3124 RecordObjectBase::construct( rParent, rxBaseStrm, xRecStrm, rRecNames, rSimpleRecs ); 3125 } 3126 3127 bool SequenceRecordObjectBase::implStartRecord( BinaryInputStream& rBaseStrm, sal_Int64& ornRecPos, sal_Int64& ornRecId, sal_Int64& ornRecSize ) 3128 { 3129 bool bValid = true; 3130 if( rBaseStrm.isSeekable() ) 3131 { 3132 ornRecPos = rBaseStrm.tell(); 3133 // do not try to overread seekable streams, may cause assertions 3134 bValid = ornRecPos < rBaseStrm.size(); 3135 } 3136 3137 // read the record header 3138 if( bValid ) 3139 bValid = implReadRecordHeader( rBaseStrm, ornRecId, ornRecSize ) && !rBaseStrm.isEof() && (0 <= ornRecSize) && (ornRecSize <= 0x00100000); 3140 3141 // read record contents into data sequence 3142 if( bValid ) 3143 { 3144 sal_Int32 nRecSize = static_cast< sal_Int32 >( ornRecSize ); 3145 mxRecData->realloc( nRecSize ); 3146 bValid = (nRecSize == 0) || (rBaseStrm.readData( *mxRecData, nRecSize ) == nRecSize); 3147 mxStrm->seekToStart(); 3148 } 3149 return bValid; 3150 } 3151 3152 // ============================================================================ 3153 // ============================================================================ 3154 3155 DumperBase::~DumperBase() 3156 { 3157 } 3158 3159 bool DumperBase::isImportEnabled() const 3160 { 3161 return !isValid() || cfg().isImportEnabled(); 3162 } 3163 3164 bool DumperBase::isImportCancelled() const 3165 { 3166 return isValid() && cfg().isPasswordCancelled(); 3167 } 3168 3169 void DumperBase::construct( const ConfigRef& rxConfig ) 3170 { 3171 if( isValid( rxConfig ) && rxConfig->isDumperEnabled() ) 3172 ObjectBase::construct( rxConfig ); 3173 } 3174 3175 // ============================================================================ 3176 // ============================================================================ 3177 3178 } // namespace dump 3179 } // namespace oox 3180 3181 #endif 3182