1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_package.hxx"
31 #include <com/sun/star/lang/XMultiServiceFactory.hpp>
32 #include <com/sun/star/ucb/XProgressHandler.hpp>
33 #include <com/sun/star/packages/zip/ZipConstants.hpp>
34 #include <com/sun/star/xml/crypto/XCipherContext.hpp>
35 #include <com/sun/star/xml/crypto/XDigestContext.hpp>
36 #include <com/sun/star/xml/crypto/XCipherContextSupplier.hpp>
37 #include <com/sun/star/xml/crypto/XDigestContextSupplier.hpp>
38 #include <com/sun/star/xml/crypto/CipherID.hpp>
39 #include <com/sun/star/xml/crypto/DigestID.hpp>
41 #include <comphelper/storagehelper.hxx>
42 #include <comphelper/processfactory.hxx>
43 #include <rtl/digest.h>
47 #include "blowfishcontext.hxx"
48 #include "sha1context.hxx"
49 #include <ZipFile.hxx>
50 #include <ZipEnumeration.hxx>
51 #include <XUnbufferedStream.hxx>
52 #include <PackageConstants.hxx>
53 #include <EncryptedDataHeader.hxx>
54 #include <EncryptionData.hxx>
55 #include <MemoryByteGrabber.hxx>
59 #define AES_CBC_BLOCK_SIZE 16
63 using namespace com::sun::star
;
64 using namespace com::sun::star::io
;
65 using namespace com::sun::star::uno
;
66 using namespace com::sun::star::ucb
;
67 using namespace com::sun::star::lang
;
68 using namespace com::sun::star::packages
;
69 using namespace com::sun::star::packages::zip
;
70 using namespace com::sun::star::packages::zip::ZipConstants
;
73 /** This class is used to read entries from a zip file
75 ZipFile::ZipFile( uno::Reference
< XInputStream
> &xInput
, const uno::Reference
< XMultiServiceFactory
> &xNewFactory
, sal_Bool bInitialise
)
76 throw(IOException
, ZipException
, RuntimeException
)
78 , aInflater (sal_True
)
80 , xSeek(xInput
, UNO_QUERY
)
81 , m_xFactory ( xNewFactory
)
82 , bRecoveryMode( sal_False
)
86 if ( readCEN() == -1 )
89 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "stream data looks to be broken" ) ), uno::Reference
< XInterface
> () );
96 ZipFile::ZipFile( uno::Reference
< XInputStream
> &xInput
, const uno::Reference
< XMultiServiceFactory
> &xNewFactory
, sal_Bool bInitialise
, sal_Bool bForceRecovery
, uno::Reference
< XProgressHandler
> xProgress
)
97 throw(IOException
, ZipException
, RuntimeException
)
99 , aInflater (sal_True
)
101 , xSeek(xInput
, UNO_QUERY
)
102 , m_xFactory ( xNewFactory
)
103 , xProgressHandler( xProgress
)
104 , bRecoveryMode( bForceRecovery
)
108 if ( bForceRecovery
)
112 else if ( readCEN() == -1 )
115 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "stream data looks to be broken" ) ), uno::Reference
< XInterface
> () );
125 void ZipFile::setInputStream ( uno::Reference
< XInputStream
> xNewStream
)
127 ::osl::MutexGuard
aGuard( m_aMutex
);
129 xStream
= xNewStream
;
130 xSeek
= uno::Reference
< XSeekable
> ( xStream
, UNO_QUERY
);
131 aGrabber
.setInputStream ( xStream
);
134 uno::Reference
< xml::crypto::XDigestContext
> ZipFile::StaticGetDigestContextForChecksum( const uno::Reference
< lang::XMultiServiceFactory
>& xArgFactory
, const ::rtl::Reference
< EncryptionData
>& xEncryptionData
)
136 uno::Reference
< xml::crypto::XDigestContext
> xDigestContext
;
137 if ( xEncryptionData
->m_nCheckAlg
== xml::crypto::DigestID::SHA256_1K
)
139 uno::Reference
< lang::XMultiServiceFactory
> xFactory
= xArgFactory
;
140 if ( !xFactory
.is() )
141 xFactory
.set( comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW
);
143 uno::Reference
< xml::crypto::XDigestContextSupplier
> xDigestContextSupplier(
144 xFactory
->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.NSSInitializer" ) ) ),
145 uno::UNO_QUERY_THROW
);
147 xDigestContext
.set( xDigestContextSupplier
->getDigestContext( xEncryptionData
->m_nCheckAlg
, uno::Sequence
< beans::NamedValue
>() ), uno::UNO_SET_THROW
);
149 else if ( xEncryptionData
->m_nCheckAlg
== xml::crypto::DigestID::SHA1_1K
)
150 xDigestContext
.set( SHA1DigestContext::Create(), uno::UNO_SET_THROW
);
152 return xDigestContext
;
155 uno::Reference
< xml::crypto::XCipherContext
> ZipFile::StaticGetCipher( const uno::Reference
< lang::XMultiServiceFactory
>& xArgFactory
, const ::rtl::Reference
< EncryptionData
>& xEncryptionData
, bool bEncrypt
)
157 uno::Reference
< xml::crypto::XCipherContext
> xResult
;
161 uno::Sequence
< sal_Int8
> aDerivedKey( xEncryptionData
->m_nDerivedKeySize
);
162 if ( rtl_Digest_E_None
!= rtl_digest_PBKDF2( reinterpret_cast< sal_uInt8
* >( aDerivedKey
.getArray() ),
163 aDerivedKey
.getLength(),
164 reinterpret_cast< const sal_uInt8
* > (xEncryptionData
->m_aKey
.getConstArray() ),
165 xEncryptionData
->m_aKey
.getLength(),
166 reinterpret_cast< const sal_uInt8
* > ( xEncryptionData
->m_aSalt
.getConstArray() ),
167 xEncryptionData
->m_aSalt
.getLength(),
168 xEncryptionData
->m_nIterationCount
) )
170 throw ZipIOException( ::rtl::OUString::createFromAscii( "Can not create derived key!\n" ),
171 uno::Reference
< XInterface
>() );
174 if ( xEncryptionData
->m_nEncAlg
== xml::crypto::CipherID::AES_CBC_W3C_PADDING
)
176 uno::Reference
< lang::XMultiServiceFactory
> xFactory
= xArgFactory
;
177 if ( !xFactory
.is() )
178 xFactory
.set( comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW
);
180 uno::Reference
< xml::crypto::XCipherContextSupplier
> xCipherContextSupplier(
181 xFactory
->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.NSSInitializer" ) ) ),
182 uno::UNO_QUERY_THROW
);
184 xResult
= xCipherContextSupplier
->getCipherContext( xEncryptionData
->m_nEncAlg
, aDerivedKey
, xEncryptionData
->m_aInitVector
, bEncrypt
, uno::Sequence
< beans::NamedValue
>() );
186 else if ( xEncryptionData
->m_nEncAlg
== xml::crypto::CipherID::BLOWFISH_CFB_8
)
188 xResult
= BlowfishCFB8CipherContext::Create( aDerivedKey
, xEncryptionData
->m_aInitVector
, bEncrypt
);
192 throw ZipIOException( ::rtl::OUString::createFromAscii( "Unknown cipher algorithm is requested!\n" ),
193 uno::Reference
< XInterface
>() );
196 catch( uno::Exception
& )
198 OSL_ENSURE( sal_False
, "Can not create cipher context!" );
204 void ZipFile::StaticFillHeader( const ::rtl::Reference
< EncryptionData
>& rData
,
206 const ::rtl::OUString
& aMediaType
,
207 sal_Int8
* & pHeader
)
209 // I think it's safe to restrict vector and salt length to 2 bytes !
210 sal_Int16 nIVLength
= static_cast < sal_Int16
> ( rData
->m_aInitVector
.getLength() );
211 sal_Int16 nSaltLength
= static_cast < sal_Int16
> ( rData
->m_aSalt
.getLength() );
212 sal_Int16 nDigestLength
= static_cast < sal_Int16
> ( rData
->m_aDigest
.getLength() );
213 sal_Int16 nMediaTypeLength
= static_cast < sal_Int16
> ( aMediaType
.getLength() * sizeof( sal_Unicode
) );
216 *(pHeader
++) = ( n_ConstHeader
>> 0 ) & 0xFF;
217 *(pHeader
++) = ( n_ConstHeader
>> 8 ) & 0xFF;
218 *(pHeader
++) = ( n_ConstHeader
>> 16 ) & 0xFF;
219 *(pHeader
++) = ( n_ConstHeader
>> 24 ) & 0xFF;
222 *(pHeader
++) = ( n_ConstCurrentVersion
>> 0 ) & 0xFF;
223 *(pHeader
++) = ( n_ConstCurrentVersion
>> 8 ) & 0xFF;
225 // Then the iteration Count
226 sal_Int32 nIterationCount
= rData
->m_nIterationCount
;
227 *(pHeader
++) = static_cast< sal_Int8
>(( nIterationCount
>> 0 ) & 0xFF);
228 *(pHeader
++) = static_cast< sal_Int8
>(( nIterationCount
>> 8 ) & 0xFF);
229 *(pHeader
++) = static_cast< sal_Int8
>(( nIterationCount
>> 16 ) & 0xFF);
230 *(pHeader
++) = static_cast< sal_Int8
>(( nIterationCount
>> 24 ) & 0xFF);
233 *(pHeader
++) = static_cast< sal_Int8
>(( nSize
>> 0 ) & 0xFF);
234 *(pHeader
++) = static_cast< sal_Int8
>(( nSize
>> 8 ) & 0xFF);
235 *(pHeader
++) = static_cast< sal_Int8
>(( nSize
>> 16 ) & 0xFF);
236 *(pHeader
++) = static_cast< sal_Int8
>(( nSize
>> 24 ) & 0xFF);
238 // Then the encryption algorithm
239 sal_Int32 nEncAlgID
= rData
->m_nEncAlg
;
240 *(pHeader
++) = static_cast< sal_Int8
>(( nEncAlgID
>> 0 ) & 0xFF);
241 *(pHeader
++) = static_cast< sal_Int8
>(( nEncAlgID
>> 8 ) & 0xFF);
242 *(pHeader
++) = static_cast< sal_Int8
>(( nEncAlgID
>> 16 ) & 0xFF);
243 *(pHeader
++) = static_cast< sal_Int8
>(( nEncAlgID
>> 24 ) & 0xFF);
245 // Then the checksum algorithm
246 sal_Int32 nChecksumAlgID
= rData
->m_nCheckAlg
;
247 *(pHeader
++) = static_cast< sal_Int8
>(( nChecksumAlgID
>> 0 ) & 0xFF);
248 *(pHeader
++) = static_cast< sal_Int8
>(( nChecksumAlgID
>> 8 ) & 0xFF);
249 *(pHeader
++) = static_cast< sal_Int8
>(( nChecksumAlgID
>> 16 ) & 0xFF);
250 *(pHeader
++) = static_cast< sal_Int8
>(( nChecksumAlgID
>> 24 ) & 0xFF);
252 // Then the derived key size
253 sal_Int32 nDerivedKeySize
= rData
->m_nDerivedKeySize
;
254 *(pHeader
++) = static_cast< sal_Int8
>(( nDerivedKeySize
>> 0 ) & 0xFF);
255 *(pHeader
++) = static_cast< sal_Int8
>(( nDerivedKeySize
>> 8 ) & 0xFF);
256 *(pHeader
++) = static_cast< sal_Int8
>(( nDerivedKeySize
>> 16 ) & 0xFF);
257 *(pHeader
++) = static_cast< sal_Int8
>(( nDerivedKeySize
>> 24 ) & 0xFF);
259 // Then the start key generation algorithm
260 sal_Int32 nKeyAlgID
= rData
->m_nStartKeyGenID
;
261 *(pHeader
++) = static_cast< sal_Int8
>(( nKeyAlgID
>> 0 ) & 0xFF);
262 *(pHeader
++) = static_cast< sal_Int8
>(( nKeyAlgID
>> 8 ) & 0xFF);
263 *(pHeader
++) = static_cast< sal_Int8
>(( nKeyAlgID
>> 16 ) & 0xFF);
264 *(pHeader
++) = static_cast< sal_Int8
>(( nKeyAlgID
>> 24 ) & 0xFF);
266 // Then the salt length
267 *(pHeader
++) = static_cast< sal_Int8
>(( nSaltLength
>> 0 ) & 0xFF);
268 *(pHeader
++) = static_cast< sal_Int8
>(( nSaltLength
>> 8 ) & 0xFF);
270 // Then the IV length
271 *(pHeader
++) = static_cast< sal_Int8
>(( nIVLength
>> 0 ) & 0xFF);
272 *(pHeader
++) = static_cast< sal_Int8
>(( nIVLength
>> 8 ) & 0xFF);
274 // Then the digest length
275 *(pHeader
++) = static_cast< sal_Int8
>(( nDigestLength
>> 0 ) & 0xFF);
276 *(pHeader
++) = static_cast< sal_Int8
>(( nDigestLength
>> 8 ) & 0xFF);
278 // Then the mediatype length
279 *(pHeader
++) = static_cast< sal_Int8
>(( nMediaTypeLength
>> 0 ) & 0xFF);
280 *(pHeader
++) = static_cast< sal_Int8
>(( nMediaTypeLength
>> 8 ) & 0xFF);
282 // Then the salt content
283 rtl_copyMemory ( pHeader
, rData
->m_aSalt
.getConstArray(), nSaltLength
);
284 pHeader
+= nSaltLength
;
286 // Then the IV content
287 rtl_copyMemory ( pHeader
, rData
->m_aInitVector
.getConstArray(), nIVLength
);
288 pHeader
+= nIVLength
;
290 // Then the digest content
291 rtl_copyMemory ( pHeader
, rData
->m_aDigest
.getConstArray(), nDigestLength
);
292 pHeader
+= nDigestLength
;
294 // Then the mediatype itself
295 rtl_copyMemory ( pHeader
, aMediaType
.getStr(), nMediaTypeLength
);
296 pHeader
+= nMediaTypeLength
;
299 sal_Bool
ZipFile::StaticFillData ( ::rtl::Reference
< BaseEncryptionData
> & rData
,
301 sal_Int32
&rChecksumAlg
,
302 sal_Int32
&rDerivedKeySize
,
303 sal_Int32
&rStartKeyGenID
,
305 ::rtl::OUString
& aMediaType
,
306 const uno::Reference
< XInputStream
>& rStream
)
308 sal_Bool bOk
= sal_False
;
309 const sal_Int32 nHeaderSize
= n_ConstHeaderSize
- 4;
310 Sequence
< sal_Int8
> aBuffer ( nHeaderSize
);
311 if ( nHeaderSize
== rStream
->readBytes ( aBuffer
, nHeaderSize
) )
314 sal_Int8
*pBuffer
= aBuffer
.getArray();
315 sal_Int16 nVersion
= pBuffer
[nPos
++] & 0xFF;
316 nVersion
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
317 if ( nVersion
== n_ConstCurrentVersion
)
319 sal_Int32 nCount
= pBuffer
[nPos
++] & 0xFF;
320 nCount
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
321 nCount
|= ( pBuffer
[nPos
++] & 0xFF ) << 16;
322 nCount
|= ( pBuffer
[nPos
++] & 0xFF ) << 24;
323 rData
->m_nIterationCount
= nCount
;
325 rSize
= pBuffer
[nPos
++] & 0xFF;
326 rSize
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
327 rSize
|= ( pBuffer
[nPos
++] & 0xFF ) << 16;
328 rSize
|= ( pBuffer
[nPos
++] & 0xFF ) << 24;
330 rEncAlg
= pBuffer
[nPos
++] & 0xFF;
331 rEncAlg
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
332 rEncAlg
|= ( pBuffer
[nPos
++] & 0xFF ) << 16;
333 rEncAlg
|= ( pBuffer
[nPos
++] & 0xFF ) << 24;
335 rChecksumAlg
= pBuffer
[nPos
++] & 0xFF;
336 rChecksumAlg
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
337 rChecksumAlg
|= ( pBuffer
[nPos
++] & 0xFF ) << 16;
338 rChecksumAlg
|= ( pBuffer
[nPos
++] & 0xFF ) << 24;
340 rDerivedKeySize
= pBuffer
[nPos
++] & 0xFF;
341 rDerivedKeySize
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
342 rDerivedKeySize
|= ( pBuffer
[nPos
++] & 0xFF ) << 16;
343 rDerivedKeySize
|= ( pBuffer
[nPos
++] & 0xFF ) << 24;
345 rStartKeyGenID
= pBuffer
[nPos
++] & 0xFF;
346 rStartKeyGenID
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
347 rStartKeyGenID
|= ( pBuffer
[nPos
++] & 0xFF ) << 16;
348 rStartKeyGenID
|= ( pBuffer
[nPos
++] & 0xFF ) << 24;
350 sal_Int16 nSaltLength
= pBuffer
[nPos
++] & 0xFF;
351 nSaltLength
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
352 sal_Int16 nIVLength
= ( pBuffer
[nPos
++] & 0xFF );
353 nIVLength
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
354 sal_Int16 nDigestLength
= pBuffer
[nPos
++] & 0xFF;
355 nDigestLength
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
357 sal_Int16 nMediaTypeLength
= pBuffer
[nPos
++] & 0xFF;
358 nMediaTypeLength
|= ( pBuffer
[nPos
++] & 0xFF ) << 8;
360 if ( nSaltLength
== rStream
->readBytes ( aBuffer
, nSaltLength
) )
362 rData
->m_aSalt
.realloc ( nSaltLength
);
363 rtl_copyMemory ( rData
->m_aSalt
.getArray(), aBuffer
.getConstArray(), nSaltLength
);
364 if ( nIVLength
== rStream
->readBytes ( aBuffer
, nIVLength
) )
366 rData
->m_aInitVector
.realloc ( nIVLength
);
367 rtl_copyMemory ( rData
->m_aInitVector
.getArray(), aBuffer
.getConstArray(), nIVLength
);
368 if ( nDigestLength
== rStream
->readBytes ( aBuffer
, nDigestLength
) )
370 rData
->m_aDigest
.realloc ( nDigestLength
);
371 rtl_copyMemory ( rData
->m_aDigest
.getArray(), aBuffer
.getConstArray(), nDigestLength
);
373 if ( nMediaTypeLength
== rStream
->readBytes ( aBuffer
, nMediaTypeLength
) )
375 aMediaType
= ::rtl::OUString( (sal_Unicode
*)aBuffer
.getConstArray(),
376 nMediaTypeLength
/ sizeof( sal_Unicode
) );
387 uno::Reference
< XInputStream
> ZipFile::StaticGetDataFromRawStream( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
,
388 const uno::Reference
< XInputStream
>& xStream
,
389 const ::rtl::Reference
< EncryptionData
> &rData
)
390 throw ( packages::WrongPasswordException
, ZipIOException
, RuntimeException
)
393 throw ZipIOException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ),
394 uno::Reference
< XInterface
>() );
396 if ( !rData
->m_aKey
.getLength() )
397 throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
399 uno::Reference
< XSeekable
> xSeek( xStream
, UNO_QUERY
);
401 throw ZipIOException( OUString::createFromAscii( "The stream must be seekable!\n" ),
402 uno::Reference
< XInterface
>() );
405 // if we have a digest, then this file is an encrypted one and we should
406 // check if we can decrypt it or not
407 OSL_ENSURE( rData
->m_aDigest
.getLength(), "Can't detect password correctness without digest!\n" );
408 if ( rData
->m_aDigest
.getLength() )
410 sal_Int32 nSize
= sal::static_int_cast
< sal_Int32
>( xSeek
->getLength() );
411 if ( nSize
> n_ConstDigestLength
+ 32 )
412 nSize
= n_ConstDigestLength
+ 32;
415 xSeek
->seek( n_ConstHeaderSize
+ rData
->m_aInitVector
.getLength() +
416 rData
->m_aSalt
.getLength() + rData
->m_aDigest
.getLength() );
418 // Only want to read enough to verify the digest
419 Sequence
< sal_Int8
> aReadBuffer ( nSize
);
421 xStream
->readBytes( aReadBuffer
, nSize
);
423 if ( !StaticHasValidPassword( xFactory
, aReadBuffer
, rData
) )
424 throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
427 return new XUnbufferedStream( xFactory
, xStream
, rData
);
431 // for debugging purposes
432 void CheckSequence( const uno::Sequence
< sal_Int8
>& aSequence
)
434 if ( aSequence
.getLength() )
436 sal_Int32
* pPointer
= *( (sal_Int32
**)&aSequence
);
437 sal_Int32 nSize
= *( pPointer
+ 1 );
438 sal_Int32 nMemSize
= *( pPointer
- 2 );
439 sal_Int32 nUsedMemSize
= ( nSize
+ 4 * sizeof( sal_Int32
) );
440 OSL_ENSURE( nSize
== aSequence
.getLength() && nUsedMemSize
+ 7 - ( nUsedMemSize
- 1 ) % 8 == nMemSize
, "Broken Sequence!" );
445 sal_Bool
ZipFile::StaticHasValidPassword( const uno::Reference
< lang::XMultiServiceFactory
>& xFactory
, const Sequence
< sal_Int8
> &aReadBuffer
, const ::rtl::Reference
< EncryptionData
> &rData
)
447 if ( !rData
.is() || !rData
->m_aKey
.getLength() )
450 sal_Bool bRet
= sal_False
;
452 uno::Reference
< xml::crypto::XCipherContext
> xCipher( StaticGetCipher( xFactory
, rData
, false ), uno::UNO_SET_THROW
);
454 uno::Sequence
< sal_Int8
> aDecryptBuffer
;
455 uno::Sequence
< sal_Int8
> aDecryptBuffer2
;
458 aDecryptBuffer
= xCipher
->convertWithCipherContext( aReadBuffer
);
459 aDecryptBuffer2
= xCipher
->finalizeCipherContextAndDispose();
461 catch( uno::Exception
& )
463 // decryption with padding will throw the exception in finalizing if the buffer represent only part of the stream
464 // it is no problem, actually this is why we read 32 additional bytes ( two of maximal possible encryption blocks )
467 if ( aDecryptBuffer2
.getLength() )
469 sal_Int32 nOldLen
= aDecryptBuffer
.getLength();
470 aDecryptBuffer
.realloc( nOldLen
+ aDecryptBuffer2
.getLength() );
471 rtl_copyMemory( aDecryptBuffer
.getArray() + nOldLen
, aDecryptBuffer2
.getArray(), aDecryptBuffer2
.getLength() );
474 if ( aDecryptBuffer
.getLength() > n_ConstDigestLength
)
475 aDecryptBuffer
.realloc( n_ConstDigestLength
);
477 uno::Sequence
< sal_Int8
> aDigestSeq
;
478 uno::Reference
< xml::crypto::XDigestContext
> xDigestContext( StaticGetDigestContextForChecksum( xFactory
, rData
), uno::UNO_SET_THROW
);
480 xDigestContext
->updateDigest( aDecryptBuffer
);
481 aDigestSeq
= xDigestContext
->finalizeDigestAndDispose();
483 // If we don't have a digest, then we have to assume that the password is correct
484 if ( rData
->m_aDigest
.getLength() != 0 &&
485 ( aDigestSeq
.getLength() != rData
->m_aDigest
.getLength() ||
486 0 != rtl_compareMemory ( aDigestSeq
.getConstArray(),
487 rData
->m_aDigest
.getConstArray(),
488 aDigestSeq
.getLength() ) ) )
490 // We should probably tell the user that the password they entered was wrong
498 sal_Bool
ZipFile::hasValidPassword ( ZipEntry
& rEntry
, const ::rtl::Reference
< EncryptionData
>& rData
)
500 ::osl::MutexGuard
aGuard( m_aMutex
);
502 sal_Bool bRet
= sal_False
;
503 if ( rData
.is() && rData
->m_aKey
.getLength() )
505 xSeek
->seek( rEntry
.nOffset
);
506 sal_Int32 nSize
= rEntry
.nMethod
== DEFLATED
? rEntry
.nCompressedSize
: rEntry
.nSize
;
508 // Only want to read enough to verify the digest
509 if ( nSize
> n_ConstDigestDecrypt
)
510 nSize
= n_ConstDigestDecrypt
;
512 Sequence
< sal_Int8
> aReadBuffer ( nSize
);
514 xStream
->readBytes( aReadBuffer
, nSize
);
516 bRet
= StaticHasValidPassword( m_xFactory
, aReadBuffer
, rData
);
522 uno::Reference
< XInputStream
> ZipFile::createUnbufferedStream(
523 SotMutexHolderRef aMutexHolder
,
525 const ::rtl::Reference
< EncryptionData
> &rData
,
526 sal_Int8 nStreamMode
,
527 sal_Bool bIsEncrypted
,
528 ::rtl::OUString aMediaType
)
530 ::osl::MutexGuard
aGuard( m_aMutex
);
532 return new XUnbufferedStream ( m_xFactory
, aMutexHolder
, rEntry
, xStream
, rData
, nStreamMode
, bIsEncrypted
, aMediaType
, bRecoveryMode
);
536 ZipEnumeration
* SAL_CALL
ZipFile::entries( )
538 return new ZipEnumeration ( aEntries
);
541 uno::Reference
< XInputStream
> SAL_CALL
ZipFile::getInputStream( ZipEntry
& rEntry
,
542 const ::rtl::Reference
< EncryptionData
> &rData
,
543 sal_Bool bIsEncrypted
,
544 SotMutexHolderRef aMutexHolder
)
545 throw(IOException
, ZipException
, RuntimeException
)
547 ::osl::MutexGuard
aGuard( m_aMutex
);
549 if ( rEntry
.nOffset
<= 0 )
552 // We want to return a rawStream if we either don't have a key or if the
555 sal_Bool bNeedRawStream
= rEntry
.nMethod
== STORED
;
557 // if we have a digest, then this file is an encrypted one and we should
558 // check if we can decrypt it or not
559 if ( bIsEncrypted
&& rData
.is() && rData
->m_aDigest
.getLength() )
560 bNeedRawStream
= !hasValidPassword ( rEntry
, rData
);
562 return createUnbufferedStream ( aMutexHolder
,
565 bNeedRawStream
? UNBUFF_STREAM_RAW
: UNBUFF_STREAM_DATA
,
569 uno::Reference
< XInputStream
> SAL_CALL
ZipFile::getDataStream( ZipEntry
& rEntry
,
570 const ::rtl::Reference
< EncryptionData
> &rData
,
571 sal_Bool bIsEncrypted
,
572 SotMutexHolderRef aMutexHolder
)
573 throw ( packages::WrongPasswordException
,
578 ::osl::MutexGuard
aGuard( m_aMutex
);
580 if ( rEntry
.nOffset
<= 0 )
583 // An exception must be thrown in case stream is encrypted and
584 // there is no key or the key is wrong
585 sal_Bool bNeedRawStream
= sal_False
;
588 // in case no digest is provided there is no way
589 // to detect password correctness
591 throw ZipException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ),
592 uno::Reference
< XInterface
>() );
594 // if we have a digest, then this file is an encrypted one and we should
595 // check if we can decrypt it or not
596 OSL_ENSURE( rData
->m_aDigest
.getLength(), "Can't detect password correctness without digest!\n" );
597 if ( rData
->m_aDigest
.getLength() && !hasValidPassword ( rEntry
, rData
) )
598 throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
601 bNeedRawStream
= ( rEntry
.nMethod
== STORED
);
603 return createUnbufferedStream ( aMutexHolder
,
606 bNeedRawStream
? UNBUFF_STREAM_RAW
: UNBUFF_STREAM_DATA
,
610 uno::Reference
< XInputStream
> SAL_CALL
ZipFile::getRawData( ZipEntry
& rEntry
,
611 const ::rtl::Reference
< EncryptionData
>& rData
,
612 sal_Bool bIsEncrypted
,
613 SotMutexHolderRef aMutexHolder
)
614 throw(IOException
, ZipException
, RuntimeException
)
616 ::osl::MutexGuard
aGuard( m_aMutex
);
618 if ( rEntry
.nOffset
<= 0 )
621 return createUnbufferedStream ( aMutexHolder
, rEntry
, rData
, UNBUFF_STREAM_RAW
, bIsEncrypted
);
624 uno::Reference
< XInputStream
> SAL_CALL
ZipFile::getWrappedRawStream(
626 const ::rtl::Reference
< EncryptionData
>& rData
,
627 const ::rtl::OUString
& aMediaType
,
628 SotMutexHolderRef aMutexHolder
)
629 throw ( packages::NoEncryptionException
,
634 ::osl::MutexGuard
aGuard( m_aMutex
);
637 throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>() );
639 if ( rEntry
.nOffset
<= 0 )
642 return createUnbufferedStream ( aMutexHolder
, rEntry
, rData
, UNBUFF_STREAM_WRAPPEDRAW
, sal_True
, aMediaType
);
645 sal_Bool
ZipFile::readLOC( ZipEntry
&rEntry
)
646 throw(IOException
, ZipException
, RuntimeException
)
648 ::osl::MutexGuard
aGuard( m_aMutex
);
650 sal_Int32 nTestSig
, nTime
, nCRC
, nSize
, nCompressedSize
;
651 sal_Int16 nVersion
, nFlag
, nHow
, nPathLen
, nExtraLen
;
652 sal_Int32 nPos
= -rEntry
.nOffset
;
655 aGrabber
>> nTestSig
;
657 if (nTestSig
!= LOCSIG
)
658 throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid LOC header (bad signature") ), uno::Reference
< XInterface
> () );
659 aGrabber
>> nVersion
;
664 aGrabber
>> nCompressedSize
;
666 aGrabber
>> nPathLen
;
667 aGrabber
>> nExtraLen
;
668 rEntry
.nOffset
= static_cast < sal_Int32
> (aGrabber
.getPosition()) + nPathLen
+ nExtraLen
;
670 // read always in UTF8, some tools seem not to set UTF8 bit
671 uno::Sequence
< sal_Int8
> aNameBuffer( nPathLen
);
672 sal_Int32 nRead
= aGrabber
.readBytes( aNameBuffer
, nPathLen
);
673 if ( nRead
< aNameBuffer
.getLength() )
674 aNameBuffer
.realloc( nRead
);
676 ::rtl::OUString sLOCPath
= rtl::OUString::intern( (sal_Char
*) aNameBuffer
.getArray(),
677 aNameBuffer
.getLength(),
678 RTL_TEXTENCODING_UTF8
);
680 if ( rEntry
.nPathLen
== -1 ) // the file was created
682 rEntry
.nPathLen
= nPathLen
;
683 rEntry
.sPath
= sLOCPath
;
686 // the method can be reset for internal use so it is not checked
687 sal_Bool bBroken
= rEntry
.nVersion
!= nVersion
688 || rEntry
.nFlag
!= nFlag
689 || rEntry
.nTime
!= nTime
690 || rEntry
.nPathLen
!= nPathLen
691 || !rEntry
.sPath
.equals( sLOCPath
);
693 if ( bBroken
&& !bRecoveryMode
)
694 throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
695 uno::Reference
< XInterface
>() );
700 sal_Int32
ZipFile::findEND( )
701 throw(IOException
, ZipException
, RuntimeException
)
703 // this method is called in constructor only, no need for mutex
704 sal_Int32 nLength
, nPos
, nEnd
;
705 Sequence
< sal_Int8
> aBuffer
;
708 nLength
= static_cast <sal_Int32
> (aGrabber
.getLength());
709 if (nLength
== 0 || nLength
< ENDHDR
)
711 nPos
= nLength
- ENDHDR
- ZIP_MAXNAMELEN
;
712 nEnd
= nPos
>= 0 ? nPos
: 0 ;
714 aGrabber
.seek( nEnd
);
715 aGrabber
.readBytes ( aBuffer
, nLength
- nEnd
);
717 const sal_Int8
*pBuffer
= aBuffer
.getConstArray();
719 nPos
= nLength
- nEnd
- ENDHDR
;
722 if (pBuffer
[nPos
] == 'P' && pBuffer
[nPos
+1] == 'K' && pBuffer
[nPos
+2] == 5 && pBuffer
[nPos
+3] == 6 )
727 catch ( IllegalArgumentException
& )
729 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference
< XInterface
> () );
731 catch ( NotConnectedException
& )
733 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference
< XInterface
> () );
735 catch ( BufferSizeExceededException
& )
737 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference
< XInterface
> () );
739 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference
< XInterface
> () );
742 sal_Int32
ZipFile::readCEN()
743 throw(IOException
, ZipException
, RuntimeException
)
745 // this method is called in constructor only, no need for mutex
746 sal_Int32 nCenLen
, nCenPos
= -1, nCenOff
, nEndPos
, nLocPos
;
747 sal_uInt16 nCount
, nTotal
;
754 aGrabber
.seek(nEndPos
+ ENDTOT
);
759 if ( nTotal
* CENHDR
> nCenLen
)
760 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "invalid END header (bad entry count)") ), uno::Reference
< XInterface
> () );
762 if ( nTotal
> ZIP_MAXENTRIES
)
763 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "too many entries in ZIP File") ), uno::Reference
< XInterface
> () );
765 if ( nCenLen
< 0 || nCenLen
> nEndPos
)
766 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), uno::Reference
< XInterface
> () );
768 nCenPos
= nEndPos
- nCenLen
;
770 if ( nCenOff
< 0 || nCenOff
> nCenPos
)
771 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), uno::Reference
< XInterface
> () );
773 nLocPos
= nCenPos
- nCenOff
;
774 aGrabber
.seek( nCenPos
);
775 Sequence
< sal_Int8
> aCENBuffer ( nCenLen
);
776 sal_Int64 nRead
= aGrabber
.readBytes ( aCENBuffer
, nCenLen
);
777 if ( static_cast < sal_Int64
> ( nCenLen
) != nRead
)
778 throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Error reading CEN into memory buffer!") ), uno::Reference
< XInterface
> () );
780 MemoryByteGrabber
aMemGrabber ( aCENBuffer
);
784 sal_Int16 nCommentLen
;
786 for (nCount
= 0 ; nCount
< nTotal
; nCount
++)
788 aMemGrabber
>> nTestSig
;
789 if ( nTestSig
!= CENSIG
)
790 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad signature)") ), uno::Reference
< XInterface
> () );
792 aMemGrabber
.skipBytes ( 2 );
793 aMemGrabber
>> aEntry
.nVersion
;
795 if ( ( aEntry
.nVersion
& 1 ) == 1 )
796 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (encrypted entry)") ), uno::Reference
< XInterface
> () );
798 aMemGrabber
>> aEntry
.nFlag
;
799 aMemGrabber
>> aEntry
.nMethod
;
801 if ( aEntry
.nMethod
!= STORED
&& aEntry
.nMethod
!= DEFLATED
)
802 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad compression method)") ), uno::Reference
< XInterface
> () );
804 aMemGrabber
>> aEntry
.nTime
;
805 aMemGrabber
>> aEntry
.nCrc
;
806 aMemGrabber
>> aEntry
.nCompressedSize
;
807 aMemGrabber
>> aEntry
.nSize
;
808 aMemGrabber
>> aEntry
.nPathLen
;
809 aMemGrabber
>> aEntry
.nExtraLen
;
810 aMemGrabber
>> nCommentLen
;
811 aMemGrabber
.skipBytes ( 8 );
812 aMemGrabber
>> aEntry
.nOffset
;
814 aEntry
.nOffset
+= nLocPos
;
815 aEntry
.nOffset
*= -1;
817 if ( aEntry
.nPathLen
< 0 )
818 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected name length" ) ), uno::Reference
< XInterface
> () );
820 if ( nCommentLen
< 0 )
821 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected comment length" ) ), uno::Reference
< XInterface
> () );
823 if ( aEntry
.nExtraLen
< 0 )
824 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected extra header info length") ), uno::Reference
< XInterface
> () );
826 // read always in UTF8, some tools seem not to set UTF8 bit
827 aEntry
.sPath
= rtl::OUString::intern ( (sal_Char
*) aMemGrabber
.getCurrentPos(),
829 RTL_TEXTENCODING_UTF8
);
831 if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( aEntry
.sPath
, sal_True
) )
832 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip entry has an invalid name.") ), uno::Reference
< XInterface
> () );
834 aMemGrabber
.skipBytes( aEntry
.nPathLen
+ aEntry
.nExtraLen
+ nCommentLen
);
835 aEntries
[aEntry
.sPath
] = aEntry
;
838 if (nCount
!= nTotal
)
839 throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Count != Total") ), uno::Reference
< XInterface
> () );
841 catch ( IllegalArgumentException
& )
843 // seek can throw this...
844 nCenPos
= -1; // make sure we return -1 to indicate an error
849 sal_Int32
ZipFile::recover()
850 throw(IOException
, ZipException
, RuntimeException
)
852 ::osl::MutexGuard
aGuard( m_aMutex
);
855 Sequence
< sal_Int8
> aBuffer
;
856 Sequence
< sal_Int32
> aHeaderOffsets
;
860 nLength
= static_cast <sal_Int32
> (aGrabber
.getLength());
861 if (nLength
== 0 || nLength
< ENDHDR
)
866 const sal_Int32 nToRead
= 32000;
867 for( sal_Int32 nGenPos
= 0; aGrabber
.readBytes( aBuffer
, nToRead
) && aBuffer
.getLength() > 16; )
869 const sal_Int8
*pBuffer
= aBuffer
.getConstArray();
870 sal_Int32 nBufSize
= aBuffer
.getLength();
873 // the buffer should contain at least one header,
874 // or if it is end of the file, at least the postheader with sizes and hash
875 while( nPos
< nBufSize
- 30
876 || ( aBuffer
.getLength() < nToRead
&& nPos
< nBufSize
- 16 ) )
879 if ( nPos
< nBufSize
- 30 && pBuffer
[nPos
] == 'P' && pBuffer
[nPos
+1] == 'K' && pBuffer
[nPos
+2] == 3 && pBuffer
[nPos
+3] == 4 )
882 MemoryByteGrabber
aMemGrabber ( Sequence
< sal_Int8
>( ((sal_Int8
*)(&(pBuffer
[nPos
+4]))), 26 ) );
884 aMemGrabber
>> aEntry
.nVersion
;
885 if ( ( aEntry
.nVersion
& 1 ) != 1 )
887 aMemGrabber
>> aEntry
.nFlag
;
888 aMemGrabber
>> aEntry
.nMethod
;
890 if ( aEntry
.nMethod
== STORED
|| aEntry
.nMethod
== DEFLATED
)
892 aMemGrabber
>> aEntry
.nTime
;
893 aMemGrabber
>> aEntry
.nCrc
;
894 aMemGrabber
>> aEntry
.nCompressedSize
;
895 aMemGrabber
>> aEntry
.nSize
;
896 aMemGrabber
>> aEntry
.nPathLen
;
897 aMemGrabber
>> aEntry
.nExtraLen
;
899 sal_Int32 nDescrLength
=
900 ( aEntry
.nMethod
== DEFLATED
&& ( aEntry
.nFlag
& 8 ) ) ?
904 // This is a quick fix for OOo1.1RC
905 // For OOo2.0 the whole package must be switched to unsigned values
906 if ( aEntry
.nCompressedSize
< 0 ) aEntry
.nCompressedSize
= 0x7FFFFFFF;
907 if ( aEntry
.nSize
< 0 ) aEntry
.nSize
= 0x7FFFFFFF;
908 if ( aEntry
.nPathLen
< 0 ) aEntry
.nPathLen
= 0x7FFF;
909 if ( aEntry
.nExtraLen
< 0 ) aEntry
.nExtraLen
= 0x7FFF;
912 sal_Int32 nDataSize
= ( aEntry
.nMethod
== DEFLATED
) ? aEntry
.nCompressedSize
: aEntry
.nSize
;
913 sal_Int32 nBlockLength
= nDataSize
+ aEntry
.nPathLen
+ aEntry
.nExtraLen
+ 30 + nDescrLength
;
914 if ( aEntry
.nPathLen
>= 0 && aEntry
.nExtraLen
>= 0
915 && ( nGenPos
+ nPos
+ nBlockLength
) <= nLength
)
917 // read always in UTF8, some tools seem not to set UTF8 bit
918 if( nPos
+ 30 + aEntry
.nPathLen
<= nBufSize
)
919 aEntry
.sPath
= OUString ( (sal_Char
*) &pBuffer
[nPos
+ 30],
921 RTL_TEXTENCODING_UTF8
);
924 Sequence
< sal_Int8
> aFileName
;
925 aGrabber
.seek( nGenPos
+ nPos
+ 30 );
926 aGrabber
.readBytes( aFileName
, aEntry
.nPathLen
);
927 aEntry
.sPath
= OUString ( (sal_Char
*) aFileName
.getArray(),
928 aFileName
.getLength(),
929 RTL_TEXTENCODING_UTF8
);
930 aEntry
.nPathLen
= static_cast< sal_Int16
>(aFileName
.getLength());
933 aEntry
.nOffset
= nGenPos
+ nPos
+ 30 + aEntry
.nPathLen
+ aEntry
.nExtraLen
;
935 if ( ( aEntry
.nSize
|| aEntry
.nCompressedSize
) && !checkSizeAndCRC( aEntry
) )
938 aEntry
.nCompressedSize
= 0;
942 if ( aEntries
.find( aEntry
.sPath
) == aEntries
.end() )
943 aEntries
[aEntry
.sPath
] = aEntry
;
950 else if (pBuffer
[nPos
] == 'P' && pBuffer
[nPos
+1] == 'K' && pBuffer
[nPos
+2] == 7 && pBuffer
[nPos
+3] == 8 )
952 sal_Int32 nCompressedSize
, nSize
, nCRC32
;
953 MemoryByteGrabber
aMemGrabber ( Sequence
< sal_Int8
>( ((sal_Int8
*)(&(pBuffer
[nPos
+4]))), 12 ) );
954 aMemGrabber
>> nCRC32
;
955 aMemGrabber
>> nCompressedSize
;
956 aMemGrabber
>> nSize
;
958 for( EntryHash::iterator aIter
= aEntries
.begin(); aIter
!= aEntries
.end(); aIter
++ )
960 ZipEntry aTmp
= (*aIter
).second
;
962 // this is a broken package, accept this block not only for DEFLATED streams
963 if( (*aIter
).second
.nFlag
& 8 )
965 sal_Int32 nStreamOffset
= nGenPos
+ nPos
- nCompressedSize
;
966 if ( nStreamOffset
== (*aIter
).second
.nOffset
&& nCompressedSize
> (*aIter
).second
.nCompressedSize
)
968 // only DEFLATED blocks need to be checked
969 sal_Bool bAcceptBlock
= ( (*aIter
).second
.nMethod
== STORED
&& nCompressedSize
== nSize
);
973 sal_Int32 nRealSize
= 0, nRealCRC
= 0;
974 getSizeAndCRC( nStreamOffset
, nCompressedSize
, &nRealSize
, &nRealCRC
);
975 bAcceptBlock
= ( nRealSize
== nSize
&& nRealCRC
== nCRC32
);
980 (*aIter
).second
.nCrc
= nCRC32
;
981 (*aIter
).second
.nCompressedSize
= nCompressedSize
;
982 (*aIter
).second
.nSize
= nSize
;
986 // for now ignore clearly broken streams
987 else if( !(*aIter
).second
.nCompressedSize
)
989 (*aIter
).second
.nCrc
= nCRC32
;
990 sal_Int32 nRealStreamSize
= nGenPos
+ nPos
- (*aIter
).second
.nOffset
;
991 (*aIter
).second
.nCompressedSize
= nGenPos
+ nPos
- (*aIter
).second
.nOffset
;
992 (*aIter
).second
.nSize
= nSize
;
1005 aGrabber
.seek( nGenPos
);
1010 catch ( IllegalArgumentException
& )
1012 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference
< XInterface
> () );
1014 catch ( NotConnectedException
& )
1016 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference
< XInterface
> () );
1018 catch ( BufferSizeExceededException
& )
1020 throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference
< XInterface
> () );
1024 sal_Bool
ZipFile::checkSizeAndCRC( const ZipEntry
& aEntry
)
1026 ::osl::MutexGuard
aGuard( m_aMutex
);
1028 sal_Int32 nSize
= 0, nCRC
= 0;
1030 if( aEntry
.nMethod
== STORED
)
1031 return ( getCRC( aEntry
.nOffset
, aEntry
.nSize
) == aEntry
.nCrc
);
1033 getSizeAndCRC( aEntry
.nOffset
, aEntry
.nCompressedSize
, &nSize
, &nCRC
);
1034 return ( aEntry
.nSize
== nSize
&& aEntry
.nCrc
== nCRC
);
1037 sal_Int32
ZipFile::getCRC( sal_Int32 nOffset
, sal_Int32 nSize
)
1039 ::osl::MutexGuard
aGuard( m_aMutex
);
1041 Sequence
< sal_Int8
> aBuffer
;
1043 sal_Int32 nBlockSize
= ::std::min( nSize
, static_cast< sal_Int32
>( 32000 ) );
1045 aGrabber
.seek( nOffset
);
1047 aGrabber
.readBytes( aBuffer
, nBlockSize
) && ind
* nBlockSize
< nSize
;
1050 aCRC
.updateSegment( aBuffer
, 0, ::std::min( nBlockSize
, nSize
- ind
* nBlockSize
) );
1053 return aCRC
.getValue();
1056 void ZipFile::getSizeAndCRC( sal_Int32 nOffset
, sal_Int32 nCompressedSize
, sal_Int32
*nSize
, sal_Int32
*nCRC
)
1058 ::osl::MutexGuard
aGuard( m_aMutex
);
1060 Sequence
< sal_Int8
> aBuffer
;
1062 sal_Int32 nRealSize
= 0;
1063 Inflater
aInflaterLocal( sal_True
);
1064 sal_Int32 nBlockSize
= ::std::min( nCompressedSize
, static_cast< sal_Int32
>( 32000 ) );
1066 aGrabber
.seek( nOffset
);
1068 !aInflaterLocal
.finished() && aGrabber
.readBytes( aBuffer
, nBlockSize
) && ind
* nBlockSize
< nCompressedSize
;
1071 Sequence
< sal_Int8
> aData( nBlockSize
);
1072 sal_Int32 nLastInflated
= 0;
1073 sal_Int32 nInBlock
= 0;
1075 aInflaterLocal
.setInput( aBuffer
);
1078 nLastInflated
= aInflaterLocal
.doInflateSegment( aData
, 0, nBlockSize
);
1079 aCRC
.updateSegment( aData
, 0, nLastInflated
);
1080 nInBlock
+= nLastInflated
;
1081 } while( !aInflater
.finished() && nLastInflated
);
1083 nRealSize
+= nInBlock
;
1087 *nCRC
= aCRC
.getValue();