[Libreoffice-commits] core.git: 14 commits - filter/source include/package package/inc package/source

Matúš Kukan matus.kukan at collabora.com
Mon Nov 17 01:49:46 PST 2014


 filter/source/xsltfilter/OleHandler.cxx          |    2 
 include/package/Deflater.hxx                     |    1 
 package/inc/CRC32.hxx                            |    2 
 package/inc/ZipOutputEntry.hxx                   |   29 --
 package/inc/ZipOutputStream.hxx                  |   23 +
 package/inc/ZipPackageFolder.hxx                 |    1 
 package/inc/ZipPackageStream.hxx                 |   11 
 package/source/zipapi/CRC32.cxx                  |    7 
 package/source/zipapi/Deflater.cxx               |    8 
 package/source/zipapi/ZipFile.cxx                |    4 
 package/source/zipapi/ZipOutputEntry.cxx         |  307 ++++-------------------
 package/source/zipapi/ZipOutputStream.cxx        |  204 +++++++++++++--
 package/source/zippackage/ContentInfo.hxx        |    2 
 package/source/zippackage/ZipPackage.cxx         |   34 +-
 package/source/zippackage/ZipPackageFolder.cxx   |   36 --
 package/source/zippackage/ZipPackageStream.cxx   |  194 ++++++++++----
 package/source/zippackage/wrapstreamforshare.cxx |    4 
 17 files changed, 441 insertions(+), 428 deletions(-)

New commits:
commit 0843ade74e5848c0babad509b10c334b01847be2
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Wed Nov 12 21:25:55 2014 +0100

    package: Do not bother with deflating jpeg images
    
    It takes a lot of time and we can save ~1% of size if at all. Rather
    store them uncompressed in the zip file.
    With png, we can save a bit more, although it's still only about 4% - 8%?
    
    Change-Id: I43a3e3812882e4ce85e7af9d0aaab454d98c4860

diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index 5eaa6e951..64b48d3 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -773,6 +773,14 @@ bool ZipPackageStream::saveChild(
             pTempEntry->nCompressedSize = pTempEntry->nSize = -1;
         }
 
+        uno::Reference< io::XSeekable > xSeek(xStream, uno::UNO_QUERY);
+        // It's not worth to deflate jpegs to save ~1% in a slow process
+        if (xSeek.is() && msMediaType.endsWith("/jpeg"))
+        {
+            ImplSetStoredData(*pTempEntry, xStream);
+            xSeek->seek(0);
+        }
+
         try
         {
             ZipOutputStream::setEntry(pTempEntry);
@@ -799,7 +807,6 @@ bool ZipPackageStream::saveChild(
             {
                 bParallelDeflate = true;
                 // Do not deflate small streams in a thread
-                uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY );
                 if (xSeek.is() && xSeek->getLength() < 100000)
                     bParallelDeflate = false;
 
commit d09b6209f1f374b6069089d8583c9ee373e3c1e5
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Tue Nov 4 09:18:57 2014 +0100

    package: Do not deflate small streams in a thread
    
    Change-Id: Iae804a34f344aa793a6d5c13315f7bc1eb64c0a2

diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index 90f0df8..5eaa6e951 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -798,6 +798,11 @@ bool ZipPackageStream::saveChild(
             else
             {
                 bParallelDeflate = true;
+                // Do not deflate small streams in a thread
+                uno::Reference< io::XSeekable > xSeek( xStream, uno::UNO_QUERY );
+                if (xSeek.is() && xSeek->getLength() < 100000)
+                    bParallelDeflate = false;
+
                 if (bParallelDeflate)
                 {
                     // Start a new thread deflating this zip entry
commit 062cf187026f55001ab4661b89242d13c6ed71d7
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Tue Oct 28 20:58:29 2014 +0100

    ZipPackageStream::getRawData can be private
    
    Change-Id: I66cbbfb2aa6abc6c8ebe34d9ea69855436c23edd

diff --git a/package/inc/ZipPackageStream.hxx b/package/inc/ZipPackageStream.hxx
index ff6d3db..af2c721 100644
--- a/package/inc/ZipPackageStream.hxx
+++ b/package/inc/ZipPackageStream.hxx
@@ -71,7 +71,10 @@ private:
     bool m_bUseWinEncoding;
     bool m_bRawStream;
 
+    /// Check that m_xStream implements io::XSeekable and return it
     ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetOwnSeekStream();
+    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawData()
+        throw(::com::sun::star::uno::RuntimeException);
 
 public:
     bool IsEncrypted () const    { return m_bIsEncrypted;}
@@ -135,8 +138,6 @@ public:
                             const rtlRandomPool &rRandomPool ) SAL_OVERRIDE;
 
     void setZipEntryOnLoading( const ZipEntry &rInEntry);
-    ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawData()
-        throw(::com::sun::star::uno::RuntimeException);
     void successfullyWritten( ZipEntry *pEntry );
 
     static ::com::sun::star::uno::Sequence < sal_Int8 > static_getImplementationId();
commit 7088166a67d1270f93ac15bccbc89343b2271fa5
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Mon Oct 27 14:26:54 2014 +0100

    Simplify input parameters to just take the sequence
    
    Change-Id: Ic2538ca8b0f7261064e1dfbf3884dd452003c797

diff --git a/filter/source/xsltfilter/OleHandler.cxx b/filter/source/xsltfilter/OleHandler.cxx
index edd0678..14ef6bd 100644
--- a/filter/source/xsltfilter/OleHandler.cxx
+++ b/filter/source/xsltfilter/OleHandler.cxx
@@ -197,7 +197,7 @@ namespace XSLT
         // Compress the bytes
         Sequence<sal_Int8> output(oledata.getLength());
         boost::scoped_ptr< ::ZipUtils::Deflater> compresser(new ::ZipUtils::Deflater((sal_Int32) 3, false));
-        compresser->setInputSegment(oledata, 0, oledata.getLength());
+        compresser->setInputSegment(oledata);
         compresser->finish();
         int compressedDataLength = compresser->doDeflateSegment(output, 0, oledata.getLength());
         compresser.reset();
diff --git a/include/package/Deflater.hxx b/include/package/Deflater.hxx
index bd6d815..d2be247 100644
--- a/include/package/Deflater.hxx
+++ b/include/package/Deflater.hxx
@@ -46,6 +46,7 @@ public:
     ~Deflater();
     Deflater(sal_Int32 nSetLevel, bool bNowrap);
     void SAL_CALL setInputSegment( const ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength );
+    void SAL_CALL setInputSegment( const ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer );
     bool SAL_CALL needsInput(  );
     void SAL_CALL finish(  );
     bool SAL_CALL finished(  ) { return bFinished;}
diff --git a/package/inc/CRC32.hxx b/package/inc/CRC32.hxx
index daaf4b5..cfc66c4 100644
--- a/package/inc/CRC32.hxx
+++ b/package/inc/CRC32.hxx
@@ -35,7 +35,7 @@ public:
 
     sal_Int64 SAL_CALL updateStream (::com::sun::star::uno::Reference < ::com::sun::star::io::XInputStream > & xStream)
         throw(::com::sun::star::uno::RuntimeException);
-    void SAL_CALL updateSegment(const ::com::sun::star::uno::Sequence< sal_Int8 > &b, sal_Int32 off, sal_Int32 len)
+    void SAL_CALL updateSegment(const ::com::sun::star::uno::Sequence< sal_Int8 > &b, sal_Int32 len)
         throw(::com::sun::star::uno::RuntimeException);
     void SAL_CALL update(const ::com::sun::star::uno::Sequence< sal_Int8 > &b)
         throw(::com::sun::star::uno::RuntimeException);
diff --git a/package/inc/ZipOutputEntry.hxx b/package/inc/ZipOutputEntry.hxx
index 9e396ce..26ebb15 100644
--- a/package/inc/ZipOutputEntry.hxx
+++ b/package/inc/ZipOutputEntry.hxx
@@ -59,7 +59,7 @@ public:
     bool isEncrypt() { return m_bEncryptCurrentEntry; }
 
     void closeEntry();
-    void write(const css::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength);
+    void write(const css::uno::Sequence< sal_Int8 >& rBuffer);
 
 private:
     void doDeflate();
diff --git a/package/inc/ZipOutputStream.hxx b/package/inc/ZipOutputStream.hxx
index 4e8e4ff..acf6dc4 100644
--- a/package/inc/ZipOutputStream.hxx
+++ b/package/inc/ZipOutputStream.hxx
@@ -50,7 +50,7 @@ public:
 
     void writeLOC( ZipEntry *pEntry, bool bEncrypt = false )
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
-    void rawWrite( ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
+    void rawWrite( const css::uno::Sequence< sal_Int8 >& rBuffer )
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
     void rawCloseEntry( bool bEncrypt = false )
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
diff --git a/package/source/zipapi/CRC32.cxx b/package/source/zipapi/CRC32.cxx
index 6aee4d5..39b4f4c 100644
--- a/package/source/zipapi/CRC32.cxx
+++ b/package/source/zipapi/CRC32.cxx
@@ -47,11 +47,10 @@ sal_Int32 SAL_CALL CRC32::getValue()
 }
 /** Update CRC32 with specified sequence of bytes
  */
-void SAL_CALL CRC32::updateSegment(const Sequence< sal_Int8 > &b,
-                                   sal_Int32 off, sal_Int32 len)
+void SAL_CALL CRC32::updateSegment(const Sequence< sal_Int8 > &b, sal_Int32 len)
         throw(RuntimeException)
 {
-    nCRC = rtl_crc32(nCRC, b.getConstArray()+off, len );
+    nCRC = rtl_crc32(nCRC, b.getConstArray(), len );
 }
 /** Update CRC32 with specified sequence of bytes
  */
@@ -70,7 +69,7 @@ sal_Int64 SAL_CALL CRC32::updateStream( Reference < XInputStream > & xStream )
     do
     {
         nLength = xStream->readBytes ( aSeq, n_ConstBufferSize );
-        updateSegment ( aSeq, 0, nLength );
+        updateSegment ( aSeq, nLength );
         nTotal += nLength;
     }
     while ( nLength == n_ConstBufferSize );
diff --git a/package/source/zipapi/Deflater.cxx b/package/source/zipapi/Deflater.cxx
index a76362f..42628d7 100644
--- a/package/source/zipapi/Deflater.cxx
+++ b/package/source/zipapi/Deflater.cxx
@@ -92,13 +92,11 @@ sal_Int32 Deflater::doDeflateBytes (uno::Sequence < sal_Int8 > &rBuffer, sal_Int
     }
 }
 
-void SAL_CALL Deflater::setInputSegment( const uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
+void SAL_CALL Deflater::setInputSegment( const uno::Sequence< sal_Int8 >& rBuffer )
 {
-    OSL_ASSERT( !(nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > rBuffer.getLength()));
-
     sInBuffer = rBuffer;
-    nOffset = nNewOffset;
-    nLength = nNewLength;
+    nOffset = 0;
+    nLength = rBuffer.getLength();
 }
 
 bool SAL_CALL Deflater::needsInput(  )
diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx
index 839a1c4..1fd536f 100644
--- a/package/source/zipapi/ZipFile.cxx
+++ b/package/source/zipapi/ZipFile.cxx
@@ -1073,7 +1073,7 @@ sal_Int32 ZipFile::getCRC( sal_Int64 nOffset, sal_Int64 nSize )
          ++ind)
     {
         sal_Int64 nLen = ::std::min(nBlockSize, nSize - ind * nBlockSize);
-        aCRC.updateSegment(aBuffer, 0, static_cast<sal_Int32>(nLen));
+        aCRC.updateSegment(aBuffer, static_cast<sal_Int32>(nLen));
     }
 
     return aCRC.getValue();
@@ -1102,7 +1102,7 @@ void ZipFile::getSizeAndCRC( sal_Int64 nOffset, sal_Int64 nCompressedSize, sal_I
         do
         {
             nLastInflated = aInflaterLocal.doInflateSegment( aData, 0, nBlockSize );
-            aCRC.updateSegment( aData, 0, nLastInflated );
+            aCRC.updateSegment( aData, nLastInflated );
             nInBlock += nLastInflated;
         } while( !aInflater.finished() && nLastInflated );
 
diff --git a/package/source/zipapi/ZipOutputEntry.cxx b/package/source/zipapi/ZipOutputEntry.cxx
index a5fbe25..54600d59 100644
--- a/package/source/zipapi/ZipOutputEntry.cxx
+++ b/package/source/zipapi/ZipOutputEntry.cxx
@@ -118,15 +118,15 @@ void ZipOutputEntry::closeEntry()
     }
 }
 
-void ZipOutputEntry::write( const Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
+void ZipOutputEntry::write( const Sequence< sal_Int8 >& rBuffer )
 {
     if (!m_aDeflater.finished())
     {
-        m_aDeflater.setInputSegment(rBuffer, nNewOffset, nNewLength);
+        m_aDeflater.setInputSegment(rBuffer);
          while (!m_aDeflater.needsInput())
             doDeflate();
         if (!m_bEncryptCurrentEntry)
-            m_aCRC.updateSegment(rBuffer, nNewOffset, nNewLength);
+            m_aCRC.updateSegment(rBuffer, rBuffer.getLength());
     }
 }
 
diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx
index fcfe35f..902816e 100644
--- a/package/source/zipapi/ZipOutputStream.cxx
+++ b/package/source/zipapi/ZipOutputStream.cxx
@@ -71,10 +71,10 @@ void ZipOutputStream::addDeflatingThread( ZipOutputEntry *pEntry, comphelper::Th
     m_aEntries.push_back(pEntry);
 }
 
-void ZipOutputStream::rawWrite( Sequence< sal_Int8 >& rBuffer, sal_Int32 /*nNewOffset*/, sal_Int32 nNewLength )
+void ZipOutputStream::rawWrite( const Sequence< sal_Int8 >& rBuffer )
     throw(IOException, RuntimeException)
 {
-    m_aChucker.WriteBytes( Sequence< sal_Int8 >(rBuffer.getConstArray(), nNewLength) );
+    m_aChucker.WriteBytes( rBuffer );
 }
 
 void ZipOutputStream::rawCloseEntry( bool bEncrypt )
@@ -100,8 +100,7 @@ void ZipOutputStream::finish()
     for (size_t i = 0; i < m_aEntries.size(); i++)
     {
         writeLOC(m_aEntries[i]->getZipEntry(), m_aEntries[i]->isEncrypt());
-        uno::Sequence< sal_Int8 > aCompressedData = m_aEntries[i]->getData();
-        rawWrite(aCompressedData, 0, aCompressedData.getLength());
+        rawWrite(m_aEntries[i]->getData());
         rawCloseEntry(m_aEntries[i]->isEncrypt());
 
         m_aEntries[i]->getZipPackageStream()->successfullyWritten(m_aEntries[i]->getZipEntry());
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index 80d4d4f..2e64af8 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -983,7 +983,7 @@ void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut )
     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(),
+    const uno::Sequence< sal_Int8 > aType( ( sal_Int8* )sMediaType.getStr(),
                                      nBufferLength );
 
     pEntry->sPath = sMime;
@@ -999,7 +999,7 @@ void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut )
     {
         ZipOutputStream::setEntry(pEntry);
         aZipOut.writeLOC(pEntry);
-        aZipOut.rawWrite(aType, 0, nBufferLength);
+        aZipOut.rawWrite(aType);
         aZipOut.rawCloseEntry();
     }
     catch ( const ::com::sun::star::io::IOException & r )
@@ -1043,10 +1043,9 @@ void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< uno::Seq
     ZipOutputStream::setEntry(pEntry);
     aZipOut.writeLOC(pEntry);
     ZipOutputEntry aZipEntry(m_xContext, *pEntry, NULL);
-    aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength);
+    aZipEntry.write(pBuffer->getSequence());
     aZipEntry.closeEntry();
-    uno::Sequence< sal_Int8 > aCompressedData = aZipEntry.getData();
-    aZipOut.rawWrite(aCompressedData, 0, aCompressedData.getLength());
+    aZipOut.rawWrite(aZipEntry.getData());
     aZipOut.rawCloseEntry();
 }
 
