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

Generated by: LCOV version 1.10