1*a3872823SAndrew Rist /**************************************************************
2cdf0e10cSrcweir *
3*a3872823SAndrew Rist * Licensed to the Apache Software Foundation (ASF) under one
4*a3872823SAndrew Rist * or more contributor license agreements. See the NOTICE file
5*a3872823SAndrew Rist * distributed with this work for additional information
6*a3872823SAndrew Rist * regarding copyright ownership. The ASF licenses this file
7*a3872823SAndrew Rist * to you under the Apache License, Version 2.0 (the
8*a3872823SAndrew Rist * "License"); you may not use this file except in compliance
9*a3872823SAndrew Rist * with the License. You may obtain a copy of the License at
10cdf0e10cSrcweir *
11*a3872823SAndrew Rist * http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir *
13*a3872823SAndrew Rist * Unless required by applicable law or agreed to in writing,
14*a3872823SAndrew Rist * software distributed under the License is distributed on an
15*a3872823SAndrew Rist * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*a3872823SAndrew Rist * KIND, either express or implied. See the License for the
17*a3872823SAndrew Rist * specific language governing permissions and limitations
18*a3872823SAndrew Rist * under the License.
19cdf0e10cSrcweir *
20*a3872823SAndrew Rist *************************************************************/
21*a3872823SAndrew Rist
22*a3872823SAndrew Rist
23cdf0e10cSrcweir
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_package.hxx"
26cdf0e10cSrcweir
27cdf0e10cSrcweir #include <com/sun/star/lang/XMultiServiceFactory.hpp>
28cdf0e10cSrcweir #include <com/sun/star/ucb/XProgressHandler.hpp>
29cdf0e10cSrcweir #include <com/sun/star/packages/zip/ZipConstants.hpp>
30cdf0e10cSrcweir #include <com/sun/star/xml/crypto/XCipherContext.hpp>
31cdf0e10cSrcweir #include <com/sun/star/xml/crypto/XDigestContext.hpp>
32cdf0e10cSrcweir #include <com/sun/star/xml/crypto/XCipherContextSupplier.hpp>
33cdf0e10cSrcweir #include <com/sun/star/xml/crypto/XDigestContextSupplier.hpp>
34cdf0e10cSrcweir #include <com/sun/star/xml/crypto/CipherID.hpp>
35cdf0e10cSrcweir #include <com/sun/star/xml/crypto/DigestID.hpp>
36cdf0e10cSrcweir
37cdf0e10cSrcweir #include <comphelper/storagehelper.hxx>
38cdf0e10cSrcweir #include <comphelper/processfactory.hxx>
39cdf0e10cSrcweir #include <rtl/digest.h>
40cdf0e10cSrcweir
41cdf0e10cSrcweir #include <vector>
42cdf0e10cSrcweir
43cdf0e10cSrcweir #include "blowfishcontext.hxx"
44cdf0e10cSrcweir #include "sha1context.hxx"
45cdf0e10cSrcweir #include <ZipFile.hxx>
46cdf0e10cSrcweir #include <ZipEnumeration.hxx>
47cdf0e10cSrcweir #include <XUnbufferedStream.hxx>
48cdf0e10cSrcweir #include <PackageConstants.hxx>
49cdf0e10cSrcweir #include <EncryptedDataHeader.hxx>
50cdf0e10cSrcweir #include <EncryptionData.hxx>
51cdf0e10cSrcweir #include <MemoryByteGrabber.hxx>
52cdf0e10cSrcweir
53cdf0e10cSrcweir #include <CRC32.hxx>
54cdf0e10cSrcweir
55cdf0e10cSrcweir #define AES_CBC_BLOCK_SIZE 16
56cdf0e10cSrcweir
57cdf0e10cSrcweir using namespace vos;
58cdf0e10cSrcweir using namespace rtl;
59cdf0e10cSrcweir using namespace com::sun::star;
60cdf0e10cSrcweir using namespace com::sun::star::io;
61cdf0e10cSrcweir using namespace com::sun::star::uno;
62cdf0e10cSrcweir using namespace com::sun::star::ucb;
63cdf0e10cSrcweir using namespace com::sun::star::lang;
64cdf0e10cSrcweir using namespace com::sun::star::packages;
65cdf0e10cSrcweir using namespace com::sun::star::packages::zip;
66cdf0e10cSrcweir using namespace com::sun::star::packages::zip::ZipConstants;
67cdf0e10cSrcweir
68cdf0e10cSrcweir
69cdf0e10cSrcweir /** This class is used to read entries from a zip file
70cdf0e10cSrcweir */
ZipFile(uno::Reference<XInputStream> & xInput,const uno::Reference<XMultiServiceFactory> & xNewFactory,sal_Bool bInitialise)71cdf0e10cSrcweir ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference < XMultiServiceFactory > &xNewFactory, sal_Bool bInitialise )
72cdf0e10cSrcweir throw(IOException, ZipException, RuntimeException)
73cdf0e10cSrcweir : aGrabber(xInput)
74cdf0e10cSrcweir , aInflater (sal_True)
75cdf0e10cSrcweir , xStream(xInput)
76cdf0e10cSrcweir , xSeek(xInput, UNO_QUERY)
77cdf0e10cSrcweir , m_xFactory ( xNewFactory )
78cdf0e10cSrcweir , bRecoveryMode( sal_False )
79cdf0e10cSrcweir {
80cdf0e10cSrcweir if (bInitialise)
81cdf0e10cSrcweir {
82cdf0e10cSrcweir if ( readCEN() == -1 )
83cdf0e10cSrcweir {
84cdf0e10cSrcweir aEntries.clear();
85cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "stream data looks to be broken" ) ), uno::Reference < XInterface > () );
86cdf0e10cSrcweir }
87cdf0e10cSrcweir }
88cdf0e10cSrcweir }
89cdf0e10cSrcweir
90cdf0e10cSrcweir
91cdf0e10cSrcweir
ZipFile(uno::Reference<XInputStream> & xInput,const uno::Reference<XMultiServiceFactory> & xNewFactory,sal_Bool bInitialise,sal_Bool bForceRecovery,uno::Reference<XProgressHandler> xProgress)92cdf0e10cSrcweir ZipFile::ZipFile( uno::Reference < XInputStream > &xInput, const uno::Reference < XMultiServiceFactory > &xNewFactory, sal_Bool bInitialise, sal_Bool bForceRecovery, uno::Reference < XProgressHandler > xProgress )
93cdf0e10cSrcweir throw(IOException, ZipException, RuntimeException)
94cdf0e10cSrcweir : aGrabber(xInput)
95cdf0e10cSrcweir , aInflater (sal_True)
96cdf0e10cSrcweir , xStream(xInput)
97cdf0e10cSrcweir , xSeek(xInput, UNO_QUERY)
98cdf0e10cSrcweir , m_xFactory ( xNewFactory )
99cdf0e10cSrcweir , xProgressHandler( xProgress )
100cdf0e10cSrcweir , bRecoveryMode( bForceRecovery )
101cdf0e10cSrcweir {
102cdf0e10cSrcweir if (bInitialise)
103cdf0e10cSrcweir {
104cdf0e10cSrcweir if ( bForceRecovery )
105cdf0e10cSrcweir {
106cdf0e10cSrcweir recover();
107cdf0e10cSrcweir }
108cdf0e10cSrcweir else if ( readCEN() == -1 )
109cdf0e10cSrcweir {
110cdf0e10cSrcweir aEntries.clear();
111cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "stream data looks to be broken" ) ), uno::Reference < XInterface > () );
112cdf0e10cSrcweir }
113cdf0e10cSrcweir }
114cdf0e10cSrcweir }
115cdf0e10cSrcweir
~ZipFile()116cdf0e10cSrcweir ZipFile::~ZipFile()
117cdf0e10cSrcweir {
118cdf0e10cSrcweir aEntries.clear();
119cdf0e10cSrcweir }
120cdf0e10cSrcweir
setInputStream(uno::Reference<XInputStream> xNewStream)121cdf0e10cSrcweir void ZipFile::setInputStream ( uno::Reference < XInputStream > xNewStream )
122cdf0e10cSrcweir {
123cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
124cdf0e10cSrcweir
125cdf0e10cSrcweir xStream = xNewStream;
126cdf0e10cSrcweir xSeek = uno::Reference < XSeekable > ( xStream, UNO_QUERY );
127cdf0e10cSrcweir aGrabber.setInputStream ( xStream );
128cdf0e10cSrcweir }
129cdf0e10cSrcweir
StaticGetDigestContextForChecksum(const uno::Reference<lang::XMultiServiceFactory> & xArgFactory,const::rtl::Reference<EncryptionData> & xEncryptionData)130cdf0e10cSrcweir uno::Reference< xml::crypto::XDigestContext > ZipFile::StaticGetDigestContextForChecksum( const uno::Reference< lang::XMultiServiceFactory >& xArgFactory, const ::rtl::Reference< EncryptionData >& xEncryptionData )
131cdf0e10cSrcweir {
132cdf0e10cSrcweir uno::Reference< xml::crypto::XDigestContext > xDigestContext;
133cdf0e10cSrcweir if ( xEncryptionData->m_nCheckAlg == xml::crypto::DigestID::SHA256_1K )
134cdf0e10cSrcweir {
135cdf0e10cSrcweir uno::Reference< lang::XMultiServiceFactory > xFactory = xArgFactory;
136cdf0e10cSrcweir if ( !xFactory.is() )
137cdf0e10cSrcweir xFactory.set( comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW );
138cdf0e10cSrcweir
139cdf0e10cSrcweir uno::Reference< xml::crypto::XDigestContextSupplier > xDigestContextSupplier(
140cdf0e10cSrcweir xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.NSSInitializer" ) ) ),
141cdf0e10cSrcweir uno::UNO_QUERY_THROW );
142cdf0e10cSrcweir
143cdf0e10cSrcweir xDigestContext.set( xDigestContextSupplier->getDigestContext( xEncryptionData->m_nCheckAlg, uno::Sequence< beans::NamedValue >() ), uno::UNO_SET_THROW );
144cdf0e10cSrcweir }
145cdf0e10cSrcweir else if ( xEncryptionData->m_nCheckAlg == xml::crypto::DigestID::SHA1_1K )
146cdf0e10cSrcweir xDigestContext.set( SHA1DigestContext::Create(), uno::UNO_SET_THROW );
147cdf0e10cSrcweir
148cdf0e10cSrcweir return xDigestContext;
149cdf0e10cSrcweir }
150cdf0e10cSrcweir
StaticGetCipher(const uno::Reference<lang::XMultiServiceFactory> & xArgFactory,const::rtl::Reference<EncryptionData> & xEncryptionData,bool bEncrypt)151cdf0e10cSrcweir uno::Reference< xml::crypto::XCipherContext > ZipFile::StaticGetCipher( const uno::Reference< lang::XMultiServiceFactory >& xArgFactory, const ::rtl::Reference< EncryptionData >& xEncryptionData, bool bEncrypt )
152cdf0e10cSrcweir {
153cdf0e10cSrcweir uno::Reference< xml::crypto::XCipherContext > xResult;
154cdf0e10cSrcweir
155cdf0e10cSrcweir try
156cdf0e10cSrcweir {
157cdf0e10cSrcweir uno::Sequence< sal_Int8 > aDerivedKey( xEncryptionData->m_nDerivedKeySize );
158cdf0e10cSrcweir if ( rtl_Digest_E_None != rtl_digest_PBKDF2( reinterpret_cast< sal_uInt8* >( aDerivedKey.getArray() ),
159cdf0e10cSrcweir aDerivedKey.getLength(),
160cdf0e10cSrcweir reinterpret_cast< const sal_uInt8 * > (xEncryptionData->m_aKey.getConstArray() ),
161cdf0e10cSrcweir xEncryptionData->m_aKey.getLength(),
162cdf0e10cSrcweir reinterpret_cast< const sal_uInt8 * > ( xEncryptionData->m_aSalt.getConstArray() ),
163cdf0e10cSrcweir xEncryptionData->m_aSalt.getLength(),
164cdf0e10cSrcweir xEncryptionData->m_nIterationCount ) )
165cdf0e10cSrcweir {
166cdf0e10cSrcweir throw ZipIOException( ::rtl::OUString::createFromAscii( "Can not create derived key!\n" ),
167cdf0e10cSrcweir uno::Reference< XInterface >() );
168cdf0e10cSrcweir }
169cdf0e10cSrcweir
170cdf0e10cSrcweir if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::AES_CBC_W3C_PADDING )
171cdf0e10cSrcweir {
172cdf0e10cSrcweir uno::Reference< lang::XMultiServiceFactory > xFactory = xArgFactory;
173cdf0e10cSrcweir if ( !xFactory.is() )
174cdf0e10cSrcweir xFactory.set( comphelper::getProcessServiceFactory(), uno::UNO_SET_THROW );
175cdf0e10cSrcweir
176cdf0e10cSrcweir uno::Reference< xml::crypto::XCipherContextSupplier > xCipherContextSupplier(
177cdf0e10cSrcweir xFactory->createInstance( rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "com.sun.star.xml.crypto.NSSInitializer" ) ) ),
178cdf0e10cSrcweir uno::UNO_QUERY_THROW );
179cdf0e10cSrcweir
180cdf0e10cSrcweir xResult = xCipherContextSupplier->getCipherContext( xEncryptionData->m_nEncAlg, aDerivedKey, xEncryptionData->m_aInitVector, bEncrypt, uno::Sequence< beans::NamedValue >() );
181cdf0e10cSrcweir }
182cdf0e10cSrcweir else if ( xEncryptionData->m_nEncAlg == xml::crypto::CipherID::BLOWFISH_CFB_8 )
183cdf0e10cSrcweir {
184cdf0e10cSrcweir xResult = BlowfishCFB8CipherContext::Create( aDerivedKey, xEncryptionData->m_aInitVector, bEncrypt );
185cdf0e10cSrcweir }
186cdf0e10cSrcweir else
187cdf0e10cSrcweir {
188cdf0e10cSrcweir throw ZipIOException( ::rtl::OUString::createFromAscii( "Unknown cipher algorithm is requested!\n" ),
189cdf0e10cSrcweir uno::Reference< XInterface >() );
190cdf0e10cSrcweir }
191cdf0e10cSrcweir }
192cdf0e10cSrcweir catch( uno::Exception& )
193cdf0e10cSrcweir {
194cdf0e10cSrcweir OSL_ENSURE( sal_False, "Can not create cipher context!" );
195cdf0e10cSrcweir }
196cdf0e10cSrcweir
197cdf0e10cSrcweir return xResult;
198cdf0e10cSrcweir }
199cdf0e10cSrcweir
StaticFillHeader(const::rtl::Reference<EncryptionData> & rData,sal_Int32 nSize,const::rtl::OUString & aMediaType,sal_Int8 * & pHeader)200cdf0e10cSrcweir void ZipFile::StaticFillHeader( const ::rtl::Reference< EncryptionData >& rData,
201cdf0e10cSrcweir sal_Int32 nSize,
202cdf0e10cSrcweir const ::rtl::OUString& aMediaType,
203cdf0e10cSrcweir sal_Int8 * & pHeader )
204cdf0e10cSrcweir {
205cdf0e10cSrcweir // I think it's safe to restrict vector and salt length to 2 bytes !
206cdf0e10cSrcweir sal_Int16 nIVLength = static_cast < sal_Int16 > ( rData->m_aInitVector.getLength() );
207cdf0e10cSrcweir sal_Int16 nSaltLength = static_cast < sal_Int16 > ( rData->m_aSalt.getLength() );
208cdf0e10cSrcweir sal_Int16 nDigestLength = static_cast < sal_Int16 > ( rData->m_aDigest.getLength() );
209cdf0e10cSrcweir sal_Int16 nMediaTypeLength = static_cast < sal_Int16 > ( aMediaType.getLength() * sizeof( sal_Unicode ) );
210cdf0e10cSrcweir
211cdf0e10cSrcweir // First the header
212cdf0e10cSrcweir *(pHeader++) = ( n_ConstHeader >> 0 ) & 0xFF;
213cdf0e10cSrcweir *(pHeader++) = ( n_ConstHeader >> 8 ) & 0xFF;
214cdf0e10cSrcweir *(pHeader++) = ( n_ConstHeader >> 16 ) & 0xFF;
215cdf0e10cSrcweir *(pHeader++) = ( n_ConstHeader >> 24 ) & 0xFF;
216cdf0e10cSrcweir
217cdf0e10cSrcweir // Then the version
218cdf0e10cSrcweir *(pHeader++) = ( n_ConstCurrentVersion >> 0 ) & 0xFF;
219cdf0e10cSrcweir *(pHeader++) = ( n_ConstCurrentVersion >> 8 ) & 0xFF;
220cdf0e10cSrcweir
221cdf0e10cSrcweir // Then the iteration Count
222cdf0e10cSrcweir sal_Int32 nIterationCount = rData->m_nIterationCount;
223cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 0 ) & 0xFF);
224cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 8 ) & 0xFF);
225cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 16 ) & 0xFF);
226cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 24 ) & 0xFF);
227cdf0e10cSrcweir
228cdf0e10cSrcweir // Then the size
229cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 0 ) & 0xFF);
230cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 8 ) & 0xFF);
231cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 16 ) & 0xFF);
232cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 24 ) & 0xFF);
233cdf0e10cSrcweir
234cdf0e10cSrcweir // Then the encryption algorithm
235cdf0e10cSrcweir sal_Int32 nEncAlgID = rData->m_nEncAlg;
236cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 0 ) & 0xFF);
237cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 8 ) & 0xFF);
238cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 16 ) & 0xFF);
239cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nEncAlgID >> 24 ) & 0xFF);
240cdf0e10cSrcweir
241cdf0e10cSrcweir // Then the checksum algorithm
242cdf0e10cSrcweir sal_Int32 nChecksumAlgID = rData->m_nCheckAlg;
243cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 0 ) & 0xFF);
244cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 8 ) & 0xFF);
245cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 16 ) & 0xFF);
246cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nChecksumAlgID >> 24 ) & 0xFF);
247cdf0e10cSrcweir
248cdf0e10cSrcweir // Then the derived key size
249cdf0e10cSrcweir sal_Int32 nDerivedKeySize = rData->m_nDerivedKeySize;
250cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 0 ) & 0xFF);
251cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 8 ) & 0xFF);
252cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 16 ) & 0xFF);
253cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nDerivedKeySize >> 24 ) & 0xFF);
254cdf0e10cSrcweir
255cdf0e10cSrcweir // Then the start key generation algorithm
256cdf0e10cSrcweir sal_Int32 nKeyAlgID = rData->m_nStartKeyGenID;
257cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 0 ) & 0xFF);
258cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 8 ) & 0xFF);
259cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 16 ) & 0xFF);
260cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nKeyAlgID >> 24 ) & 0xFF);
261cdf0e10cSrcweir
262cdf0e10cSrcweir // Then the salt length
263cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nSaltLength >> 0 ) & 0xFF);
264cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nSaltLength >> 8 ) & 0xFF);
265cdf0e10cSrcweir
266cdf0e10cSrcweir // Then the IV length
267cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nIVLength >> 0 ) & 0xFF);
268cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nIVLength >> 8 ) & 0xFF);
269cdf0e10cSrcweir
270cdf0e10cSrcweir // Then the digest length
271cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nDigestLength >> 0 ) & 0xFF);
272cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nDigestLength >> 8 ) & 0xFF);
273cdf0e10cSrcweir
274cdf0e10cSrcweir // Then the mediatype length
275cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nMediaTypeLength >> 0 ) & 0xFF);
276cdf0e10cSrcweir *(pHeader++) = static_cast< sal_Int8 >(( nMediaTypeLength >> 8 ) & 0xFF);
277cdf0e10cSrcweir
278cdf0e10cSrcweir // Then the salt content
279cdf0e10cSrcweir rtl_copyMemory ( pHeader, rData->m_aSalt.getConstArray(), nSaltLength );
280cdf0e10cSrcweir pHeader += nSaltLength;
281cdf0e10cSrcweir
282cdf0e10cSrcweir // Then the IV content
283cdf0e10cSrcweir rtl_copyMemory ( pHeader, rData->m_aInitVector.getConstArray(), nIVLength );
284cdf0e10cSrcweir pHeader += nIVLength;
285cdf0e10cSrcweir
286cdf0e10cSrcweir // Then the digest content
287cdf0e10cSrcweir rtl_copyMemory ( pHeader, rData->m_aDigest.getConstArray(), nDigestLength );
288cdf0e10cSrcweir pHeader += nDigestLength;
289cdf0e10cSrcweir
290cdf0e10cSrcweir // Then the mediatype itself
291cdf0e10cSrcweir rtl_copyMemory ( pHeader, aMediaType.getStr(), nMediaTypeLength );
292cdf0e10cSrcweir pHeader += nMediaTypeLength;
293cdf0e10cSrcweir }
294cdf0e10cSrcweir
StaticFillData(::rtl::Reference<BaseEncryptionData> & rData,sal_Int32 & rEncAlg,sal_Int32 & rChecksumAlg,sal_Int32 & rDerivedKeySize,sal_Int32 & rStartKeyGenID,sal_Int32 & rSize,::rtl::OUString & aMediaType,const uno::Reference<XInputStream> & rStream)295cdf0e10cSrcweir sal_Bool ZipFile::StaticFillData ( ::rtl::Reference< BaseEncryptionData > & rData,
296cdf0e10cSrcweir sal_Int32 &rEncAlg,
297cdf0e10cSrcweir sal_Int32 &rChecksumAlg,
298cdf0e10cSrcweir sal_Int32 &rDerivedKeySize,
299cdf0e10cSrcweir sal_Int32 &rStartKeyGenID,
300cdf0e10cSrcweir sal_Int32 &rSize,
301cdf0e10cSrcweir ::rtl::OUString& aMediaType,
302cdf0e10cSrcweir const uno::Reference< XInputStream >& rStream )
303cdf0e10cSrcweir {
304cdf0e10cSrcweir sal_Bool bOk = sal_False;
305cdf0e10cSrcweir const sal_Int32 nHeaderSize = n_ConstHeaderSize - 4;
306cdf0e10cSrcweir Sequence < sal_Int8 > aBuffer ( nHeaderSize );
307cdf0e10cSrcweir if ( nHeaderSize == rStream->readBytes ( aBuffer, nHeaderSize ) )
308cdf0e10cSrcweir {
309cdf0e10cSrcweir sal_Int16 nPos = 0;
310cdf0e10cSrcweir sal_Int8 *pBuffer = aBuffer.getArray();
311cdf0e10cSrcweir sal_Int16 nVersion = pBuffer[nPos++] & 0xFF;
312cdf0e10cSrcweir nVersion |= ( pBuffer[nPos++] & 0xFF ) << 8;
313cdf0e10cSrcweir if ( nVersion == n_ConstCurrentVersion )
314cdf0e10cSrcweir {
315cdf0e10cSrcweir sal_Int32 nCount = pBuffer[nPos++] & 0xFF;
316cdf0e10cSrcweir nCount |= ( pBuffer[nPos++] & 0xFF ) << 8;
317cdf0e10cSrcweir nCount |= ( pBuffer[nPos++] & 0xFF ) << 16;
318cdf0e10cSrcweir nCount |= ( pBuffer[nPos++] & 0xFF ) << 24;
319cdf0e10cSrcweir rData->m_nIterationCount = nCount;
320cdf0e10cSrcweir
321cdf0e10cSrcweir rSize = pBuffer[nPos++] & 0xFF;
322cdf0e10cSrcweir rSize |= ( pBuffer[nPos++] & 0xFF ) << 8;
323cdf0e10cSrcweir rSize |= ( pBuffer[nPos++] & 0xFF ) << 16;
324cdf0e10cSrcweir rSize |= ( pBuffer[nPos++] & 0xFF ) << 24;
325cdf0e10cSrcweir
326cdf0e10cSrcweir rEncAlg = pBuffer[nPos++] & 0xFF;
327cdf0e10cSrcweir rEncAlg |= ( pBuffer[nPos++] & 0xFF ) << 8;
328cdf0e10cSrcweir rEncAlg |= ( pBuffer[nPos++] & 0xFF ) << 16;
329cdf0e10cSrcweir rEncAlg |= ( pBuffer[nPos++] & 0xFF ) << 24;
330cdf0e10cSrcweir
331cdf0e10cSrcweir rChecksumAlg = pBuffer[nPos++] & 0xFF;
332cdf0e10cSrcweir rChecksumAlg |= ( pBuffer[nPos++] & 0xFF ) << 8;
333cdf0e10cSrcweir rChecksumAlg |= ( pBuffer[nPos++] & 0xFF ) << 16;
334cdf0e10cSrcweir rChecksumAlg |= ( pBuffer[nPos++] & 0xFF ) << 24;
335cdf0e10cSrcweir
336cdf0e10cSrcweir rDerivedKeySize = pBuffer[nPos++] & 0xFF;
337cdf0e10cSrcweir rDerivedKeySize |= ( pBuffer[nPos++] & 0xFF ) << 8;
338cdf0e10cSrcweir rDerivedKeySize |= ( pBuffer[nPos++] & 0xFF ) << 16;
339cdf0e10cSrcweir rDerivedKeySize |= ( pBuffer[nPos++] & 0xFF ) << 24;
340cdf0e10cSrcweir
341cdf0e10cSrcweir rStartKeyGenID = pBuffer[nPos++] & 0xFF;
342cdf0e10cSrcweir rStartKeyGenID |= ( pBuffer[nPos++] & 0xFF ) << 8;
343cdf0e10cSrcweir rStartKeyGenID |= ( pBuffer[nPos++] & 0xFF ) << 16;
344cdf0e10cSrcweir rStartKeyGenID |= ( pBuffer[nPos++] & 0xFF ) << 24;
345cdf0e10cSrcweir
346cdf0e10cSrcweir sal_Int16 nSaltLength = pBuffer[nPos++] & 0xFF;
347cdf0e10cSrcweir nSaltLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
348cdf0e10cSrcweir sal_Int16 nIVLength = ( pBuffer[nPos++] & 0xFF );
349cdf0e10cSrcweir nIVLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
350cdf0e10cSrcweir sal_Int16 nDigestLength = pBuffer[nPos++] & 0xFF;
351cdf0e10cSrcweir nDigestLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
352cdf0e10cSrcweir
353cdf0e10cSrcweir sal_Int16 nMediaTypeLength = pBuffer[nPos++] & 0xFF;
354cdf0e10cSrcweir nMediaTypeLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
355cdf0e10cSrcweir
356cdf0e10cSrcweir if ( nSaltLength == rStream->readBytes ( aBuffer, nSaltLength ) )
357cdf0e10cSrcweir {
358cdf0e10cSrcweir rData->m_aSalt.realloc ( nSaltLength );
359cdf0e10cSrcweir rtl_copyMemory ( rData->m_aSalt.getArray(), aBuffer.getConstArray(), nSaltLength );
360cdf0e10cSrcweir if ( nIVLength == rStream->readBytes ( aBuffer, nIVLength ) )
361cdf0e10cSrcweir {
362cdf0e10cSrcweir rData->m_aInitVector.realloc ( nIVLength );
363cdf0e10cSrcweir rtl_copyMemory ( rData->m_aInitVector.getArray(), aBuffer.getConstArray(), nIVLength );
364cdf0e10cSrcweir if ( nDigestLength == rStream->readBytes ( aBuffer, nDigestLength ) )
365cdf0e10cSrcweir {
366cdf0e10cSrcweir rData->m_aDigest.realloc ( nDigestLength );
367cdf0e10cSrcweir rtl_copyMemory ( rData->m_aDigest.getArray(), aBuffer.getConstArray(), nDigestLength );
368cdf0e10cSrcweir
369cdf0e10cSrcweir if ( nMediaTypeLength == rStream->readBytes ( aBuffer, nMediaTypeLength ) )
370cdf0e10cSrcweir {
371cdf0e10cSrcweir aMediaType = ::rtl::OUString( (sal_Unicode*)aBuffer.getConstArray(),
372cdf0e10cSrcweir nMediaTypeLength / sizeof( sal_Unicode ) );
373cdf0e10cSrcweir bOk = sal_True;
374cdf0e10cSrcweir }
375cdf0e10cSrcweir }
376cdf0e10cSrcweir }
377cdf0e10cSrcweir }
378cdf0e10cSrcweir }
379cdf0e10cSrcweir }
380cdf0e10cSrcweir return bOk;
381cdf0e10cSrcweir }
382cdf0e10cSrcweir
StaticGetDataFromRawStream(const uno::Reference<lang::XMultiServiceFactory> & xFactory,const uno::Reference<XInputStream> & xStream,const::rtl::Reference<EncryptionData> & rData)383cdf0e10cSrcweir uno::Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const uno::Reference< lang::XMultiServiceFactory >& xFactory,
384cdf0e10cSrcweir const uno::Reference< XInputStream >& xStream,
385cdf0e10cSrcweir const ::rtl::Reference< EncryptionData > &rData )
386cdf0e10cSrcweir throw ( packages::WrongPasswordException, ZipIOException, RuntimeException )
387cdf0e10cSrcweir {
388cdf0e10cSrcweir if ( !rData.is() )
389cdf0e10cSrcweir throw ZipIOException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ),
390cdf0e10cSrcweir uno::Reference< XInterface >() );
391cdf0e10cSrcweir
392cdf0e10cSrcweir if ( !rData->m_aKey.getLength() )
393cdf0e10cSrcweir throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
394cdf0e10cSrcweir
395cdf0e10cSrcweir uno::Reference< XSeekable > xSeek( xStream, UNO_QUERY );
396cdf0e10cSrcweir if ( !xSeek.is() )
397cdf0e10cSrcweir throw ZipIOException( OUString::createFromAscii( "The stream must be seekable!\n" ),
398cdf0e10cSrcweir uno::Reference< XInterface >() );
399cdf0e10cSrcweir
400cdf0e10cSrcweir
401cdf0e10cSrcweir // if we have a digest, then this file is an encrypted one and we should
402cdf0e10cSrcweir // check if we can decrypt it or not
403cdf0e10cSrcweir OSL_ENSURE( rData->m_aDigest.getLength(), "Can't detect password correctness without digest!\n" );
404cdf0e10cSrcweir if ( rData->m_aDigest.getLength() )
405cdf0e10cSrcweir {
406cdf0e10cSrcweir sal_Int32 nSize = sal::static_int_cast< sal_Int32 >( xSeek->getLength() );
407cdf0e10cSrcweir if ( nSize > n_ConstDigestLength + 32 )
408cdf0e10cSrcweir nSize = n_ConstDigestLength + 32;
409cdf0e10cSrcweir
410cdf0e10cSrcweir // skip header
411cdf0e10cSrcweir xSeek->seek( n_ConstHeaderSize + rData->m_aInitVector.getLength() +
412cdf0e10cSrcweir rData->m_aSalt.getLength() + rData->m_aDigest.getLength() );
413cdf0e10cSrcweir
414cdf0e10cSrcweir // Only want to read enough to verify the digest
415cdf0e10cSrcweir Sequence < sal_Int8 > aReadBuffer ( nSize );
416cdf0e10cSrcweir
417cdf0e10cSrcweir xStream->readBytes( aReadBuffer, nSize );
418cdf0e10cSrcweir
419cdf0e10cSrcweir if ( !StaticHasValidPassword( xFactory, aReadBuffer, rData ) )
420cdf0e10cSrcweir throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
421cdf0e10cSrcweir }
422cdf0e10cSrcweir
423cdf0e10cSrcweir return new XUnbufferedStream( xFactory, xStream, rData );
424cdf0e10cSrcweir }
425cdf0e10cSrcweir
426cdf0e10cSrcweir #if 0
427cdf0e10cSrcweir // for debugging purposes
428cdf0e10cSrcweir void CheckSequence( const uno::Sequence< sal_Int8 >& aSequence )
429cdf0e10cSrcweir {
430cdf0e10cSrcweir if ( aSequence.getLength() )
431cdf0e10cSrcweir {
432cdf0e10cSrcweir sal_Int32* pPointer = *( (sal_Int32**)&aSequence );
433cdf0e10cSrcweir sal_Int32 nSize = *( pPointer + 1 );
434cdf0e10cSrcweir sal_Int32 nMemSize = *( pPointer - 2 );
435cdf0e10cSrcweir sal_Int32 nUsedMemSize = ( nSize + 4 * sizeof( sal_Int32 ) );
436cdf0e10cSrcweir OSL_ENSURE( nSize == aSequence.getLength() && nUsedMemSize + 7 - ( nUsedMemSize - 1 ) % 8 == nMemSize, "Broken Sequence!" );
437cdf0e10cSrcweir }
438cdf0e10cSrcweir }
439cdf0e10cSrcweir #endif
440cdf0e10cSrcweir
StaticHasValidPassword(const uno::Reference<lang::XMultiServiceFactory> & xFactory,const Sequence<sal_Int8> & aReadBuffer,const::rtl::Reference<EncryptionData> & rData)441cdf0e10cSrcweir sal_Bool ZipFile::StaticHasValidPassword( const uno::Reference< lang::XMultiServiceFactory >& xFactory, const Sequence< sal_Int8 > &aReadBuffer, const ::rtl::Reference< EncryptionData > &rData )
442cdf0e10cSrcweir {
443cdf0e10cSrcweir if ( !rData.is() || !rData->m_aKey.getLength() )
444cdf0e10cSrcweir return sal_False;
445cdf0e10cSrcweir
446cdf0e10cSrcweir sal_Bool bRet = sal_False;
447cdf0e10cSrcweir
448cdf0e10cSrcweir uno::Reference< xml::crypto::XCipherContext > xCipher( StaticGetCipher( xFactory, rData, false ), uno::UNO_SET_THROW );
449cdf0e10cSrcweir
450cdf0e10cSrcweir uno::Sequence< sal_Int8 > aDecryptBuffer;
451cdf0e10cSrcweir uno::Sequence< sal_Int8 > aDecryptBuffer2;
452cdf0e10cSrcweir try
453cdf0e10cSrcweir {
454cdf0e10cSrcweir aDecryptBuffer = xCipher->convertWithCipherContext( aReadBuffer );
455cdf0e10cSrcweir aDecryptBuffer2 = xCipher->finalizeCipherContextAndDispose();
456cdf0e10cSrcweir }
457cdf0e10cSrcweir catch( uno::Exception& )
458cdf0e10cSrcweir {
459cdf0e10cSrcweir // decryption with padding will throw the exception in finalizing if the buffer represent only part of the stream
460cdf0e10cSrcweir // it is no problem, actually this is why we read 32 additional bytes ( two of maximal possible encryption blocks )
461cdf0e10cSrcweir }
462cdf0e10cSrcweir
463cdf0e10cSrcweir if ( aDecryptBuffer2.getLength() )
464cdf0e10cSrcweir {
465cdf0e10cSrcweir sal_Int32 nOldLen = aDecryptBuffer.getLength();
466cdf0e10cSrcweir aDecryptBuffer.realloc( nOldLen + aDecryptBuffer2.getLength() );
467cdf0e10cSrcweir rtl_copyMemory( aDecryptBuffer.getArray() + nOldLen, aDecryptBuffer2.getArray(), aDecryptBuffer2.getLength() );
468cdf0e10cSrcweir }
469cdf0e10cSrcweir
470cdf0e10cSrcweir if ( aDecryptBuffer.getLength() > n_ConstDigestLength )
471cdf0e10cSrcweir aDecryptBuffer.realloc( n_ConstDigestLength );
472cdf0e10cSrcweir
473cdf0e10cSrcweir uno::Sequence< sal_Int8 > aDigestSeq;
474cdf0e10cSrcweir uno::Reference< xml::crypto::XDigestContext > xDigestContext( StaticGetDigestContextForChecksum( xFactory, rData ), uno::UNO_SET_THROW );
475cdf0e10cSrcweir
476cdf0e10cSrcweir xDigestContext->updateDigest( aDecryptBuffer );
477cdf0e10cSrcweir aDigestSeq = xDigestContext->finalizeDigestAndDispose();
478cdf0e10cSrcweir
479cdf0e10cSrcweir // If we don't have a digest, then we have to assume that the password is correct
480cdf0e10cSrcweir if ( rData->m_aDigest.getLength() != 0 &&
481cdf0e10cSrcweir ( aDigestSeq.getLength() != rData->m_aDigest.getLength() ||
482cdf0e10cSrcweir 0 != rtl_compareMemory ( aDigestSeq.getConstArray(),
483cdf0e10cSrcweir rData->m_aDigest.getConstArray(),
484cdf0e10cSrcweir aDigestSeq.getLength() ) ) )
485cdf0e10cSrcweir {
486cdf0e10cSrcweir // We should probably tell the user that the password they entered was wrong
487cdf0e10cSrcweir }
488cdf0e10cSrcweir else
489cdf0e10cSrcweir bRet = sal_True;
490cdf0e10cSrcweir
491cdf0e10cSrcweir return bRet;
492cdf0e10cSrcweir }
493cdf0e10cSrcweir
hasValidPassword(ZipEntry & rEntry,const::rtl::Reference<EncryptionData> & rData)494cdf0e10cSrcweir sal_Bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const ::rtl::Reference< EncryptionData >& rData )
495cdf0e10cSrcweir {
496cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
497cdf0e10cSrcweir
498cdf0e10cSrcweir sal_Bool bRet = sal_False;
499cdf0e10cSrcweir if ( rData.is() && rData->m_aKey.getLength() )
500cdf0e10cSrcweir {
501cdf0e10cSrcweir xSeek->seek( rEntry.nOffset );
502cdf0e10cSrcweir sal_Int32 nSize = rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize;
503cdf0e10cSrcweir
504cdf0e10cSrcweir // Only want to read enough to verify the digest
505cdf0e10cSrcweir if ( nSize > n_ConstDigestDecrypt )
506cdf0e10cSrcweir nSize = n_ConstDigestDecrypt;
507cdf0e10cSrcweir
508cdf0e10cSrcweir Sequence < sal_Int8 > aReadBuffer ( nSize );
509cdf0e10cSrcweir
510cdf0e10cSrcweir xStream->readBytes( aReadBuffer, nSize );
511cdf0e10cSrcweir
512cdf0e10cSrcweir bRet = StaticHasValidPassword( m_xFactory, aReadBuffer, rData );
513cdf0e10cSrcweir }
514cdf0e10cSrcweir
515cdf0e10cSrcweir return bRet;
516cdf0e10cSrcweir }
517cdf0e10cSrcweir
createUnbufferedStream(SotMutexHolderRef aMutexHolder,ZipEntry & rEntry,const::rtl::Reference<EncryptionData> & rData,sal_Int8 nStreamMode,sal_Bool bIsEncrypted,::rtl::OUString aMediaType)518cdf0e10cSrcweir uno::Reference< XInputStream > ZipFile::createUnbufferedStream(
519cdf0e10cSrcweir SotMutexHolderRef aMutexHolder,
520cdf0e10cSrcweir ZipEntry & rEntry,
521cdf0e10cSrcweir const ::rtl::Reference< EncryptionData > &rData,
522cdf0e10cSrcweir sal_Int8 nStreamMode,
523cdf0e10cSrcweir sal_Bool bIsEncrypted,
524cdf0e10cSrcweir ::rtl::OUString aMediaType )
525cdf0e10cSrcweir {
526cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
527cdf0e10cSrcweir
528cdf0e10cSrcweir return new XUnbufferedStream ( m_xFactory, aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode );
529cdf0e10cSrcweir }
530cdf0e10cSrcweir
531cdf0e10cSrcweir
entries()532cdf0e10cSrcweir ZipEnumeration * SAL_CALL ZipFile::entries( )
533cdf0e10cSrcweir {
534cdf0e10cSrcweir return new ZipEnumeration ( aEntries );
535cdf0e10cSrcweir }
536cdf0e10cSrcweir
getInputStream(ZipEntry & rEntry,const::rtl::Reference<EncryptionData> & rData,sal_Bool bIsEncrypted,SotMutexHolderRef aMutexHolder)537cdf0e10cSrcweir uno::Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry,
538cdf0e10cSrcweir const ::rtl::Reference< EncryptionData > &rData,
539cdf0e10cSrcweir sal_Bool bIsEncrypted,
540cdf0e10cSrcweir SotMutexHolderRef aMutexHolder )
541cdf0e10cSrcweir throw(IOException, ZipException, RuntimeException)
542cdf0e10cSrcweir {
543cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
544cdf0e10cSrcweir
545cdf0e10cSrcweir if ( rEntry.nOffset <= 0 )
546cdf0e10cSrcweir readLOC( rEntry );
547cdf0e10cSrcweir
548cdf0e10cSrcweir // We want to return a rawStream if we either don't have a key or if the
549cdf0e10cSrcweir // key is wrong
550cdf0e10cSrcweir
551cdf0e10cSrcweir sal_Bool bNeedRawStream = rEntry.nMethod == STORED;
552cdf0e10cSrcweir
553cdf0e10cSrcweir // if we have a digest, then this file is an encrypted one and we should
554cdf0e10cSrcweir // check if we can decrypt it or not
555cdf0e10cSrcweir if ( bIsEncrypted && rData.is() && rData->m_aDigest.getLength() )
556cdf0e10cSrcweir bNeedRawStream = !hasValidPassword ( rEntry, rData );
557cdf0e10cSrcweir
558cdf0e10cSrcweir return createUnbufferedStream ( aMutexHolder,
559cdf0e10cSrcweir rEntry,
560cdf0e10cSrcweir rData,
561cdf0e10cSrcweir bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA,
562cdf0e10cSrcweir bIsEncrypted );
563cdf0e10cSrcweir }
564cdf0e10cSrcweir
getDataStream(ZipEntry & rEntry,const::rtl::Reference<EncryptionData> & rData,sal_Bool bIsEncrypted,SotMutexHolderRef aMutexHolder)565cdf0e10cSrcweir uno::Reference< XInputStream > SAL_CALL ZipFile::getDataStream( ZipEntry& rEntry,
566cdf0e10cSrcweir const ::rtl::Reference< EncryptionData > &rData,
567cdf0e10cSrcweir sal_Bool bIsEncrypted,
568cdf0e10cSrcweir SotMutexHolderRef aMutexHolder )
569cdf0e10cSrcweir throw ( packages::WrongPasswordException,
570cdf0e10cSrcweir IOException,
571cdf0e10cSrcweir ZipException,
572cdf0e10cSrcweir RuntimeException )
573cdf0e10cSrcweir {
574cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
575cdf0e10cSrcweir
576cdf0e10cSrcweir if ( rEntry.nOffset <= 0 )
577cdf0e10cSrcweir readLOC( rEntry );
578cdf0e10cSrcweir
579cdf0e10cSrcweir // An exception must be thrown in case stream is encrypted and
580cdf0e10cSrcweir // there is no key or the key is wrong
581cdf0e10cSrcweir sal_Bool bNeedRawStream = sal_False;
582cdf0e10cSrcweir if ( bIsEncrypted )
583cdf0e10cSrcweir {
584cdf0e10cSrcweir // in case no digest is provided there is no way
585cdf0e10cSrcweir // to detect password correctness
586cdf0e10cSrcweir if ( !rData.is() )
587cdf0e10cSrcweir throw ZipException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ),
588cdf0e10cSrcweir uno::Reference< XInterface >() );
589cdf0e10cSrcweir
590cdf0e10cSrcweir // if we have a digest, then this file is an encrypted one and we should
591cdf0e10cSrcweir // check if we can decrypt it or not
592cdf0e10cSrcweir OSL_ENSURE( rData->m_aDigest.getLength(), "Can't detect password correctness without digest!\n" );
593cdf0e10cSrcweir if ( rData->m_aDigest.getLength() && !hasValidPassword ( rEntry, rData ) )
594cdf0e10cSrcweir throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
595cdf0e10cSrcweir }
596cdf0e10cSrcweir else
597cdf0e10cSrcweir bNeedRawStream = ( rEntry.nMethod == STORED );
598cdf0e10cSrcweir
599cdf0e10cSrcweir return createUnbufferedStream ( aMutexHolder,
600cdf0e10cSrcweir rEntry,
601cdf0e10cSrcweir rData,
602cdf0e10cSrcweir bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA,
603cdf0e10cSrcweir bIsEncrypted );
604cdf0e10cSrcweir }
605cdf0e10cSrcweir
getRawData(ZipEntry & rEntry,const::rtl::Reference<EncryptionData> & rData,sal_Bool bIsEncrypted,SotMutexHolderRef aMutexHolder)606cdf0e10cSrcweir uno::Reference< XInputStream > SAL_CALL ZipFile::getRawData( ZipEntry& rEntry,
607cdf0e10cSrcweir const ::rtl::Reference< EncryptionData >& rData,
608cdf0e10cSrcweir sal_Bool bIsEncrypted,
609cdf0e10cSrcweir SotMutexHolderRef aMutexHolder )
610cdf0e10cSrcweir throw(IOException, ZipException, RuntimeException)
611cdf0e10cSrcweir {
612cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
613cdf0e10cSrcweir
614cdf0e10cSrcweir if ( rEntry.nOffset <= 0 )
615cdf0e10cSrcweir readLOC( rEntry );
616cdf0e10cSrcweir
617cdf0e10cSrcweir return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted );
618cdf0e10cSrcweir }
619cdf0e10cSrcweir
getWrappedRawStream(ZipEntry & rEntry,const::rtl::Reference<EncryptionData> & rData,const::rtl::OUString & aMediaType,SotMutexHolderRef aMutexHolder)620cdf0e10cSrcweir uno::Reference< XInputStream > SAL_CALL ZipFile::getWrappedRawStream(
621cdf0e10cSrcweir ZipEntry& rEntry,
622cdf0e10cSrcweir const ::rtl::Reference< EncryptionData >& rData,
623cdf0e10cSrcweir const ::rtl::OUString& aMediaType,
624cdf0e10cSrcweir SotMutexHolderRef aMutexHolder )
625cdf0e10cSrcweir throw ( packages::NoEncryptionException,
626cdf0e10cSrcweir IOException,
627cdf0e10cSrcweir ZipException,
628cdf0e10cSrcweir RuntimeException )
629cdf0e10cSrcweir {
630cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
631cdf0e10cSrcweir
632cdf0e10cSrcweir if ( !rData.is() )
633cdf0e10cSrcweir throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
634cdf0e10cSrcweir
635cdf0e10cSrcweir if ( rEntry.nOffset <= 0 )
636cdf0e10cSrcweir readLOC( rEntry );
637cdf0e10cSrcweir
638cdf0e10cSrcweir return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, sal_True, aMediaType );
639cdf0e10cSrcweir }
640cdf0e10cSrcweir
readLOC(ZipEntry & rEntry)641cdf0e10cSrcweir sal_Bool ZipFile::readLOC( ZipEntry &rEntry )
642cdf0e10cSrcweir throw(IOException, ZipException, RuntimeException)
643cdf0e10cSrcweir {
644cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
645cdf0e10cSrcweir
646cdf0e10cSrcweir sal_Int32 nTestSig, nTime, nCRC, nSize, nCompressedSize;
647cdf0e10cSrcweir sal_Int16 nVersion, nFlag, nHow, nPathLen, nExtraLen;
648cdf0e10cSrcweir sal_Int32 nPos = -rEntry.nOffset;
649cdf0e10cSrcweir
650cdf0e10cSrcweir aGrabber.seek(nPos);
651cdf0e10cSrcweir aGrabber >> nTestSig;
652cdf0e10cSrcweir
653cdf0e10cSrcweir if (nTestSig != LOCSIG)
654cdf0e10cSrcweir throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid LOC header (bad signature") ), uno::Reference < XInterface > () );
655cdf0e10cSrcweir aGrabber >> nVersion;
656cdf0e10cSrcweir aGrabber >> nFlag;
657cdf0e10cSrcweir aGrabber >> nHow;
658cdf0e10cSrcweir aGrabber >> nTime;
659cdf0e10cSrcweir aGrabber >> nCRC;
660cdf0e10cSrcweir aGrabber >> nCompressedSize;
661cdf0e10cSrcweir aGrabber >> nSize;
662cdf0e10cSrcweir aGrabber >> nPathLen;
663cdf0e10cSrcweir aGrabber >> nExtraLen;
664cdf0e10cSrcweir rEntry.nOffset = static_cast < sal_Int32 > (aGrabber.getPosition()) + nPathLen + nExtraLen;
665cdf0e10cSrcweir
666cdf0e10cSrcweir // read always in UTF8, some tools seem not to set UTF8 bit
667cdf0e10cSrcweir uno::Sequence < sal_Int8 > aNameBuffer( nPathLen );
668cdf0e10cSrcweir sal_Int32 nRead = aGrabber.readBytes( aNameBuffer, nPathLen );
669cdf0e10cSrcweir if ( nRead < aNameBuffer.getLength() )
670cdf0e10cSrcweir aNameBuffer.realloc( nRead );
671cdf0e10cSrcweir
672cdf0e10cSrcweir ::rtl::OUString sLOCPath = rtl::OUString::intern( (sal_Char *) aNameBuffer.getArray(),
673cdf0e10cSrcweir aNameBuffer.getLength(),
674cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 );
675cdf0e10cSrcweir
676cdf0e10cSrcweir if ( rEntry.nPathLen == -1 ) // the file was created
677cdf0e10cSrcweir {
678cdf0e10cSrcweir rEntry.nPathLen = nPathLen;
679cdf0e10cSrcweir rEntry.sPath = sLOCPath;
680cdf0e10cSrcweir }
681cdf0e10cSrcweir
682cdf0e10cSrcweir // the method can be reset for internal use so it is not checked
683cdf0e10cSrcweir sal_Bool bBroken = rEntry.nVersion != nVersion
684cdf0e10cSrcweir || rEntry.nFlag != nFlag
685cdf0e10cSrcweir || rEntry.nTime != nTime
686cdf0e10cSrcweir || rEntry.nPathLen != nPathLen
687cdf0e10cSrcweir || !rEntry.sPath.equals( sLOCPath );
688cdf0e10cSrcweir
689cdf0e10cSrcweir if ( bBroken && !bRecoveryMode )
690cdf0e10cSrcweir throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
691cdf0e10cSrcweir uno::Reference< XInterface >() );
692cdf0e10cSrcweir
693cdf0e10cSrcweir return sal_True;
694cdf0e10cSrcweir }
695cdf0e10cSrcweir
findEND()696cdf0e10cSrcweir sal_Int32 ZipFile::findEND( )
697cdf0e10cSrcweir throw(IOException, ZipException, RuntimeException)
698cdf0e10cSrcweir {
699cdf0e10cSrcweir // this method is called in constructor only, no need for mutex
700cdf0e10cSrcweir sal_Int32 nLength, nPos, nEnd;
701cdf0e10cSrcweir Sequence < sal_Int8 > aBuffer;
702cdf0e10cSrcweir try
703cdf0e10cSrcweir {
704cdf0e10cSrcweir nLength = static_cast <sal_Int32 > (aGrabber.getLength());
705cdf0e10cSrcweir if (nLength == 0 || nLength < ENDHDR)
706cdf0e10cSrcweir return -1;
707cdf0e10cSrcweir nPos = nLength - ENDHDR - ZIP_MAXNAMELEN;
708cdf0e10cSrcweir nEnd = nPos >= 0 ? nPos : 0 ;
709cdf0e10cSrcweir
710cdf0e10cSrcweir aGrabber.seek( nEnd );
711cdf0e10cSrcweir aGrabber.readBytes ( aBuffer, nLength - nEnd );
712cdf0e10cSrcweir
713cdf0e10cSrcweir const sal_Int8 *pBuffer = aBuffer.getConstArray();
714cdf0e10cSrcweir
715cdf0e10cSrcweir nPos = nLength - nEnd - ENDHDR;
716cdf0e10cSrcweir while ( nPos >= 0 )
717cdf0e10cSrcweir {
718cdf0e10cSrcweir if (pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 5 && pBuffer[nPos+3] == 6 )
719cdf0e10cSrcweir return nPos + nEnd;
720cdf0e10cSrcweir nPos--;
721cdf0e10cSrcweir }
722cdf0e10cSrcweir }
723cdf0e10cSrcweir catch ( IllegalArgumentException& )
724cdf0e10cSrcweir {
725cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () );
726cdf0e10cSrcweir }
727cdf0e10cSrcweir catch ( NotConnectedException& )
728cdf0e10cSrcweir {
729cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () );
730cdf0e10cSrcweir }
731cdf0e10cSrcweir catch ( BufferSizeExceededException& )
732cdf0e10cSrcweir {
733cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () );
734cdf0e10cSrcweir }
735cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () );
736cdf0e10cSrcweir }
737cdf0e10cSrcweir
readCEN()738cdf0e10cSrcweir sal_Int32 ZipFile::readCEN()
739cdf0e10cSrcweir throw(IOException, ZipException, RuntimeException)
740cdf0e10cSrcweir {
741cdf0e10cSrcweir // this method is called in constructor only, no need for mutex
742cdf0e10cSrcweir sal_Int32 nCenLen, nCenPos = -1, nCenOff, nEndPos, nLocPos;
743cdf0e10cSrcweir sal_uInt16 nCount, nTotal;
744cdf0e10cSrcweir
745cdf0e10cSrcweir try
746cdf0e10cSrcweir {
747cdf0e10cSrcweir nEndPos = findEND();
748cdf0e10cSrcweir if (nEndPos == -1)
749cdf0e10cSrcweir return -1;
750cdf0e10cSrcweir aGrabber.seek(nEndPos + ENDTOT);
751cdf0e10cSrcweir aGrabber >> nTotal;
752cdf0e10cSrcweir aGrabber >> nCenLen;
753cdf0e10cSrcweir aGrabber >> nCenOff;
754cdf0e10cSrcweir
755cdf0e10cSrcweir if ( nTotal * CENHDR > nCenLen )
756cdf0e10cSrcweir throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "invalid END header (bad entry count)") ), uno::Reference < XInterface > () );
757cdf0e10cSrcweir
758cdf0e10cSrcweir if ( nTotal > ZIP_MAXENTRIES )
759cdf0e10cSrcweir throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "too many entries in ZIP File") ), uno::Reference < XInterface > () );
760cdf0e10cSrcweir
761cdf0e10cSrcweir if ( nCenLen < 0 || nCenLen > nEndPos )
762cdf0e10cSrcweir throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), uno::Reference < XInterface > () );
763cdf0e10cSrcweir
764cdf0e10cSrcweir nCenPos = nEndPos - nCenLen;
765cdf0e10cSrcweir
766cdf0e10cSrcweir if ( nCenOff < 0 || nCenOff > nCenPos )
767cdf0e10cSrcweir throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), uno::Reference < XInterface > () );
768cdf0e10cSrcweir
769cdf0e10cSrcweir nLocPos = nCenPos - nCenOff;
770cdf0e10cSrcweir aGrabber.seek( nCenPos );
771cdf0e10cSrcweir Sequence < sal_Int8 > aCENBuffer ( nCenLen );
772cdf0e10cSrcweir sal_Int64 nRead = aGrabber.readBytes ( aCENBuffer, nCenLen );
773cdf0e10cSrcweir if ( static_cast < sal_Int64 > ( nCenLen ) != nRead )
774cdf0e10cSrcweir throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Error reading CEN into memory buffer!") ), uno::Reference < XInterface > () );
775cdf0e10cSrcweir
776cdf0e10cSrcweir MemoryByteGrabber aMemGrabber ( aCENBuffer );
777cdf0e10cSrcweir
778cdf0e10cSrcweir ZipEntry aEntry;
779cdf0e10cSrcweir sal_Int32 nTestSig;
780cdf0e10cSrcweir sal_Int16 nCommentLen;
781cdf0e10cSrcweir
782cdf0e10cSrcweir for (nCount = 0 ; nCount < nTotal; nCount++)
783cdf0e10cSrcweir {
784cdf0e10cSrcweir aMemGrabber >> nTestSig;
785cdf0e10cSrcweir if ( nTestSig != CENSIG )
786cdf0e10cSrcweir throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad signature)") ), uno::Reference < XInterface > () );
787cdf0e10cSrcweir
788cdf0e10cSrcweir aMemGrabber.skipBytes ( 2 );
789cdf0e10cSrcweir aMemGrabber >> aEntry.nVersion;
790cdf0e10cSrcweir
791cdf0e10cSrcweir if ( ( aEntry.nVersion & 1 ) == 1 )
792cdf0e10cSrcweir throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (encrypted entry)") ), uno::Reference < XInterface > () );
793cdf0e10cSrcweir
794cdf0e10cSrcweir aMemGrabber >> aEntry.nFlag;
795cdf0e10cSrcweir aMemGrabber >> aEntry.nMethod;
796cdf0e10cSrcweir
797cdf0e10cSrcweir if ( aEntry.nMethod != STORED && aEntry.nMethod != DEFLATED)
798cdf0e10cSrcweir throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad compression method)") ), uno::Reference < XInterface > () );
799cdf0e10cSrcweir
800cdf0e10cSrcweir aMemGrabber >> aEntry.nTime;
801cdf0e10cSrcweir aMemGrabber >> aEntry.nCrc;
802cdf0e10cSrcweir aMemGrabber >> aEntry.nCompressedSize;
803cdf0e10cSrcweir aMemGrabber >> aEntry.nSize;
804cdf0e10cSrcweir aMemGrabber >> aEntry.nPathLen;
805cdf0e10cSrcweir aMemGrabber >> aEntry.nExtraLen;
806cdf0e10cSrcweir aMemGrabber >> nCommentLen;
807cdf0e10cSrcweir aMemGrabber.skipBytes ( 8 );
808cdf0e10cSrcweir aMemGrabber >> aEntry.nOffset;
809cdf0e10cSrcweir
810cdf0e10cSrcweir aEntry.nOffset += nLocPos;
811cdf0e10cSrcweir aEntry.nOffset *= -1;
812cdf0e10cSrcweir
813cdf0e10cSrcweir if ( aEntry.nPathLen < 0 )
814cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected name length" ) ), uno::Reference < XInterface > () );
815cdf0e10cSrcweir
816cdf0e10cSrcweir if ( nCommentLen < 0 )
817cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected comment length" ) ), uno::Reference < XInterface > () );
818cdf0e10cSrcweir
819cdf0e10cSrcweir if ( aEntry.nExtraLen < 0 )
820cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected extra header info length") ), uno::Reference < XInterface > () );
821cdf0e10cSrcweir
822cdf0e10cSrcweir // read always in UTF8, some tools seem not to set UTF8 bit
823cdf0e10cSrcweir aEntry.sPath = rtl::OUString::intern ( (sal_Char *) aMemGrabber.getCurrentPos(),
824cdf0e10cSrcweir aEntry.nPathLen,
825cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 );
826cdf0e10cSrcweir
827cdf0e10cSrcweir if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( aEntry.sPath, sal_True ) )
828cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip entry has an invalid name.") ), uno::Reference < XInterface > () );
829cdf0e10cSrcweir
830cdf0e10cSrcweir aMemGrabber.skipBytes( aEntry.nPathLen + aEntry.nExtraLen + nCommentLen );
831cdf0e10cSrcweir aEntries[aEntry.sPath] = aEntry;
832cdf0e10cSrcweir }
833cdf0e10cSrcweir
834cdf0e10cSrcweir if (nCount != nTotal)
835cdf0e10cSrcweir throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Count != Total") ), uno::Reference < XInterface > () );
836cdf0e10cSrcweir }
837cdf0e10cSrcweir catch ( IllegalArgumentException & )
838cdf0e10cSrcweir {
839cdf0e10cSrcweir // seek can throw this...
840cdf0e10cSrcweir nCenPos = -1; // make sure we return -1 to indicate an error
841cdf0e10cSrcweir }
842cdf0e10cSrcweir return nCenPos;
843cdf0e10cSrcweir }
844cdf0e10cSrcweir
recover()845cdf0e10cSrcweir sal_Int32 ZipFile::recover()
846cdf0e10cSrcweir throw(IOException, ZipException, RuntimeException)
847cdf0e10cSrcweir {
848cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
849cdf0e10cSrcweir
850cdf0e10cSrcweir sal_Int32 nLength;
851cdf0e10cSrcweir Sequence < sal_Int8 > aBuffer;
852cdf0e10cSrcweir Sequence < sal_Int32 > aHeaderOffsets;
853cdf0e10cSrcweir
854cdf0e10cSrcweir try
855cdf0e10cSrcweir {
856cdf0e10cSrcweir nLength = static_cast <sal_Int32 > (aGrabber.getLength());
857cdf0e10cSrcweir if (nLength == 0 || nLength < ENDHDR)
858cdf0e10cSrcweir return -1;
859cdf0e10cSrcweir
860cdf0e10cSrcweir aGrabber.seek( 0 );
861cdf0e10cSrcweir
862cdf0e10cSrcweir const sal_Int32 nToRead = 32000;
863cdf0e10cSrcweir for( sal_Int32 nGenPos = 0; aGrabber.readBytes( aBuffer, nToRead ) && aBuffer.getLength() > 16; )
864cdf0e10cSrcweir {
865cdf0e10cSrcweir const sal_Int8 *pBuffer = aBuffer.getConstArray();
866cdf0e10cSrcweir sal_Int32 nBufSize = aBuffer.getLength();
867cdf0e10cSrcweir
868cdf0e10cSrcweir sal_Int32 nPos = 0;
869cdf0e10cSrcweir // the buffer should contain at least one header,
870cdf0e10cSrcweir // or if it is end of the file, at least the postheader with sizes and hash
871cdf0e10cSrcweir while( nPos < nBufSize - 30
872cdf0e10cSrcweir || ( aBuffer.getLength() < nToRead && nPos < nBufSize - 16 ) )
873cdf0e10cSrcweir
874cdf0e10cSrcweir {
875cdf0e10cSrcweir if ( nPos < nBufSize - 30 && pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 3 && pBuffer[nPos+3] == 4 )
876cdf0e10cSrcweir {
877cdf0e10cSrcweir ZipEntry aEntry;
878cdf0e10cSrcweir MemoryByteGrabber aMemGrabber ( Sequence< sal_Int8 >( ((sal_Int8*)(&(pBuffer[nPos+4]))), 26 ) );
879cdf0e10cSrcweir
880cdf0e10cSrcweir aMemGrabber >> aEntry.nVersion;
881cdf0e10cSrcweir if ( ( aEntry.nVersion & 1 ) != 1 )
882cdf0e10cSrcweir {
883cdf0e10cSrcweir aMemGrabber >> aEntry.nFlag;
884cdf0e10cSrcweir aMemGrabber >> aEntry.nMethod;
885cdf0e10cSrcweir
886cdf0e10cSrcweir if ( aEntry.nMethod == STORED || aEntry.nMethod == DEFLATED )
887cdf0e10cSrcweir {
888cdf0e10cSrcweir aMemGrabber >> aEntry.nTime;
889cdf0e10cSrcweir aMemGrabber >> aEntry.nCrc;
890cdf0e10cSrcweir aMemGrabber >> aEntry.nCompressedSize;
891cdf0e10cSrcweir aMemGrabber >> aEntry.nSize;
892cdf0e10cSrcweir aMemGrabber >> aEntry.nPathLen;
893cdf0e10cSrcweir aMemGrabber >> aEntry.nExtraLen;
894cdf0e10cSrcweir
895cdf0e10cSrcweir sal_Int32 nDescrLength =
896cdf0e10cSrcweir ( aEntry.nMethod == DEFLATED && ( aEntry.nFlag & 8 ) ) ?
897cdf0e10cSrcweir 16 : 0;
898cdf0e10cSrcweir
899cdf0e10cSrcweir
900cdf0e10cSrcweir // This is a quick fix for OOo1.1RC
901cdf0e10cSrcweir // For OOo2.0 the whole package must be switched to unsigned values
902cdf0e10cSrcweir if ( aEntry.nCompressedSize < 0 ) aEntry.nCompressedSize = 0x7FFFFFFF;
903cdf0e10cSrcweir if ( aEntry.nSize < 0 ) aEntry.nSize = 0x7FFFFFFF;
904cdf0e10cSrcweir if ( aEntry.nPathLen < 0 ) aEntry.nPathLen = 0x7FFF;
905cdf0e10cSrcweir if ( aEntry.nExtraLen < 0 ) aEntry.nExtraLen = 0x7FFF;
906cdf0e10cSrcweir // End of quick fix
907cdf0e10cSrcweir
908cdf0e10cSrcweir sal_Int32 nDataSize = ( aEntry.nMethod == DEFLATED ) ? aEntry.nCompressedSize : aEntry.nSize;
909cdf0e10cSrcweir sal_Int32 nBlockLength = nDataSize + aEntry.nPathLen + aEntry.nExtraLen + 30 + nDescrLength;
910cdf0e10cSrcweir if ( aEntry.nPathLen >= 0 && aEntry.nExtraLen >= 0
911cdf0e10cSrcweir && ( nGenPos + nPos + nBlockLength ) <= nLength )
912cdf0e10cSrcweir {
913cdf0e10cSrcweir // read always in UTF8, some tools seem not to set UTF8 bit
914cdf0e10cSrcweir if( nPos + 30 + aEntry.nPathLen <= nBufSize )
915cdf0e10cSrcweir aEntry.sPath = OUString ( (sal_Char *) &pBuffer[nPos + 30],
916cdf0e10cSrcweir aEntry.nPathLen,
917cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 );
918cdf0e10cSrcweir else
919cdf0e10cSrcweir {
920cdf0e10cSrcweir Sequence < sal_Int8 > aFileName;
921cdf0e10cSrcweir aGrabber.seek( nGenPos + nPos + 30 );
922cdf0e10cSrcweir aGrabber.readBytes( aFileName, aEntry.nPathLen );
923cdf0e10cSrcweir aEntry.sPath = OUString ( (sal_Char *) aFileName.getArray(),
924cdf0e10cSrcweir aFileName.getLength(),
925cdf0e10cSrcweir RTL_TEXTENCODING_UTF8 );
926cdf0e10cSrcweir aEntry.nPathLen = static_cast< sal_Int16 >(aFileName.getLength());
927cdf0e10cSrcweir }
928cdf0e10cSrcweir
929cdf0e10cSrcweir aEntry.nOffset = nGenPos + nPos + 30 + aEntry.nPathLen + aEntry.nExtraLen;
930cdf0e10cSrcweir
931cdf0e10cSrcweir if ( ( aEntry.nSize || aEntry.nCompressedSize ) && !checkSizeAndCRC( aEntry ) )
932cdf0e10cSrcweir {
933cdf0e10cSrcweir aEntry.nCrc = 0;
934cdf0e10cSrcweir aEntry.nCompressedSize = 0;
935cdf0e10cSrcweir aEntry.nSize = 0;
936cdf0e10cSrcweir }
937cdf0e10cSrcweir
938cdf0e10cSrcweir if ( aEntries.find( aEntry.sPath ) == aEntries.end() )
939cdf0e10cSrcweir aEntries[aEntry.sPath] = aEntry;
940cdf0e10cSrcweir }
941cdf0e10cSrcweir }
942cdf0e10cSrcweir }
943cdf0e10cSrcweir
944cdf0e10cSrcweir nPos += 4;
945cdf0e10cSrcweir }
946cdf0e10cSrcweir else if (pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 7 && pBuffer[nPos+3] == 8 )
947cdf0e10cSrcweir {
948cdf0e10cSrcweir sal_Int32 nCompressedSize, nSize, nCRC32;
949cdf0e10cSrcweir MemoryByteGrabber aMemGrabber ( Sequence< sal_Int8 >( ((sal_Int8*)(&(pBuffer[nPos+4]))), 12 ) );
950cdf0e10cSrcweir aMemGrabber >> nCRC32;
951cdf0e10cSrcweir aMemGrabber >> nCompressedSize;
952cdf0e10cSrcweir aMemGrabber >> nSize;
953cdf0e10cSrcweir
954cdf0e10cSrcweir for( EntryHash::iterator aIter = aEntries.begin(); aIter != aEntries.end(); aIter++ )
955cdf0e10cSrcweir {
956cdf0e10cSrcweir ZipEntry aTmp = (*aIter).second;
957cdf0e10cSrcweir
958cdf0e10cSrcweir // this is a broken package, accept this block not only for DEFLATED streams
959cdf0e10cSrcweir if( (*aIter).second.nFlag & 8 )
960cdf0e10cSrcweir {
961cdf0e10cSrcweir sal_Int32 nStreamOffset = nGenPos + nPos - nCompressedSize;
962cdf0e10cSrcweir if ( nStreamOffset == (*aIter).second.nOffset && nCompressedSize > (*aIter).second.nCompressedSize )
963cdf0e10cSrcweir {
964cdf0e10cSrcweir // only DEFLATED blocks need to be checked
965cdf0e10cSrcweir sal_Bool bAcceptBlock = ( (*aIter).second.nMethod == STORED && nCompressedSize == nSize );
966cdf0e10cSrcweir
967cdf0e10cSrcweir if ( !bAcceptBlock )
968cdf0e10cSrcweir {
969cdf0e10cSrcweir sal_Int32 nRealSize = 0, nRealCRC = 0;
970cdf0e10cSrcweir getSizeAndCRC( nStreamOffset, nCompressedSize, &nRealSize, &nRealCRC );
971cdf0e10cSrcweir bAcceptBlock = ( nRealSize == nSize && nRealCRC == nCRC32 );
972cdf0e10cSrcweir }
973cdf0e10cSrcweir
974cdf0e10cSrcweir if ( bAcceptBlock )
975cdf0e10cSrcweir {
976cdf0e10cSrcweir (*aIter).second.nCrc = nCRC32;
977cdf0e10cSrcweir (*aIter).second.nCompressedSize = nCompressedSize;
978cdf0e10cSrcweir (*aIter).second.nSize = nSize;
979cdf0e10cSrcweir }
980cdf0e10cSrcweir }
981cdf0e10cSrcweir #if 0
982cdf0e10cSrcweir // for now ignore clearly broken streams
983cdf0e10cSrcweir else if( !(*aIter).second.nCompressedSize )
984cdf0e10cSrcweir {
985cdf0e10cSrcweir (*aIter).second.nCrc = nCRC32;
986cdf0e10cSrcweir sal_Int32 nRealStreamSize = nGenPos + nPos - (*aIter).second.nOffset;
987cdf0e10cSrcweir (*aIter).second.nCompressedSize = nGenPos + nPos - (*aIter).second.nOffset;
988cdf0e10cSrcweir (*aIter).second.nSize = nSize;
989cdf0e10cSrcweir }
990cdf0e10cSrcweir #endif
991cdf0e10cSrcweir }
992cdf0e10cSrcweir }
993cdf0e10cSrcweir
994cdf0e10cSrcweir nPos += 4;
995cdf0e10cSrcweir }
996cdf0e10cSrcweir else
997cdf0e10cSrcweir nPos++;
998cdf0e10cSrcweir }
999cdf0e10cSrcweir
1000cdf0e10cSrcweir nGenPos += nPos;
1001cdf0e10cSrcweir aGrabber.seek( nGenPos );
1002cdf0e10cSrcweir }
1003cdf0e10cSrcweir
1004cdf0e10cSrcweir return 0;
1005cdf0e10cSrcweir }
1006cdf0e10cSrcweir catch ( IllegalArgumentException& )
1007cdf0e10cSrcweir {
1008cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () );
1009cdf0e10cSrcweir }
1010cdf0e10cSrcweir catch ( NotConnectedException& )
1011cdf0e10cSrcweir {
1012cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () );
1013cdf0e10cSrcweir }
1014cdf0e10cSrcweir catch ( BufferSizeExceededException& )
1015cdf0e10cSrcweir {
1016cdf0e10cSrcweir throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), uno::Reference < XInterface > () );
1017cdf0e10cSrcweir }
1018cdf0e10cSrcweir }
1019cdf0e10cSrcweir
checkSizeAndCRC(const ZipEntry & aEntry)1020cdf0e10cSrcweir sal_Bool ZipFile::checkSizeAndCRC( const ZipEntry& aEntry )
1021cdf0e10cSrcweir {
1022cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
1023cdf0e10cSrcweir
1024cdf0e10cSrcweir sal_Int32 nSize = 0, nCRC = 0;
1025cdf0e10cSrcweir
1026cdf0e10cSrcweir if( aEntry.nMethod == STORED )
1027cdf0e10cSrcweir return ( getCRC( aEntry.nOffset, aEntry.nSize ) == aEntry.nCrc );
1028cdf0e10cSrcweir
1029cdf0e10cSrcweir getSizeAndCRC( aEntry.nOffset, aEntry.nCompressedSize, &nSize, &nCRC );
1030cdf0e10cSrcweir return ( aEntry.nSize == nSize && aEntry.nCrc == nCRC );
1031cdf0e10cSrcweir }
1032cdf0e10cSrcweir
getCRC(sal_Int32 nOffset,sal_Int32 nSize)1033cdf0e10cSrcweir sal_Int32 ZipFile::getCRC( sal_Int32 nOffset, sal_Int32 nSize )
1034cdf0e10cSrcweir {
1035cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
1036cdf0e10cSrcweir
1037cdf0e10cSrcweir Sequence < sal_Int8 > aBuffer;
1038cdf0e10cSrcweir CRC32 aCRC;
1039cdf0e10cSrcweir sal_Int32 nBlockSize = ::std::min( nSize, static_cast< sal_Int32 >( 32000 ) );
1040cdf0e10cSrcweir
1041cdf0e10cSrcweir aGrabber.seek( nOffset );
1042cdf0e10cSrcweir for ( int ind = 0;
1043cdf0e10cSrcweir aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nSize;
1044cdf0e10cSrcweir ind++ )
1045cdf0e10cSrcweir {
1046cdf0e10cSrcweir aCRC.updateSegment( aBuffer, 0, ::std::min( nBlockSize, nSize - ind * nBlockSize ) );
1047cdf0e10cSrcweir }
1048cdf0e10cSrcweir
1049cdf0e10cSrcweir return aCRC.getValue();
1050cdf0e10cSrcweir }
1051cdf0e10cSrcweir
getSizeAndCRC(sal_Int32 nOffset,sal_Int32 nCompressedSize,sal_Int32 * nSize,sal_Int32 * nCRC)1052cdf0e10cSrcweir void ZipFile::getSizeAndCRC( sal_Int32 nOffset, sal_Int32 nCompressedSize, sal_Int32 *nSize, sal_Int32 *nCRC )
1053cdf0e10cSrcweir {
1054cdf0e10cSrcweir ::osl::MutexGuard aGuard( m_aMutex );
1055cdf0e10cSrcweir
1056cdf0e10cSrcweir Sequence < sal_Int8 > aBuffer;
1057cdf0e10cSrcweir CRC32 aCRC;
1058cdf0e10cSrcweir sal_Int32 nRealSize = 0;
1059cdf0e10cSrcweir Inflater aInflaterLocal( sal_True );
1060cdf0e10cSrcweir sal_Int32 nBlockSize = ::std::min( nCompressedSize, static_cast< sal_Int32 >( 32000 ) );
1061cdf0e10cSrcweir
1062cdf0e10cSrcweir aGrabber.seek( nOffset );
1063cdf0e10cSrcweir for ( int ind = 0;
1064cdf0e10cSrcweir !aInflaterLocal.finished() && aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nCompressedSize;
1065cdf0e10cSrcweir ind++ )
1066cdf0e10cSrcweir {
1067cdf0e10cSrcweir Sequence < sal_Int8 > aData( nBlockSize );
1068cdf0e10cSrcweir sal_Int32 nLastInflated = 0;
1069cdf0e10cSrcweir sal_Int32 nInBlock = 0;
1070cdf0e10cSrcweir
1071cdf0e10cSrcweir aInflaterLocal.setInput( aBuffer );
1072cdf0e10cSrcweir do
1073cdf0e10cSrcweir {
1074cdf0e10cSrcweir nLastInflated = aInflaterLocal.doInflateSegment( aData, 0, nBlockSize );
1075cdf0e10cSrcweir aCRC.updateSegment( aData, 0, nLastInflated );
1076cdf0e10cSrcweir nInBlock += nLastInflated;
1077cdf0e10cSrcweir } while( !aInflater.finished() && nLastInflated );
1078cdf0e10cSrcweir
1079cdf0e10cSrcweir nRealSize += nInBlock;
1080cdf0e10cSrcweir }
1081cdf0e10cSrcweir
1082cdf0e10cSrcweir *nSize = nRealSize;
1083cdf0e10cSrcweir *nCRC = aCRC.getValue();
1084cdf0e10cSrcweir }
1085cdf0e10cSrcweir
1086