Update ooo320-m1
[ooovba.git] / sc / source / filter / excel / xistream.cxx
bloba040f21b1c4f31a6405c64c4a38a502ffaaf3926
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: xistream.cxx,v $
10 * $Revision: 1.22.30.3 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sc.hxx"
34 #include "xistream.hxx"
35 #include "xlstring.hxx"
36 #include "xiroot.hxx"
38 #include <vector>
40 using ::rtl::OString;
41 using ::rtl::OUString;
42 using ::rtl::OUStringToOString;
44 // ============================================================================
45 // Decryption
46 // ============================================================================
48 XclImpDecrypter::XclImpDecrypter() :
49 mnError( EXC_ENCR_ERROR_UNSUPP_CRYPT ),
50 mnOldPos( STREAM_SEEK_TO_END ),
51 mnRecSize( 0 )
55 XclImpDecrypter::XclImpDecrypter( const XclImpDecrypter& rSrc ) :
56 ::comphelper::IDocPasswordVerifier(),
57 mnError( rSrc.mnError ),
58 mnOldPos( STREAM_SEEK_TO_END ),
59 mnRecSize( 0 )
63 XclImpDecrypter::~XclImpDecrypter()
67 XclImpDecrypterRef XclImpDecrypter::Clone() const
69 XclImpDecrypterRef xNewDecr;
70 if( IsValid() )
71 xNewDecr.reset( OnClone() );
72 return xNewDecr;
75 ::comphelper::DocPasswordVerifierResult XclImpDecrypter::verifyPassword( const OUString& rPassword )
77 bool bValid = OnVerify( rPassword );
78 mnError = bValid ? ERRCODE_NONE : ERRCODE_ABORT;
79 return bValid ? ::comphelper::DocPasswordVerifierResult_OK : ::comphelper::DocPasswordVerifierResult_WRONG_PASSWORD;
82 void XclImpDecrypter::Update( SvStream& rStrm, sal_uInt16 nRecSize )
84 if( IsValid() )
86 sal_Size nNewPos = rStrm.Tell();
87 if( (mnOldPos != nNewPos) || (mnRecSize != nRecSize) )
89 OnUpdate( mnOldPos, nNewPos, nRecSize );
90 mnOldPos = nNewPos;
91 mnRecSize = nRecSize;
96 sal_uInt16 XclImpDecrypter::Read( SvStream& rStrm, void* pData, sal_uInt16 nBytes )
98 sal_uInt16 nRet = 0;
99 if( pData && nBytes )
101 if( IsValid() )
103 Update( rStrm, mnRecSize );
104 nRet = OnRead( rStrm, reinterpret_cast< sal_uInt8* >( pData ), nBytes );
105 mnOldPos = rStrm.Tell();
107 else
108 nRet = static_cast< sal_uInt16 >( rStrm.Read( pData, nBytes ) );
110 return nRet;
113 // ----------------------------------------------------------------------------
115 XclImpBiff5Decrypter::XclImpBiff5Decrypter( sal_uInt16 nKey, sal_uInt16 nHash ) :
116 maPassword( 16 ),
117 mnKey( nKey ),
118 mnHash( nHash )
122 XclImpBiff5Decrypter::XclImpBiff5Decrypter( const XclImpBiff5Decrypter& rSrc ) :
123 XclImpDecrypter( rSrc ),
124 maPassword( rSrc.maPassword ),
125 mnKey( rSrc.mnKey ),
126 mnHash( rSrc.mnHash )
128 if( IsValid() )
129 maCodec.InitKey( &maPassword.front() );
132 XclImpBiff5Decrypter* XclImpBiff5Decrypter::OnClone() const
134 return new XclImpBiff5Decrypter( *this );
137 bool XclImpBiff5Decrypter::OnVerify( const OUString& rPassword )
139 /* Convert password to a byte string. TODO: this needs some finetuning
140 according to the spec... */
141 OString aBytePassword = OUStringToOString( rPassword, osl_getThreadTextEncoding() );
142 sal_Int32 nLen = aBytePassword.getLength();
143 if( (0 < nLen) && (nLen < 16) )
145 // copy byte string to sal_uInt8 array
146 maPassword.clear();
147 maPassword.resize( 16, 0 );
148 memcpy( &maPassword.front(), aBytePassword.getStr(), static_cast< size_t >( nLen ) );
150 // init codec
151 maCodec.InitKey( &maPassword.front() );
152 return maCodec.VerifyKey( mnKey, mnHash );
154 return false;
157 void XclImpBiff5Decrypter::OnUpdate( sal_Size /*nOldStrmPos*/, sal_Size nNewStrmPos, sal_uInt16 nRecSize )
159 maCodec.InitCipher();
160 maCodec.Skip( (nNewStrmPos + nRecSize) & 0x0F );
163 sal_uInt16 XclImpBiff5Decrypter::OnRead( SvStream& rStrm, sal_uInt8* pnData, sal_uInt16 nBytes )
165 sal_uInt16 nRet = static_cast< sal_uInt16 >( rStrm.Read( pnData, nBytes ) );
166 maCodec.Decode( pnData, nRet );
167 return nRet;
170 // ----------------------------------------------------------------------------
172 XclImpBiff8Decrypter::XclImpBiff8Decrypter( sal_uInt8 pnSalt[ 16 ],
173 sal_uInt8 pnVerifier[ 16 ], sal_uInt8 pnVerifierHash[ 16 ] ) :
174 maPassword( 16, 0 ),
175 maSalt( pnSalt, pnSalt + 16 ),
176 maVerifier( pnVerifier, pnVerifier + 16 ),
177 maVerifierHash( pnVerifierHash, pnVerifierHash + 16 )
181 XclImpBiff8Decrypter::XclImpBiff8Decrypter( const XclImpBiff8Decrypter& rSrc ) :
182 XclImpDecrypter( rSrc ),
183 maPassword( rSrc.maPassword ),
184 maSalt( rSrc.maSalt ),
185 maVerifier( rSrc.maVerifier ),
186 maVerifierHash( rSrc.maVerifierHash )
188 if( IsValid() )
189 maCodec.InitKey( &maPassword.front(), &maSalt.front() );
192 XclImpBiff8Decrypter* XclImpBiff8Decrypter::OnClone() const
194 return new XclImpBiff8Decrypter( *this );
197 bool XclImpBiff8Decrypter::OnVerify( const OUString& rPassword )
199 sal_Int32 nLen = rPassword.getLength();
200 if( (0 < nLen) && (nLen < 16) )
202 // copy string to sal_uInt16 array
203 maPassword.clear();
204 maPassword.resize( 16, 0 );
205 const sal_Unicode* pcChar = rPassword.getStr();
206 const sal_Unicode* pcCharEnd = pcChar + nLen;
207 ::std::vector< sal_uInt16 >::iterator aIt = maPassword.begin();
208 for( ; pcChar < pcCharEnd; ++pcChar, ++aIt )
209 *aIt = static_cast< sal_uInt16 >( *pcChar );
211 // init codec
212 maCodec.InitKey( &maPassword.front(), &maSalt.front() );
213 return maCodec.VerifyKey( &maVerifier.front(), &maVerifierHash.front() );
215 return false;
218 void XclImpBiff8Decrypter::OnUpdate( sal_Size nOldStrmPos, sal_Size nNewStrmPos, sal_uInt16 /*nRecSize*/ )
220 if( nNewStrmPos != nOldStrmPos )
222 sal_uInt32 nOldBlock = GetBlock( nOldStrmPos );
223 sal_uInt16 nOldOffset = GetOffset( nOldStrmPos );
225 sal_uInt32 nNewBlock = GetBlock( nNewStrmPos );
226 sal_uInt16 nNewOffset = GetOffset( nNewStrmPos );
228 /* Rekey cipher, if block changed or if previous offset in same block. */
229 if( (nNewBlock != nOldBlock) || (nNewOffset < nOldOffset) )
231 maCodec.InitCipher( nNewBlock );
232 nOldOffset = 0; // reset nOldOffset for next if() statement
235 /* Seek to correct offset. */
236 if( nNewOffset > nOldOffset )
237 maCodec.Skip( nNewOffset - nOldOffset );
241 sal_uInt16 XclImpBiff8Decrypter::OnRead( SvStream& rStrm, sal_uInt8* pnData, sal_uInt16 nBytes )
243 sal_uInt16 nRet = 0;
245 sal_uInt8* pnCurrData = pnData;
246 sal_uInt16 nBytesLeft = nBytes;
247 while( nBytesLeft )
249 sal_uInt16 nBlockLeft = EXC_ENCR_BLOCKSIZE - GetOffset( rStrm.Tell() );
250 sal_uInt16 nDecBytes = ::std::min< sal_uInt16 >( nBytesLeft, nBlockLeft );
252 // read the block from stream
253 nRet = nRet + static_cast< sal_uInt16 >( rStrm.Read( pnCurrData, nDecBytes ) );
254 // decode the block inplace
255 maCodec.Decode( pnCurrData, nDecBytes, pnCurrData, nDecBytes );
256 if( GetOffset( rStrm.Tell() ) == 0 )
257 maCodec.InitCipher( GetBlock( rStrm.Tell() ) );
259 pnCurrData += nDecBytes;
260 nBytesLeft = nBytesLeft - nDecBytes;
263 return nRet;
266 sal_uInt32 XclImpBiff8Decrypter::GetBlock( sal_Size nStrmPos ) const
268 return static_cast< sal_uInt32 >( nStrmPos / EXC_ENCR_BLOCKSIZE );
271 sal_uInt16 XclImpBiff8Decrypter::GetOffset( sal_Size nStrmPos ) const
273 return static_cast< sal_uInt16 >( nStrmPos % EXC_ENCR_BLOCKSIZE );
276 // ============================================================================
277 // Stream
278 // ============================================================================
280 XclImpStreamPos::XclImpStreamPos() :
281 mnPos( STREAM_SEEK_TO_BEGIN ),
282 mnNextPos( STREAM_SEEK_TO_BEGIN ),
283 mnCurrSize( 0 ),
284 mnRawRecId( EXC_ID_UNKNOWN ),
285 mnRawRecSize( 0 ),
286 mnRawRecLeft( 0 ),
287 mbValid( false )
291 void XclImpStreamPos::Set(
292 const SvStream& rStrm, sal_Size nNextPos, sal_Size nCurrSize,
293 sal_uInt16 nRawRecId, sal_uInt16 nRawRecSize, sal_uInt16 nRawRecLeft,
294 bool bValid )
296 mnPos = rStrm.Tell();
297 mnNextPos = nNextPos;
298 mnCurrSize = nCurrSize;
299 mnRawRecId = nRawRecId;
300 mnRawRecSize = nRawRecSize;
301 mnRawRecLeft = nRawRecLeft;
302 mbValid = bValid;
305 void XclImpStreamPos::Get(
306 SvStream& rStrm, sal_Size& rnNextPos, sal_Size& rnCurrSize,
307 sal_uInt16& rnRawRecId, sal_uInt16& rnRawRecSize, sal_uInt16& rnRawRecLeft,
308 bool& rbValid ) const
310 rStrm.Seek( mnPos );
311 rnNextPos = mnNextPos;
312 rnCurrSize = mnCurrSize;
313 rnRawRecId = mnRawRecId;
314 rnRawRecSize = mnRawRecSize;
315 rnRawRecLeft = mnRawRecLeft;
316 rbValid = mbValid;
319 // ============================================================================
321 XclBiff XclImpStream::DetectBiffVersion( SvStream& rStrm )
323 XclBiff eBiff = EXC_BIFF_UNKNOWN;
325 rStrm.Seek( STREAM_SEEK_TO_BEGIN );
326 sal_uInt16 nBofId, nBofSize;
327 rStrm >> nBofId >> nBofSize;
329 if( (4 <= nBofSize) && (nBofSize <= 16) ) switch( nBofId )
331 case EXC_ID2_BOF:
332 eBiff = EXC_BIFF2;
333 break;
334 case EXC_ID3_BOF:
335 eBiff = EXC_BIFF3;
336 break;
337 case EXC_ID4_BOF:
338 eBiff = EXC_BIFF4;
339 break;
340 case EXC_ID5_BOF:
342 sal_uInt16 nVersion;
343 rStrm >> nVersion;
344 // #i23425# #i44031# #i62752# there are some *really* broken documents out there...
345 switch( nVersion & 0xFF00 )
347 case 0: eBiff = EXC_BIFF5; break; // #i44031# #i62752#
348 case EXC_BOF_BIFF2: eBiff = EXC_BIFF2; break;
349 case EXC_BOF_BIFF3: eBiff = EXC_BIFF3; break;
350 case EXC_BOF_BIFF4: eBiff = EXC_BIFF4; break;
351 case EXC_BOF_BIFF5: eBiff = EXC_BIFF5; break;
352 case EXC_BOF_BIFF8: eBiff = EXC_BIFF8; break;
353 default: DBG_ERROR1( "XclImpStream::DetectBiffVersion - unknown BIFF version: 0x%04hX", nVersion );
356 break;
358 return eBiff;
361 XclImpStream::XclImpStream( SvStream& rInStrm, const XclImpRoot& rRoot, bool bContLookup ) :
362 mrStrm( rInStrm ),
363 mrRoot( rRoot ),
364 mnGlobRecId( EXC_ID_UNKNOWN ),
365 mbGlobValidRec( false ),
366 mbHasGlobPos( false ),
367 mnNextRecPos( STREAM_SEEK_TO_BEGIN ),
368 mnCurrRecSize( 0 ),
369 mnComplRecSize( 0 ),
370 mbHasComplRec( false ),
371 mnRecId( EXC_ID_UNKNOWN ),
372 mnAltContId( EXC_ID_UNKNOWN ),
373 mnRawRecId( EXC_ID_UNKNOWN ),
374 mnRawRecSize( 0 ),
375 mnRawRecLeft( 0 ),
376 mcNulSubst( '?' ),
377 mbCont( bContLookup ),
378 mbUseDecr( false ),
379 mbValidRec( false ),
380 mbValid( false )
382 mrStrm.Seek( STREAM_SEEK_TO_END );
383 mnStreamSize = mrStrm.Tell();
384 mrStrm.Seek( STREAM_SEEK_TO_BEGIN );
385 DBG_ASSERT( mnStreamSize < STREAM_SEEK_TO_END, "XclImpStream::XclImpStream - stream error" );
388 XclImpStream::~XclImpStream()
392 bool XclImpStream::StartNextRecord()
394 maPosStack.clear();
396 /* #i4266# Counter to ignore zero records (id==len==0) (i.e. the application
397 "Crystal Report" writes zero records between other records) */
398 sal_Size nZeroRecCount = 5;
399 bool bIsZeroRec = false;
403 mbValidRec = ReadNextRawRecHeader();
404 bIsZeroRec = (mnRawRecId == 0) && (mnRawRecSize == 0);
405 if( bIsZeroRec ) --nZeroRecCount;
406 mnNextRecPos = mrStrm.Tell() + mnRawRecSize;
408 while( mbValidRec && ((mbCont && IsContinueId( mnRawRecId )) || (bIsZeroRec && nZeroRecCount)) );
410 mbValidRec = mbValidRec && !bIsZeroRec;
411 mbValid = mbValidRec;
412 SetupRecord();
414 return mbValidRec;
417 bool XclImpStream::StartNextRecord( sal_Size nNextRecPos )
419 mnNextRecPos = nNextRecPos;
420 return StartNextRecord();
423 void XclImpStream::ResetRecord( bool bContLookup, sal_uInt16 nAltContId )
425 if( mbValidRec )
427 maPosStack.clear();
428 RestorePosition( maFirstRec );
429 mnCurrRecSize = mnComplRecSize = mnRawRecSize;
430 mbHasComplRec = !bContLookup;
431 mbCont = bContLookup;
432 mnAltContId = nAltContId;
433 EnableDecryption();
437 void XclImpStream::SetDecrypter( XclImpDecrypterRef xDecrypter )
439 mxDecrypter = xDecrypter;
440 EnableDecryption();
441 SetupDecrypter();
444 void XclImpStream::CopyDecrypterFrom( const XclImpStream& rStrm )
446 XclImpDecrypterRef xNewDecr;
447 if( rStrm.mxDecrypter.is() )
448 xNewDecr = rStrm.mxDecrypter->Clone();
449 SetDecrypter( xNewDecr );
452 bool XclImpStream::HasValidDecrypter() const
454 return mxDecrypter.is() && mxDecrypter->IsValid();
457 void XclImpStream::EnableDecryption( bool bEnable )
459 mbUseDecr = bEnable && HasValidDecrypter();
462 // ----------------------------------------------------------------------------
464 void XclImpStream::PushPosition()
466 maPosStack.push_back( XclImpStreamPos() );
467 StorePosition( maPosStack.back() );
470 void XclImpStream::PopPosition()
472 DBG_ASSERT( !maPosStack.empty(), "XclImpStream::PopPosition - stack empty" );
473 if( !maPosStack.empty() )
475 RestorePosition( maPosStack.back() );
476 maPosStack.pop_back();
480 //UNUSED2008-05 void XclImpStream::RejectPosition()
481 //UNUSED2008-05 {
482 //UNUSED2008-05 DBG_ASSERT( !maPosStack.empty(), "XclImpStream::RejectPosition - stack empty" );
483 //UNUSED2008-05 if( !maPosStack.empty() )
484 //UNUSED2008-05 maPosStack.pop_back();
485 //UNUSED2008-05 }
487 void XclImpStream::StoreGlobalPosition()
489 StorePosition( maGlobPos );
490 mnGlobRecId = mnRecId;
491 mbGlobValidRec = mbValidRec;
492 mbHasGlobPos = true;
495 void XclImpStream::SeekGlobalPosition()
497 DBG_ASSERT( mbHasGlobPos, "XclImpStream::SeekGlobalPosition - no position stored" );
498 if( mbHasGlobPos )
500 RestorePosition( maGlobPos );
501 mnRecId = mnGlobRecId;
502 mnComplRecSize = mnCurrRecSize;
503 mbHasComplRec = !mbCont;
504 mbValidRec = mbGlobValidRec;
508 sal_Size XclImpStream::GetRecPos() const
510 return mbValid ? (mnCurrRecSize - mnRawRecLeft) : EXC_REC_SEEK_TO_END;
513 sal_Size XclImpStream::GetRecSize()
515 if( !mbHasComplRec )
517 PushPosition();
518 while( JumpToNextContinue() ) ; // JumpToNextContinue() adds up mnCurrRecSize
519 mnComplRecSize = mnCurrRecSize;
520 mbHasComplRec = true;
521 PopPosition();
523 return mnComplRecSize;
526 sal_Size XclImpStream::GetRecLeft()
528 return mbValid ? (GetRecSize() - GetRecPos()) : 0;
531 sal_uInt16 XclImpStream::GetNextRecId()
533 sal_uInt16 nRecId = EXC_ID_UNKNOWN;
534 if( mbValidRec )
536 PushPosition();
537 while( JumpToNextContinue() ) ; // skip following CONTINUE records
538 if( mnNextRecPos < mnStreamSize )
540 mrStrm.Seek( mnNextRecPos );
541 mrStrm >> nRecId;
543 PopPosition();
545 return nRecId;
548 // ----------------------------------------------------------------------------
550 XclImpStream& XclImpStream::operator>>( sal_Int8& rnValue )
552 if( EnsureRawReadSize( 1 ) )
554 if( mbUseDecr )
555 mxDecrypter->Read( mrStrm, &rnValue, 1 );
556 else
557 mrStrm >> rnValue;
558 --mnRawRecLeft;
560 return *this;
563 XclImpStream& XclImpStream::operator>>( sal_uInt8& rnValue )
565 if( EnsureRawReadSize( 1 ) )
567 if( mbUseDecr )
568 mxDecrypter->Read( mrStrm, &rnValue, 1 );
569 else
570 mrStrm >> rnValue;
571 --mnRawRecLeft;
573 return *this;
576 XclImpStream& XclImpStream::operator>>( sal_Int16& rnValue )
578 if( EnsureRawReadSize( 2 ) )
580 if( mbUseDecr )
582 SVBT16 pnBuffer;
583 mxDecrypter->Read( mrStrm, pnBuffer, 2 );
584 rnValue = static_cast< sal_Int16 >( SVBT16ToShort( pnBuffer ) );
586 else
587 mrStrm >> rnValue;
588 mnRawRecLeft -= 2;
590 return *this;
593 XclImpStream& XclImpStream::operator>>( sal_uInt16& rnValue )
595 if( EnsureRawReadSize( 2 ) )
597 if( mbUseDecr )
599 SVBT16 pnBuffer;
600 mxDecrypter->Read( mrStrm, pnBuffer, 2 );
601 rnValue = SVBT16ToShort( pnBuffer );
603 else
604 mrStrm >> rnValue;
605 mnRawRecLeft -= 2;
607 return *this;
610 XclImpStream& XclImpStream::operator>>( sal_Int32& rnValue )
612 if( EnsureRawReadSize( 4 ) )
614 if( mbUseDecr )
616 SVBT32 pnBuffer;
617 mxDecrypter->Read( mrStrm, pnBuffer, 4 );
618 rnValue = static_cast< sal_Int32 >( SVBT32ToUInt32( pnBuffer ) );
620 else
621 mrStrm >> rnValue;
622 mnRawRecLeft -= 4;
624 return *this;
627 XclImpStream& XclImpStream::operator>>( sal_uInt32& rnValue )
629 if( EnsureRawReadSize( 4 ) )
631 if( mbUseDecr )
633 SVBT32 pnBuffer;
634 mxDecrypter->Read( mrStrm, pnBuffer, 4 );
635 rnValue = SVBT32ToUInt32( pnBuffer );
637 else
638 mrStrm >> rnValue;
639 mnRawRecLeft -= 4;
641 return *this;
644 XclImpStream& XclImpStream::operator>>( float& rfValue )
646 if( EnsureRawReadSize( 4 ) )
648 if( mbUseDecr )
650 SVBT32 pnBuffer;
651 mxDecrypter->Read( mrStrm, pnBuffer, 4 );
652 sal_uInt32 nValue = SVBT32ToUInt32( pnBuffer );
653 memcpy( &rfValue, &nValue, 4 );
655 else
656 mrStrm >> rfValue;
657 mnRawRecLeft -= 4;
659 return *this;
662 XclImpStream& XclImpStream::operator>>( double& rfValue )
664 if( EnsureRawReadSize( 8 ) )
666 if( mbUseDecr )
668 SVBT64 pnBuffer;
669 mxDecrypter->Read( mrStrm, pnBuffer, 8 );
670 rfValue = SVBT64ToDouble( pnBuffer );
672 else
673 mrStrm >> rfValue;
674 mnRawRecLeft -= 8;
676 return *this;
679 sal_Int8 XclImpStream::ReadInt8()
681 sal_Int8 nValue;
682 operator>>( nValue );
683 return nValue;
686 sal_uInt8 XclImpStream::ReaduInt8()
688 sal_uInt8 nValue;
689 operator>>( nValue );
690 return nValue;
693 sal_Int16 XclImpStream::ReadInt16()
695 sal_Int16 nValue;
696 operator>>( nValue );
697 return nValue;
700 sal_uInt16 XclImpStream::ReaduInt16()
702 sal_uInt16 nValue;
703 operator>>( nValue );
704 return nValue;
707 sal_Int32 XclImpStream::ReadInt32()
709 sal_Int32 nValue;
710 operator>>( nValue );
711 return nValue;
714 sal_uInt32 XclImpStream::ReaduInt32()
716 sal_uInt32 nValue;
717 operator>>( nValue );
718 return nValue;
721 float XclImpStream::ReadFloat()
723 float fValue;
724 operator>>( fValue );
725 return fValue;
728 double XclImpStream::ReadDouble()
730 double fValue;
731 operator>>( fValue );
732 return fValue;
735 sal_Size XclImpStream::Read( void* pData, sal_Size nBytes )
737 sal_Size nRet = 0;
738 if( mbValid && pData && (nBytes > 0) )
740 sal_uInt8* pnBuffer = reinterpret_cast< sal_uInt8* >( pData );
741 sal_Size nBytesLeft = nBytes;
743 while( mbValid && (nBytesLeft > 0) )
745 sal_uInt16 nReadSize = GetMaxRawReadSize( nBytesLeft );
746 sal_uInt16 nReadRet = ReadRawData( pnBuffer, nReadSize );
747 nRet += nReadRet;
748 mbValid = (nReadSize == nReadRet);
749 DBG_ASSERT( mbValid, "XclImpStream::Read - stream read error" );
750 pnBuffer += nReadRet;
751 nBytesLeft -= nReadRet;
752 if( mbValid && (nBytesLeft > 0) )
753 JumpToNextContinue();
754 DBG_ASSERT( mbValid, "XclImpStream::Read - record overread" );
757 return nRet;
760 sal_Size XclImpStream::CopyToStream( SvStream& rOutStrm, sal_Size nBytes )
762 sal_Size nRet = 0;
763 if( mbValid && (nBytes > 0) )
765 const sal_Size nMaxBuffer = 4096;
766 sal_uInt8* pnBuffer = new sal_uInt8[ ::std::min( nBytes, nMaxBuffer ) ];
767 sal_Size nBytesLeft = nBytes;
769 while( mbValid && (nBytesLeft > 0) )
771 sal_Size nReadSize = ::std::min( nBytesLeft, nMaxBuffer );
772 nRet += Read( pnBuffer, nReadSize );
773 rOutStrm.Write( pnBuffer, nReadSize );
774 nBytesLeft -= nReadSize;
777 delete[] pnBuffer;
779 return nRet;
782 sal_Size XclImpStream::CopyRecordToStream( SvStream& rOutStrm )
784 sal_Size nRet = 0;
785 if( mbValidRec )
787 PushPosition();
788 RestorePosition( maFirstRec );
789 nRet = CopyToStream( rOutStrm, GetRecSize() );
790 PopPosition();
792 return nRet;
795 void XclImpStream::Seek( sal_Size nPos )
797 if( mbValidRec )
799 sal_Size nCurrPos = GetRecPos();
800 if( !mbValid || (nPos < nCurrPos) ) // from invalid state or backward
802 RestorePosition( maFirstRec );
803 Ignore( nPos );
805 else if( nPos > nCurrPos ) // forward
807 Ignore( nPos - nCurrPos );
812 void XclImpStream::Ignore( sal_Size nBytes )
814 // implementation similar to Read(), but without really reading anything
815 sal_Size nBytesLeft = nBytes;
816 while( mbValid && (nBytesLeft > 0) )
818 sal_uInt16 nReadSize = GetMaxRawReadSize( nBytesLeft );
819 mrStrm.SeekRel( nReadSize );
820 mnRawRecLeft = mnRawRecLeft - nReadSize;
821 nBytesLeft -= nReadSize;
822 if( nBytesLeft > 0 )
823 JumpToNextContinue();
824 DBG_ASSERT( mbValid, "XclImpStream::Ignore - record overread" );
828 // ----------------------------------------------------------------------------
830 sal_Size XclImpStream::ReadUniStringExtHeader(
831 bool& rb16Bit, bool& rbRich, bool& rbFareast,
832 sal_uInt16& rnFormatRuns, sal_uInt32& rnExtInf, sal_uInt8 nFlags )
834 DBG_ASSERT( !::get_flag( nFlags, EXC_STRF_UNKNOWN ), "XclImpStream::ReadUniStringExt - unknown flags" );
835 rb16Bit = ::get_flag( nFlags, EXC_STRF_16BIT );
836 rbRich = ::get_flag( nFlags, EXC_STRF_RICH );
837 rbFareast = ::get_flag( nFlags, EXC_STRF_FAREAST );
838 rnFormatRuns = rbRich ? ReaduInt16() : 0;
839 rnExtInf = rbFareast ? ReaduInt32() : 0;
840 return rnExtInf + 4 * rnFormatRuns;
843 sal_Size XclImpStream::ReadUniStringExtHeader( bool& rb16Bit, sal_uInt8 nFlags )
845 bool bRich, bFareast;
846 sal_uInt16 nCrun;
847 sal_uInt32 nExtInf;
848 return ReadUniStringExtHeader( rb16Bit, bRich, bFareast, nCrun, nExtInf, nFlags );
851 // ----------------------------------------------------------------------------
853 String XclImpStream::ReadRawUniString( sal_uInt16 nChars, bool b16Bit )
855 String aRet;
856 sal_uInt16 nCharsLeft = nChars;
857 sal_uInt16 nReadSize;
859 sal_Unicode* pcBuffer = new sal_Unicode[ nCharsLeft + 1 ];
861 while( IsValid() && (nCharsLeft > 0) )
863 if( b16Bit )
865 nReadSize = ::std::min< sal_uInt16 >( nCharsLeft, mnRawRecLeft / 2 );
866 DBG_ASSERT( (nReadSize <= nCharsLeft) || !(mnRawRecLeft & 0x1),
867 "XclImpStream::ReadRawUniString - missing a byte" );
869 else
870 nReadSize = GetMaxRawReadSize( nCharsLeft );
872 sal_Unicode* pcUniChar = pcBuffer;
873 sal_Unicode* pcEndChar = pcBuffer + nReadSize;
875 if( b16Bit )
877 sal_uInt16 nReadChar;
878 for( ; IsValid() && (pcUniChar < pcEndChar); ++pcUniChar )
880 operator>>( nReadChar );
881 (*pcUniChar) = (nReadChar == EXC_NUL) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
884 else
886 sal_uInt8 nReadChar;
887 for( ; IsValid() && (pcUniChar < pcEndChar); ++pcUniChar )
889 operator>>( nReadChar );
890 (*pcUniChar) = (nReadChar == EXC_NUL_C) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
894 *pcEndChar = '\0';
895 aRet.Append( pcBuffer );
897 nCharsLeft = nCharsLeft - nReadSize;
898 if( nCharsLeft > 0 )
899 JumpToNextStringContinue( b16Bit );
902 delete[] pcBuffer;
903 return aRet;
906 String XclImpStream::ReadUniString( sal_uInt16 nChars, sal_uInt8 nFlags )
908 bool b16Bit;
909 sal_Size nExtSize = ReadUniStringExtHeader( b16Bit, nFlags );
910 String aRet( ReadRawUniString( nChars, b16Bit ) );
911 Ignore( nExtSize );
912 return aRet;
915 String XclImpStream::ReadUniString( sal_uInt16 nChars )
917 return ReadUniString( nChars, ReaduInt8() );
920 String XclImpStream::ReadUniString()
922 return ReadUniString( ReaduInt16() );
925 void XclImpStream::IgnoreRawUniString( sal_uInt16 nChars, bool b16Bit )
927 sal_uInt16 nCharsLeft = nChars;
928 sal_uInt16 nReadSize;
930 while( IsValid() && (nCharsLeft > 0) )
932 if( b16Bit )
934 nReadSize = ::std::min< sal_uInt16 >( nCharsLeft, mnRawRecLeft / 2 );
935 DBG_ASSERT( (nReadSize <= nCharsLeft) || !(mnRawRecLeft & 0x1),
936 "XclImpStream::IgnoreRawUniString - missing a byte" );
937 Ignore( nReadSize * 2 );
939 else
941 nReadSize = GetMaxRawReadSize( nCharsLeft );
942 Ignore( nReadSize );
945 nCharsLeft = nCharsLeft - nReadSize;
946 if( nCharsLeft > 0 )
947 JumpToNextStringContinue( b16Bit );
951 void XclImpStream::IgnoreUniString( sal_uInt16 nChars, sal_uInt8 nFlags )
953 bool b16Bit;
954 sal_Size nExtSize = ReadUniStringExtHeader( b16Bit, nFlags );
955 IgnoreRawUniString( nChars, b16Bit );
956 Ignore( nExtSize );
959 void XclImpStream::IgnoreUniString( sal_uInt16 nChars )
961 IgnoreUniString( nChars, ReaduInt8() );
964 void XclImpStream::IgnoreUniString()
966 IgnoreUniString( ReaduInt16() );
969 // ----------------------------------------------------------------------------
971 String XclImpStream::ReadRawByteString( sal_uInt16 nChars )
973 sal_Char* pcBuffer = new sal_Char[ nChars + 1 ];
974 sal_uInt16 nCharsRead = ReadRawData( pcBuffer, nChars );
975 pcBuffer[ nCharsRead ] = '\0';
976 String aRet( pcBuffer, mrRoot.GetTextEncoding() );
977 delete[] pcBuffer;
978 return aRet;
981 String XclImpStream::ReadByteString( bool b16BitLen )
983 return ReadRawByteString( ReadByteStrLen( b16BitLen ) );
986 // private --------------------------------------------------------------------
988 void XclImpStream::StorePosition( XclImpStreamPos& rPos )
990 rPos.Set( mrStrm, mnNextRecPos, mnCurrRecSize, mnRawRecId, mnRawRecSize, mnRawRecLeft, mbValid );
993 void XclImpStream::RestorePosition( const XclImpStreamPos& rPos )
995 rPos.Get( mrStrm, mnNextRecPos, mnCurrRecSize, mnRawRecId, mnRawRecSize, mnRawRecLeft, mbValid );
996 SetupDecrypter();
999 bool XclImpStream::ReadNextRawRecHeader()
1001 mrStrm.Seek( mnNextRecPos );
1002 bool bRet = mnNextRecPos + 4 <= mnStreamSize;
1003 if( bRet )
1004 mrStrm >> mnRawRecId >> mnRawRecSize;
1005 return bRet;
1008 void XclImpStream::SetupDecrypter()
1010 if( mxDecrypter.is() )
1011 mxDecrypter->Update( mrStrm, mnRawRecSize );
1014 void XclImpStream::SetupRawRecord()
1016 // pre: mnRawRecSize contains current raw record size
1017 // pre: mrStrm points to start of raw record data
1018 mnNextRecPos = mrStrm.Tell() + mnRawRecSize;
1019 mnRawRecLeft = mnRawRecSize;
1020 mnCurrRecSize += mnRawRecSize;
1021 SetupDecrypter(); // decrypter works on raw record level
1024 void XclImpStream::SetupRecord()
1026 mnRecId = mnRawRecId;
1027 mnAltContId = EXC_ID_UNKNOWN;
1028 mnCurrRecSize = 0;
1029 mnComplRecSize = mnRawRecSize;
1030 mbHasComplRec = !mbCont;
1031 SetupRawRecord();
1032 SetNulSubstChar();
1033 EnableDecryption();
1034 StorePosition( maFirstRec );
1037 bool XclImpStream::IsContinueId( sal_uInt16 nRecId ) const
1039 return (nRecId == EXC_ID_CONT) || (nRecId == mnAltContId);
1042 bool XclImpStream::JumpToNextContinue()
1044 mbValid = mbValid && mbCont && ReadNextRawRecHeader() && IsContinueId( mnRawRecId );
1045 if( mbValid ) // do not setup a following non-CONTINUE record
1046 SetupRawRecord();
1047 return mbValid;
1050 bool XclImpStream::JumpToNextStringContinue( bool& rb16Bit )
1052 DBG_ASSERT( mnRawRecLeft == 0, "XclImpStream::JumpToNextStringContinue - unexpected garbage" );
1054 if( mbCont && (GetRecLeft() > 0) )
1056 JumpToNextContinue();
1058 else if( mnRecId == EXC_ID_CONT )
1060 // CONTINUE handling is off, but we have started reading in a CONTINUE record
1061 // -> start next CONTINUE for TXO import
1062 mbValidRec = ReadNextRawRecHeader() && ((mnRawRecId != 0) || (mnRawRecSize > 0));
1063 mbValid = mbValidRec && (mnRawRecId == EXC_ID_CONT);
1064 // we really start a new record here - no chance to return to string origin
1065 if( mbValid )
1066 SetupRecord();
1068 else
1069 mbValid = false;
1071 if( mbValid )
1072 rb16Bit = ::get_flag( ReaduInt8(), EXC_STRF_16BIT );
1073 return mbValid;
1076 bool XclImpStream::EnsureRawReadSize( sal_uInt16 nBytes )
1078 if( mbValid && nBytes )
1080 while( mbValid && !mnRawRecLeft ) JumpToNextContinue();
1081 mbValid = mbValid && (nBytes <= mnRawRecLeft);
1082 DBG_ASSERT( mbValid, "XclImpStream::EnsureRawReadSize - record overread" );
1084 return mbValid;
1087 sal_uInt16 XclImpStream::GetMaxRawReadSize( sal_Size nBytes ) const
1089 return static_cast< sal_uInt16 >( ::std::min< sal_Size >( nBytes, mnRawRecLeft ) );
1092 sal_uInt16 XclImpStream::ReadRawData( void* pData, sal_uInt16 nBytes )
1094 DBG_ASSERT( (nBytes <= mnRawRecLeft), "XclImpStream::ReadRawData - record overread" );
1095 sal_uInt16 nRet = 0;
1096 if( mbUseDecr )
1097 nRet = mxDecrypter->Read( mrStrm, pData, nBytes );
1098 else
1099 nRet = static_cast< sal_uInt16 >( mrStrm.Read( pData, nBytes ) );
1100 mnRawRecLeft = mnRawRecLeft - nRet;
1101 return nRet;
1104 // ============================================================================