@@ -1098,10 +1097,9 @@ void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno:
     ZipOutputStream::setEntry(pEntry);
     aZipOut.writeLOC(pEntry);
     ZipOutputEntry aZipEntry(m_xContext, *pEntry, NULL);
-    aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength);
+    aZipEntry.write(pBuffer->getSequence());
     aZipEntry.closeEntry();
-    uno::Sequence< sal_Int8 > aCompressedData = aZipEntry.getData();
-    aZipOut.rawWrite(aCompressedData, 0, aCompressedData.getLength());
+    aZipOut.rawWrite(aZipEntry.getData());
     aZipOut.rawCloseEntry();
 }
 
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index d5e0d62..90f0df8 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -447,7 +447,10 @@ static void deflateZipEntry(ZipOutputEntry *pZipEntry,
     do
     {
         nLength = xInStream->readBytes(aSeq, n_ConstBufferSize);
-        pZipEntry->write(aSeq, 0, nLength);
+        if (nLength != n_ConstBufferSize)
+            aSeq.realloc(nLength);
+
+        pZipEntry->write(aSeq);
     }
     while (nLength == n_ConstBufferSize);
     pZipEntry->closeEntry();
@@ -722,7 +725,10 @@ bool ZipPackageStream::saveChild(
             do
             {
                 nLength = xStream->readBytes( aSeq, n_ConstBufferSize );
-                rZipOut.rawWrite(aSeq, 0, nLength);
+                if (nLength != n_ConstBufferSize)
+                    aSeq.realloc(nLength);
+
+                rZipOut.rawWrite(aSeq);
             }
             while ( nLength == n_ConstBufferSize );
 
@@ -781,7 +787,10 @@ bool ZipPackageStream::saveChild(
                 do
                 {
                     nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
-                    rZipOut.rawWrite(aSeq, 0, nLength);
+                    if (nLength != n_ConstBufferSize)
+                        aSeq.realloc(nLength);
+
+                    rZipOut.rawWrite(aSeq);
                 }
                 while ( nLength == n_ConstBufferSize );
                 rZipOut.rawCloseEntry(bToBeEncrypted);
@@ -800,8 +809,7 @@ bool ZipPackageStream::saveChild(
                     rZipOut.writeLOC(pTempEntry, bToBeEncrypted);
                     ZipOutputEntry aZipEntry(m_xContext, *pTempEntry, this, bToBeEncrypted);
                     deflateZipEntry(&aZipEntry, xStream);
-                    uno::Sequence< sal_Int8 > aCompressedData = aZipEntry.getData();
-                    rZipOut.rawWrite(aCompressedData, 0, aCompressedData.getLength());
+                    rZipOut.rawWrite(aZipEntry.getData());
                     rZipOut.rawCloseEntry(bToBeEncrypted);
                 }
             }
commit a42aa52acbbff738a00299de172ca85cb001d840
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Fri Oct 24 14:43:06 2014 +0200

    package: Add possibility to disable deflating in a thread
    
    Change-Id: I4d98b6f8b3315b731206700eb65f08463299dda3

diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index 9f29a68..d5e0d62 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -439,6 +439,20 @@ bool ZipPackageStream::ParsePackageRawStream()
     return true;
 }
 
+static void deflateZipEntry(ZipOutputEntry *pZipEntry,
+        const uno::Reference< io::XInputStream >& xInStream)
+{
+    sal_Int32 nLength = 0;
+    uno::Sequence< sal_Int8 > aSeq(n_ConstBufferSize);
+    do
+    {
+        nLength = xInStream->readBytes(aSeq, n_ConstBufferSize);
+        pZipEntry->write(aSeq, 0, nLength);
+    }
+    while (nLength == n_ConstBufferSize);
+    pZipEntry->closeEntry();
+}
+
 class DeflateThread: public comphelper::ThreadTask
 {
     ZipOutputEntry *mpEntry;
@@ -454,16 +468,7 @@ public:
 private:
     virtual void doWork() SAL_OVERRIDE
     {
-        sal_Int32 nLength = 0;
-        uno::Sequence< sal_Int8 > aSeq(n_ConstBufferSize);
-        do
-        {
-            nLength = mxInStream->readBytes(aSeq, n_ConstBufferSize);
-            mpEntry->write(aSeq, 0, nLength);
-        }
-        while (nLength == n_ConstBufferSize);
-        mpEntry->closeEntry();
-
+        deflateZipEntry(mpEntry, mxInStream);
         mxInStream.clear();
     }
 };
@@ -784,9 +789,21 @@ bool ZipPackageStream::saveChild(
             else
             {
                 bParallelDeflate = true;
-                // Start a new thread deflating this zip entry
-                ZipOutputEntry *pZipEntry = new ZipOutputEntry(m_xContext, *pTempEntry, this, bToBeEncrypted);
-                rZipOut.addDeflatingThread( pZipEntry, new DeflateThread(pZipEntry, xStream) );
+                if (bParallelDeflate)
+                {
+                    // Start a new thread deflating this zip entry
+                    ZipOutputEntry *pZipEntry = new ZipOutputEntry(m_xContext, *pTempEntry, this, bToBeEncrypted);
+                    rZipOut.addDeflatingThread( pZipEntry, new DeflateThread(pZipEntry, xStream) );
+                }
+                else
+                {
+                    rZipOut.writeLOC(pTempEntry, bToBeEncrypted);
+                    ZipOutputEntry aZipEntry(m_xContext, *pTempEntry, this, bToBeEncrypted);
+                    deflateZipEntry(&aZipEntry, xStream);
+                    uno::Sequence< sal_Int8 > aCompressedData = aZipEntry.getData();
+                    rZipOut.rawWrite(aCompressedData, 0, aCompressedData.getLength());
+                    rZipOut.rawCloseEntry(bToBeEncrypted);
+                }
             }
         }
         catch ( ZipException& )
commit fbf714b45625c50bb1c736ef231b5dbbab0016a1
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Tue Oct 21 15:17:13 2014 +0200

    package: Finally implement parallel zip entries deflating
    
    For that:
    1, create ZipPackageStream::successfullyWritten to be called after
    the content is written
    2, Do not take mutex when reading from WrapStreamForShare - threads should
    be using different streams anyway, but there is only one common mutex. :-/
    
    Change-Id: I90303e49206b19454dd4141e24cc8be29c433045

diff --git a/package/inc/ZipOutputEntry.hxx b/package/inc/ZipOutputEntry.hxx
index c24d5a9..9e396ce 100644
--- a/package/inc/ZipOutputEntry.hxx
+++ b/package/inc/ZipOutputEntry.hxx
@@ -54,6 +54,9 @@ public:
     ~ZipOutputEntry();
 
     css::uno::Sequence< sal_Int8 > getData();
+    ZipEntry* getZipEntry() { return m_pCurrentEntry; }
+    ZipPackageStream* getZipPackageStream() { return m_pCurrentStream; }
+    bool isEncrypt() { return m_bEncryptCurrentEntry; }
 
     void closeEntry();
     void write(const css::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength);
diff --git a/package/inc/ZipOutputStream.hxx b/package/inc/ZipOutputStream.hxx
index f11b883..4e8e4ff 100644
--- a/package/inc/ZipOutputStream.hxx
+++ b/package/inc/ZipOutputStream.hxx
@@ -23,10 +23,12 @@
 #include <com/sun/star/io/XOutputStream.hpp>
 
 #include <ByteChucker.hxx>
+#include <comphelper/threadpool.hxx>
 
 #include <vector>
 
 struct ZipEntry;
+class ZipOutputEntry;
 class ZipPackageStream;
 
 class ZipOutputStream
@@ -35,14 +37,17 @@ class ZipOutputStream
     ::std::vector < ZipEntry * > m_aZipList;
 
     ByteChucker         m_aChucker;
-    bool                m_bFinished;
     ZipEntry            *m_pCurrentEntry;
+    comphelper::ThreadPool &m_rSharedThreadPool;
+    std::vector< ZipOutputEntry* > m_aEntries;
 
 public:
     ZipOutputStream(
         const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > &xOStream );
     ~ZipOutputStream();
 
+    void addDeflatingThread( ZipOutputEntry *pEntry, comphelper::ThreadTask *pThreadTask );
+
     void writeLOC( ZipEntry *pEntry, bool bEncrypt = false )
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
     void rawWrite( ::com::sun::star::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
diff --git a/package/inc/ZipPackageStream.hxx b/package/inc/ZipPackageStream.hxx
index 356d42b..ff6d3db 100644
--- a/package/inc/ZipPackageStream.hxx
+++ b/package/inc/ZipPackageStream.hxx
@@ -63,14 +63,13 @@ private:
     sal_uInt8   m_nStreamMode;
     sal_uInt32  m_nMagicalHackPos;
     sal_uInt32  m_nMagicalHackSize;
+    sal_Int64   m_nOwnStreamOrigSize;
 
     bool m_bHasSeekable;
-
     bool m_bCompressedIsSetFromOutside;
-
     bool m_bFromManifest;
-
     bool m_bUseWinEncoding;
+    bool m_bRawStream;
 
     ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > GetOwnSeekStream();
 
@@ -138,6 +137,7 @@ public:
     void setZipEntryOnLoading( const ZipEntry &rInEntry);
     ::com::sun::star::uno::Reference< ::com::sun::star::io::XInputStream > SAL_CALL getRawData()
         throw(::com::sun::star::uno::RuntimeException);
+    void successfullyWritten( ZipEntry *pEntry );
 
     static ::com::sun::star::uno::Sequence < sal_Int8 > static_getImplementationId();
 
diff --git a/package/source/zipapi/ZipOutputEntry.cxx b/package/source/zipapi/ZipOutputEntry.cxx
index f43b5c7..a5fbe25 100644
--- a/package/source/zipapi/ZipOutputEntry.cxx
+++ b/package/source/zipapi/ZipOutputEntry.cxx
@@ -47,14 +47,13 @@ ZipOutputEntry::ZipOutputEntry( const uno::Reference< uno::XComponentContext >&
 , m_pCurrentEntry(&rEntry)
 , m_nDigested(0)
 , m_bEncryptCurrentEntry(bEncrypt)
-, m_pCurrentStream(NULL)
+, m_pCurrentStream(pStream)
 {
     assert(m_pCurrentEntry->nMethod == DEFLATED && "Use ZipPackageStream::rawWrite() for STORED entries");
     if (m_bEncryptCurrentEntry)
     {
         m_xCipherContext = ZipFile::StaticGetCipher( rxContext, pStream->GetEncryptionData(), true );
         m_xDigestContext = ZipFile::StaticGetDigestContextForChecksum( rxContext, pStream->GetEncryptionData() );
-        m_pCurrentStream = pStream;
     }
 }
 
diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx
index c9b6e08..fcfe35f 100644
--- a/package/source/zipapi/ZipOutputStream.cxx
+++ b/package/source/zipapi/ZipOutputStream.cxx
@@ -27,6 +27,7 @@
 
 #include <PackageConstants.hxx>
 #include <ZipEntry.hxx>
+#include <ZipOutputEntry.hxx>
 #include <ZipPackageStream.hxx>
 
 using namespace com::sun::star;
@@ -39,15 +40,13 @@ using namespace com::sun::star::packages::zip::ZipConstants;
 ZipOutputStream::ZipOutputStream( const uno::Reference < io::XOutputStream > &xOStream )
 : m_xStream(xOStream)
 , m_aChucker(xOStream)
-, m_bFinished(false)
 , m_pCurrentEntry(NULL)
+, m_rSharedThreadPool(comphelper::ThreadPool::getSharedOptimalPool())
 {
 }
 
 ZipOutputStream::~ZipOutputStream( void )
 {
-    for (sal_Int32 i = 0, nEnd = m_aZipList.size(); i < nEnd; i++)
-        delete m_aZipList[i];
 }
 
 void ZipOutputStream::setEntry( ZipEntry *pEntry )
@@ -66,6 +65,12 @@ void ZipOutputStream::setEntry( ZipEntry *pEntry )
     }
 }
 
+void ZipOutputStream::addDeflatingThread( ZipOutputEntry *pEntry, comphelper::ThreadTask *pThread )
+{
+    m_rSharedThreadPool.pushTask(pThread);
+    m_aEntries.push_back(pEntry);
+}
+
 void ZipOutputStream::rawWrite( Sequence< sal_Int8 >& rBuffer, sal_Int32 /*nNewOffset*/, sal_Int32 nNewLength )
     throw(IOException, RuntimeException)
 {
@@ -85,21 +90,33 @@ void ZipOutputStream::rawCloseEntry( bool bEncrypt )
     m_pCurrentEntry = NULL;
 }
 
-void ZipOutputStream::finish(  )
+void ZipOutputStream::finish()
     throw(IOException, RuntimeException)
 {
-    if (m_bFinished)
-        return;
+    assert(!m_aZipList.empty() && "Zip file must have at least one entry!");
+
+    // Wait for all threads to finish & write
+    m_rSharedThreadPool.waitUntilEmpty();
+    for (size_t i = 0; i < m_aEntries.size(); i++)
+    {
+        writeLOC(m_aEntries[i]->getZipEntry(), m_aEntries[i]->isEncrypt());
+        uno::Sequence< sal_Int8 > aCompressedData = m_aEntries[i]->getData();
+        rawWrite(aCompressedData, 0, aCompressedData.getLength());
+        rawCloseEntry(m_aEntries[i]->isEncrypt());
 
-    if (m_aZipList.size() < 1)
-        OSL_FAIL("Zip file must have at least one entry!\n");
+        m_aEntries[i]->getZipPackageStream()->successfullyWritten(m_aEntries[i]->getZipEntry());
+        delete m_aEntries[i];
+    }
 
     sal_Int32 nOffset= static_cast < sal_Int32 > (m_aChucker.GetPosition());
-    for (sal_Int32 i =0, nEnd = m_aZipList.size(); i < nEnd; i++)
+    for (size_t i = 0; i < m_aZipList.size(); i++)
+    {
         writeCEN( *m_aZipList[i] );
+        delete m_aZipList[i];
+    }
     writeEND( nOffset, static_cast < sal_Int32 > (m_aChucker.GetPosition()) - nOffset);
-    m_bFinished = true;
     m_xStream->flush();
+    m_aZipList.clear();
 }
 
 void ZipOutputStream::writeEND(sal_uInt32 nOffset, sal_uInt32 nLength)
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index ca2ad01..9f29a68 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -90,10 +90,12 @@ ZipPackageStream::ZipPackageStream ( ZipPackage & rNewPackage,
 , m_nStreamMode( PACKAGE_STREAM_NOTSET )
 , m_nMagicalHackPos( 0 )
 , m_nMagicalHackSize( 0 )
+, m_nOwnStreamOrigSize( 0 )
 , m_bHasSeekable( false )
 , m_bCompressedIsSetFromOutside( false )
 , m_bFromManifest( false )
 , m_bUseWinEncoding( false )
+, m_bRawStream( false )
 {
     m_xContext = xContext;
     m_nFormat = nFormat;
@@ -437,6 +439,35 @@ bool ZipPackageStream::ParsePackageRawStream()
     return true;
 }
 
+class DeflateThread: public comphelper::ThreadTask
+{
+    ZipOutputEntry *mpEntry;
+    uno::Reference< io::XInputStream > mxInStream;
+
+public:
+    DeflateThread( ZipOutputEntry *pEntry,
+                   const uno::Reference< io::XInputStream >& xInStream )
+        : mpEntry(pEntry)
+        , mxInStream(xInStream)
+    {}
+
+private:
+    virtual void doWork() SAL_OVERRIDE
+    {
+        sal_Int32 nLength = 0;
+        uno::Sequence< sal_Int8 > aSeq(n_ConstBufferSize);
+        do
+        {
+            nLength = mxInStream->readBytes(aSeq, n_ConstBufferSize);
+            mpEntry->write(aSeq, 0, nLength);
+        }
+        while (nLength == n_ConstBufferSize);
+        mpEntry->closeEntry();
+
+        mxInStream.clear();
+    }
+};
+
 static void ImplSetStoredData( ZipEntry & rEntry, uno::Reference< io::XInputStream> & rStream )
 {
     // It's very annoying that we have to do this, but lots of zip packages
@@ -497,20 +528,21 @@ bool ZipPackageStream::saveChild(
 
     OSL_ENSURE( m_nStreamMode != PACKAGE_STREAM_NOTSET, "Unacceptable ZipPackageStream mode!" );
 
-    bool bRawStream = false;
+    m_bRawStream = false;
     if ( m_nStreamMode == PACKAGE_STREAM_DETECT )
-        bRawStream = ParsePackageRawStream();
+        m_bRawStream = ParsePackageRawStream();
     else if ( m_nStreamMode == PACKAGE_STREAM_RAW )
-        bRawStream = true;
+        m_bRawStream = true;
 
+    bool bParallelDeflate = false;
     bool bTransportOwnEncrStreamAsRaw = false;
     // During the storing the original size of the stream can be changed
     // TODO/LATER: get rid of this hack
-    sal_Int64 nOwnStreamOrigSize = bRawStream ? m_nMagicalHackSize : aEntry.nSize;
+    m_nOwnStreamOrigSize = m_bRawStream ? m_nMagicalHackSize : aEntry.nSize;
 
     bool bUseNonSeekableAccess = false;
     uno::Reference < io::XInputStream > xStream;
-    if ( !IsPackageMember() && !bRawStream && !bToBeEncrypted && bToBeCompressed )
+    if ( !IsPackageMember() && !m_bRawStream && !bToBeEncrypted && bToBeCompressed )
     {
         // the stream is not a package member, not a raw stream,
         // it should not be encrypted and it should be compressed,
@@ -540,11 +572,11 @@ bool ZipPackageStream::saveChild(
             {
                 // If the stream is a raw one, then we should be positioned
                 // at the beginning of the actual data
-                if ( !bToBeCompressed || bRawStream )
+                if ( !bToBeCompressed || m_bRawStream )
                 {
                     // The raw stream can neither be encrypted nor connected
-                    OSL_ENSURE( !bRawStream || !(bToBeCompressed || bToBeEncrypted), "The stream is already encrypted!\n" );
-                    xSeek->seek ( bRawStream ? m_nMagicalHackPos : 0 );
+                    OSL_ENSURE( !m_bRawStream || !(bToBeCompressed || bToBeEncrypted), "The stream is already encrypted!\n" );
+                    xSeek->seek ( m_bRawStream ? m_nMagicalHackPos : 0 );
                     ImplSetStoredData ( *pTempEntry, xStream );
 
                     // TODO/LATER: Get rid of hacks related to switching of Flag Method and Size properties!
@@ -553,7 +585,7 @@ bool ZipPackageStream::saveChild(
                 {
                     // this is the correct original size
                     pTempEntry->nSize = xSeek->getLength();
-                    nOwnStreamOrigSize = pTempEntry->nSize;
+                    m_nOwnStreamOrigSize = pTempEntry->nSize;
                 }
 
                 xSeek->seek ( 0 );
@@ -592,7 +624,7 @@ bool ZipPackageStream::saveChild(
             return bSuccess;
         }
 
-        if ( bToBeEncrypted || bRawStream || bTransportOwnEncrStreamAsRaw )
+        if ( bToBeEncrypted || m_bRawStream || bTransportOwnEncrStreamAsRaw )
         {
             if ( bToBeEncrypted && !bTransportOwnEncrStreamAsRaw )
             {
@@ -624,11 +656,11 @@ bool ZipPackageStream::saveChild(
             aPropSet[PKG_MNFST_ITERATION].Value <<= m_xBaseEncryptionData->m_nIterationCount;
 
             // Need to store the uncompressed size in the manifest
-            OSL_ENSURE( nOwnStreamOrigSize >= 0, "The stream size was not correctly initialized!\n" );
+            OSL_ENSURE( m_nOwnStreamOrigSize >= 0, "The stream size was not correctly initialized!\n" );
             aPropSet[PKG_MNFST_UCOMPSIZE].Name = sSizeProperty;
-            aPropSet[PKG_MNFST_UCOMPSIZE].Value <<= nOwnStreamOrigSize;
+            aPropSet[PKG_MNFST_UCOMPSIZE].Value <<= m_nOwnStreamOrigSize;
 
-            if ( bRawStream || bTransportOwnEncrStreamAsRaw )
+            if ( m_bRawStream || bTransportOwnEncrStreamAsRaw )
             {
                 ::rtl::Reference< EncryptionData > xEncData = GetEncryptionData();
                 if ( !xEncData.is() )
@@ -651,7 +683,7 @@ bool ZipPackageStream::saveChild(
     // 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
+      && ( m_bRawStream || bTransportOwnEncrStreamAsRaw
         || ( IsPackageMember() && !bToBeEncrypted
           && ( ( aEntry.nMethod == DEFLATED && bToBeCompressed )
             || ( aEntry.nMethod == STORED && !bToBeCompressed ) ) ) ) )
@@ -671,7 +703,7 @@ bool ZipPackageStream::saveChild(
 
         try
         {
-            if ( bRawStream )
+            if ( m_bRawStream )
                 xStream->skipBytes( m_nMagicalHackPos );
 
             ZipOutputStream::setEntry(pTempEntry);
@@ -733,35 +765,29 @@ bool ZipPackageStream::saveChild(
         try
         {
             ZipOutputStream::setEntry(pTempEntry);
-            rZipOut.writeLOC(pTempEntry, bToBeEncrypted);
             // the entry is provided to the ZipOutputStream that will delete it
             pAutoTempEntry.release();
-            sal_Int32 nLength;
-            uno::Sequence < sal_Int8 > aSeq (n_ConstBufferSize);
 
             if (pTempEntry->nMethod == STORED)
             {
+                sal_Int32 nLength;
+                uno::Sequence< sal_Int8 > aSeq(n_ConstBufferSize);
+                rZipOut.writeLOC(pTempEntry, bToBeEncrypted);
                 do
                 {
                     nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
                     rZipOut.rawWrite(aSeq, 0, nLength);
                 }
                 while ( nLength == n_ConstBufferSize );
+                rZipOut.rawCloseEntry(bToBeEncrypted);
             }
             else
             {
-                ZipOutputEntry aZipEntry(m_xContext, *pTempEntry, this, bToBeEncrypted);
-                do
-                {
-                    nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
-                    aZipEntry.write(aSeq, 0, nLength);
-                }
-                while ( nLength == n_ConstBufferSize );
-                aZipEntry.closeEntry();
-                uno::Sequence< sal_Int8 > aCompressedData = aZipEntry.getData();
-                rZipOut.rawWrite(aCompressedData, 0, aCompressedData.getLength());
+                bParallelDeflate = true;
+                // Start a new thread deflating this zip entry
+                ZipOutputEntry *pZipEntry = new ZipOutputEntry(m_xContext, *pTempEntry, this, bToBeEncrypted);
+                rZipOut.addDeflatingThread( pZipEntry, new DeflateThread(pZipEntry, xStream) );
             }
-            rZipOut.rawCloseEntry(bToBeEncrypted);
         }
         catch ( ZipException& )
         {
@@ -793,36 +819,39 @@ bool ZipPackageStream::saveChild(
         }
     }
 
-    if( bSuccess )
-    {
-        if ( !IsPackageMember() )
-        {
-            CloseOwnStreamIfAny();
-            SetPackageMember ( true );
-        }
+    if (bSuccess && !bParallelDeflate)
+        successfullyWritten(pTempEntry);
 
-        if ( bRawStream )
-        {
-            // the raw stream was integrated and now behaves
-            // as usual encrypted stream
-            SetToBeEncrypted( true );
-        }
+    if ( aPropSet.getLength()
+      && ( m_nFormat == embed::StorageFormats::PACKAGE || m_nFormat == embed::StorageFormats::OFOPXML ) )
+        rManList.push_back( aPropSet );
 
-        // Then copy it back afterwards...
-        ZipPackageFolder::copyZipEntry ( aEntry, *pTempEntry );
+    return bSuccess;
+}
 
-        // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
-        if ( IsEncrypted() )
-            setSize( nOwnStreamOrigSize );
+void ZipPackageStream::successfullyWritten( ZipEntry *pEntry )
+{
+    if ( !IsPackageMember() )
+    {
+        CloseOwnStreamIfAny();
+        SetPackageMember ( true );
+    }
 
-        aEntry.nOffset *= -1;
+    if ( m_bRawStream )
+    {
+        // the raw stream was integrated and now behaves
+        // as usual encrypted stream
+        SetToBeEncrypted( true );
     }
 
-    if ( aPropSet.getLength()
-      && ( m_nFormat == embed::StorageFormats::PACKAGE || m_nFormat == embed::StorageFormats::OFOPXML ) )
-        rManList.push_back( aPropSet );
+    // Then copy it back afterwards...
+    ZipPackageFolder::copyZipEntry( aEntry, *pEntry );
 
-    return bSuccess;
+    // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
+    if ( IsEncrypted() )
+        setSize( m_nOwnStreamOrigSize );
+
+    aEntry.nOffset *= -1;
 }
 
 void ZipPackageStream::SetPackageMember( bool bNewValue )
diff --git a/package/source/zippackage/wrapstreamforshare.cxx b/package/source/zippackage/wrapstreamforshare.cxx
index 4f737bf..c74e4b2 100644
--- a/package/source/zippackage/wrapstreamforshare.cxx
+++ b/package/source/zippackage/wrapstreamforshare.cxx
@@ -54,8 +54,6 @@ sal_Int32 SAL_CALL WrapStreamForShare::readBytes( uno::Sequence< sal_Int8 >& aDa
                 io::IOException,
                 uno::RuntimeException, std::exception )
 {
-    ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
-
     if ( !m_xInStream.is() )
         throw io::IOException(THROW_WHERE );
 
@@ -73,8 +71,6 @@ sal_Int32 SAL_CALL WrapStreamForShare::readSomeBytes( uno::Sequence< sal_Int8 >&
                 io::IOException,
                 uno::RuntimeException, std::exception )
 {
-    ::osl::MutexGuard aGuard( m_rMutexRef->GetMutex() );
-
     if ( !m_xInStream.is() )
         throw io::IOException(THROW_WHERE );
 
commit db5552631b13e5a1d330929cd5093bd0f9894ec8
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Tue Oct 21 10:37:02 2014 +0200

    package: Call writeLOC always after putNextEntry explicitly
    
    Preparation step to parallel deflating.
    Rename putNextEntry to setEntry and make it a static function.
    We need to call setEntry before starting thread but writeLOC after.
    
    Change-Id: I99a9ffa7dc4c18b47c621847b48bf8469bfb789a

diff --git a/package/inc/ZipOutputStream.hxx b/package/inc/ZipOutputStream.hxx
index 2d78eb7..f11b883 100644
--- a/package/inc/ZipOutputStream.hxx
+++ b/package/inc/ZipOutputStream.hxx
@@ -37,33 +37,30 @@ class ZipOutputStream
     ByteChucker         m_aChucker;
     bool                m_bFinished;
     ZipEntry            *m_pCurrentEntry;
-    bool                m_bEncrypt;
 
 public:
     ZipOutputStream(
         const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > &xOStream );
     ~ZipOutputStream();
 
-    // rawWrite to support a direct write to the output stream
+    void writeLOC( ZipEntry *pEntry, bool bEncrypt = false )
+        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
     void 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 rawCloseEntry()
+    void rawCloseEntry( bool bEncrypt = false )
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
 
-    void putNextEntry( ZipEntry& rEntry, bool bEncrypt = false )
-        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
     void finish()
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
 
     static sal_uInt32 getCurrentDosTime();
+    static void setEntry( ZipEntry *pEntry );
 
 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);
-    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);
 };
diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx
index 25cdb18..c9b6e08 100644
--- a/package/source/zipapi/ZipOutputStream.cxx
+++ b/package/source/zipapi/ZipOutputStream.cxx
@@ -50,28 +50,20 @@ ZipOutputStream::~ZipOutputStream( void )
         delete m_aZipList[i];
 }
 
-void ZipOutputStream::putNextEntry( ZipEntry& rEntry, bool bEncrypt )
-    throw(IOException, RuntimeException)
+void ZipOutputStream::setEntry( ZipEntry *pEntry )
 {
-    assert(!m_pCurrentEntry && "Forgot to close an entry before putNextEntry()?");
-    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)
+    if (pEntry->nTime == -1)
+        pEntry->nTime = getCurrentDosTime();
+    if (pEntry->nMethod == -1)
+        pEntry->nMethod = DEFLATED;
+    pEntry->nVersion = 20;
+    pEntry->nFlag = 1 << 11;
+    if (pEntry->nSize == -1 || pEntry->nCompressedSize == -1 ||
+        pEntry->nCrc == -1)
     {
-        rEntry.nSize = rEntry.nCompressedSize = 0;
-        rEntry.nFlag |= 8;
+        pEntry->nSize = pEntry->nCompressedSize = 0;
+        pEntry->nFlag |= 8;
     }
-    m_bEncrypt = bEncrypt;
-
-    sal_Int32 nLOCLength = writeLOC(rEntry);
-    rEntry.nOffset = m_aChucker.GetPosition() - nLOCLength;
-    m_aZipList.push_back( &rEntry );
-    m_pCurrentEntry = &rEntry;
 }
 
 void ZipOutputStream::rawWrite( Sequence< sal_Int8 >& rBuffer, sal_Int32 /*nNewOffset*/, sal_Int32 nNewLength )
@@ -80,13 +72,14 @@ void ZipOutputStream::rawWrite( Sequence< sal_Int8 >& rBuffer, sal_Int32 /*nNewO
     m_aChucker.WriteBytes( Sequence< sal_Int8 >(rBuffer.getConstArray(), nNewLength) );
 }
 
-void ZipOutputStream::rawCloseEntry()
+void ZipOutputStream::rawCloseEntry( bool bEncrypt )
     throw(IOException, RuntimeException)
 {
+    assert(m_pCurrentEntry && "Forgot to call writeLOC()?");
     if ( m_pCurrentEntry->nMethod == DEFLATED && ( m_pCurrentEntry->nFlag & 8 ) )
         writeEXT(*m_pCurrentEntry);
 
-    if (m_bEncrypt)
+    if (bEncrypt)
         m_pCurrentEntry->nMethod = STORED;
 
     m_pCurrentEntry = NULL;
@@ -192,9 +185,14 @@ void ZipOutputStream::writeEXT( const ZipEntry &rEntry )
     }
 }
 
-sal_Int32 ZipOutputStream::writeLOC( const ZipEntry &rEntry )
+void ZipOutputStream::writeLOC( ZipEntry *pEntry, bool bEncrypt )
     throw(IOException, RuntimeException)
 {
+    assert(!m_pCurrentEntry && "Forgot to close an entry with rawCloseEntry()?");
+    m_pCurrentEntry = pEntry;
+    m_aZipList.push_back( m_pCurrentEntry );
+    const ZipEntry &rEntry = *m_pCurrentEntry;
+
     if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( rEntry.sPath, true ) )
         throw IOException("Unexpected character is used in file name." );
 
@@ -206,7 +204,7 @@ sal_Int32 ZipOutputStream::writeLOC( const ZipEntry &rEntry )
 
     m_aChucker << rEntry.nFlag;
     // If it's an encrypted entry, we pretend its stored plain text
-    if (m_bEncrypt)
+    if (bEncrypt)
         m_aChucker << static_cast < sal_Int16 > ( STORED );
     else
         m_aChucker << rEntry.nMethod;
@@ -240,7 +238,7 @@ sal_Int32 ZipOutputStream::writeLOC( const ZipEntry &rEntry )
     Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() );
     m_aChucker.WriteBytes( aSequence );
 
-    return LOCHDR + nNameLength;
+    m_pCurrentEntry->nOffset = m_aChucker.GetPosition() - (LOCHDR + nNameLength);
 }
 
 sal_uInt32 ZipOutputStream::getCurrentDosTime()
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index a802fd5..80d4d4f 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -997,7 +997,8 @@ void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut )
 
     try
     {
-        aZipOut.putNextEntry(*pEntry);
+        ZipOutputStream::setEntry(pEntry);
+        aZipOut.writeLOC(pEntry);
         aZipOut.rawWrite(aType, 0, nBufferLength);
         aZipOut.rawCloseEntry();
     }
@@ -1039,7 +1040,8 @@ 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);
+    ZipOutputStream::setEntry(pEntry);
+    aZipOut.writeLOC(pEntry);
     ZipOutputEntry aZipEntry(m_xContext, *pEntry, NULL);
     aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength);
     aZipEntry.closeEntry();
@@ -1093,7 +1095,8 @@ void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno:
     pBuffer->realloc( nBufferLength );
 
     // there is no encryption in this format currently
-    aZipOut.putNextEntry(*pEntry);
+    ZipOutputStream::setEntry(pEntry);
+    aZipOut.writeLOC(pEntry);
     ZipOutputEntry aZipEntry(m_xContext, *pEntry, NULL);
     aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength);
     aZipEntry.closeEntry();
diff --git a/package/source/zippackage/ZipPackageFolder.cxx b/package/source/zippackage/ZipPackageFolder.cxx
index a6b2e5c..cb72ed1 100644
--- a/package/source/zippackage/ZipPackageFolder.cxx
+++ b/package/source/zippackage/ZipPackageFolder.cxx
@@ -337,7 +337,8 @@ void ZipPackageFolder::saveContents(
 
         try
         {
-            rZipOut.putNextEntry( *pTempEntry );
+            ZipOutputStream::setEntry(pTempEntry);
+            rZipOut.writeLOC(pTempEntry);
             rZipOut.rawCloseEntry();
         }
         catch ( ZipException& )
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index c5f8a31..ca2ad01 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -674,7 +674,8 @@ bool ZipPackageStream::saveChild(
             if ( bRawStream )
                 xStream->skipBytes( m_nMagicalHackPos );
 
-            rZipOut.putNextEntry(*pTempEntry);
+            ZipOutputStream::setEntry(pTempEntry);
+            rZipOut.writeLOC(pTempEntry);
             // the entry is provided to the ZipOutputStream that will delete it
             pAutoTempEntry.release();
 
@@ -731,7 +732,8 @@ bool ZipPackageStream::saveChild(
 
         try
         {
-            rZipOut.putNextEntry(*pTempEntry, bToBeEncrypted);
+            ZipOutputStream::setEntry(pTempEntry);
+            rZipOut.writeLOC(pTempEntry, bToBeEncrypted);
             // the entry is provided to the ZipOutputStream that will delete it
             pAutoTempEntry.release();
             sal_Int32 nLength;
@@ -759,7 +761,7 @@ bool ZipPackageStream::saveChild(
                 uno::Sequence< sal_Int8 > aCompressedData = aZipEntry.getData();
                 rZipOut.rawWrite(aCompressedData, 0, aCompressedData.getLength());
             }
-            rZipOut.rawCloseEntry();
+            rZipOut.rawCloseEntry(bToBeEncrypted);
         }
         catch ( ZipException& )
         {
commit 30f80f12fb1db4c9c6f19fcfda4e796891b6e03c
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Tue Oct 21 12:21:22 2014 +0200

    package: Do not use hacky bit 1<<4 in ZipEntry::nFlag
    
    Change-Id: I504f5c0c9aa9b655ffb53d9820a33677dad6aa08

diff --git a/package/inc/ZipOutputStream.hxx b/package/inc/ZipOutputStream.hxx
index 0c8dafe..2d78eb7 100644
--- a/package/inc/ZipOutputStream.hxx
+++ b/package/inc/ZipOutputStream.hxx
@@ -37,6 +37,7 @@ class ZipOutputStream
     ByteChucker         m_aChucker;
     bool                m_bFinished;
     ZipEntry            *m_pCurrentEntry;
+    bool                m_bEncrypt;
 
 public:
     ZipOutputStream(
diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx
index d4f0456..25cdb18 100644
--- a/package/source/zipapi/ZipOutputStream.cxx
+++ b/package/source/zipapi/ZipOutputStream.cxx
@@ -66,10 +66,7 @@ void ZipOutputStream::putNextEntry( ZipEntry& rEntry, bool bEncrypt )
         rEntry.nSize = rEntry.nCompressedSize = 0;
         rEntry.nFlag |= 8;
     }
-    if (bEncrypt)
-    {
-        rEntry.nFlag |= 1 << 4;
-    }
+    m_bEncrypt = bEncrypt;
 
     sal_Int32 nLOCLength = writeLOC(rEntry);
     rEntry.nOffset = m_aChucker.GetPosition() - nLOCLength;
@@ -88,6 +85,10 @@ void ZipOutputStream::rawCloseEntry()
 {
     if ( m_pCurrentEntry->nMethod == DEFLATED && ( m_pCurrentEntry->nFlag & 8 ) )
         writeEXT(*m_pCurrentEntry);
+
+    if (m_bEncrypt)
+        m_pCurrentEntry->nMethod = STORED;
+
     m_pCurrentEntry = NULL;
 }
 
@@ -144,19 +145,8 @@ void ZipOutputStream::writeCEN( const ZipEntry &rEntry )
     m_aChucker << CENSIG;
     m_aChucker << rEntry.nVersion;
     m_aChucker << rEntry.nVersion;
-    if (rEntry.nFlag & (1 << 4) )
-    {
-        // If it's an encrypted entry, we pretend its stored plain text
-        ZipEntry *pEntry = const_cast < ZipEntry * > ( &rEntry );
-        pEntry->nFlag &= ~(1 <<4 );
-        m_aChucker << rEntry.nFlag;
-        m_aChucker << static_cast < sal_Int16 > ( STORED );
-    }
-    else
-    {
-        m_aChucker << rEntry.nFlag;
-        m_aChucker << rEntry.nMethod;
-    }
+    m_aChucker << rEntry.nFlag;
+    m_aChucker << rEntry.nMethod;
     bool bWrite64Header = false;
 
     m_aChucker << static_cast < sal_uInt32> ( rEntry.nTime );
@@ -214,19 +204,12 @@ sal_Int32 ZipOutputStream::writeLOC( const ZipEntry &rEntry )
     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 << rEntry.nFlag;
+    // If it's an encrypted entry, we pretend its stored plain text
+    if (m_bEncrypt)
         m_aChucker << static_cast < sal_Int16 > ( STORED );
-    }
     else
-    {
-        m_aChucker << rEntry.nFlag;
         m_aChucker << rEntry.nMethod;
-    }
 
     bool bWrite64Header = false;
 
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index 590ff0e..c5f8a31 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -809,13 +809,6 @@ bool ZipPackageStream::saveChild(
         // Then copy it back afterwards...
         ZipPackageFolder::copyZipEntry ( aEntry, *pTempEntry );
 
-        // Remove hacky bit from entry flags
-        if ( aEntry.nFlag & ( 1 << 4 ) )
-        {
-            aEntry.nFlag &= ~( 1 << 4 );
-            aEntry.nMethod = STORED;
-        }
-
         // TODO/LATER: get rid of this hack ( the encrypted stream size property is changed during saving )
         if ( IsEncrypted() )
             setSize( nOwnStreamOrigSize );
commit ef8e7eabe1e53a99bbfeac0297faa9592cd18175
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Tue Oct 21 09:29:19 2014 +0200

    There is no XZipOutputEntry interface
    
    Change-Id: Ib8fa3351ba25416a13d6c8bf63bd5fc8e43703c5

diff --git a/package/inc/ZipOutputEntry.hxx b/package/inc/ZipOutputEntry.hxx
index e04cebf..c24d5a9 100644
--- a/package/inc/ZipOutputEntry.hxx
+++ b/package/inc/ZipOutputEntry.hxx
@@ -19,7 +19,6 @@
 #ifndef INCLUDED_PACKAGE_INC_ZIPOUTPUTENTRY_HXX
 #define INCLUDED_PACKAGE_INC_ZIPOUTPUTENTRY_HXX
 
-#include <com/sun/star/io/IOException.hpp>
 #include <com/sun/star/uno/Reference.hxx>
 #include <com/sun/star/uno/XComponentContext.hpp>
 #include <com/sun/star/xml/crypto/XCipherContext.hpp>
@@ -56,11 +55,8 @@ public:
 
     css::uno::Sequence< sal_Int8 > getData();
 
-    // 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);
+    void closeEntry();
+    void write(const css::uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength);
 
 private:
     void doDeflate();
diff --git a/package/source/zipapi/ZipOutputEntry.cxx b/package/source/zipapi/ZipOutputEntry.cxx
index bcbb6eb..f43b5c7 100644
--- a/package/source/zipapi/ZipOutputEntry.cxx
+++ b/package/source/zipapi/ZipOutputEntry.cxx
@@ -68,8 +68,7 @@ uno::Sequence< sal_Int8 > ZipOutputEntry::getData()
     return m_pBuffer->getSequence();
 }
 
-void SAL_CALL ZipOutputEntry::closeEntry()
-    throw(IOException, RuntimeException)
+void ZipOutputEntry::closeEntry()
 {
     m_aDeflater.finish();
     while (!m_aDeflater.finished())
@@ -120,8 +119,7 @@ void SAL_CALL ZipOutputEntry::closeEntry()
     }
 }
 
-void SAL_CALL ZipOutputEntry::write( const Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
-    throw(IOException, RuntimeException)
+void ZipOutputEntry::write( const Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
 {
     if (!m_aDeflater.finished())
     {
commit 3e3b8483d7866e96bc75ddda283416c6829714af
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Tue Oct 21 09:20:24 2014 +0200

    package: Use memory stream for compressing zip entries
    
    Change-Id: Ibf81dc3cd8a9a9da3dfd6ee6e587a522c4d56a44

diff --git a/package/inc/ZipOutputEntry.hxx b/package/inc/ZipOutputEntry.hxx
index 73bd8a4..e04cebf 100644
--- a/package/inc/ZipOutputEntry.hxx
+++ b/package/inc/ZipOutputEntry.hxx
@@ -29,19 +29,19 @@
 #include <CRC32.hxx>
 
 struct ZipEntry;
-class ZipOutputStream;
+class ZipPackageBuffer;
 class ZipPackageStream;
 
 class ZipOutputEntry
 {
     ::com::sun::star::uno::Sequence< sal_Int8 > m_aDeflateBuffer;
-    ZipUtils::Deflater  m_aDeflater;
+    ZipUtils::Deflater m_aDeflater;
+    css::uno::Reference< ZipPackageBuffer > m_pBuffer;
 
     ::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;
-    ZipOutputStream*    m_pZipOutputStream;
     ZipEntry            *m_pCurrentEntry;
     sal_Int16           m_nDigested;
     bool                m_bEncryptCurrentEntry;
@@ -50,10 +50,12 @@ class ZipOutputEntry
 public:
     ZipOutputEntry(
         const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext,
-        ZipOutputStream *pZipOutputStream, ZipEntry& rEntry, ZipPackageStream* pStream, bool bEncrypt = false);
+        ZipEntry& rEntry, ZipPackageStream* pStream, bool bEncrypt = false);
 
     ~ZipOutputEntry();
 
+    css::uno::Sequence< sal_Int8 > getData();
+
     // XZipOutputEntry interfaces
     void SAL_CALL closeEntry(  )
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
diff --git a/package/inc/ZipOutputStream.hxx b/package/inc/ZipOutputStream.hxx
index 6775bd0..0c8dafe 100644
--- a/package/inc/ZipOutputStream.hxx
+++ b/package/inc/ZipOutputStream.hxx
@@ -53,7 +53,6 @@ public:
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
     void finish()
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
-    ByteChucker& getChucker();
 
     static sal_uInt32 getCurrentDosTime();
 
diff --git a/package/source/zipapi/ZipOutputEntry.cxx b/package/source/zipapi/ZipOutputEntry.cxx
index ca08abb..bcbb6eb 100644
--- a/package/source/zipapi/ZipOutputEntry.cxx
+++ b/package/source/zipapi/ZipOutputEntry.cxx
@@ -24,11 +24,10 @@
 
 #include <osl/time.h>
 
-#include <ByteChucker.hxx>
 #include <PackageConstants.hxx>
 #include <ZipEntry.hxx>
 #include <ZipFile.hxx>
-#include <ZipOutputStream.hxx>
+#include <ZipPackageBuffer.hxx>
 #include <ZipPackageStream.hxx>
 
 using namespace com::sun::star;
@@ -39,13 +38,12 @@ using namespace com::sun::star::packages::zip::ZipConstants;
 /** This class is used to deflate Zip entries
  */
 ZipOutputEntry::ZipOutputEntry( const uno::Reference< uno::XComponentContext >& rxContext,
-                        ZipOutputStream* pOutputStream,
                         ZipEntry& rEntry,
                         ZipPackageStream* pStream,
                         bool bEncrypt)
 : m_aDeflateBuffer(n_ConstBufferSize)
 , m_aDeflater(DEFAULT_COMPRESSION, true)
-, m_pZipOutputStream(pOutputStream)
+, m_pBuffer(new ZipPackageBuffer(n_ConstBufferSize))
 , m_pCurrentEntry(&rEntry)
 , m_nDigested(0)
 , m_bEncryptCurrentEntry(bEncrypt)
@@ -64,6 +62,12 @@ ZipOutputEntry::~ZipOutputEntry( void )
 {
 }
 
+uno::Sequence< sal_Int8 > ZipOutputEntry::getData()
+{
+    m_pBuffer->realloc(m_pBuffer->getPosition());
+    return m_pBuffer->getSequence();
+}
+
 void SAL_CALL ZipOutputEntry::closeEntry()
     throw(IOException, RuntimeException)
 {
@@ -151,7 +155,7 @@ void ZipOutputEntry::doDeflate()
             // FIXME64: uno::Sequence not 64bit safe.
             uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->convertWithCipherContext( aTmpBuffer );
 
-            m_pZipOutputStream->getChucker().WriteBytes( aEncryptionBuffer );
+            m_pBuffer->writeBytes( aEncryptionBuffer );
 
             // the sizes as well as checksum for encrypted streams is calculated here
             m_pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength();
@@ -160,7 +164,7 @@ void ZipOutputEntry::doDeflate()
         }
         else
         {
-            m_pZipOutputStream->getChucker().WriteBytes ( aTmpBuffer );
+            m_pBuffer->writeBytes ( aTmpBuffer );
         }
     }
 
@@ -170,7 +174,7 @@ void ZipOutputEntry::doDeflate()
         uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->finalizeCipherContextAndDispose();
         if ( aEncryptionBuffer.getLength() )
         {
-            m_pZipOutputStream->getChucker().WriteBytes( aEncryptionBuffer );
+            m_pBuffer->writeBytes( aEncryptionBuffer );
 
             // the sizes as well as checksum for encrypted streams is calculated hier
             m_pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength();
diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx
index 29c19c4..d4f0456 100644
--- a/package/source/zipapi/ZipOutputStream.cxx
+++ b/package/source/zipapi/ZipOutputStream.cxx
@@ -108,11 +108,6 @@ void ZipOutputStream::finish(  )
     m_xStream->flush();
 }
 
-ByteChucker& ZipOutputStream::getChucker()
-{
-    return m_aChucker;
-}
-
 void ZipOutputStream::writeEND(sal_uInt32 nOffset, sal_uInt32 nLength)
     throw(IOException, RuntimeException)
 {
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index 23a737e..a802fd5 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -1040,9 +1040,11 @@ void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< uno::Seq
 
     // the manifest.xml is never encrypted - so pass an empty reference
     aZipOut.putNextEntry(*pEntry);
-    ZipOutputEntry aZipEntry(m_xContext, &aZipOut, *pEntry, NULL);
+    ZipOutputEntry aZipEntry(m_xContext, *pEntry, NULL);
     aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength);
     aZipEntry.closeEntry();
+    uno::Sequence< sal_Int8 > aCompressedData = aZipEntry.getData();
+    aZipOut.rawWrite(aCompressedData, 0, aCompressedData.getLength());
     aZipOut.rawCloseEntry();
 }
 
@@ -1092,9 +1094,11 @@ void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno:
 
     // there is no encryption in this format currently
     aZipOut.putNextEntry(*pEntry);
-    ZipOutputEntry aZipEntry(m_xContext, &aZipOut, *pEntry, NULL);
+    ZipOutputEntry aZipEntry(m_xContext, *pEntry, NULL);
     aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength);
     aZipEntry.closeEntry();
+    uno::Sequence< sal_Int8 > aCompressedData = aZipEntry.getData();
+    aZipOut.rawWrite(aCompressedData, 0, aCompressedData.getLength());
     aZipOut.rawCloseEntry();
 }
 
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index edc1c7aa..590ff0e 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -748,7 +748,7 @@ bool ZipPackageStream::saveChild(
             }
             else
             {
-                ZipOutputEntry aZipEntry(m_xContext, &rZipOut, *pTempEntry, this, bToBeEncrypted);
+                ZipOutputEntry aZipEntry(m_xContext, *pTempEntry, this, bToBeEncrypted);
                 do
                 {
                     nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
@@ -756,6 +756,8 @@ bool ZipPackageStream::saveChild(
                 }
                 while ( nLength == n_ConstBufferSize );
                 aZipEntry.closeEntry();
+                uno::Sequence< sal_Int8 > aCompressedData = aZipEntry.getData();
+                rZipOut.rawWrite(aCompressedData, 0, aCompressedData.getLength());
             }
             rZipOut.rawCloseEntry();
         }
commit 3e7ab1ac1dc91544bdc58949ac62853b0ee33760
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Mon Oct 20 22:54:49 2014 +0200

    ZipOutputEntry: m_pCurrentEntry is always set
    
    Change-Id: Ib6a69a83f4a378df838b2231b9eba7fba49cd9f1

diff --git a/package/source/zipapi/ZipOutputEntry.cxx b/package/source/zipapi/ZipOutputEntry.cxx
index b73f0a2..ca08abb 100644
--- a/package/source/zipapi/ZipOutputEntry.cxx
+++ b/package/source/zipapi/ZipOutputEntry.cxx
@@ -64,62 +64,55 @@ ZipOutputEntry::~ZipOutputEntry( void )
 {
 }
 
-void SAL_CALL ZipOutputEntry::closeEntry(  )
+void SAL_CALL ZipOutputEntry::closeEntry()
     throw(IOException, RuntimeException)
 {
-    ZipEntry *pEntry = m_pCurrentEntry;
-    if (pEntry)
+    m_aDeflater.finish();
+    while (!m_aDeflater.finished())
+        doDeflate();
+
+    if ((m_pCurrentEntry->nFlag & 8) == 0)
     {
-        m_aDeflater.finish();
-        while (!m_aDeflater.finished())
-            doDeflate();
-        if ((pEntry->nFlag & 8) == 0)
+        if (m_pCurrentEntry->nSize != m_aDeflater.getTotalIn())
         {
-            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");
-            }
+            OSL_FAIL("Invalid entry size");
         }
-        else
+        if (m_pCurrentEntry->nCompressedSize != m_aDeflater.getTotalOut())
         {
-            if ( !m_bEncryptCurrentEntry )
-            {
-                pEntry->nSize = m_aDeflater.getTotalIn();
-                pEntry->nCompressedSize = m_aDeflater.getTotalOut();
-            }
-            pEntry->nCrc = m_aCRC.getValue();
+            // Different compression strategies make the merit of this
+            // test somewhat dubious
+            m_pCurrentEntry->nCompressedSize = m_aDeflater.getTotalOut();
         }
-        m_aDeflater.reset();
-        m_aCRC.reset();
-
-        if (m_bEncryptCurrentEntry)
+        if (m_pCurrentEntry->nCrc != m_aCRC.getValue())
         {
-            m_bEncryptCurrentEntry = false;
-
-            m_xCipherContext.clear();
+            OSL_FAIL("Invalid entry CRC-32");
+        }
+    }
+    else
+    {
+        if ( !m_bEncryptCurrentEntry )
+        {
+            m_pCurrentEntry->nSize = m_aDeflater.getTotalIn();
+            m_pCurrentEntry->nCompressedSize = m_aDeflater.getTotalOut();
+        }
+        m_pCurrentEntry->nCrc = m_aCRC.getValue();
+    }
+    m_aDeflater.reset();
+    m_aCRC.reset();
 
-            uno::Sequence< sal_Int8 > aDigestSeq;
-            if ( m_xDigestContext.is() )
-            {
-                aDigestSeq = m_xDigestContext->finalizeDigestAndDispose();
-                m_xDigestContext.clear();
-            }
+    if (m_bEncryptCurrentEntry)
+    {
+        m_xCipherContext.clear();
 
-            if ( m_pCurrentStream )
-                m_pCurrentStream->setDigest( aDigestSeq );
+        uno::Sequence< sal_Int8 > aDigestSeq;
+        if ( m_xDigestContext.is() )
+        {
+            aDigestSeq = m_xDigestContext->finalizeDigestAndDispose();
+            m_xDigestContext.clear();
         }
-        m_pCurrentEntry = NULL;
-        m_pCurrentStream = NULL;
+
+        if ( m_pCurrentStream )
+            m_pCurrentStream->setDigest( aDigestSeq );
     }
 }
 
commit 4d1cb2dc5f1cae97ea44bded3b68d57076e21731
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Mon Oct 20 22:02:48 2014 +0200

    package: Zipping STORED entry is the same as rawWrite and we don't encrypt it
    
    Change-Id: Ie3f8ac261a70c9a2b5182fc7d36938d0a46ec045

diff --git a/package/source/zipapi/ZipOutputEntry.cxx b/package/source/zipapi/ZipOutputEntry.cxx
index 4e2f6d4..b73f0a2 100644
--- a/package/source/zipapi/ZipOutputEntry.cxx
+++ b/package/source/zipapi/ZipOutputEntry.cxx
@@ -51,6 +51,7 @@ ZipOutputEntry::ZipOutputEntry( const uno::Reference< uno::XComponentContext >&
 , m_bEncryptCurrentEntry(bEncrypt)
 , m_pCurrentStream(NULL)
 {
+    assert(m_pCurrentEntry->nMethod == DEFLATED && "Use ZipPackageStream::rawWrite() for STORED entries");
     if (m_bEncryptCurrentEntry)
     {
         m_xCipherContext = ZipFile::StaticGetCipher( rxContext, pStream->GetEncryptionData(), true );
@@ -69,49 +70,37 @@ void SAL_CALL ZipOutputEntry::closeEntry(  )
     ZipEntry *pEntry = m_pCurrentEntry;
     if (pEntry)
     {
-        switch (pEntry->nMethod)
+        m_aDeflater.finish();
+        while (!m_aDeflater.finished())
+            doDeflate();
+        if ((pEntry->nFlag & 8) == 0)
         {
-            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();
-                }
-                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 (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();
+        }
+        m_aDeflater.reset();
+        m_aCRC.reset();
 
         if (m_bEncryptCurrentEntry)
         {
@@ -137,24 +126,13 @@ void SAL_CALL ZipOutputEntry::closeEntry(  )
 void SAL_CALL ZipOutputEntry::write( const Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
     throw(IOException, RuntimeException)
 {
-    switch (m_pCurrentEntry->nMethod)
+    if (!m_aDeflater.finished())
     {
-        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_pZipOutputStream->getChucker().WriteBytes( aTmpBuffer );
-            }
-            break;
+        m_aDeflater.setInputSegment(rBuffer, nNewOffset, nNewLength);
+         while (!m_aDeflater.needsInput())
+            doDeflate();
+        if (!m_bEncryptCurrentEntry)
+            m_aCRC.updateSegment(rBuffer, nNewOffset, nNewLength);
     }
 }
 
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index a05320a..23a737e 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -998,9 +998,7 @@ void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut )
     try
     {
         aZipOut.putNextEntry(*pEntry);
-        ZipOutputEntry aZipEntry(m_xContext, &aZipOut, *pEntry, NULL);
-        aZipEntry.write(aType, 0, nBufferLength);
-        aZipEntry.closeEntry();
+        aZipOut.rawWrite(aType, 0, nBufferLength);
         aZipOut.rawCloseEntry();
     }
     catch ( const ::com::sun::star::io::IOException & r )
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index 7547e9c..edc1c7aa 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -485,8 +485,8 @@ bool ZipPackageStream::saveChild(
     pTempEntry->sPath = rPath;
     pTempEntry->nPathLen = (sal_Int16)( OUStringToOString( pTempEntry->sPath, RTL_TEXTENCODING_UTF8 ).getLength() );
 
-    bool bToBeEncrypted = m_bToBeEncrypted && (rEncryptionKey.getLength() || m_bHaveOwnKey);
-    bool bToBeCompressed = bToBeEncrypted ? sal_True : m_bToBeCompressed;
+    const bool bToBeEncrypted = m_bToBeEncrypted && (rEncryptionKey.getLength() || m_bHaveOwnKey);
+    const bool bToBeCompressed = bToBeEncrypted ? sal_True : m_bToBeCompressed;
 
     aPropSet[PKG_MNFST_MEDIATYPE].Name = sMediaTypeProperty;
     aPropSet[PKG_MNFST_MEDIATYPE].Value <<= GetMediaType( );
@@ -732,20 +732,31 @@ bool ZipPackageStream::saveChild(
         try
         {
             rZipOut.putNextEntry(*pTempEntry, bToBeEncrypted);
-            ZipOutputEntry aZipEntry(m_xContext, &rZipOut, *pTempEntry, this, bToBeEncrypted);
             // the entry is provided to the ZipOutputStream that will delete it
             pAutoTempEntry.release();
-
             sal_Int32 nLength;
             uno::Sequence < sal_Int8 > aSeq (n_ConstBufferSize);
-            do
+
+            if (pTempEntry->nMethod == STORED)
             {
-                nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
-                aZipEntry.write(aSeq, 0, nLength);
+                do
+                {
+                    nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
+                    rZipOut.rawWrite(aSeq, 0, nLength);
+                }
+                while ( nLength == n_ConstBufferSize );
+            }
+            else
+            {
+                ZipOutputEntry aZipEntry(m_xContext, &rZipOut, *pTempEntry, this, bToBeEncrypted);
+                do
+                {
+                    nLength = xStream->readBytes(aSeq, n_ConstBufferSize);
+                    aZipEntry.write(aSeq, 0, nLength);
+                }
+                while ( nLength == n_ConstBufferSize );
+                aZipEntry.closeEntry();
             }
-            while ( nLength == n_ConstBufferSize );
-
-            aZipEntry.closeEntry();
             rZipOut.rawCloseEntry();
         }
         catch ( ZipException& )
commit 2d92a84a6aac37e34d1699fdebe0270468b4f746
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Mon Oct 20 21:13:50 2014 +0200

    package: Move most ZipOutputEntry's methods back to ZipOutputStream
    
    We want to use ZipOutputEntry only for deflating (and maybe rename it).
    ca13a9377e4a36436e4c82bb33648d0f3b6db6f5 was not a good idea because the
    data still needs to be written sequentially anyway. Otherwise it's hard
    to get offset positions of individual entries right.
    
    Since this commit rawCloseEntry needs to be called always; also when we
    use write&closeEntry because we don't call writeEXT in closeEntry
    anymore.
    Need to rename and add comments later.
    
    Change-Id: I03bd48ca6e108e6253a77a137746165909ca3c3d

diff --git a/package/inc/ZipOutputEntry.hxx b/package/inc/ZipOutputEntry.hxx
index a1d03d3..73bd8a4 100644
--- a/package/inc/ZipOutputEntry.hxx
+++ b/package/inc/ZipOutputEntry.hxx
@@ -19,16 +19,17 @@
 #ifndef INCLUDED_PACKAGE_INC_ZIPOUTPUTENTRY_HXX
 #define INCLUDED_PACKAGE_INC_ZIPOUTPUTENTRY_HXX
 
+#include <com/sun/star/io/IOException.hpp>
 #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 ZipOutputStream;
 class ZipPackageStream;
 
 class ZipOutputEntry
@@ -40,7 +41,7 @@ class ZipOutputEntry
     ::com::sun::star::uno::Reference< ::com::sun::star::xml::crypto::XDigestContext > m_xDigestContext;
 
     CRC32               m_aCRC;
-    ByteChucker         &m_rChucker;
+    ZipOutputStream*    m_pZipOutputStream;
     ZipEntry            *m_pCurrentEntry;
     sal_Int16           m_nDigested;
     bool                m_bEncryptCurrentEntry;
@@ -49,29 +50,18 @@ class ZipOutputEntry
 public:
     ZipOutputEntry(
         const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XComponentContext >& rxContext,
-        ByteChucker& rChucker, ZipEntry& rEntry, ZipPackageStream* pStream, bool bEncrypt = false);
+        ZipOutputStream *pZipOutputStream, 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
diff --git a/package/inc/ZipOutputStream.hxx b/package/inc/ZipOutputStream.hxx
index 95c27f3..6775bd0 100644
--- a/package/inc/ZipOutputStream.hxx
+++ b/package/inc/ZipOutputStream.hxx
@@ -27,6 +27,7 @@
 #include <vector>
 
 struct ZipEntry;
+class ZipPackageStream;
 
 class ZipOutputStream
 {
@@ -35,22 +36,36 @@ class ZipOutputStream
 
     ByteChucker         m_aChucker;
     bool                m_bFinished;
+    ZipEntry            *m_pCurrentEntry;
 
 public:
     ZipOutputStream(
         const ::com::sun::star::uno::Reference< ::com::sun::star::io::XOutputStream > &xOStream );
     ~ZipOutputStream();
 
-    void addEntry( ZipEntry *pZipEntry );
+    // rawWrite to support a direct write to the output stream
+    void 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 rawCloseEntry()
+        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+
+    void putNextEntry( ZipEntry& rEntry, bool bEncrypt = false )
+        throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
     void finish()
         throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
     ByteChucker& getChucker();
 
+    static sal_uInt32 getCurrentDosTime();
+
 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);
+    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
diff --git a/package/source/zipapi/ZipOutputEntry.cxx b/package/source/zipapi/ZipOutputEntry.cxx
index a3e3cc8..4e2f6d4 100644
--- a/package/source/zipapi/ZipOutputEntry.cxx
+++ b/package/source/zipapi/ZipOutputEntry.cxx
@@ -24,9 +24,11 @@
 
 #include <osl/time.h>
 
+#include <ByteChucker.hxx>
 #include <PackageConstants.hxx>
 #include <ZipEntry.hxx>
 #include <ZipFile.hxx>
+#include <ZipOutputStream.hxx>
 #include <ZipPackageStream.hxx>
 
 using namespace com::sun::star;
@@ -37,43 +39,24 @@ 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,
+                        ZipOutputStream* pOutputStream,
                         ZipEntry& rEntry,
                         ZipPackageStream* pStream,
                         bool bEncrypt)
 : m_aDeflateBuffer(n_ConstBufferSize)
 , m_aDeflater(DEFAULT_COMPRESSION, true)
-, m_rChucker(rChucker)
+, m_pZipOutputStream(pOutputStream)
 , m_pCurrentEntry(&rEntry)
 , m_nDigested(0)
-, m_bEncryptCurrentEntry(false)
+, m_bEncryptCurrentEntry(bEncrypt)
 , 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)
+    if (m_bEncryptCurrentEntry)
     {
-        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 )
@@ -117,7 +100,6 @@ void SAL_CALL ZipOutputEntry::closeEntry(  )
                         pEntry->nCompressedSize = m_aDeflater.getTotalOut();
                     }
                     pEntry->nCrc = m_aCRC.getValue();
-                    writeEXT(*pEntry);
                 }
                 m_aDeflater.reset();
                 m_aCRC.reset();
@@ -170,27 +152,12 @@ void SAL_CALL ZipOutputEntry::write( const Sequence< sal_Int8 >& rBuffer, sal_In
         case STORED:
             {
                 Sequence < sal_Int8 > aTmpBuffer ( rBuffer.getConstArray(), nNewLength );
-                m_rChucker.WriteBytes( aTmpBuffer );
+                m_pZipOutputStream->getChucker().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());
@@ -213,7 +180,7 @@ void ZipOutputEntry::doDeflate()
             // FIXME64: uno::Sequence not 64bit safe.
             uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->convertWithCipherContext( aTmpBuffer );
 
-            m_rChucker.WriteBytes( aEncryptionBuffer );
+            m_pZipOutputStream->getChucker().WriteBytes( aEncryptionBuffer );
 
             // the sizes as well as checksum for encrypted streams is calculated here
             m_pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength();
@@ -222,7 +189,7 @@ void ZipOutputEntry::doDeflate()
         }
         else
         {
-            m_rChucker.WriteBytes ( aTmpBuffer );
+            m_pZipOutputStream->getChucker().WriteBytes ( aTmpBuffer );
         }
     }
 
@@ -232,7 +199,7 @@ void ZipOutputEntry::doDeflate()
         uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->finalizeCipherContextAndDispose();
         if ( aEncryptionBuffer.getLength() )
         {
-            m_rChucker.WriteBytes( aEncryptionBuffer );
+            m_pZipOutputStream->getChucker().WriteBytes( aEncryptionBuffer );
 
             // the sizes as well as checksum for encrypted streams is calculated hier
             m_pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength();
@@ -242,126 +209,4 @@ void ZipOutputEntry::doDeflate()
     }
 }
 
-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 7cd5acd..29c19c4 100644
--- a/package/source/zipapi/ZipOutputStream.cxx
+++ b/package/source/zipapi/ZipOutputStream.cxx
@@ -23,8 +23,11 @@
 #include <com/sun/star/io/XOutputStream.hpp>
 #include <comphelper/storagehelper.hxx>
 
+#include <osl/time.h>
+
 #include <PackageConstants.hxx>
 #include <ZipEntry.hxx>
+#include <ZipPackageStream.hxx>
 
 using namespace com::sun::star;
 using namespace com::sun::star::io;
@@ -37,6 +40,7 @@ ZipOutputStream::ZipOutputStream( const uno::Reference < io::XOutputStream > &xO
 : m_xStream(xOStream)
 , m_aChucker(xOStream)
 , m_bFinished(false)
+, m_pCurrentEntry(NULL)
 {
 }
 
@@ -46,9 +50,45 @@ ZipOutputStream::~ZipOutputStream( void )
         delete m_aZipList[i];
 }
 
-void ZipOutputStream::addEntry( ZipEntry *pZipEntry )
+void ZipOutputStream::putNextEntry( ZipEntry& rEntry, bool bEncrypt )
+    throw(IOException, RuntimeException)
+{
+    assert(!m_pCurrentEntry && "Forgot to close an entry before putNextEntry()?");
+    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)
+    {
+        rEntry.nFlag |= 1 << 4;
+    }
+
+    sal_Int32 nLOCLength = writeLOC(rEntry);
+    rEntry.nOffset = m_aChucker.GetPosition() - nLOCLength;
+    m_aZipList.push_back( &rEntry );
+    m_pCurrentEntry = &rEntry;
+}
+
+void ZipOutputStream::rawWrite( Sequence< sal_Int8 >& rBuffer, sal_Int32 /*nNewOffset*/, sal_Int32 nNewLength )
+    throw(IOException, RuntimeException)
+{
+    m_aChucker.WriteBytes( Sequence< sal_Int8 >(rBuffer.getConstArray(), nNewLength) );
+}
+
+void ZipOutputStream::rawCloseEntry()
+    throw(IOException, RuntimeException)
 {
-    m_aZipList.push_back( pZipEntry );
+    if ( m_pCurrentEntry->nMethod == DEFLATED && ( m_pCurrentEntry->nFlag & 8 ) )
+        writeEXT(*m_pCurrentEntry);
+    m_pCurrentEntry = NULL;
 }
 
 void ZipOutputStream::finish(  )
@@ -148,4 +188,116 @@ void ZipOutputStream::writeCEN( const ZipEntry &rEntry )
     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;
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/package/source/zippackage/ZipPackage.cxx b/package/source/zippackage/ZipPackage.cxx
index a631cab..a05320a 100644
--- a/package/source/zippackage/ZipPackage.cxx
+++ b/package/source/zippackage/ZipPackage.cxx
@@ -989,7 +989,7 @@ void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut )
     pEntry->sPath = sMime;
     pEntry->nMethod = STORED;
     pEntry->nSize = pEntry->nCompressedSize = nBufferLength;
-    pEntry->nTime = ZipOutputEntry::getCurrentDosTime();
+    pEntry->nTime = ZipOutputStream::getCurrentDosTime();
 
     CRC32 aCRC32;
     aCRC32.update( aType );
@@ -997,10 +997,11 @@ void ZipPackage::WriteMimetypeMagicFile( ZipOutputStream& aZipOut )
 
     try
     {
-        ZipOutputEntry aZipEntry(m_xContext, aZipOut.getChucker(), *pEntry, NULL);
+        aZipOut.putNextEntry(*pEntry);
+        ZipOutputEntry aZipEntry(m_xContext, &aZipOut, *pEntry, NULL);
         aZipEntry.write(aType, 0, nBufferLength);
         aZipEntry.closeEntry();
-        aZipOut.addEntry(pEntry);
+        aZipOut.rawCloseEntry();
     }
     catch ( const ::com::sun::star::io::IOException & r )
     {
@@ -1023,7 +1024,7 @@ void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< uno::Seq
     pEntry->nMethod = DEFLATED;
     pEntry->nCrc = -1;
     pEntry->nSize = pEntry->nCompressedSize = -1;
-    pEntry->nTime = ZipOutputEntry::getCurrentDosTime();
+    pEntry->nTime = ZipOutputStream::getCurrentDosTime();
 
     // Convert vector into a uno::Sequence
     uno::Sequence < uno::Sequence < PropertyValue > > aManifestSequence ( aManList.size() );
@@ -1040,10 +1041,11 @@ void ZipPackage::WriteManifest( ZipOutputStream& aZipOut, const vector< uno::Seq
     pBuffer->realloc( nBufferLength );
 
     // the manifest.xml is never encrypted - so pass an empty reference
-    ZipOutputEntry aZipEntry(m_xContext, aZipOut.getChucker(), *pEntry, NULL);
+    aZipOut.putNextEntry(*pEntry);
+    ZipOutputEntry aZipEntry(m_xContext, &aZipOut, *pEntry, NULL);
     aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength);
     aZipEntry.closeEntry();
-    aZipOut.addEntry(pEntry);
+    aZipOut.rawCloseEntry();
 }
 
 void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno::Sequence < PropertyValue > >& aManList )
@@ -1056,7 +1058,7 @@ void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno:
     pEntry->nMethod = DEFLATED;
     pEntry->nCrc = -1;
     pEntry->nSize = pEntry->nCompressedSize = -1;
-    pEntry->nTime = ZipOutputEntry::getCurrentDosTime();
+    pEntry->nTime = ZipOutputStream::getCurrentDosTime();
 
     // Convert vector into a uno::Sequence
     // TODO/LATER: use Defaulst entries in future
@@ -1091,10 +1093,11 @@ void ZipPackage::WriteContentTypes( ZipOutputStream& aZipOut, const vector< uno:
     pBuffer->realloc( nBufferLength );
 
     // there is no encryption in this format currently
-    ZipOutputEntry aZipEntry(m_xContext, aZipOut.getChucker(), *pEntry, NULL);
+    aZipOut.putNextEntry(*pEntry);
+    ZipOutputEntry aZipEntry(m_xContext, &aZipOut, *pEntry, NULL);
     aZipEntry.write(pBuffer->getSequence(), 0, nBufferLength);
     aZipEntry.closeEntry();
-    aZipOut.addEntry(pEntry);
+    aZipOut.rawCloseEntry();
 }
 
 void ZipPackage::ConnectTo( const uno::Reference< io::XInputStream >& xInStream )
diff --git a/package/source/zippackage/ZipPackageFolder.cxx b/package/source/zippackage/ZipPackageFolder.cxx
index c2e5a4f..a6b2e5c 100644
--- a/package/source/zippackage/ZipPackageFolder.cxx
+++ b/package/source/zippackage/ZipPackageFolder.cxx
@@ -21,7 +21,6 @@
 
 #include <ZipPackageFolder.hxx>
 #include <ZipFile.hxx>
-#include <ZipOutputEntry.hxx>
 #include <ZipOutputStream.hxx>
 #include <ZipPackageStream.hxx>
 #include <PackageConstants.hxx>
@@ -338,9 +337,8 @@ void ZipPackageFolder::saveContents(
 
         try
         {
-            ZipOutputEntry aZipEntry(m_xContext, rZipOut.getChucker(), *pTempEntry, NULL, false);
-            aZipEntry.rawCloseEntry();
-            rZipOut.addEntry(pTempEntry);
+            rZipOut.putNextEntry( *pTempEntry );
+            rZipOut.rawCloseEntry();
         }
         catch ( ZipException& )
         {
diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index a4651d7..7547e9c 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -674,7 +674,7 @@ bool ZipPackageStream::saveChild(
             if ( bRawStream )
                 xStream->skipBytes( m_nMagicalHackPos );
 

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list