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

Generated by: LCOV version 1.10