LCOV - code coverage report
Current view: top level - package/source/zipapi - ZipFile.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 209 519 40.3 %
Date: 2012-08-25 Functions: 16 24 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 234 986 23.7 %

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

Generated by: LCOV version 1.10