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 void XclImpStream::ResetRecord( bool bContLookup
, sal_uInt16 nAltContId
)
422 RestorePosition( maFirstRec
);
423 mnCurrRecSize
= mnComplRecSize
= mnRawRecSize
;
424 mbHasComplRec
= !bContLookup
;
425 mbCont
= bContLookup
;
426 mnAltContId
= nAltContId
;
431 void XclImpStream::SetDecrypter( XclImpDecrypterRef xDecrypter
)
433 mxDecrypter
= xDecrypter
;
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()
476 //UNUSED2008-05 DBG_ASSERT( !maPosStack.empty(), "XclImpStream::RejectPosition - stack empty" );
477 //UNUSED2008-05 if( !maPosStack.empty() )
478 //UNUSED2008-05 maPosStack.pop_back();
481 void XclImpStream::StoreGlobalPosition()
483 StorePosition( maGlobPos
);
484 mnGlobRecId
= mnRecId
;
485 mbGlobValidRec
= mbValidRec
;
489 void XclImpStream::SeekGlobalPosition()
491 DBG_ASSERT( mbHasGlobPos
, "XclImpStream::SeekGlobalPosition - no position stored" );
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()
512 while( JumpToNextContinue() ) ; // JumpToNextContinue() adds up mnCurrRecSize
513 mnComplRecSize
= mnCurrRecSize
;
514 mbHasComplRec
= true;
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
;
531 while( JumpToNextContinue() ) ; // skip following CONTINUE records
532 if( mnNextRecPos
< mnStreamSize
)
534 mrStrm
.Seek( mnNextRecPos
);
542 // ----------------------------------------------------------------------------
544 XclImpStream
& XclImpStream::operator>>( sal_Int8
& rnValue
)
546 if( EnsureRawReadSize( 1 ) )
549 mxDecrypter
->Read( mrStrm
, &rnValue
, 1 );
557 XclImpStream
& XclImpStream::operator>>( sal_uInt8
& rnValue
)
559 if( EnsureRawReadSize( 1 ) )
562 mxDecrypter
->Read( mrStrm
, &rnValue
, 1 );
570 XclImpStream
& XclImpStream::operator>>( sal_Int16
& rnValue
)
572 if( EnsureRawReadSize( 2 ) )
577 mxDecrypter
->Read( mrStrm
, pnBuffer
, 2 );
578 rnValue
= static_cast< sal_Int16
>( SVBT16ToShort( pnBuffer
) );
587 XclImpStream
& XclImpStream::operator>>( sal_uInt16
& rnValue
)
589 if( EnsureRawReadSize( 2 ) )
594 mxDecrypter
->Read( mrStrm
, pnBuffer
, 2 );
595 rnValue
= SVBT16ToShort( pnBuffer
);
604 XclImpStream
& XclImpStream::operator>>( sal_Int32
& rnValue
)
606 if( EnsureRawReadSize( 4 ) )
611 mxDecrypter
->Read( mrStrm
, pnBuffer
, 4 );
612 rnValue
= static_cast< sal_Int32
>( SVBT32ToUInt32( pnBuffer
) );
621 XclImpStream
& XclImpStream::operator>>( sal_uInt32
& rnValue
)
623 if( EnsureRawReadSize( 4 ) )
628 mxDecrypter
->Read( mrStrm
, pnBuffer
, 4 );
629 rnValue
= SVBT32ToUInt32( pnBuffer
);
638 XclImpStream
& XclImpStream::operator>>( float& rfValue
)
640 if( EnsureRawReadSize( 4 ) )
645 mxDecrypter
->Read( mrStrm
, pnBuffer
, 4 );
646 sal_uInt32 nValue
= SVBT32ToUInt32( pnBuffer
);
647 memcpy( &rfValue
, &nValue
, 4 );
656 XclImpStream
& XclImpStream::operator>>( double& rfValue
)
658 if( EnsureRawReadSize( 8 ) )
663 mxDecrypter
->Read( mrStrm
, pnBuffer
, 8 );
664 rfValue
= SVBT64ToDouble( pnBuffer
);
673 sal_Int8
XclImpStream::ReadInt8()
676 operator>>( nValue
);
680 sal_uInt8
XclImpStream::ReaduInt8()
683 operator>>( nValue
);
687 sal_Int16
XclImpStream::ReadInt16()
690 operator>>( nValue
);
694 sal_uInt16
XclImpStream::ReaduInt16()
697 operator>>( nValue
);
701 sal_Int32
XclImpStream::ReadInt32()
704 operator>>( nValue
);
708 sal_uInt32
XclImpStream::ReaduInt32()
711 operator>>( nValue
);
715 float XclImpStream::ReadFloat()
718 operator>>( fValue
);
722 double XclImpStream::ReadDouble()
725 operator>>( fValue
);
729 sal_Size
XclImpStream::Read( void* pData
, sal_Size nBytes
)
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
);
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" );
754 sal_Size
XclImpStream::CopyToStream( SvStream
& rOutStrm
, sal_Size nBytes
)
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
;
776 sal_Size
XclImpStream::CopyRecordToStream( SvStream
& rOutStrm
)
782 RestorePosition( maFirstRec
);
783 nRet
= CopyToStream( rOutStrm
, GetRecSize() );
789 void XclImpStream::Seek( sal_Size nPos
)
793 sal_Size nCurrPos
= GetRecPos();
794 if( !mbValid
|| (nPos
< nCurrPos
) ) // from invalid state or backward
796 RestorePosition( maFirstRec
);
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
;
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
;
842 return ReadUniStringExtHeader( rb16Bit
, bRich
, bFareast
, nCrun
, nExtInf
, nFlags
);
845 // ----------------------------------------------------------------------------
847 String
XclImpStream::ReadRawUniString( sal_uInt16 nChars
, bool b16Bit
)
850 sal_uInt16 nCharsLeft
= nChars
;
851 sal_uInt16 nReadSize
;
853 sal_Unicode
* pcBuffer
= new sal_Unicode
[ nCharsLeft
+ 1 ];
855 while( IsValid() && (nCharsLeft
> 0) )
859 nReadSize
= ::std::min
< sal_uInt16
>( nCharsLeft
, mnRawRecLeft
/ 2 );
860 DBG_ASSERT( (nReadSize
<= nCharsLeft
) || !(mnRawRecLeft
& 0x1),
861 "XclImpStream::ReadRawUniString - missing a byte" );
864 nReadSize
= GetMaxRawReadSize( nCharsLeft
);
866 sal_Unicode
* pcUniChar
= pcBuffer
;
867 sal_Unicode
* pcEndChar
= pcBuffer
+ nReadSize
;
871 sal_uInt16 nReadChar
;
872 for( ; IsValid() && (pcUniChar
< pcEndChar
); ++pcUniChar
)
874 operator>>( nReadChar
);
875 (*pcUniChar
) = (nReadChar
== EXC_NUL
) ? mcNulSubst
: static_cast< sal_Unicode
>( nReadChar
);
881 for( ; IsValid() && (pcUniChar
< pcEndChar
); ++pcUniChar
)
883 operator>>( nReadChar
);
884 (*pcUniChar
) = (nReadChar
== EXC_NUL_C
) ? mcNulSubst
: static_cast< sal_Unicode
>( nReadChar
);
889 aRet
.Append( pcBuffer
);
891 nCharsLeft
= nCharsLeft
- nReadSize
;
893 JumpToNextStringContinue( b16Bit
);
900 String
XclImpStream::ReadUniString( sal_uInt16 nChars
, sal_uInt8 nFlags
)
903 sal_Size nExtSize
= ReadUniStringExtHeader( b16Bit
, nFlags
);
904 String
aRet( ReadRawUniString( nChars
, b16Bit
) );
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) )
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 );
935 nReadSize
= GetMaxRawReadSize( nCharsLeft
);
939 nCharsLeft
= nCharsLeft
- nReadSize
;
941 JumpToNextStringContinue( b16Bit
);
945 void XclImpStream::IgnoreUniString( sal_uInt16 nChars
, sal_uInt8 nFlags
)
948 sal_Size nExtSize
= ReadUniStringExtHeader( b16Bit
, nFlags
);
949 IgnoreRawUniString( nChars
, b16Bit
);
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() );
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
);
993 bool XclImpStream::ReadNextRawRecHeader()
995 mrStrm
.Seek( mnNextRecPos
);
996 bool bRet
= mnNextRecPos
+ 4 <= mnStreamSize
;
998 mrStrm
>> mnRawRecId
>> mnRawRecSize
;
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
;
1023 mnComplRecSize
= mnRawRecSize
;
1024 mbHasComplRec
= !mbCont
;
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
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
1066 rb16Bit
= ::get_flag( ReaduInt8(), EXC_STRF_16BIT
);
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" );
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;
1091 nRet
= mxDecrypter
->Read( mrStrm
, pData
, nBytes
);
1093 nRet
= static_cast< sal_uInt16
>( mrStrm
.Read( pData
, nBytes
) );
1094 mnRawRecLeft
= mnRawRecLeft
- nRet
;
1098 // ============================================================================