diff options
Diffstat (limited to 'package/source/zippackage/ZipPackage.cxx')
-rw-r--r-- | package/source/zippackage/ZipPackage.cxx | 1890 |
1 files changed, 0 insertions, 1890 deletions
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx deleted file mode 100644 index b3eb2fc47..000000000 --- a/package/source/zippackage/ZipPackage.cxx +++ /dev/null @@ -1,1890 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ -/************************************************************************* - * - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * Copyright 2000, 2010 Oracle and/or its affiliates. - * - * OpenOffice.org - a multi-platform office productivity suite - * - * This file is part of OpenOffice.org. - * - * OpenOffice.org is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License version 3 - * only, as published by the Free Software Foundation. - * - * OpenOffice.org is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License version 3 for more details - * ( a copy is included in the LICENSE file that accompanied this code ). - * - * You should have received a copy of the GNU Lesser General Public License - * version 3 along with OpenOffice.org. If not, see - * <http://www.openoffice.org/license.html> - * for a copy of the LGPLv3 License. - * - ************************************************************************/ - -// MARKER( update_precomp.py ): autogen include statement, do not remove -#include "precompiled_package.hxx" -#include <ZipPackage.hxx> -#include <ZipPackageSink.hxx> -#include <ZipEnumeration.hxx> -#include <ZipPackageStream.hxx> -#include <ZipPackageFolder.hxx> -#include <ZipOutputStream.hxx> -#include <ZipPackageBuffer.hxx> -#include <ZipFile.hxx> -#include <PackageConstants.hxx> -#include <com/sun/star/beans/PropertyValue.hpp> -#include <com/sun/star/packages/zip/ZipConstants.hpp> -#include <com/sun/star/packages/manifest/XManifestReader.hpp> -#include <com/sun/star/packages/manifest/XManifestWriter.hpp> -#include <com/sun/star/io/XStream.hpp> -#include <com/sun/star/io/XInputStream.hpp> -#include <com/sun/star/io/XOutputStream.hpp> -#include <com/sun/star/io/XTruncate.hpp> -#include <com/sun/star/io/XSeekable.hpp> -#include <com/sun/star/lang/XMultiServiceFactory.hpp> -#include <com/sun/star/container/XNameContainer.hpp> -#include <com/sun/star/ucb/IOErrorCode.hpp> -#include <ucbhelper/content.hxx> -#include <cppuhelper/factory.hxx> -#include <cppuhelper/exc_hlp.hxx> -#include <com/sun/star/ucb/TransferInfo.hpp> -#include <com/sun/star/ucb/NameClash.hpp> -#include <com/sun/star/ucb/OpenCommandArgument2.hpp> -#include <com/sun/star/ucb/OpenMode.hpp> -#include <com/sun/star/ucb/XProgressHandler.hpp> -#include <com/sun/star/ucb/XSimpleFileAccess.hpp> -#include <com/sun/star/io/XActiveDataStreamer.hpp> -#include <com/sun/star/embed/XTransactedObject.hpp> -#include <com/sun/star/embed/UseBackupException.hpp> -#include <com/sun/star/embed/StorageFormats.hpp> -#include <com/sun/star/beans/NamedValue.hpp> -#include <com/sun/star/xml/crypto/DigestID.hpp> -#include <com/sun/star/xml/crypto/CipherID.hpp> -#include <cppuhelper/implbase1.hxx> -#include <ContentInfo.hxx> -#include <cppuhelper/typeprovider.hxx> -#include <rtl/uri.hxx> -#include <rtl/random.h> -#include <rtl/logfile.hxx> -#include <rtl/instance.hxx> -#include <osl/time.h> -#include <osl/file.hxx> -#include "com/sun/star/io/XAsyncOutputMonitor.hpp" - -#include <memory> -#include <vector> - -#include <ucbhelper/contentbroker.hxx> -#include <ucbhelper/fileidentifierconverter.hxx> -#include <comphelper/seekableinput.hxx> -#include <comphelper/storagehelper.hxx> -#include <comphelper/ofopxmlhelper.hxx> -#include <comphelper/documentconstants.hxx> -#include <comphelper/sequenceashashmap.hxx> - -using namespace std; -using namespace osl; -using namespace cppu; -using namespace ucbhelper; -using namespace com::sun::star; -using namespace com::sun::star::io; -using namespace com::sun::star::uno; -using namespace com::sun::star::ucb; -using namespace com::sun::star::util; -using namespace com::sun::star::lang; -using namespace com::sun::star::task; -using namespace com::sun::star::beans; -using namespace com::sun::star::packages; -using namespace com::sun::star::container; -using namespace com::sun::star::packages::zip; -using namespace com::sun::star::packages::manifest; -using namespace com::sun::star::packages::zip::ZipConstants; - -using ::rtl::OUString; -using ::rtl::OString; - -#define LOGFILE_AUTHOR "mg115289" - - -namespace { - -sal_Bool isLocalFile_Impl( ::rtl::OUString aURL ) -{ - ::rtl::OUString aSystemPath; - ContentBroker* pBroker = ContentBroker::get(); - if ( !pBroker ) - { - ::rtl::OUString aRet; - if ( FileBase::getSystemPathFromFileURL( aURL, aRet ) == FileBase::E_None ) - aSystemPath = aRet; - } - else - { - uno::Reference< XContentProviderManager > xManager = - pBroker->getContentProviderManagerInterface(); - try - { - aSystemPath = getSystemPathFromFileURL( xManager, aURL ); - } - catch ( Exception& ) - { - } - } - - return ( aSystemPath.getLength() != 0 ); -} - -} - -//=========================================================================== - -class ActiveDataStreamer : public ::cppu::WeakImplHelper1< XActiveDataStreamer > -{ - uno::Reference< XStream > mStream; -public: - - virtual uno::Reference< XStream > SAL_CALL getStream() - throw( RuntimeException ) - { return mStream; } - - virtual void SAL_CALL setStream( const uno::Reference< XStream >& stream ) - throw( RuntimeException ) - { mStream = stream; } -}; - -class DummyInputStream : public ::cppu::WeakImplHelper1< XInputStream > -{ - virtual sal_Int32 SAL_CALL readBytes( uno::Sequence< sal_Int8 >&, sal_Int32 ) - throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) - { return 0; } - - virtual sal_Int32 SAL_CALL readSomeBytes( uno::Sequence< sal_Int8 >&, sal_Int32 ) - throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) - { return 0; } - - virtual void SAL_CALL skipBytes( sal_Int32 ) - throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) - {} - - virtual sal_Int32 SAL_CALL available() - throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) - { return 0; } - - virtual void SAL_CALL closeInput() - throw ( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException ) - {} -}; - -//=========================================================================== - -ZipPackage::ZipPackage ( const uno::Reference < XMultiServiceFactory > &xNewFactory ) -: m_aMutexHolder( new SotMutexHolder ) -, m_nStartKeyGenerationID( xml::crypto::DigestID::SHA1 ) -, m_nChecksumDigestID( xml::crypto::DigestID::SHA1_1K ) -, m_nCommonEncryptionID( xml::crypto::CipherID::BLOWFISH_CFB_8 ) -, m_bHasEncryptedEntries ( sal_False ) -, m_bHasNonEncryptedEntries ( sal_False ) -, m_bInconsistent ( sal_False ) -, m_bForceRecovery ( sal_False ) -, m_bMediaTypeFallbackUsed ( sal_False ) -, m_nFormat( embed::StorageFormats::PACKAGE ) // package is the default format -, m_bAllowRemoveOnInsert( sal_True ) -, m_eMode ( e_IMode_None ) -, m_xFactory( xNewFactory ) -, m_pRootFolder( NULL ) -, m_pZipFile( NULL ) -{ - m_xRootFolder = m_pRootFolder = new ZipPackageFolder( m_xFactory, m_nFormat, m_bAllowRemoveOnInsert ); -} - -ZipPackage::~ZipPackage( void ) -{ - delete m_pZipFile; - - // All folders and streams contain pointers to their parents, when a parent diappeares - // it should disconnect all the children from itself during destruction automatically. - // So there is no need in explicit m_pRootFolder->releaseUpwardRef() call here any more - // since m_pRootFolder has no parent and cleaning of it's children will be done automatically - // during m_pRootFolder dieing by refcount. -} - -//-------------------------------------------------------- -void ZipPackage::parseManifest() -{ - if ( m_nFormat == embed::StorageFormats::PACKAGE ) - { - sal_Bool bManifestParsed = sal_False; - bool bDifferentStartKeyAlgorithm = false; - const OUString sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) ); - if ( m_xRootFolder->hasByName( sMeta ) ) - { - const OUString sManifest ( RTL_CONSTASCII_USTRINGPARAM( "manifest.xml" ) ); - - try { - uno::Reference< XUnoTunnel > xTunnel; - Any aAny = m_xRootFolder->getByName( sMeta ); - aAny >>= xTunnel; - uno::Reference< XNameContainer > xMetaInfFolder( xTunnel, UNO_QUERY ); - if ( xMetaInfFolder.is() && xMetaInfFolder->hasByName( sManifest ) ) - { - aAny = xMetaInfFolder->getByName( sManifest ); - aAny >>= xTunnel; - uno::Reference < XActiveDataSink > xSink ( xTunnel, UNO_QUERY ); - if ( xSink.is() ) - { - OUString sManifestReader ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.manifest.ManifestReader" ) ); - uno::Reference < XManifestReader > xReader ( m_xFactory->createInstance( sManifestReader ), UNO_QUERY ); - if ( xReader.is() ) - { - const OUString sPropFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); - const OUString sPropVersion ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ); - const OUString sPropMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); - const OUString sPropInitialisationVector ( RTL_CONSTASCII_USTRINGPARAM ( "InitialisationVector" ) ); - const OUString sPropSalt ( RTL_CONSTASCII_USTRINGPARAM ( "Salt" ) ); - const OUString sPropIterationCount ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) ); - const OUString sPropSize ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ); - const OUString sPropDigest ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ); - const OUString sPropDerivedKeySize ( RTL_CONSTASCII_USTRINGPARAM ( "DerivedKeySize" ) ); - const OUString sPropDigestAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "DigestAlgorithm" ) ); - const OUString sPropEncryptionAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "EncryptionAlgorithm" ) ); - const OUString sPropStartKeyAlgorithm ( RTL_CONSTASCII_USTRINGPARAM ( "StartKeyAlgorithm" ) ); - - uno::Sequence < uno::Sequence < PropertyValue > > aManifestSequence = xReader->readManifestSequence ( xSink->getInputStream() ); - sal_Int32 nLength = aManifestSequence.getLength(); - const uno::Sequence < PropertyValue > *pSequence = aManifestSequence.getConstArray(); - ZipPackageStream *pStream = NULL; - ZipPackageFolder *pFolder = NULL; - - for ( sal_Int32 i = 0; i < nLength ; i++, pSequence++ ) - { - OUString sPath, sMediaType, sVersion; - const PropertyValue *pValue = pSequence->getConstArray(); - const Any *pSalt = NULL, *pVector = NULL, *pCount = NULL, *pSize = NULL, *pDigest = NULL, *pDigestAlg = NULL, *pEncryptionAlg = NULL, *pStartKeyAlg = NULL, *pDerivedKeySize = NULL; - for ( sal_Int32 j = 0, nNum = pSequence->getLength(); j < nNum; j++ ) - { - if ( pValue[j].Name.equals( sPropFullPath ) ) - pValue[j].Value >>= sPath; - else if ( pValue[j].Name.equals( sPropVersion ) ) - pValue[j].Value >>= sVersion; - else if ( pValue[j].Name.equals( sPropMediaType ) ) - pValue[j].Value >>= sMediaType; - else if ( pValue[j].Name.equals( sPropSalt ) ) - pSalt = &( pValue[j].Value ); - else if ( pValue[j].Name.equals( sPropInitialisationVector ) ) - pVector = &( pValue[j].Value ); - else if ( pValue[j].Name.equals( sPropIterationCount ) ) - pCount = &( pValue[j].Value ); - else if ( pValue[j].Name.equals( sPropSize ) ) - pSize = &( pValue[j].Value ); - else if ( pValue[j].Name.equals( sPropDigest ) ) - pDigest = &( pValue[j].Value ); - else if ( pValue[j].Name.equals( sPropDigestAlgorithm ) ) - pDigestAlg = &( pValue[j].Value ); - else if ( pValue[j].Name.equals( sPropEncryptionAlgorithm ) ) - pEncryptionAlg = &( pValue[j].Value ); - else if ( pValue[j].Name.equals( sPropStartKeyAlgorithm ) ) - pStartKeyAlg = &( pValue[j].Value ); - else if ( pValue[j].Name.equals( sPropDerivedKeySize ) ) - pDerivedKeySize = &( pValue[j].Value ); - } - - if ( sPath.getLength() && hasByHierarchicalName ( sPath ) ) - { - aAny = getByHierarchicalName( sPath ); - uno::Reference < XUnoTunnel > xUnoTunnel; - aAny >>= xUnoTunnel; - sal_Int64 nTest=0; - if ( (nTest = xUnoTunnel->getSomething( ZipPackageFolder::static_getImplementationId() )) != 0 ) - { - pFolder = reinterpret_cast < ZipPackageFolder* > ( nTest ); - pFolder->SetMediaType ( sMediaType ); - pFolder->SetVersion ( sVersion ); - } - else - { - pStream = reinterpret_cast < ZipPackageStream* > ( xUnoTunnel->getSomething( ZipPackageStream::static_getImplementationId() )); - pStream->SetMediaType ( sMediaType ); - pStream->SetFromManifest( sal_True ); - - if ( pSalt && pVector && pCount && pSize && pDigest && pDigestAlg && pEncryptionAlg ) - { - uno::Sequence < sal_Int8 > aSequence; - sal_Int32 nCount = 0, nSize = 0, nDigestAlg = 0, nEncryptionAlg = 0, nDerivedKeySize = 16, nStartKeyAlg = xml::crypto::DigestID::SHA1; - - pStream->SetToBeEncrypted ( sal_True ); - - *pSalt >>= aSequence; - pStream->setSalt ( aSequence ); - - *pVector >>= aSequence; - pStream->setInitialisationVector ( aSequence ); - - *pCount >>= nCount; - pStream->setIterationCount ( nCount ); - - *pSize >>= nSize; - pStream->setSize ( nSize ); - - *pDigest >>= aSequence; - pStream->setDigest ( aSequence ); - - *pDigestAlg >>= nDigestAlg; - pStream->SetImportedChecksumAlgorithm( nDigestAlg ); - - *pEncryptionAlg >>= nEncryptionAlg; - pStream->SetImportedEncryptionAlgorithm( nEncryptionAlg ); - - if ( pDerivedKeySize ) - *pDerivedKeySize >>= nDerivedKeySize; - pStream->SetImportedDerivedKeySize( nDerivedKeySize ); - - if ( pStartKeyAlg ) - *pStartKeyAlg >>= nStartKeyAlg; - pStream->SetImportedStartKeyAlgorithm( nStartKeyAlg ); - - pStream->SetToBeCompressed ( sal_True ); - pStream->SetToBeEncrypted ( sal_True ); - pStream->SetIsEncrypted ( sal_True ); - if ( !m_bHasEncryptedEntries - && pStream->getName().equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "content.xml" ) ) ) ) - { - m_bHasEncryptedEntries = sal_True; - m_nStartKeyGenerationID = nStartKeyAlg; - m_nChecksumDigestID = nDigestAlg; - m_nCommonEncryptionID = nEncryptionAlg; - } - } - else - m_bHasNonEncryptedEntries = sal_True; - } - } - } - - bManifestParsed = sal_True; - } - else - throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No manifes parser!" ) ), uno::Reference< uno::XInterface >() ); - } - - // now hide the manifest.xml file from user - xMetaInfFolder->removeByName( sManifest ); - } - } - catch( Exception& ) - { - if ( !m_bForceRecovery ) - throw; - } - } - - if ( !bManifestParsed && !m_bForceRecovery ) - throw ZipIOException( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Could not parse manifest.xml\n" ) ), - uno::Reference< uno::XInterface >() ); - - const OUString sMimetype ( RTL_CONSTASCII_USTRINGPARAM ( "mimetype" ) ); - if ( m_xRootFolder->hasByName( sMimetype ) ) - { - // get mediatype from the "mimetype" stream - ::rtl::OUString aPackageMediatype; - uno::Reference< lang::XUnoTunnel > xMimeTypeTunnel; - m_xRootFolder->getByName( sMimetype ) >>= xMimeTypeTunnel; - uno::Reference < io::XActiveDataSink > xMimeSink( xMimeTypeTunnel, UNO_QUERY ); - if ( xMimeSink.is() ) - { - uno::Reference< io::XInputStream > xMimeInStream = xMimeSink->getInputStream(); - if ( xMimeInStream.is() ) - { - // Mediatypes longer than 1024 symbols should not appear here - uno::Sequence< sal_Int8 > aData( 1024 ); - sal_Int32 nRead = xMimeInStream->readBytes( aData, 1024 ); - if ( nRead > aData.getLength() ) - nRead = aData.getLength(); - - if ( nRead ) - aPackageMediatype = ::rtl::OUString( ( sal_Char* )aData.getConstArray(), nRead, RTL_TEXTENCODING_ASCII_US ); - } - } - - - if ( !bManifestParsed ) - { - // the manifest.xml could not be successfuly parsed, this is an inconsistent package - if ( aPackageMediatype.compareToAscii( RTL_CONSTASCII_STRINGPARAM( "application/vnd." ) ) == 0 ) - { - // accept only types that look similar to own mediatypes - m_pRootFolder->SetMediaType( aPackageMediatype ); - m_bMediaTypeFallbackUsed = sal_True; - } - } - else if ( !m_bForceRecovery ) - { - // the mimetype stream should contain the information from manifest.xml - if ( !m_pRootFolder->GetMediaType().equals( aPackageMediatype ) ) - throw ZipIOException( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "mimetype conflicts with manifest.xml\n" ) ), - uno::Reference< uno::XInterface >() ); - } - - m_xRootFolder->removeByName( sMimetype ); - } - - m_bInconsistent = m_pRootFolder->LookForUnexpectedODF12Streams( ::rtl::OUString() ); - - sal_Bool bODF12AndNewer = ( m_pRootFolder->GetVersion().compareTo( ODFVER_012_TEXT ) >= 0 ); - if ( !m_bForceRecovery && bODF12AndNewer ) - { - if ( m_bInconsistent ) - { - // this is an ODF1.2 document that contains streams not referred in the manifest.xml; - // in case of ODF1.2 documents without version in manifest.xml the property IsInconsistent - // should be checked later - throw ZipIOException( - ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "there are streams not referred in manifest.xml\n" ) ), - uno::Reference< uno::XInterface >() ); - } - else if ( bDifferentStartKeyAlgorithm ) - { - // all the streams should be encrypted with the same StartKey in ODF1.2 - // TODO/LATER: in future the exception should be thrown - OSL_ENSURE( false, "ODF1.2 contains different StartKey Algorithms" ); - // throw ZipIOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "More than one Start Key Generation algorithm is specified!" ) ), uno::Reference< uno::XInterface >() ); - } - } - - // in case it is a correct ODF1.2 document, the version must be set - // and the META-INF folder is reserved for package format - if ( bODF12AndNewer ) - m_xRootFolder->removeByName( sMeta ); - } -} - -//-------------------------------------------------------- -void ZipPackage::parseContentType() -{ - if ( m_nFormat == embed::StorageFormats::OFOPXML ) - { - const ::rtl::OUString aContentTypes( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) ); - try { - // the content type must exist in OFOPXML format! - if ( !m_xRootFolder->hasByName( aContentTypes ) ) - throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Wrong format!" ) ), - uno::Reference< uno::XInterface >() ); - - uno::Reference< lang::XUnoTunnel > xTunnel; - uno::Any aAny = m_xRootFolder->getByName( aContentTypes ); - aAny >>= xTunnel; - uno::Reference < io::XActiveDataSink > xSink( xTunnel, UNO_QUERY ); - if ( xSink.is() ) - { - uno::Reference< io::XInputStream > xInStream = xSink->getInputStream(); - if ( xInStream.is() ) - { - sal_Int32 nInd = 0; - // here aContentTypeInfo[0] - Defaults, and aContentTypeInfo[1] - Overrides - uno::Sequence< uno::Sequence< beans::StringPair > > aContentTypeInfo = - ::comphelper::OFOPXMLHelper::ReadContentTypeSequence( xInStream, m_xFactory ); - - if ( aContentTypeInfo.getLength() != 2 ) - throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - - // set the implicit types fist - for ( nInd = 0; nInd < aContentTypeInfo[0].getLength(); nInd++ ) - m_pRootFolder->setChildStreamsTypeByExtension( aContentTypeInfo[0][nInd] ); - - // now set the explicit types - for ( nInd = 0; nInd < aContentTypeInfo[1].getLength(); nInd++ ) - { - ::rtl::OUString aPath; - if ( aContentTypeInfo[1][nInd].First.toChar() == ( sal_Unicode )'/' ) - aPath = aContentTypeInfo[1][nInd].First.copy( 1 ); - else - aPath = aContentTypeInfo[1][nInd].First; - - if ( aPath.getLength() && hasByHierarchicalName( aPath ) ) - { - uno::Any aIterAny = getByHierarchicalName( aPath ); - uno::Reference < lang::XUnoTunnel > xIterTunnel; - aIterAny >>= xIterTunnel; - sal_Int64 nTest = xIterTunnel->getSomething( ZipPackageStream::static_getImplementationId() ); - if ( nTest != 0 ) - { - // this is a package stream, in OFOPXML format only streams can have mediatype - ZipPackageStream *pStream = reinterpret_cast < ZipPackageStream* > ( nTest ); - pStream->SetMediaType( aContentTypeInfo[1][nInd].Second ); - } - } - } - } - } - - m_xRootFolder->removeByName( aContentTypes ); - } - catch( uno::Exception& ) - { - if ( !m_bForceRecovery ) - throw; - } - } -} - -//-------------------------------------------------------- -void ZipPackage::getZipFileContents() -{ - auto_ptr < ZipEnumeration > pEnum ( m_pZipFile->entries() ); - ZipPackageStream *pPkgStream; - ZipPackageFolder *pPkgFolder, *pCurrent; - OUString sTemp, sDirName; - sal_Int32 nOldIndex, nIndex, nStreamIndex; - FolderHash::iterator aIter; - - while ( pEnum->hasMoreElements() ) - { - nIndex = nOldIndex = 0; - pCurrent = m_pRootFolder; - const ZipEntry & rEntry = *pEnum->nextElement(); - OUString rName = rEntry.sPath; - - if ( m_bForceRecovery ) - { - // the PKZIP Application note version 6.2 does not allows to use '\' as separator - // unfortunately it is used by some implementations, so we have to support it in recovery mode - rName = rName.replace( '\\', '/' ); - } - - nStreamIndex = rName.lastIndexOf ( '/' ); - if ( nStreamIndex != -1 ) - { - sDirName = rName.copy ( 0, nStreamIndex ); - aIter = m_aRecent.find ( sDirName ); - if ( aIter != m_aRecent.end() ) - pCurrent = ( *aIter ).second; - } - - if ( pCurrent == m_pRootFolder ) - { - while ( ( nIndex = rName.indexOf( '/', nOldIndex ) ) != -1 ) - { - sTemp = rName.copy ( nOldIndex, nIndex - nOldIndex ); - if ( nIndex == nOldIndex ) - break; - if ( !pCurrent->hasByName( sTemp ) ) - { - pPkgFolder = new ZipPackageFolder( m_xFactory, m_nFormat, m_bAllowRemoveOnInsert ); - pPkgFolder->setName( sTemp ); - pPkgFolder->doSetParent( pCurrent, sal_True ); - pCurrent = pPkgFolder; - } - else - pCurrent = pCurrent->doGetByName( sTemp ).pFolder; - nOldIndex = nIndex+1; - } - if ( nStreamIndex != -1 && sDirName.getLength() ) - m_aRecent [ sDirName ] = pCurrent; - } - if ( rName.getLength() -1 != nStreamIndex ) - { - nStreamIndex++; - sTemp = rName.copy( nStreamIndex, rName.getLength() - nStreamIndex ); - pPkgStream = new ZipPackageStream( *this, m_xFactory, m_bAllowRemoveOnInsert ); - pPkgStream->SetPackageMember( sal_True ); - pPkgStream->setZipEntryOnLoading( rEntry ); - pPkgStream->setName( sTemp ); - pPkgStream->doSetParent( pCurrent, sal_True ); - } - } - - if ( m_nFormat == embed::StorageFormats::PACKAGE ) - parseManifest(); - else if ( m_nFormat == embed::StorageFormats::OFOPXML ) - parseContentType(); -} - -//-------------------------------------------------------- -void SAL_CALL ZipPackage::initialize( const uno::Sequence< Any >& aArguments ) - throw( Exception, RuntimeException ) -{ - RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "{ ZipPackage::initialize" ); - sal_Bool bBadZipFile = sal_False, bHaveZipFile = sal_True; - uno::Reference< XProgressHandler > xProgressHandler; - beans::NamedValue aNamedValue; - - if ( aArguments.getLength() ) - { - for( int ind = 0; ind < aArguments.getLength(); ind++ ) - { - OUString aParamUrl; - if ( ( aArguments[ind] >>= aParamUrl )) - { - m_eMode = e_IMode_URL; - try - { - sal_Int32 nParam = aParamUrl.indexOf( '?' ); - if ( nParam >= 0 ) - { - m_aURL = aParamUrl.copy( 0, nParam ); - OUString aParam = aParamUrl.copy( nParam + 1 ); - - sal_Int32 nIndex = 0; - do - { - ::rtl::OUString aCommand = aParam.getToken( 0, '&', nIndex ); - if ( aCommand.equals( OUString(RTL_CONSTASCII_USTRINGPARAM( "repairpackage" )) ) ) - { - m_bForceRecovery = sal_True; - break; - } - else if ( aCommand.equals( OUString(RTL_CONSTASCII_USTRINGPARAM( "purezip" )) ) ) - { - m_nFormat = embed::StorageFormats::ZIP; - m_pRootFolder->setPackageFormat_Impl( m_nFormat ); - break; - } - else if ( aCommand.equals( OUString(RTL_CONSTASCII_USTRINGPARAM( "ofopxml" )) ) ) - { - m_nFormat = embed::StorageFormats::OFOPXML; - m_pRootFolder->setPackageFormat_Impl( m_nFormat ); - break; - } - } - while ( nIndex >= 0 ); - } - else - m_aURL = aParamUrl; - - Content aContent ( m_aURL, uno::Reference < XCommandEnvironment >() ); - Any aAny = aContent.getPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM( "Size" )) ); - sal_uInt64 aSize = 0; - // kind of optimisation: treat empty files as nonexistent files - // and write to such files directly. Note that "Size" property is optional. - bool bHasSizeProperty = aAny >>= aSize; - if( !bHasSizeProperty || ( bHasSizeProperty && aSize ) ) - { - uno::Reference < XActiveDataSink > xSink = new ZipPackageSink; - if ( aContent.openStream ( xSink ) ) - m_xContentStream = xSink->getInputStream(); - } - else - bHaveZipFile = sal_False; - } - catch ( com::sun::star::uno::Exception& ) - { - // Exception derived from uno::Exception thrown. This probably - // means the file doesn't exist...we'll create it at - // commitChanges time - bHaveZipFile = sal_False; - } - } - else if ( ( aArguments[ind] >>= m_xStream ) ) - { - // a writable stream can implement both XStream & XInputStream - m_eMode = e_IMode_XStream; - m_xContentStream = m_xStream->getInputStream(); - } - else if ( ( aArguments[ind] >>= m_xContentStream ) ) - { - m_eMode = e_IMode_XInputStream; - } - else if ( ( aArguments[ind] >>= aNamedValue ) ) - { - if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "RepairPackage" ) ) ) - aNamedValue.Value >>= m_bForceRecovery; - else if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "PackageFormat" ) ) ) - { - // setting this argument to true means Package format - // setting it to false means plain Zip format - - sal_Bool bPackFormat = sal_True; - aNamedValue.Value >>= bPackFormat; - if ( !bPackFormat ) - m_nFormat = embed::StorageFormats::ZIP; - - m_pRootFolder->setPackageFormat_Impl( m_nFormat ); - } - else if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StorageFormat" ) ) ) - { - ::rtl::OUString aFormatName; - sal_Int32 nFormatID = 0; - if ( aNamedValue.Value >>= aFormatName ) - { - if ( aFormatName.equals( PACKAGE_STORAGE_FORMAT_STRING ) ) - m_nFormat = embed::StorageFormats::PACKAGE; - else if ( aFormatName.equals( ZIP_STORAGE_FORMAT_STRING ) ) - m_nFormat = embed::StorageFormats::ZIP; - else if ( aFormatName.equals( OFOPXML_STORAGE_FORMAT_STRING ) ) - m_nFormat = embed::StorageFormats::OFOPXML; - else - throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); - } - else if ( aNamedValue.Value >>= nFormatID ) - { - if ( nFormatID != embed::StorageFormats::PACKAGE - && nFormatID != embed::StorageFormats::ZIP - && nFormatID != embed::StorageFormats::OFOPXML ) - throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); - - m_nFormat = nFormatID; - } - else - throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 ); - - m_pRootFolder->setPackageFormat_Impl( m_nFormat ); - } - else if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "AllowRemoveOnInsert" ) ) ) - { - aNamedValue.Value >>= m_bAllowRemoveOnInsert; - m_pRootFolder->setRemoveOnInsertMode_Impl( m_bAllowRemoveOnInsert ); - } - - // for now the progress handler is not used, probably it will never be - // if ( aNamedValue.Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ProgressHandler" ) ) - } - else - { - // The URL is not acceptable - throw com::sun::star::uno::Exception ( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Bad arguments." ) ), - static_cast < ::cppu::OWeakObject * > ( this ) ); - } - } - - try - { - if ( m_xContentStream.is() ) - { - // the stream must be seekable, if it is not it will be wrapped - m_xContentStream = ::comphelper::OSeekableInputWrapper::CheckSeekableCanWrap( m_xContentStream, m_xFactory ); - m_xContentSeek = uno::Reference < XSeekable > ( m_xContentStream, UNO_QUERY ); - if ( ! m_xContentSeek.is() ) - throw com::sun::star::uno::Exception ( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "The package component _requires_ an XSeekable interface!" ) ), - static_cast < ::cppu::OWeakObject * > ( this ) ); - - if ( !m_xContentSeek->getLength() ) - bHaveZipFile = sal_False; - } - else - bHaveZipFile = sal_False; - } - catch ( com::sun::star::uno::Exception& ) - { - // Exception derived from uno::Exception thrown. This probably - // means the file doesn't exist...we'll create it at - // commitChanges time - bHaveZipFile = sal_False; - } - if ( bHaveZipFile ) - { - try - { - m_pZipFile = new ZipFile ( m_xContentStream, m_xFactory, sal_True, m_bForceRecovery, xProgressHandler ); - getZipFileContents(); - } - catch ( IOException & ) - { - bBadZipFile = sal_True; - } - catch ( ZipException & ) - { - bBadZipFile = sal_True; - } - catch ( Exception & ) - { - if( m_pZipFile ) { delete m_pZipFile; m_pZipFile = NULL; } - throw; - } - - if ( bBadZipFile ) - { - // clean up the memory, and tell the UCB about the error - if( m_pZipFile ) { delete m_pZipFile; m_pZipFile = NULL; } - - throw com::sun::star::packages::zip::ZipIOException ( - OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Bad Zip File." ) ), - static_cast < ::cppu::OWeakObject * > ( this ) ); - } - } - } - - RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "} ZipPackage::initialize" ); -} - -//-------------------------------------------------------- -Any SAL_CALL ZipPackage::getByHierarchicalName( const OUString& aName ) - throw( NoSuchElementException, RuntimeException ) -{ - OUString sTemp, sDirName; - sal_Int32 nOldIndex, nIndex, nStreamIndex; - FolderHash::iterator aIter; - - if ( ( nIndex = aName.getLength() ) == 1 && *aName.getStr() == '/' ) - return makeAny ( uno::Reference < XUnoTunnel > ( m_pRootFolder ) ); - else - { - nStreamIndex = aName.lastIndexOf ( '/' ); - bool bFolder = nStreamIndex == nIndex-1; - if ( nStreamIndex != -1 ) - { - sDirName = aName.copy ( 0, nStreamIndex ); - aIter = m_aRecent.find ( sDirName ); - if ( aIter != m_aRecent.end() ) - { - if ( bFolder ) - { - sal_Int32 nDirIndex = aName.lastIndexOf ( '/', nStreamIndex ); - sTemp = aName.copy ( nDirIndex == -1 ? 0 : nDirIndex+1, nStreamIndex-nDirIndex-1 ); - if ( sTemp == ( *aIter ).second->getName() ) - return makeAny ( uno::Reference < XUnoTunnel > ( ( *aIter ).second ) ); - else - m_aRecent.erase ( aIter ); - } - else - { - sTemp = aName.copy ( nStreamIndex + 1 ); - if ( ( *aIter ).second->hasByName( sTemp ) ) - return ( *aIter ).second->getByName( sTemp ); - else - m_aRecent.erase( aIter ); - } - } - } - else - { - if ( m_pRootFolder->hasByName ( aName ) ) - return m_pRootFolder->getByName ( aName ); - } - nOldIndex = 0; - ZipPackageFolder * pCurrent = m_pRootFolder; - ZipPackageFolder * pPrevious = NULL; - while ( ( nIndex = aName.indexOf( '/', nOldIndex )) != -1 ) - { - sTemp = aName.copy ( nOldIndex, nIndex - nOldIndex ); - if ( nIndex == nOldIndex ) - break; - if ( pCurrent->hasByName( sTemp ) ) - { - pPrevious = pCurrent; - pCurrent = pCurrent->doGetByName( sTemp ).pFolder; - } - else - throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - nOldIndex = nIndex+1; - } - if ( bFolder ) - { - if ( nStreamIndex != -1 ) - m_aRecent[sDirName] = pPrevious; - return makeAny ( uno::Reference < XUnoTunnel > ( pCurrent ) ); - } - else - { - sTemp = aName.copy( nOldIndex, aName.getLength() - nOldIndex ); - if ( pCurrent->hasByName ( sTemp ) ) - { - if ( nStreamIndex != -1 ) - m_aRecent[sDirName] = pCurrent; - return pCurrent->getByName( sTemp ); - } - else - throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - } - } -} - -//-------------------------------------------------------- -sal_Bool SAL_CALL ZipPackage::hasByHierarchicalName( const OUString& aName ) - throw( RuntimeException ) -{ - OUString sTemp, sDirName; - sal_Int32 nOldIndex, nIndex, nStreamIndex; - FolderHash::iterator aIter; - - if ( ( nIndex = aName.getLength() ) == 1 && *aName.getStr() == '/' ) - return sal_True; - else - { - nStreamIndex = aName.lastIndexOf ( '/' ); - bool bFolder = nStreamIndex == nIndex-1; - if ( nStreamIndex != -1 ) - { - sDirName = aName.copy ( 0, nStreamIndex ); - aIter = m_aRecent.find ( sDirName ); - if ( aIter != m_aRecent.end() ) - { - if ( bFolder ) - { - sal_Int32 nDirIndex = aName.lastIndexOf ( '/', nStreamIndex ); - sTemp = aName.copy ( nDirIndex == -1 ? 0 : nDirIndex+1, nStreamIndex-nDirIndex-1 ); - if ( sTemp == ( *aIter ).second->getName() ) - return sal_True; - else - m_aRecent.erase ( aIter ); - } - else - { - sTemp = aName.copy ( nStreamIndex + 1 ); - if ( ( *aIter ).second->hasByName( sTemp ) ) - return sal_True; - else - m_aRecent.erase( aIter ); - } - } - } - else - { - if ( m_pRootFolder->hasByName ( aName ) ) - return sal_True; - } - ZipPackageFolder * pCurrent = m_pRootFolder; - ZipPackageFolder * pPrevious = NULL; - nOldIndex = 0; - while ( ( nIndex = aName.indexOf( '/', nOldIndex )) != -1 ) - { - sTemp = aName.copy ( nOldIndex, nIndex - nOldIndex ); - if ( nIndex == nOldIndex ) - break; - if ( pCurrent->hasByName( sTemp ) ) - { - pPrevious = pCurrent; - pCurrent = pCurrent->doGetByName( sTemp ).pFolder; - } - else - return sal_False; - nOldIndex = nIndex+1; - } - if ( bFolder ) - { - m_aRecent[sDirName] = pPrevious; - return sal_True; - } - else - { - sTemp = aName.copy( nOldIndex, aName.getLength() - nOldIndex ); - - if ( pCurrent->hasByName( sTemp ) ) - { - m_aRecent[sDirName] = pCurrent; - return sal_True; - } - } - return sal_False; - } -} - -//-------------------------------------------------------- -uno::Reference< XInterface > SAL_CALL ZipPackage::createInstance() - throw( Exception, RuntimeException ) -{ - uno::Reference < XInterface > xRef = *( new ZipPackageStream ( *this, m_xFactory, m_bAllowRemoveOnInsert ) ); - return xRef; -} -//-------------------------------------------------------- -uno::Reference< XInterface > SAL_CALL ZipPackage::createInstanceWithArguments( const uno::Sequence< Any >& aArguments ) - throw( Exception, RuntimeException ) -{ - sal_Bool bArg = sal_False; - uno::Reference < XInterface > xRef; - if ( aArguments.getLength() ) - aArguments[0] >>= bArg; - if ( bArg ) - xRef = *new ZipPackageFolder ( m_xFactory, m_nFormat, m_bAllowRemoveOnInsert ); - else - xRef = *new ZipPackageStream ( *this, m_xFactory, m_bAllowRemoveOnInsert ); - - return xRef; -} - -//-------------------------------------------------------- -void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut ) -{ - const OUString sMime ( RTL_CONSTASCII_USTRINGPARAM ( "mimetype" ) ); - if ( m_xRootFolder->hasByName( sMime ) ) - m_xRootFolder->removeByName( sMime ); - - ZipEntry * pEntry = new ZipEntry; - sal_Int32 nBufferLength = m_pRootFolder->GetMediaType().getLength(); - OString sMediaType = OUStringToOString( m_pRootFolder->GetMediaType(), RTL_TEXTENCODING_ASCII_US ); - uno::Sequence< sal_Int8 > aType( ( sal_Int8* )sMediaType.getStr(), - nBufferLength ); - - - pEntry->sPath = sMime; - pEntry->nMethod = STORED; - pEntry->nSize = pEntry->nCompressedSize = nBufferLength; - pEntry->nTime = ZipOutputStream::getCurrentDosTime(); - - CRC32 aCRC32; - aCRC32.update( aType ); - pEntry->nCrc = aCRC32.getValue(); - - try - { - aZipOut.putNextEntry( *pEntry, NULL ); - aZipOut.write( aType, 0, nBufferLength ); - aZipOut.closeEntry(); - } - catch ( ::com::sun::star::io::IOException & r ) - { - throw WrappedTargetException( - OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Error adding mimetype to the ZipOutputStream!" ) ), - static_cast < OWeakObject * > ( this ), - makeAny( r ) ); - } -} - -//-------------------------------------------------------- -void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< uno::Sequence < PropertyValue > >& aManList ) -{ - // Write the manifest - uno::Reference < XOutputStream > xManOutStream; - OUString sManifestWriter( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.manifest.ManifestWriter" ) ); - uno::Reference < XManifestWriter > xWriter ( m_xFactory->createInstance( sManifestWriter ), UNO_QUERY ); - if ( xWriter.is() ) - { - ZipEntry * pEntry = new ZipEntry; - ZipPackageBuffer *pBuffer = new ZipPackageBuffer( n_ConstBufferSize ); - xManOutStream = uno::Reference < XOutputStream > ( *pBuffer, UNO_QUERY ); - - pEntry->sPath = OUString( RTL_CONSTASCII_USTRINGPARAM ( "META-INF/manifest.xml" ) ); - pEntry->nMethod = DEFLATED; - pEntry->nCrc = pEntry->nSize = pEntry->nCompressedSize = -1; - pEntry->nTime = ZipOutputStream::getCurrentDosTime(); - - // Convert vector into a uno::Sequence - uno::Sequence < uno::Sequence < PropertyValue > > aManifestSequence ( aManList.size() ); - sal_Int32 nInd = 0; - for ( vector < uno::Sequence < PropertyValue > >::const_iterator aIter = aManList.begin(), aEnd = aManList.end(); - aIter != aEnd; - aIter++, nInd++ ) - { - aManifestSequence[nInd] = ( *aIter ); - } - xWriter->writeManifestSequence ( xManOutStream, aManifestSequence ); - - sal_Int32 nBufferLength = static_cast < sal_Int32 > ( pBuffer->getPosition() ); - pBuffer->realloc( nBufferLength ); - - // the manifest.xml is never encrypted - so pass an empty reference - aZipOut.putNextEntry( *pEntry, NULL ); - aZipOut.write( pBuffer->getSequence(), 0, nBufferLength ); - aZipOut.closeEntry(); - } - else - { - OSL_FAIL( "Couldn't get a ManifestWriter!" ); - IOException aException; - throw WrappedTargetException( - OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Couldn't get a ManifestWriter!" ) ), - static_cast < OWeakObject * > ( this ), - makeAny( aException ) ); - } -} - -//-------------------------------------------------------- -void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno::Sequence < PropertyValue > >& aManList ) -{ - const OUString sFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); - const OUString sMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); - - ZipEntry* pEntry = new ZipEntry; - ZipPackageBuffer *pBuffer = new ZipPackageBuffer( n_ConstBufferSize ); - uno::Reference< io::XOutputStream > xConTypeOutStream( *pBuffer, UNO_QUERY ); - - pEntry->sPath = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) ); - pEntry->nMethod = DEFLATED; - pEntry->nCrc = pEntry->nSize = pEntry->nCompressedSize = -1; - pEntry->nTime = ZipOutputStream::getCurrentDosTime(); - - // Convert vector into a uno::Sequence - // TODO/LATER: use Defaulst entries in future - uno::Sequence< beans::StringPair > aDefaultsSequence; - uno::Sequence< beans::StringPair > aOverridesSequence( aManList.size() ); - sal_Int32 nSeqLength = 0; - for ( vector< uno::Sequence< beans::PropertyValue > >::const_iterator aIter = aManList.begin(), - aEnd = aManList.end(); - aIter != aEnd; - ++aIter) - { - ::rtl::OUString aPath; - ::rtl::OUString aType; - OSL_ENSURE( ( *aIter )[PKG_MNFST_MEDIATYPE].Name.equals( sMediaType ) && ( *aIter )[PKG_MNFST_FULLPATH].Name.equals( sFullPath ), - "The mediatype sequence format is wrong!\n" ); - ( *aIter )[PKG_MNFST_MEDIATYPE].Value >>= aType; - if ( aType.getLength() ) - { - // only nonempty type makes sence here - nSeqLength++; - ( *aIter )[PKG_MNFST_FULLPATH].Value >>= aPath; - aOverridesSequence[nSeqLength-1].First = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "/" ) ) + aPath; - aOverridesSequence[nSeqLength-1].Second = aType; - } - } - aOverridesSequence.realloc( nSeqLength ); - - ::comphelper::OFOPXMLHelper::WriteContentSequence( - xConTypeOutStream, aDefaultsSequence, aOverridesSequence, m_xFactory ); - - sal_Int32 nBufferLength = static_cast < sal_Int32 > ( pBuffer->getPosition() ); - pBuffer->realloc( nBufferLength ); - - // there is no encryption in this format currently - aZipOut.putNextEntry( *pEntry, NULL ); - aZipOut.write( pBuffer->getSequence(), 0, nBufferLength ); - aZipOut.closeEntry(); -} - -//-------------------------------------------------------- -void ZipPackage::ConnectTo( const uno::Reference< io::XInputStream >& xInStream ) -{ - m_xContentSeek.set( xInStream, uno::UNO_QUERY_THROW ); - m_xContentStream = xInStream; - - // seek back to the beginning of the temp file so we can read segments from it - m_xContentSeek->seek( 0 ); - if ( m_pZipFile ) - m_pZipFile->setInputStream( m_xContentStream ); - else - m_pZipFile = new ZipFile ( m_xContentStream, m_xFactory, sal_False ); -} - -//-------------------------------------------------------- -uno::Reference< io::XInputStream > ZipPackage::writeTempFile() -{ - // In case the target local file does not exist or empty - // write directly to it otherwize create a temporary file to write to. - // If a temporary file is created it is returned back by the method. - // If the data written directly, xComponentStream will be switched here - - sal_Bool bUseTemp = sal_True; - uno::Reference < io::XInputStream > xResult; - uno::Reference < io::XInputStream > xTempIn; - - uno::Reference < io::XOutputStream > xTempOut; - uno::Reference< io::XActiveDataStreamer > xSink; - - if ( m_eMode == e_IMode_URL && !m_pZipFile && isLocalFile_Impl( m_aURL ) ) - { - xSink = openOriginalForOutput(); - if( xSink.is() ) - { - uno::Reference< io::XStream > xStr = xSink->getStream(); - if( xStr.is() ) - { - xTempOut = xStr->getOutputStream(); - if( xTempOut.is() ) - bUseTemp = sal_False; - } - } - } - else if ( m_eMode == e_IMode_XStream && !m_pZipFile ) - { - // write directly to an empty stream - xTempOut = m_xStream->getOutputStream(); - if( xTempOut.is() ) - bUseTemp = sal_False; - } - - if( bUseTemp ) - { - // create temporary file - const OUString sServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) ); - uno::Reference < io::XStream > xTempFile( m_xFactory->createInstance ( sServiceName ), UNO_QUERY_THROW ); - xTempOut.set( xTempFile->getOutputStream(), UNO_SET_THROW ); - xTempIn.set( xTempFile->getInputStream(), UNO_SET_THROW ); - } - - // Hand it to the ZipOutputStream: - ZipOutputStream aZipOut( m_xFactory, xTempOut ); - aZipOut.setMethod( DEFLATED ); - aZipOut.setLevel( DEFAULT_COMPRESSION ); - - try - { - if ( m_nFormat == embed::StorageFormats::PACKAGE ) - { - // Remove the old manifest.xml file as the - // manifest will be re-generated and the - // META-INF directory implicitly created if does not exist - const OUString sMeta ( RTL_CONSTASCII_USTRINGPARAM ( "META-INF" ) ); - - if ( m_xRootFolder->hasByName( sMeta ) ) - { - const OUString sManifest ( RTL_CONSTASCII_USTRINGPARAM( "manifest.xml" ) ); - - uno::Reference< XUnoTunnel > xTunnel; - Any aAny = m_xRootFolder->getByName( sMeta ); - aAny >>= xTunnel; - uno::Reference< XNameContainer > xMetaInfFolder( xTunnel, UNO_QUERY ); - if ( xMetaInfFolder.is() && xMetaInfFolder->hasByName( sManifest ) ) - xMetaInfFolder->removeByName( sManifest ); - } - - // Write a magic file with mimetype - WriteMimetypeMagicFile( aZipOut ); - } - else if ( m_nFormat == embed::StorageFormats::OFOPXML ) - { - // Remove the old [Content_Types].xml file as the - // file will be re-generated - - const ::rtl::OUString aContentTypes( RTL_CONSTASCII_USTRINGPARAM ( "[Content_Types].xml" ) ); - - if ( m_xRootFolder->hasByName( aContentTypes ) ) - m_xRootFolder->removeByName( aContentTypes ); - } - - // Create a vector to store data for the manifest.xml file - vector < uno::Sequence < PropertyValue > > aManList; - - const OUString sMediaType ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); - const OUString sVersion ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ); - const OUString sFullPath ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); - - if ( m_nFormat == embed::StorageFormats::PACKAGE ) - { - uno::Sequence < PropertyValue > aPropSeq( PKG_SIZE_NOENCR_MNFST ); - aPropSeq [PKG_MNFST_MEDIATYPE].Name = sMediaType; - aPropSeq [PKG_MNFST_MEDIATYPE].Value <<= m_pRootFolder->GetMediaType(); - aPropSeq [PKG_MNFST_VERSION].Name = sVersion; - aPropSeq [PKG_MNFST_VERSION].Value <<= m_pRootFolder->GetVersion(); - aPropSeq [PKG_MNFST_FULLPATH].Name = sFullPath; - aPropSeq [PKG_MNFST_FULLPATH].Value <<= OUString ( RTL_CONSTASCII_USTRINGPARAM ( "/" ) ); - - aManList.push_back( aPropSeq ); - } - - // Get a random number generator and seed it with current timestamp - // This will be used to generate random salt and initialisation vectors - // for encrypted streams - TimeValue aTime; - osl_getSystemTime( &aTime ); - rtlRandomPool aRandomPool = rtl_random_createPool (); - rtl_random_addBytes ( aRandomPool, &aTime, 8 ); - - // call saveContents ( it will recursively save sub-directories - OUString aEmptyString; - m_pRootFolder->saveContents( aEmptyString, aManList, aZipOut, GetEncryptionKey(), aRandomPool ); - - // Clean up random pool memory - rtl_random_destroyPool ( aRandomPool ); - - if( m_nFormat == embed::StorageFormats::PACKAGE ) - { - WriteManifest( aZipOut, aManList ); - } - else if( m_nFormat == embed::StorageFormats::OFOPXML ) - { - WriteContentTypes( aZipOut, aManList ); - } - - aZipOut.finish(); - - if( bUseTemp ) - xResult = xTempIn; - - // Update our References to point to the new temp file - if( !bUseTemp ) - { - // the case when the original contents were written directly - xTempOut->flush(); - - // in case the stream is based on a file it will implement the following interface - // the call should be used to be sure that the contents are written to the file system - uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor( xTempOut, uno::UNO_QUERY ); - if ( asyncOutputMonitor.is() ) - asyncOutputMonitor->waitForCompletion(); - - // no need to postpone switching to the new stream since the target was written directly - uno::Reference< io::XInputStream > xNewStream; - if ( m_eMode == e_IMode_URL ) - xNewStream = xSink->getStream()->getInputStream(); - else if ( m_eMode == e_IMode_XStream && m_xStream.is() ) - xNewStream = m_xStream->getInputStream(); - - if ( xNewStream.is() ) - ConnectTo( xNewStream ); - } - } - catch ( uno::Exception& ) - { - if( bUseTemp ) - { - // no information loss appeares, thus no special handling is required - uno::Any aCaught( ::cppu::getCaughtException() ); - - // it is allowed to throw WrappedTargetException - WrappedTargetException aException; - if ( aCaught >>= aException ) - throw aException; - - throw WrappedTargetException( - OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Problem writing the original content!" ) ), - static_cast < OWeakObject * > ( this ), - aCaught ); - } - else - { - // the document is written directly, although it was empty it is important to notify that the writing has failed - // TODO/LATER: let the package be able to recover in this situation - ::rtl::OUString aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is unusable!" ) ); - embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), ::rtl::OUString() ); - throw WrappedTargetException( aErrTxt, - static_cast < OWeakObject * > ( this ), - makeAny ( aException ) ); - } - } - - return xResult; -} - -//-------------------------------------------------------- -uno::Reference< XActiveDataStreamer > ZipPackage::openOriginalForOutput() -{ - // open and truncate the original file - Content aOriginalContent ( m_aURL, uno::Reference < XCommandEnvironment >() ); - uno::Reference< XActiveDataStreamer > xSink = new ActiveDataStreamer; - - if ( m_eMode == e_IMode_URL ) - { - try - { - sal_Bool bTruncSuccess = sal_False; - - try - { - Exception aDetect; - sal_Int64 aSize = 0; - Any aAny = aOriginalContent.setPropertyValue( OUString(RTL_CONSTASCII_USTRINGPARAM( "Size" )), makeAny( aSize ) ); - if( !( aAny >>= aDetect ) ) - bTruncSuccess = sal_True; - } - catch( Exception& ) - { - } - - if( !bTruncSuccess ) - { - // the file is not accessible - // just try to write an empty stream to it - - uno::Reference< XInputStream > xTempIn = new DummyInputStream; //uno::Reference< XInputStream >( xTempOut, UNO_QUERY ); - aOriginalContent.writeStream( xTempIn , sal_True ); - } - - OpenCommandArgument2 aArg; - aArg.Mode = OpenMode::DOCUMENT; - aArg.Priority = 0; // unused - aArg.Sink = xSink; - aArg.Properties = uno::Sequence< Property >( 0 ); // unused - - aOriginalContent.executeCommand( OUString(RTL_CONSTASCII_USTRINGPARAM( "open" )), makeAny( aArg ) ); - } - catch( Exception& ) - { - // seems to be nonlocal file - // temporary file mechanics should be used - } - } - - return xSink; -} - -//-------------------------------------------------------- -void SAL_CALL ZipPackage::commitChanges() - throw( WrappedTargetException, RuntimeException ) -{ - // lock the component for the time of commiting - ::osl::MutexGuard aGuard( m_aMutexHolder->GetMutex() ); - - if ( m_eMode == e_IMode_XInputStream ) - { - IOException aException; - throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is read only!" ) ), - static_cast < OWeakObject * > ( this ), makeAny ( aException ) ); - } - - RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "{ ZipPackage::commitChanges" ); - - // first the writeTempFile is called, if it returns a stream the stream should be written to the target - // if no stream was returned, the file was written directly, nothing should be done - - uno::Reference< io::XInputStream > xTempInStream = writeTempFile(); - if ( xTempInStream.is() ) - { - uno::Reference< io::XSeekable > xTempSeek( xTempInStream, uno::UNO_QUERY_THROW ); - - try - { - xTempSeek->seek( 0 ); - } - catch( uno::Exception& r ) - { - throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "Temporary file should be seekable!" ) ), - static_cast < OWeakObject * > ( this ), makeAny ( r ) ); - } - - // connect to the temporary stream - ConnectTo( xTempInStream ); - - if ( m_eMode == e_IMode_XStream ) - { - // First truncate our output stream - uno::Reference < XOutputStream > xOutputStream; - - // preparation for copy step - try - { - xOutputStream = m_xStream->getOutputStream(); - uno::Reference < XTruncate > xTruncate ( xOutputStream, UNO_QUERY ); - if ( !xTruncate.is() ) - throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - - // after successful truncation the original file contents are already lost - xTruncate->truncate(); - } - catch( uno::Exception& r ) - { - throw WrappedTargetException( OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is read only!" ) ), - static_cast < OWeakObject * > ( this ), makeAny ( r ) ); - } - - try - { - // then copy the contents of the tempfile to our output stream - ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, xOutputStream ); - xOutputStream->flush(); - uno::Reference< io::XAsyncOutputMonitor > asyncOutputMonitor( - xOutputStream, uno::UNO_QUERY ); - if ( asyncOutputMonitor.is() ) { - asyncOutputMonitor->waitForCompletion(); - } - } - catch( uno::Exception& ) - { - // if anything goes wrong in this block the target file becomes corrupted - // so an exception should be thrown as a notification about it - // and the package must disconnect from the stream - DisconnectFromTargetAndThrowException_Impl( xTempInStream ); - } - } - else if ( m_eMode == e_IMode_URL ) - { - uno::Reference< XOutputStream > aOrigFileStream; - sal_Bool bCanBeCorrupted = sal_False; - - if( isLocalFile_Impl( m_aURL ) ) - { - // write directly in case of local file - uno::Reference< ::com::sun::star::ucb::XSimpleFileAccess > xSimpleAccess( - m_xFactory->createInstance( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.ucb.SimpleFileAccess") ) ), - uno::UNO_QUERY ); - OSL_ENSURE( xSimpleAccess.is(), "Can't instatiate SimpleFileAccess service!\n" ); - uno::Reference< io::XTruncate > xOrigTruncate; - if ( xSimpleAccess.is() ) - { - try - { - aOrigFileStream = xSimpleAccess->openFileWrite( m_aURL ); - xOrigTruncate = uno::Reference< io::XTruncate >( aOrigFileStream, uno::UNO_QUERY_THROW ); - // after successful truncation the file is already corrupted - xOrigTruncate->truncate(); - } - catch( uno::Exception& ) - {} - } - - if( xOrigTruncate.is() ) - { - try - { - ::comphelper::OStorageHelper::CopyInputToOutput( xTempInStream, aOrigFileStream ); - aOrigFileStream->closeOutput(); - } - catch( uno::Exception& ) - { - try { - aOrigFileStream->closeOutput(); - } catch ( uno::Exception& ) {} - - aOrigFileStream = uno::Reference< XOutputStream >(); - // the original file can already be corrupted - bCanBeCorrupted = sal_True; - } - } - } - - if( !aOrigFileStream.is() ) - { - try - { - uno::Reference < XPropertySet > xPropSet ( xTempInStream, UNO_QUERY ); - OSL_ENSURE( xPropSet.is(), "This is a temporary file that must implement XPropertySet!\n" ); - if ( !xPropSet.is() ) - throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - - OUString sTargetFolder = m_aURL.copy ( 0, m_aURL.lastIndexOf ( static_cast < sal_Unicode > ( '/' ) ) ); - Content aContent ( sTargetFolder, uno::Reference < XCommandEnvironment > () ); - - OUString sTempURL; - Any aAny = xPropSet->getPropertyValue ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Uri" ) ) ); - aAny >>= sTempURL; - - TransferInfo aInfo; - aInfo.NameClash = NameClash::OVERWRITE; - aInfo.MoveData = sal_False; - aInfo.SourceURL = sTempURL; - aInfo.NewTitle = rtl::Uri::decode ( m_aURL.copy ( 1 + m_aURL.lastIndexOf ( static_cast < sal_Unicode > ( '/' ) ) ), - rtl_UriDecodeWithCharset, - RTL_TEXTENCODING_UTF8 ); - aAny <<= aInfo; - - // if the file is still not corrupted, it can become after the next step - aContent.executeCommand ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "transfer" ) ), aAny ); - } - catch ( ::com::sun::star::uno::Exception& r ) - { - if ( bCanBeCorrupted ) - DisconnectFromTargetAndThrowException_Impl( xTempInStream ); - - throw WrappedTargetException( - OUString( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package may be read only!" ) ), - static_cast < OWeakObject * > ( this ), - makeAny ( r ) ); - } - } - } - } - - // after successful storing it can be set to false - m_bMediaTypeFallbackUsed = sal_False; - - RTL_LOGFILE_TRACE_AUTHOR ( "package", LOGFILE_AUTHOR, "} ZipPackage::commitChanges" ); -} - -//-------------------------------------------------------- -void ZipPackage::DisconnectFromTargetAndThrowException_Impl( const uno::Reference< io::XInputStream >& xTempStream ) -{ - m_xStream = uno::Reference< io::XStream >( xTempStream, uno::UNO_QUERY ); - if ( m_xStream.is() ) - m_eMode = e_IMode_XStream; - else - m_eMode = e_IMode_XInputStream; - - ::rtl::OUString aTempURL; - try { - uno::Reference< beans::XPropertySet > xTempFile( xTempStream, uno::UNO_QUERY_THROW ); - uno::Any aUrl = xTempFile->getPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Uri") ) ); - aUrl >>= aTempURL; - xTempFile->setPropertyValue( ::rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("RemoveFile") ), - uno::makeAny( sal_False ) ); - } - catch ( uno::Exception& ) - { - OSL_FAIL( "These calls are pretty simple, they should not fail!\n" ); - } - - ::rtl::OUString aErrTxt( RTL_CONSTASCII_USTRINGPARAM ( OSL_LOG_PREFIX "This package is read only!" ) ); - embed::UseBackupException aException( aErrTxt, uno::Reference< uno::XInterface >(), aTempURL ); - throw WrappedTargetException( aErrTxt, - static_cast < OWeakObject * > ( this ), - makeAny ( aException ) ); -} - -//-------------------------------------------------------- -const uno::Sequence< sal_Int8 > ZipPackage::GetEncryptionKey() -{ - uno::Sequence< sal_Int8 > aResult; - - if ( m_aStorageEncryptionKeys.getLength() ) - { - ::rtl::OUString aNameToFind; - if ( m_nStartKeyGenerationID == xml::crypto::DigestID::SHA256 ) - aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA256UTF8; - else if ( m_nStartKeyGenerationID == xml::crypto::DigestID::SHA1 ) - aNameToFind = PACKAGE_ENCRYPTIONDATA_SHA1UTF8; - else - throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() ); - - for ( sal_Int32 nInd = 0; nInd < m_aStorageEncryptionKeys.getLength(); nInd++ ) - if ( m_aStorageEncryptionKeys[nInd].Name.equals( aNameToFind ) ) - m_aStorageEncryptionKeys[nInd].Value >>= aResult; - - // empty keys are not allowed here - // so it is not important whether there is no key, or the key is empty, it is an error - if ( !aResult.getLength() ) - throw uno::RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "No expected key is provided!" ) ), uno::Reference< uno::XInterface >() ); - } - else - aResult = m_aEncryptionKey; - - return aResult; -} - -//-------------------------------------------------------- -sal_Bool SAL_CALL ZipPackage::hasPendingChanges() - throw( RuntimeException ) -{ - return sal_False; -} -//-------------------------------------------------------- -Sequence< ElementChange > SAL_CALL ZipPackage::getPendingChanges() - throw( RuntimeException ) -{ - return uno::Sequence < ElementChange > (); -} - -/** - * Function to create a new component instance; is needed by factory helper implementation. - * @param xMgr service manager to if the components needs other component instances - */ -uno::Reference < XInterface >SAL_CALL ZipPackage_createInstance( - const uno::Reference< XMultiServiceFactory > & xMgr ) -{ - return uno::Reference< XInterface >( *new ZipPackage( xMgr ) ); -} - -//-------------------------------------------------------- -OUString ZipPackage::static_getImplementationName() -{ - return OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.comp.ZipPackage" ) ); -} - -//-------------------------------------------------------- -Sequence< OUString > ZipPackage::static_getSupportedServiceNames() -{ - uno::Sequence< OUString > aNames( 1 ); - aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.Package" ) ); - return aNames; -} -//-------------------------------------------------------- -sal_Bool SAL_CALL ZipPackage::static_supportsService( OUString const & rServiceName ) -{ - return rServiceName == getSupportedServiceNames()[0]; -} - -//-------------------------------------------------------- -OUString ZipPackage::getImplementationName() - throw ( RuntimeException ) -{ - return static_getImplementationName(); -} - -//-------------------------------------------------------- -Sequence< OUString > ZipPackage::getSupportedServiceNames() - throw ( RuntimeException ) -{ - return static_getSupportedServiceNames(); -} -//-------------------------------------------------------- -sal_Bool SAL_CALL ZipPackage::supportsService( OUString const & rServiceName ) - throw ( RuntimeException ) -{ - return static_supportsService ( rServiceName ); -} -//-------------------------------------------------------- -uno::Reference < XSingleServiceFactory > ZipPackage::createServiceFactory( uno::Reference < XMultiServiceFactory > const & rServiceFactory ) -{ - return cppu::createSingleFactory ( rServiceFactory, - static_getImplementationName(), - ZipPackage_createInstance, - static_getSupportedServiceNames() ); -} - -namespace { struct lcl_ImplId : public rtl::Static< ::cppu::OImplementationId, lcl_ImplId > {}; } - -//-------------------------------------------------------- -Sequence< sal_Int8 > ZipPackage::getUnoTunnelImplementationId( void ) - throw ( RuntimeException ) -{ - ::cppu::OImplementationId &rId = lcl_ImplId::get(); - return rId.getImplementationId(); -} - -//-------------------------------------------------------- -sal_Int64 SAL_CALL ZipPackage::getSomething( const uno::Sequence< sal_Int8 >& aIdentifier ) - throw( RuntimeException ) -{ - if ( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory( getUnoTunnelImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) - return reinterpret_cast < sal_Int64 > ( this ); - return 0; -} - -//-------------------------------------------------------- -uno::Reference< XPropertySetInfo > SAL_CALL ZipPackage::getPropertySetInfo() - throw( RuntimeException ) -{ - return uno::Reference < XPropertySetInfo > (); -} - -//-------------------------------------------------------- -void SAL_CALL ZipPackage::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) - throw( UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException ) -{ - if ( m_nFormat != embed::StorageFormats::PACKAGE ) - throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - - if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( HAS_ENCRYPTED_ENTRIES_PROPERTY ) ) - ||aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( HAS_NONENCRYPTED_ENTRIES_PROPERTY ) ) - ||aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( IS_INCONSISTENT_PROPERTY ) ) - ||aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( MEDIATYPE_FALLBACK_USED_PROPERTY ) ) ) - throw PropertyVetoException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_KEY_PROPERTY ) ) ) - { - if ( !( aValue >>= m_aEncryptionKey ) ) - throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 2 ); - - m_aStorageEncryptionKeys.realloc( 0 ); - } - else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ) - { - // this property is only necessary to support raw passwords in storage API; - // because of this support the storage has to operate with more than one key dependent on storage generation algorithm; - // when this support is removed, the storage will get only one key from outside - // TODO/LATER: Get rid of this property as well as of support of raw passwords in storages - uno::Sequence< beans::NamedValue > aKeys; - if ( !( aValue >>= aKeys ) || ( aKeys.getLength() && aKeys.getLength() < 2 ) ) - throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 2 ); - - if ( aKeys.getLength() ) - { - bool bHasSHA256 = false; - bool bHasSHA1 = false; - for ( sal_Int32 nInd = 0; nInd < aKeys.getLength(); nInd++ ) - { - if ( aKeys[nInd].Name.equals( PACKAGE_ENCRYPTIONDATA_SHA256UTF8 ) ) - bHasSHA256 = true; - if ( aKeys[nInd].Name.equals( PACKAGE_ENCRYPTIONDATA_SHA1UTF8 ) ) - bHasSHA1 = true; - } - - if ( !bHasSHA256 || !bHasSHA1 ) - throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Expected keys are not provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); - } - - m_aStorageEncryptionKeys = aKeys; - m_aEncryptionKey.realloc( 0 ); - } - else if ( aPropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY ) ) ) - { - uno::Sequence< beans::NamedValue > aAlgorithms; - if ( m_pZipFile || !( aValue >>= aAlgorithms ) || aAlgorithms.getLength() == 0 ) - { - // the algorithms can not be changed if the file has a persistence based on the algorithms ( m_pZipFile ) - throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "unexpected algorithms list is provided." ) ), uno::Reference< uno::XInterface >(), 2 ); - } - - for ( sal_Int32 nInd = 0; nInd < aAlgorithms.getLength(); nInd++ ) - { - if ( aAlgorithms[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "StartKeyGenerationAlgorithm" ) ) ) - { - sal_Int32 nID = 0; - if ( !( aAlgorithms[nInd].Value >>= nID ) - || ( nID != xml::crypto::DigestID::SHA256 && nID != xml::crypto::DigestID::SHA1 ) ) - throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected start key generation algorithm is provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); - - m_nStartKeyGenerationID = nID; - } - else if ( aAlgorithms[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "EncryptionAlgorithm" ) ) ) - { - sal_Int32 nID = 0; - if ( !( aAlgorithms[nInd].Value >>= nID ) - || ( nID != xml::crypto::CipherID::AES_CBC_W3C_PADDING && nID != xml::crypto::CipherID::BLOWFISH_CFB_8 ) ) - throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected start key generation algorithm is provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); - - m_nCommonEncryptionID = nID; - } - else if ( aAlgorithms[nInd].Name.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "ChecksumAlgorithm" ) ) ) - { - sal_Int32 nID = 0; - if ( !( aAlgorithms[nInd].Value >>= nID ) - || ( nID != xml::crypto::DigestID::SHA1_1K && nID != xml::crypto::DigestID::SHA256_1K ) ) - throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "Unexpected start key generation algorithm is provided!" ) ), uno::Reference< uno::XInterface >(), 2 ); - - m_nChecksumDigestID = nID; - } - else - { - OSL_ENSURE( sal_False, "Unexpected encryption algorithm is provided!" ); - throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX "unexpected algorithms list is provided." ) ), uno::Reference< uno::XInterface >(), 2 ); - } - } - } - else - throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); -} - -//-------------------------------------------------------- -Any SAL_CALL ZipPackage::getPropertyValue( const OUString& PropertyName ) - throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) -{ - // TODO/LATER: Activate the check when zip-ucp is ready - // if ( m_nFormat != embed::StorageFormats::PACKAGE ) - // throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); - - Any aAny; - if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( ENCRYPTION_KEY_PROPERTY ) ) ) - { - aAny <<= m_aEncryptionKey; - return aAny; - } - else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( ENCRYPTION_ALGORITHMS_PROPERTY ) ) ) - { - ::comphelper::SequenceAsHashMap aAlgorithms; - aAlgorithms[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "StartKeyGenerationAlgorithm" ) ) ] <<= m_nStartKeyGenerationID; - aAlgorithms[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "EncryptionAlgorithm" ) ) ] <<= m_nCommonEncryptionID; - aAlgorithms[ ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "ChecksumAlgorithm" ) ) ] <<= m_nChecksumDigestID; - aAny <<= aAlgorithms.getAsConstNamedValueList(); - return aAny; - } - if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( STORAGE_ENCRYPTION_KEYS_PROPERTY ) ) ) - { - aAny <<= m_aStorageEncryptionKeys; - return aAny; - } - else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( HAS_ENCRYPTED_ENTRIES_PROPERTY ) ) ) - { - aAny <<= m_bHasEncryptedEntries; - return aAny; - } - else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( HAS_NONENCRYPTED_ENTRIES_PROPERTY ) ) ) - { - aAny <<= m_bHasNonEncryptedEntries; - return aAny; - } - else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( IS_INCONSISTENT_PROPERTY ) ) ) - { - aAny <<= m_bInconsistent; - return aAny; - } - else if ( PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( MEDIATYPE_FALLBACK_USED_PROPERTY ) ) ) - { - aAny <<= m_bMediaTypeFallbackUsed; - return aAny; - } - throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); -} -//-------------------------------------------------------- -void SAL_CALL ZipPackage::addPropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*xListener*/ ) - throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) -{ -} -//-------------------------------------------------------- -void SAL_CALL ZipPackage::removePropertyChangeListener( const OUString& /*aPropertyName*/, const uno::Reference< XPropertyChangeListener >& /*aListener*/ ) - throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) -{ -} -//-------------------------------------------------------- -void SAL_CALL ZipPackage::addVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ ) - throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) -{ -} -//-------------------------------------------------------- -void SAL_CALL ZipPackage::removeVetoableChangeListener( const OUString& /*PropertyName*/, const uno::Reference< XVetoableChangeListener >& /*aListener*/ ) - throw( UnknownPropertyException, WrappedTargetException, RuntimeException ) -{ -} - -/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |