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