1*ca5ec200SAndrew Rist /************************************************************** 2cdf0e10cSrcweir * 3*ca5ec200SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one 4*ca5ec200SAndrew Rist * or more contributor license agreements. See the NOTICE file 5*ca5ec200SAndrew Rist * distributed with this work for additional information 6*ca5ec200SAndrew Rist * regarding copyright ownership. The ASF licenses this file 7*ca5ec200SAndrew Rist * to you under the Apache License, Version 2.0 (the 8*ca5ec200SAndrew Rist * "License"); you may not use this file except in compliance 9*ca5ec200SAndrew Rist * with the License. You may obtain a copy of the License at 10cdf0e10cSrcweir * 11*ca5ec200SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0 12cdf0e10cSrcweir * 13*ca5ec200SAndrew Rist * Unless required by applicable law or agreed to in writing, 14*ca5ec200SAndrew Rist * software distributed under the License is distributed on an 15*ca5ec200SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16*ca5ec200SAndrew Rist * KIND, either express or implied. See the License for the 17*ca5ec200SAndrew Rist * specific language governing permissions and limitations 18*ca5ec200SAndrew Rist * under the License. 19cdf0e10cSrcweir * 20*ca5ec200SAndrew Rist *************************************************************/ 21*ca5ec200SAndrew Rist 22*ca5ec200SAndrew Rist 23cdf0e10cSrcweir 24cdf0e10cSrcweir #include "oox/xls/biffcodec.hxx" 25cdf0e10cSrcweir 26cdf0e10cSrcweir #include <osl/thread.h> 27cdf0e10cSrcweir #include <string.h> 28cdf0e10cSrcweir #include "oox/core/filterbase.hxx" 29cdf0e10cSrcweir #include "oox/xls/biffinputstream.hxx" 30cdf0e10cSrcweir 31cdf0e10cSrcweir namespace oox { 32cdf0e10cSrcweir namespace xls { 33cdf0e10cSrcweir 34cdf0e10cSrcweir // ============================================================================ 35cdf0e10cSrcweir 36cdf0e10cSrcweir using namespace ::com::sun::star::beans; 37cdf0e10cSrcweir using namespace ::com::sun::star::uno; 38cdf0e10cSrcweir 39cdf0e10cSrcweir using ::oox::core::FilterBase; 40cdf0e10cSrcweir using ::rtl::OString; 41cdf0e10cSrcweir using ::rtl::OUString; 42cdf0e10cSrcweir using ::rtl::OStringToOUString; 43cdf0e10cSrcweir 44cdf0e10cSrcweir // ============================================================================ 45cdf0e10cSrcweir 46cdf0e10cSrcweir BiffDecoderBase::BiffDecoderBase() : 47cdf0e10cSrcweir mbValid( false ) 48cdf0e10cSrcweir { 49cdf0e10cSrcweir } 50cdf0e10cSrcweir 51cdf0e10cSrcweir BiffDecoderBase::~BiffDecoderBase() 52cdf0e10cSrcweir { 53cdf0e10cSrcweir } 54cdf0e10cSrcweir 55cdf0e10cSrcweir ::comphelper::DocPasswordVerifierResult BiffDecoderBase::verifyPassword( const OUString& rPassword, Sequence< NamedValue >& o_rEncryptionData ) 56cdf0e10cSrcweir { 57cdf0e10cSrcweir o_rEncryptionData = implVerifyPassword( rPassword ); 58cdf0e10cSrcweir mbValid = o_rEncryptionData.hasElements(); 59cdf0e10cSrcweir return mbValid ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD; 60cdf0e10cSrcweir } 61cdf0e10cSrcweir 62cdf0e10cSrcweir ::comphelper::DocPasswordVerifierResult BiffDecoderBase::verifyEncryptionData( const Sequence< NamedValue >& rEncryptionData ) 63cdf0e10cSrcweir { 64cdf0e10cSrcweir mbValid = implVerifyEncryptionData( rEncryptionData ); 65cdf0e10cSrcweir return mbValid ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD; 66cdf0e10cSrcweir } 67cdf0e10cSrcweir 68cdf0e10cSrcweir void BiffDecoderBase::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes ) 69cdf0e10cSrcweir { 70cdf0e10cSrcweir if( pnDestData && pnSrcData && (nBytes > 0) ) 71cdf0e10cSrcweir { 72cdf0e10cSrcweir if( mbValid ) 73cdf0e10cSrcweir implDecode( pnDestData, pnSrcData, nStreamPos, nBytes ); 74cdf0e10cSrcweir else 75cdf0e10cSrcweir memcpy( pnDestData, pnSrcData, nBytes ); 76cdf0e10cSrcweir } 77cdf0e10cSrcweir } 78cdf0e10cSrcweir 79cdf0e10cSrcweir // ============================================================================ 80cdf0e10cSrcweir 81cdf0e10cSrcweir BiffDecoder_XOR::BiffDecoder_XOR( sal_uInt16 nKey, sal_uInt16 nHash ) : 82cdf0e10cSrcweir maCodec( ::oox::core::BinaryCodec_XOR::CODEC_EXCEL ), 83cdf0e10cSrcweir mnKey( nKey ), 84cdf0e10cSrcweir mnHash( nHash ) 85cdf0e10cSrcweir { 86cdf0e10cSrcweir } 87cdf0e10cSrcweir 88cdf0e10cSrcweir BiffDecoder_XOR::BiffDecoder_XOR( const BiffDecoder_XOR& rDecoder ) : 89cdf0e10cSrcweir BiffDecoderBase(), // must be called to prevent compiler warning 90cdf0e10cSrcweir maCodec( ::oox::core::BinaryCodec_XOR::CODEC_EXCEL ), 91cdf0e10cSrcweir maEncryptionData( rDecoder.maEncryptionData ), 92cdf0e10cSrcweir mnKey( rDecoder.mnKey ), 93cdf0e10cSrcweir mnHash( rDecoder.mnHash ) 94cdf0e10cSrcweir { 95cdf0e10cSrcweir if( isValid() ) 96cdf0e10cSrcweir maCodec.initCodec( maEncryptionData ); 97cdf0e10cSrcweir } 98cdf0e10cSrcweir 99cdf0e10cSrcweir BiffDecoder_XOR* BiffDecoder_XOR::implClone() 100cdf0e10cSrcweir { 101cdf0e10cSrcweir return new BiffDecoder_XOR( *this ); 102cdf0e10cSrcweir } 103cdf0e10cSrcweir 104cdf0e10cSrcweir Sequence< NamedValue > BiffDecoder_XOR::implVerifyPassword( const OUString& rPassword ) 105cdf0e10cSrcweir { 106cdf0e10cSrcweir maEncryptionData.realloc( 0 ); 107cdf0e10cSrcweir 108cdf0e10cSrcweir /* Convert password to a byte string. TODO: this needs some finetuning 109cdf0e10cSrcweir according to the spec... */ 110cdf0e10cSrcweir OString aBytePassword = OUStringToOString( rPassword, osl_getThreadTextEncoding() ); 111cdf0e10cSrcweir sal_Int32 nLen = aBytePassword.getLength(); 112cdf0e10cSrcweir if( (0 < nLen) && (nLen < 16) ) 113cdf0e10cSrcweir { 114cdf0e10cSrcweir // init codec 115cdf0e10cSrcweir maCodec.initKey( reinterpret_cast< const sal_uInt8* >( aBytePassword.getStr() ) ); 116cdf0e10cSrcweir 117cdf0e10cSrcweir if( maCodec.verifyKey( mnKey, mnHash ) ) 118cdf0e10cSrcweir maEncryptionData = maCodec.getEncryptionData(); 119cdf0e10cSrcweir } 120cdf0e10cSrcweir 121cdf0e10cSrcweir return maEncryptionData; 122cdf0e10cSrcweir } 123cdf0e10cSrcweir 124cdf0e10cSrcweir bool BiffDecoder_XOR::implVerifyEncryptionData( const Sequence< NamedValue >& rEncryptionData ) 125cdf0e10cSrcweir { 126cdf0e10cSrcweir maEncryptionData.realloc( 0 ); 127cdf0e10cSrcweir 128cdf0e10cSrcweir if( rEncryptionData.hasElements() ) 129cdf0e10cSrcweir { 130cdf0e10cSrcweir // init codec 131cdf0e10cSrcweir maCodec.initCodec( rEncryptionData ); 132cdf0e10cSrcweir 133cdf0e10cSrcweir if( maCodec.verifyKey( mnKey, mnHash ) ) 134cdf0e10cSrcweir maEncryptionData = rEncryptionData; 135cdf0e10cSrcweir } 136cdf0e10cSrcweir 137cdf0e10cSrcweir return maEncryptionData.hasElements(); 138cdf0e10cSrcweir } 139cdf0e10cSrcweir 140cdf0e10cSrcweir void BiffDecoder_XOR::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes ) 141cdf0e10cSrcweir { 142cdf0e10cSrcweir maCodec.startBlock(); 143cdf0e10cSrcweir maCodec.skip( static_cast< sal_Int32 >( (nStreamPos + nBytes) & 0x0F ) ); 144cdf0e10cSrcweir maCodec.decode( pnDestData, pnSrcData, nBytes ); 145cdf0e10cSrcweir } 146cdf0e10cSrcweir 147cdf0e10cSrcweir // ============================================================================ 148cdf0e10cSrcweir 149cdf0e10cSrcweir namespace { 150cdf0e10cSrcweir 151cdf0e10cSrcweir /** Returns the block index of the passed stream position for RCF decryption. */ 152cdf0e10cSrcweir sal_Int32 lclGetRcfBlock( sal_Int64 nStreamPos ) 153cdf0e10cSrcweir { 154cdf0e10cSrcweir return static_cast< sal_Int32 >( nStreamPos / BIFF_RCF_BLOCKSIZE ); 155cdf0e10cSrcweir } 156cdf0e10cSrcweir 157cdf0e10cSrcweir /** Returns the offset of the passed stream position in a block for RCF decryption. */ 158cdf0e10cSrcweir sal_Int32 lclGetRcfOffset( sal_Int64 nStreamPos ) 159cdf0e10cSrcweir { 160cdf0e10cSrcweir return static_cast< sal_Int32 >( nStreamPos % BIFF_RCF_BLOCKSIZE ); 161cdf0e10cSrcweir } 162cdf0e10cSrcweir 163cdf0e10cSrcweir } // namespace 164cdf0e10cSrcweir 165cdf0e10cSrcweir // ---------------------------------------------------------------------------- 166cdf0e10cSrcweir 167cdf0e10cSrcweir BiffDecoder_RCF::BiffDecoder_RCF( sal_uInt8 pnSalt[ 16 ], sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] ) : 168cdf0e10cSrcweir maSalt( pnSalt, pnSalt + 16 ), 169cdf0e10cSrcweir maVerifier( pnVerifier, pnVerifier + 16 ), 170cdf0e10cSrcweir maVerifierHash( pnVerifierHash, pnVerifierHash + 16 ) 171cdf0e10cSrcweir { 172cdf0e10cSrcweir } 173cdf0e10cSrcweir 174cdf0e10cSrcweir BiffDecoder_RCF::BiffDecoder_RCF( const BiffDecoder_RCF& rDecoder ) : 175cdf0e10cSrcweir BiffDecoderBase(), // must be called to prevent compiler warning 176cdf0e10cSrcweir maEncryptionData( rDecoder.maEncryptionData ), 177cdf0e10cSrcweir maSalt( rDecoder.maSalt ), 178cdf0e10cSrcweir maVerifier( rDecoder.maVerifier ), 179cdf0e10cSrcweir maVerifierHash( rDecoder.maVerifierHash ) 180cdf0e10cSrcweir { 181cdf0e10cSrcweir if( isValid() ) 182cdf0e10cSrcweir maCodec.initCodec( maEncryptionData ); 183cdf0e10cSrcweir } 184cdf0e10cSrcweir 185cdf0e10cSrcweir BiffDecoder_RCF* BiffDecoder_RCF::implClone() 186cdf0e10cSrcweir { 187cdf0e10cSrcweir return new BiffDecoder_RCF( *this ); 188cdf0e10cSrcweir } 189cdf0e10cSrcweir 190cdf0e10cSrcweir Sequence< NamedValue > BiffDecoder_RCF::implVerifyPassword( const OUString& rPassword ) 191cdf0e10cSrcweir { 192cdf0e10cSrcweir maEncryptionData.realloc( 0 ); 193cdf0e10cSrcweir 194cdf0e10cSrcweir sal_Int32 nLen = rPassword.getLength(); 195cdf0e10cSrcweir if( (0 < nLen) && (nLen < 16) ) 196cdf0e10cSrcweir { 197cdf0e10cSrcweir // copy string to sal_uInt16 array 198cdf0e10cSrcweir ::std::vector< sal_uInt16 > aPassVect( 16 ); 199cdf0e10cSrcweir const sal_Unicode* pcChar = rPassword.getStr(); 200cdf0e10cSrcweir const sal_Unicode* pcCharEnd = pcChar + nLen; 201cdf0e10cSrcweir ::std::vector< sal_uInt16 >::iterator aIt = aPassVect.begin(); 202cdf0e10cSrcweir for( ; pcChar < pcCharEnd; ++pcChar, ++aIt ) 203cdf0e10cSrcweir *aIt = static_cast< sal_uInt16 >( *pcChar ); 204cdf0e10cSrcweir 205cdf0e10cSrcweir // init codec 206cdf0e10cSrcweir maCodec.initKey( &aPassVect.front(), &maSalt.front() ); 207cdf0e10cSrcweir if( maCodec.verifyKey( &maVerifier.front(), &maVerifierHash.front() ) ) 208cdf0e10cSrcweir maEncryptionData = maCodec.getEncryptionData(); 209cdf0e10cSrcweir } 210cdf0e10cSrcweir 211cdf0e10cSrcweir return maEncryptionData; 212cdf0e10cSrcweir } 213cdf0e10cSrcweir 214cdf0e10cSrcweir bool BiffDecoder_RCF::implVerifyEncryptionData( const Sequence< NamedValue >& rEncryptionData ) 215cdf0e10cSrcweir { 216cdf0e10cSrcweir maEncryptionData.realloc( 0 ); 217cdf0e10cSrcweir 218cdf0e10cSrcweir if( rEncryptionData.hasElements() ) 219cdf0e10cSrcweir { 220cdf0e10cSrcweir // init codec 221cdf0e10cSrcweir maCodec.initCodec( rEncryptionData ); 222cdf0e10cSrcweir 223cdf0e10cSrcweir if( maCodec.verifyKey( &maVerifier.front(), &maVerifierHash.front() ) ) 224cdf0e10cSrcweir maEncryptionData = rEncryptionData; 225cdf0e10cSrcweir } 226cdf0e10cSrcweir 227cdf0e10cSrcweir return maEncryptionData.hasElements(); 228cdf0e10cSrcweir } 229cdf0e10cSrcweir 230cdf0e10cSrcweir void BiffDecoder_RCF::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes ) 231cdf0e10cSrcweir { 232cdf0e10cSrcweir sal_uInt8* pnCurrDest = pnDestData; 233cdf0e10cSrcweir const sal_uInt8* pnCurrSrc = pnSrcData; 234cdf0e10cSrcweir sal_Int64 nCurrPos = nStreamPos; 235cdf0e10cSrcweir sal_uInt16 nBytesLeft = nBytes; 236cdf0e10cSrcweir while( nBytesLeft > 0 ) 237cdf0e10cSrcweir { 238cdf0e10cSrcweir // initialize codec for current stream position 239cdf0e10cSrcweir maCodec.startBlock( lclGetRcfBlock( nCurrPos ) ); 240cdf0e10cSrcweir maCodec.skip( lclGetRcfOffset( nCurrPos ) ); 241cdf0e10cSrcweir 242cdf0e10cSrcweir // decode the block 243cdf0e10cSrcweir sal_uInt16 nBlockLeft = static_cast< sal_uInt16 >( BIFF_RCF_BLOCKSIZE - lclGetRcfOffset( nCurrPos ) ); 244cdf0e10cSrcweir sal_uInt16 nDecBytes = ::std::min( nBytesLeft, nBlockLeft ); 245cdf0e10cSrcweir maCodec.decode( pnCurrDest, pnCurrSrc, static_cast< sal_Int32 >( nDecBytes ) ); 246cdf0e10cSrcweir 247cdf0e10cSrcweir // prepare for next block 248cdf0e10cSrcweir pnCurrDest += nDecBytes; 249cdf0e10cSrcweir pnCurrSrc += nDecBytes; 250cdf0e10cSrcweir nCurrPos += nDecBytes; 251cdf0e10cSrcweir nBytesLeft = nBytesLeft - nDecBytes; 252cdf0e10cSrcweir } 253cdf0e10cSrcweir } 254cdf0e10cSrcweir 255cdf0e10cSrcweir // ============================================================================ 256cdf0e10cSrcweir 257cdf0e10cSrcweir namespace { 258cdf0e10cSrcweir 259cdf0e10cSrcweir const sal_uInt16 BIFF_FILEPASS_XOR = 0; 260cdf0e10cSrcweir const sal_uInt16 BIFF_FILEPASS_RCF = 1; 261cdf0e10cSrcweir 262cdf0e10cSrcweir const sal_uInt16 BIFF_FILEPASS_BIFF8_RCF = 1; 263cdf0e10cSrcweir const sal_uInt16 BIFF_FILEPASS_BIFF8_CRYPTOAPI_2003 = 2; 264cdf0e10cSrcweir const sal_uInt16 BIFF_FILEPASS_BIFF8_CRYPTOAPI_2007 = 3; 265cdf0e10cSrcweir 266cdf0e10cSrcweir // ---------------------------------------------------------------------------- 267cdf0e10cSrcweir 268cdf0e10cSrcweir BiffDecoderRef lclReadFilePass_XOR( BiffInputStream& rStrm ) 269cdf0e10cSrcweir { 270cdf0e10cSrcweir BiffDecoderRef xDecoder; 271cdf0e10cSrcweir OSL_ENSURE( rStrm.getRemaining() == 4, "lclReadFilePass_XOR - wrong record size" ); 272cdf0e10cSrcweir if( rStrm.getRemaining() == 4 ) 273cdf0e10cSrcweir { 274cdf0e10cSrcweir sal_uInt16 nBaseKey, nHash; 275cdf0e10cSrcweir rStrm >> nBaseKey >> nHash; 276cdf0e10cSrcweir xDecoder.reset( new BiffDecoder_XOR( nBaseKey, nHash ) ); 277cdf0e10cSrcweir } 278cdf0e10cSrcweir return xDecoder; 279cdf0e10cSrcweir } 280cdf0e10cSrcweir 281cdf0e10cSrcweir BiffDecoderRef lclReadFilePass_RCF( BiffInputStream& rStrm ) 282cdf0e10cSrcweir { 283cdf0e10cSrcweir BiffDecoderRef xDecoder; 284cdf0e10cSrcweir OSL_ENSURE( rStrm.getRemaining() == 48, "lclReadFilePass_RCF - wrong record size" ); 285cdf0e10cSrcweir if( rStrm.getRemaining() == 48 ) 286cdf0e10cSrcweir { 287cdf0e10cSrcweir sal_uInt8 pnSalt[ 16 ]; 288cdf0e10cSrcweir sal_uInt8 pnVerifier[ 16 ]; 289cdf0e10cSrcweir sal_uInt8 pnVerifierHash[ 16 ]; 290cdf0e10cSrcweir rStrm.readMemory( pnSalt, 16 ); 291cdf0e10cSrcweir rStrm.readMemory( pnVerifier, 16 ); 292cdf0e10cSrcweir rStrm.readMemory( pnVerifierHash, 16 ); 293cdf0e10cSrcweir xDecoder.reset( new BiffDecoder_RCF( pnSalt, pnVerifier, pnVerifierHash ) ); 294cdf0e10cSrcweir } 295cdf0e10cSrcweir return xDecoder; 296cdf0e10cSrcweir } 297cdf0e10cSrcweir 298cdf0e10cSrcweir BiffDecoderRef lclReadFilePass_CryptoApi( BiffInputStream& /*rStrm*/ ) 299cdf0e10cSrcweir { 300cdf0e10cSrcweir // not supported 301cdf0e10cSrcweir return BiffDecoderRef(); 302cdf0e10cSrcweir } 303cdf0e10cSrcweir 304cdf0e10cSrcweir BiffDecoderRef lclReadFilePassBiff8( BiffInputStream& rStrm ) 305cdf0e10cSrcweir { 306cdf0e10cSrcweir BiffDecoderRef xDecoder; 307cdf0e10cSrcweir switch( rStrm.readuInt16() ) 308cdf0e10cSrcweir { 309cdf0e10cSrcweir case BIFF_FILEPASS_XOR: 310cdf0e10cSrcweir xDecoder = lclReadFilePass_XOR( rStrm ); 311cdf0e10cSrcweir break; 312cdf0e10cSrcweir 313cdf0e10cSrcweir case BIFF_FILEPASS_RCF: 314cdf0e10cSrcweir { 315cdf0e10cSrcweir sal_uInt16 nMajor = rStrm.readuInt16(); 316cdf0e10cSrcweir rStrm.skip( 2 ); 317cdf0e10cSrcweir switch( nMajor ) 318cdf0e10cSrcweir { 319cdf0e10cSrcweir case BIFF_FILEPASS_BIFF8_RCF: 320cdf0e10cSrcweir xDecoder = lclReadFilePass_RCF( rStrm ); 321cdf0e10cSrcweir break; 322cdf0e10cSrcweir case BIFF_FILEPASS_BIFF8_CRYPTOAPI_2003: 323cdf0e10cSrcweir case BIFF_FILEPASS_BIFF8_CRYPTOAPI_2007: 324cdf0e10cSrcweir xDecoder = lclReadFilePass_CryptoApi( rStrm ); 325cdf0e10cSrcweir break; 326cdf0e10cSrcweir default: 327cdf0e10cSrcweir OSL_ENSURE( false, "lclReadFilePassBiff8 - unknown BIFF8 encryption sub mode" ); 328cdf0e10cSrcweir } 329cdf0e10cSrcweir } 330cdf0e10cSrcweir break; 331cdf0e10cSrcweir 332cdf0e10cSrcweir default: 333cdf0e10cSrcweir OSL_ENSURE( false, "lclReadFilePassBiff8 - unknown encryption mode" ); 334cdf0e10cSrcweir } 335cdf0e10cSrcweir return xDecoder; 336cdf0e10cSrcweir } 337cdf0e10cSrcweir 338cdf0e10cSrcweir } // namespace 339cdf0e10cSrcweir 340cdf0e10cSrcweir // ---------------------------------------------------------------------------- 341cdf0e10cSrcweir 342cdf0e10cSrcweir BiffCodecHelper::BiffCodecHelper( const WorkbookHelper& rHelper ) : 343cdf0e10cSrcweir WorkbookHelper( rHelper ) 344cdf0e10cSrcweir { 345cdf0e10cSrcweir } 346cdf0e10cSrcweir 347cdf0e10cSrcweir /*static*/ BiffDecoderRef BiffCodecHelper::implReadFilePass( BiffInputStream& rStrm, BiffType eBiff ) 348cdf0e10cSrcweir { 349cdf0e10cSrcweir rStrm.enableDecoder( false ); 350cdf0e10cSrcweir BiffDecoderRef xDecoder = (eBiff == BIFF8) ? lclReadFilePassBiff8( rStrm ) : lclReadFilePass_XOR( rStrm ); 351cdf0e10cSrcweir rStrm.setDecoder( xDecoder ); 352cdf0e10cSrcweir return xDecoder; 353cdf0e10cSrcweir } 354cdf0e10cSrcweir 355cdf0e10cSrcweir bool BiffCodecHelper::importFilePass( BiffInputStream& rStrm ) 356cdf0e10cSrcweir { 357cdf0e10cSrcweir OSL_ENSURE( !mxDecoder, "BiffCodecHelper::importFilePass - multiple FILEPASS records" ); 358cdf0e10cSrcweir mxDecoder = implReadFilePass( rStrm, getBiff() ); 359cdf0e10cSrcweir // request and verify a password (decoder implements IDocPasswordVerifier) 360cdf0e10cSrcweir if( mxDecoder.get() ) 361cdf0e10cSrcweir getBaseFilter().requestEncryptionData( *mxDecoder ); 362cdf0e10cSrcweir // correct password is indicated by isValid() function of decoder 363cdf0e10cSrcweir return mxDecoder.get() && mxDecoder->isValid(); 364cdf0e10cSrcweir } 365cdf0e10cSrcweir 366cdf0e10cSrcweir void BiffCodecHelper::cloneDecoder( BiffInputStream& rStrm ) 367cdf0e10cSrcweir { 368cdf0e10cSrcweir if( mxDecoder.get() ) 369cdf0e10cSrcweir rStrm.setDecoder( BiffDecoderRef( mxDecoder->clone() ) ); 370cdf0e10cSrcweir } 371cdf0e10cSrcweir 372cdf0e10cSrcweir // ============================================================================ 373cdf0e10cSrcweir 374cdf0e10cSrcweir } // namespace xls 375cdf0e10cSrcweir } // namespace oox 376