/************************************************************************* * * 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 * * for a copy of the LGPLv3 License. * ************************************************************************/ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_package.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace com::sun::star::packages::zip::ZipConstants; using namespace com::sun::star::packages::zip; using namespace com::sun::star::container; using namespace com::sun::star::packages; using namespace com::sun::star::beans; using namespace com::sun::star::lang; using namespace com::sun::star::uno; using namespace com::sun::star::io; using namespace cppu; using namespace rtl; using namespace std; using namespace ::com::sun::star; using vos::ORef; namespace { struct lcl_CachedImplId : public rtl::Static< Sequence < sal_Int8 >, lcl_CachedImplId > {}; } ZipPackageFolder::ZipPackageFolder ( const Reference< XMultiServiceFactory >& xFactory, sal_Int32 nFormat, sal_Bool bAllowRemoveOnInsert ) : m_xFactory( xFactory ) , m_nFormat( nFormat ) { OSL_ENSURE( m_xFactory.is(), "No factory is provided to the package folder!" ); this->mbAllowRemoveOnInsert = bAllowRemoveOnInsert; SetFolder ( sal_True ); aEntry.nVersion = -1; aEntry.nFlag = 0; aEntry.nMethod = STORED; aEntry.nTime = -1; aEntry.nCrc = 0; aEntry.nCompressedSize = 0; aEntry.nSize = 0; aEntry.nOffset = -1; Sequence < sal_Int8 > &rCachedImplId = lcl_CachedImplId::get(); if ( !rCachedImplId.getLength() ) rCachedImplId = getImplementationId(); } ZipPackageFolder::~ZipPackageFolder() { } sal_Bool ZipPackageFolder::LookForUnexpectedODF12Streams( const ::rtl::OUString& aPath ) { sal_Bool bHasUnexpected = sal_False; for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end(); !bHasUnexpected && aCI != aEnd; aCI++) { const OUString &rShortName = (*aCI).first; const ContentInfo &rInfo = *(*aCI).second; if ( rInfo.bFolder ) { if ( aPath.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF/" ) ) ) ) { // META-INF is not allowed to contain subfolders bHasUnexpected = sal_True; } else { OUString sOwnPath = aPath + rShortName + OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) ); bHasUnexpected = rInfo.pFolder->LookForUnexpectedODF12Streams( sOwnPath ); } } else { if ( aPath.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "META-INF/" ) ) ) ) { if ( !rShortName.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "manifest.xml" ) ) ) && rShortName.indexOf( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "signatures" ) ) ) == -1 ) { // a stream from META-INF with unexpected name bHasUnexpected = sal_True; } // streams from META-INF with expected names are allowed not to be registered in manifest.xml } else if ( !rInfo.pStream->IsFromManifest() ) { // the stream is not in META-INF and ist notregistered in manifest.xml, // check whether it is an internal part of the package format if ( aPath.getLength() || !rShortName.equals( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "mimetype" ) ) ) ) { // if it is not "mimetype" from the root it is not a part of the package bHasUnexpected = sal_True; } } } } return bHasUnexpected; } void ZipPackageFolder::setChildStreamsTypeByExtension( const beans::StringPair& aPair ) { ::rtl::OUString aExt; if ( aPair.First.toChar() == (sal_Unicode)'.' ) aExt = aPair.First; else aExt = ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "." ) ) + aPair.First; for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end(); aCI != aEnd; aCI++) { const OUString &rShortName = (*aCI).first; const ContentInfo &rInfo = *(*aCI).second; if ( rInfo.bFolder ) rInfo.pFolder->setChildStreamsTypeByExtension( aPair ); else { sal_Int32 nPathLength = rShortName.getLength(); sal_Int32 nExtLength = aExt.getLength(); if ( nPathLength >= nExtLength && rShortName.match( aExt, nPathLength - nExtLength ) ) rInfo.pStream->SetMediaType( aPair.Second ); } } } void ZipPackageFolder::copyZipEntry( ZipEntry &rDest, const ZipEntry &rSource) { rDest.nVersion = rSource.nVersion; rDest.nFlag = rSource.nFlag; rDest.nMethod = rSource.nMethod; rDest.nTime = rSource.nTime; rDest.nCrc = rSource.nCrc; rDest.nCompressedSize = rSource.nCompressedSize; rDest.nSize = rSource.nSize; rDest.nOffset = rSource.nOffset; rDest.sPath = rSource.sPath; rDest.nPathLen = rSource.nPathLen; rDest.nExtraLen = rSource.nExtraLen; } const ::com::sun::star::uno::Sequence < sal_Int8 >& ZipPackageFolder::static_getImplementationId() { return lcl_CachedImplId::get(); } // XNameContainer void SAL_CALL ZipPackageFolder::insertByName( const OUString& aName, const Any& aElement ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) { if (hasByName(aName)) throw ElementExistException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); else { Reference < XUnoTunnel > xRef; aElement >>= xRef; if ( ( aElement >>= xRef ) ) { sal_Int64 nTest; ZipPackageEntry *pEntry; if ( ( nTest = xRef->getSomething ( ZipPackageFolder::static_getImplementationId() ) ) != 0 ) { ZipPackageFolder *pFolder = reinterpret_cast < ZipPackageFolder * > ( nTest ); pEntry = static_cast < ZipPackageEntry * > ( pFolder ); } else if ( ( nTest = xRef->getSomething ( ZipPackageStream::static_getImplementationId() ) ) != 0 ) { ZipPackageStream *pStream = reinterpret_cast < ZipPackageStream * > ( nTest ); pEntry = static_cast < ZipPackageEntry * > ( pStream ); } else throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 ); if (pEntry->getName() != aName ) pEntry->setName (aName); doInsertByName ( pEntry, sal_True ); } else throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 0 ); } } void SAL_CALL ZipPackageFolder::removeByName( const OUString& Name ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) { ContentHash::iterator aIter = maContents.find ( Name ); if ( aIter == maContents.end() ) throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); maContents.erase( aIter ); } // XEnumerationAccess Reference< XEnumeration > SAL_CALL ZipPackageFolder::createEnumeration( ) throw(RuntimeException) { return Reference < XEnumeration> (new ZipPackageFolderEnumeration(maContents)); } // XElementAccess Type SAL_CALL ZipPackageFolder::getElementType( ) throw(RuntimeException) { return ::getCppuType ((const Reference< XUnoTunnel > *) 0); } sal_Bool SAL_CALL ZipPackageFolder::hasElements( ) throw(RuntimeException) { return maContents.size() > 0; } // XNameAccess ContentInfo& ZipPackageFolder::doGetByName( const OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) { ContentHash::iterator aIter = maContents.find ( aName ); if ( aIter == maContents.end()) throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); return *(*aIter).second; } Any SAL_CALL ZipPackageFolder::getByName( const OUString& aName ) throw(NoSuchElementException, WrappedTargetException, RuntimeException) { return makeAny ( doGetByName ( aName ).xTunnel ); } Sequence< OUString > SAL_CALL ZipPackageFolder::getElementNames( ) throw(RuntimeException) { sal_uInt32 i=0, nSize = maContents.size(); Sequence < OUString > aSequence ( nSize ); OUString *pNames = aSequence.getArray(); for ( ContentHash::const_iterator aIterator = maContents.begin(), aEnd = maContents.end(); aIterator != aEnd; ++i, ++aIterator) pNames[i] = (*aIterator).first; return aSequence; } sal_Bool SAL_CALL ZipPackageFolder::hasByName( const OUString& aName ) throw(RuntimeException) { return maContents.find ( aName ) != maContents.end (); } // XNameReplace void SAL_CALL ZipPackageFolder::replaceByName( const OUString& aName, const Any& aElement ) throw(IllegalArgumentException, NoSuchElementException, WrappedTargetException, RuntimeException) { if ( hasByName( aName ) ) removeByName( aName ); else throw NoSuchElementException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); insertByName(aName, aElement); } static void ImplSetStoredData( ZipEntry & rEntry, Reference < XInputStream> & rStream ) { // It's very annoying that we have to do this, but lots of zip packages // don't allow data descriptors for STORED streams, meaning we have to // know the size and CRC32 of uncompressed streams before we actually // write them ! CRC32 aCRC32; rEntry.nMethod = STORED; rEntry.nCompressedSize = rEntry.nSize = aCRC32.updateStream ( rStream ); rEntry.nCrc = aCRC32.getValue(); } void ZipPackageFolder::saveContents(OUString &rPath, std::vector < Sequence < PropertyValue > > &rManList, ZipOutputStream & rZipOut, Sequence < sal_Int8 > &rEncryptionKey, rtlRandomPool &rRandomPool) throw(RuntimeException) { sal_Bool bWritingFailed = sal_False; ZipPackageFolder *pFolder = NULL; ZipPackageStream *pStream = NULL; const OUString sMediaTypeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "MediaType" ) ); const OUString sVersionProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Version" ) ); const OUString sFullPathProperty ( RTL_CONSTASCII_USTRINGPARAM ( "FullPath" ) ); const OUString sInitialisationVectorProperty ( RTL_CONSTASCII_USTRINGPARAM ( "InitialisationVector" ) ); const OUString sSaltProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Salt" ) ); const OUString sIterationCountProperty ( RTL_CONSTASCII_USTRINGPARAM ( "IterationCount" ) ); const OUString sSizeProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Size" ) ); const OUString sDigestProperty ( RTL_CONSTASCII_USTRINGPARAM ( "Digest" ) ); sal_Bool bHaveEncryptionKey = rEncryptionKey.getLength() ? sal_True : sal_False; if ( maContents.begin() == maContents.end() && rPath.getLength() && m_nFormat != embed::StorageFormats::OFOPXML ) { // it is an empty subfolder, use workaround to store it ZipEntry* pTempEntry = new ZipEntry(); ZipPackageFolder::copyZipEntry ( *pTempEntry, aEntry ); pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( rPath, RTL_TEXTENCODING_UTF8 ).getLength() ); pTempEntry->nExtraLen = -1; pTempEntry->sPath = rPath; try { vos::ORef < EncryptionData > aEmptyEncr; rZipOut.putNextEntry ( *pTempEntry, aEmptyEncr, sal_False ); rZipOut.rawCloseEntry(); } catch ( ZipException& ) { VOS_ENSURE( 0, "Error writing ZipOutputStream" ); bWritingFailed = sal_True; } catch ( IOException& ) { VOS_ENSURE( 0, "Error writing ZipOutputStream" ); bWritingFailed = sal_True; } } for ( ContentHash::const_iterator aCI = maContents.begin(), aEnd = maContents.end(); aCI != aEnd; aCI++) { const OUString &rShortName = (*aCI).first; const ContentInfo &rInfo = *(*aCI).second; Sequence < PropertyValue > aPropSet (PKG_SIZE_NOENCR_MNFST); PropertyValue *pValue = aPropSet.getArray(); if ( rInfo.bFolder ) pFolder = rInfo.pFolder; else pStream = rInfo.pStream; if ( rInfo.bFolder ) { OUString sTempName = rPath + rShortName + OUString( RTL_CONSTASCII_USTRINGPARAM ( "/" ) ); pValue[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty; pValue[PKG_MNFST_MEDIATYPE].Value <<= pFolder->GetMediaType(); pValue[PKG_MNFST_VERSION].Name = sVersionProperty; pValue[PKG_MNFST_VERSION].Value <<= pFolder->GetVersion(); pValue[PKG_MNFST_FULLPATH].Name = sFullPathProperty; pValue[PKG_MNFST_FULLPATH].Value <<= sTempName; pFolder->saveContents( sTempName, rManList, rZipOut, rEncryptionKey, rRandomPool); } else { // if pTempEntry is necessary, it will be released and passed to the ZipOutputStream // and be deleted in the ZipOutputStream destructor auto_ptr < ZipEntry > pAutoTempEntry ( new ZipEntry ); ZipEntry* pTempEntry = pAutoTempEntry.get(); // In case the entry we are reading is also the entry we are writing, we will // store the ZipEntry data in pTempEntry ZipPackageFolder::copyZipEntry ( *pTempEntry, pStream->aEntry ); pTempEntry->sPath = rPath + rShortName; pTempEntry->nPathLen = (sal_Int16)( ::rtl::OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() ); sal_Bool bToBeEncrypted = pStream->IsToBeEncrypted() && (bHaveEncryptionKey || pStream->HasOwnKey()); sal_Bool bToBeCompressed = bToBeEncrypted ? sal_True : pStream->IsToBeCompressed(); pValue[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty; pValue[PKG_MNFST_MEDIATYPE].Value <<= pStream->GetMediaType( ); pValue[PKG_MNFST_VERSION].Name = sVersionProperty; pValue[PKG_MNFST_VERSION].Value <<= ::rtl::OUString(); // no version is stored for streams currently pValue[PKG_MNFST_FULLPATH].Name = sFullPathProperty; pValue[PKG_MNFST_FULLPATH].Value <<= pTempEntry->sPath; OSL_ENSURE( pStream->GetStreamMode() != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" ); sal_Bool bRawStream = sal_False; if ( pStream->GetStreamMode() == PACKAGE_STREAM_DETECT ) bRawStream = pStream->ParsePackageRawStream(); else if ( pStream->GetStreamMode() == PACKAGE_STREAM_RAW ) bRawStream = sal_True; sal_Bool bTransportOwnEncrStreamAsRaw = sal_False; // During the storing the original size of the stream can be changed // TODO/LATER: get rid of this hack sal_Int32 nOwnStreamOrigSize = bRawStream ? pStream->GetMagicalHackSize() : pStream->getSize(); sal_Bool bUseNonSeekableAccess = sal_False; Reference < XInputStream > xStream; if ( !pStream->IsPackageMember() && !bRawStream && !bToBeEncrypted && bToBeCompressed ) { // the stream is not a package member, not a raw stream, // it should not be encrypted and it should be compressed, // in this case nonseekable access can be used xStream = pStream->GetOwnStreamNoWrap(); Reference < XSeekable > xSeek ( xStream, UNO_QUERY ); bUseNonSeekableAccess = ( xStream.is() && !xSeek.is() ); } if ( !bUseNonSeekableAccess ) { xStream = pStream->getRawData(); if ( !xStream.is() ) { VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); bWritingFailed = sal_True; continue; } Reference < XSeekable > xSeek ( xStream, UNO_QUERY ); try { if ( xSeek.is() ) { // If the stream is a raw one, then we should be positioned // at the beginning of the actual data if ( !bToBeCompressed || bRawStream ) { // The raw stream can neither be encrypted nor connected OSL_ENSURE( !bRawStream || !bToBeCompressed && !bToBeEncrypted, "The stream is already encrypted!\n" ); xSeek->seek ( bRawStream ? pStream->GetMagicalHackPos() : 0 ); ImplSetStoredData ( *pTempEntry, xStream ); // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties! } else if ( bToBeEncrypted ) { // this is the correct original size pTempEntry->nSize = static_cast < sal_Int32 > ( xSeek->getLength() ); nOwnStreamOrigSize = pTempEntry->nSize; } xSeek->seek ( 0 ); } else { // Okay, we don't have an xSeekable stream. This is possibly bad. // check if it's one of our own streams, if it is then we know that // each time we ask for it we'll get a new stream that will be // at position zero...otherwise, assert and skip this stream... if ( pStream->IsPackageMember() ) { // if the password has been changed than the stream should not be package member any more if ( pStream->IsEncrypted() && pStream->IsToBeEncrypted() ) { // Should be handled close to the raw stream handling bTransportOwnEncrStreamAsRaw = sal_True; pTempEntry->nMethod = STORED; // TODO/LATER: get rid of this situation // this size should be different from the one that will be stored in manifest.xml // it is used in storing algorithms and after storing the correct size will be set pTempEntry->nSize = pTempEntry->nCompressedSize; } } else { VOS_ENSURE( 0, "The package component requires that every stream either be FROM a package or it must support XSeekable!" ); continue; } } } catch ( Exception& ) { VOS_ENSURE( 0, "The stream provided to the package component has problems!" ); bWritingFailed = sal_True; continue; } if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw ) { if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw ) { Sequence < sal_uInt8 > aSalt ( 16 ), aVector ( 8 ); rtl_random_getBytes ( rRandomPool, aSalt.getArray(), 16 ); rtl_random_getBytes ( rRandomPool, aVector.getArray(), 8 ); sal_Int32 nIterationCount = 1024; if ( !pStream->HasOwnKey() ) pStream->setKey ( rEncryptionKey ); pStream->setInitialisationVector ( aVector ); pStream->setSalt ( aSalt ); pStream->setIterationCount ( nIterationCount ); } // last property is digest, which is inserted later if we didn't have // a magic header aPropSet.realloc(PKG_SIZE_ENCR_MNFST); pValue = aPropSet.getArray(); pValue[PKG_MNFST_INIVECTOR].Name = sInitialisationVectorProperty; pValue[PKG_MNFST_INIVECTOR].Value <<= pStream->getInitialisationVector(); pValue[PKG_MNFST_SALT].Name = sSaltProperty; pValue[PKG_MNFST_SALT].Value <<= pStream->getSalt(); pValue[PKG_MNFST_ITERATION].Name = sIterationCountProperty; pValue[PKG_MNFST_ITERATION].Value <<= pStream->getIterationCount (); // Need to store the uncompressed size in the manifest OSL_ENSURE( nOwnStreamOrigSize >= 0, "The stream size was not correctly initialized!\n" ); pValue[PKG_MNFST_UCOMPSIZE].Name = sSizeProperty; pValue[PKG_MNFST_UCOMPSIZE].Value <<= nOwnStreamOrigSize; if ( bRawStream || bTransportOwnEncrStreamAsRaw ) { pValue[PKG_MNFST_DIGEST].Name = sDigestProperty; pValue[PKG_MNFST_DIGEST].Value <<= pStream->getDigest(); } } } // If the entry is already stored in the zip file in the format we // want for this write...copy it raw if ( !bUseNonSeekableAccess && ( bRawStream || bTransportOwnEncrStreamAsRaw || ( pStream->IsPackageMember() && !bToBeEncrypted && ( ( pStream->aEntry.nMethod == DEFLATED && bToBeCompressed ) || ( pStream->aEntry.nMethod == STORED && !bToBeCompressed ) ) ) ) ) { // If it's a PackageMember, then it's an unbuffered stream and we need // to get a new version of it as we can't seek backwards. if ( pStream->IsPackageMember() ) { xStream = pStream->getRawData(); if ( !xStream.is() ) { // Make sure that we actually _got_ a new one ! VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); continue; } } try { if ( bRawStream ) xStream->skipBytes( pStream->GetMagicalHackPos() ); rZipOut.putNextEntry ( *pTempEntry, pStream->getEncryptionData(), sal_False ); // the entry is provided to the ZipOutputStream that will delete it pAutoTempEntry.release(); Sequence < sal_Int8 > aSeq ( n_ConstBufferSize ); sal_Int32 nLength; do { nLength = xStream->readBytes( aSeq, n_ConstBufferSize ); rZipOut.rawWrite(aSeq, 0, nLength); } while ( nLength == n_ConstBufferSize ); rZipOut.rawCloseEntry(); } catch ( ZipException& ) { VOS_ENSURE( 0, "Error writing ZipOutputStream" ); bWritingFailed = sal_True; } catch ( IOException& ) { VOS_ENSURE( 0, "Error writing ZipOutputStream" ); bWritingFailed = sal_True; } } else { // This stream is defenitly not a raw stream // If nonseekable access is used the stream should be at the beginning and // is useless after the storing. Thus if the storing fails the package should // be thrown away ( as actually it is done currently )! // To allow to reuse the package after the error, the optimization must be removed! // If it's a PackageMember, then our previous reference held a 'raw' stream // so we need to re-get it, unencrypted, uncompressed and positioned at the // beginning of the stream if ( pStream->IsPackageMember() ) { xStream = pStream->getInputStream(); if ( !xStream.is() ) { // Make sure that we actually _got_ a new one ! VOS_ENSURE( 0, "ZipPackageStream didn't have a stream associated with it, skipping!" ); continue; } } if ( bToBeCompressed ) { pTempEntry->nMethod = DEFLATED; pTempEntry->nCrc = pTempEntry->nCompressedSize = pTempEntry->nSize = -1; } try { rZipOut.putNextEntry ( *pTempEntry, pStream->getEncryptionData(), bToBeEncrypted); // the entry is provided to the ZipOutputStream that will delete it pAutoTempEntry.release(); sal_Int32 nLength; Sequence < sal_Int8 > aSeq (n_ConstBufferSize); do { nLength = xStream->readBytes(aSeq, n_ConstBufferSize); rZipOut.write(aSeq, 0, nLength); } while ( nLength == n_ConstBufferSize ); rZipOut.closeEntry(); } catch ( ZipException& ) { VOS_ENSURE( 0, "Error writing ZipOutputStream" ); bWritingFailed = sal_True; } catch ( IOException& ) { VOS_ENSURE( 0, "Error writing ZipOutputStream" ); bWritingFailed = sal_True; } if ( bToBeEncrypted ) { pValue[PKG_MNFST_DIGEST].Name = sDigestProperty; pValue[PKG_MNFST_DIGEST].Value <<= pStream->getDigest(); pStream->SetIsEncrypted ( sal_True ); } } if( !bWritingFailed ) { if ( !pStream->IsPackageMember() ) { pStream->CloseOwnStreamIfAny(); pStream->SetPackageMember ( sal_True ); } if ( bRawStream ) { // the raw stream was integrated and now behaves // as usual encrypted stream pStream->SetToBeEncrypted( sal_True ); } // Remove hacky bit from entry flags if ( pTempEntry->nFlag & ( 1 << 4 ) ) { pTempEntry->nFlag &= ~( 1 << 4 ); pTempEntry->nMethod = STORED; } // Then copy it back afterwards... ZipPackageFolder::copyZipEntry ( pStream->aEntry, *pTempEntry ); // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving ) if ( pStream->IsEncrypted() ) pStream->setSize( nOwnStreamOrigSize ); pStream->aEntry.nOffset *= -1; } } // folder can have a mediatype only in package format if ( m_nFormat == embed::StorageFormats::PACKAGE || ( m_nFormat == embed::StorageFormats::OFOPXML && !rInfo.bFolder ) ) rManList.push_back( aPropSet ); } if( bWritingFailed ) throw RuntimeException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); } void ZipPackageFolder::releaseUpwardRef( void ) { // Now it is possible that a package folder is disconnected from the package before removing of the folder. // Such a scenario is used in storage implementation. When a new version of a folder is provided the old // one is retrieved, removed from the package but preserved for the error handling. // In this scenario the referencing to the parent is not really useful, since it requires disposing. // Actually there is no need in having a reference to the parent, it even make things more complicated and // requires disposing mechanics. Using of a simple pointer seems to be easier solution and also a safe enough. clearParent(); #if 0 for ( ContentHash::const_iterator aCI = maContents.begin(); aCI!=maContents.end(); aCI++) { ContentInfo &rInfo = * (*aCI).second; if ( rInfo.bFolder )// && ! rInfo.pFolder->HasReleased () ) rInfo.pFolder->releaseUpwardRef(); else //if ( !rInfo.bFolder && !rInfo.pStream->HasReleased() ) rInfo.pStream->clearParent(); } clearParent(); VOS_ENSURE ( m_refCount == 1, "Ref-count is not 1!" ); #endif } sal_Int64 SAL_CALL ZipPackageFolder::getSomething( const Sequence< sal_Int8 >& aIdentifier ) throw(RuntimeException) { sal_Int64 nMe = 0; if ( aIdentifier.getLength() == 16 && 0 == rtl_compareMemory(static_getImplementationId().getConstArray(), aIdentifier.getConstArray(), 16 ) ) nMe = reinterpret_cast < sal_Int64 > ( this ); return nMe; } void SAL_CALL ZipPackageFolder::setPropertyValue( const OUString& aPropertyName, const Any& aValue ) throw(UnknownPropertyException, PropertyVetoException, IllegalArgumentException, WrappedTargetException, RuntimeException) { if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("MediaType"))) { // TODO/LATER: activate 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 >() ); aValue >>= sMediaType; } else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Version"))) aValue >>= m_sVersion; else if (aPropertyName.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("Size") ) ) aValue >>= aEntry.nSize; else throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); } Any SAL_CALL ZipPackageFolder::getPropertyValue( const OUString& PropertyName ) throw(UnknownPropertyException, WrappedTargetException, RuntimeException) { if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM( "MediaType" ) ) ) { // TODO/LATER: activate 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 >() ); return makeAny ( sMediaType ); } else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Version" ) ) ) return makeAny( m_sVersion ); else if (PropertyName.equalsAsciiL( RTL_CONSTASCII_STRINGPARAM ( "Size" ) ) ) return makeAny ( aEntry.nSize ); else throw UnknownPropertyException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() ); } void ZipPackageFolder::doInsertByName ( ZipPackageEntry *pEntry, sal_Bool bSetParent ) throw(IllegalArgumentException, ElementExistException, WrappedTargetException, RuntimeException) { try { if ( pEntry->IsFolder() ) maContents[pEntry->getName()] = new ContentInfo ( static_cast < ZipPackageFolder *> ( pEntry ) ); else maContents[pEntry->getName()] = new ContentInfo ( static_cast < ZipPackageStream *> ( pEntry ) ); } catch(const uno::Exception& rEx) { (void)rEx; throw; } if ( bSetParent ) pEntry->setParent ( *this ); } OUString ZipPackageFolder::getImplementationName() throw (RuntimeException) { return OUString ( RTL_CONSTASCII_USTRINGPARAM ( "ZipPackageFolder" ) ); } Sequence< OUString > ZipPackageFolder::getSupportedServiceNames() throw (RuntimeException) { Sequence< OUString > aNames(1); aNames[0] = OUString( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.packages.PackageFolder" ) ); return aNames; } sal_Bool SAL_CALL ZipPackageFolder::supportsService( OUString const & rServiceName ) throw (RuntimeException) { return rServiceName == getSupportedServiceNames()[0]; }