update dev300-m58
[ooovba.git] / sc / source / filter / excel / xistream.cxx
blobb168c4389c4c6fbcd3d0565dff28a853dffe4ad2
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 void XclImpStream::ResetRecord( bool bContLookup, sal_uInt16 nAltContId )
419 if( mbValidRec )
421 maPosStack.clear();
422 RestorePosition( maFirstRec );
423 mnCurrRecSize = mnComplRecSize = mnRawRecSize;
424 mbHasComplRec = !bContLookup;
425 mbCont = bContLookup;
426 mnAltContId = nAltContId;
427 EnableDecryption();
431 void XclImpStream::SetDecrypter( XclImpDecrypterRef xDecrypter )
433 mxDecrypter = xDecrypter;
434 EnableDecryption();
435 SetupDecrypter();
438 void XclImpStream::CopyDecrypterFrom( const XclImpStream& rStrm )
440 XclImpDecrypterRef xNewDecr;
441 if( rStrm.mxDecrypter.is() )
442 xNewDecr = rStrm.mxDecrypter->Clone();
443 SetDecrypter( xNewDecr );
446 bool XclImpStream::HasValidDecrypter() const
448 return mxDecrypter.is() && mxDecrypter->IsValid();
451 void XclImpStream::EnableDecryption( bool bEnable )
453 mbUseDecr = bEnable && HasValidDecrypter();
456 // ----------------------------------------------------------------------------
458 void XclImpStream::PushPosition()
460 maPosStack.push_back( XclImpStreamPos() );
461 StorePosition( maPosStack.back() );
464 void XclImpStream::PopPosition()
466 DBG_ASSERT( !maPosStack.empty(), "XclImpStream::PopPosition - stack empty" );
467 if( !maPosStack.empty() )
469 RestorePosition( maPosStack.back() );
470 maPosStack.pop_back();
474 //UNUSED2008-05 void XclImpStream::RejectPosition()
475 //UNUSED2008-05 {
476 //UNUSED2008-05 DBG_ASSERT( !maPosStack.empty(), "XclImpStream::RejectPosition - stack empty" );
477 //UNUSED2008-05 if( !maPosStack.empty() )
478 //UNUSED2008-05 maPosStack.pop_back();
479 //UNUSED2008-05 }
481 void XclImpStream::StoreGlobalPosition()
483 StorePosition( maGlobPos );
484 mnGlobRecId = mnRecId;
485 mbGlobValidRec = mbValidRec;
486 mbHasGlobPos = true;
489 void XclImpStream::SeekGlobalPosition()
491 DBG_ASSERT( mbHasGlobPos, "XclImpStream::SeekGlobalPosition - no position stored" );
492 if( mbHasGlobPos )
494 RestorePosition( maGlobPos );
495 mnRecId = mnGlobRecId;
496 mnComplRecSize = mnCurrRecSize;
497 mbHasComplRec = !mbCont;
498 mbValidRec = mbGlobValidRec;
502 sal_Size XclImpStream::GetRecPos() const
504 return mbValid ? (mnCurrRecSize - mnRawRecLeft) : EXC_REC_SEEK_TO_END;
507 sal_Size XclImpStream::GetRecSize()
509 if( !mbHasComplRec )
511 PushPosition();
512 while( JumpToNextContinue() ) ; // JumpToNextContinue() adds up mnCurrRecSize
513 mnComplRecSize = mnCurrRecSize;
514 mbHasComplRec = true;
515 PopPosition();
517 return mnComplRecSize;
520 sal_Size XclImpStream::GetRecLeft()
522 return mbValid ? (GetRecSize() - GetRecPos()) : 0;
525 sal_uInt16 XclImpStream::GetNextRecId()
527 sal_uInt16 nRecId = EXC_ID_UNKNOWN;
528 if( mbValidRec )
530 PushPosition();
531 while( JumpToNextContinue() ) ; // skip following CONTINUE records
532 if( mnNextRecPos < mnStreamSize )
534 mrStrm.Seek( mnNextRecPos );
535 mrStrm >> nRecId;
537 PopPosition();
539 return nRecId;
542 // ----------------------------------------------------------------------------
544 XclImpStream& XclImpStream::operator>>( sal_Int8& rnValue )
546 if( EnsureRawReadSize( 1 ) )
548 if( mbUseDecr )
549 mxDecrypter->Read( mrStrm, &rnValue, 1 );
550 else
551 mrStrm >> rnValue;
552 --mnRawRecLeft;
554 return *this;
557 XclImpStream& XclImpStream::operator>>( sal_uInt8& rnValue )
559 if( EnsureRawReadSize( 1 ) )
561 if( mbUseDecr )
562 mxDecrypter->Read( mrStrm, &rnValue, 1 );
563 else
564 mrStrm >> rnValue;
565 --mnRawRecLeft;
567 return *this;
570 XclImpStream& XclImpStream::operator>>( sal_Int16& rnValue )
572 if( EnsureRawReadSize( 2 ) )
574 if( mbUseDecr )
576 SVBT16 pnBuffer;
577 mxDecrypter->Read( mrStrm, pnBuffer, 2 );
578 rnValue = static_cast< sal_Int16 >( SVBT16ToShort( pnBuffer ) );
580 else
581 mrStrm >> rnValue;
582 mnRawRecLeft -= 2;
584 return *this;
587 XclImpStream& XclImpStream::operator>>( sal_uInt16& rnValue )
589 if( EnsureRawReadSize( 2 ) )
591 if( mbUseDecr )
593 SVBT16 pnBuffer;
594 mxDecrypter->Read( mrStrm, pnBuffer, 2 );
595 rnValue = SVBT16ToShort( pnBuffer );
597 else
598 mrStrm >> rnValue;
599 mnRawRecLeft -= 2;
601 return *this;
604 XclImpStream& XclImpStream::operator>>( sal_Int32& rnValue )
606 if( EnsureRawReadSize( 4 ) )
608 if( mbUseDecr )
610 SVBT32 pnBuffer;
611 mxDecrypter->Read( mrStrm, pnBuffer, 4 );
612 rnValue = static_cast< sal_Int32 >( SVBT32ToUInt32( pnBuffer ) );
614 else
615 mrStrm >> rnValue;
616 mnRawRecLeft -= 4;
618 return *this;
621 XclImpStream& XclImpStream::operator>>( sal_uInt32& rnValue )
623 if( EnsureRawReadSize( 4 ) )
625 if( mbUseDecr )
627 SVBT32 pnBuffer;
628 mxDecrypter->Read( mrStrm, pnBuffer, 4 );
629 rnValue = SVBT32ToUInt32( pnBuffer );
631 else
632 mrStrm >> rnValue;
633 mnRawRecLeft -= 4;
635 return *this;
638 XclImpStream& XclImpStream::operator>>( float& rfValue )
640 if( EnsureRawReadSize( 4 ) )
642 if( mbUseDecr )
644 SVBT32 pnBuffer;
645 mxDecrypter->Read( mrStrm, pnBuffer, 4 );
646 sal_uInt32 nValue = SVBT32ToUInt32( pnBuffer );
647 memcpy( &rfValue, &nValue, 4 );
649 else
650 mrStrm >> rfValue;
651 mnRawRecLeft -= 4;
653 return *this;
656 XclImpStream& XclImpStream::operator>>( double& rfValue )
658 if( EnsureRawReadSize( 8 ) )
660 if( mbUseDecr )
662 SVBT64 pnBuffer;
663 mxDecrypter->Read( mrStrm, pnBuffer, 8 );
664 rfValue = SVBT64ToDouble( pnBuffer );
666 else
667 mrStrm >> rfValue;
668 mnRawRecLeft -= 8;
670 return *this;
673 sal_Int8 XclImpStream::ReadInt8()
675 sal_Int8 nValue;
676 operator>>( nValue );
677 return nValue;
680 sal_uInt8 XclImpStream::ReaduInt8()
682 sal_uInt8 nValue;
683 operator>>( nValue );
684 return nValue;
687 sal_Int16 XclImpStream::ReadInt16()
689 sal_Int16 nValue;
690 operator>>( nValue );
691 return nValue;
694 sal_uInt16 XclImpStream::ReaduInt16()
696 sal_uInt16 nValue;
697 operator>>( nValue );
698 return nValue;
701 sal_Int32 XclImpStream::ReadInt32()
703 sal_Int32 nValue;
704 operator>>( nValue );
705 return nValue;
708 sal_uInt32 XclImpStream::ReaduInt32()
710 sal_uInt32 nValue;
711 operator>>( nValue );
712 return nValue;
715 float XclImpStream::ReadFloat()
717 float fValue;
718 operator>>( fValue );
719 return fValue;
722 double XclImpStream::ReadDouble()
724 double fValue;
725 operator>>( fValue );
726 return fValue;
729 sal_Size XclImpStream::Read( void* pData, sal_Size nBytes )
731 sal_Size nRet = 0;
732 if( mbValid && pData && (nBytes > 0) )
734 sal_uInt8* pnBuffer = reinterpret_cast< sal_uInt8* >( pData );
735 sal_Size nBytesLeft = nBytes;
737 while( mbValid && (nBytesLeft > 0) )
739 sal_uInt16 nReadSize = GetMaxRawReadSize( nBytesLeft );
740 sal_uInt16 nReadRet = ReadRawData( pnBuffer, nReadSize );
741 nRet += nReadRet;
742 mbValid = (nReadSize == nReadRet);
743 DBG_ASSERT( mbValid, "XclImpStream::Read - stream read error" );
744 pnBuffer += nReadRet;
745 nBytesLeft -= nReadRet;
746 if( mbValid && (nBytesLeft > 0) )
747 JumpToNextContinue();
748 DBG_ASSERT( mbValid, "XclImpStream::Read - record overread" );
751 return nRet;
754 sal_Size XclImpStream::CopyToStream( SvStream& rOutStrm, sal_Size nBytes )
756 sal_Size nRet = 0;
757 if( mbValid && (nBytes > 0) )
759 const sal_Size nMaxBuffer = 4096;
760 sal_uInt8* pnBuffer = new sal_uInt8[ ::std::min( nBytes, nMaxBuffer ) ];
761 sal_Size nBytesLeft = nBytes;
763 while( mbValid && (nBytesLeft > 0) )
765 sal_Size nReadSize = ::std::min( nBytesLeft, nMaxBuffer );
766 nRet += Read( pnBuffer, nReadSize );
767 rOutStrm.Write( pnBuffer, nReadSize );
768 nBytesLeft -= nReadSize;
771 delete[] pnBuffer;
773 return nRet;
776 sal_Size XclImpStream::CopyRecordToStream( SvStream& rOutStrm )
778 sal_Size nRet = 0;
779 if( mbValidRec )
781 PushPosition();
782 RestorePosition( maFirstRec );
783 nRet = CopyToStream( rOutStrm, GetRecSize() );
784 PopPosition();
786 return nRet;
789 void XclImpStream::Seek( sal_Size nPos )
791 if( mbValidRec )
793 sal_Size nCurrPos = GetRecPos();
794 if( !mbValid || (nPos < nCurrPos) ) // from invalid state or backward
796 RestorePosition( maFirstRec );
797 Ignore( nPos );
799 else if( nPos > nCurrPos ) // forward
801 Ignore( nPos - nCurrPos );
806 void XclImpStream::Ignore( sal_Size nBytes )
808 // implementation similar to Read(), but without really reading anything
809 sal_Size nBytesLeft = nBytes;
810 while( mbValid && (nBytesLeft > 0) )
812 sal_uInt16 nReadSize = GetMaxRawReadSize( nBytesLeft );
813 mrStrm.SeekRel( nReadSize );
814 mnRawRecLeft = mnRawRecLeft - nReadSize;
815 nBytesLeft -= nReadSize;
816 if( nBytesLeft > 0 )
817 JumpToNextContinue();
818 DBG_ASSERT( mbValid, "XclImpStream::Ignore - record overread" );
822 // ----------------------------------------------------------------------------
824 sal_Size XclImpStream::ReadUniStringExtHeader(
825 bool& rb16Bit, bool& rbRich, bool& rbFareast,
826 sal_uInt16& rnFormatRuns, sal_uInt32& rnExtInf, sal_uInt8 nFlags )
828 DBG_ASSERT( !::get_flag( nFlags, EXC_STRF_UNKNOWN ), "XclImpStream::ReadUniStringExt - unknown flags" );
829 rb16Bit = ::get_flag( nFlags, EXC_STRF_16BIT );
830 rbRich = ::get_flag( nFlags, EXC_STRF_RICH );
831 rbFareast = ::get_flag( nFlags, EXC_STRF_FAREAST );
832 rnFormatRuns = rbRich ? ReaduInt16() : 0;
833 rnExtInf = rbFareast ? ReaduInt32() : 0;
834 return rnExtInf + 4 * rnFormatRuns;
837 sal_Size XclImpStream::ReadUniStringExtHeader( bool& rb16Bit, sal_uInt8 nFlags )
839 bool bRich, bFareast;
840 sal_uInt16 nCrun;
841 sal_uInt32 nExtInf;
842 return ReadUniStringExtHeader( rb16Bit, bRich, bFareast, nCrun, nExtInf, nFlags );
845 // ----------------------------------------------------------------------------
847 String XclImpStream::ReadRawUniString( sal_uInt16 nChars, bool b16Bit )
849 String aRet;
850 sal_uInt16 nCharsLeft = nChars;
851 sal_uInt16 nReadSize;
853 sal_Unicode* pcBuffer = new sal_Unicode[ nCharsLeft + 1 ];
855 while( IsValid() && (nCharsLeft > 0) )
857 if( b16Bit )
859 nReadSize = ::std::min< sal_uInt16 >( nCharsLeft, mnRawRecLeft / 2 );
860 DBG_ASSERT( (nReadSize <= nCharsLeft) || !(mnRawRecLeft & 0x1),
861 "XclImpStream::ReadRawUniString - missing a byte" );
863 else
864 nReadSize = GetMaxRawReadSize( nCharsLeft );
866 sal_Unicode* pcUniChar = pcBuffer;
867 sal_Unicode* pcEndChar = pcBuffer + nReadSize;
869 if( b16Bit )
871 sal_uInt16 nReadChar;
872 for( ; IsValid() && (pcUniChar < pcEndChar); ++pcUniChar )
874 operator>>( nReadChar );
875 (*pcUniChar) = (nReadChar == EXC_NUL) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
878 else
880 sal_uInt8 nReadChar;
881 for( ; IsValid() && (pcUniChar < pcEndChar); ++pcUniChar )
883 operator>>( nReadChar );
884 (*pcUniChar) = (nReadChar == EXC_NUL_C) ? mcNulSubst : static_cast< sal_Unicode >( nReadChar );
888 *pcEndChar = '\0';
889 aRet.Append( pcBuffer );
891 nCharsLeft = nCharsLeft - nReadSize;
892 if( nCharsLeft > 0 )
893 JumpToNextStringContinue( b16Bit );
896 delete[] pcBuffer;
897 return aRet;
900 String XclImpStream::ReadUniString( sal_uInt16 nChars, sal_uInt8 nFlags )
902 bool b16Bit;
903 sal_Size nExtSize = ReadUniStringExtHeader( b16Bit, nFlags );
904 String aRet( ReadRawUniString( nChars, b16Bit ) );
905 Ignore( nExtSize );
906 return aRet;
909 String XclImpStream::ReadUniString( sal_uInt16 nChars )
911 return ReadUniString( nChars, ReaduInt8() );
914 String XclImpStream::ReadUniString()
916 return ReadUniString( ReaduInt16() );
919 void XclImpStream::IgnoreRawUniString( sal_uInt16 nChars, bool b16Bit )
921 sal_uInt16 nCharsLeft = nChars;
922 sal_uInt16 nReadSize;
924 while( IsValid() && (nCharsLeft > 0) )
926 if( b16Bit )
928 nReadSize = ::std::min< sal_uInt16 >( nCharsLeft, mnRawRecLeft / 2 );
929 DBG_ASSERT( (nReadSize <= nCharsLeft) || !(mnRawRecLeft & 0x1),
930 "XclImpStream::IgnoreRawUniString - missing a byte" );
931 Ignore( nReadSize * 2 );
933 else
935 nReadSize = GetMaxRawReadSize( nCharsLeft );
936 Ignore( nReadSize );
939 nCharsLeft = nCharsLeft - nReadSize;
940 if( nCharsLeft > 0 )
941 JumpToNextStringContinue( b16Bit );
945 void XclImpStream::IgnoreUniString( sal_uInt16 nChars, sal_uInt8 nFlags )
947 bool b16Bit;
948 sal_Size nExtSize = ReadUniStringExtHeader( b16Bit, nFlags );
949 IgnoreRawUniString( nChars, b16Bit );
950 Ignore( nExtSize );
953 void XclImpStream::IgnoreUniString( sal_uInt16 nChars )
955 IgnoreUniString( nChars, ReaduInt8() );
958 void XclImpStream::IgnoreUniString()
960 IgnoreUniString( ReaduInt16() );
963 // ----------------------------------------------------------------------------
965 String XclImpStream::ReadRawByteString( sal_uInt16 nChars )
967 sal_Char* pcBuffer = new sal_Char[ nChars + 1 ];
968 sal_uInt16 nCharsRead = ReadRawData( pcBuffer, nChars );
969 pcBuffer[ nCharsRead ] = '\0';
970 String aRet( pcBuffer, mrRoot.GetTextEncoding() );
971 delete[] pcBuffer;
972 return aRet;
975 String XclImpStream::ReadByteString( bool b16BitLen )
977 return ReadRawByteString( ReadByteStrLen( b16BitLen ) );
980 // private --------------------------------------------------------------------
982 void XclImpStream::StorePosition( XclImpStreamPos& rPos )
984 rPos.Set( mrStrm, mnNextRecPos, mnCurrRecSize, mnRawRecId, mnRawRecSize, mnRawRecLeft, mbValid );
987 void XclImpStream::RestorePosition( const XclImpStreamPos& rPos )
989 rPos.Get( mrStrm, mnNextRecPos, mnCurrRecSize, mnRawRecId, mnRawRecSize, mnRawRecLeft, mbValid );
990 SetupDecrypter();
993 bool XclImpStream::ReadNextRawRecHeader()
995 mrStrm.Seek( mnNextRecPos );
996 bool bRet = mnNextRecPos + 4 <= mnStreamSize;
997 if( bRet )
998 mrStrm >> mnRawRecId >> mnRawRecSize;
999 return bRet;
1002 void XclImpStream::SetupDecrypter()
1004 if( mxDecrypter.is() )
1005 mxDecrypter->Update( mrStrm, mnRawRecSize );
1008 void XclImpStream::SetupRawRecord()
1010 // pre: mnRawRecSize contains current raw record size
1011 // pre: mrStrm points to start of raw record data
1012 mnNextRecPos = mrStrm.Tell() + mnRawRecSize;
1013 mnRawRecLeft = mnRawRecSize;
1014 mnCurrRecSize += mnRawRecSize;
1015 SetupDecrypter(); // decrypter works on raw record level
1018 void XclImpStream::SetupRecord()
1020 mnRecId = mnRawRecId;
1021 mnAltContId = EXC_ID_UNKNOWN;
1022 mnCurrRecSize = 0;
1023 mnComplRecSize = mnRawRecSize;
1024 mbHasComplRec = !mbCont;
1025 SetupRawRecord();
1026 SetNulSubstChar();
1027 EnableDecryption();
1028 StorePosition( maFirstRec );
1031 bool XclImpStream::IsContinueId( sal_uInt16 nRecId ) const
1033 return (nRecId == EXC_ID_CONT) || (nRecId == mnAltContId);
1036 bool XclImpStream::JumpToNextContinue()
1038 mbValid = mbValid && mbCont && ReadNextRawRecHeader() && IsContinueId( mnRawRecId );
1039 if( mbValid ) // do not setup a following non-CONTINUE record
1040 SetupRawRecord();
1041 return mbValid;
1044 bool XclImpStream::JumpToNextStringContinue( bool& rb16Bit )
1046 DBG_ASSERT( mnRawRecLeft == 0, "XclImpStream::JumpToNextStringContinue - unexpected garbage" );
1048 if( mbCont && (GetRecLeft() > 0) )
1050 JumpToNextContinue();
1052 else if( mnRecId == EXC_ID_CONT )
1054 // CONTINUE handling is off, but we have started reading in a CONTINUE record
1055 // -> start next CONTINUE for TXO import
1056 mbValidRec = ReadNextRawRecHeader() && ((mnRawRecId != 0) || (mnRawRecSize > 0));
1057 mbValid = mbValidRec && (mnRawRecId == EXC_ID_CONT);
1058 // we really start a new record here - no chance to return to string origin
1059 if( mbValid )
1060 SetupRecord();
1062 else
1063 mbValid = false;
1065 if( mbValid )
1066 rb16Bit = ::get_flag( ReaduInt8(), EXC_STRF_16BIT );
1067 return mbValid;
1070 bool XclImpStream::EnsureRawReadSize( sal_uInt16 nBytes )
1072 if( mbValid && nBytes )
1074 while( mbValid && !mnRawRecLeft ) JumpToNextContinue();
1075 mbValid = mbValid && (nBytes <= mnRawRecLeft);
1076 DBG_ASSERT( mbValid, "XclImpStream::EnsureRawReadSize - record overread" );
1078 return mbValid;
1081 sal_uInt16 XclImpStream::GetMaxRawReadSize( sal_Size nBytes ) const
1083 return static_cast< sal_uInt16 >( ::std::min< sal_Size >( nBytes, mnRawRecLeft ) );
1086 sal_uInt16 XclImpStream::ReadRawData( void* pData, sal_uInt16 nBytes )
1088 DBG_ASSERT( (nBytes <= mnRawRecLeft), "XclImpStream::ReadRawData - record overread" );
1089 sal_uInt16 nRet = 0;
1090 if( mbUseDecr )
1091 nRet = mxDecrypter->Read( mrStrm, pData, nBytes );
1092 else
1093 nRet = static_cast< sal_uInt16 >( mrStrm.Read( pData, nBytes ) );
1094 mnRawRecLeft = mnRawRecLeft - nRet;
1095 return nRet;
1098 // ============================================================================