diff options
author | Matúš Kukan <matus.kukan@collabora.com> | 2014-10-09 15:22:54 +0200 |
---|---|---|
committer | Matúš Kukan <matus.kukan@collabora.com> | 2014-10-23 14:30:30 +0200 |
commit | 3a8bddc18e4218210f74a9b0192f1528536a58a2 (patch) | |
tree | bdb7e732477621386a05b22224f04e875d44d613 /package | |
parent | 0c24faee6b622971d7d8f989da36029200cbd2a5 (diff) |
package: Add ZipOutputEntry to isolate deflating of streams.
Preparation commit for deflating streams in parallel.
We still use the same single XOutputStream (ByteChucker :-) for
sequential writing but this can now be changed more easily.
Change-Id: Idf26cc2187461660e31ac2e12c4708e761596fb2
Diffstat (limited to 'package')
-rw-r--r-- | package/Library_package2.mk | 1 | ||||
-rw-r--r-- | package/inc/ZipOutputEntry.hxx | 79 | ||||
-rw-r--r-- | package/inc/ZipOutputStream.hxx | 49 | ||||
-rw-r--r-- | package/inc/ZipPackageFolder.hxx | 5 | ||||
-rw-r--r-- | package/source/zipapi/ZipOutputEntry.cxx | 367 | ||||
-rw-r--r-- | package/source/zipapi/ZipOutputStream.cxx | 351 | ||||
-rw-r--r-- | package/source/zippackage/ZipPackage.cxx | 36 | ||||
-rw-r--r-- | package/source/zippackage/ZipPackageFolder.cxx | 31 |
8 files changed, 504 insertions, 415 deletions
diff --git a/package/Library_package2.mk b/package/Library_package2.mk index 269cf812921e..f563d0a0c0cc 100644 --- a/package/Library_package2.mk +++ b/package/Library_package2.mk @@ -55,6 +55,7 @@ $(eval $(call gb_Library_add_exception_objects,package2,\ package/source/zipapi/XUnbufferedStream \ package/source/zipapi/ZipEnumeration \ package/source/zipapi/ZipFile \ + package/source/zipapi/ZipOutputEntry \ package/source/zipapi/ZipOutputStream \ package/source/zippackage/wrapstreamforshare \ package/source/zippackage/zipfileaccess \ diff --git a/package/inc/ZipOutputEntry.hxx b/package/inc/ZipOutputEntry.hxx new file mode 100644 index 000000000000..a1d03d3ebc40 --- /dev/null +++ b/package/inc/ZipOutputEntry.hxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_PACKAGE_INC_ZIPOUTPUTENTRY_HXX +#define INCLUDED_PACKAGE_INC_ZIPOUTPUTENTRY_HXX + +#include <com/sun/star/uno/Reference.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <com/sun/star/xml/crypto/XCipherContext.hpp> +#include <com/sun/star/xml/crypto/XDigestContext.hpp> + +#include <package/Deflater.hxx> +#include <ByteChucker.hxx> +#include <CRC32.hxx> + +struct ZipEntry; +class ZipPackageStream; + +class ZipOutputEntry +{ + ::com::sun::star::uno::Sequence< sal_Int8 > m_aDeflateBuffer; + ZipUtils::Deflater m_aDeflater; + + ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XCipherContext > m_xCipherContext; + ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XDigestContext > m_xDigestContext; + + CRC32 m_aCRC; + ByteChucker &m_rChucker; + ZipEntry *m_pCurrentEntry; + sal_Int16 m_nDigested; + bool m_bEncryptCurrentEntry; + ZipPackageStream* m_pCurrentStream; + +public: + ZipOutputEntry( + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, + ByteChucker& rChucker, ZipEntry& rEntry, ZipPackageStream* pStream, bool bEncrypt = false); + + ~ZipOutputEntry(); + + // rawWrite to support a direct write to the output stream + void SAL_CALL rawWrite( ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength ) + throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + void SAL_CALL rawCloseEntry( ) + throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + + // XZipOutputEntry interfaces + void SAL_CALL closeEntry( ) + throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + void SAL_CALL write( const ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength ) + throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + static sal_uInt32 getCurrentDosTime ( ); + +private: + void doDeflate(); + sal_Int32 writeLOC( const ZipEntry &rEntry ) + throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + void writeEXT( const ZipEntry &rEntry ) + throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); +}; + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/inc/ZipOutputStream.hxx b/package/inc/ZipOutputStream.hxx index 146e6427eebe..95c27f3a959a 100644 --- a/package/inc/ZipOutputStream.hxx +++ b/package/inc/ZipOutputStream.hxx @@ -21,75 +21,36 @@ #include <com/sun/star/uno/Reference.hxx> #include <com/sun/star/io/XOutputStream.hpp> -#include <com/sun/star/xml/crypto/XCipherContext.hpp> -#include <com/sun/star/xml/crypto/XDigestContext.hpp> -#include <package/Deflater.hxx> #include <ByteChucker.hxx> -#include <CRC32.hxx> #include <vector> struct ZipEntry; -class ZipPackageStream; class ZipOutputStream { -protected: - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext> m_xContext; ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > m_xStream; - ::std::vector < ZipEntry * > m_aZipList; - ::com::sun::star::uno::Sequence< sal_Int8 > m_aDeflateBuffer; - - OUString m_sComment; - ZipUtils::Deflater m_aDeflater; - - ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XCipherContext > m_xCipherContext; - ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XDigestContext > m_xDigestContext; - - CRC32 m_aCRC; ByteChucker m_aChucker; - ZipEntry *m_pCurrentEntry; - sal_Int16 m_nDigested; - bool m_bFinished, m_bEncryptCurrentEntry; - ZipPackageStream* m_pCurrentStream; + bool m_bFinished; public: ZipOutputStream( - const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext, const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > &xOStream ); ~ZipOutputStream(); - // rawWrite to support a direct write to the output stream - void SAL_CALL rawWrite( ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - void SAL_CALL rawCloseEntry( ) + void addEntry( ZipEntry *pZipEntry ); + void finish() throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); + ByteChucker& getChucker(); - // XZipOutputStream interfaces - void SAL_CALL putNextEntry( ZipEntry& rEntry, - ZipPackageStream* pStream, - bool bEncrypt = false ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - void SAL_CALL closeEntry( ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - void SAL_CALL write( const ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - void SAL_CALL finish( ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - static sal_uInt32 getCurrentDosTime ( ); -protected: - void doDeflate(); +private: void writeEND(sal_uInt32 nOffset, sal_uInt32 nLength) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); void writeCEN( const ZipEntry &rEntry ) throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - void writeEXT( const ZipEntry &rEntry ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); - sal_Int32 writeLOC( const ZipEntry &rEntry ) - throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException); }; #endif diff --git a/package/inc/ZipPackageFolder.hxx b/package/inc/ZipPackageFolder.hxx index 6053b48d844e..dd0ff95ba8ad 100644 --- a/package/inc/ZipPackageFolder.hxx +++ b/package/inc/ZipPackageFolder.hxx @@ -22,6 +22,7 @@ #include <com/sun/star/container/XNameContainer.hpp> #include <com/sun/star/container/XEnumerationAccess.hpp> #include <com/sun/star/beans/StringPair.hpp> +#include <com/sun/star/uno/XComponentContext.hpp> #include <HashMaps.hxx> #include <ZipPackageEntry.hxx> #include <cppuhelper/implbase2.hxx> @@ -50,13 +51,15 @@ class ZipPackageFolder : public cppu::ImplInheritanceHelper2 > { private: + css::uno::Reference< css::uno::XComponentContext> m_xContext; ContentHash maContents; sal_Int32 m_nFormat; OUString m_sVersion; public: - ZipPackageFolder( sal_Int32 nFormat, + ZipPackageFolder( css::uno::Reference< css::uno::XComponentContext> xContext, + sal_Int32 nFormat, bool bAllowRemoveOnInsert ); virtual ~ZipPackageFolder(); diff --git a/package/source/zipapi/ZipOutputEntry.cxx b/package/source/zipapi/ZipOutputEntry.cxx new file mode 100644 index 000000000000..a3e3cc8bb72f --- /dev/null +++ b/package/source/zipapi/ZipOutputEntry.cxx @@ -0,0 +1,367 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <ZipOutputEntry.hxx> + +#include <com/sun/star/packages/zip/ZipConstants.hpp> +#include <comphelper/storagehelper.hxx> + +#include <osl/time.h> + +#include <PackageConstants.hxx> +#include <ZipEntry.hxx> +#include <ZipFile.hxx> +#include <ZipPackageStream.hxx> + +using namespace com::sun::star; +using namespace com::sun::star::io; +using namespace com::sun::star::uno; +using namespace com::sun::star::packages::zip::ZipConstants; + +/** This class is used to deflate Zip entries + */ +ZipOutputEntry::ZipOutputEntry( const uno::Reference< uno::XComponentContext >& rxContext, + ByteChucker& rChucker, + ZipEntry& rEntry, + ZipPackageStream* pStream, + bool bEncrypt) +: m_aDeflateBuffer(n_ConstBufferSize) +, m_aDeflater(DEFAULT_COMPRESSION, true) +, m_rChucker(rChucker) +, m_pCurrentEntry(&rEntry) +, m_nDigested(0) +, m_bEncryptCurrentEntry(false) +, m_pCurrentStream(NULL) +{ + if (rEntry.nTime == -1) + rEntry.nTime = getCurrentDosTime(); + if (rEntry.nMethod == -1) + rEntry.nMethod = DEFLATED; + rEntry.nVersion = 20; + rEntry.nFlag = 1 << 11; + if (rEntry.nSize == -1 || rEntry.nCompressedSize == -1 || + rEntry.nCrc == -1) + { + rEntry.nSize = rEntry.nCompressedSize = 0; + rEntry.nFlag |= 8; + } + + if (bEncrypt) + { + m_bEncryptCurrentEntry = true; + + m_xCipherContext = ZipFile::StaticGetCipher( rxContext, pStream->GetEncryptionData(), true ); + m_xDigestContext = ZipFile::StaticGetDigestContextForChecksum( rxContext, pStream->GetEncryptionData() ); + m_nDigested = 0; + rEntry.nFlag |= 1 << 4; + m_pCurrentStream = pStream; + } + sal_Int32 nLOCLength = writeLOC(rEntry); + rEntry.nOffset = m_rChucker.GetPosition() - nLOCLength; +} + +ZipOutputEntry::~ZipOutputEntry( void ) +{ +} + +void SAL_CALL ZipOutputEntry::closeEntry( ) + throw(IOException, RuntimeException) +{ + ZipEntry *pEntry = m_pCurrentEntry; + if (pEntry) + { + switch (pEntry->nMethod) + { + case DEFLATED: + m_aDeflater.finish(); + while (!m_aDeflater.finished()) + doDeflate(); + if ((pEntry->nFlag & 8) == 0) + { + if (pEntry->nSize != m_aDeflater.getTotalIn()) + { + OSL_FAIL("Invalid entry size"); + } + if (pEntry->nCompressedSize != m_aDeflater.getTotalOut()) + { + // Different compression strategies make the merit of this + // test somewhat dubious + pEntry->nCompressedSize = m_aDeflater.getTotalOut(); + } + if (pEntry->nCrc != m_aCRC.getValue()) + { + OSL_FAIL("Invalid entry CRC-32"); + } + } + else + { + if ( !m_bEncryptCurrentEntry ) + { + pEntry->nSize = m_aDeflater.getTotalIn(); + pEntry->nCompressedSize = m_aDeflater.getTotalOut(); + } + pEntry->nCrc = m_aCRC.getValue(); + writeEXT(*pEntry); + } + m_aDeflater.reset(); + m_aCRC.reset(); + break; + case STORED: + if (!((pEntry->nFlag & 8) == 0)) + OSL_FAIL( "Serious error, one of compressed size, size or CRC was -1 in a STORED stream"); + break; + default: + OSL_FAIL("Invalid compression method"); + break; + } + + if (m_bEncryptCurrentEntry) + { + m_bEncryptCurrentEntry = false; + + m_xCipherContext.clear(); + + uno::Sequence< sal_Int8 > aDigestSeq; + if ( m_xDigestContext.is() ) + { + aDigestSeq = m_xDigestContext->finalizeDigestAndDispose(); + m_xDigestContext.clear(); + } + + if ( m_pCurrentStream ) + m_pCurrentStream->setDigest( aDigestSeq ); + } + m_pCurrentEntry = NULL; + m_pCurrentStream = NULL; + } +} + +void SAL_CALL ZipOutputEntry::write( const Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength ) + throw(IOException, RuntimeException) +{ + switch (m_pCurrentEntry->nMethod) + { + case DEFLATED: + if (!m_aDeflater.finished()) + { + m_aDeflater.setInputSegment(rBuffer, nNewOffset, nNewLength); + while (!m_aDeflater.needsInput()) + doDeflate(); + if (!m_bEncryptCurrentEntry) + m_aCRC.updateSegment(rBuffer, nNewOffset, nNewLength); + } + break; + case STORED: + { + Sequence < sal_Int8 > aTmpBuffer ( rBuffer.getConstArray(), nNewLength ); + m_rChucker.WriteBytes( aTmpBuffer ); + } + break; + } +} + +void SAL_CALL ZipOutputEntry::rawWrite( Sequence< sal_Int8 >& rBuffer, sal_Int32 /*nNewOffset*/, sal_Int32 nNewLength ) + throw(IOException, RuntimeException) +{ + Sequence < sal_Int8 > aTmpBuffer ( rBuffer.getConstArray(), nNewLength ); + m_rChucker.WriteBytes( aTmpBuffer ); +} + +void SAL_CALL ZipOutputEntry::rawCloseEntry( ) + throw(IOException, RuntimeException) +{ + if ( m_pCurrentEntry->nMethod == DEFLATED && ( m_pCurrentEntry->nFlag & 8 ) ) + writeEXT(*m_pCurrentEntry); + m_pCurrentEntry = NULL; +} + +void ZipOutputEntry::doDeflate() +{ + sal_Int32 nLength = m_aDeflater.doDeflateSegment(m_aDeflateBuffer, 0, m_aDeflateBuffer.getLength()); + + if ( nLength > 0 ) + { + uno::Sequence< sal_Int8 > aTmpBuffer( m_aDeflateBuffer.getConstArray(), nLength ); + if ( m_bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is() ) + { + // Need to update our digest before encryption... + sal_Int32 nDiff = n_ConstDigestLength - m_nDigested; + if ( nDiff ) + { + sal_Int32 nEat = ::std::min( nLength, nDiff ); + uno::Sequence< sal_Int8 > aTmpSeq( aTmpBuffer.getConstArray(), nEat ); + m_xDigestContext->updateDigest( aTmpSeq ); + m_nDigested = m_nDigested + static_cast< sal_Int16 >( nEat ); + } + + // FIXME64: uno::Sequence not 64bit safe. + uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->convertWithCipherContext( aTmpBuffer ); + + m_rChucker.WriteBytes( aEncryptionBuffer ); + + // the sizes as well as checksum for encrypted streams is calculated here + m_pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength(); + m_pCurrentEntry->nSize = m_pCurrentEntry->nCompressedSize; + m_aCRC.update( aEncryptionBuffer ); + } + else + { + m_rChucker.WriteBytes ( aTmpBuffer ); + } + } + + if ( m_aDeflater.finished() && m_bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is() ) + { + // FIXME64: sequence not 64bit safe. + uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->finalizeCipherContextAndDispose(); + if ( aEncryptionBuffer.getLength() ) + { + m_rChucker.WriteBytes( aEncryptionBuffer ); + + // the sizes as well as checksum for encrypted streams is calculated hier + m_pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength(); + m_pCurrentEntry->nSize = m_pCurrentEntry->nCompressedSize; + m_aCRC.update( aEncryptionBuffer ); + } + } +} + +static sal_uInt32 getTruncated( sal_Int64 nNum, bool *pIsTruncated ) +{ + if( nNum >= 0xffffffff ) + { + *pIsTruncated = true; + return 0xffffffff; + } + else + return static_cast< sal_uInt32 >( nNum ); +} + +void ZipOutputEntry::writeEXT( const ZipEntry &rEntry ) + throw(IOException, RuntimeException) +{ + bool bWrite64Header = false; + + m_rChucker << EXTSIG; + m_rChucker << static_cast < sal_uInt32> ( rEntry.nCrc ); + m_rChucker << getTruncated( rEntry.nCompressedSize, &bWrite64Header ); + m_rChucker << getTruncated( rEntry.nSize, &bWrite64Header ); + + if( bWrite64Header ) + { + // FIXME64: need to append a ZIP64 header instead of throwing + // We're about to silently lose people's data - which they are + // unlikely to appreciate so fail instead: + throw IOException( "File contains streams that are too large." ); + } +} + +sal_Int32 ZipOutputEntry::writeLOC( const ZipEntry &rEntry ) + throw(IOException, RuntimeException) +{ + if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( rEntry.sPath, true ) ) + throw IOException("Unexpected character is used in file name." ); + + OString sUTF8Name = OUStringToOString( rEntry.sPath, RTL_TEXTENCODING_UTF8 ); + sal_Int16 nNameLength = static_cast < sal_Int16 > ( sUTF8Name.getLength() ); + + m_rChucker << LOCSIG; + m_rChucker << rEntry.nVersion; + + if (rEntry.nFlag & (1 << 4) ) + { + // If it's an encrypted entry, we pretend its stored plain text + sal_Int16 nTmpFlag = rEntry.nFlag; + nTmpFlag &= ~(1 <<4 ); + m_rChucker << nTmpFlag; + m_rChucker << static_cast < sal_Int16 > ( STORED ); + } + else + { + m_rChucker << rEntry.nFlag; + m_rChucker << rEntry.nMethod; + } + + bool bWrite64Header = false; + + m_rChucker << static_cast < sal_uInt32 > (rEntry.nTime); + if ((rEntry.nFlag & 8) == 8 ) + { + m_rChucker << static_cast < sal_Int32 > (0); + m_rChucker << static_cast < sal_Int32 > (0); + m_rChucker << static_cast < sal_Int32 > (0); + } + else + { + m_rChucker << static_cast < sal_uInt32 > (rEntry.nCrc); + m_rChucker << getTruncated( rEntry.nCompressedSize, &bWrite64Header ); + m_rChucker << getTruncated( rEntry.nSize, &bWrite64Header ); + } + m_rChucker << nNameLength; + m_rChucker << static_cast < sal_Int16 > (0); + + if( bWrite64Header ) + { + // FIXME64: need to append a ZIP64 header instead of throwing + // We're about to silently lose people's data - which they are + // unlikely to appreciate so fail instead: + throw IOException( "File contains streams that are too large." ); + } + + Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() ); + m_rChucker.WriteBytes( aSequence ); + + return LOCHDR + nNameLength; +} +sal_uInt32 ZipOutputEntry::getCurrentDosTime( ) +{ + oslDateTime aDateTime; + TimeValue aTimeValue; + osl_getSystemTime ( &aTimeValue ); + osl_getDateTimeFromTimeValue( &aTimeValue, &aDateTime); + + // at year 2108, there is an overflow + // -> some decision needs to be made + // how to handle the ZIP file format (just overflow?) + + // if the current system time is before 1980, + // then the time traveller will have to make a decision + // how to handle the ZIP file format before it is invented + // (just underflow?) + + assert(aDateTime.Year > 1980 && aDateTime.Year < 2108); + + sal_uInt32 nYear = static_cast <sal_uInt32> (aDateTime.Year); + + if (nYear>=1980) + nYear-=1980; + else if (nYear>=80) + { + nYear-=80; + } + sal_uInt32 nResult = static_cast < sal_uInt32>( ( ( ( aDateTime.Day) + + ( 32 * (aDateTime.Month)) + + ( 512 * nYear ) ) << 16) | + ( ( aDateTime.Seconds/2) + + ( 32 * aDateTime.Minutes) + + ( 2048 * static_cast <sal_uInt32 > (aDateTime.Hours) ) ) ); + return nResult; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx index 34f097921e75..7cd5acdb5c7b 100644 --- a/package/source/zipapi/ZipOutputStream.cxx +++ b/package/source/zipapi/ZipOutputStream.cxx @@ -17,18 +17,14 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <ZipOutputStream.hxx> + #include <com/sun/star/packages/zip/ZipConstants.hpp> #include <com/sun/star/io/XOutputStream.hpp> #include <comphelper/storagehelper.hxx> -#include <osl/time.h> - -#include <EncryptionData.hxx> #include <PackageConstants.hxx> #include <ZipEntry.hxx> -#include <ZipFile.hxx> -#include <ZipPackageStream.hxx> -#include <ZipOutputStream.hxx> using namespace com::sun::star; using namespace com::sun::star::io; @@ -37,18 +33,10 @@ using namespace com::sun::star::packages::zip::ZipConstants; /** This class is used to write Zip files */ -ZipOutputStream::ZipOutputStream( const uno::Reference< uno::XComponentContext >& rxContext, - const uno::Reference < XOutputStream > &xOStream ) -: m_xContext( rxContext ) -, m_xStream(xOStream) -, m_aDeflateBuffer(n_ConstBufferSize) -, m_aDeflater(DEFAULT_COMPRESSION, true) +ZipOutputStream::ZipOutputStream( const uno::Reference < io::XOutputStream > &xOStream ) +: m_xStream(xOStream) , m_aChucker(xOStream) -, m_pCurrentEntry(NULL) -, m_nDigested(0) , m_bFinished(false) -, m_bEncryptCurrentEntry(false) -, m_pCurrentStream(NULL) { } @@ -58,162 +46,17 @@ ZipOutputStream::~ZipOutputStream( void ) delete m_aZipList[i]; } -void SAL_CALL ZipOutputStream::putNextEntry( ZipEntry& rEntry, - ZipPackageStream* pStream, - bool bEncrypt) - throw(IOException, RuntimeException) -{ - if (m_pCurrentEntry != NULL) - closeEntry(); - if (rEntry.nTime == -1) - rEntry.nTime = getCurrentDosTime(); - if (rEntry.nMethod == -1) - rEntry.nMethod = DEFLATED; - rEntry.nVersion = 20; - rEntry.nFlag = 1 << 11; - if (rEntry.nSize == -1 || rEntry.nCompressedSize == -1 || - rEntry.nCrc == -1) - { - rEntry.nSize = rEntry.nCompressedSize = 0; - rEntry.nFlag |= 8; - } - - if (bEncrypt) - { - m_bEncryptCurrentEntry = true; - - m_xCipherContext = ZipFile::StaticGetCipher( m_xContext, pStream->GetEncryptionData(), true ); - m_xDigestContext = ZipFile::StaticGetDigestContextForChecksum( m_xContext, pStream->GetEncryptionData() ); - m_nDigested = 0; - rEntry.nFlag |= 1 << 4; - m_pCurrentStream = pStream; - } - sal_Int32 nLOCLength = writeLOC(rEntry); - rEntry.nOffset = m_aChucker.GetPosition() - nLOCLength; - m_aZipList.push_back( &rEntry ); - m_pCurrentEntry = &rEntry; -} - -void SAL_CALL ZipOutputStream::closeEntry( ) - throw(IOException, RuntimeException) -{ - ZipEntry *pEntry = m_pCurrentEntry; - if (pEntry) - { - switch (pEntry->nMethod) - { - case DEFLATED: - m_aDeflater.finish(); - while (!m_aDeflater.finished()) - doDeflate(); - if ((pEntry->nFlag & 8) == 0) - { - if (pEntry->nSize != m_aDeflater.getTotalIn()) - { - OSL_FAIL("Invalid entry size"); - } - if (pEntry->nCompressedSize != m_aDeflater.getTotalOut()) - { - // Different compression strategies make the merit of this - // test somewhat dubious - pEntry->nCompressedSize = m_aDeflater.getTotalOut(); - } - if (pEntry->nCrc != m_aCRC.getValue()) - { - OSL_FAIL("Invalid entry CRC-32"); - } - } - else - { - if ( !m_bEncryptCurrentEntry ) - { - pEntry->nSize = m_aDeflater.getTotalIn(); - pEntry->nCompressedSize = m_aDeflater.getTotalOut(); - } - pEntry->nCrc = m_aCRC.getValue(); - writeEXT(*pEntry); - } - m_aDeflater.reset(); - m_aCRC.reset(); - break; - case STORED: - if (!((pEntry->nFlag & 8) == 0)) - OSL_FAIL( "Serious error, one of compressed size, size or CRC was -1 in a STORED stream"); - break; - default: - OSL_FAIL("Invalid compression method"); - break; - } - - if (m_bEncryptCurrentEntry) - { - m_bEncryptCurrentEntry = false; - - m_xCipherContext.clear(); - - uno::Sequence< sal_Int8 > aDigestSeq; - if ( m_xDigestContext.is() ) - { - aDigestSeq = m_xDigestContext->finalizeDigestAndDispose(); - m_xDigestContext.clear(); - } - - if ( m_pCurrentStream ) - m_pCurrentStream->setDigest( aDigestSeq ); - } - m_pCurrentEntry = NULL; - m_pCurrentStream = NULL; - } -} - -void SAL_CALL ZipOutputStream::write( const Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength ) - throw(IOException, RuntimeException) -{ - switch (m_pCurrentEntry->nMethod) - { - case DEFLATED: - if (!m_aDeflater.finished()) - { - m_aDeflater.setInputSegment(rBuffer, nNewOffset, nNewLength); - while (!m_aDeflater.needsInput()) - doDeflate(); - if (!m_bEncryptCurrentEntry) - m_aCRC.updateSegment(rBuffer, nNewOffset, nNewLength); - } - break; - case STORED: - { - Sequence < sal_Int8 > aTmpBuffer ( rBuffer.getConstArray(), nNewLength ); - m_aChucker.WriteBytes( aTmpBuffer ); - } - break; - } -} - -void SAL_CALL ZipOutputStream::rawWrite( Sequence< sal_Int8 >& rBuffer, sal_Int32 /*nNewOffset*/, sal_Int32 nNewLength ) - throw(IOException, RuntimeException) +void ZipOutputStream::addEntry( ZipEntry *pZipEntry ) { - Sequence < sal_Int8 > aTmpBuffer ( rBuffer.getConstArray(), nNewLength ); - m_aChucker.WriteBytes( aTmpBuffer ); + m_aZipList.push_back( pZipEntry ); } -void SAL_CALL ZipOutputStream::rawCloseEntry( ) - throw(IOException, RuntimeException) -{ - if ( m_pCurrentEntry->nMethod == DEFLATED && ( m_pCurrentEntry->nFlag & 8 ) ) - writeEXT(*m_pCurrentEntry); - m_pCurrentEntry = NULL; -} - -void SAL_CALL ZipOutputStream::finish( ) +void ZipOutputStream::finish( ) throw(IOException, RuntimeException) { if (m_bFinished) return; - if (m_pCurrentEntry != NULL) - closeEntry(); - if (m_aZipList.size() < 1) OSL_FAIL("Zip file must have at least one entry!\n"); @@ -225,55 +68,9 @@ void SAL_CALL ZipOutputStream::finish( ) m_xStream->flush(); } -void ZipOutputStream::doDeflate() +ByteChucker& ZipOutputStream::getChucker() { - sal_Int32 nLength = m_aDeflater.doDeflateSegment(m_aDeflateBuffer, 0, m_aDeflateBuffer.getLength()); - - if ( nLength > 0 ) - { - uno::Sequence< sal_Int8 > aTmpBuffer( m_aDeflateBuffer.getConstArray(), nLength ); - if ( m_bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is() ) - { - // Need to update our digest before encryption... - sal_Int32 nDiff = n_ConstDigestLength - m_nDigested; - if ( nDiff ) - { - sal_Int32 nEat = ::std::min( nLength, nDiff ); - uno::Sequence< sal_Int8 > aTmpSeq( aTmpBuffer.getConstArray(), nEat ); - m_xDigestContext->updateDigest( aTmpSeq ); - m_nDigested = m_nDigested + static_cast< sal_Int16 >( nEat ); - } - - // FIXME64: uno::Sequence not 64bit safe. - uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->convertWithCipherContext( aTmpBuffer ); - - m_aChucker.WriteBytes( aEncryptionBuffer ); - - // the sizes as well as checksum for encrypted streams is calculated here - m_pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength(); - m_pCurrentEntry->nSize = m_pCurrentEntry->nCompressedSize; - m_aCRC.update( aEncryptionBuffer ); - } - else - { - m_aChucker.WriteBytes ( aTmpBuffer ); - } - } - - if ( m_aDeflater.finished() && m_bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is() ) - { - // FIXME64: sequence not 64bit safe. - uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->finalizeCipherContextAndDispose(); - if ( aEncryptionBuffer.getLength() ) - { - m_aChucker.WriteBytes( aEncryptionBuffer ); - - // the sizes as well as checksum for encrypted streams is calculated hier - m_pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength(); - m_pCurrentEntry->nSize = m_pCurrentEntry->nCompressedSize; - m_aCRC.update( aEncryptionBuffer ); - } - } + return m_aChucker; } void ZipOutputStream::writeEND(sal_uInt32 nOffset, sal_uInt32 nLength) @@ -350,135 +147,5 @@ void ZipOutputStream::writeCEN( const ZipEntry &rEntry ) Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() ); m_aChucker.WriteBytes( aSequence ); } -void ZipOutputStream::writeEXT( const ZipEntry &rEntry ) - throw(IOException, RuntimeException) -{ - bool bWrite64Header = false; - - m_aChucker << EXTSIG; - m_aChucker << static_cast < sal_uInt32> ( rEntry.nCrc ); - m_aChucker << getTruncated( rEntry.nCompressedSize, &bWrite64Header ); - m_aChucker << getTruncated( rEntry.nSize, &bWrite64Header ); - - if( bWrite64Header ) - { - // FIXME64: need to append a ZIP64 header instead of throwing - // We're about to silently lose people's data - which they are - // unlikely to appreciate so fail instead: - throw IOException( "File contains streams that are too large." ); - } -} - -sal_Int32 ZipOutputStream::writeLOC( const ZipEntry &rEntry ) - throw(IOException, RuntimeException) -{ - if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( rEntry.sPath, true ) ) - throw IOException("Unexpected character is used in file name." ); - - OString sUTF8Name = OUStringToOString( rEntry.sPath, RTL_TEXTENCODING_UTF8 ); - sal_Int16 nNameLength = static_cast < sal_Int16 > ( sUTF8Name.getLength() ); - - m_aChucker << LOCSIG; - m_aChucker << rEntry.nVersion; - - if (rEntry.nFlag & (1 << 4) ) - { - // If it's an encrypted entry, we pretend its stored plain text - sal_Int16 nTmpFlag = rEntry.nFlag; - nTmpFlag &= ~(1 <<4 ); - m_aChucker << nTmpFlag; - m_aChucker << static_cast < sal_Int16 > ( STORED ); - } - else - { - m_aChucker << rEntry.nFlag; - m_aChucker << rEntry.nMethod; - } - - bool bWrite64Header = false; - - m_aChucker << static_cast < sal_uInt32 > (rEntry.nTime); - if ((rEntry.nFlag & 8) == 8 ) - { - m_aChucker << static_cast < sal_Int32 > (0); - m_aChucker << static_cast < sal_Int32 > (0); - m_aChucker << static_cast < sal_Int32 > (0); - } - else - { - m_aChucker << static_cast < sal_uInt32 > (rEntry.nCrc); - m_aChucker << getTruncated( rEntry.nCompressedSize, &bWrite64Header ); - m_aChucker << getTruncated( rEntry.nSize, &bWrite64Header ); - } - m_aChucker << nNameLength; - m_aChucker << static_cast < sal_Int16 > (0); - - if( bWrite64Header ) - { - // FIXME64: need to append a ZIP64 header instead of throwing - // We're about to silently lose people's data - which they are - // unlikely to appreciate so fail instead: - throw IOException( "File contains streams that are too large." ); - } - - Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() ); - m_aChucker.WriteBytes( aSequence ); - - return LOCHDR + nNameLength; -} -sal_uInt32 ZipOutputStream::getCurrentDosTime( ) -{ - oslDateTime aDateTime; - TimeValue aTimeValue; - osl_getSystemTime ( &aTimeValue ); - osl_getDateTimeFromTimeValue( &aTimeValue, &aDateTime); - - // at year 2108, there is an overflow - // -> some decision needs to be made - // how to handle the ZIP file format (just overflow?) - - // if the current system time is before 1980, - // then the time traveller will have to make a decision - // how to handle the ZIP file format before it is invented - // (just underflow?) - - assert(aDateTime.Year > 1980 && aDateTime.Year < 2108); - - sal_uInt32 nYear = static_cast <sal_uInt32> (aDateTime.Year); - - if (nYear>=1980) - nYear-=1980; - else if (nYear>=80) - { - nYear-=80; - } - sal_uInt32 nResult = static_cast < sal_uInt32>( ( ( ( aDateTime.Day) + - ( 32 * (aDateTime.Month)) + - ( 512 * nYear ) ) << 16) | - ( ( aDateTime.Seconds/2) + - ( 32 * aDateTime.Minutes) + - ( 2048 * static_cast <sal_uInt32 > (aDateTime.Hours) ) ) ); - return nResult; -} -/* - - This is actually never used, so I removed it, but thought that the - implementation details may be useful in the future...mtg 20010307 - - I stopped using the time library and used the OSL version instead, but - it might still be useful to have this code here.. - -void ZipOutputStream::dosDateToTMDate ( tm &rTime, sal_uInt32 nDosDate) -{ - sal_uInt32 nDate = static_cast < sal_uInt32 > (nDosDate >> 16); - rTime.tm_mday = static_cast < sal_uInt32 > ( nDate & 0x1F); - rTime.tm_mon = static_cast < sal_uInt32 > ( ( ( (nDate) & 0x1E0)/0x20)-1); - rTime.tm_year = static_cast < sal_uInt32 > ( ( (nDate & 0x0FE00)/0x0200)+1980); - - rTime.tm_hour = static_cast < sal_uInt32 > ( (nDosDate & 0xF800)/0x800); - rTime.tm_min = static_cast < sal_uInt32 > ( (nDosDate & 0x7E0)/0x20); - rTime.tm_sec = static_cast < sal_uInt32 > ( 2 * (nDosDate & 0x1F) ); -} -*/ /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx index 3bc0627aa619..0a26c5a2591d 100644 --- a/package/source/zippackage/ZipPackage.cxx +++ b/package/source/zippackage/ZipPackage.cxx @@ -22,6 +22,7 @@ #include <ZipEnumeration.hxx> #include <ZipPackageStream.hxx> #include <ZipPackageFolder.hxx> +#include <ZipOutputEntry.hxx> #include <ZipOutputStream.hxx> #include <ZipPackageBuffer.hxx> #include <ZipFile.hxx> @@ -156,7 +157,7 @@ ZipPackage::ZipPackage ( const uno::Reference < XComponentContext > &xContext ) , m_pRootFolder( NULL ) , m_pZipFile( NULL ) { - m_xRootFolder = m_pRootFolder = new ZipPackageFolder( m_nFormat, m_bAllowRemoveOnInsert ); + m_xRootFolder = m_pRootFolder = new ZipPackageFolder( m_xContext, m_nFormat, m_bAllowRemoveOnInsert ); } ZipPackage::~ZipPackage( void ) @@ -539,7 +540,7 @@ void ZipPackage::getZipFileContents() break; if ( !pCurrent->hasByName( sTemp ) ) { - pPkgFolder = new ZipPackageFolder( m_nFormat, m_bAllowRemoveOnInsert ); + pPkgFolder = new ZipPackageFolder( m_xContext, m_nFormat, m_bAllowRemoveOnInsert ); pPkgFolder->setName( sTemp ); pPkgFolder->doSetParent( pCurrent, true ); pCurrent = pPkgFolder; @@ -953,7 +954,7 @@ uno::Reference< XInterface > SAL_CALL ZipPackage::createInstanceWithArguments( c if ( aArguments.getLength() ) aArguments[0] >>= bArg; if ( bArg ) - xRef = *new ZipPackageFolder ( m_nFormat, m_bAllowRemoveOnInsert ); + xRef = *new ZipPackageFolder ( m_xContext, m_nFormat, m_bAllowRemoveOnInsert ); else xRef = *new ZipPackageStream ( *this, m_xContext, m_bAllowRemoveOnInsert ); @@ -975,7 +976,7 @@ void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut ) pEntry->sPath = sMime; pEntry->nMethod = STORED; pEntry->nSize = pEntry->nCompressedSize = nBufferLength; - pEntry->nTime = ZipOutputStream::getCurrentDosTime(); + pEntry->nTime = ZipOutputEntry::getCurrentDosTime(); CRC32 aCRC32; aCRC32.update( aType ); @@ -983,9 +984,10 @@ void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut ) try { - aZipOut.putNextEntry( *pEntry, NULL ); - aZipOut.write( aType, 0, nBufferLength ); - aZipOut.closeEntry(); + ZipOutputEntry aZipEntry(m_xContext, aZipOut.getChucker(), *pEntry, NULL); + aZipEntry.write(aType, 0, nBufferLength); + aZipEntry.closeEntry(); + aZipOut.addEntry(pEntry); } catch ( const ::com::sun::star::io::IOException & r ) { @@ -1008,7 +1010,7 @@ void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< uno::Seq pEntry->nMethod = DEFLATED; pEntry->nCrc = -1; pEntry->nSize = pEntry->nCompressedSize = -1; - pEntry->nTime = ZipOutputStream::getCurrentDosTime(); + pEntry->nTime = ZipOutputEntry::getCurrentDosTime(); // Convert vector into a uno::Sequence uno::Sequence < uno::Sequence < PropertyValue > > aManifestSequence ( aManList.size() ); @@ -1025,9 +1027,10 @@ void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< uno::Seq 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(); + ZipOutputEntry aZipEntry(m_xContext, aZipOut.getChucker(), *pEntry, NULL); + aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength); + aZipEntry.closeEntry(); + aZipOut.addEntry(pEntry); } void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno::Sequence < PropertyValue > >& aManList ) @@ -1040,7 +1043,7 @@ void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno: pEntry->nMethod = DEFLATED; pEntry->nCrc = -1; pEntry->nSize = pEntry->nCompressedSize = -1; - pEntry->nTime = ZipOutputStream::getCurrentDosTime(); + pEntry->nTime = ZipOutputEntry::getCurrentDosTime(); // Convert vector into a uno::Sequence // TODO/LATER: use Defaulst entries in future @@ -1075,9 +1078,10 @@ void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno: pBuffer->realloc( nBufferLength ); // there is no encryption in this format currently - aZipOut.putNextEntry( *pEntry, NULL ); - aZipOut.write( pBuffer->getSequence(), 0, nBufferLength ); - aZipOut.closeEntry(); + ZipOutputEntry aZipEntry(m_xContext, aZipOut.getChucker(), *pEntry, NULL); + aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength); + aZipEntry.closeEntry(); + aZipOut.addEntry(pEntry); } void ZipPackage::ConnectTo( const uno::Reference< io::XInputStream >& xInStream ) @@ -1138,7 +1142,7 @@ uno::Reference< io::XInputStream > ZipPackage::writeTempFile() } // Hand it to the ZipOutputStream: - ZipOutputStream aZipOut( m_xContext, xTempOut ); + ZipOutputStream aZipOut( xTempOut ); try { if ( m_nFormat == embed::StorageFormats::PACKAGE ) diff --git a/package/source/zippackage/ZipPackageFolder.cxx b/package/source/zippackage/ZipPackageFolder.cxx index c0baf907bbf6..c6a3b372a399 100644 --- a/package/source/zippackage/ZipPackageFolder.cxx +++ b/package/source/zippackage/ZipPackageFolder.cxx @@ -21,6 +21,7 @@ #include <ZipPackageFolder.hxx> #include <ZipFile.hxx> +#include <ZipOutputEntry.hxx> #include <ZipOutputStream.hxx> #include <ZipPackageStream.hxx> #include <PackageConstants.hxx> @@ -60,9 +61,11 @@ using namespace ::com::sun::star; namespace { struct lcl_CachedImplId : public rtl::Static< cppu::OImplementationId, lcl_CachedImplId > {}; } -ZipPackageFolder::ZipPackageFolder ( sal_Int32 nFormat, +ZipPackageFolder::ZipPackageFolder ( css::uno::Reference< css::uno::XComponentContext> xContext, + sal_Int32 nFormat, bool bAllowRemoveOnInsert ) -: m_nFormat( nFormat ) + : m_xContext( xContext ) + , m_nFormat( nFormat ) { this->mbAllowRemoveOnInsert = bAllowRemoveOnInsert; @@ -338,6 +341,7 @@ static bool ZipPackageFolder_saveChild( } static bool ZipPackageStream_saveChild( + css::uno::Reference< css::uno::XComponentContext> xContext, const ContentInfo &rInfo, const OUString &rPath, std::vector < uno::Sequence < PropertyValue > > &rManList, @@ -563,7 +567,7 @@ static bool ZipPackageStream_saveChild( if ( bRawStream ) xStream->skipBytes( rInfo.pStream->GetMagicalHackPos() ); - rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, false ); + ZipOutputEntry aZipEntry(xContext, rZipOut.getChucker(), *pTempEntry, rInfo.pStream, false); // the entry is provided to the ZipOutputStream that will delete it pAutoTempEntry.release(); @@ -573,11 +577,12 @@ static bool ZipPackageStream_saveChild( do { nLength = xStream->readBytes( aSeq, n_ConstBufferSize ); - rZipOut.rawWrite(aSeq, 0, nLength); + aZipEntry.rawWrite(aSeq, 0, nLength); } while ( nLength == n_ConstBufferSize ); - rZipOut.rawCloseEntry(); + aZipEntry.rawCloseEntry(); + rZipOut.addEntry(pTempEntry); } catch ( ZipException& ) { @@ -620,7 +625,7 @@ static bool ZipPackageStream_saveChild( try { - rZipOut.putNextEntry ( *pTempEntry, rInfo.pStream, bToBeEncrypted); + ZipOutputEntry aZipEntry(xContext, rZipOut.getChucker(), *pTempEntry, rInfo.pStream, bToBeEncrypted); // the entry is provided to the ZipOutputStream that will delete it pAutoTempEntry.release(); @@ -629,11 +634,12 @@ static bool ZipPackageStream_saveChild( do { nLength = xStream->readBytes(aSeq, n_ConstBufferSize); - rZipOut.write(aSeq, 0, nLength); + aZipEntry.write(aSeq, 0, nLength); } while ( nLength == n_ConstBufferSize ); - rZipOut.closeEntry(); + aZipEntry.closeEntry(); + rZipOut.addEntry(pTempEntry); } catch ( ZipException& ) { @@ -726,8 +732,9 @@ void ZipPackageFolder::saveContents( try { - rZipOut.putNextEntry( *pTempEntry, NULL, false ); - rZipOut.rawCloseEntry(); + ZipOutputEntry aZipEntry(m_xContext, rZipOut.getChucker(), *pTempEntry, NULL, false); + aZipEntry.rawCloseEntry(); + rZipOut.addEntry(pTempEntry); } catch ( ZipException& ) { @@ -748,7 +755,7 @@ void ZipPackageFolder::saveContents( if ( aIter != maContents.end() && !(*aIter).second->bFolder ) { bMimeTypeStreamStored = true; - bWritingFailed = !ZipPackageStream_saveChild( + bWritingFailed = !ZipPackageStream_saveChild( m_xContext, *aIter->second, rPath + aIter->first, rManList, rZipOut, rEncryptionKey, rRandomPool, m_nFormat ); } } @@ -769,7 +776,7 @@ void ZipPackageFolder::saveContents( } else { - bWritingFailed = !ZipPackageStream_saveChild( + bWritingFailed = !ZipPackageStream_saveChild( m_xContext, rInfo, rPath + rShortName, rManList, rZipOut, rEncryptionKey, rRandomPool, m_nFormat ); } } |