Line data Source code
1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /*
3 : * This file is part of the LibreOffice project.
4 : *
5 : * This Source Code Form is subject to the terms of the Mozilla Public
6 : * License, v. 2.0. If a copy of the MPL was not distributed with this
7 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 : *
9 : * This file incorporates work covered by the following license notice:
10 : *
11 : * Licensed to the Apache Software Foundation (ASF) under one or more
12 : * contributor license agreements. See the NOTICE file distributed
13 : * with this work for additional information regarding copyright
14 : * ownership. The ASF licenses this file to you under the Apache
15 : * License, Version 2.0 (the "License"); you may not use this file
16 : * except in compliance with the License. You may obtain a copy of
17 : * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 : */
19 :
20 : #include <comphelper/docpasswordhelper.hxx>
21 : #include <comphelper/sequenceashashmap.hxx>
22 : #include <osl/thread.h>
23 : #include <osl/diagnose.h>
24 : #include "xistream.hxx"
25 : #include "xlstring.hxx"
26 : #include "xiroot.hxx"
27 :
28 : #include <vector>
29 : #include <boost/scoped_array.hpp>
30 :
31 : using namespace ::com::sun::star;
32 :
33 : // Decryption
34 0 : XclImpDecrypter::XclImpDecrypter() :
35 : mnError( EXC_ENCR_ERROR_UNSUPP_CRYPT ),
36 : mnOldPos( STREAM_SEEK_TO_END ),
37 0 : mnRecSize( 0 )
38 : {
39 0 : }
40 :
41 0 : XclImpDecrypter::XclImpDecrypter( const XclImpDecrypter& rSrc ) :
42 : ::comphelper::IDocPasswordVerifier(),
43 : mnError( rSrc.mnError ),
44 : mnOldPos( STREAM_SEEK_TO_END ),
45 0 : mnRecSize( 0 )
46 : {
47 0 : }
48 :
49 0 : XclImpDecrypter::~XclImpDecrypter()
50 : {
51 0 : }
52 :
53 0 : XclImpDecrypterRef XclImpDecrypter::Clone() const
54 : {
55 0 : XclImpDecrypterRef xNewDecr;
56 0 : if( IsValid() )
57 0 : xNewDecr.reset( OnClone() );
58 0 : return xNewDecr;
59 : }
60 :
61 0 : ::comphelper::DocPasswordVerifierResult XclImpDecrypter::verifyPassword( const OUString& rPassword, uno::Sequence< beans::NamedValue >& o_rEncryptionData )
62 : {
63 0 : o_rEncryptionData = OnVerifyPassword( rPassword );
64 0 : mnError = o_rEncryptionData.getLength() ? ERRCODE_NONE : ERRCODE_ABORT;
65 0 : return o_rEncryptionData.getLength() ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
66 : }
67 :
68 0 : ::comphelper::DocPasswordVerifierResult XclImpDecrypter::verifyEncryptionData( const uno::Sequence< beans::NamedValue >& rEncryptionData )
69 : {
70 0 : bool bValid = OnVerifyEncryptionData( rEncryptionData );
71 0 : mnError = bValid ? ERRCODE_NONE : ERRCODE_ABORT;
72 0 : return bValid ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
73 : }
74 :
75 0 : void XclImpDecrypter::Update( SvStream& rStrm, sal_uInt16 nRecSize )
76 : {
77 0 : if( IsValid() )
78 : {
79 0 : sal_uInt64 const nNewPos = rStrm.Tell();
80 0 : if( (mnOldPos != nNewPos) || (mnRecSize != nRecSize) )
81 : {
82 0 : OnUpdate( mnOldPos, nNewPos, nRecSize );
83 0 : mnOldPos = nNewPos;
84 0 : mnRecSize = nRecSize;
85 : }
86 : }
87 0 : }
88 :
89 0 : sal_uInt16 XclImpDecrypter::Read( SvStream& rStrm, void* pData, sal_uInt16 nBytes )
90 : {
91 0 : sal_uInt16 nRet = 0;
92 0 : if( pData && nBytes )
93 : {
94 0 : if( IsValid() )
95 : {
96 0 : Update( rStrm, mnRecSize );
97 0 : nRet = OnRead( rStrm, static_cast< sal_uInt8* >( pData ), nBytes );
98 0 : mnOldPos = rStrm.Tell();
99 : }
100 : else
101 0 : nRet = static_cast< sal_uInt16 >( rStrm.Read( pData, nBytes ) );
102 : }
103 0 : return nRet;
104 : }
105 :
106 0 : XclImpBiff5Decrypter::XclImpBiff5Decrypter( sal_uInt16 nKey, sal_uInt16 nHash ) :
107 : mnKey( nKey ),
108 0 : mnHash( nHash )
109 : {
110 0 : }
111 :
112 0 : XclImpBiff5Decrypter::XclImpBiff5Decrypter( const XclImpBiff5Decrypter& rSrc ) :
113 : XclImpDecrypter( rSrc ),
114 : maEncryptionData( rSrc.maEncryptionData ),
115 : mnKey( rSrc.mnKey ),
116 0 : mnHash( rSrc.mnHash )
117 : {
118 0 : if( IsValid() )
119 0 : maCodec.InitCodec( maEncryptionData );
120 0 : }
121 :
122 0 : XclImpBiff5Decrypter* XclImpBiff5Decrypter::OnClone() const
123 : {
124 0 : return new XclImpBiff5Decrypter( *this );
125 : }
126 :
127 0 : uno::Sequence< beans::NamedValue > XclImpBiff5Decrypter::OnVerifyPassword( const OUString& rPassword )
128 : {
129 0 : maEncryptionData.realloc( 0 );
130 :
131 : /* Convert password to a byte string. TODO: this needs some finetuning
132 : according to the spec... */
133 0 : OString aBytePassword = OUStringToOString( rPassword, osl_getThreadTextEncoding() );
134 0 : sal_Int32 nLen = aBytePassword.getLength();
135 0 : if( (0 < nLen) && (nLen < 16) )
136 : {
137 : // init codec
138 0 : maCodec.InitKey( reinterpret_cast<sal_uInt8 const *>(aBytePassword.getStr()) );
139 :
140 0 : if ( maCodec.VerifyKey( mnKey, mnHash ) )
141 : {
142 0 : maEncryptionData = maCodec.GetEncryptionData();
143 :
144 : // since the export uses Std97 encryption always we have to request it here
145 0 : ::std::vector< sal_uInt16 > aPassVect( 16 );
146 0 : ::std::vector< sal_uInt16 >::iterator aIt = aPassVect.begin();
147 0 : for( sal_Int32 nInd = 0; nInd < nLen; ++nInd, ++aIt )
148 0 : *aIt = static_cast< sal_uInt16 >( rPassword[nInd] );
149 :
150 0 : uno::Sequence< sal_Int8 > aDocId = ::comphelper::DocPasswordHelper::GenerateRandomByteSequence( 16 );
151 : OSL_ENSURE( aDocId.getLength() == 16, "Unexpected length of the senquence!" );
152 :
153 0 : ::msfilter::MSCodec_Std97 aCodec97;
154 0 : aCodec97.InitKey( &aPassVect.front(), reinterpret_cast<sal_uInt8 const *>(aDocId.getConstArray()) );
155 :
156 : // merge the EncryptionData, there should be no conflicts
157 0 : ::comphelper::SequenceAsHashMap aEncryptionHash( maEncryptionData );
158 0 : aEncryptionHash.update( ::comphelper::SequenceAsHashMap( aCodec97.GetEncryptionData() ) );
159 0 : aEncryptionHash >> maEncryptionData;
160 : }
161 : }
162 :
163 0 : return maEncryptionData;
164 : }
165 :
166 0 : bool XclImpBiff5Decrypter::OnVerifyEncryptionData( const uno::Sequence< beans::NamedValue >& rEncryptionData )
167 : {
168 0 : maEncryptionData.realloc( 0 );
169 :
170 0 : if( rEncryptionData.getLength() )
171 : {
172 : // init codec
173 0 : maCodec.InitCodec( rEncryptionData );
174 :
175 0 : if ( maCodec.VerifyKey( mnKey, mnHash ) )
176 0 : maEncryptionData = rEncryptionData;
177 : }
178 :
179 0 : return maEncryptionData.getLength();
180 : }
181 :
182 0 : void XclImpBiff5Decrypter::OnUpdate( sal_Size /*nOldStrmPos*/, sal_Size nNewStrmPos, sal_uInt16 nRecSize )
183 : {
184 0 : maCodec.InitCipher();
185 0 : maCodec.Skip( (nNewStrmPos + nRecSize) & 0x0F );
186 0 : }
187 :
188 0 : sal_uInt16 XclImpBiff5Decrypter::OnRead( SvStream& rStrm, sal_uInt8* pnData, sal_uInt16 nBytes )
189 : {
190 0 : sal_uInt16 nRet = static_cast< sal_uInt16 >( rStrm.Read( pnData, nBytes ) );
191 0 : maCodec.Decode( pnData, nRet );
192 0 : return nRet;
193 : }
194 :
195 0 : XclImpBiff8Decrypter::XclImpBiff8Decrypter( sal_uInt8 pnSalt[ 16 ],
196 : sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] ) :
197 : maSalt( pnSalt, pnSalt + 16 ),
198 : maVerifier( pnVerifier, pnVerifier + 16 ),
199 0 : maVerifierHash( pnVerifierHash, pnVerifierHash + 16 )
200 : {
201 0 : }
202 :
203 0 : XclImpBiff8Decrypter::XclImpBiff8Decrypter( const XclImpBiff8Decrypter& rSrc ) :
204 : XclImpDecrypter( rSrc ),
205 : maEncryptionData( rSrc.maEncryptionData ),
206 : maSalt( rSrc.maSalt ),
207 : maVerifier( rSrc.maVerifier ),
208 0 : maVerifierHash( rSrc.maVerifierHash )
209 : {
210 0 : if( IsValid() )
211 0 : maCodec.InitCodec( maEncryptionData );
212 0 : }
213 :
214 0 : XclImpBiff8Decrypter* XclImpBiff8Decrypter::OnClone() const
215 : {
216 0 : return new XclImpBiff8Decrypter( *this );
217 : }
218 :
219 0 : uno::Sequence< beans::NamedValue > XclImpBiff8Decrypter::OnVerifyPassword( const OUString& rPassword )
220 : {
221 0 : maEncryptionData.realloc( 0 );
222 :
223 0 : sal_Int32 nLen = rPassword.getLength();
224 0 : if( (0 < nLen) && (nLen < 16) )
225 : {
226 : // copy string to sal_uInt16 array
227 0 : ::std::vector< sal_uInt16 > aPassVect( 16 );
228 0 : const sal_Unicode* pcChar = rPassword.getStr();
229 0 : const sal_Unicode* pcCharEnd = pcChar + nLen;
230 0 : ::std::vector< sal_uInt16 >::iterator aIt = aPassVect.begin();
231 0 : for( ; pcChar < pcCharEnd; ++pcChar, ++aIt )
232 0 : *aIt = static_cast< sal_uInt16 >( *pcChar );
233 :
234 : // init codec
235 0 : maCodec.InitKey( &aPassVect.front(), &maSalt.front() );
236 0 : if ( maCodec.VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) )
237 0 : maEncryptionData = maCodec.GetEncryptionData();
238 : }
239 :
240 0 : return maEncryptionData;
241 : }
242 :
243 0 : bool XclImpBiff8Decrypter::OnVerifyEncryptionData( const uno::Sequence< beans::NamedValue >& rEncryptionData )
244 : {
245 0 : maEncryptionData.realloc( 0 );
246 :
247 0 : if( rEncryptionData.getLength() )
248 : {
249 : // init codec
250 0 : maCodec.InitCodec( rEncryptionData );
251 :
252 0 : if ( maCodec.VerifyKey( &maVerifier.front(), &maVerifierHash.front() ) )
253 0 : maEncryptionData = rEncryptionData;
254 : }
255 :
256 0 : return maEncryptionData.getLength();
257 : }
258 :
259 0 : void XclImpBiff8Decrypter::OnUpdate( sal_Size nOldStrmPos, sal_Size nNewStrmPos, sal_uInt16 /*nRecSize*/ )
260 : {
261 0 : if( nNewStrmPos != nOldStrmPos )
262 : {
263 0 : sal_uInt32 nOldBlock = GetBlock( nOldStrmPos );
264 0 : sal_uInt16 nOldOffset = GetOffset( nOldStrmPos );
265 :
266 0 : sal_uInt32 nNewBlock = GetBlock( nNewStrmPos );
267 0 : sal_uInt16 nNewOffset = GetOffset( nNewStrmPos );
268 :
269 : /* Rekey cipher, if block changed or if previous offset in same block. */
270 0 : if( (nNewBlock != nOldBlock) || (nNewOffset < nOldOffset) )
271 : {
272 0 : maCodec.InitCipher( nNewBlock );
273 0 : nOldOffset = 0; // reset nOldOffset for next if() statement
274 : }
275 :
276 : /* Seek to correct offset. */
277 0 : if( nNewOffset > nOldOffset )
278 0 : maCodec.Skip( nNewOffset - nOldOffset );
279 : }
280 0 : }
281 :
282 0 : sal_uInt16 XclImpBiff8Decrypter::OnRead( SvStream& rStrm, sal_uInt8* pnData, sal_uInt16 nBytes )
283 : {
284 0 : sal_uInt16 nRet = 0;
285 :
286 0 : sal_uInt8* pnCurrData = pnData;
287 0 : sal_uInt16 nBytesLeft = nBytes;
288 0 : while( nBytesLeft )
289 : {
290 0 : sal_uInt16 nBlockLeft = EXC_ENCR_BLOCKSIZE - GetOffset( rStrm.Tell() );
291 0 : sal_uInt16 nDecBytes = ::std::min< sal_uInt16 >( nBytesLeft, nBlockLeft );
292 :
293 : // read the block from stream
294 0 : nRet = nRet + static_cast< sal_uInt16 >( rStrm.Read( pnCurrData, nDecBytes ) );
295 : // decode the block inplace
296 0 : maCodec.Decode( pnCurrData, nDecBytes, pnCurrData, nDecBytes );
297 0 : if( GetOffset( rStrm.Tell() ) == 0 )
298 0 : maCodec.InitCipher( GetBlock( rStrm.Tell() ) );
299 :
300 0 : pnCurrData += nDecBytes;
301 0 : nBytesLeft = nBytesLeft - nDecBytes;
302 : }
303 :
304 0 : return nRet;
305 : }
306 :
307 0 : sal_uInt32 XclImpBiff8Decrypter::GetBlock( sal_Size nStrmPos )
308 : {
309 0 : return static_cast< sal_uInt32 >( nStrmPos / EXC_ENCR_BLOCKSIZE );
310 : }
311 :
312 0 : sal_uInt16 XclImpBiff8Decrypter::GetOffset( sal_Size nStrmPos )
313 : {
314 0 : return static_cast< sal_uInt16 >( nStrmPos % EXC_ENCR_BLOCKSIZE );
315 : }
316 :
317 : // Stream
318 11580 : XclImpStreamPos::XclImpStreamPos() :
319 : mnPos( STREAM_SEEK_TO_BEGIN ),
320 : mnNextPos( STREAM_SEEK_TO_BEGIN ),
321 : mnCurrSize( 0 ),
322 : mnRawRecId( EXC_ID_UNKNOWN ),
323 : mnRawRecSize( 0 ),
324 : mnRawRecLeft( 0 ),
325 11580 : mbValid( false )
326 : {
327 11580 : }
328 :
329 1187030 : void XclImpStreamPos::Set(
330 : const SvStream& rStrm, sal_Size nNextPos, sal_Size nCurrSize,
331 : sal_uInt16 nRawRecId, sal_uInt16 nRawRecSize, sal_uInt16 nRawRecLeft,
332 : bool bValid )
333 : {
334 1187030 : mnPos = rStrm.Tell();
335 1187030 : mnNextPos = nNextPos;
336 1187030 : mnCurrSize = nCurrSize;
337 1187030 : mnRawRecId = nRawRecId;
338 1187030 : mnRawRecSize = nRawRecSize;
339 1187030 : mnRawRecLeft = nRawRecLeft;
340 1187030 : mbValid = bValid;
341 1187030 : }
342 :
343 12493 : void XclImpStreamPos::Get(
344 : SvStream& rStrm, sal_Size& rnNextPos, sal_Size& rnCurrSize,
345 : sal_uInt16& rnRawRecId, sal_uInt16& rnRawRecSize, sal_uInt16& rnRawRecLeft,
346 : bool& rbValid ) const
347 : {
348 12493 : rStrm.Seek( mnPos );
349 12493 : rnNextPos = mnNextPos;
350 12493 : rnCurrSize = mnCurrSize;
351 12493 : rnRawRecId = mnRawRecId;
352 12493 : rnRawRecSize = mnRawRecSize;
353 12493 : rnRawRecLeft = mnRawRecLeft;
354 12493 : rbValid = mbValid;
355 12493 : }
356 :
357 85 : XclBiff XclImpStream::DetectBiffVersion( SvStream& rStrm )
358 : {
359 85 : XclBiff eBiff = EXC_BIFF_UNKNOWN;
360 :
361 85 : rStrm.Seek( STREAM_SEEK_TO_BEGIN );
362 : sal_uInt16 nBofId, nBofSize;
363 85 : rStrm.ReadUInt16( nBofId ).ReadUInt16( nBofSize );
364 :
365 85 : if( (4 <= nBofSize) && (nBofSize <= 16) ) switch( nBofId )
366 : {
367 : case EXC_ID2_BOF:
368 0 : eBiff = EXC_BIFF2;
369 0 : break;
370 : case EXC_ID3_BOF:
371 0 : eBiff = EXC_BIFF3;
372 0 : break;
373 : case EXC_ID4_BOF:
374 0 : eBiff = EXC_BIFF4;
375 0 : break;
376 : case EXC_ID5_BOF:
377 : {
378 : sal_uInt16 nVersion;
379 84 : rStrm.ReadUInt16( nVersion );
380 : // #i23425# #i44031# #i62752# there are some *really* broken documents out there...
381 84 : switch( nVersion & 0xFF00 )
382 : {
383 0 : case 0: eBiff = EXC_BIFF5; break; // #i44031# #i62752#
384 0 : case EXC_BOF_BIFF2: eBiff = EXC_BIFF2; break;
385 0 : case EXC_BOF_BIFF3: eBiff = EXC_BIFF3; break;
386 0 : case EXC_BOF_BIFF4: eBiff = EXC_BIFF4; break;
387 3 : case EXC_BOF_BIFF5: eBiff = EXC_BIFF5; break;
388 81 : case EXC_BOF_BIFF8: eBiff = EXC_BIFF8; break;
389 : default: OSL_TRACE( "XclImpStream::DetectBiffVersion - unknown BIFF version: 0x%04hX", nVersion );
390 : }
391 : }
392 84 : break;
393 : }
394 85 : return eBiff;
395 : }
396 :
397 193 : XclImpStream::XclImpStream( SvStream& rInStrm, const XclImpRoot& rRoot, bool bContLookup ) :
398 : mrStrm( rInStrm ),
399 : mrRoot( rRoot ),
400 : mnGlobRecId( EXC_ID_UNKNOWN ),
401 : mbGlobValidRec( false ),
402 : mbHasGlobPos( false ),
403 : mnNextRecPos( STREAM_SEEK_TO_BEGIN ),
404 : mnCurrRecSize( 0 ),
405 : mnComplRecSize( 0 ),
406 : mbHasComplRec( false ),
407 : mnRecId( EXC_ID_UNKNOWN ),
408 : mnAltContId( EXC_ID_UNKNOWN ),
409 : mnRawRecId( EXC_ID_UNKNOWN ),
410 : mnRawRecSize( 0 ),
411 : mnRawRecLeft( 0 ),
412 : mcNulSubst( '?' ),
413 : mbCont( bContLookup ),
414 : mbUseDecr( false ),
415 : mbValidRec( false ),
416 193 : mbValid( false )
417 : {
418 193 : mrStrm.Seek( STREAM_SEEK_TO_END );
419 193 : mnStreamSize = mrStrm.Tell();
420 193 : mrStrm.Seek( STREAM_SEEK_TO_BEGIN );
421 193 : }
422 :
423 193 : XclImpStream::~XclImpStream()
424 : {
425 193 : }
426 :
427 1175529 : bool XclImpStream::StartNextRecord()
428 : {
429 1175529 : maPosStack.clear();
430 :
431 : /* #i4266# Counter to ignore zero records (id==len==0) (i.e. the application
432 : "Crystal Report" writes zero records between other records) */
433 1175529 : sal_Size nZeroRecCount = 5;
434 1175529 : bool bIsZeroRec = false;
435 :
436 1175663 : do
437 : {
438 1175663 : mbValidRec = ReadNextRawRecHeader();
439 1175663 : bIsZeroRec = (mnRawRecId == 0) && (mnRawRecSize == 0);
440 1175663 : if( bIsZeroRec ) --nZeroRecCount;
441 1175663 : mnNextRecPos = mrStrm.Tell() + mnRawRecSize;
442 : }
443 1175663 : while( mbValidRec && ((mbCont && IsContinueId( mnRawRecId )) || (bIsZeroRec && nZeroRecCount)) );
444 :
445 1175529 : mbValidRec = mbValidRec && !bIsZeroRec;
446 1175529 : mbValid = mbValidRec;
447 1175529 : SetupRecord();
448 :
449 1175529 : return mbValidRec;
450 : }
451 :
452 224 : bool XclImpStream::StartNextRecord( sal_Size nNextRecPos )
453 : {
454 224 : mnNextRecPos = nNextRecPos;
455 224 : return StartNextRecord();
456 : }
457 :
458 551 : void XclImpStream::ResetRecord( bool bContLookup, sal_uInt16 nAltContId )
459 : {
460 551 : if( mbValidRec )
461 : {
462 551 : maPosStack.clear();
463 551 : RestorePosition( maFirstRec );
464 551 : mnCurrRecSize = mnComplRecSize = mnRawRecSize;
465 551 : mbHasComplRec = !bContLookup;
466 551 : mbCont = bContLookup;
467 551 : mnAltContId = nAltContId;
468 551 : EnableDecryption();
469 : }
470 551 : }
471 :
472 0 : void XclImpStream::RewindRecord()
473 : {
474 0 : mnNextRecPos = maFirstRec.GetPos();
475 0 : mbValid = mbValidRec = false;
476 0 : }
477 :
478 4 : void XclImpStream::SetDecrypter( XclImpDecrypterRef xDecrypter )
479 : {
480 4 : mxDecrypter = xDecrypter;
481 4 : EnableDecryption();
482 4 : SetupDecrypter();
483 4 : }
484 :
485 4 : void XclImpStream::CopyDecrypterFrom( const XclImpStream& rStrm )
486 : {
487 4 : XclImpDecrypterRef xNewDecr;
488 4 : if( rStrm.mxDecrypter )
489 0 : xNewDecr = rStrm.mxDecrypter->Clone();
490 4 : SetDecrypter( xNewDecr );
491 4 : }
492 :
493 1176436 : bool XclImpStream::HasValidDecrypter() const
494 : {
495 1176436 : return mxDecrypter && mxDecrypter->IsValid();
496 : }
497 :
498 1176976 : void XclImpStream::EnableDecryption( bool bEnable )
499 : {
500 1176976 : mbUseDecr = bEnable && HasValidDecrypter();
501 1176976 : }
502 :
503 10930 : void XclImpStream::PushPosition()
504 : {
505 10930 : maPosStack.push_back( XclImpStreamPos() );
506 10930 : StorePosition( maPosStack.back() );
507 10930 : }
508 :
509 10930 : void XclImpStream::PopPosition()
510 : {
511 : OSL_ENSURE( !maPosStack.empty(), "XclImpStream::PopPosition - stack empty" );
512 10930 : if( !maPosStack.empty() )
513 : {
514 10930 : RestorePosition( maPosStack.back() );
515 10930 : maPosStack.pop_back();
516 : }
517 10930 : }
518 :
519 307 : void XclImpStream::StoreGlobalPosition()
520 : {
521 307 : StorePosition( maGlobPos );
522 307 : mnGlobRecId = mnRecId;
523 307 : mbGlobValidRec = mbValidRec;
524 307 : mbHasGlobPos = true;
525 307 : }
526 :
527 307 : void XclImpStream::SeekGlobalPosition()
528 : {
529 : OSL_ENSURE( mbHasGlobPos, "XclImpStream::SeekGlobalPosition - no position stored" );
530 307 : if( mbHasGlobPos )
531 : {
532 307 : RestorePosition( maGlobPos );
533 307 : mnRecId = mnGlobRecId;
534 307 : mnComplRecSize = mnCurrRecSize;
535 307 : mbHasComplRec = !mbCont;
536 307 : mbValidRec = mbGlobValidRec;
537 : }
538 307 : }
539 :
540 95066 : sal_Size XclImpStream::GetRecPos() const
541 : {
542 95066 : return mbValid ? (mnCurrRecSize - mnRawRecLeft) : EXC_REC_SEEK_TO_END;
543 : }
544 :
545 61531 : sal_Size XclImpStream::GetRecSize()
546 : {
547 61531 : if( !mbHasComplRec )
548 : {
549 6031 : PushPosition();
550 6031 : while( JumpToNextContinue() ) ; // JumpToNextContinue() adds up mnCurrRecSize
551 6031 : mnComplRecSize = mnCurrRecSize;
552 6031 : mbHasComplRec = true;
553 6031 : PopPosition();
554 : }
555 61531 : return mnComplRecSize;
556 : }
557 :
558 61122 : sal_Size XclImpStream::GetRecLeft()
559 : {
560 61122 : return mbValid ? (GetRecSize() - GetRecPos()) : 0;
561 : }
562 :
563 2838 : sal_uInt16 XclImpStream::GetNextRecId()
564 : {
565 2838 : sal_uInt16 nRecId = EXC_ID_UNKNOWN;
566 2838 : if( mbValidRec )
567 : {
568 2838 : PushPosition();
569 2838 : while( JumpToNextContinue() ) ; // skip following CONTINUE records
570 2838 : if( mnNextRecPos < mnStreamSize )
571 : {
572 2838 : mrStrm.Seek( mnNextRecPos );
573 2838 : mrStrm.ReadUInt16( nRecId );
574 : }
575 2838 : PopPosition();
576 : }
577 2838 : return nRecId;
578 : }
579 :
580 218 : sal_uInt16 XclImpStream::PeekRecId( sal_Size nPos )
581 : {
582 218 : sal_uInt16 nRecId = EXC_ID_UNKNOWN;
583 218 : if (mbValidRec && nPos < mnStreamSize)
584 : {
585 218 : sal_Size nCurPos = mrStrm.Tell();
586 218 : mrStrm.Seek(nPos);
587 218 : mrStrm.ReadUInt16( nRecId );
588 218 : mrStrm.Seek(nCurPos);
589 : }
590 218 : return nRecId;
591 : }
592 :
593 107433 : sal_uInt8 XclImpStream::ReaduInt8()
594 : {
595 107433 : sal_uInt8 nValue = 0;
596 107433 : if( EnsureRawReadSize( 1 ) )
597 : {
598 107433 : if( mbUseDecr )
599 0 : mxDecrypter->Read( mrStrm, &nValue, 1 );
600 : else
601 107433 : mrStrm.ReadUChar( nValue );
602 107433 : --mnRawRecLeft;
603 : }
604 107433 : return nValue;
605 : }
606 :
607 1364 : sal_Int16 XclImpStream::ReadInt16()
608 : {
609 1364 : sal_Int16 nValue = 0;
610 1364 : if( EnsureRawReadSize( 2 ) )
611 : {
612 1364 : if( mbUseDecr )
613 : {
614 : SVBT16 pnBuffer;
615 0 : mxDecrypter->Read( mrStrm, pnBuffer, 2 );
616 0 : nValue = static_cast< sal_Int16 >( SVBT16ToShort( pnBuffer ) );
617 : }
618 : else
619 1364 : mrStrm.ReadInt16( nValue );
620 1364 : mnRawRecLeft -= 2;
621 : }
622 1364 : return nValue;
623 : }
624 :
625 2101141 : sal_uInt16 XclImpStream::ReaduInt16()
626 : {
627 2101141 : sal_uInt16 nValue = 0;
628 2101141 : if( EnsureRawReadSize( 2 ) )
629 : {
630 2101141 : if( mbUseDecr )
631 : {
632 : SVBT16 pnBuffer;
633 0 : mxDecrypter->Read( mrStrm, pnBuffer, 2 );
634 0 : nValue = SVBT16ToShort( pnBuffer );
635 : }
636 : else
637 2101141 : mrStrm.ReadUInt16( nValue );
638 2101141 : mnRawRecLeft -= 2;
639 : }
640 2101141 : return nValue;
641 : }
642 :
643 16360 : sal_Int32 XclImpStream::ReadInt32()
644 : {
645 16360 : sal_Int32 nValue = 0;
646 16360 : if( EnsureRawReadSize( 4 ) )
647 : {
648 16360 : if( mbUseDecr )
649 : {
650 : SVBT32 pnBuffer;
651 0 : mxDecrypter->Read( mrStrm, pnBuffer, 4 );
652 0 : nValue = static_cast< sal_Int32 >( SVBT32ToUInt32( pnBuffer ) );
653 : }
654 : else
655 16360 : mrStrm.ReadInt32( nValue );
656 16360 : mnRawRecLeft -= 4;
657 : }
658 16360 : return nValue;
659 : }
660 :
661 85519 : sal_uInt32 XclImpStream::ReaduInt32()
662 : {
663 85519 : sal_uInt32 nValue = 0;
664 85519 : if( EnsureRawReadSize( 4 ) )
665 : {
666 85519 : if( mbUseDecr )
667 : {
668 : SVBT32 pnBuffer;
669 0 : mxDecrypter->Read( mrStrm, pnBuffer, 4 );
670 0 : nValue = SVBT32ToUInt32( pnBuffer );
671 : }
672 : else
673 85519 : mrStrm.ReadUInt32( nValue );
674 85519 : mnRawRecLeft -= 4;
675 : }
676 85519 : return nValue;
677 : }
678 :
679 7433 : double XclImpStream::ReadDouble()
680 : {
681 7433 : double nValue = 0;
682 7433 : if( EnsureRawReadSize( 8 ) )
683 : {
684 7433 : if( mbUseDecr )
685 : {
686 : SVBT64 pnBuffer;
687 0 : mxDecrypter->Read( mrStrm, pnBuffer, 8 );
688 0 : nValue = SVBT64ToDouble( pnBuffer );
689 : }
690 : else
691 7433 : mrStrm.ReadDouble( nValue );
692 7433 : mnRawRecLeft -= 8;
693 : }
694 7433 : return nValue;
695 : }
696 :
697 607 : sal_Size XclImpStream::Read( void* pData, sal_Size nBytes )
698 : {
699 607 : sal_Size nRet = 0;
700 607 : if( mbValid && pData && (nBytes > 0) )
701 : {
702 607 : sal_uInt8* pnBuffer = static_cast< sal_uInt8* >( pData );
703 607 : sal_Size nBytesLeft = nBytes;
704 :
705 1862 : while( mbValid && (nBytesLeft > 0) )
706 : {
707 648 : sal_uInt16 nReadSize = GetMaxRawReadSize( nBytesLeft );
708 648 : sal_uInt16 nReadRet = ReadRawData( pnBuffer, nReadSize );
709 648 : nRet += nReadRet;
710 648 : mbValid = (nReadSize == nReadRet);
711 : OSL_ENSURE( mbValid, "XclImpStream::Read - stream read error" );
712 648 : pnBuffer += nReadRet;
713 648 : nBytesLeft -= nReadRet;
714 648 : if( mbValid && (nBytesLeft > 0) )
715 41 : JumpToNextContinue();
716 : OSL_ENSURE( mbValid, "XclImpStream::Read - record overread" );
717 : }
718 : }
719 607 : return nRet;
720 : }
721 :
722 401 : sal_Size XclImpStream::CopyToStream( SvStream& rOutStrm, sal_Size nBytes )
723 : {
724 401 : sal_Size nRet = 0;
725 401 : if( mbValid && (nBytes > 0) )
726 : {
727 401 : const sal_Size nMaxBuffer = 4096;
728 401 : boost::scoped_array<sal_uInt8> pnBuffer(new sal_uInt8[ ::std::min( nBytes, nMaxBuffer ) ]);
729 401 : sal_Size nBytesLeft = nBytes;
730 :
731 1288 : while( mbValid && (nBytesLeft > 0) )
732 : {
733 486 : sal_Size nReadSize = ::std::min( nBytesLeft, nMaxBuffer );
734 486 : nRet += Read( pnBuffer.get(), nReadSize );
735 : // writing more bytes than read results in invalid memory access
736 : SAL_WARN_IF(nRet != nReadSize, "sc", "read less bytes than requested");
737 486 : rOutStrm.Write( pnBuffer.get(), nReadSize );
738 486 : nBytesLeft -= nReadSize;
739 401 : }
740 : }
741 401 : return nRet;
742 : }
743 :
744 304 : sal_Size XclImpStream::CopyRecordToStream( SvStream& rOutStrm )
745 : {
746 304 : sal_Size nRet = 0;
747 304 : if( mbValidRec )
748 : {
749 304 : PushPosition();
750 304 : RestorePosition( maFirstRec );
751 304 : nRet = CopyToStream( rOutStrm, GetRecSize() );
752 304 : PopPosition();
753 : }
754 304 : return nRet;
755 : }
756 :
757 3292 : void XclImpStream::Seek( sal_Size nPos )
758 : {
759 3292 : if( mbValidRec )
760 : {
761 3292 : sal_Size nCurrPos = GetRecPos();
762 3292 : if( !mbValid || (nPos < nCurrPos) ) // from invalid state or backward
763 : {
764 137 : RestorePosition( maFirstRec );
765 137 : Ignore( nPos );
766 : }
767 3155 : else if( nPos > nCurrPos ) // forward
768 : {
769 59 : Ignore( nPos - nCurrPos );
770 : }
771 : }
772 3292 : }
773 :
774 553026 : void XclImpStream::Ignore( sal_Size nBytes )
775 : {
776 : // implementation similar to Read(), but without really reading anything
777 553026 : sal_Size nBytesLeft = nBytes;
778 1650950 : while( mbValid && (nBytesLeft > 0) )
779 : {
780 544898 : sal_uInt16 nReadSize = GetMaxRawReadSize( nBytesLeft );
781 544898 : mrStrm.SeekRel( nReadSize );
782 544898 : mnRawRecLeft = mnRawRecLeft - nReadSize;
783 544898 : nBytesLeft -= nReadSize;
784 544898 : if( nBytesLeft > 0 )
785 5 : JumpToNextContinue();
786 : OSL_ENSURE( mbValid, "XclImpStream::Ignore - record overread" );
787 : }
788 553026 : }
789 :
790 8040 : sal_Size XclImpStream::ReadUniStringExtHeader(
791 : bool& rb16Bit, bool& rbRich, bool& rbFareast,
792 : sal_uInt16& rnFormatRuns, sal_uInt32& rnExtInf, sal_uInt8 nFlags )
793 : {
794 : OSL_ENSURE( !::get_flag( nFlags, EXC_STRF_UNKNOWN ), "XclImpStream::ReadUniStringExt - unknown flags" );
795 8040 : rb16Bit = ::get_flag( nFlags, EXC_STRF_16BIT );
796 8040 : rbRich = ::get_flag( nFlags, EXC_STRF_RICH );
797 8040 : rbFareast = ::get_flag( nFlags, EXC_STRF_FAREAST );
798 8040 : rnFormatRuns = rbRich ? ReaduInt16() : 0;
799 8040 : rnExtInf = rbFareast ? ReaduInt32() : 0;
800 8040 : return rnExtInf + 4 * rnFormatRuns;
801 : }
802 :
803 5811 : sal_Size XclImpStream::ReadUniStringExtHeader( bool& rb16Bit, sal_uInt8 nFlags )
804 : {
805 : bool bRich, bFareast;
806 : sal_uInt16 nCrun;
807 : sal_uInt32 nExtInf;
808 5811 : return ReadUniStringExtHeader( rb16Bit, bRich, bFareast, nCrun, nExtInf, nFlags );
809 : }
810 :
811 8048 : OUString XclImpStream::ReadRawUniString( sal_uInt16 nChars, bool b16Bit )
812 : {
813 8048 : OUString aRet;
814 8048 : sal_uInt16 nCharsLeft = nChars;
815 : sal_uInt16 nReadSize;
816 :
817 16096 : boost::scoped_array<sal_Unicode> pcBuffer(new sal_Unicode[ nCharsLeft + 1 ]);
818 :
819 24137 : while( IsValid() && (nCharsLeft > 0) )
820 : {
821 8041 : if( b16Bit )
822 : {
823 1582 : nReadSize = ::std::min< sal_uInt16 >( nCharsLeft, mnRawRecLeft / 2 );
824 : OSL_ENSURE( (nReadSize <= nCharsLeft) || !(mnRawRecLeft & 0x1),
825 : "XclImpStream::ReadRawUniString - missing a byte" );
826 : }
827 : else
828 6459 : nReadSize = GetMaxRawReadSize( nCharsLeft );
829 :
830 8041 : sal_Unicode* pcUniChar = pcBuffer.get();
831 8041 : sal_Unicode* pcEndChar = pcBuffer.get() + nReadSize;
832 :
833 8041 : if( b16Bit )
834 : {
835 : sal_uInt16 nReadChar;
836 33006 : for( ; IsValid() && (pcUniChar < pcEndChar); ++pcUniChar )
837 : {
838 31424 : nReadChar = ReaduInt16();
839 31424 : (*pcUniChar) = (nReadChar == EXC_NUL) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
840 : }
841 : }
842 : else
843 : {
844 : sal_uInt8 nReadChar;
845 62578 : for( ; IsValid() && (pcUniChar < pcEndChar); ++pcUniChar )
846 : {
847 56119 : nReadChar = ReaduInt8();
848 56119 : (*pcUniChar) = (nReadChar == EXC_NUL_C) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
849 : }
850 : }
851 :
852 8041 : *pcEndChar = '\0';
853 8041 : aRet += OUString( pcBuffer.get() );
854 :
855 8041 : nCharsLeft = nCharsLeft - nReadSize;
856 8041 : if( nCharsLeft > 0 )
857 3 : JumpToNextStringContinue( b16Bit );
858 : }
859 :
860 16096 : return aRet;
861 : }
862 :
863 5811 : OUString XclImpStream::ReadUniString( sal_uInt16 nChars, sal_uInt8 nFlags )
864 : {
865 : bool b16Bit;
866 5811 : sal_Size nExtSize = ReadUniStringExtHeader( b16Bit, nFlags );
867 5811 : OUString aRet( ReadRawUniString( nChars, b16Bit ) );
868 5811 : Ignore( nExtSize );
869 5811 : return aRet;
870 : }
871 :
872 5811 : OUString XclImpStream::ReadUniString( sal_uInt16 nChars )
873 : {
874 5811 : return ReadUniString( nChars, ReaduInt8() );
875 : }
876 :
877 1817 : OUString XclImpStream::ReadUniString()
878 : {
879 1817 : return ReadUniString( ReaduInt16() );
880 : }
881 :
882 0 : void XclImpStream::IgnoreRawUniString( sal_uInt16 nChars, bool b16Bit )
883 : {
884 0 : sal_uInt16 nCharsLeft = nChars;
885 : sal_uInt16 nReadSize;
886 :
887 0 : while( IsValid() && (nCharsLeft > 0) )
888 : {
889 0 : if( b16Bit )
890 : {
891 0 : nReadSize = ::std::min< sal_uInt16 >( nCharsLeft, mnRawRecLeft / 2 );
892 : OSL_ENSURE( (nReadSize <= nCharsLeft) || !(mnRawRecLeft & 0x1),
893 : "XclImpStream::IgnoreRawUniString - missing a byte" );
894 0 : Ignore( nReadSize * 2 );
895 : }
896 : else
897 : {
898 0 : nReadSize = GetMaxRawReadSize( nCharsLeft );
899 0 : Ignore( nReadSize );
900 : }
901 :
902 0 : nCharsLeft = nCharsLeft - nReadSize;
903 0 : if( nCharsLeft > 0 )
904 0 : JumpToNextStringContinue( b16Bit );
905 : }
906 0 : }
907 :
908 0 : void XclImpStream::IgnoreUniString( sal_uInt16 nChars, sal_uInt8 nFlags )
909 : {
910 : bool b16Bit;
911 0 : sal_Size nExtSize = ReadUniStringExtHeader( b16Bit, nFlags );
912 0 : IgnoreRawUniString( nChars, b16Bit );
913 0 : Ignore( nExtSize );
914 0 : }
915 :
916 0 : void XclImpStream::IgnoreUniString( sal_uInt16 nChars )
917 : {
918 0 : IgnoreUniString( nChars, ReaduInt8() );
919 0 : }
920 :
921 865 : OUString XclImpStream::ReadRawByteString( sal_uInt16 nChars )
922 : {
923 865 : nChars = GetMaxRawReadSize(nChars);
924 865 : boost::scoped_array<sal_Char> pcBuffer(new sal_Char[ nChars + 1 ]);
925 865 : sal_uInt16 nCharsRead = ReadRawData( pcBuffer.get(), nChars );
926 865 : pcBuffer[ nCharsRead ] = '\0';
927 865 : OUString aRet( pcBuffer.get(), strlen(pcBuffer.get()), mrRoot.GetTextEncoding() );
928 865 : return aRet;
929 : }
930 :
931 864 : OUString XclImpStream::ReadByteString( bool b16BitLen )
932 : {
933 864 : return ReadRawByteString( ReadByteStrLen( b16BitLen ) );
934 : }
935 :
936 : // private --------------------------------------------------------------------
937 :
938 1187030 : void XclImpStream::StorePosition( XclImpStreamPos& rPos )
939 : {
940 1187030 : rPos.Set( mrStrm, mnNextRecPos, mnCurrRecSize, mnRawRecId, mnRawRecSize, mnRawRecLeft, mbValid );
941 1187030 : }
942 :
943 12493 : void XclImpStream::RestorePosition( const XclImpStreamPos& rPos )
944 : {
945 12493 : rPos.Get( mrStrm, mnNextRecPos, mnCurrRecSize, mnRawRecId, mnRawRecSize, mnRawRecLeft, mbValid );
946 12493 : SetupDecrypter();
947 12493 : }
948 :
949 1184049 : bool XclImpStream::ReadNextRawRecHeader()
950 : {
951 1184049 : sal_Size nSeekedPos = mrStrm.Seek( mnNextRecPos );
952 1184049 : bool bRet = (nSeekedPos == mnNextRecPos) && (mnNextRecPos + 4 <= mnStreamSize);
953 1184049 : if( bRet )
954 : {
955 1183943 : mrStrm.ReadUInt16( mnRawRecId ).ReadUInt16( mnRawRecSize );
956 1183943 : bRet = mrStrm.good();
957 : }
958 1184049 : return bRet;
959 : }
960 :
961 1188113 : void XclImpStream::SetupDecrypter()
962 : {
963 1188113 : if( mxDecrypter )
964 0 : mxDecrypter->Update( mrStrm, mnRawRecSize );
965 1188113 : }
966 :
967 1175616 : void XclImpStream::SetupRawRecord()
968 : {
969 : // pre: mnRawRecSize contains current raw record size
970 : // pre: mrStrm points to start of raw record data
971 1175616 : mnNextRecPos = mrStrm.Tell() + mnRawRecSize;
972 1175616 : mnRawRecLeft = mnRawRecSize;
973 1175616 : mnCurrRecSize += mnRawRecSize;
974 1175616 : SetupDecrypter(); // decrypter works on raw record level
975 1175616 : }
976 :
977 1175529 : void XclImpStream::SetupRecord()
978 : {
979 1175529 : mnRecId = mnRawRecId;
980 1175529 : mnAltContId = EXC_ID_UNKNOWN;
981 1175529 : mnCurrRecSize = 0;
982 1175529 : mnComplRecSize = mnRawRecSize;
983 1175529 : mbHasComplRec = !mbCont;
984 1175529 : SetupRawRecord();
985 1175529 : SetNulSubstChar();
986 1175529 : EnableDecryption();
987 1175529 : StorePosition( maFirstRec );
988 1175529 : }
989 :
990 1183656 : bool XclImpStream::IsContinueId( sal_uInt16 nRecId ) const
991 : {
992 1183656 : return (nRecId == EXC_ID_CONT) || (nRecId == mnAltContId);
993 : }
994 :
995 8962 : bool XclImpStream::JumpToNextContinue()
996 : {
997 8962 : mbValid = mbValid && mbCont && ReadNextRawRecHeader() && IsContinueId( mnRawRecId );
998 8962 : if( mbValid ) // do not setup a following non-CONTINUE record
999 87 : SetupRawRecord();
1000 8962 : return mbValid;
1001 : }
1002 :
1003 3 : bool XclImpStream::JumpToNextStringContinue( bool& rb16Bit )
1004 : {
1005 : OSL_ENSURE( mnRawRecLeft == 0, "XclImpStream::JumpToNextStringContinue - unexpected garbage" );
1006 :
1007 3 : if( mbCont && (GetRecLeft() > 0) )
1008 : {
1009 3 : JumpToNextContinue();
1010 : }
1011 0 : else if( mnRecId == EXC_ID_CONT )
1012 : {
1013 : // CONTINUE handling is off, but we have started reading in a CONTINUE record
1014 : // -> start next CONTINUE for TXO import
1015 0 : mbValidRec = ReadNextRawRecHeader() && ((mnRawRecId != 0) || (mnRawRecSize > 0));
1016 0 : mbValid = mbValidRec && (mnRawRecId == EXC_ID_CONT);
1017 : // we really start a new record here - no chance to return to string origin
1018 0 : if( mbValid )
1019 0 : SetupRecord();
1020 : }
1021 : else
1022 0 : mbValid = false;
1023 :
1024 3 : if( mbValid )
1025 2 : rb16Bit = ::get_flag( ReaduInt8(), EXC_STRF_16BIT );
1026 3 : return mbValid;
1027 : }
1028 :
1029 2319250 : bool XclImpStream::EnsureRawReadSize( sal_uInt16 nBytes )
1030 : {
1031 2319250 : if( mbValid && nBytes )
1032 : {
1033 2319250 : while( mbValid && !mnRawRecLeft ) JumpToNextContinue();
1034 2319250 : mbValid = mbValid && (nBytes <= mnRawRecLeft);
1035 : OSL_ENSURE( mbValid, "XclImpStream::EnsureRawReadSize - record overread" );
1036 : }
1037 2319250 : return mbValid;
1038 : }
1039 :
1040 552870 : sal_uInt16 XclImpStream::GetMaxRawReadSize( sal_Size nBytes ) const
1041 : {
1042 552870 : return static_cast< sal_uInt16 >( ::std::min< sal_Size >( nBytes, mnRawRecLeft ) );
1043 : }
1044 :
1045 1513 : sal_uInt16 XclImpStream::ReadRawData( void* pData, sal_uInt16 nBytes )
1046 : {
1047 : OSL_ENSURE( (nBytes <= mnRawRecLeft), "XclImpStream::ReadRawData - record overread" );
1048 1513 : sal_uInt16 nRet = 0;
1049 1513 : if( mbUseDecr )
1050 0 : nRet = mxDecrypter->Read( mrStrm, pData, nBytes );
1051 : else
1052 1513 : nRet = static_cast< sal_uInt16 >( mrStrm.Read( pData, nBytes ) );
1053 1513 : mnRawRecLeft = mnRawRecLeft - nRet;
1054 1513 : return nRet;
1055 : }
1056 :
1057 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|