LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/package/source/zippackage - ZipPackageFolder.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 288 384 75.0 %
Date: 2013-07-09 Functions: 21 28 75.0 %
Legend: Lines: hit not hit

          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             : #include <string.h>
      21             : 
      22             : #include <ZipPackageFolder.hxx>
      23             : #include <ZipFile.hxx>
      24             : #include <ZipOutputStream.hxx>
      25             : #include <ZipPackageStream.hxx>
      26             : #include <PackageConstants.hxx>
      27             : #include <ZipPackageFolderEnumeration.hxx>
      28             : #include <com/sun/star/packages/zip/ZipConstants.hpp>
      29             : #include <com/sun/star/embed/StorageFormats.hpp>
      30             : #include <osl/diagnose.h>
      31             : #include <osl/time.h>
      32             : #include <rtl/digest.h>
      33             : #include <ContentInfo.hxx>
      34             : #include <com/sun/star/beans/PropertyValue.hpp>
      35             : #include <com/sun/star/io/XSeekable.hpp>
      36             : #include <EncryptedDataHeader.hxx>
      37             : #include <rtl/random.h>
      38             : #include <rtl/instance.hxx>
      39             : #include <memory>
      40             : 
      41             : using namespace com::sun::star;
      42             : using namespace com::sun::star::packages::zip::ZipConstants;
      43             : using namespace com::sun::star::packages::zip;
      44             : using namespace com::sun::star::packages;
      45             : using namespace com::sun::star::container;
      46             : using namespace com::sun::star::beans;
      47             : using namespace com::sun::star::lang;
      48             : using namespace com::sun::star::io;
      49             : using namespace cppu;
      50             : using namespace std;
      51             : using namespace ::com::sun::star;
      52             : 
      53             : namespace { struct lcl_CachedImplId : public rtl::Static< uno::Sequence < sal_Int8 >, lcl_CachedImplId > {}; }
      54             : 
      55       16971 : ZipPackageFolder::ZipPackageFolder ( sal_Int32 nFormat,
      56             :                                      sal_Bool bAllowRemoveOnInsert )
      57       16971 : : m_nFormat( nFormat )
      58             : {
      59       16971 :     this->mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
      60             : 
      61       16971 :     SetFolder ( sal_True );
      62       16971 :     aEntry.nVersion     = -1;
      63       16971 :     aEntry.nFlag        = 0;
      64       16971 :     aEntry.nMethod      = STORED;
      65       16971 :     aEntry.nTime        = -1;
      66       16971 :     aEntry.nCrc         = 0;
      67       16971 :     aEntry.nCompressedSize = 0;
      68       16971 :     aEntry.nSize        = 0;
      69       16971 :     aEntry.nOffset      = -1;
      70       16971 :     uno::Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get();
      71       16971 :     if ( !rCachedImplId.getLength() )
      72          69 :         rCachedImplId = getImplementationId();
      73       16971 : }
      74             : 
      75             : 
      76       33672 : ZipPackageFolder::~ZipPackageFolder()
      77             : {
      78       33672 : }
      79             : 
      80        3517 : sal_Bool ZipPackageFolder::LookForUnexpectedODF12Streams( const OUString& aPath )
      81             : {
      82        3517 :     sal_Bool bHasUnexpected = sal_False;
      83             : 
      84       17752 :     for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end();
      85        8876 :           !bHasUnexpected && aCI != aEnd;
      86             :           ++aCI)
      87             :     {
      88        5359 :         const OUString &rShortName = (*aCI).first;
      89        5359 :         const ContentInfo &rInfo = *(*aCI).second;
      90             : 
      91        5359 :         if ( rInfo.bFolder )
      92             :         {
      93        3158 :             if ( aPath == "META-INF/" )
      94             :             {
      95             :                 // META-INF is not allowed to contain subfolders
      96           0 :                 bHasUnexpected = sal_True;
      97             :             }
      98             :             else
      99             :             {
     100        3158 :                 OUString sOwnPath = aPath + rShortName + "/";
     101        3158 :                 bHasUnexpected = rInfo.pFolder->LookForUnexpectedODF12Streams( sOwnPath );
     102             :             }
     103             :         }
     104             :         else
     105             :         {
     106        2201 :             if ( aPath == "META-INF/" )
     107             :             {
     108           0 :                 if ( rShortName != "manifest.xml"
     109           0 :                   && rShortName.indexOf( "signatures" ) == -1 )
     110             :                 {
     111             :                     // a stream from META-INF with unexpected name
     112           0 :                     bHasUnexpected = sal_True;
     113             :                 }
     114             : 
     115             :                 // streams from META-INF with expected names are allowed not to be registered in manifest.xml
     116             :             }
     117        2201 :             else if ( !rInfo.pStream->IsFromManifest() )
     118             :             {
     119             :                 // the stream is not in META-INF and ist notregistered in manifest.xml,
     120             :                 // check whether it is an internal part of the package format
     121           0 :                 if ( !aPath.isEmpty() || rShortName != "mimetype" )
     122             :                 {
     123             :                     // if it is not "mimetype" from the root it is not a part of the package
     124           0 :                     bHasUnexpected = sal_True;
     125             :                 }
     126             :             }
     127             :         }
     128             :     }
     129             : 
     130        3517 :     return bHasUnexpected;
     131             : }
     132             : 
     133        3026 : void ZipPackageFolder::setChildStreamsTypeByExtension( const beans::StringPair& aPair )
     134             : {
     135        3026 :     OUString aExt;
     136        3026 :     if ( aPair.First.toChar() == (sal_Unicode)'.' )
     137           0 :         aExt = aPair.First;
     138             :     else
     139        3026 :         aExt = "." + aPair.First;
     140             : 
     141       12061 :     for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end();
     142             :           aCI != aEnd;
     143             :           ++aCI)
     144             :     {
     145        9035 :         const OUString &rShortName = (*aCI).first;
     146        9035 :         const ContentInfo &rInfo = *(*aCI).second;
     147             : 
     148        9035 :         if ( rInfo.bFolder )
     149        2590 :             rInfo.pFolder->setChildStreamsTypeByExtension( aPair );
     150             :         else
     151             :         {
     152        6445 :             sal_Int32 nPathLength = rShortName.getLength();
     153        6445 :             sal_Int32 nExtLength = aExt.getLength();
     154        6445 :             if ( nPathLength >= nExtLength && rShortName.match( aExt, nPathLength - nExtLength ) )
     155        2638 :                 rInfo.pStream->SetMediaType( aPair.Second );
     156             :         }
     157        3026 :     }
     158        3026 : }
     159             : 
     160        2044 : void ZipPackageFolder::copyZipEntry( ZipEntry &rDest, const ZipEntry &rSource)
     161             : {
     162        2044 :       rDest.nVersion            = rSource.nVersion;
     163        2044 :     rDest.nFlag             = rSource.nFlag;
     164        2044 :     rDest.nMethod           = rSource.nMethod;
     165        2044 :     rDest.nTime             = rSource.nTime;
     166        2044 :     rDest.nCrc              = rSource.nCrc;
     167        2044 :     rDest.nCompressedSize   = rSource.nCompressedSize;
     168        2044 :     rDest.nSize             = rSource.nSize;
     169        2044 :     rDest.nOffset           = rSource.nOffset;
     170        2044 :     rDest.sPath             = rSource.sPath;
     171        2044 :     rDest.nPathLen          = rSource.nPathLen;
     172        2044 :     rDest.nExtraLen         = rSource.nExtraLen;
     173        2044 : }
     174             : 
     175       11278 : const ::com::sun::star::uno::Sequence < sal_Int8 >& ZipPackageFolder::static_getImplementationId()
     176             : {
     177       11278 :     return lcl_CachedImplId::get();
     178             : }
     179             : 
     180             :     // XNameContainer
     181        2161 : void SAL_CALL ZipPackageFolder::insertByName( const OUString& aName, const uno::Any& aElement )
     182             :         throw(IllegalArgumentException, ElementExistException, WrappedTargetException, uno::RuntimeException)
     183             : {
     184        2161 :     if (hasByName(aName))
     185           0 :         throw ElementExistException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
     186             :     else
     187             :     {
     188        2161 :         uno::Reference < XUnoTunnel > xRef;
     189        2161 :         aElement >>= xRef;
     190        2161 :         if ( (  aElement >>= xRef ) )
     191             :         {
     192             :             sal_Int64 nTest;
     193             :             ZipPackageEntry *pEntry;
     194        2161 :             if ( ( nTest = xRef->getSomething ( ZipPackageFolder::static_getImplementationId() ) ) != 0 )
     195             :             {
     196         484 :                 ZipPackageFolder *pFolder = reinterpret_cast < ZipPackageFolder * > ( nTest );
     197         484 :                 pEntry = static_cast < ZipPackageEntry * > ( pFolder );
     198             :             }
     199        1677 :             else if ( ( nTest = xRef->getSomething ( ZipPackageStream::static_getImplementationId() ) ) != 0 )
     200             :             {
     201        1677 :                 ZipPackageStream *pStream = reinterpret_cast < ZipPackageStream * > ( nTest );
     202        1677 :                 pEntry = static_cast < ZipPackageEntry * > ( pStream );
     203             :             }
     204             :             else
     205           0 :                 throw IllegalArgumentException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >(), 0 );
     206             : 
     207        2161 :             if (pEntry->getName() != aName )
     208        2160 :                 pEntry->setName (aName);
     209        2161 :             doInsertByName ( pEntry, sal_True );
     210             :         }
     211             :         else
     212           0 :             throw IllegalArgumentException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >(), 0 );
     213             :     }
     214        2161 : }
     215        1290 : void SAL_CALL ZipPackageFolder::removeByName( const OUString& Name )
     216             :         throw(NoSuchElementException, WrappedTargetException, uno::RuntimeException)
     217             : {
     218        1290 :     ContentHash::iterator aIter = maContents.find ( Name );
     219        1290 :     if ( aIter == maContents.end() )
     220           0 :         throw NoSuchElementException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
     221        1290 :     maContents.erase( aIter );
     222        1290 : }
     223             :     // XEnumerationAccess
     224        8515 : uno::Reference< XEnumeration > SAL_CALL ZipPackageFolder::createEnumeration(  )
     225             :         throw(uno::RuntimeException)
     226             : {
     227        8515 :     return uno::Reference < XEnumeration> (new ZipPackageFolderEnumeration(maContents));
     228             : }
     229             :     // XElementAccess
     230           0 : uno::Type SAL_CALL ZipPackageFolder::getElementType(  )
     231             :         throw(uno::RuntimeException)
     232             : {
     233           0 :     return ::getCppuType ((const uno::Reference< XUnoTunnel > *) 0);
     234             : }
     235           0 : sal_Bool SAL_CALL ZipPackageFolder::hasElements(  )
     236             :         throw(uno::RuntimeException)
     237             : {
     238           0 :     return maContents.size() > 0;
     239             : }
     240             :     // XNameAccess
     241       17165 : ContentInfo& ZipPackageFolder::doGetByName( const OUString& aName )
     242             :     throw(NoSuchElementException, WrappedTargetException, uno::RuntimeException)
     243             : {
     244       17165 :     ContentHash::iterator aIter = maContents.find ( aName );
     245       17165 :     if ( aIter == maContents.end())
     246           0 :         throw NoSuchElementException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
     247       17165 :     return *(*aIter).second;
     248             : }
     249       12564 : uno::Any SAL_CALL ZipPackageFolder::getByName( const OUString& aName )
     250             :     throw(NoSuchElementException, WrappedTargetException, uno::RuntimeException)
     251             : {
     252       12564 :     return uno::makeAny ( doGetByName ( aName ).xTunnel );
     253             : }
     254           0 : uno::Sequence< OUString > SAL_CALL ZipPackageFolder::getElementNames(  )
     255             :         throw(uno::RuntimeException)
     256             : {
     257           0 :     sal_uInt32 i=0, nSize = maContents.size();
     258           0 :     uno::Sequence < OUString > aSequence ( nSize );
     259           0 :     for ( ContentHash::const_iterator aIterator = maContents.begin(), aEnd = maContents.end();
     260             :           aIterator != aEnd;
     261             :           ++i, ++aIterator)
     262           0 :         aSequence[i] = (*aIterator).first;
     263           0 :     return aSequence;
     264             : }
     265       52261 : sal_Bool SAL_CALL ZipPackageFolder::hasByName( const OUString& aName )
     266             :     throw(uno::RuntimeException)
     267             : {
     268       52261 :     return maContents.find ( aName ) != maContents.end ();
     269             : }
     270             :     // XNameReplace
     271           0 : void SAL_CALL ZipPackageFolder::replaceByName( const OUString& aName, const uno::Any& aElement )
     272             :         throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, uno::RuntimeException)
     273             : {
     274           0 :     if ( hasByName( aName ) )
     275           0 :         removeByName( aName );
     276             :     else
     277           0 :         throw NoSuchElementException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
     278           0 :     insertByName(aName, aElement);
     279           0 : }
     280             : 
     281          30 : static void ImplSetStoredData( ZipEntry & rEntry, uno::Reference< XInputStream> & rStream )
     282             : {
     283             :     // It's very annoying that we have to do this, but lots of zip packages
     284             :     // don't allow data descriptors for STORED streams, meaning we have to
     285             :     // know the size and CRC32 of uncompressed streams before we actually
     286             :     // write them !
     287          30 :     CRC32 aCRC32;
     288          30 :     rEntry.nMethod = STORED;
     289          30 :     rEntry.nCompressedSize = rEntry.nSize = aCRC32.updateStream ( rStream );
     290          30 :     rEntry.nCrc = aCRC32.getValue();
     291          30 : }
     292             : 
     293        1480 : bool ZipPackageFolder::saveChild( const OUString &rShortName, const ContentInfo &rInfo, OUString &rPath, std::vector < uno::Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, const uno::Sequence < sal_Int8 >& rEncryptionKey, rtlRandomPool &rRandomPool)
     294             : {
     295        1480 :     bool bSuccess = true;
     296             : 
     297        1480 :     const OUString sMediaTypeProperty ("MediaType");
     298        2960 :     const OUString sVersionProperty ("Version");
     299        2960 :     const OUString sFullPathProperty ("FullPath");
     300        2960 :     const OUString sInitialisationVectorProperty ("InitialisationVector");
     301        2960 :     const OUString sSaltProperty ("Salt");
     302        2960 :     const OUString sIterationCountProperty ("IterationCount");
     303        2960 :     const OUString sSizeProperty ("Size");
     304        2960 :     const OUString sDigestProperty ("Digest");
     305        2960 :     const OUString sEncryptionAlgProperty    ("EncryptionAlgorithm");
     306        2960 :     const OUString sStartKeyAlgProperty  ("StartKeyAlgorithm");
     307        2960 :     const OUString sDigestAlgProperty    ("DigestAlgorithm");
     308        2960 :     const OUString  sDerivedKeySizeProperty  ("DerivedKeySize");
     309             : 
     310        2960 :     uno::Sequence < PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST);
     311             : 
     312             :     OSL_ENSURE( ( rInfo.bFolder && rInfo.pFolder ) || ( !rInfo.bFolder && rInfo.pStream ), "A valid child object is expected!" );
     313        1480 :     if ( rInfo.bFolder )
     314             :     {
     315         531 :         OUString sTempName = rPath + rShortName + "/";
     316             : 
     317         531 :         if ( !rInfo.pFolder->GetMediaType().isEmpty() )
     318             :         {
     319          33 :             aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
     320          33 :             aPropSet[PKG_MNFST_MEDIATYPE].Value <<= rInfo.pFolder->GetMediaType();
     321          33 :             aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty;
     322          33 :             aPropSet[PKG_MNFST_VERSION].Value <<= rInfo.pFolder->GetVersion();
     323          33 :             aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
     324          33 :             aPropSet[PKG_MNFST_FULLPATH].Value <<= sTempName;
     325             :         }
     326             :         else
     327         498 :             aPropSet.realloc( 0 );
     328             : 
     329         531 :         rInfo.pFolder->saveContents( sTempName, rManList, rZipOut, rEncryptionKey, rRandomPool);
     330             :     }
     331             :     else
     332             :     {
     333             :         // if pTempEntry is necessary, it will be released and passed to the ZipOutputStream
     334             :         // and be deleted in the ZipOutputStream destructor
     335         949 :         auto_ptr < ZipEntry > pAutoTempEntry ( new ZipEntry );
     336         949 :         ZipEntry* pTempEntry = pAutoTempEntry.get();
     337             : 
     338             :         // In case the entry we are reading is also the entry we are writing, we will
     339             :         // store the ZipEntry data in pTempEntry
     340             : 
     341         949 :         ZipPackageFolder::copyZipEntry ( *pTempEntry, rInfo.pStream->aEntry );
     342         949 :         pTempEntry->sPath = rPath + rShortName;
     343         949 :         pTempEntry->nPathLen = (sal_Int16)( OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() );
     344             : 
     345         949 :         sal_Bool bToBeEncrypted = rInfo.pStream->IsToBeEncrypted() && (rEncryptionKey.getLength() || rInfo.pStream->HasOwnKey());
     346         949 :         sal_Bool bToBeCompressed = bToBeEncrypted ? sal_True : rInfo.pStream->IsToBeCompressed();
     347             : 
     348         949 :         aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
     349         949 :         aPropSet[PKG_MNFST_MEDIATYPE].Value <<= rInfo.pStream->GetMediaType( );
     350         949 :         aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty;
     351         949 :         aPropSet[PKG_MNFST_VERSION].Value <<= OUString(); // no version is stored for streams currently
     352         949 :         aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
     353         949 :         aPropSet[PKG_MNFST_FULLPATH].Value <<= pTempEntry->sPath;
     354             : 
     355             : 
     356             :         OSL_ENSURE( rInfo.pStream->GetStreamMode() != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" );
     357             : 
     358         949 :         sal_Bool bRawStream = sal_False;
     359         949 :         if ( rInfo.pStream->GetStreamMode() == PACKAGE_STREAM_DETECT )
     360           0 :             bRawStream = rInfo.pStream->ParsePackageRawStream();
     361         949 :         else if ( rInfo.pStream->GetStreamMode() == PACKAGE_STREAM_RAW )
     362           0 :             bRawStream = sal_True;
     363             : 
     364         949 :         sal_Bool bTransportOwnEncrStreamAsRaw = sal_False;
     365             :         // During the storing the original size of the stream can be changed
     366             :         // TODO/LATER: get rid of this hack
     367         949 :         sal_Int64 nOwnStreamOrigSize = bRawStream ? rInfo.pStream->GetMagicalHackSize() : rInfo.pStream->getSize();
     368             : 
     369         949 :         sal_Bool bUseNonSeekableAccess = sal_False;
     370        1898 :         uno::Reference < XInputStream > xStream;
     371         949 :         if ( !rInfo.pStream->IsPackageMember() && !bRawStream && !bToBeEncrypted && bToBeCompressed )
     372             :         {
     373             :             // the stream is not a package member, not a raw stream,
     374             :             // it should not be encrypted and it should be compressed,
     375             :             // in this case nonseekable access can be used
     376             : 
     377         867 :             xStream = rInfo.pStream->GetOwnStreamNoWrap();
     378         867 :             uno::Reference < XSeekable > xSeek ( xStream, uno::UNO_QUERY );
     379             : 
     380         867 :             bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() );
     381             :         }
     382             : 
     383         949 :         if ( !bUseNonSeekableAccess )
     384             :         {
     385         938 :             xStream = rInfo.pStream->getRawData();
     386             : 
     387         938 :             if ( !xStream.is() )
     388             :             {
     389             :                 OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" );
     390           0 :                 bSuccess = false;
     391           0 :                 return bSuccess;
     392             :             }
     393             : 
     394         938 :             uno::Reference < XSeekable > xSeek ( xStream, uno::UNO_QUERY );
     395             :             try
     396             :             {
     397         938 :                 if ( xSeek.is() )
     398             :                 {
     399             :                     // If the stream is a raw one, then we should be positioned
     400             :                     // at the beginning of the actual data
     401         891 :                     if ( !bToBeCompressed || bRawStream )
     402             :                     {
     403             :                         // The raw stream can neither be encrypted nor connected
     404             :                         OSL_ENSURE( !bRawStream || !(bToBeCompressed || bToBeEncrypted), "The stream is already encrypted!\n" );
     405          30 :                         xSeek->seek ( bRawStream ? rInfo.pStream->GetMagicalHackPos() : 0 );
     406          30 :                         ImplSetStoredData ( *pTempEntry, xStream );
     407             : 
     408             :                         // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties!
     409             :                     }
     410         861 :                     else if ( bToBeEncrypted )
     411             :                     {
     412             :                         // this is the correct original size
     413           5 :                         pTempEntry->nSize = xSeek->getLength();
     414           5 :                         nOwnStreamOrigSize = pTempEntry->nSize;
     415             :                     }
     416             : 
     417         891 :                     xSeek->seek ( 0 );
     418             :                 }
     419             :                 else
     420             :                 {
     421             :                     // Okay, we don't have an xSeekable stream. This is possibly bad.
     422             :                     // check if it's one of our own streams, if it is then we know that
     423             :                     // each time we ask for it we'll get a new stream that will be
     424             :                     // at position zero...otherwise, assert and skip this stream...
     425          47 :                     if ( rInfo.pStream->IsPackageMember() )
     426             :                     {
     427             :                         // if the password has been changed than the stream should not be package member any more
     428          47 :                         if ( rInfo.pStream->IsEncrypted() && rInfo.pStream->IsToBeEncrypted() )
     429             :                         {
     430             :                             // Should be handled close to the raw stream handling
     431           0 :                             bTransportOwnEncrStreamAsRaw = sal_True;
     432           0 :                             pTempEntry->nMethod = STORED;
     433             : 
     434             :                             // TODO/LATER: get rid of this situation
     435             :                             // this size should be different from the one that will be stored in manifest.xml
     436             :                             // it is used in storing algorithms and after storing the correct size will be set
     437           0 :                             pTempEntry->nSize = pTempEntry->nCompressedSize;
     438             :                         }
     439             :                     }
     440             :                     else
     441             :                     {
     442           0 :                         bSuccess = false;
     443           0 :                         return bSuccess;
     444             :                     }
     445             :                 }
     446             :             }
     447           0 :             catch ( uno::Exception& )
     448             :             {
     449           0 :                 bSuccess = false;
     450           0 :                 return bSuccess;
     451             :             }
     452             : 
     453         938 :             if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw )
     454             :             {
     455           5 :                 if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw )
     456             :                 {
     457          10 :                     uno::Sequence < sal_Int8 > aSalt( 16 ), aVector( rInfo.pStream->GetBlockSize() );
     458           5 :                     rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 );
     459           5 :                     rtl_random_getBytes ( rRandomPool, aVector.getArray(), aVector.getLength() );
     460           5 :                     sal_Int32 nIterationCount = 1024;
     461             : 
     462           5 :                     if ( !rInfo.pStream->HasOwnKey() )
     463           5 :                         rInfo.pStream->setKey ( rEncryptionKey );
     464             : 
     465           5 :                     rInfo.pStream->setInitialisationVector ( aVector );
     466           5 :                     rInfo.pStream->setSalt ( aSalt );
     467          10 :                     rInfo.pStream->setIterationCount ( nIterationCount );
     468             :                 }
     469             : 
     470             :                 // last property is digest, which is inserted later if we didn't have
     471             :                 // a magic header
     472           5 :                 aPropSet.realloc(PKG_SIZE_ENCR_MNFST);
     473             : 
     474           5 :                 aPropSet[PKG_MNFST_INIVECTOR].Name = sInitialisationVectorProperty;
     475           5 :                 aPropSet[PKG_MNFST_INIVECTOR].Value <<= rInfo.pStream->getInitialisationVector();
     476           5 :                 aPropSet[PKG_MNFST_SALT].Name = sSaltProperty;
     477           5 :                 aPropSet[PKG_MNFST_SALT].Value <<= rInfo.pStream->getSalt();
     478           5 :                 aPropSet[PKG_MNFST_ITERATION].Name = sIterationCountProperty;
     479           5 :                 aPropSet[PKG_MNFST_ITERATION].Value <<= rInfo.pStream->getIterationCount ();
     480             : 
     481             :                 // Need to store the uncompressed size in the manifest
     482             :                 OSL_ENSURE( nOwnStreamOrigSize >= 0, "The stream size was not correctly initialized!\n" );
     483           5 :                 aPropSet[PKG_MNFST_UCOMPSIZE].Name = sSizeProperty;
     484           5 :                 aPropSet[PKG_MNFST_UCOMPSIZE].Value <<= nOwnStreamOrigSize;
     485             : 
     486           5 :                 if ( bRawStream || bTransportOwnEncrStreamAsRaw )
     487             :                 {
     488           0 :                     ::rtl::Reference< EncryptionData > xEncData = rInfo.pStream->GetEncryptionData();
     489           0 :                     if ( !xEncData.is() )
     490           0 :                         throw uno::RuntimeException();
     491             : 
     492           0 :                     aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty;
     493           0 :                     aPropSet[PKG_MNFST_DIGEST].Value <<= rInfo.pStream->getDigest();
     494           0 :                     aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty;
     495           0 :                     aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg;
     496           0 :                     aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty;
     497           0 :                     aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID;
     498           0 :                     aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty;
     499           0 :                     aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg;
     500           0 :                     aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty;
     501           0 :                     aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize;
     502             :                 }
     503         938 :             }
     504             :         }
     505             : 
     506             :         // If the entry is already stored in the zip file in the format we
     507             :         // want for this write...copy it raw
     508         949 :         if ( !bUseNonSeekableAccess
     509         996 :           && ( bRawStream || bTransportOwnEncrStreamAsRaw
     510         938 :             || ( rInfo.pStream->IsPackageMember() && !bToBeEncrypted
     511          47 :               && ( ( rInfo.pStream->aEntry.nMethod == DEFLATED && bToBeCompressed )
     512           0 :                 || ( rInfo.pStream->aEntry.nMethod == STORED && !bToBeCompressed ) ) ) ) )
     513             :         {
     514             :             // If it's a PackageMember, then it's an unbuffered stream and we need
     515             :             // to get a new version of it as we can't seek backwards.
     516          47 :             if ( rInfo.pStream->IsPackageMember() )
     517             :             {
     518          47 :                 xStream = rInfo.pStream->getRawData();
     519          47 :                 if ( !xStream.is() )
     520             :                 {
     521             :                     // Make sure that we actually _got_ a new one !
     522           0 :                     bSuccess = false;
     523           0 :                     return bSuccess;
     524             :                 }
     525             :             }
     526             : 
     527             :             try
     528             :             {
     529          47 :                 if ( bRawStream )
     530           0 :                     xStream->skipBytes( rInfo.pStream->GetMagicalHackPos() );
     531             : 
     532          47 :                 rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, sal_False );
     533             :                 // the entry is provided to the ZipOutputStream that will delete it
     534          47 :                 pAutoTempEntry.release();
     535             : 
     536          47 :                 uno::Sequence < sal_Int8 > aSeq ( n_ConstBufferSize );
     537             :                 sal_Int32 nLength;
     538             : 
     539          47 :                 do
     540             :                 {
     541          47 :                     nLength = xStream->readBytes( aSeq, n_ConstBufferSize );
     542          47 :                     rZipOut.rawWrite(aSeq, 0, nLength);
     543             :                 }
     544             :                 while ( nLength == n_ConstBufferSize );
     545             : 
     546          47 :                 rZipOut.rawCloseEntry();
     547             :             }
     548           0 :             catch ( ZipException& )
     549             :             {
     550           0 :                 bSuccess = false;
     551             :             }
     552           0 :             catch ( IOException& )
     553             :             {
     554           0 :                 bSuccess = false;
     555             :             }
     556             :         }
     557             :         else
     558             :         {
     559             :             // This stream is defenitly not a raw stream
     560             : 
     561             :             // If nonseekable access is used the stream should be at the beginning and
     562             :             // is useless after the storing. Thus if the storing fails the package should
     563             :             // be thrown away ( as actually it is done currently )!
     564             :             // To allow to reuse the package after the error, the optimization must be removed!
     565             : 
     566             :             // If it's a PackageMember, then our previous reference held a 'raw' stream
     567             :             // so we need to re-get it, unencrypted, uncompressed and positioned at the
     568             :             // beginning of the stream
     569         902 :             if ( rInfo.pStream->IsPackageMember() )
     570             :             {
     571           0 :                 xStream = rInfo.pStream->getInputStream();
     572           0 :                 if ( !xStream.is() )
     573             :                 {
     574             :                     // Make sure that we actually _got_ a new one !
     575           0 :                     bSuccess = false;
     576           0 :                     return bSuccess;
     577             :                 }
     578             :             }
     579             : 
     580         902 :             if ( bToBeCompressed )
     581             :             {
     582         872 :                 pTempEntry->nMethod = DEFLATED;
     583         872 :                 pTempEntry->nCrc = -1;
     584         872 :                 pTempEntry->nCompressedSize = pTempEntry->nSize = -1;
     585             :             }
     586             : 
     587             :             try
     588             :             {
     589         902 :                 rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, bToBeEncrypted);
     590             :                 // the entry is provided to the ZipOutputStream that will delete it
     591         902 :                 pAutoTempEntry.release();
     592             : 
     593             :                 sal_Int32 nLength;
     594         902 :                 uno::Sequence < sal_Int8 > aSeq (n_ConstBufferSize);
     595         939 :                 do
     596             :                 {
     597         939 :                     nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
     598         939 :                     rZipOut.write(aSeq, 0, nLength);
     599             :                 }
     600             :                 while ( nLength == n_ConstBufferSize );
     601             : 
     602         902 :                 rZipOut.closeEntry();
     603             :             }
     604           0 :             catch ( ZipException& )
     605             :             {
     606           0 :                 bSuccess = false;
     607             :             }
     608           0 :             catch ( IOException& )
     609             :             {
     610           0 :                 bSuccess = false;
     611             :             }
     612             : 
     613         902 :             if ( bToBeEncrypted )
     614             :             {
     615           5 :                 ::rtl::Reference< EncryptionData > xEncData = rInfo.pStream->GetEncryptionData();
     616           5 :                 if ( !xEncData.is() )
     617           0 :                     throw uno::RuntimeException();
     618             : 
     619           5 :                 aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty;
     620           5 :                 aPropSet[PKG_MNFST_DIGEST].Value <<= rInfo.pStream->getDigest();
     621           5 :                 aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty;
     622           5 :                 aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg;
     623           5 :                 aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty;
     624           5 :                 aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID;
     625           5 :                 aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty;
     626           5 :                 aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg;
     627           5 :                 aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty;
     628           5 :                 aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize;
     629             : 
     630           5 :                 rInfo.pStream->SetIsEncrypted ( sal_True );
     631             :             }
     632             :         }
     633             : 
     634         949 :         if( bSuccess )
     635             :         {
     636         949 :             if ( !rInfo.pStream->IsPackageMember() )
     637             :             {
     638         902 :                 rInfo.pStream->CloseOwnStreamIfAny();
     639         902 :                 rInfo.pStream->SetPackageMember ( sal_True );
     640             :             }
     641             : 
     642         949 :             if ( bRawStream )
     643             :             {
     644             :                 // the raw stream was integrated and now behaves
     645             :                 // as usual encrypted stream
     646           0 :                 rInfo.pStream->SetToBeEncrypted( sal_True );
     647             :             }
     648             : 
     649             :             // Then copy it back afterwards...
     650         949 :             ZipPackageFolder::copyZipEntry ( rInfo.pStream->aEntry, *pTempEntry );
     651             : 
     652             :             // Remove hacky bit from entry flags
     653         949 :             if ( rInfo.pStream->aEntry.nFlag & ( 1 << 4 ) )
     654             :             {
     655           5 :                 rInfo.pStream->aEntry.nFlag &= ~( 1 << 4 );
     656           5 :                 rInfo.pStream->aEntry.nMethod = STORED;
     657             :             }
     658             : 
     659             :             // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
     660         949 :             if ( rInfo.pStream->IsEncrypted() )
     661           5 :                 rInfo.pStream->setSize( nOwnStreamOrigSize );
     662             : 
     663         949 :             rInfo.pStream->aEntry.nOffset *= -1;
     664         949 :         }
     665             :     }
     666             : 
     667             :     // folder can have a mediatype only in package format
     668        2960 :     if ( aPropSet.getLength()
     669        1480 :       && ( m_nFormat == embed::StorageFormats::PACKAGE || ( m_nFormat == embed::StorageFormats::OFOPXML && !rInfo.bFolder ) ) )
     670         982 :         rManList.push_back( aPropSet );
     671             : 
     672        2960 :     return bSuccess;
     673             : }
     674             : 
     675         760 : void ZipPackageFolder::saveContents( OUString &rPath, std::vector < uno::Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, const uno::Sequence < sal_Int8 >& rEncryptionKey, rtlRandomPool &rRandomPool )
     676             :     throw( uno::RuntimeException )
     677             : {
     678         760 :     bool bWritingFailed = false;
     679             : 
     680         760 :     if ( maContents.begin() == maContents.end() && !rPath.isEmpty() && m_nFormat != embed::StorageFormats::OFOPXML )
     681             :     {
     682             :         // it is an empty subfolder, use workaround to store it
     683         146 :         ZipEntry* pTempEntry = new ZipEntry();
     684         146 :         ZipPackageFolder::copyZipEntry ( *pTempEntry, aEntry );
     685         146 :         pTempEntry->nPathLen = (sal_Int16)( OUStringToOString( rPath, RTL_TEXTENCODING_UTF8 ).getLength() );
     686         146 :         pTempEntry->nExtraLen = -1;
     687         146 :         pTempEntry->sPath = rPath;
     688             : 
     689             :         try
     690             :         {
     691         146 :             rZipOut.putNextEntry( *pTempEntry, NULL, sal_False );
     692         146 :             rZipOut.rawCloseEntry();
     693             :         }
     694           0 :         catch ( ZipException& )
     695             :         {
     696           0 :             bWritingFailed = true;
     697             :         }
     698           0 :         catch ( IOException& )
     699             :         {
     700           0 :             bWritingFailed = true;
     701             :         }
     702             :     }
     703             : 
     704         760 :     bool bMimeTypeStreamStored = false;
     705         760 :     OUString aMimeTypeStreamName("mimetype");
     706         760 :     if ( m_nFormat == embed::StorageFormats::ZIP && rPath.isEmpty() )
     707             :     {
     708             :         // let the "mimtype" stream in root folder be stored as the first stream if it is zip format
     709           0 :         ContentHash::iterator aIter = maContents.find ( aMimeTypeStreamName );
     710           0 :         if ( aIter != maContents.end() && !(*aIter).second->bFolder )
     711             :         {
     712           0 :             bMimeTypeStreamStored = true;
     713           0 :             bWritingFailed = !saveChild( (*aIter).first, *(*aIter).second, rPath, rManList, rZipOut, rEncryptionKey, rRandomPool );
     714             :         }
     715             :     }
     716             : 
     717        2240 :     for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end();
     718             :           aCI != aEnd;
     719             :           ++aCI)
     720             :     {
     721        1480 :         const OUString &rShortName = (*aCI).first;
     722        1480 :         const ContentInfo &rInfo = *(*aCI).second;
     723             : 
     724        1480 :         if ( !bMimeTypeStreamStored || !rShortName.equals( aMimeTypeStreamName ) )
     725        1480 :             bWritingFailed = !saveChild( rShortName, rInfo, rPath, rManList, rZipOut, rEncryptionKey, rRandomPool );
     726             :     }
     727             : 
     728         760 :     if( bWritingFailed )
     729           0 :         throw uno::RuntimeException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
     730         760 : }
     731             : 
     732        8651 : void ZipPackageFolder::releaseUpwardRef( void )
     733             : {
     734             :     // Now it is possible that a package folder is disconnected from the package before removing of the folder.
     735             :     // Such a scenario is used in storage implementation. When a new version of a folder is provided the old
     736             :     // one is retrieved, removed from the package but preserved for the error handling.
     737             :     // In this scenario the referencing to the parent is not really useful, since it requires disposing.
     738             : 
     739             :     // Actually there is no need in having a reference to the parent, it even make things more complicated and
     740             :     // requires disposing mechanics. Using of a simple pointer seems to be easier solution and also a safe enough.
     741             : 
     742        8651 :     clearParent();
     743             : 
     744             : #if 0
     745             :     for ( ContentHash::const_iterator aCI = maContents.begin();
     746             :           aCI!=maContents.end();
     747             :           aCI++)
     748             :     {
     749             :         ContentInfo &rInfo = * (*aCI).second;
     750             :         if ( rInfo.bFolder )// && ! rInfo.pFolder->HasReleased () )
     751             :             rInfo.pFolder->releaseUpwardRef();
     752             :         else //if ( !rInfo.bFolder && !rInfo.pStream->HasReleased() )
     753             :             rInfo.pStream->clearParent();
     754             :     }
     755             :     clearParent();
     756             : 
     757             :     OSL_ENSURE ( m_refCount == 1, "Ref-count is not 1!" );
     758             : #endif
     759        8651 : }
     760             : 
     761        3700 : sal_Int64 SAL_CALL ZipPackageFolder::getSomething( const uno::Sequence< sal_Int8 >& aIdentifier )
     762             :     throw(uno::RuntimeException)
     763             : {
     764        3700 :     sal_Int64 nMe = 0;
     765        7400 :     if ( aIdentifier.getLength() == 16 &&
     766        3700 :          0 == memcmp(static_getImplementationId().getConstArray(),  aIdentifier.getConstArray(), 16 ) )
     767        3700 :         nMe = reinterpret_cast < sal_Int64 > ( this );
     768        3700 :     return nMe;
     769             : }
     770        1636 : void SAL_CALL ZipPackageFolder::setPropertyValue( const OUString& aPropertyName, const uno::Any& aValue )
     771             :         throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, uno::RuntimeException)
     772             : {
     773        1636 :     if ( aPropertyName == "MediaType" )
     774             :     {
     775             :         // TODO/LATER: activate when zip ucp is ready
     776             :         // if ( m_nFormat != embed::StorageFormats::PACKAGE )
     777             :         //  throw UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
     778             : 
     779         818 :         aValue >>= sMediaType;
     780             :     }
     781         818 :     else if ( aPropertyName == "Version" )
     782         818 :         aValue >>= m_sVersion;
     783           0 :     else if ( aPropertyName == "Size" )
     784           0 :         aValue >>= aEntry.nSize;
     785             :     else
     786           0 :         throw UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
     787        1636 : }
     788       17878 : uno::Any SAL_CALL ZipPackageFolder::getPropertyValue( const OUString& PropertyName )
     789             :         throw(UnknownPropertyException, WrappedTargetException, uno::RuntimeException)
     790             : {
     791       17878 :     if ( PropertyName == "MediaType" )
     792             :     {
     793             :         // TODO/LATER: activate when zip ucp is ready
     794             :         // if ( m_nFormat != embed::StorageFormats::PACKAGE )
     795             :         //  throw UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
     796             : 
     797        8905 :         return uno::makeAny ( sMediaType );
     798             :     }
     799        8973 :     else if ( PropertyName == "Version" )
     800        8973 :         return uno::makeAny( m_sVersion );
     801           0 :     else if ( PropertyName == "Size" )
     802           0 :         return uno::makeAny ( aEntry.nSize );
     803             :     else
     804           0 :         throw UnknownPropertyException(OSL_LOG_PREFIX, uno::Reference< uno::XInterface >() );
     805             : }
     806             : 
     807       23932 : void ZipPackageFolder::doInsertByName ( ZipPackageEntry *pEntry, sal_Bool bSetParent )
     808             :         throw(IllegalArgumentException, ElementExistException, WrappedTargetException, uno::RuntimeException)
     809             : {
     810             :     try
     811             :     {
     812       23932 :         if ( pEntry->IsFolder() )
     813        8759 :             maContents[pEntry->getName()] = new ContentInfo ( static_cast < ZipPackageFolder *> ( pEntry ) );
     814             :         else
     815       15173 :             maContents[pEntry->getName()] = new ContentInfo ( static_cast < ZipPackageStream *> ( pEntry ) );
     816             :     }
     817           0 :     catch(const uno::Exception& rEx)
     818             :     {
     819             :         (void)rEx;
     820           0 :         throw;
     821             :     }
     822       23932 :     if ( bSetParent )
     823        2161 :         pEntry->setParent ( *this );
     824       23932 : }
     825           0 : OUString ZipPackageFolder::getImplementationName()
     826             :     throw (uno::RuntimeException)
     827             : {
     828           0 :     return OUString("ZipPackageFolder");
     829             : }
     830             : 
     831           0 : uno::Sequence< OUString > ZipPackageFolder::getSupportedServiceNames()
     832             :     throw (uno::RuntimeException)
     833             : {
     834           0 :     uno::Sequence< OUString > aNames(1);
     835           0 :     aNames[0] = "com.sun.star.packages.PackageFolder";
     836           0 :     return aNames;
     837             : }
     838           0 : sal_Bool SAL_CALL ZipPackageFolder::supportsService( OUString const & rServiceName )
     839             :     throw (uno::RuntimeException)
     840             : {
     841           0 :     return rServiceName == getSupportedServiceNames()[0];
     842             : }
     843             : 
     844             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10