[Libreoffice-commits] core.git: Branch 'feature/perfwork5' - 18 commits - filter/source include/package package/inc package/source

Matúš Kukan matus.kukan at collabora.com
Wed Nov 5 14:37:06 PST 2014


 filter/source/xsltfilter/OleHandler.cxx          |    2 
 include/package/Deflater.hxx                     |    1 
 package/inc/CRC32.hxx                            |    2 
 package/inc/PackageConstants.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   |  187 +++++++++-----
 package/source/zippackage/wrapstreamforshare.cxx |    4 
 18 files changed, 435 insertions(+), 429 deletions(-)

New commits:
commit d1982b369d8adbd46ebd5c78bf023cb5b8f587b4
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 a570699e7cde8e1734d9655314b1983e217db7da
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Sat Nov 1 12:06:41 2014 +0100

    Test parallelism again.
    
    Change-Id: I495e147b679b770c479eb0bb2c2714d815e5b9e9

diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index c110374..90f0df8 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -797,7 +797,7 @@ bool ZipPackageStream::saveChild(
             }
             else
             {
-                bParallelDeflate = false;
+                bParallelDeflate = true;
                 if (bParallelDeflate)
                 {
                     // Start a new thread deflating this zip entry
commit 1e9d173507126b9bc3df5a80e15446e3b9c57327
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Fri Oct 31 16:55:41 2014 +0100

    package: Increase size of buffers
    
    I just want to see what's going to happen - if anything.
    
    Change-Id: Iba09c261126654ab19fc5755b3923b406db15031

diff --git a/package/inc/PackageConstants.hxx b/package/inc/PackageConstants.hxx
index df7bebc..9336e68 100644
--- a/package/inc/PackageConstants.hxx
+++ b/package/inc/PackageConstants.hxx
@@ -21,7 +21,7 @@
 
 #include <sal/types.h>
 
-const sal_Int32 n_ConstBufferSize = 32768;
+const sal_Int32 n_ConstBufferSize = 524288;
 
 // by calculation of the digest we read 32 bytes more ( if available )
 // it allows to ignore the padding if the stream is longer than n_ConstDigestDecrypt since we read at least two blocks more;
commit 3f4986b6d15b127fd6e033b541098b189181b8aa
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 e14b7a4c5710b5e5cfabdaee57cac85a36c11c27
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 c183158..f0e1c94 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 8d61c6b..c110374 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 094c325110bb849d413a60dc600845bf3535d195
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Mon Oct 27 19:05:07 2014 +0100

    Revert "HACK to avoid expensive and pointless deflating of jpeg files"
    
    This reverts commit 8c10cb5edc6902a96dc265d36faad0a8382b1a4a.

diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index bbdb18d..8d61c6b 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -773,18 +773,8 @@ bool ZipPackageStream::saveChild(
             // the entry is provided to the ZipOutputStream that will delete it
             pAutoTempEntry.release();
 
-            if (pTempEntry->nMethod == STORED || rPath.endsWith(".jpeg"))
+            if (pTempEntry->nMethod == STORED)
             {
-                // Do not try to deflate jpeg files, pretend they are compressed already
-                // Unfortunately we don't know CRC value
-                if (rPath.endsWith(".jpeg"))
-                {
-                    uno::Reference< io::XSeekable > xSeek(xStream, uno::UNO_QUERY);
-                    pTempEntry->nSize = pTempEntry->nCompressedSize = xSeek->getLength();
-                    pTempEntry->nCrc = 0;
-                    pTempEntry->nMethod = STORED;
-                    pTempEntry->nFlag &= ~(pTempEntry->nFlag & 8);
-                }
                 sal_Int32 nLength;
                 uno::Sequence< sal_Int8 > aSeq(n_ConstBufferSize);
                 rZipOut.writeLOC(pTempEntry, bToBeEncrypted);
commit db22872e395bdfd8ad323ef5b4a384e050d8bc42
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Fri Oct 24 14:46:21 2014 +0200

    Disable deflating in a thread
    
    Change-Id: I1803cd61e283bcc20d4d59870121e785bc778f4a

diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index 2a92d0c..bbdb18d 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -798,7 +798,7 @@ bool ZipPackageStream::saveChild(
             }
             else
             {
-                bParallelDeflate = true;
+                bParallelDeflate = false;
                 if (bParallelDeflate)
                 {
                     // Start a new thread deflating this zip entry
commit 4cc661ac4402e4812269a0ecd046a520a5ec5d2b
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 4638871..2a92d0c 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();
     }
 };
@@ -794,9 +799,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 9bdef33768fb68e66386928401a9561a713584f8
Author: Matúš Kukan <matus.kukan at collabora.com>
Date:   Thu Oct 23 09:07:38 2014 +0200

    HACK to avoid expensive and pointless deflating of jpeg files
    
    This is not intended to land in master; it's just for testing.
    
    Change-Id: If93cb78dcef903584de7b23f37282852c6d69f35

diff --git a/package/source/zippackage/ZipPackageStream.cxx b/package/source/zippackage/ZipPackageStream.cxx
index 9f29a68..4638871 100644
--- a/package/source/zippackage/ZipPackageStream.cxx
+++ b/package/source/zippackage/ZipPackageStream.cxx
@@ -768,8 +768,18 @@ bool ZipPackageStream::saveChild(
             // the entry is provided to the ZipOutputStream that will delete it
             pAutoTempEntry.release();
 
-            if (pTempEntry->nMethod == STORED)
+            if (pTempEntry->nMethod == STORED || rPath.endsWith(".jpeg"))
             {
+                // Do not try to deflate jpeg files, pretend they are compressed already
+                // Unfortunately we don't know CRC value
+                if (rPath.endsWith(".jpeg"))
+                {
+                    uno::Reference< io::XSeekable > xSeek(xStream, uno::UNO_QUERY);
+                    pTempEntry->nSize = pTempEntry->nCompressedSize = xSeek->getLength();
+                    pTempEntry->nCrc = 0;
+                    pTempEntry->nMethod = STORED;
+                    pTempEntry->nFlag &= ~(pTempEntry->nFlag & 8);
+                }
                 sal_Int32 nLength;
                 uno::Sequence< sal_Int8 > aSeq(n_ConstBufferSize);
                 rZipOut.writeLOC(pTempEntry, bToBeEncrypted);
commit c95b2483e6c4f73043934d267394f74df6c2c239
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 6a3d70465288aa64c9665b524e6720186e59baf3
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 3eb1c1e..c183158 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 a88b5944cc10d44fc1c6ce3277b3baad20c8b2ef
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 62bc0dcfb83eb462fb21ba5b5f970992410cc6ff
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 4847e143f8ffd8e3fbd41b7cc0fcf423f2b7561d
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 d587b3a..3eb1c1e 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 d10d70d8181753426f9c816cdd2ffca246b2c48c
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 e639042357efda281cb28d0707b2d683be64360a
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 308a153..d587b3a 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 c11ca6a616f29b5c5ccad0acfac044400a1fa076
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 d210d45..308a153 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 );

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list