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