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