LCOV - code coverage report
Current view: top level - package/source/zippackage - ZipPackageStream.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 410 617 66.5 %
Date: 2014-11-03 Functions: 27 33 81.8 %
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 <ZipPackageStream.hxx>
      21             : 
      22             : #include <com/sun/star/beans/PropertyValue.hpp>
      23             : #include <com/sun/star/packages/zip/ZipConstants.hpp>
      24             : #include <com/sun/star/embed/StorageFormats.hpp>
      25             : #include <com/sun/star/packages/zip/ZipIOException.hpp>
      26             : #include <com/sun/star/io/TempFile.hpp>
      27             : #include <com/sun/star/io/XInputStream.hpp>
      28             : #include <com/sun/star/io/XOutputStream.hpp>
      29             : #include <com/sun/star/io/XStream.hpp>
      30             : #include <com/sun/star/io/XSeekable.hpp>
      31             : #include <com/sun/star/xml/crypto/DigestID.hpp>
      32             : #include <com/sun/star/xml/crypto/CipherID.hpp>
      33             : 
      34             : #include <string.h>
      35             : 
      36             : #include <CRC32.hxx>
      37             : #include <ZipOutputEntry.hxx>
      38             : #include <ZipOutputStream.hxx>
      39             : #include <ZipPackage.hxx>
      40             : #include <ZipPackageFolder.hxx>
      41             : #include <ZipFile.hxx>
      42             : #include <EncryptedDataHeader.hxx>
      43             : #include <osl/diagnose.h>
      44             : #include "wrapstreamforshare.hxx"
      45             : 
      46             : #include <comphelper/processfactory.hxx>
      47             : #include <comphelper/seekableinput.hxx>
      48             : #include <comphelper/storagehelper.hxx>
      49             : #include <cppuhelper/supportsservice.hxx>
      50             : #include <cppuhelper/typeprovider.hxx>
      51             : 
      52             : #include <rtl/instance.hxx>
      53             : #include <rtl/random.h>
      54             : 
      55             : #include <PackageConstants.hxx>
      56             : 
      57             : using namespace com::sun::star::packages::zip::ZipConstants;
      58             : using namespace com::sun::star::packages::zip;
      59             : using namespace com::sun::star::uno;
      60             : using namespace com::sun::star::lang;
      61             : using namespace com::sun::star;
      62             : using namespace cppu;
      63             : 
      64             : #if OSL_DEBUG_LEVEL > 0
      65             : #define THROW_WHERE SAL_WHERE
      66             : #else
      67             : #define THROW_WHERE ""
      68             : #endif
      69             : 
      70             : namespace { struct lcl_CachedImplId : public rtl::Static< cppu::OImplementationId, lcl_CachedImplId > {}; }
      71             : 
      72      327454 : ::com::sun::star::uno::Sequence < sal_Int8 > ZipPackageStream::static_getImplementationId()
      73             : {
      74      327454 :     return lcl_CachedImplId::get().getImplementationId();
      75             : }
      76             : 
      77      428362 : ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage,
      78             :                                     const uno::Reference< XComponentContext >& xContext,
      79             :                                     sal_Int32 nFormat,
      80             :                                     bool bAllowRemoveOnInsert )
      81             : : m_rZipPackage( rNewPackage )
      82             : , m_bToBeCompressed ( true )
      83             : , m_bToBeEncrypted ( false )
      84             : , m_bHaveOwnKey ( false )
      85             : , m_bIsEncrypted ( false )
      86             : , m_nImportedStartKeyAlgorithm( 0 )
      87             : , m_nImportedEncryptionAlgorithm( 0 )
      88             : , m_nImportedChecksumAlgorithm( 0 )
      89             : , m_nImportedDerivedKeySize( 0 )
      90             : , m_nStreamMode( PACKAGE_STREAM_NOTSET )
      91             : , m_nMagicalHackPos( 0 )
      92             : , m_nMagicalHackSize( 0 )
      93             : , m_bHasSeekable( false )
      94             : , m_bCompressedIsSetFromOutside( false )
      95             : , m_bFromManifest( false )
      96      428362 : , m_bUseWinEncoding( false )
      97             : {
      98      428362 :     m_xContext = xContext;
      99      428362 :     m_nFormat = nFormat;
     100      428362 :     mbAllowRemoveOnInsert = bAllowRemoveOnInsert;
     101      428362 :     SetFolder ( false );
     102      428362 :     aEntry.nVersion     = -1;
     103      428362 :     aEntry.nFlag        = 0;
     104      428362 :     aEntry.nMethod      = -1;
     105      428362 :     aEntry.nTime        = -1;
     106      428362 :     aEntry.nCrc         = -1;
     107      428362 :     aEntry.nCompressedSize  = -1;
     108      428362 :     aEntry.nSize        = -1;
     109      428362 :     aEntry.nOffset      = -1;
     110      428362 :     aEntry.nPathLen     = -1;
     111      428362 :     aEntry.nExtraLen    = -1;
     112      428362 : }
     113             : 
     114      856652 : ZipPackageStream::~ZipPackageStream( void )
     115             : {
     116      856652 : }
     117             : 
     118      381078 : void ZipPackageStream::setZipEntryOnLoading( const ZipEntry &rInEntry )
     119             : {
     120      381078 :     aEntry.nVersion = rInEntry.nVersion;
     121      381078 :     aEntry.nFlag = rInEntry.nFlag;
     122      381078 :     aEntry.nMethod = rInEntry.nMethod;
     123      381078 :     aEntry.nTime = rInEntry.nTime;
     124      381078 :     aEntry.nCrc = rInEntry.nCrc;
     125      381078 :     aEntry.nCompressedSize = rInEntry.nCompressedSize;
     126      381078 :     aEntry.nSize = rInEntry.nSize;
     127      381078 :     aEntry.nOffset = rInEntry.nOffset;
     128      381078 :     aEntry.sPath = rInEntry.sPath;
     129      381078 :     aEntry.nPathLen = rInEntry.nPathLen;
     130      381078 :     aEntry.nExtraLen = rInEntry.nExtraLen;
     131             : 
     132      381078 :     if ( aEntry.nMethod == STORED )
     133       10112 :         m_bToBeCompressed = false;
     134      381078 : }
     135             : 
     136       16316 : void ZipPackageStream::CloseOwnStreamIfAny()
     137             : {
     138       16316 :     if ( m_xStream.is() )
     139             :     {
     140       16316 :         m_xStream->closeInput();
     141       16316 :         m_xStream = uno::Reference< io::XInputStream >();
     142       16316 :         m_bHasSeekable = false;
     143             :     }
     144       16316 : }
     145             : 
     146       39422 : uno::Reference< io::XInputStream > ZipPackageStream::GetOwnSeekStream()
     147             : {
     148       39422 :     if ( !m_bHasSeekable && m_xStream.is() )
     149             :     {
     150             :         // The package component requires that every stream either be FROM a package or it must support XSeekable!
     151             :         // The only exception is a nonseekable stream that is provided only for storing, if such a stream
     152             :         // is accessed before commit it MUST be wrapped.
     153             :         // Wrap the stream in case it is not seekable
     154       17360 :         m_xStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( m_xStream, m_xContext );
     155       17360 :         uno::Reference< io::XSeekable > xSeek( m_xStream, UNO_QUERY );
     156       17360 :         if ( !xSeek.is() )
     157           0 :             throw RuntimeException( THROW_WHERE "The stream must support XSeekable!" );
     158             : 
     159       17360 :         m_bHasSeekable = true;
     160             :     }
     161             : 
     162       39422 :     return m_xStream;
     163             : }
     164             : 
     165           0 : uno::Reference< io::XInputStream > ZipPackageStream::GetRawEncrStreamNoHeaderCopy()
     166             : {
     167           0 :     if ( m_nStreamMode != PACKAGE_STREAM_RAW || !GetOwnSeekStream().is() )
     168           0 :         throw io::IOException(THROW_WHERE );
     169             : 
     170           0 :     if ( m_xBaseEncryptionData.is() )
     171           0 :         throw ZipIOException(THROW_WHERE "Encrypted stream without encryption data!" );
     172             : 
     173           0 :     uno::Reference< io::XSeekable > xSeek( GetOwnSeekStream(), UNO_QUERY );
     174           0 :     if ( !xSeek.is() )
     175           0 :         throw ZipIOException(THROW_WHERE "The stream must be seekable!" );
     176             : 
     177             :     // skip header
     178           0 :     xSeek->seek( n_ConstHeaderSize + m_xBaseEncryptionData->m_aInitVector.getLength() +
     179           0 :                     m_xBaseEncryptionData->m_aSalt.getLength() + m_xBaseEncryptionData->m_aDigest.getLength() );
     180             : 
     181             :     // create temporary stream
     182           0 :     uno::Reference < io::XTempFile > xTempFile = io::TempFile::create(m_xContext);
     183           0 :     uno::Reference < io::XOutputStream > xTempOut = xTempFile->getOutputStream();
     184           0 :     uno::Reference < io::XInputStream > xTempIn = xTempFile->getInputStream();;
     185           0 :     uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
     186             : 
     187             :     // copy the raw stream to the temporary file starting from the current position
     188           0 :     ::comphelper::OStorageHelper::CopyInputToOutput( GetOwnSeekStream(), xTempOut );
     189           0 :     xTempOut->closeOutput();
     190           0 :     xTempSeek->seek( 0 );
     191             : 
     192           0 :     return xTempIn;
     193             : }
     194             : 
     195         184 : sal_Int32 ZipPackageStream::GetEncryptionAlgorithm() const
     196             : {
     197         184 :     return m_nImportedEncryptionAlgorithm ? m_nImportedEncryptionAlgorithm : m_rZipPackage.GetEncAlgID();
     198             : }
     199             : 
     200          10 : sal_Int32 ZipPackageStream::GetBlockSize() const
     201             : {
     202          10 :     return GetEncryptionAlgorithm() == ::com::sun::star::xml::crypto::CipherID::AES_CBC_W3C_PADDING ? 16 : 8;
     203             : }
     204             : 
     205      104586 : ::rtl::Reference< EncryptionData > ZipPackageStream::GetEncryptionData( bool bUseWinEncoding )
     206             : {
     207      104586 :     ::rtl::Reference< EncryptionData > xResult;
     208      104586 :     if ( m_xBaseEncryptionData.is() )
     209         592 :         xResult = new EncryptionData(
     210         174 :             *m_xBaseEncryptionData,
     211             :             GetEncryptionKey( bUseWinEncoding ),
     212             :             GetEncryptionAlgorithm(),
     213         122 :             m_nImportedChecksumAlgorithm ? m_nImportedChecksumAlgorithm : m_rZipPackage.GetChecksumAlgID(),
     214         122 :             m_nImportedDerivedKeySize ? m_nImportedDerivedKeySize : m_rZipPackage.GetDefaultDerivedKeySize(),
     215         174 :             GetStartKeyGenID() );
     216             : 
     217      104586 :     return xResult;
     218             : }
     219             : 
     220         174 : uno::Sequence< sal_Int8 > ZipPackageStream::GetEncryptionKey( bool bUseWinEncoding )
     221             : {
     222         174 :     uno::Sequence< sal_Int8 > aResult;
     223         174 :     sal_Int32 nKeyGenID = GetStartKeyGenID();
     224         174 :     bUseWinEncoding = ( bUseWinEncoding || m_bUseWinEncoding );
     225             : 
     226         174 :     if ( m_bHaveOwnKey && m_aStorageEncryptionKeys.getLength() )
     227             :     {
     228          46 :         OUString aNameToFind;
     229          46 :         if ( nKeyGenID == xml::crypto::DigestID::SHA256 )
     230          30 :             aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8;
     231          16 :         else if ( nKeyGenID == xml::crypto::DigestID::SHA1 )
     232             :         {
     233          16 :             aNameToFind = bUseWinEncoding ? PACKAGE_ENCRYPTIONDATA_SHA1MS1252 : PACKAGE_ENCRYPTIONDATA_SHA1UTF8;
     234             :         }
     235             :         else
     236           0 :             throw uno::RuntimeException(THROW_WHERE "No expected key is provided!" );
     237             : 
     238         184 :         for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ )
     239         138 :             if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) )
     240          46 :                 m_aStorageEncryptionKeys[nInd].Value >>= aResult;
     241             : 
     242             :         // empty keys are not allowed here
     243             :         // so it is not important whether there is no key, or the key is empty, it is an error
     244          46 :         if ( !aResult.getLength() )
     245           0 :             throw uno::RuntimeException(THROW_WHERE "No expected key is provided!" );
     246             :     }
     247             :     else
     248         128 :         aResult = m_aEncryptionKey;
     249             : 
     250         174 :     if ( !aResult.getLength() || !m_bHaveOwnKey )
     251         128 :         aResult = m_rZipPackage.GetEncryptionKey();
     252             : 
     253         174 :     return aResult;
     254             : }
     255             : 
     256         348 : sal_Int32 ZipPackageStream::GetStartKeyGenID()
     257             : {
     258             :     // generally should all the streams use the same Start Key
     259             :     // but if raw copy without password takes place, we should preserve the imported algorithm
     260         348 :     return m_nImportedStartKeyAlgorithm ? m_nImportedStartKeyAlgorithm : m_rZipPackage.GetStartKeyGenID();
     261             : }
     262             : 
     263           0 : uno::Reference< io::XInputStream > ZipPackageStream::TryToGetRawFromDataStream( bool bAddHeaderForEncr )
     264             : {
     265           0 :     if ( m_nStreamMode != PACKAGE_STREAM_DATA || !GetOwnSeekStream().is() || ( bAddHeaderForEncr && !m_bToBeEncrypted ) )
     266           0 :         throw packages::NoEncryptionException(THROW_WHERE );
     267             : 
     268           0 :     Sequence< sal_Int8 > aKey;
     269             : 
     270           0 :     if ( m_bToBeEncrypted )
     271             :     {
     272           0 :         aKey = GetEncryptionKey();
     273           0 :         if ( !aKey.getLength() )
     274           0 :             throw packages::NoEncryptionException(THROW_WHERE );
     275             :     }
     276             : 
     277             :     try
     278             :     {
     279             :         // create temporary file
     280             :         uno::Reference < io::XStream > xTempStream(
     281             :                             io::TempFile::create(m_xContext),
     282           0 :                             uno::UNO_QUERY_THROW );
     283             : 
     284             :         // create a package based on it
     285           0 :         ZipPackage* pPackage = new ZipPackage( m_xContext );
     286           0 :         uno::Reference< XSingleServiceFactory > xPackageAsFactory( static_cast< XSingleServiceFactory* >( pPackage ) );
     287           0 :         if ( !xPackageAsFactory.is() )
     288           0 :             throw RuntimeException(THROW_WHERE );
     289             : 
     290           0 :         Sequence< Any > aArgs( 1 );
     291           0 :         aArgs[0] <<= xTempStream;
     292           0 :         pPackage->initialize( aArgs );
     293             : 
     294             :         // create a new package stream
     295           0 :         uno::Reference< XDataSinkEncrSupport > xNewPackStream( xPackageAsFactory->createInstance(), UNO_QUERY );
     296           0 :         if ( !xNewPackStream.is() )
     297           0 :             throw RuntimeException(THROW_WHERE );
     298             : 
     299           0 :         xNewPackStream->setDataStream( static_cast< io::XInputStream* >(
     300           0 :                                                     new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() ) ) );
     301             : 
     302           0 :         uno::Reference< XPropertySet > xNewPSProps( xNewPackStream, UNO_QUERY );
     303           0 :         if ( !xNewPSProps.is() )
     304           0 :             throw RuntimeException(THROW_WHERE );
     305             : 
     306             :         // copy all the properties of this stream to the new stream
     307           0 :         xNewPSProps->setPropertyValue("MediaType", makeAny( msMediaType ) );
     308           0 :         xNewPSProps->setPropertyValue("Compressed", makeAny( m_bToBeCompressed ) );
     309           0 :         if ( m_bToBeEncrypted )
     310             :         {
     311           0 :             xNewPSProps->setPropertyValue(ENCRYPTION_KEY_PROPERTY, makeAny( aKey ) );
     312           0 :             xNewPSProps->setPropertyValue("Encrypted", makeAny( true ) );
     313             :         }
     314             : 
     315             :         // insert a new stream in the package
     316           0 :         uno::Reference< XUnoTunnel > xTunnel;
     317           0 :         Any aRoot = pPackage->getByHierarchicalName("/");
     318           0 :         aRoot >>= xTunnel;
     319           0 :         uno::Reference< container::XNameContainer > xRootNameContainer( xTunnel, UNO_QUERY );
     320           0 :         if ( !xRootNameContainer.is() )
     321           0 :             throw RuntimeException(THROW_WHERE );
     322             : 
     323           0 :         uno::Reference< XUnoTunnel > xNPSTunnel( xNewPackStream, UNO_QUERY );
     324           0 :         xRootNameContainer->insertByName("dummy", makeAny( xNPSTunnel ) );
     325             : 
     326             :         // commit the temporary package
     327           0 :         pPackage->commitChanges();
     328             : 
     329             :         // get raw stream from the temporary package
     330           0 :         uno::Reference< io::XInputStream > xInRaw;
     331           0 :         if ( bAddHeaderForEncr )
     332           0 :             xInRaw = xNewPackStream->getRawStream();
     333             :         else
     334           0 :             xInRaw = xNewPackStream->getPlainRawStream();
     335             : 
     336             :         // create another temporary file
     337             :         uno::Reference < io::XOutputStream > xTempOut(
     338             :                             io::TempFile::create(m_xContext),
     339           0 :                             uno::UNO_QUERY_THROW );
     340           0 :         uno::Reference < io::XInputStream > xTempIn( xTempOut, UNO_QUERY_THROW );
     341           0 :         uno::Reference < io::XSeekable > xTempSeek( xTempOut, UNO_QUERY_THROW );
     342             : 
     343             :         // copy the raw stream to the temporary file
     344           0 :         ::comphelper::OStorageHelper::CopyInputToOutput( xInRaw, xTempOut );
     345           0 :         xTempOut->closeOutput();
     346           0 :         xTempSeek->seek( 0 );
     347             : 
     348             :         // close raw stream, package stream and folder
     349           0 :         xInRaw = uno::Reference< io::XInputStream >();
     350           0 :         xNewPSProps = uno::Reference< XPropertySet >();
     351           0 :         xNPSTunnel = uno::Reference< XUnoTunnel >();
     352           0 :         xNewPackStream = uno::Reference< XDataSinkEncrSupport >();
     353           0 :         xTunnel = uno::Reference< XUnoTunnel >();
     354           0 :         xRootNameContainer = uno::Reference< container::XNameContainer >();
     355             : 
     356             :         // return the stream representing the first temporary file
     357           0 :         return xTempIn;
     358             :     }
     359           0 :     catch ( RuntimeException& )
     360             :     {
     361           0 :         throw;
     362             :     }
     363           0 :     catch ( Exception& )
     364             :     {
     365             :     }
     366             : 
     367           0 :     throw io::IOException(THROW_WHERE );
     368             : }
     369             : 
     370           2 : bool ZipPackageStream::ParsePackageRawStream()
     371             : {
     372             :     OSL_ENSURE( GetOwnSeekStream().is(), "A stream must be provided!\n" );
     373             : 
     374           2 :     if ( !GetOwnSeekStream().is() )
     375           0 :         return false;
     376             : 
     377           2 :     bool bOk = false;
     378             : 
     379           2 :     ::rtl::Reference< BaseEncryptionData > xTempEncrData;
     380           2 :     sal_Int32 nMagHackSize = 0;
     381           4 :     Sequence < sal_Int8 > aHeader ( 4 );
     382             : 
     383             :     try
     384             :     {
     385           2 :         if ( GetOwnSeekStream()->readBytes ( aHeader, 4 ) == 4 )
     386             :         {
     387           2 :             const sal_Int8 *pHeader = aHeader.getConstArray();
     388           4 :             sal_uInt32 nHeader = ( pHeader [0] & 0xFF )       |
     389           4 :                                  ( pHeader [1] & 0xFF ) << 8  |
     390           4 :                                  ( pHeader [2] & 0xFF ) << 16 |
     391           4 :                                  ( pHeader [3] & 0xFF ) << 24;
     392           2 :             if ( nHeader == n_ConstHeader )
     393             :             {
     394             :                 // this is one of our god-awful, but extremely devious hacks, everyone cheer
     395           2 :                 xTempEncrData = new BaseEncryptionData;
     396             : 
     397           2 :                 OUString aMediaType;
     398           2 :                 sal_Int32 nEncAlgorithm = 0;
     399           2 :                 sal_Int32 nChecksumAlgorithm = 0;
     400           2 :                 sal_Int32 nDerivedKeySize = 0;
     401           2 :                 sal_Int32 nStartKeyGenID = 0;
     402           2 :                 if ( ZipFile::StaticFillData( xTempEncrData, nEncAlgorithm, nChecksumAlgorithm, nDerivedKeySize, nStartKeyGenID, nMagHackSize, aMediaType, GetOwnSeekStream() ) )
     403             :                 {
     404             :                     // We'll want to skip the data we've just read, so calculate how much we just read
     405             :                     // and remember it
     406           2 :                     m_nMagicalHackPos = n_ConstHeaderSize + xTempEncrData->m_aSalt.getLength()
     407           2 :                                                         + xTempEncrData->m_aInitVector.getLength()
     408           2 :                                                         + xTempEncrData->m_aDigest.getLength()
     409           2 :                                                         + aMediaType.getLength() * sizeof( sal_Unicode );
     410           2 :                     m_nImportedEncryptionAlgorithm = nEncAlgorithm;
     411           2 :                     m_nImportedChecksumAlgorithm = nChecksumAlgorithm;
     412           2 :                     m_nImportedDerivedKeySize = nDerivedKeySize;
     413           2 :                     m_nImportedStartKeyAlgorithm = nStartKeyGenID;
     414           2 :                     m_nMagicalHackSize = nMagHackSize;
     415           2 :                     msMediaType = aMediaType;
     416             : 
     417           2 :                     bOk = true;
     418           2 :                 }
     419             :             }
     420             :         }
     421             :     }
     422           0 :     catch( Exception& )
     423             :     {
     424             :     }
     425             : 
     426           2 :     if ( !bOk )
     427             :     {
     428             :         // the provided stream is not a raw stream
     429           0 :         return false;
     430             :     }
     431             : 
     432           2 :     m_xBaseEncryptionData = xTempEncrData;
     433           2 :     SetIsEncrypted ( true );
     434             :     // it's already compressed and encrypted
     435           2 :     m_bToBeEncrypted = m_bToBeCompressed = false;
     436             : 
     437           4 :     return true;
     438             : }
     439             : 
     440         106 : static void ImplSetStoredData( ZipEntry & rEntry, uno::Reference< io::XInputStream> & rStream )
     441             : {
     442             :     // It's very annoying that we have to do this, but lots of zip packages
     443             :     // don't allow data descriptors for STORED streams, meaning we have to
     444             :     // know the size and CRC32 of uncompressed streams before we actually
     445             :     // write them !
     446         106 :     CRC32 aCRC32;
     447         106 :     rEntry.nMethod = STORED;
     448         106 :     rEntry.nCompressedSize = rEntry.nSize = aCRC32.updateStream ( rStream );
     449         106 :     rEntry.nCrc = aCRC32.getValue();
     450         106 : }
     451             : 
     452       16494 : bool ZipPackageStream::saveChild(
     453             :         const OUString &rPath,
     454             :         std::vector < uno::Sequence < beans::PropertyValue > > &rManList,
     455             :         ZipOutputStream & rZipOut,
     456             :         const uno::Sequence < sal_Int8 >& rEncryptionKey,
     457             :         const rtlRandomPool &rRandomPool)
     458             : {
     459       16494 :     bool bSuccess = true;
     460             : 
     461       16494 :     const OUString sMediaTypeProperty ("MediaType");
     462       32988 :     const OUString sVersionProperty ("Version");
     463       32988 :     const OUString sFullPathProperty ("FullPath");
     464       32988 :     const OUString sInitialisationVectorProperty ("InitialisationVector");
     465       32988 :     const OUString sSaltProperty ("Salt");
     466       32988 :     const OUString sIterationCountProperty ("IterationCount");
     467       32988 :     const OUString sSizeProperty ("Size");
     468       32988 :     const OUString sDigestProperty ("Digest");
     469       32988 :     const OUString sEncryptionAlgProperty    ("EncryptionAlgorithm");
     470       32988 :     const OUString sStartKeyAlgProperty  ("StartKeyAlgorithm");
     471       32988 :     const OUString sDigestAlgProperty    ("DigestAlgorithm");
     472       32988 :     const OUString sDerivedKeySizeProperty  ("DerivedKeySize");
     473             : 
     474       32988 :     uno::Sequence < beans::PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST);
     475             : 
     476             :     // if pTempEntry is necessary, it will be released and passed to the ZipOutputStream
     477             :     // and be deleted in the ZipOutputStream destructor
     478       32988 :     std::unique_ptr < ZipEntry > pAutoTempEntry ( new ZipEntry );
     479       16494 :     ZipEntry* pTempEntry = pAutoTempEntry.get();
     480             : 
     481             :     // In case the entry we are reading is also the entry we are writing, we will
     482             :     // store the ZipEntry data in pTempEntry
     483             : 
     484       16494 :     ZipPackageFolder::copyZipEntry ( *pTempEntry, aEntry );
     485       16494 :     pTempEntry->sPath = rPath;
     486       16494 :     pTempEntry->nPathLen = (sal_Int16)( OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() );
     487             : 
     488       16494 :     bool bToBeEncrypted = m_bToBeEncrypted && (rEncryptionKey.getLength() || m_bHaveOwnKey);
     489       16494 :     bool bToBeCompressed = bToBeEncrypted ? sal_True : m_bToBeCompressed;
     490             : 
     491       16494 :     aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
     492       16494 :     aPropSet[PKG_MNFST_MEDIATYPE].Value <<= GetMediaType( );
     493       16494 :     aPropSet[PKG_MNFST_VERSION].Name = sVersionProperty;
     494       16494 :     aPropSet[PKG_MNFST_VERSION].Value <<= OUString(); // no version is stored for streams currently
     495       16494 :     aPropSet[PKG_MNFST_FULLPATH].Name = sFullPathProperty;
     496       16494 :     aPropSet[PKG_MNFST_FULLPATH].Value <<= pTempEntry->sPath;
     497             : 
     498             :     OSL_ENSURE( m_nStreamMode != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" );
     499             : 
     500       16494 :     bool bRawStream = false;
     501       16494 :     if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
     502           0 :         bRawStream = ParsePackageRawStream();
     503       16494 :     else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
     504           2 :         bRawStream = true;
     505             : 
     506       16494 :     bool bTransportOwnEncrStreamAsRaw = false;
     507             :     // During the storing the original size of the stream can be changed
     508             :     // TODO/LATER: get rid of this hack
     509       16494 :     sal_Int64 nOwnStreamOrigSize = bRawStream ? m_nMagicalHackSize : aEntry.nSize;
     510             : 
     511       16494 :     bool bUseNonSeekableAccess = false;
     512       32988 :     uno::Reference < io::XInputStream > xStream;
     513       16494 :     if ( !IsPackageMember() && !bRawStream && !bToBeEncrypted && bToBeCompressed )
     514             :     {
     515             :         // the stream is not a package member, not a raw stream,
     516             :         // it should not be encrypted and it should be compressed,
     517             :         // in this case nonseekable access can be used
     518             : 
     519       16200 :         xStream = m_xStream;
     520       16200 :         uno::Reference < io::XSeekable > xSeek ( xStream, uno::UNO_QUERY );
     521             : 
     522       16200 :         bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() );
     523             :     }
     524             : 
     525       16494 :     if ( !bUseNonSeekableAccess )
     526             :     {
     527       16462 :         xStream = getRawData();
     528             : 
     529       16462 :         if ( !xStream.is() )
     530             :         {
     531             :             OSL_FAIL( "ZipPackageStream didn't have a stream associated with it, skipping!" );
     532           0 :             bSuccess = false;
     533           0 :             return bSuccess;
     534             :         }
     535             : 
     536       16462 :         uno::Reference < io::XSeekable > xSeek ( xStream, uno::UNO_QUERY );
     537             :         try
     538             :         {
     539       16462 :             if ( xSeek.is() )
     540             :             {
     541             :                 // If the stream is a raw one, then we should be positioned
     542             :                 // at the beginning of the actual data
     543       16284 :                 if ( !bToBeCompressed || bRawStream )
     544             :                 {
     545             :                     // The raw stream can neither be encrypted nor connected
     546             :                     OSL_ENSURE( !bRawStream || !(bToBeCompressed || bToBeEncrypted), "The stream is already encrypted!\n" );
     547         106 :                     xSeek->seek ( bRawStream ? m_nMagicalHackPos : 0 );
     548         106 :                     ImplSetStoredData ( *pTempEntry, xStream );
     549             : 
     550             :                     // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties!
     551             :                 }
     552       16178 :                 else if ( bToBeEncrypted )
     553             :                 {
     554             :                     // this is the correct original size
     555          10 :                     pTempEntry->nSize = xSeek->getLength();
     556          10 :                     nOwnStreamOrigSize = pTempEntry->nSize;
     557             :                 }
     558             : 
     559       16284 :                 xSeek->seek ( 0 );
     560             :             }
     561             :             else
     562             :             {
     563             :                 // Okay, we don't have an xSeekable stream. This is possibly bad.
     564             :                 // check if it's one of our own streams, if it is then we know that
     565             :                 // each time we ask for it we'll get a new stream that will be
     566             :                 // at position zero...otherwise, assert and skip this stream...
     567         178 :                 if ( IsPackageMember() )
     568             :                 {
     569             :                     // if the password has been changed than the stream should not be package member any more
     570         178 :                     if ( m_bIsEncrypted && m_bToBeEncrypted )
     571             :                     {
     572             :                         // Should be handled close to the raw stream handling
     573           0 :                         bTransportOwnEncrStreamAsRaw = true;
     574           0 :                         pTempEntry->nMethod = STORED;
     575             : 
     576             :                         // TODO/LATER: get rid of this situation
     577             :                         // this size should be different from the one that will be stored in manifest.xml
     578             :                         // it is used in storing algorithms and after storing the correct size will be set
     579           0 :                         pTempEntry->nSize = pTempEntry->nCompressedSize;
     580             :                     }
     581             :                 }
     582             :                 else
     583             :                 {
     584           0 :                     bSuccess = false;
     585           0 :                     return bSuccess;
     586             :                 }
     587             :             }
     588             :         }
     589           0 :         catch ( uno::Exception& )
     590             :         {
     591           0 :             bSuccess = false;
     592           0 :             return bSuccess;
     593             :         }
     594             : 
     595       16462 :         if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw )
     596             :         {
     597          12 :             if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw )
     598             :             {
     599          20 :                 uno::Sequence < sal_Int8 > aSalt( 16 ), aVector( GetBlockSize() );
     600          10 :                 rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 );
     601          10 :                 rtl_random_getBytes ( rRandomPool, aVector.getArray(), aVector.getLength() );
     602          10 :                 sal_Int32 nIterationCount = 1024;
     603             : 
     604          10 :                 if ( !m_bHaveOwnKey )
     605             :                 {
     606          10 :                     m_aEncryptionKey = rEncryptionKey;
     607          10 :                     m_aStorageEncryptionKeys.realloc( 0 );
     608             :                 }
     609             : 
     610          10 :                 setInitialisationVector ( aVector );
     611          10 :                 setSalt ( aSalt );
     612          20 :                 setIterationCount ( nIterationCount );
     613             :             }
     614             : 
     615             :             // last property is digest, which is inserted later if we didn't have
     616             :             // a magic header
     617          12 :             aPropSet.realloc(PKG_SIZE_ENCR_MNFST);
     618             : 
     619          12 :             aPropSet[PKG_MNFST_INIVECTOR].Name = sInitialisationVectorProperty;
     620          12 :             aPropSet[PKG_MNFST_INIVECTOR].Value <<= m_xBaseEncryptionData->m_aInitVector;
     621          12 :             aPropSet[PKG_MNFST_SALT].Name = sSaltProperty;
     622          12 :             aPropSet[PKG_MNFST_SALT].Value <<= m_xBaseEncryptionData->m_aSalt;
     623          12 :             aPropSet[PKG_MNFST_ITERATION].Name = sIterationCountProperty;
     624          12 :             aPropSet[PKG_MNFST_ITERATION].Value <<= m_xBaseEncryptionData->m_nIterationCount;
     625             : 
     626             :             // Need to store the uncompressed size in the manifest
     627             :             OSL_ENSURE( nOwnStreamOrigSize >= 0, "The stream size was not correctly initialized!\n" );
     628          12 :             aPropSet[PKG_MNFST_UCOMPSIZE].Name = sSizeProperty;
     629          12 :             aPropSet[PKG_MNFST_UCOMPSIZE].Value <<= nOwnStreamOrigSize;
     630             : 
     631          12 :             if ( bRawStream || bTransportOwnEncrStreamAsRaw )
     632             :             {
     633           2 :                 ::rtl::Reference< EncryptionData > xEncData = GetEncryptionData();
     634           2 :                 if ( !xEncData.is() )
     635           0 :                     throw uno::RuntimeException();
     636             : 
     637           2 :                 aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty;
     638           2 :                 aPropSet[PKG_MNFST_DIGEST].Value <<= m_xBaseEncryptionData->m_aDigest;
     639           2 :                 aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty;
     640           2 :                 aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg;
     641           2 :                 aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty;
     642           2 :                 aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID;
     643           2 :                 aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty;
     644           2 :                 aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg;
     645           2 :                 aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty;
     646           2 :                 aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize;
     647             :             }
     648       16462 :         }
     649             :     }
     650             : 
     651             :     // If the entry is already stored in the zip file in the format we
     652             :     // want for this write...copy it raw
     653       32988 :     if ( !bUseNonSeekableAccess
     654       16674 :       && ( bRawStream || bTransportOwnEncrStreamAsRaw
     655       16460 :         || ( IsPackageMember() && !bToBeEncrypted
     656         178 :           && ( ( aEntry.nMethod == DEFLATED && bToBeCompressed )
     657          60 :             || ( aEntry.nMethod == STORED && !bToBeCompressed ) ) ) ) )
     658             :     {
     659             :         // If it's a PackageMember, then it's an unbuffered stream and we need
     660             :         // to get a new version of it as we can't seek backwards.
     661         180 :         if ( IsPackageMember() )
     662             :         {
     663         178 :             xStream = getRawData();
     664         178 :             if ( !xStream.is() )
     665             :             {
     666             :                 // Make sure that we actually _got_ a new one !
     667           0 :                 bSuccess = false;
     668           0 :                 return bSuccess;
     669             :             }
     670             :         }
     671             : 
     672             :         try
     673             :         {
     674         180 :             if ( bRawStream )
     675           2 :                 xStream->skipBytes( m_nMagicalHackPos );
     676             : 
     677         180 :             ZipOutputEntry aZipEntry(m_xContext, rZipOut.getChucker(), *pTempEntry, this, false);
     678             :             // the entry is provided to the ZipOutputStream that will delete it
     679         180 :             pAutoTempEntry.release();
     680             : 
     681         360 :             uno::Sequence < sal_Int8 > aSeq ( n_ConstBufferSize );
     682             :             sal_Int32 nLength;
     683             : 
     684         188 :             do
     685             :             {
     686         188 :                 nLength = xStream->readBytes( aSeq, n_ConstBufferSize );
     687         188 :                 aZipEntry.rawWrite(aSeq, 0, nLength);
     688             :             }
     689             :             while ( nLength == n_ConstBufferSize );
     690             : 
     691         180 :             aZipEntry.rawCloseEntry();
     692         360 :             rZipOut.addEntry(pTempEntry);
     693             :         }
     694           0 :         catch ( ZipException& )
     695             :         {
     696           0 :             bSuccess = false;
     697             :         }
     698           0 :         catch ( io::IOException& )
     699             :         {
     700           0 :             bSuccess = false;
     701             :         }
     702             :     }
     703             :     else
     704             :     {
     705             :         // This stream is defenitly not a raw stream
     706             : 
     707             :         // If nonseekable access is used the stream should be at the beginning and
     708             :         // is useless after the storing. Thus if the storing fails the package should
     709             :         // be thrown away ( as actually it is done currently )!
     710             :         // To allow to reuse the package after the error, the optimization must be removed!
     711             : 
     712             :         // If it's a PackageMember, then our previous reference held a 'raw' stream
     713             :         // so we need to re-get it, unencrypted, uncompressed and positioned at the
     714             :         // beginning of the stream
     715       16314 :         if ( IsPackageMember() )
     716             :         {
     717           0 :             xStream = getInputStream();
     718           0 :             if ( !xStream.is() )
     719             :             {
     720             :                 // Make sure that we actually _got_ a new one !
     721           0 :                 bSuccess = false;
     722           0 :                 return bSuccess;
     723             :             }
     724             :         }
     725             : 
     726       16314 :         if ( bToBeCompressed )
     727             :         {
     728       16210 :             pTempEntry->nMethod = DEFLATED;
     729       16210 :             pTempEntry->nCrc = -1;
     730       16210 :             pTempEntry->nCompressedSize = pTempEntry->nSize = -1;
     731             :         }
     732             : 
     733             :         try
     734             :         {
     735       16314 :             ZipOutputEntry aZipEntry(m_xContext, rZipOut.getChucker(), *pTempEntry, this, bToBeEncrypted);
     736             :             // the entry is provided to the ZipOutputStream that will delete it
     737       16314 :             pAutoTempEntry.release();
     738             : 
     739             :             sal_Int32 nLength;
     740       32628 :             uno::Sequence < sal_Int8 > aSeq (n_ConstBufferSize);
     741       17118 :             do
     742             :             {
     743       17118 :                 nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
     744       17118 :                 aZipEntry.write(aSeq, 0, nLength);
     745             :             }
     746             :             while ( nLength == n_ConstBufferSize );
     747             : 
     748       16314 :             aZipEntry.closeEntry();
     749       32628 :             rZipOut.addEntry(pTempEntry);
     750             :         }
     751           0 :         catch ( ZipException& )
     752             :         {
     753           0 :             bSuccess = false;
     754             :         }
     755           0 :         catch ( io::IOException& )
     756             :         {
     757           0 :             bSuccess = false;
     758             :         }
     759             : 
     760       16314 :         if ( bToBeEncrypted )
     761             :         {
     762          10 :             ::rtl::Reference< EncryptionData > xEncData = GetEncryptionData();
     763          10 :             if ( !xEncData.is() )
     764           0 :                 throw uno::RuntimeException();
     765             : 
     766          10 :             aPropSet[PKG_MNFST_DIGEST].Name = sDigestProperty;
     767          10 :             aPropSet[PKG_MNFST_DIGEST].Value <<= m_xBaseEncryptionData->m_aDigest;
     768          10 :             aPropSet[PKG_MNFST_ENCALG].Name = sEncryptionAlgProperty;
     769          10 :             aPropSet[PKG_MNFST_ENCALG].Value <<= xEncData->m_nEncAlg;
     770          10 :             aPropSet[PKG_MNFST_STARTALG].Name = sStartKeyAlgProperty;
     771          10 :             aPropSet[PKG_MNFST_STARTALG].Value <<= xEncData->m_nStartKeyGenID;
     772          10 :             aPropSet[PKG_MNFST_DIGESTALG].Name = sDigestAlgProperty;
     773          10 :             aPropSet[PKG_MNFST_DIGESTALG].Value <<= xEncData->m_nCheckAlg;
     774          10 :             aPropSet[PKG_MNFST_DERKEYSIZE].Name = sDerivedKeySizeProperty;
     775          10 :             aPropSet[PKG_MNFST_DERKEYSIZE].Value <<= xEncData->m_nDerivedKeySize;
     776             : 
     777          10 :             SetIsEncrypted ( true );
     778             :         }
     779             :     }
     780             : 
     781       16494 :     if( bSuccess )
     782             :     {
     783       16494 :         if ( !IsPackageMember() )
     784             :         {
     785       16316 :             CloseOwnStreamIfAny();
     786       16316 :             SetPackageMember ( true );
     787             :         }
     788             : 
     789       16494 :         if ( bRawStream )
     790             :         {
     791             :             // the raw stream was integrated and now behaves
     792             :             // as usual encrypted stream
     793           2 :             SetToBeEncrypted( true );
     794             :         }
     795             : 
     796             :         // Then copy it back afterwards...
     797       16494 :         ZipPackageFolder::copyZipEntry ( aEntry, *pTempEntry );
     798             : 
     799             :         // Remove hacky bit from entry flags
     800       16494 :         if ( aEntry.nFlag & ( 1 << 4 ) )
     801             :         {
     802          10 :             aEntry.nFlag &= ~( 1 << 4 );
     803          10 :             aEntry.nMethod = STORED;
     804             :         }
     805             : 
     806             :         // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
     807       16494 :         if ( IsEncrypted() )
     808          12 :             setSize( nOwnStreamOrigSize );
     809             : 
     810       16494 :         aEntry.nOffset *= -1;
     811             :     }
     812             : 
     813       32988 :     if ( aPropSet.getLength()
     814       16494 :       && ( m_nFormat == embed::StorageFormats::PACKAGE || m_nFormat == embed::StorageFormats::OFOPXML ) )
     815       16494 :         rManList.push_back( aPropSet );
     816             : 
     817       32988 :     return bSuccess;
     818             : }
     819             : 
     820      422024 : void ZipPackageStream::SetPackageMember( bool bNewValue )
     821             : {
     822      422024 :     if ( bNewValue )
     823             :     {
     824      397394 :         m_nStreamMode = PACKAGE_STREAM_PACKAGEMEMBER;
     825      397394 :         m_nMagicalHackPos = 0;
     826      397394 :         m_nMagicalHackSize = 0;
     827             :     }
     828       24630 :     else if ( m_nStreamMode == PACKAGE_STREAM_PACKAGEMEMBER )
     829           0 :         m_nStreamMode = PACKAGE_STREAM_NOTSET; // must be reset
     830      422024 : }
     831             : 
     832             : // XActiveDataSink
     833       24628 : void SAL_CALL ZipPackageStream::setInputStream( const uno::Reference< io::XInputStream >& aStream )
     834             :         throw( RuntimeException, std::exception )
     835             : {
     836             :     // if seekable access is required the wrapping will be done on demand
     837       24628 :     m_xStream = aStream;
     838       24628 :     m_nImportedEncryptionAlgorithm = 0;
     839       24628 :     m_bHasSeekable = false;
     840       24628 :     SetPackageMember ( false );
     841       24628 :     aEntry.nTime = -1;
     842       24628 :     m_nStreamMode = PACKAGE_STREAM_DETECT;
     843       24628 : }
     844             : 
     845       16640 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawData()
     846             :         throw( RuntimeException )
     847             : {
     848             :     try
     849             :     {
     850       16640 :         if ( IsPackageMember() )
     851             :         {
     852         356 :             return m_rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
     853             :         }
     854       16284 :         else if ( GetOwnSeekStream().is() )
     855             :         {
     856       16284 :             return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() );
     857             :         }
     858             :         else
     859           0 :             return uno::Reference < io::XInputStream > ();
     860             :     }
     861           0 :     catch ( ZipException & )//rException )
     862             :     {
     863             :         OSL_FAIL( "ZipException thrown" );//rException.Message);
     864           0 :         return uno::Reference < io::XInputStream > ();
     865             :     }
     866           0 :     catch ( Exception & )
     867             :     {
     868             :         OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
     869           0 :         return uno::Reference < io::XInputStream > ();
     870             :     }
     871             : }
     872             : 
     873       11394 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getInputStream()
     874             :         throw( RuntimeException, std::exception )
     875             : {
     876             :     try
     877             :     {
     878       11394 :         if ( IsPackageMember() )
     879             :         {
     880       11394 :             return m_rZipPackage.getZipFile().getInputStream( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
     881             :         }
     882           0 :         else if ( GetOwnSeekStream().is() )
     883             :         {
     884           0 :             return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() );
     885             :         }
     886             :         else
     887           0 :             return uno::Reference < io::XInputStream > ();
     888             :     }
     889           0 :     catch ( ZipException & )//rException )
     890             :     {
     891             :         OSL_FAIL( "ZipException thrown" );//rException.Message);
     892           0 :         return uno::Reference < io::XInputStream > ();
     893             :     }
     894           0 :     catch ( Exception &ex )
     895             :     {
     896             :         OSL_FAIL( "Exception is thrown during stream wrapping!\n" );
     897             :         OSL_FAIL(OUStringToOString(ex.Message, RTL_TEXTENCODING_UTF8).getStr());
     898             :         (void)ex;
     899           0 :         return uno::Reference < io::XInputStream > ();
     900             :     }
     901             : }
     902             : 
     903             : // XDataSinkEncrSupport
     904      122372 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getDataStream()
     905             :         throw ( packages::WrongPasswordException, ZipException,
     906             :                 io::IOException,
     907             :                 RuntimeException, std::exception )
     908             : {
     909             :     // There is no stream attached to this object
     910      122372 :     if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
     911       26156 :         return uno::Reference< io::XInputStream >();
     912             : 
     913             :     // this method can not be used together with old approach
     914       96216 :     if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
     915           0 :         throw packages::zip::ZipIOException(THROW_WHERE );
     916             : 
     917       96216 :     if ( IsPackageMember() )
     918             :     {
     919       92792 :         uno::Reference< io::XInputStream > xResult;
     920             :         try
     921             :         {
     922       92792 :             xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
     923             :         }
     924           8 :         catch( const packages::WrongPasswordException& )
     925             :         {
     926           8 :             if ( m_rZipPackage.GetStartKeyGenID() == xml::crypto::DigestID::SHA1 )
     927             :             {
     928             :                 try
     929             :                 {
     930             :                     // rhbz#1013844 / fdo#47482 workaround for the encrypted
     931             :                     // OpenOffice.org 1.0 documents generated by Libreoffice <=
     932             :                     // 3.6 with the new encryption format and using SHA256, but
     933             :                     // missing a specified startkey of SHA256
     934             : 
     935             :                     // force SHA256 and see if that works
     936           8 :                     m_nImportedStartKeyAlgorithm = xml::crypto::DigestID::SHA256;
     937           8 :                     xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
     938           8 :                     return xResult;
     939             :                 }
     940           0 :                 catch (const packages::WrongPasswordException&)
     941             :                 {
     942             :                     // if that didn't work, restore to SHA1 and trundle through the *other* earlier
     943             :                     // bug fix
     944           0 :                     m_nImportedStartKeyAlgorithm = xml::crypto::DigestID::SHA1;
     945             :                 }
     946             : 
     947             :                 // workaround for the encrypted documents generated with the old OOo1.x bug.
     948           0 :                 if ( !m_bUseWinEncoding )
     949             :                 {
     950           0 :                     xResult = m_rZipPackage.getZipFile().getDataStream( aEntry, GetEncryptionData( true ), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
     951           0 :                     m_bUseWinEncoding = true;
     952             :                 }
     953             :                 else
     954           0 :                     throw;
     955             :             }
     956             :             else
     957           0 :                 throw;
     958           0 :         }
     959       92784 :         return xResult;
     960             :     }
     961        3424 :     else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
     962           0 :         return ZipFile::StaticGetDataFromRawStream( m_xContext, GetOwnSeekStream(), GetEncryptionData() );
     963        3424 :     else if ( GetOwnSeekStream().is() )
     964             :     {
     965        3424 :         return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() );
     966             :     }
     967             :     else
     968           0 :         return uno::Reference< io::XInputStream >();
     969             : }
     970             : 
     971           2 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getRawStream()
     972             :         throw ( packages::NoEncryptionException,
     973             :                 io::IOException,
     974             :                 uno::RuntimeException, std::exception )
     975             : {
     976             :     // There is no stream attached to this object
     977           2 :     if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
     978           0 :         return uno::Reference< io::XInputStream >();
     979             : 
     980             :     // this method can not be used together with old approach
     981           2 :     if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
     982           0 :         throw packages::zip::ZipIOException(THROW_WHERE );
     983             : 
     984           2 :     if ( IsPackageMember() )
     985             :     {
     986           2 :         if ( !m_bIsEncrypted || !GetEncryptionData().is() )
     987           0 :             throw packages::NoEncryptionException(THROW_WHERE );
     988             : 
     989           2 :         return m_rZipPackage.getZipFile().getWrappedRawStream( aEntry, GetEncryptionData(), msMediaType, m_rZipPackage.GetSharedMutexRef() );
     990             :     }
     991           0 :     else if ( GetOwnSeekStream().is() )
     992             :     {
     993           0 :         if ( m_nStreamMode == PACKAGE_STREAM_RAW )
     994             :         {
     995           0 :             return new WrapStreamForShare( GetOwnSeekStream(), m_rZipPackage.GetSharedMutexRef() );
     996             :         }
     997           0 :         else if ( m_nStreamMode == PACKAGE_STREAM_DATA && m_bToBeEncrypted )
     998           0 :             return TryToGetRawFromDataStream( true );
     999             :     }
    1000             : 
    1001           0 :     throw packages::NoEncryptionException(THROW_WHERE );
    1002             : }
    1003             : 
    1004       24628 : void SAL_CALL ZipPackageStream::setDataStream( const uno::Reference< io::XInputStream >& aStream )
    1005             :         throw ( io::IOException,
    1006             :                 RuntimeException, std::exception )
    1007             : {
    1008       24628 :     setInputStream( aStream );
    1009       24628 :     m_nStreamMode = PACKAGE_STREAM_DATA;
    1010       24628 : }
    1011             : 
    1012           2 : void SAL_CALL ZipPackageStream::setRawStream( const uno::Reference< io::XInputStream >& aStream )
    1013             :         throw ( packages::EncryptionNotAllowedException,
    1014             :                 packages::NoRawFormatException,
    1015             :                 io::IOException,
    1016             :                 RuntimeException, std::exception )
    1017             : {
    1018             :     // wrap the stream in case it is not seekable
    1019           2 :     uno::Reference< io::XInputStream > xNewStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( aStream, m_xContext );
    1020           4 :     uno::Reference< io::XSeekable > xSeek( xNewStream, UNO_QUERY );
    1021           2 :     if ( !xSeek.is() )
    1022           0 :         throw RuntimeException(THROW_WHERE "The stream must support XSeekable!" );
    1023             : 
    1024           2 :     xSeek->seek( 0 );
    1025           4 :     uno::Reference< io::XInputStream > xOldStream = m_xStream;
    1026           2 :     m_xStream = xNewStream;
    1027           2 :     if ( !ParsePackageRawStream() )
    1028             :     {
    1029           0 :         m_xStream = xOldStream;
    1030           0 :         throw packages::NoRawFormatException(THROW_WHERE );
    1031             :     }
    1032             : 
    1033             :     // the raw stream MUST have seekable access
    1034           2 :     m_bHasSeekable = true;
    1035             : 
    1036           2 :     SetPackageMember ( false );
    1037           2 :     aEntry.nTime = -1;
    1038           4 :     m_nStreamMode = PACKAGE_STREAM_RAW;
    1039           2 : }
    1040             : 
    1041           0 : uno::Reference< io::XInputStream > SAL_CALL ZipPackageStream::getPlainRawStream()
    1042             :         throw ( io::IOException, packages::NoEncryptionException,
    1043             :                 uno::RuntimeException, std::exception )
    1044             : {
    1045             :     // There is no stream attached to this object
    1046           0 :     if ( m_nStreamMode == PACKAGE_STREAM_NOTSET )
    1047           0 :         return uno::Reference< io::XInputStream >();
    1048             : 
    1049             :     // this method can not be used together with old approach
    1050           0 :     if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
    1051           0 :         throw packages::zip::ZipIOException(THROW_WHERE );
    1052             : 
    1053           0 :     if ( IsPackageMember() )
    1054             :     {
    1055           0 :         return m_rZipPackage.getZipFile().getRawData( aEntry, GetEncryptionData(), m_bIsEncrypted, m_rZipPackage.GetSharedMutexRef() );
    1056             :     }
    1057           0 :     else if ( GetOwnSeekStream().is() )
    1058             :     {
    1059           0 :         if ( m_nStreamMode == PACKAGE_STREAM_RAW )
    1060             :         {
    1061             :             // the header should not be returned here
    1062           0 :             return GetRawEncrStreamNoHeaderCopy();
    1063             :         }
    1064           0 :         else if ( m_nStreamMode == PACKAGE_STREAM_DATA )
    1065           0 :             return TryToGetRawFromDataStream( false );
    1066             :     }
    1067             : 
    1068           0 :     return uno::Reference< io::XInputStream >();
    1069             : }
    1070             : 
    1071             : // XUnoTunnel
    1072             : 
    1073      179030 : sal_Int64 SAL_CALL ZipPackageStream::getSomething( const Sequence< sal_Int8 >& aIdentifier )
    1074             :     throw( RuntimeException, std::exception )
    1075             : {
    1076      179030 :     sal_Int64 nMe = 0;
    1077      716120 :     if ( aIdentifier.getLength() == 16 &&
    1078      716120 :          0 == memcmp( static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) )
    1079      148424 :         nMe = reinterpret_cast < sal_Int64 > ( this );
    1080      179030 :     return nMe;
    1081             : }
    1082             : 
    1083             : // XPropertySet
    1084       84132 : void SAL_CALL ZipPackageStream::setPropertyValue( const OUString& aPropertyName, const Any& aValue )
    1085             :         throw( beans::UnknownPropertyException, beans::PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException, std::exception )
    1086             : {
    1087       84132 :     if ( aPropertyName == "MediaType" )
    1088             :     {
    1089       26584 :         if ( m_rZipPackage.getFormat() != embed::StorageFormats::PACKAGE && m_rZipPackage.getFormat() != embed::StorageFormats::OFOPXML )
    1090           0 :             throw beans::PropertyVetoException(THROW_WHERE );
    1091             : 
    1092       26584 :         if ( aValue >>= msMediaType )
    1093             :         {
    1094       26584 :             if ( !msMediaType.isEmpty() )
    1095             :             {
    1096       46204 :                 if ( msMediaType.indexOf ( "text" ) != -1
    1097       23102 :                  || msMediaType == "application/vnd.sun.star.oleobject" )
    1098        5062 :                     m_bToBeCompressed = true;
    1099       18040 :                 else if ( !m_bCompressedIsSetFromOutside )
    1100       16266 :                     m_bToBeCompressed = false;
    1101             :             }
    1102             :         }
    1103             :         else
    1104             :             throw IllegalArgumentException(THROW_WHERE "MediaType must be a string!",
    1105             :                                             uno::Reference< XInterface >(),
    1106           0 :                                             2 );
    1107             : 
    1108             :     }
    1109       57548 :     else if ( aPropertyName == "Size" )
    1110             :     {
    1111           0 :         if ( !( aValue >>= aEntry.nSize ) )
    1112             :             throw IllegalArgumentException(THROW_WHERE "Wrong type for Size property!",
    1113             :                                             uno::Reference< XInterface >(),
    1114           0 :                                             2 );
    1115             :     }
    1116       57548 :     else if ( aPropertyName == "Encrypted" )
    1117             :     {
    1118       20610 :         if ( m_rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
    1119           0 :             throw beans::PropertyVetoException(THROW_WHERE );
    1120             : 
    1121       20610 :         bool bEnc = false;
    1122       20610 :         if ( aValue >>= bEnc )
    1123             :         {
    1124             :             // In case of new raw stream, the stream must not be encrypted on storing
    1125       20610 :             if ( bEnc && m_nStreamMode == PACKAGE_STREAM_RAW )
    1126             :                 throw IllegalArgumentException(THROW_WHERE "Raw stream can not be encrypted on storing",
    1127             :                                                 uno::Reference< XInterface >(),
    1128           0 :                                                 2 );
    1129             : 
    1130       20610 :             m_bToBeEncrypted = bEnc;
    1131       20610 :             if ( m_bToBeEncrypted && !m_xBaseEncryptionData.is() )
    1132        9598 :                 m_xBaseEncryptionData = new BaseEncryptionData;
    1133             :         }
    1134             :         else
    1135             :             throw IllegalArgumentException(THROW_WHERE "Wrong type for Encrypted property!",
    1136             :                                             uno::Reference< XInterface >(),
    1137           0 :                                             2 );
    1138             : 
    1139             :     }
    1140       36938 :     else if ( aPropertyName == ENCRYPTION_KEY_PROPERTY )
    1141             :     {
    1142           0 :         if ( m_rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
    1143           0 :             throw beans::PropertyVetoException(THROW_WHERE );
    1144             : 
    1145           0 :         uno::Sequence< sal_Int8 > aNewKey;
    1146             : 
    1147           0 :         if ( !( aValue >>= aNewKey ) )
    1148             :         {
    1149           0 :             OUString sTempString;
    1150           0 :             if ( ( aValue >>= sTempString ) )
    1151             :             {
    1152           0 :                 sal_Int32 nPathLength = sTempString.getLength();
    1153           0 :                 Sequence < sal_Int8 > aSequence ( nPathLength );
    1154           0 :                 sal_Int8 *pArray = aSequence.getArray();
    1155           0 :                 const sal_Unicode *pChar = sTempString.getStr();
    1156           0 :                 for ( sal_Int16 i = 0; i < nPathLength; i++ )
    1157           0 :                     pArray[i] = static_cast < const sal_Int8 > ( pChar[i] );
    1158           0 :                 aNewKey = aSequence;
    1159             :             }
    1160             :             else
    1161             :                 throw IllegalArgumentException(THROW_WHERE "Wrong type for EncryptionKey property!",
    1162             :                                                 uno::Reference< XInterface >(),
    1163           0 :                                                 2 );
    1164             :         }
    1165             : 
    1166           0 :         if ( aNewKey.getLength() )
    1167             :         {
    1168           0 :             if ( !m_xBaseEncryptionData.is() )
    1169           0 :                 m_xBaseEncryptionData = new BaseEncryptionData;
    1170             : 
    1171           0 :             m_aEncryptionKey = aNewKey;
    1172             :             // In case of new raw stream, the stream must not be encrypted on storing
    1173           0 :             m_bHaveOwnKey = true;
    1174           0 :             if ( m_nStreamMode != PACKAGE_STREAM_RAW )
    1175           0 :                 m_bToBeEncrypted = true;
    1176             :         }
    1177             :         else
    1178             :         {
    1179           0 :             m_bHaveOwnKey = false;
    1180           0 :             m_aEncryptionKey.realloc( 0 );
    1181             :         }
    1182             : 
    1183           0 :         m_aStorageEncryptionKeys.realloc( 0 );
    1184             :     }
    1185       36938 :     else if ( aPropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
    1186             :     {
    1187       10354 :         if ( m_rZipPackage.getFormat() != embed::StorageFormats::PACKAGE )
    1188           0 :             throw beans::PropertyVetoException(THROW_WHERE );
    1189             : 
    1190       10354 :         uno::Sequence< beans::NamedValue > aKeys;
    1191       10354 :         if ( !( aValue >>= aKeys ) )
    1192             :         {
    1193             :                 throw IllegalArgumentException(THROW_WHERE "Wrong type for StorageEncryptionKeys property!",
    1194             :                                                 uno::Reference< XInterface >(),
    1195           0 :                                                 2 );
    1196             :         }
    1197             : 
    1198       10354 :         if ( aKeys.getLength() )
    1199             :         {
    1200          36 :             if ( !m_xBaseEncryptionData.is() )
    1201           0 :                 m_xBaseEncryptionData = new BaseEncryptionData;
    1202             : 
    1203          36 :             m_aStorageEncryptionKeys = aKeys;
    1204             : 
    1205             :             // In case of new raw stream, the stream must not be encrypted on storing
    1206          36 :             m_bHaveOwnKey = true;
    1207          36 :             if ( m_nStreamMode != PACKAGE_STREAM_RAW )
    1208          36 :                 m_bToBeEncrypted = true;
    1209             :         }
    1210             :         else
    1211             :         {
    1212       10318 :             m_bHaveOwnKey = false;
    1213       10318 :             m_aStorageEncryptionKeys.realloc( 0 );
    1214             :         }
    1215             : 
    1216       10354 :         m_aEncryptionKey.realloc( 0 );
    1217             :     }
    1218       26584 :     else if ( aPropertyName == "Compressed" )
    1219             :     {
    1220       26584 :         bool bCompr = false;
    1221             : 
    1222       26584 :         if ( aValue >>= bCompr )
    1223             :         {
    1224             :             // In case of new raw stream, the stream must not be encrypted on storing
    1225       26584 :             if ( bCompr && m_nStreamMode == PACKAGE_STREAM_RAW )
    1226             :                 throw IllegalArgumentException(THROW_WHERE "Raw stream can not be encrypted on storing",
    1227             :                                                 uno::Reference< XInterface >(),
    1228           0 :                                                 2 );
    1229             : 
    1230       26584 :             m_bToBeCompressed = bCompr;
    1231       26584 :             m_bCompressedIsSetFromOutside = true;
    1232             :         }
    1233             :         else
    1234             :             throw IllegalArgumentException(THROW_WHERE "Wrong type for Compressed property!",
    1235             :                                             uno::Reference< XInterface >(),
    1236           0 :                                             2 );
    1237             :     }
    1238             :     else
    1239           0 :         throw beans::UnknownPropertyException(THROW_WHERE );
    1240       84132 : }
    1241             : 
    1242      279276 : Any SAL_CALL ZipPackageStream::getPropertyValue( const OUString& PropertyName )
    1243             :         throw( beans::UnknownPropertyException, WrappedTargetException, RuntimeException, std::exception )
    1244             : {
    1245      279276 :     Any aAny;
    1246      279276 :     if ( PropertyName == "MediaType" )
    1247             :     {
    1248       74732 :         aAny <<= msMediaType;
    1249       74732 :         return aAny;
    1250             :     }
    1251      204544 :     else if ( PropertyName == "Size" )
    1252             :     {
    1253       89478 :         aAny <<= aEntry.nSize;
    1254       89478 :         return aAny;
    1255             :     }
    1256      115066 :     else if ( PropertyName == "Encrypted" )
    1257             :     {
    1258       11318 :         aAny <<= ((m_nStreamMode == PACKAGE_STREAM_RAW) || m_bToBeEncrypted);
    1259       11318 :         return aAny;
    1260             :     }
    1261      103748 :     else if ( PropertyName == "WasEncrypted" )
    1262             :     {
    1263       14156 :         aAny <<= m_bIsEncrypted;
    1264       14156 :         return aAny;
    1265             :     }
    1266       89592 :     else if ( PropertyName == "Compressed" )
    1267             :     {
    1268       89476 :         aAny <<= m_bToBeCompressed;
    1269       89476 :         return aAny;
    1270             :     }
    1271         116 :     else if ( PropertyName == ENCRYPTION_KEY_PROPERTY )
    1272             :     {
    1273           0 :         aAny <<= m_aEncryptionKey;
    1274           0 :         return aAny;
    1275             :     }
    1276         116 :     else if ( PropertyName == STORAGE_ENCRYPTION_KEYS_PROPERTY )
    1277             :     {
    1278         116 :         aAny <<= m_aStorageEncryptionKeys;
    1279         116 :         return aAny;
    1280             :     }
    1281             :     else
    1282           0 :         throw beans::UnknownPropertyException(THROW_WHERE );
    1283             : }
    1284             : 
    1285          62 : void ZipPackageStream::setSize ( const sal_Int64 nNewSize )
    1286             : {
    1287          62 :     if ( aEntry.nCompressedSize != nNewSize )
    1288          62 :         aEntry.nMethod = DEFLATED;
    1289          62 :     aEntry.nSize = nNewSize;
    1290          62 : }
    1291           0 : OUString ZipPackageStream::getImplementationName()
    1292             :     throw ( RuntimeException, std::exception )
    1293             : {
    1294           0 :     return OUString ("ZipPackageStream");
    1295             : }
    1296             : 
    1297           0 : Sequence< OUString > ZipPackageStream::getSupportedServiceNames()
    1298             :     throw ( RuntimeException, std::exception )
    1299             : {
    1300           0 :     Sequence< OUString > aNames( 1 );
    1301           0 :     aNames[0] = "com.sun.star.packages.PackageStream";
    1302           0 :     return aNames;
    1303             : }
    1304             : 
    1305           0 : sal_Bool SAL_CALL ZipPackageStream::supportsService( OUString const & rServiceName )
    1306             :     throw ( RuntimeException, std::exception )
    1307             : {
    1308           0 :     return cppu::supportsService(this, rServiceName);
    1309             : }
    1310             : 
    1311             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10