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