merge the formfield patch from ooo-build
[ooovba.git] / oox / source / xls / biffcodec.cxx
bloba589b1b3218f1db34290f73e8e80277f47dcfc6b
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: biffcodec.cxx,v $
10 * $Revision: 1.4 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 #include "oox/xls/biffcodec.hxx"
32 #include <osl/thread.h>
33 #include <string.h>
34 #include "oox/core/filterbase.hxx"
35 #include "oox/xls/biffinputstream.hxx"
37 using ::rtl::OString;
38 using ::rtl::OUString;
39 using ::rtl::OStringToOUString;
40 using ::oox::core::FilterBase;
42 namespace oox {
43 namespace xls {
45 // ============================================================================
47 BiffDecoderBase::BiffDecoderBase() :
48 mbValid( false )
52 BiffDecoderBase::~BiffDecoderBase()
56 ::comphelper::DocPasswordVerifierResult BiffDecoderBase::verifyPassword( const OUString& rPassword )
58 mbValid = implVerify( rPassword );
59 return mbValid ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
62 void BiffDecoderBase::decode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes )
64 if( pnDestData && pnSrcData && (nBytes > 0) )
66 if( mbValid )
67 implDecode( pnDestData, pnSrcData, nStreamPos, nBytes );
68 else
69 memcpy( pnDestData, pnSrcData, nBytes );
73 // ============================================================================
75 BiffDecoder_XOR::BiffDecoder_XOR( sal_uInt16 nKey, sal_uInt16 nHash ) :
76 maCodec( ::oox::core::BinaryCodec_XOR::CODEC_EXCEL ),
77 maPassword( 16 ),
78 mnKey( nKey ),
79 mnHash( nHash )
83 BiffDecoder_XOR::BiffDecoder_XOR( const BiffDecoder_XOR& rDecoder ) :
84 BiffDecoderBase(), // must be called to prevent compiler warning
85 maCodec( ::oox::core::BinaryCodec_XOR::CODEC_EXCEL ),
86 maPassword( rDecoder.maPassword ),
87 mnKey( rDecoder.mnKey ),
88 mnHash( rDecoder.mnHash )
90 if( isValid() )
91 maCodec.initKey( &maPassword.front() );
94 BiffDecoder_XOR* BiffDecoder_XOR::implClone()
96 return new BiffDecoder_XOR( *this );
99 bool BiffDecoder_XOR::implVerify( const OUString& rPassword )
101 /* Convert password to a byte string. TODO: this needs some finetuning
102 according to the spec... */
103 OString aBytePassword = OUStringToOString( rPassword, osl_getThreadTextEncoding() );
104 sal_Int32 nLen = aBytePassword.getLength();
105 if( (0 < nLen) && (nLen < 16) )
107 // copy byte string to sal_uInt8 array
108 maPassword.clear();
109 maPassword.resize( 16, 0 );
110 memcpy( &maPassword.front(), aBytePassword.getStr(), static_cast< size_t >( nLen ) );
112 // init codec
113 maCodec.initKey( &maPassword.front() );
114 return maCodec.verifyKey( mnKey, mnHash );
116 return false;
119 void BiffDecoder_XOR::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes )
121 maCodec.startBlock();
122 maCodec.skip( static_cast< sal_Int32 >( (nStreamPos + nBytes) & 0x0F ) );
123 maCodec.decode( pnDestData, pnSrcData, nBytes );
126 // ============================================================================
128 namespace {
130 /** Returns the block index of the passed stream position for RCF decryption. */
131 sal_Int32 lclGetRcfBlock( sal_Int64 nStreamPos )
133 return static_cast< sal_Int32 >( nStreamPos / BIFF_RCF_BLOCKSIZE );
136 /** Returns the offset of the passed stream position in a block for RCF decryption. */
137 sal_Int32 lclGetRcfOffset( sal_Int64 nStreamPos )
139 return static_cast< sal_Int32 >( nStreamPos % BIFF_RCF_BLOCKSIZE );
142 } // namespace
144 // ----------------------------------------------------------------------------
146 BiffDecoder_RCF::BiffDecoder_RCF( sal_uInt8 pnSalt[ 16 ], sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] ) :
147 maPassword( 16, 0 ),
148 maSalt( pnSalt, pnSalt + 16 ),
149 maVerifier( pnVerifier, pnVerifier + 16 ),
150 maVerifierHash( pnVerifierHash, pnVerifierHash + 16 )
154 BiffDecoder_RCF::BiffDecoder_RCF( const BiffDecoder_RCF& rDecoder ) :
155 BiffDecoderBase(), // must be called to prevent compiler warning
156 maPassword( rDecoder.maPassword ),
157 maSalt( rDecoder.maSalt ),
158 maVerifier( rDecoder.maVerifier ),
159 maVerifierHash( rDecoder.maVerifierHash )
161 if( isValid() )
162 maCodec.initKey( &maPassword.front(), &maSalt.front() );
165 BiffDecoder_RCF* BiffDecoder_RCF::implClone()
167 return new BiffDecoder_RCF( *this );
170 bool BiffDecoder_RCF::implVerify( const OUString& rPassword )
172 sal_Int32 nLen = rPassword.getLength();
173 if( (0 < nLen) && (nLen < 16) )
175 // copy string to sal_uInt16 array
176 maPassword.clear();
177 maPassword.resize( 16, 0 );
178 const sal_Unicode* pcChar = rPassword.getStr();
179 const sal_Unicode* pcCharEnd = pcChar + nLen;
180 ::std::vector< sal_uInt16 >::iterator aIt = maPassword.begin();
181 for( ; pcChar < pcCharEnd; ++pcChar, ++aIt )
182 *aIt = static_cast< sal_uInt16 >( *pcChar );
184 // init codec
185 maCodec.initKey( &maPassword.front(), &maSalt.front() );
186 return maCodec.verifyKey( &maVerifier.front(), &maVerifierHash.front() );
188 return false;
191 void BiffDecoder_RCF::implDecode( sal_uInt8* pnDestData, const sal_uInt8* pnSrcData, sal_Int64 nStreamPos, sal_uInt16 nBytes )
193 sal_uInt8* pnCurrDest = pnDestData;
194 const sal_uInt8* pnCurrSrc = pnSrcData;
195 sal_Int64 nCurrPos = nStreamPos;
196 sal_uInt16 nBytesLeft = nBytes;
197 while( nBytesLeft > 0 )
199 // initialize codec for current stream position
200 maCodec.startBlock( lclGetRcfBlock( nCurrPos ) );
201 maCodec.skip( lclGetRcfOffset( nCurrPos ) );
203 // decode the block
204 sal_uInt16 nBlockLeft = static_cast< sal_uInt16 >( BIFF_RCF_BLOCKSIZE - lclGetRcfOffset( nCurrPos ) );
205 sal_uInt16 nDecBytes = ::std::min( nBytesLeft, nBlockLeft );
206 maCodec.decode( pnCurrDest, pnCurrSrc, static_cast< sal_Int32 >( nDecBytes ) );
208 // prepare for next block
209 pnCurrDest += nDecBytes;
210 pnCurrSrc += nDecBytes;
211 nCurrPos += nDecBytes;
212 nBytesLeft = nBytesLeft - nDecBytes;
216 // ============================================================================
218 namespace {
220 const sal_uInt16 BIFF_FILEPASS_XOR = 0;
221 const sal_uInt16 BIFF_FILEPASS_RCF = 1;
223 const sal_uInt16 BIFF_FILEPASS_BIFF8_RCF = 1;
224 const sal_uInt16 BIFF_FILEPASS_BIFF8_CRYPTOAPI_2003 = 2;
225 const sal_uInt16 BIFF_FILEPASS_BIFF8_CRYPTOAPI_2007 = 3;
227 // ----------------------------------------------------------------------------
229 BiffDecoderRef lclReadFilePass_XOR( BiffInputStream& rStrm )
231 BiffDecoderRef xDecoder;
232 OSL_ENSURE( rStrm.getRemaining() == 4, "lclReadFilePass_XOR - wrong record size" );
233 if( rStrm.getRemaining() == 4 )
235 sal_uInt16 nBaseKey, nHash;
236 rStrm >> nBaseKey >> nHash;
237 xDecoder.reset( new BiffDecoder_XOR( nBaseKey, nHash ) );
239 return xDecoder;
242 BiffDecoderRef lclReadFilePass_RCF( BiffInputStream& rStrm )
244 BiffDecoderRef xDecoder;
245 OSL_ENSURE( rStrm.getRemaining() == 48, "lclReadFilePass_RCF - wrong record size" );
246 if( rStrm.getRemaining() == 48 )
248 sal_uInt8 pnSalt[ 16 ];
249 sal_uInt8 pnVerifier[ 16 ];
250 sal_uInt8 pnVerifierHash[ 16 ];
251 rStrm.readMemory( pnSalt, 16 );
252 rStrm.readMemory( pnVerifier, 16 );
253 rStrm.readMemory( pnVerifierHash, 16 );
254 xDecoder.reset( new BiffDecoder_RCF( pnSalt, pnVerifier, pnVerifierHash ) );
256 return xDecoder;
259 BiffDecoderRef lclReadFilePass_CryptoApi( BiffInputStream& /*rStrm*/ )
261 // not supported
262 return BiffDecoderRef();
265 BiffDecoderRef lclReadFilePassBiff8( BiffInputStream& rStrm )
267 BiffDecoderRef xDecoder;
268 switch( rStrm.readuInt16() )
270 case BIFF_FILEPASS_XOR:
271 xDecoder = lclReadFilePass_XOR( rStrm );
272 break;
274 case BIFF_FILEPASS_RCF:
276 sal_uInt16 nMajor = rStrm.readuInt16();
277 rStrm.skip( 2 );
278 switch( nMajor )
280 case BIFF_FILEPASS_BIFF8_RCF:
281 xDecoder = lclReadFilePass_RCF( rStrm );
282 break;
283 case BIFF_FILEPASS_BIFF8_CRYPTOAPI_2003:
284 case BIFF_FILEPASS_BIFF8_CRYPTOAPI_2007:
285 xDecoder = lclReadFilePass_CryptoApi( rStrm );
286 break;
287 default:
288 OSL_ENSURE( false, "lclReadFilePassBiff8 - unknown BIFF8 encryption sub mode" );
291 break;
293 default:
294 OSL_ENSURE( false, "lclReadFilePassBiff8 - unknown encryption mode" );
296 return xDecoder;
299 } // namespace
301 // ----------------------------------------------------------------------------
303 BiffCodecHelper::BiffCodecHelper( const WorkbookHelper& rHelper ) :
304 WorkbookHelper( rHelper )
308 /*static*/ BiffDecoderRef BiffCodecHelper::implReadFilePass( BiffInputStream& rStrm, BiffType eBiff )
310 rStrm.enableDecoder( false );
311 BiffDecoderRef xDecoder = (eBiff == BIFF8) ? lclReadFilePassBiff8( rStrm ) : lclReadFilePass_XOR( rStrm );
312 rStrm.setDecoder( xDecoder );
313 return xDecoder;
316 bool BiffCodecHelper::importFilePass( BiffInputStream& rStrm )
318 OSL_ENSURE( !mxDecoder, "BiffCodecHelper::importFilePass - multiple FILEPASS records" );
319 mxDecoder = implReadFilePass( rStrm, getBiff() );
320 // request and verify a password (decoder implements IDocPasswordVerifier)
321 if( mxDecoder.get() )
322 getBaseFilter().requestPassword( *mxDecoder );
323 // correct password is indicated by isValid() function of decoder
324 return mxDecoder.get() && mxDecoder->isValid();
327 void BiffCodecHelper::cloneDecoder( BiffInputStream& rStrm )
329 if( mxDecoder.get() )
330 rStrm.setDecoder( BiffDecoderRef( mxDecoder->clone() ) );
333 // ============================================================================
335 } // namespace xls
336 } // namespace oox