LCOV - code coverage report
Current view: top level - package/source/zipapi - XUnbufferedStream.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 77 127 60.6 %
Date: 2012-08-25 Functions: 6 9 66.7 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 112 290 38.6 %

           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/packages/zip/ZipConstants.hpp>
      22                 :            : #include <com/sun/star/packages/zip/ZipIOException.hpp>
      23                 :            : #include <com/sun/star/xml/crypto/CipherID.hpp>
      24                 :            : 
      25                 :            : #include <XUnbufferedStream.hxx>
      26                 :            : #include <EncryptionData.hxx>
      27                 :            : #include <PackageConstants.hxx>
      28                 :            : #include <ZipFile.hxx>
      29                 :            : #include <EncryptedDataHeader.hxx>
      30                 :            : #include <algorithm>
      31                 :            : #include <string.h>
      32                 :            : 
      33                 :            : #include <osl/mutex.hxx>
      34                 :            : 
      35                 :            : using namespace ::com::sun::star;
      36                 :            : using namespace com::sun::star::packages::zip::ZipConstants;
      37                 :            : using namespace com::sun::star::io;
      38                 :            : using namespace com::sun::star::uno;
      39                 :            : using com::sun::star::lang::IllegalArgumentException;
      40                 :            : using com::sun::star::packages::zip::ZipIOException;
      41                 :            : using ::rtl::OUString;
      42                 :            : 
      43                 :      13984 : XUnbufferedStream::XUnbufferedStream(
      44                 :            :                       const uno::Reference< lang::XMultiServiceFactory >& xFactory,
      45                 :            :                       SotMutexHolderRef aMutexHolder,
      46                 :            :                       ZipEntry & rEntry,
      47                 :            :                       Reference < XInputStream > xNewZipStream,
      48                 :            :                       const ::rtl::Reference< EncryptionData >& rData,
      49                 :            :                       sal_Int8 nStreamMode,
      50                 :            :                       sal_Bool bIsEncrypted,
      51                 :            :                       const ::rtl::OUString& aMediaType,
      52                 :            :                       sal_Bool bRecoveryMode )
      53         [ #  # ]:      13984 : : maMutexHolder( aMutexHolder.Is() ? aMutexHolder : SotMutexHolderRef( new SotMutexHolder ) )
      54                 :            : , mxZipStream ( xNewZipStream )
      55                 :            : , mxZipSeek ( xNewZipStream, UNO_QUERY )
      56                 :            : , maEntry ( rEntry )
      57                 :            : , mxData ( rData )
      58                 :            : , mnBlockSize( 1 )
      59                 :            : , maInflater ( sal_True )
      60                 :            : , mbRawStream ( nStreamMode == UNBUFF_STREAM_RAW || nStreamMode == UNBUFF_STREAM_WRAPPEDRAW )
      61                 :            : , mbWrappedRaw ( nStreamMode == UNBUFF_STREAM_WRAPPEDRAW )
      62                 :            : , mbFinished ( sal_False )
      63                 :            : , mnHeaderToRead ( 0 )
      64                 :            : , mnZipCurrent ( 0 )
      65                 :            : , mnZipEnd ( 0 )
      66                 :            : , mnZipSize ( 0 )
      67                 :            : , mnMyCurrent ( 0 )
      68 [ +  - ][ #  # ]:      27968 : , mbCheckCRC( !bRecoveryMode )
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  + ][ -  + ]
                 [ +  - ]
      69                 :            : {
      70                 :      13984 :     mnZipCurrent = maEntry.nOffset;
      71         [ +  + ]:      13984 :     if ( mbRawStream )
      72                 :            :     {
      73         [ +  + ]:       8491 :         mnZipSize = maEntry.nMethod == DEFLATED ? maEntry.nCompressedSize : maEntry.nSize;
      74                 :       8491 :         mnZipEnd = maEntry.nOffset + mnZipSize;
      75                 :            :     }
      76                 :            :     else
      77                 :            :     {
      78                 :       5493 :         mnZipSize = maEntry.nSize;
      79         [ +  - ]:       5493 :         mnZipEnd = maEntry.nMethod == DEFLATED ? maEntry.nOffset + maEntry.nCompressedSize : maEntry.nOffset + maEntry.nSize;
      80                 :            :     }
      81 [ +  + ][ +  + ]:      13984 :     sal_Bool bHaveEncryptData = ( rData.is() && rData->m_aSalt.getLength() && rData->m_aInitVector.getLength() && rData->m_nIterationCount != 0 ) ? sal_True : sal_False;
         [ +  - ][ +  - ]
      82 [ +  + ][ +  + ]:      13984 :     sal_Bool bMustDecrypt = ( nStreamMode == UNBUFF_STREAM_DATA && bHaveEncryptData && bIsEncrypted ) ? sal_True : sal_False;
                 [ +  - ]
      83                 :            : 
      84         [ +  + ]:      13984 :     if ( bMustDecrypt )
      85                 :            :     {
      86 [ +  - ][ +  - ]:         24 :         m_xCipherContext = ZipFile::StaticGetCipher( xFactory, rData, false );
      87         [ +  + ]:         24 :         mnBlockSize = ( rData->m_nEncAlg == xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 1 );
      88                 :            :     }
      89                 :            : 
      90 [ +  + ][ -  + ]:      13984 :     if ( bHaveEncryptData && mbWrappedRaw && bIsEncrypted )
                 [ #  # ]
      91                 :            :     {
      92                 :            :         // if we have the data needed to decrypt it, but didn't want it decrypted (or
      93                 :            :         // we couldn't decrypt it due to wrong password), then we prepend this
      94                 :            :         // data to the stream
      95                 :            : 
      96                 :            :         // Make a buffer big enough to hold both the header and the data itself
      97                 :            :         maHeader.realloc  ( n_ConstHeaderSize +
      98                 :          0 :                             rData->m_aInitVector.getLength() +
      99                 :          0 :                             rData->m_aSalt.getLength() +
     100                 :          0 :                             rData->m_aDigest.getLength() +
     101         [ #  # ]:          0 :                             aMediaType.getLength() * sizeof( sal_Unicode ) );
     102         [ #  # ]:          0 :         sal_Int8 * pHeader = maHeader.getArray();
     103         [ #  # ]:          0 :         ZipFile::StaticFillHeader( rData, rEntry.nSize, aMediaType, pHeader );
     104                 :          0 :         mnHeaderToRead = static_cast < sal_Int16 > ( maHeader.getLength() );
     105                 :            :     }
     106                 :      13984 : }
     107                 :            : 
     108                 :            : // allows to read package raw stream
     109                 :          0 : XUnbufferedStream::XUnbufferedStream(
     110                 :            :                     const uno::Reference< lang::XMultiServiceFactory >& /*xFactory*/,
     111                 :            :                     const Reference < XInputStream >& xRawStream,
     112                 :            :                     const ::rtl::Reference< EncryptionData >& rData )
     113   [ #  #  #  # ]:          0 : : maMutexHolder( new SotMutexHolder )
     114                 :            : , mxZipStream ( xRawStream )
     115                 :            : , mxZipSeek ( xRawStream, UNO_QUERY )
     116                 :            : , mxData ( rData )
     117                 :            : , mnBlockSize( 1 )
     118                 :            : , maInflater ( sal_True )
     119                 :            : , mbRawStream ( sal_False )
     120                 :            : , mbWrappedRaw ( sal_False )
     121                 :            : , mbFinished ( sal_False )
     122                 :            : , mnHeaderToRead ( 0 )
     123                 :            : , mnZipCurrent ( 0 )
     124                 :            : , mnZipEnd ( 0 )
     125                 :            : , mnZipSize ( 0 )
     126                 :            : , mnMyCurrent ( 0 )
     127 [ #  # ][ #  # ]:          0 : , mbCheckCRC( sal_False )
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     128                 :            : {
     129                 :            :     // for this scenario maEntry is not set !!!
     130                 :            :     OSL_ENSURE( mxZipSeek.is(), "The stream must be seekable!\n" );
     131                 :            : 
     132                 :            :     // skip raw header, it must be already parsed to rData
     133                 :          0 :     mnZipCurrent = n_ConstHeaderSize + rData->m_aInitVector.getLength() +
     134                 :          0 :                             rData->m_aSalt.getLength() + rData->m_aDigest.getLength();
     135                 :            : 
     136                 :            :     try {
     137         [ #  # ]:          0 :         if ( mxZipSeek.is() )
     138 [ #  # ][ #  # ]:          0 :             mnZipSize = mxZipSeek->getLength();
     139         [ #  # ]:          0 :     } catch( Exception& )
     140                 :            :     {
     141                 :            :         // in case of problem the size will stay set to 0
     142                 :            :     }
     143                 :            : 
     144                 :          0 :     mnZipEnd = mnZipCurrent + mnZipSize;
     145                 :            : 
     146                 :            :     // the raw data will not be decrypted, no need for the cipher
     147                 :            :     // m_xCipherContext = ZipFile::StaticGetCipher( xFactory, rData, false );
     148                 :          0 : }
     149                 :            : 
     150 [ +  - ][ +  - ]:      13984 : XUnbufferedStream::~XUnbufferedStream()
         [ +  - ][ +  - ]
                 [ +  - ]
     151                 :            : {
     152         [ -  + ]:      27968 : }
     153                 :            : 
     154                 :      16774 : sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
     155                 :            :         throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
     156                 :            : {
     157         [ +  - ]:      16774 :     ::osl::MutexGuard aGuard( maMutexHolder->GetMutex() );
     158                 :            : 
     159                 :      16774 :     sal_Int32 nRequestedBytes = nBytesToRead;
     160                 :            :     OSL_ENSURE( !mnHeaderToRead || mbWrappedRaw, "Only encrypted raw stream can be provided with header!" );
     161         [ +  + ]:      16774 :     if ( mnMyCurrent + nRequestedBytes > mnZipSize + maHeader.getLength() )
     162                 :      16555 :         nRequestedBytes = static_cast < sal_Int32 > ( mnZipSize + maHeader.getLength() - mnMyCurrent );
     163                 :            : 
     164                 :      16774 :     sal_Int32 nTotal = 0;
     165         [ +  - ]:      16774 :     aData.realloc ( nRequestedBytes );
     166         [ +  + ]:      16774 :     if ( nRequestedBytes )
     167                 :            :     {
     168                 :      12930 :         sal_Int32 nRead = 0;
     169                 :      12930 :         sal_Int32 nLastRead = 0;
     170         [ +  + ]:      12930 :         if ( mbRawStream )
     171                 :            :         {
     172                 :       8201 :             sal_Int64 nDiff = mnZipEnd - mnZipCurrent;
     173                 :            : 
     174 [ -  + ][ #  # ]:       8201 :             if ( mbWrappedRaw && mnHeaderToRead )
     175                 :            :             {
     176                 :            :                 sal_Int16 nHeadRead = static_cast< sal_Int16 >(( nRequestedBytes > mnHeaderToRead ?
     177                 :          0 :                                                                                  mnHeaderToRead : nRequestedBytes ));
     178         [ #  # ]:          0 :                 memcpy ( aData.getArray(), maHeader.getConstArray() + maHeader.getLength() - mnHeaderToRead, nHeadRead );
     179                 :          0 :                 mnHeaderToRead = mnHeaderToRead - nHeadRead;
     180                 :            : 
     181         [ #  # ]:          0 :                 if ( nHeadRead < nRequestedBytes )
     182                 :            :                 {
     183                 :          0 :                     sal_Int32 nToRead = nRequestedBytes - nHeadRead;
     184         [ #  # ]:          0 :                     nToRead = ( nDiff < nToRead ) ? sal::static_int_cast< sal_Int32 >( nDiff ) : nToRead;
     185                 :            : 
     186         [ #  # ]:          0 :                     Sequence< sal_Int8 > aPureData( nToRead );
     187 [ #  # ][ #  # ]:          0 :                     mxZipSeek->seek ( mnZipCurrent );
     188 [ #  # ][ #  # ]:          0 :                     nRead = mxZipStream->readBytes ( aPureData, nToRead );
     189                 :          0 :                     mnZipCurrent += nRead;
     190                 :            : 
     191         [ #  # ]:          0 :                     aPureData.realloc( nRead );
     192         [ #  # ]:          0 :                     if ( mbCheckCRC )
     193         [ #  # ]:          0 :                         maCRC.update( aPureData );
     194                 :            : 
     195         [ #  # ]:          0 :                     aData.realloc( nHeadRead + nRead );
     196                 :            : 
     197         [ #  # ]:          0 :                     sal_Int8* pPureBuffer = aPureData.getArray();
     198         [ #  # ]:          0 :                     sal_Int8* pBuffer = aData.getArray();
     199         [ #  # ]:          0 :                     for ( sal_Int32 nInd = 0; nInd < nRead; nInd++ )
     200         [ #  # ]:          0 :                         pBuffer[ nHeadRead + nInd ] = pPureBuffer[ nInd ];
     201                 :            :                 }
     202                 :            : 
     203                 :          0 :                 nRead += nHeadRead;
     204                 :            :             }
     205                 :            :             else
     206                 :            :             {
     207 [ +  - ][ +  - ]:       8201 :                 mxZipSeek->seek ( mnZipCurrent );
     208                 :            : 
     209         [ +  - ]:       8201 :                 nRead = mxZipStream->readBytes (
     210                 :            :                                         aData,
     211         [ +  - ]:       8201 :                                         static_cast < sal_Int32 > ( nDiff < nRequestedBytes ? nDiff : nRequestedBytes ) );
     212                 :            : 
     213                 :       8201 :                 mnZipCurrent += nRead;
     214                 :            : 
     215         [ +  - ]:       8201 :                 aData.realloc( nRead );
     216 [ -  + ][ #  # ]:       8201 :                 if ( mbWrappedRaw && mbCheckCRC )
     217         [ #  # ]:       8201 :                     maCRC.update( aData );
     218                 :            :             }
     219                 :            :         }
     220                 :            :         else
     221                 :            :         {
     222 [ +  - ][ +  + ]:       9263 :             while ( 0 == ( nLastRead = maInflater.doInflateSegment( aData, nRead, aData.getLength() - nRead ) ) ||
         [ -  + ][ #  # ]
                 [ +  + ]
     223                 :            :                   ( nRead + nLastRead != nRequestedBytes && mnZipCurrent < mnZipEnd ) )
     224                 :            :             {
     225                 :       4534 :                 nRead += nLastRead;
     226                 :            : 
     227         [ -  + ]:       4534 :                 if ( nRead > nRequestedBytes )
     228                 :            :                     throw RuntimeException(
     229                 :            :                         OUString( RTL_CONSTASCII_USTRINGPARAM( "Should not be possible to read more then requested!" ) ),
     230 [ #  # ][ #  # ]:          0 :                         Reference< XInterface >() );
     231                 :            : 
     232 [ +  - ][ +  - ]:       4534 :                 if ( maInflater.finished() || maInflater.getLastInflateError() )
         [ -  + ][ -  + ]
     233                 :            :                     throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
     234 [ #  # ][ #  # ]:          0 :                                         Reference< XInterface >() );
     235                 :            : 
     236 [ +  - ][ -  + ]:       4534 :                 if ( maInflater.needsDictionary() )
     237                 :            :                     throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "Dictionaries are not supported!" ) ),
     238 [ #  # ][ #  # ]:          0 :                                         Reference< XInterface >() );
     239                 :            : 
     240                 :       4534 :                 sal_Int32 nDiff = static_cast< sal_Int32 >( mnZipEnd - mnZipCurrent );
     241         [ +  - ]:       4534 :                 if ( nDiff > 0 )
     242                 :            :                 {
     243 [ +  - ][ +  - ]:       4534 :                     mxZipSeek->seek ( mnZipCurrent );
     244                 :            : 
     245         [ +  - ]:       4534 :                     sal_Int32 nToRead = std::max( nRequestedBytes, static_cast< sal_Int32 >( 8192 ) );
     246         [ +  + ]:       4534 :                     if ( mnBlockSize > 1 )
     247                 :         12 :                         nToRead = nToRead + mnBlockSize - nToRead % mnBlockSize;
     248         [ +  - ]:       4534 :                     nToRead = std::min( nDiff, nToRead );
     249                 :            : 
     250 [ +  - ][ +  - ]:       4534 :                     sal_Int32 nZipRead = mxZipStream->readBytes( maCompBuffer, nToRead );
     251         [ -  + ]:       4534 :                     if ( nZipRead < nToRead )
     252                 :            :                         throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "No expected data!" ) ),
     253 [ #  # ][ #  # ]:          0 :                                             Reference< XInterface >() );
     254                 :            : 
     255                 :       4534 :                     mnZipCurrent += nZipRead;
     256                 :            :                     // maCompBuffer now has the data, check if we need to decrypt
     257                 :            :                     // before passing to the Inflater
     258         [ +  + ]:       4534 :                     if ( m_xCipherContext.is() )
     259                 :            :                     {
     260         [ +  - ]:         24 :                         if ( mbCheckCRC )
     261         [ +  - ]:         24 :                             maCRC.update( maCompBuffer );
     262                 :            : 
     263 [ +  - ][ +  - ]:         24 :                         maCompBuffer = m_xCipherContext->convertWithCipherContext( maCompBuffer );
         [ +  - ][ +  - ]
     264         [ +  - ]:         24 :                         if ( mnZipCurrent == mnZipEnd )
     265                 :            :                         {
     266 [ +  - ][ +  - ]:         24 :                             uno::Sequence< sal_Int8 > aSuffix = m_xCipherContext->finalizeCipherContextAndDispose();
     267         [ +  + ]:         24 :                             if ( aSuffix.getLength() )
     268                 :            :                             {
     269                 :         12 :                                 sal_Int32 nOldLen = maCompBuffer.getLength();
     270         [ +  - ]:         12 :                                 maCompBuffer.realloc( nOldLen + aSuffix.getLength() );
     271         [ +  - ]:         12 :                                 memcpy( maCompBuffer.getArray() + nOldLen, aSuffix.getConstArray(), aSuffix.getLength() );
     272         [ +  - ]:         24 :                             }
     273                 :            :                         }
     274                 :            :                     }
     275         [ +  - ]:       4534 :                     maInflater.setInput ( maCompBuffer );
     276                 :            :                 }
     277                 :            :                 else
     278                 :            :                 {
     279                 :            :                     throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
     280 [ #  # ][ #  # ]:          0 :                                         Reference< XInterface >() );
     281                 :            :                 }
     282                 :            :             }
     283                 :            :         }
     284                 :            : 
     285                 :      12930 :         mnMyCurrent += nRead + nLastRead;
     286                 :      12930 :         nTotal = nRead + nLastRead;
     287         [ -  + ]:      12930 :         if ( nTotal < nRequestedBytes)
     288         [ #  # ]:          0 :             aData.realloc ( nTotal );
     289                 :            : 
     290 [ +  - ][ +  + ]:      12930 :         if ( mbCheckCRC && ( !mbRawStream || mbWrappedRaw ) )
                 [ -  + ]
     291                 :            :         {
     292 [ +  + ][ +  - ]:       4729 :             if ( !m_xCipherContext.is() && !mbWrappedRaw )
                 [ +  + ]
     293         [ +  - ]:       4705 :                 maCRC.update( aData );
     294                 :            : 
     295 [ +  + ][ +  - ]:       4729 :             if ( mnZipSize + maHeader.getLength() == mnMyCurrent && maCRC.getValue() != maEntry.nCrc )
         [ -  + ][ -  + ]
     296                 :            :                 throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
     297 [ #  # ][ #  # ]:          0 :                                     Reference< XInterface >() );
     298                 :            :         }
     299                 :            :     }
     300                 :            : 
     301         [ +  - ]:      16774 :     return nTotal;
     302                 :            : }
     303                 :            : 
     304                 :       7405 : sal_Int32 SAL_CALL XUnbufferedStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
     305                 :            :         throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
     306                 :            : {
     307                 :       7405 :     return readBytes ( aData, nMaxBytesToRead );
     308                 :            : }
     309                 :          0 : void SAL_CALL XUnbufferedStream::skipBytes( sal_Int32 nBytesToSkip )
     310                 :            :         throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
     311                 :            : {
     312         [ #  # ]:          0 :     if ( nBytesToSkip )
     313                 :            :     {
     314         [ #  # ]:          0 :         Sequence < sal_Int8 > aSequence ( nBytesToSkip );
     315 [ #  # ][ #  # ]:          0 :         readBytes ( aSequence, nBytesToSkip );
     316                 :            :     }
     317                 :          0 : }
     318                 :            : 
     319                 :          0 : sal_Int32 SAL_CALL XUnbufferedStream::available(  )
     320                 :            :         throw( NotConnectedException, IOException, RuntimeException)
     321                 :            : {
     322                 :          0 :     return static_cast < sal_Int32 > ( mnZipSize - mnMyCurrent );
     323                 :            : }
     324                 :            : 
     325                 :       2950 : void SAL_CALL XUnbufferedStream::closeInput(  )
     326                 :            :         throw( NotConnectedException, IOException, RuntimeException)
     327                 :            : {
     328                 :       2950 : }
     329                 :            : 
     330                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10