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"
41 using ::rtl::OUString
;
42 using ::rtl::OUStringToOString
;
44 // ============================================================================
46 // ============================================================================
48 XclImpDecrypter::XclImpDecrypter() :
49 mnError( EXC_ENCR_ERROR_UNSUPP_CRYPT
),
50 mnOldPos( STREAM_SEEK_TO_END
),
55 XclImpDecrypter::XclImpDecrypter( const XclImpDecrypter
& rSrc
) :
56 ::comphelper::IDocPasswordVerifier(),
57 mnError( rSrc
.mnError
),
58 mnOldPos( STREAM_SEEK_TO_END
),
63 XclImpDecrypter::~XclImpDecrypter()
67 XclImpDecrypterRef
XclImpDecrypter::Clone() const
69 XclImpDecrypterRef xNewDecr
;
71 xNewDecr
.reset( OnClone() );
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
)
86 sal_Size nNewPos
= rStrm
.Tell();
87 if( (mnOldPos
!= nNewPos
) || (mnRecSize
!= nRecSize
) )
89 OnUpdate( mnOldPos
, nNewPos
, nRecSize
);
96 sal_uInt16
XclImpDecrypter::Read( SvStream
& rStrm
, void* pData
, sal_uInt16 nBytes
)
103 Update( rStrm
, mnRecSize
);
104 nRet
= OnRead( rStrm
, reinterpret_cast< sal_uInt8
* >( pData
), nBytes
);
105 mnOldPos
= rStrm
.Tell();
108 nRet
= static_cast< sal_uInt16
>( rStrm
.Read( pData
, nBytes
) );
113 // ----------------------------------------------------------------------------
115 XclImpBiff5Decrypter::XclImpBiff5Decrypter( sal_uInt16 nKey
, sal_uInt16 nHash
) :
122 XclImpBiff5Decrypter::XclImpBiff5Decrypter( const XclImpBiff5Decrypter
& rSrc
) :
123 XclImpDecrypter( rSrc
),
124 maPassword( rSrc
.maPassword
),
126 mnHash( rSrc
.mnHash
)
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
147 maPassword
.resize( 16, 0 );
148 memcpy( &maPassword
.front(), aBytePassword
.getStr(), static_cast< size_t >( nLen
) );
151 maCodec
.InitKey( &maPassword
.front() );
152 return maCodec
.VerifyKey( mnKey
, mnHash
);
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
);
170 // ----------------------------------------------------------------------------
172 XclImpBiff8Decrypter::XclImpBiff8Decrypter( sal_uInt8 pnSalt
[ 16 ],
173 sal_uInt8 pnVerifier
[ 16 ], sal_uInt8 pnVerifierHash
[ 16 ] ) :
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
)
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
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
);
212 maCodec
.InitKey( &maPassword
.front(), &maSalt
.front() );
213 return maCodec
.VerifyKey( &maVerifier
.front(), &maVerifierHash
.front() );
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
)
245 sal_uInt8
* pnCurrData
= pnData
;
246 sal_uInt16 nBytesLeft
= nBytes
;
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
;
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 // ============================================================================
278 // ============================================================================
280 XclImpStreamPos::XclImpStreamPos() :
281 mnPos( STREAM_SEEK_TO_BEGIN
),
282 mnNextPos( STREAM_SEEK_TO_BEGIN
),
284 mnRawRecId( EXC_ID_UNKNOWN
),
291 void XclImpStreamPos::Set(
292 const SvStream
& rStrm
, sal_Size nNextPos
, sal_Size nCurrSize
,
293 sal_uInt16 nRawRecId
, sal_uInt16 nRawRecSize
, sal_uInt16 nRawRecLeft
,
296 mnPos
= rStrm
.Tell();
297 mnNextPos
= nNextPos
;
298 mnCurrSize
= nCurrSize
;
299 mnRawRecId
= nRawRecId
;
300 mnRawRecSize
= nRawRecSize
;
301 mnRawRecLeft
= nRawRecLeft
;
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
311 rnNextPos
= mnNextPos
;
312 rnCurrSize
= mnCurrSize
;
313 rnRawRecId
= mnRawRecId
;
314 rnRawRecSize
= mnRawRecSize
;
315 rnRawRecLeft
= mnRawRecLeft
;
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
)
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
);
361 XclImpStream::XclImpStream( SvStream
& rInStrm
, const XclImpRoot
& rRoot
, bool bContLookup
) :
364 mnGlobRecId( EXC_ID_UNKNOWN
),
365 mbGlobValidRec( false ),
366 mbHasGlobPos( false ),
367 mnNextRecPos( STREAM_SEEK_TO_BEGIN
),
370 mbHasComplRec( false ),
371 mnRecId( EXC_ID_UNKNOWN
),
372 mnAltContId( EXC_ID_UNKNOWN
),
373 mnRawRecId( EXC_ID_UNKNOWN
),
377 mbCont( bContLookup
),
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()
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
;
417 bool XclImpStream::StartNextRecord( sal_Size nNextRecPos
)
419 mnNextRecPos
= nNextRecPos
;
420 return StartNextRecord();
423 void XclImpStream::ResetRecord( bool bContLookup
, sal_uInt16 nAltContId
)
428 RestorePosition( maFirstRec
);
429 mnCurrRecSize
= mnComplRecSize
= mnRawRecSize
;
430 mbHasComplRec
= !bContLookup
;
431 mbCont
= bContLookup
;
432 mnAltContId
= nAltContId
;
437 void XclImpStream::SetDecrypter( XclImpDecrypterRef xDecrypter
)
439 mxDecrypter
= xDecrypter
;
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()
482 //UNUSED2008-05 DBG_ASSERT( !maPosStack.empty(), "XclImpStream::RejectPosition - stack empty" );
483 //UNUSED2008-05 if( !maPosStack.empty() )
484 //UNUSED2008-05 maPosStack.pop_back();
487 void XclImpStream::StoreGlobalPosition()
489 StorePosition( maGlobPos
);
490 mnGlobRecId
= mnRecId
;
491 mbGlobValidRec
= mbValidRec
;
495 void XclImpStream::SeekGlobalPosition()
497 DBG_ASSERT( mbHasGlobPos
, "XclImpStream::SeekGlobalPosition - no position stored" );
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()
518 while( JumpToNextContinue() ) ; // JumpToNextContinue() adds up mnCurrRecSize
519 mnComplRecSize
= mnCurrRecSize
;
520 mbHasComplRec
= true;
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
;
537 while( JumpToNextContinue() ) ; // skip following CONTINUE records
538 if( mnNextRecPos
< mnStreamSize
)
540 mrStrm
.Seek( mnNextRecPos
);
548 // ----------------------------------------------------------------------------
550 XclImpStream
& XclImpStream::operator>>( sal_Int8
& rnValue
)
552 if( EnsureRawReadSize( 1 ) )
555 mxDecrypter
->Read( mrStrm
, &rnValue
, 1 );
563 XclImpStream
& XclImpStream::operator>>( sal_uInt8
& rnValue
)
565 if( EnsureRawReadSize( 1 ) )
568 mxDecrypter
->Read( mrStrm
, &rnValue
, 1 );
576 XclImpStream
& XclImpStream::operator>>( sal_Int16
& rnValue
)
578 if( EnsureRawReadSize( 2 ) )
583 mxDecrypter
->Read( mrStrm
, pnBuffer
, 2 );
584 rnValue
= static_cast< sal_Int16
>( SVBT16ToShort( pnBuffer
) );
593 XclImpStream
& XclImpStream::operator>>( sal_uInt16
& rnValue
)
595 if( EnsureRawReadSize( 2 ) )
600 mxDecrypter
->Read( mrStrm
, pnBuffer
, 2 );
601 rnValue
= SVBT16ToShort( pnBuffer
);
610 XclImpStream
& XclImpStream::operator>>( sal_Int32
& rnValue
)
612 if( EnsureRawReadSize( 4 ) )
617 mxDecrypter
->Read( mrStrm
, pnBuffer
, 4 );
618 rnValue
= static_cast< sal_Int32
>( SVBT32ToUInt32( pnBuffer
) );
627 XclImpStream
& XclImpStream::operator>>( sal_uInt32
& rnValue
)
629 if( EnsureRawReadSize( 4 ) )
634 mxDecrypter
->Read( mrStrm
, pnBuffer
, 4 );
635 rnValue
= SVBT32ToUInt32( pnBuffer
);
644 XclImpStream
& XclImpStream::operator>>( float& rfValue
)
646 if( EnsureRawReadSize( 4 ) )
651 mxDecrypter
->Read( mrStrm
, pnBuffer
, 4 );
652 sal_uInt32 nValue
= SVBT32ToUInt32( pnBuffer
);
653 memcpy( &rfValue
, &nValue
, 4 );
662 XclImpStream
& XclImpStream::operator>>( double& rfValue
)
664 if( EnsureRawReadSize( 8 ) )
669 mxDecrypter
->Read( mrStrm
, pnBuffer
, 8 );
670 rfValue
= SVBT64ToDouble( pnBuffer
);
679 sal_Int8
XclImpStream::ReadInt8()
682 operator>>( nValue
);
686 sal_uInt8
XclImpStream::ReaduInt8()
689 operator>>( nValue
);
693 sal_Int16
XclImpStream::ReadInt16()
696 operator>>( nValue
);
700 sal_uInt16
XclImpStream::ReaduInt16()
703 operator>>( nValue
);
707 sal_Int32
XclImpStream::ReadInt32()
710 operator>>( nValue
);
714 sal_uInt32
XclImpStream::ReaduInt32()
717 operator>>( nValue
);
721 float XclImpStream::ReadFloat()
724 operator>>( fValue
);
728 double XclImpStream::ReadDouble()
731 operator>>( fValue
);
735 sal_Size
XclImpStream::Read( void* pData
, sal_Size nBytes
)
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
);
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" );
760 sal_Size
XclImpStream::CopyToStream( SvStream
& rOutStrm
, sal_Size nBytes
)
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
;
782 sal_Size
XclImpStream::CopyRecordToStream( SvStream
& rOutStrm
)
788 RestorePosition( maFirstRec
);
789 nRet
= CopyToStream( rOutStrm
, GetRecSize() );
795 void XclImpStream::Seek( sal_Size nPos
)
799 sal_Size nCurrPos
= GetRecPos();
800 if( !mbValid
|| (nPos
< nCurrPos
) ) // from invalid state or backward
802 RestorePosition( maFirstRec
);
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
;
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
;
848 return ReadUniStringExtHeader( rb16Bit
, bRich
, bFareast
, nCrun
, nExtInf
, nFlags
);
851 // ----------------------------------------------------------------------------
853 String
XclImpStream::ReadRawUniString( sal_uInt16 nChars
, bool b16Bit
)
856 sal_uInt16 nCharsLeft
= nChars
;
857 sal_uInt16 nReadSize
;
859 sal_Unicode
* pcBuffer
= new sal_Unicode
[ nCharsLeft
+ 1 ];
861 while( IsValid() && (nCharsLeft
> 0) )
865 nReadSize
= ::std::min
< sal_uInt16
>( nCharsLeft
, mnRawRecLeft
/ 2 );
866 DBG_ASSERT( (nReadSize
<= nCharsLeft
) || !(mnRawRecLeft
& 0x1),
867 "XclImpStream::ReadRawUniString - missing a byte" );
870 nReadSize
= GetMaxRawReadSize( nCharsLeft
);
872 sal_Unicode
* pcUniChar
= pcBuffer
;
873 sal_Unicode
* pcEndChar
= pcBuffer
+ nReadSize
;
877 sal_uInt16 nReadChar
;
878 for( ; IsValid() && (pcUniChar
< pcEndChar
); ++pcUniChar
)
880 operator>>( nReadChar
);
881 (*pcUniChar
) = (nReadChar
== EXC_NUL
) ? mcNulSubst
: static_cast< sal_Unicode
>( nReadChar
);
887 for( ; IsValid() && (pcUniChar
< pcEndChar
); ++pcUniChar
)
889 operator>>( nReadChar
);
890 (*pcUniChar
) = (nReadChar
== EXC_NUL_C
) ? mcNulSubst
: static_cast< sal_Unicode
>( nReadChar
);
895 aRet
.Append( pcBuffer
);
897 nCharsLeft
= nCharsLeft
- nReadSize
;
899 JumpToNextStringContinue( b16Bit
);
906 String
XclImpStream::ReadUniString( sal_uInt16 nChars
, sal_uInt8 nFlags
)
909 sal_Size nExtSize
= ReadUniStringExtHeader( b16Bit
, nFlags
);
910 String
aRet( ReadRawUniString( nChars
, b16Bit
) );
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) )
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 );
941 nReadSize
= GetMaxRawReadSize( nCharsLeft
);
945 nCharsLeft
= nCharsLeft
- nReadSize
;
947 JumpToNextStringContinue( b16Bit
);
951 void XclImpStream::IgnoreUniString( sal_uInt16 nChars
, sal_uInt8 nFlags
)
954 sal_Size nExtSize
= ReadUniStringExtHeader( b16Bit
, nFlags
);
955 IgnoreRawUniString( nChars
, b16Bit
);
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() );
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
);
999 bool XclImpStream::ReadNextRawRecHeader()
1001 mrStrm
.Seek( mnNextRecPos
);
1002 bool bRet
= mnNextRecPos
+ 4 <= mnStreamSize
;
1004 mrStrm
>> mnRawRecId
>> mnRawRecSize
;
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
;
1029 mnComplRecSize
= mnRawRecSize
;
1030 mbHasComplRec
= !mbCont
;
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
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
1072 rb16Bit
= ::get_flag( ReaduInt8(), EXC_STRF_16BIT
);
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" );
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;
1097 nRet
= mxDecrypter
->Read( mrStrm
, pData
, nBytes
);
1099 nRet
= static_cast< sal_uInt16
>( mrStrm
.Read( pData
, nBytes
) );
1100 mnRawRecLeft
= mnRawRecLeft
- nRet
;
1104 // ============================================================================