summaryrefslogtreecommitdiff
path: root/package/source/zipapi
diff options
context:
space:
mode:
Diffstat (limited to 'package/source/zipapi')
-rw-r--r--package/source/zipapi/ByteChucker.cxx112
-rw-r--r--package/source/zipapi/ByteGrabber.cxx191
-rw-r--r--package/source/zipapi/CRC32.cxx96
-rw-r--r--package/source/zipapi/Deflater.cxx212
-rw-r--r--package/source/zipapi/EntryInputStream.cxx201
-rw-r--r--package/source/zipapi/EntryInputStream.hxx86
-rw-r--r--package/source/zipapi/Inflater.cxx162
-rw-r--r--package/source/zipapi/MemoryByteGrabber.hxx177
-rw-r--r--package/source/zipapi/XFileStream.cxx227
-rw-r--r--package/source/zipapi/XFileStream.hxx96
-rw-r--r--package/source/zipapi/XMemoryStream.cxx52
-rw-r--r--package/source/zipapi/XMemoryStream.hxx42
-rw-r--r--package/source/zipapi/XUnbufferedStream.cxx360
-rw-r--r--package/source/zipapi/XUnbufferedStream.hxx108
-rw-r--r--package/source/zipapi/ZipEnumeration.cxx53
-rw-r--r--package/source/zipapi/ZipFile.cxx1057
-rw-r--r--package/source/zipapi/ZipOutputStream.cxx429
-rw-r--r--package/source/zipapi/makefile.mk59
18 files changed, 3720 insertions, 0 deletions
diff --git a/package/source/zipapi/ByteChucker.cxx b/package/source/zipapi/ByteChucker.cxx
new file mode 100644
index 000000000000..3b93c4696148
--- /dev/null
+++ b/package/source/zipapi/ByteChucker.cxx
@@ -0,0 +1,112 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ByteChucker.hxx>
+#include <PackageConstants.hxx>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+using namespace ::com::sun::star::io;
+using namespace ::com::sun::star::uno;
+using namespace ::com::sun::star::lang;
+
+ByteChucker::ByteChucker(Reference<XOutputStream> xOstream)
+: xStream(xOstream)
+, xSeek (xOstream, UNO_QUERY )
+, a1Sequence ( 1 )
+, a2Sequence ( 2 )
+, a4Sequence ( 4 )
+, p1Sequence ( a1Sequence.getArray() )
+, p2Sequence ( a2Sequence.getArray() )
+, p4Sequence ( a4Sequence.getArray() )
+{
+}
+
+ByteChucker::~ByteChucker()
+{
+}
+
+void ByteChucker::WriteBytes( const Sequence< sal_Int8 >& aData )
+ throw(NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ xStream->writeBytes(aData);
+}
+
+sal_Int64 ByteChucker::GetPosition( )
+ throw(IOException, RuntimeException)
+{
+ return xSeek->getPosition();
+}
+
+ByteChucker& ByteChucker::operator << (sal_Int8 nInt8)
+{
+ p1Sequence[0] = nInt8 & 0xFF;
+ WriteBytes( a1Sequence );
+ return *this;
+}
+
+ByteChucker& ByteChucker::operator << (sal_Int16 nInt16)
+{
+ p2Sequence[0] = static_cast< sal_Int8 >((nInt16 >> 0 ) & 0xFF);
+ p2Sequence[1] = static_cast< sal_Int8 >((nInt16 >> 8 ) & 0xFF);
+ WriteBytes( a2Sequence );
+ return *this;
+}
+ByteChucker& ByteChucker::operator << (sal_Int32 nInt32)
+{
+ p4Sequence[0] = static_cast< sal_Int8 >((nInt32 >> 0 ) & 0xFF);
+ p4Sequence[1] = static_cast< sal_Int8 >((nInt32 >> 8 ) & 0xFF);
+ p4Sequence[2] = static_cast< sal_Int8 >((nInt32 >> 16 ) & 0xFF);
+ p4Sequence[3] = static_cast< sal_Int8 >((nInt32 >> 24 ) & 0xFF);
+ WriteBytes( a4Sequence );
+ return *this;
+}
+
+ByteChucker& ByteChucker::operator << (sal_uInt8 nuInt8)
+{
+ p1Sequence[0] = nuInt8 & 0xFF;
+ WriteBytes( a1Sequence );
+ return *this;
+}
+ByteChucker& ByteChucker::operator << (sal_uInt16 nuInt16)
+{
+ p2Sequence[0] = static_cast< sal_Int8 >((nuInt16 >> 0 ) & 0xFF);
+ p2Sequence[1] = static_cast< sal_Int8 >((nuInt16 >> 8 ) & 0xFF);
+ WriteBytes( a2Sequence );
+ return *this;
+}
+ByteChucker& ByteChucker::operator << (sal_uInt32 nuInt32)
+{
+ p4Sequence[0] = static_cast < sal_Int8 > ((nuInt32 >> 0 ) & 0xFF);
+ p4Sequence[1] = static_cast < sal_Int8 > ((nuInt32 >> 8 ) & 0xFF);
+ p4Sequence[2] = static_cast < sal_Int8 > ((nuInt32 >> 16 ) & 0xFF);
+ p4Sequence[3] = static_cast < sal_Int8 > ((nuInt32 >> 24 ) & 0xFF);
+ WriteBytes( a4Sequence );
+ return *this;
+}
diff --git a/package/source/zipapi/ByteGrabber.cxx b/package/source/zipapi/ByteGrabber.cxx
new file mode 100644
index 000000000000..40998c3de70d
--- /dev/null
+++ b/package/source/zipapi/ByteGrabber.cxx
@@ -0,0 +1,191 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ByteGrabber.hxx>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+
+using namespace ::com::sun::star;
+
+/** ByteGrabber implements the >> operators on an XOutputStream. This is
+ * potentially quite slow and may need to be optimised
+ */
+
+ByteGrabber::ByteGrabber(uno::Reference < io::XInputStream > xIstream)
+: xStream(xIstream)
+, xSeek (xIstream, uno::UNO_QUERY )
+, aSequence ( 4 )
+{
+ pSequence = aSequence.getArray();
+}
+
+ByteGrabber::~ByteGrabber()
+{
+}
+
+void ByteGrabber::setInputStream (uno::Reference < io::XInputStream > xNewStream)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ xStream = xNewStream;
+ xSeek = uno::Reference < io::XSeekable > (xNewStream, uno::UNO_QUERY);
+}
+
+// XInputStream chained
+sal_Int32 SAL_CALL ByteGrabber::readBytes( uno::Sequence< sal_Int8 >& aData,
+ sal_Int32 nBytesToRead )
+ throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ return xStream->readBytes(aData, nBytesToRead );
+}
+
+// XSeekable chained...
+sal_Int64 SAL_CALL ByteGrabber::seek( sal_Int64 location )
+ throw(lang::IllegalArgumentException, io::IOException, uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (xSeek.is() )
+ {
+ sal_Int64 nLen = xSeek->getLength();
+ if ( location < 0 || location > nLen )
+ throw lang::IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
+ if (location > nLen )
+ location = nLen;
+ xSeek->seek( location );
+ return location;
+ }
+ else
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+sal_Int64 SAL_CALL ByteGrabber::getPosition( )
+ throw(io::IOException, uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (xSeek.is() )
+ return xSeek->getPosition();
+ else
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+sal_Int64 SAL_CALL ByteGrabber::getLength( )
+ throw(io::IOException, uno::RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (xSeek.is() )
+ return xSeek->getLength();
+ else
+ throw io::IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+}
+
+ByteGrabber& ByteGrabber::operator >> (sal_Int8& rInt8)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (xStream->readBytes(aSequence,1) != 1)
+ rInt8 = 0;
+ else
+ rInt8 = aSequence[0] & 0xFF;
+ return *this;
+}
+
+ByteGrabber& ByteGrabber::operator >> (sal_Int16& rInt16)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+ if (xStream->readBytes ( aSequence, 2) != 2)
+ rInt16 = 0;
+ else
+ {
+ pSequence = aSequence.getConstArray();
+ rInt16 = static_cast <sal_Int16>
+ ( (pSequence[0] & 0xFF)
+ | (pSequence[1] & 0xFF) << 8);
+ }
+ return *this;
+}
+
+ByteGrabber& ByteGrabber::operator >> (sal_Int32& rInt32)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if (xStream->readBytes(aSequence, 4) != 4)
+ rInt32 = 0;
+ else
+ {
+ pSequence = aSequence.getConstArray();
+ rInt32 = static_cast < sal_Int32 >
+ ( (pSequence[0] & 0xFF)
+ | ( pSequence[1] & 0xFF ) << 8
+ | ( pSequence[2] & 0xFF ) << 16
+ | ( pSequence[3] & 0xFF ) << 24 );
+ }
+ return *this;
+}
+
+ByteGrabber& ByteGrabber::operator >> (sal_uInt8& rInt8)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if (xStream->readBytes(aSequence,1) != 1)
+ rInt8 = 0;
+ else
+ rInt8 = static_cast < sal_uInt8 > (aSequence[0] & 0xFF );
+ return *this;
+}
+ByteGrabber& ByteGrabber::operator >> (sal_uInt16& rInt16)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if (xStream->readBytes(aSequence, 2) != 2)
+ rInt16 = 0;
+ else
+ {
+ pSequence = aSequence.getConstArray();
+ rInt16 = static_cast <sal_uInt16>
+ ( (pSequence[0] & 0xFF)
+ | (pSequence[1] & 0xFF) << 8);
+ }
+ return *this;
+}
+ByteGrabber& ByteGrabber::operator >> (sal_uInt32& ruInt32)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if (xStream->readBytes(aSequence, 4) != 4)
+ ruInt32 = 0;
+ else
+ {
+ pSequence = aSequence.getConstArray();
+ ruInt32 = static_cast < sal_uInt32 >
+ ( (pSequence[0] & 0xFF)
+ | ( pSequence[1] & 0xFF ) << 8
+ | ( pSequence[2] & 0xFF ) << 16
+ | ( pSequence[3] & 0xFF ) << 24 );
+ }
+ return *this;
+}
diff --git a/package/source/zipapi/CRC32.cxx b/package/source/zipapi/CRC32.cxx
new file mode 100644
index 000000000000..2ee6b1feea1a
--- /dev/null
+++ b/package/source/zipapi/CRC32.cxx
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <CRC32.hxx>
+#ifndef _ZLIB_H
+#ifdef SYSTEM_ZLIB
+#include <zlib.h>
+#else
+#include <external/zlib/zlib.h>
+#endif
+#endif
+#include <PackageConstants.hxx>
+#include <com/sun/star/io/XInputStream.hpp>
+
+using namespace rtl;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::io;
+
+/** A class to compute the CRC32 value of a data stream
+ */
+
+CRC32::CRC32()
+: nCRC(0)
+{
+}
+CRC32::~CRC32()
+{
+}
+void SAL_CALL CRC32::reset()
+ throw(RuntimeException)
+{
+ nCRC=0;
+}
+sal_Int32 SAL_CALL CRC32::getValue()
+ throw(RuntimeException)
+{
+ return nCRC & 0xFFFFFFFFL;
+}
+/** Update CRC32 with specified sequence of bytes
+ */
+void SAL_CALL CRC32::updateSegment(const Sequence< sal_Int8 > &b,
+ sal_Int32 off,
+ sal_Int32 len)
+ throw(RuntimeException)
+{
+ nCRC = crc32(nCRC, (const unsigned char*)b.getConstArray()+off, len );
+}
+/** Update CRC32 with specified sequence of bytes
+ */
+void SAL_CALL CRC32::update(const Sequence< sal_Int8 > &b)
+ throw(RuntimeException)
+{
+ nCRC = crc32(nCRC, (const unsigned char*)b.getConstArray(),b.getLength());
+}
+
+sal_Int32 SAL_CALL CRC32::updateStream( Reference < XInputStream > & xStream )
+ throw ( RuntimeException )
+{
+ sal_Int32 nLength, nTotal = 0;
+ Sequence < sal_Int8 > aSeq ( n_ConstBufferSize );
+ do
+ {
+ nLength = xStream->readBytes ( aSeq, n_ConstBufferSize );
+ updateSegment ( aSeq, 0, nLength );
+ nTotal += nLength;
+ }
+ while ( nLength == n_ConstBufferSize );
+
+ return nTotal;
+}
diff --git a/package/source/zipapi/Deflater.cxx b/package/source/zipapi/Deflater.cxx
new file mode 100644
index 000000000000..ac12a8cb5831
--- /dev/null
+++ b/package/source/zipapi/Deflater.cxx
@@ -0,0 +1,212 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <Deflater.hxx>
+#ifndef _ZLIB_H
+#ifdef SYSTEM_ZLIB
+#include <zlib.h>
+#else
+#include <external/zlib/zlib.h>
+#endif
+#endif
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <string.h> // for memset
+
+using namespace com::sun::star::packages::zip::ZipConstants;
+using namespace com::sun::star;
+
+/** Provides general purpose compression using the ZLIB compression
+ * library.
+ */
+
+Deflater::~Deflater(void)
+{
+ end();
+}
+void Deflater::init (sal_Int32 nLevelArg, sal_Int32 nStrategyArg, sal_Bool bNowrap)
+{
+ pStream = new z_stream;
+ /* Memset it to 0...sets zalloc/zfree/opaque to NULL */
+ memset (pStream, 0, sizeof(*pStream));
+
+ switch (deflateInit2(pStream, nLevelArg, Z_DEFLATED, bNowrap? -MAX_WBITS : MAX_WBITS,
+ DEF_MEM_LEVEL, nStrategyArg))
+ {
+ case Z_OK:
+ break;
+ case Z_MEM_ERROR:
+ delete pStream;
+ break;
+ case Z_STREAM_ERROR:
+ delete pStream;
+ break;
+ default:
+ break;
+ }
+}
+
+Deflater::Deflater(sal_Int32 nSetLevel, sal_Bool bNowrap)
+: bFinish(sal_False)
+, bFinished(sal_False)
+, bSetParams(sal_False)
+, nLevel(nSetLevel)
+, nStrategy(DEFAULT_STRATEGY)
+, nOffset(0)
+, nLength(0)
+{
+ init(nSetLevel, DEFAULT_STRATEGY, bNowrap);
+}
+
+sal_Int32 Deflater::doDeflateBytes (uno::Sequence < sal_Int8 > &rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength)
+{
+ sal_Int32 nResult;
+ if (bSetParams)
+ {
+ pStream->next_in = (unsigned char*) sInBuffer.getConstArray() + nOffset;
+ pStream->next_out = (unsigned char*) rBuffer.getArray()+nNewOffset;
+ pStream->avail_in = nLength;
+ pStream->avail_out = nNewLength;
+
+#ifdef SYSTEM_ZLIB
+ nResult = deflateParams(pStream, nLevel, nStrategy);
+#else
+ nResult = z_deflateParams(pStream, nLevel, nStrategy);
+#endif
+ switch (nResult)
+ {
+ case Z_OK:
+ bSetParams = sal_False;
+ nOffset += nLength - pStream->avail_in;
+ nLength = pStream->avail_in;
+ return nNewLength - pStream->avail_out;
+ case Z_BUF_ERROR:
+ bSetParams = sal_False;
+ return 0;
+ default:
+ return 0;
+ }
+ }
+ else
+ {
+ pStream->next_in = (unsigned char*) sInBuffer.getConstArray() + nOffset;
+ pStream->next_out = (unsigned char*) rBuffer.getArray()+nNewOffset;
+ pStream->avail_in = nLength;
+ pStream->avail_out = nNewLength;
+
+#ifdef SYSTEM_ZLIB
+ nResult = deflate(pStream, bFinish ? Z_FINISH : Z_NO_FLUSH);
+#else
+ nResult = z_deflate(pStream, bFinish ? Z_FINISH : Z_NO_FLUSH);
+#endif
+ switch (nResult)
+ {
+ case Z_STREAM_END:
+ bFinished = sal_True;
+ case Z_OK:
+ nOffset += nLength - pStream->avail_in;
+ nLength = pStream->avail_in;
+ return nNewLength - pStream->avail_out;
+ case Z_BUF_ERROR:
+ bSetParams = sal_False;
+ return 0;
+ default:
+ return 0;
+ }
+ }
+}
+
+void SAL_CALL Deflater::setInputSegment( const uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
+{
+ OSL_ASSERT( !(nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > rBuffer.getLength()));
+
+ sInBuffer = rBuffer;
+ nOffset = nNewOffset;
+ nLength = nNewLength;
+}
+void SAL_CALL Deflater::setLevel( sal_Int32 nNewLevel )
+{
+ if ((nNewLevel < 0 || nNewLevel > 9) && nNewLevel != DEFAULT_COMPRESSION)
+ {
+ // do error handling
+ }
+ if (nNewLevel != nLevel)
+ {
+ nLevel = nNewLevel;
+ bSetParams = sal_True;
+ }
+}
+sal_Bool SAL_CALL Deflater::needsInput( )
+{
+ return nLength <=0;
+}
+void SAL_CALL Deflater::finish( )
+{
+ bFinish = sal_True;
+}
+sal_Bool SAL_CALL Deflater::finished( )
+{
+ return bFinished;
+}
+sal_Int32 SAL_CALL Deflater::doDeflateSegment( uno::Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
+{
+ OSL_ASSERT( !(nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > rBuffer.getLength()));
+ return doDeflateBytes(rBuffer, nNewOffset, nNewLength);
+}
+sal_Int32 SAL_CALL Deflater::getTotalIn( )
+{
+ return pStream->total_in;
+}
+sal_Int32 SAL_CALL Deflater::getTotalOut( )
+{
+ return pStream->total_out;
+}
+void SAL_CALL Deflater::reset( )
+{
+#ifdef SYSTEM_ZLIB
+ deflateReset(pStream);
+#else
+ z_deflateReset(pStream);
+#endif
+ bFinish = sal_False;
+ bFinished = sal_False;
+ nOffset = nLength = 0;
+}
+void SAL_CALL Deflater::end( )
+{
+ if (pStream != NULL)
+ {
+#ifdef SYSTEM_ZLIB
+ deflateEnd(pStream);
+#else
+ z_deflateEnd(pStream);
+#endif
+ delete pStream;
+ }
+ pStream = NULL;
+}
diff --git a/package/source/zipapi/EntryInputStream.cxx b/package/source/zipapi/EntryInputStream.cxx
new file mode 100644
index 000000000000..671ef7381f9d
--- /dev/null
+++ b/package/source/zipapi/EntryInputStream.cxx
@@ -0,0 +1,201 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <EntryInputStream.hxx>
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <rtl/cipher.h>
+#include <rtl/digest.h>
+#include <memory.h> // for memcpy
+
+using namespace rtl;
+using namespace com::sun::star;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::packages::zip;
+using namespace com::sun::star::packages::zip::ZipConstants;
+
+/** Provides access to the compressed data in a zipfile.
+ *
+ * 04/12/00 - uncompresses the stream into memory and seeks on it 'in memory'
+ * This and the ZipPackageBuffer used in the ZipOutputStream are memory hogs
+ * and will hopefully be replaced eventually
+ *
+ * Acts on the same underlying XInputStream as both the full Zip File and other
+ * EntryInputStreams, and thus must maintain its current position in the stream and
+ * seek to it before performing any reads.
+ */
+
+EntryInputStream::EntryInputStream( Reference < io::XInputStream > xNewInput,
+ const ZipEntry & rNewEntry,
+ const vos::ORef < EncryptionData > &xEncryptData,
+ sal_Bool bGetRawStream)
+: xStream( xNewInput )
+, xSeek( xNewInput, UNO_QUERY )
+, aEntry (rNewEntry )
+, nCurrent( 0 )
+, bHaveInMemory ( sal_False )
+, aInflater( sal_True )
+, aBuffer( 0 )
+, xEncryptionData (xEncryptData)
+, bRawStream (bGetRawStream)
+{
+ if (bGetRawStream)
+ {
+ nUncompressedSize = aEntry.nMethod == DEFLATED ? aEntry.nCompressedSize : aEntry.nSize;
+ nEnd = aEntry.nOffset + nUncompressedSize;
+ }
+ else
+ {
+ nEnd = aEntry.nMethod == DEFLATED ? aEntry.nOffset + aEntry.nCompressedSize : aEntry.nOffset + aEntry.nSize;
+ nUncompressedSize = aEntry.nSize;
+ }
+}
+void EntryInputStream::readIntoMemory()
+ throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException)
+{
+ if (!bHaveInMemory)
+ {
+ Sequence < sal_Int8 > aReadBuffer;
+ xSeek->seek(aEntry.nOffset);
+ sal_Int32 nSize = aEntry.nMethod == DEFLATED ? aEntry.nCompressedSize : aEntry.nSize;
+
+ if (nSize <0)
+ throw io::BufferSizeExceededException(::rtl::OUString(), *this);
+
+ xStream->readBytes( aReadBuffer, nSize ); // Now it holds the raw stuff from disk
+
+ if (xEncryptionData->aSalt.getLength())
+ {
+ // Have salt, will travel
+ Sequence < sal_uInt8 > aDerivedKey (16);
+ rtlCipherError aResult;
+ Sequence < sal_Int8 > aDecryptBuffer;
+
+ // Get the key
+ rtl_digest_PBKDF2 ( aDerivedKey.getArray(), 16,
+ reinterpret_cast < const sal_uInt8 * > (xEncryptionData->aKey.getConstArray()),
+ xEncryptionData->aKey.getLength(),
+ xEncryptionData->aSalt.getConstArray(),
+ xEncryptionData->aSalt.getLength(),
+ xEncryptionData->nIterationCount );
+
+ rtlCipher aCipher = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream);
+ aResult = rtl_cipher_init( aCipher, rtl_Cipher_DirectionDecode,
+ aDerivedKey.getConstArray(),
+ aDerivedKey.getLength(),
+ xEncryptionData->aInitVector.getConstArray(),
+ xEncryptionData->aInitVector.getLength());
+ OSL_ASSERT (aResult == rtl_Cipher_E_None);
+ aDecryptBuffer.realloc ( nSize );
+ aResult = rtl_cipher_decode ( aCipher,
+ aReadBuffer.getConstArray(),
+ nSize,
+ reinterpret_cast < sal_uInt8 * > (aDecryptBuffer.getArray()),
+ nSize);
+ OSL_ASSERT (aResult == rtl_Cipher_E_None);
+ aReadBuffer = aDecryptBuffer; // Now it holds the decrypted data
+ }
+ if (bRawStream || aEntry.nMethod == STORED)
+ aBuffer = aReadBuffer; // bRawStream means the caller doesn't want it decompressed
+ else
+ {
+ aInflater.setInputSegment(aReadBuffer, 0, nSize );
+ aBuffer.realloc( aEntry.nSize );
+ aInflater.doInflate(aBuffer);
+ aInflater.end();
+ }
+ bHaveInMemory = sal_True;
+ }
+}
+EntryInputStream::~EntryInputStream( void )
+{
+}
+
+sal_Int32 SAL_CALL EntryInputStream::readBytes( Sequence< sal_Int8 >& aData,
+ sal_Int32 nBytesToRead )
+ throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException)
+{
+ if (nBytesToRead <0)
+ throw io::BufferSizeExceededException(::rtl::OUString(), *this);
+ if (!bHaveInMemory)
+ readIntoMemory();
+ if (nBytesToRead + nCurrent > nUncompressedSize)
+ nBytesToRead = static_cast < sal_Int32> ( nUncompressedSize - nCurrent );
+
+ aData.realloc( nBytesToRead );
+ memcpy(aData.getArray(), aBuffer.getConstArray() + nCurrent, nBytesToRead);
+ nCurrent+=nBytesToRead;
+
+ return nBytesToRead;
+}
+sal_Int32 SAL_CALL EntryInputStream::readSomeBytes( Sequence< sal_Int8 >& aData,
+ sal_Int32 nMaxBytesToRead )
+ throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException)
+{
+ return readBytes( aData, nMaxBytesToRead );
+}
+void SAL_CALL EntryInputStream::skipBytes( sal_Int32 nBytesToSkip )
+ throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException)
+{
+ if (nBytesToSkip < 0)
+ throw io::BufferSizeExceededException(::rtl::OUString(), *this);
+
+ if (nBytesToSkip + nCurrent > nUncompressedSize)
+ nBytesToSkip = static_cast < sal_Int32 > (nUncompressedSize- nCurrent);
+
+ nCurrent+=nBytesToSkip;
+}
+sal_Int32 SAL_CALL EntryInputStream::available( )
+ throw(io::NotConnectedException, io::IOException, RuntimeException)
+{
+ return static_cast < sal_Int32 > (nUncompressedSize - nCurrent);
+}
+void SAL_CALL EntryInputStream::closeInput( )
+ throw(io::NotConnectedException, io::IOException, RuntimeException)
+{
+}
+
+void SAL_CALL EntryInputStream::seek( sal_Int64 location )
+ throw(lang::IllegalArgumentException, io::IOException, RuntimeException)
+{
+ if (location > nUncompressedSize)
+ location = nUncompressedSize;
+ if (location <0)
+ location = 0;
+ nCurrent = location;
+}
+sal_Int64 SAL_CALL EntryInputStream::getPosition( )
+ throw(io::IOException, RuntimeException)
+{
+ return nCurrent;
+}
+sal_Int64 SAL_CALL EntryInputStream::getLength( )
+ throw(io::IOException, RuntimeException)
+{
+ return nUncompressedSize;
+}
diff --git a/package/source/zipapi/EntryInputStream.hxx b/package/source/zipapi/EntryInputStream.hxx
new file mode 100644
index 000000000000..c04a5dc2d33b
--- /dev/null
+++ b/package/source/zipapi/EntryInputStream.hxx
@@ -0,0 +1,86 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _ENTRY_INPUT_STREAM_HXX
+#define _ENTRY_INPUT_STREAM_HXX
+
+#include <cppuhelper/implbase2.hxx> // helper for implementations
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <Inflater.hxx>
+#include <com/sun/star/packages/zip/ZipEntry.hpp>
+#ifndef _VOS_REF_H_
+#include <vos/ref.hxx>
+#endif
+#ifndef _ENCRYPTION_DATA_HXX
+#include <EncryptionData.hxx>
+#endif
+class EntryInputStream : public cppu::WeakImplHelper2< com::sun::star::io::XInputStream,
+ com::sun::star::io::XSeekable >
+{
+protected:
+ com::sun::star::uno::Reference< com::sun::star::io::XInputStream > xStream;
+ com::sun::star::uno::Reference< com::sun::star::io::XSeekable > xSeek;
+ sal_Int64 nEnd, nCurrent, nUncompressedSize;
+ sal_Bool bRawStream, bHaveInMemory, bEncrypted;
+ com::sun::star::uno::Sequence < sal_Int8 > aBuffer;
+ const vos::ORef < EncryptionData > xEncryptionData;
+ const com::sun::star::packages::zip::ZipEntry aEntry;
+ Inflater aInflater;
+ void readIntoMemory()
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+public:
+ EntryInputStream( com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xInput,
+ const com::sun::star::packages::zip::ZipEntry &rNewEntry,
+ const vos::ORef < EncryptionData > &xEncryptData,
+ sal_Bool bGetRawStream = sal_False);
+ virtual ~EntryInputStream();
+
+ // XInputStream
+ virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL available( )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL closeInput( )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ // XSeekable
+ virtual void SAL_CALL seek( sal_Int64 location )
+ throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int64 SAL_CALL getPosition( )
+ throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int64 SAL_CALL getLength( )
+ throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ /*
+private:
+ void fill( void );
+ */
+};
+
+#endif
diff --git a/package/source/zipapi/Inflater.cxx b/package/source/zipapi/Inflater.cxx
new file mode 100644
index 000000000000..e95809a35dad
--- /dev/null
+++ b/package/source/zipapi/Inflater.cxx
@@ -0,0 +1,162 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <Inflater.hxx>
+#ifndef _ZLIB_H
+#ifdef SYSTEM_ZLIB
+#include <zlib.h>
+#else
+#include <external/zlib/zlib.h>
+#endif
+#endif
+#include <string.h> // for memset
+
+using namespace com::sun::star::uno;
+
+/** Provides general purpose decompression using the ZLIB library */
+
+Inflater::Inflater(sal_Bool bNoWrap)
+: bFinished(sal_False),
+ bSetParams(sal_False),
+ bNeedDict(sal_False),
+ nOffset(0),
+ nLength(0),
+ nLastInflateError(0),
+ pStream(NULL)
+{
+ pStream = new z_stream;
+ /* memset to 0 to set zalloc/opaque etc */
+ memset (pStream, 0, sizeof(*pStream));
+ sal_Int32 nRes;
+ nRes = inflateInit2(pStream, bNoWrap ? -MAX_WBITS : MAX_WBITS);
+ switch (nRes)
+ {
+ case Z_OK:
+ break;
+ case Z_MEM_ERROR:
+ delete pStream;
+ break;
+ case Z_STREAM_ERROR:
+ delete pStream;
+ break;
+ default:
+ break;
+ }
+}
+
+Inflater::~Inflater()
+{
+ end();
+}
+
+void SAL_CALL Inflater::setInput( const Sequence< sal_Int8 >& rBuffer )
+{
+ sInBuffer = rBuffer;
+ nOffset = 0;
+ nLength = rBuffer.getLength();
+}
+
+sal_Bool SAL_CALL Inflater::needsDictionary( )
+{
+ return bNeedDict;
+}
+
+sal_Bool SAL_CALL Inflater::finished( )
+{
+ return bFinished;
+}
+
+sal_Int32 SAL_CALL Inflater::doInflateSegment( Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
+{
+ if (nNewOffset < 0 || nNewLength < 0 || nNewOffset + nNewLength > rBuffer.getLength())
+ {
+ // do error handling
+ }
+ return doInflateBytes(rBuffer, nNewOffset, nNewLength);
+}
+
+void SAL_CALL Inflater::end( )
+{
+ if (pStream != NULL)
+ {
+#ifdef SYSTEM_ZLIB
+ inflateEnd(pStream);
+#else
+ z_inflateEnd(pStream);
+#endif
+ delete pStream;
+ }
+ pStream = NULL;
+}
+
+sal_Int32 Inflater::doInflateBytes (Sequence < sal_Int8 > &rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength)
+{
+ if ( !pStream )
+ {
+ nLastInflateError = Z_STREAM_ERROR;
+ return 0;
+ }
+
+ nLastInflateError = 0;
+
+ pStream->next_in = ( unsigned char* ) ( sInBuffer.getConstArray() + nOffset );
+ pStream->avail_in = nLength;
+ pStream->next_out = reinterpret_cast < unsigned char* > ( rBuffer.getArray() + nNewOffset );
+ pStream->avail_out = nNewLength;
+
+#ifdef SYSTEM_ZLIB
+ sal_Int32 nResult = ::inflate(pStream, Z_PARTIAL_FLUSH);
+#else
+ sal_Int32 nResult = ::z_inflate(pStream, Z_PARTIAL_FLUSH);
+#endif
+
+ switch (nResult)
+ {
+ case Z_STREAM_END:
+ bFinished = sal_True;
+ case Z_OK:
+ nOffset += nLength - pStream->avail_in;
+ nLength = pStream->avail_in;
+ return nNewLength - pStream->avail_out;
+
+ case Z_NEED_DICT:
+ bNeedDict = sal_True;
+ nOffset += nLength - pStream->avail_in;
+ nLength = pStream->avail_in;
+ return 0;
+
+ default:
+ // it is no error, if there is no input or no output
+ if ( nLength && nNewLength )
+ nLastInflateError = nResult;
+ }
+
+ return 0;
+}
+
diff --git a/package/source/zipapi/MemoryByteGrabber.hxx b/package/source/zipapi/MemoryByteGrabber.hxx
new file mode 100644
index 000000000000..8a8d96556bae
--- /dev/null
+++ b/package/source/zipapi/MemoryByteGrabber.hxx
@@ -0,0 +1,177 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _MEMORY_BYTE_GRABBER_HXX_
+#define _MEMORY_BYTE_GRABBER_HXX_
+
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <string.h>
+
+class MemoryByteGrabber
+{
+protected:
+ const com::sun::star::uno::Sequence < sal_Int8 > maBuffer;
+ const sal_Int8 *mpBuffer;
+ sal_Int32 mnCurrent, mnEnd;
+public:
+ MemoryByteGrabber ( const com::sun::star::uno::Sequence < sal_Int8 > & rBuffer )
+ : maBuffer ( rBuffer )
+ , mpBuffer ( rBuffer.getConstArray() )
+ , mnCurrent ( 0 )
+ , mnEnd ( rBuffer.getLength() )
+ {
+ }
+ MemoryByteGrabber()
+ {
+ }
+ const sal_Int8 * getCurrentPos () { return mpBuffer + mnCurrent; }
+
+ // XInputStream chained
+ sal_Int32 SAL_CALL readBytes( com::sun::star::uno::Sequence< sal_Int8 >& aData,
+ sal_Int32 nBytesToRead )
+ throw(com::sun::star::io::NotConnectedException, com::sun::star::io::BufferSizeExceededException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+ {
+ if ( nBytesToRead < 0)
+ throw com::sun::star::io::BufferSizeExceededException();
+
+ if (nBytesToRead + mnCurrent > mnEnd)
+ nBytesToRead = mnEnd - mnCurrent;
+
+ aData.realloc ( nBytesToRead );
+ memcpy ( aData.getArray(), mpBuffer + mnCurrent, nBytesToRead );
+ mnCurrent += nBytesToRead;
+ return nBytesToRead;
+ }
+
+ sal_Int32 SAL_CALL readSomeBytes( com::sun::star::uno::Sequence< sal_Int8 >& aData,
+ sal_Int32 nMaxBytesToRead )
+ throw(com::sun::star::io::NotConnectedException, com::sun::star::io::BufferSizeExceededException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+ {
+ return readBytes( aData, nMaxBytesToRead );
+ }
+ void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
+ throw(com::sun::star::io::NotConnectedException, com::sun::star::io::BufferSizeExceededException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+ {
+ mnCurrent += nBytesToSkip;
+ }
+ sal_Int32 SAL_CALL available( )
+ throw(com::sun::star::io::NotConnectedException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+ {
+ return mnEnd - mnCurrent;
+ }
+ void SAL_CALL closeInput( )
+ throw(com::sun::star::io::NotConnectedException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+ {
+ }
+
+ // XSeekable chained...
+ sal_Int64 SAL_CALL seek( sal_Int64 location )
+ throw(com::sun::star::lang::IllegalArgumentException, com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+ {
+ if ( location < 0 || location > mnEnd )
+ throw com::sun::star::lang::IllegalArgumentException ();
+ mnCurrent = static_cast < sal_Int32 > ( location );
+ return mnCurrent;
+ }
+ sal_Int64 SAL_CALL getPosition( )
+ throw(com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+ {
+ return mnCurrent;
+ }
+ sal_Int64 SAL_CALL getLength( )
+ throw(com::sun::star::io::IOException, com::sun::star::uno::RuntimeException)
+ {
+ return mnEnd;
+ }
+ MemoryByteGrabber& operator >> (sal_Int8& rInt8)
+ {
+ if (mnCurrent + 1 > mnEnd )
+ rInt8 = 0;
+ else
+ rInt8 = mpBuffer [mnCurrent++] & 0xFF;
+ return *this;
+ }
+ MemoryByteGrabber& operator >> (sal_Int16& rInt16)
+ {
+ if (mnCurrent + 2 > mnEnd )
+ rInt16 = 0;
+ else
+ {
+ rInt16 = mpBuffer[mnCurrent++] & 0xFF;
+ rInt16 |= ( mpBuffer[mnCurrent++] & 0xFF ) << 8;
+ }
+ return *this;
+ }
+ MemoryByteGrabber& operator >> (sal_Int32& rInt32)
+ {
+ if (mnCurrent + 4 > mnEnd )
+ rInt32 = 0;
+ else
+ {
+ rInt32 = mpBuffer[mnCurrent++] & 0xFF;
+ rInt32 |= ( mpBuffer[mnCurrent++] & 0xFF ) << 8;
+ rInt32 |= ( mpBuffer[mnCurrent++] & 0xFF ) << 16;
+ rInt32 |= ( mpBuffer[mnCurrent++] & 0xFF ) << 24;
+ }
+ return *this;
+ }
+
+ MemoryByteGrabber& operator >> (sal_uInt8& rInt8)
+ {
+ if (mnCurrent + 1 > mnEnd )
+ rInt8 = 0;
+ else
+ rInt8 = mpBuffer [mnCurrent++] & 0xFF;
+ return *this;
+ }
+ MemoryByteGrabber& operator >> (sal_uInt16& rInt16)
+ {
+ if (mnCurrent + 2 > mnEnd )
+ rInt16 = 0;
+ else
+ {
+ rInt16 = mpBuffer [mnCurrent++] & 0xFF;
+ rInt16 |= ( mpBuffer [mnCurrent++] & 0xFF ) << 8;
+ }
+ return *this;
+ }
+ MemoryByteGrabber& operator >> (sal_uInt32& rInt32)
+ {
+ if (mnCurrent + 4 > mnEnd )
+ rInt32 = 0;
+ else
+ {
+ rInt32 = mpBuffer [mnCurrent++] & 0xFF;
+ rInt32 |= ( mpBuffer [mnCurrent++] & 0xFF ) << 8;
+ rInt32 |= ( mpBuffer [mnCurrent++] & 0xFF ) << 16;
+ rInt32 |= ( mpBuffer [mnCurrent++] & 0xFF ) << 24;
+ }
+ return *this;
+ }
+};
+
+#endif
diff --git a/package/source/zipapi/XFileStream.cxx b/package/source/zipapi/XFileStream.cxx
new file mode 100644
index 000000000000..9e7156ee82b3
--- /dev/null
+++ b/package/source/zipapi/XFileStream.cxx
@@ -0,0 +1,227 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <XFileStream.hxx>
+#include <EncryptionData.hxx>
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <PackageConstants.hxx>
+#include <rtl/cipher.h>
+#include <ZipFile.hxx>
+#include <EncryptedDataHeader.hxx>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+using namespace com::sun::star::packages::zip::ZipConstants;
+using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
+using com::sun::star::lang::IllegalArgumentException;
+using ::rtl::OUString;
+
+XFileStream::XFileStream( ZipEntry & rEntry,
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream,
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewTempStream,
+ const vos::ORef < EncryptionData > &rData,
+ sal_Bool bNewRawStream,
+ sal_Bool bIsEncrypted )
+: maEntry ( rEntry )
+, mxData ( rData )
+, mbRawStream ( bNewRawStream )
+, mbFinished ( sal_False )
+, mxTempIn ( xNewTempStream )
+, mxTempSeek ( xNewTempStream, UNO_QUERY )
+, mxTempOut ( xNewTempStream, UNO_QUERY )
+, mxZipStream ( xNewZipStream )
+, mxZipSeek ( xNewZipStream, UNO_QUERY )
+, maInflater ( sal_True )
+, maCipher ( NULL )
+{
+ mnZipCurrent = maEntry.nOffset;
+ if (mbRawStream)
+ {
+ mnZipSize = maEntry.nMethod == DEFLATED ? maEntry.nCompressedSize : maEntry.nSize;
+ mnZipEnd = maEntry.nOffset + mnZipSize;
+ }
+ else
+ {
+ mnZipSize = maEntry.nSize;
+ mnZipEnd = maEntry.nMethod == DEFLATED ? maEntry.nOffset + maEntry.nCompressedSize : maEntry.nOffset + maEntry.nSize;
+ }
+
+ if ( bIsEncrypted )
+ {
+ sal_Bool bHaveEncryptData = ( !rData.isEmpty() && rData->aSalt.getLength() && rData->aInitVector.getLength() && rData->nIterationCount != 0 ) ? sal_True : sal_False;
+
+ // if we have all the encrypted data, and want a raw stream, then prepend it to the stream, otherwise
+ // make a cipher so we can decrypt it
+ if ( bHaveEncryptData )
+ {
+ if ( !bNewRawStream )
+ ZipFile::StaticGetCipher ( rData, maCipher, sal_True );
+ else
+ {
+ // Put in the EncryptedDataHeader
+ Sequence < sal_Int8 > aEncryptedDataHeader ( n_ConstHeaderSize +
+ rData->aInitVector.getLength() +
+ rData->aSalt.getLength() +
+ rData->aDigest.getLength() );
+ sal_Int8 * pHeader = aEncryptedDataHeader.getArray();
+ ZipFile::StaticFillHeader ( rData, rEntry.nSize, pHeader );
+ mxTempOut->writeBytes ( aEncryptedDataHeader );
+ mnZipSize += mxTempSeek->getPosition();
+ mxTempSeek->seek ( 0 );
+ }
+ }
+ }
+}
+
+XFileStream::~XFileStream()
+{
+ if ( maCipher )
+ rtl_cipher_destroy ( maCipher );
+}
+
+void XFileStream::fill( sal_Int64 nUntil)
+{
+ sal_Int32 nRead;
+ sal_Int64 nPosition = mxTempSeek->getPosition();
+ mxTempSeek->seek ( mxTempSeek->getLength() );
+ maBuffer.realloc ( n_ConstBufferSize );
+
+ while ( mxTempSeek->getLength() < nUntil )
+ {
+ if ( !mbRawStream )
+ {
+ while ( 0 == ( nRead = maInflater.doInflate( maBuffer ) ) )
+ {
+ if ( maInflater.finished() || maInflater.needsDictionary() )
+ {
+ // some error handling ?
+ return;
+ }
+
+ sal_Int64 nDiff = mnZipEnd - mnZipCurrent;
+ if ( nDiff > 0 )
+ {
+ mxZipSeek->seek ( mnZipCurrent );
+ nRead = mxZipStream->readBytes ( maCompBuffer, static_cast < sal_Int32 > ( nDiff < n_ConstBufferSize ? nDiff : n_ConstBufferSize ) );
+ mnZipCurrent += nRead;
+ // maCompBuffer now has the uncompressed data, check if we need to decrypt
+ // before passing to the Inflater
+ if ( maCipher )
+ {
+ Sequence < sal_Int8 > aCryptBuffer ( nRead );
+ rtlCipherError aResult = rtl_cipher_decode ( maCipher,
+ maCompBuffer.getConstArray(),
+ nRead,
+ reinterpret_cast < sal_uInt8 * > (aCryptBuffer.getArray()),
+ nRead);
+ OSL_ASSERT (aResult == rtl_Cipher_E_None);
+ maCompBuffer = aCryptBuffer; // Now it holds the decrypted data
+
+ }
+ maInflater.setInput ( maCompBuffer );
+ }
+ else
+ {
+ // some error handling ?
+ return;
+ }
+ }
+ }
+ else
+ {
+ sal_Int64 nDiff = mnZipEnd - mnZipCurrent;
+ mxZipSeek->seek ( mnZipCurrent );
+ nRead = mxZipStream->readBytes ( maBuffer, static_cast < sal_Int32 > ( nDiff < n_ConstBufferSize ? nDiff : n_ConstBufferSize ) );
+ mnZipCurrent += nRead;
+ }
+ Sequence < sal_Int8 > aTmpBuffer ( maBuffer.getConstArray(), nRead );
+ mxTempOut->writeBytes ( aTmpBuffer );
+ }
+ mxTempSeek->seek ( nPosition );
+}
+
+sal_Int32 SAL_CALL XFileStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ sal_Int64 nPosition = mxTempSeek->getPosition();
+ if ( nPosition + nBytesToRead > mnZipSize )
+ nBytesToRead = static_cast < sal_Int32 > ( mnZipSize - nPosition );
+
+ sal_Int64 nUntil = nBytesToRead + nPosition + n_ConstBufferSize;
+ if (nUntil > mnZipSize )
+ nUntil = mnZipSize;
+ if ( nUntil > mxTempSeek->getLength() )
+ fill ( nUntil );
+ sal_Int32 nRead = mxTempIn->readBytes ( aData, nBytesToRead );
+ return nRead;
+}
+
+sal_Int32 SAL_CALL XFileStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+ throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ return readBytes ( aData, nMaxBytesToRead );
+}
+void SAL_CALL XFileStream::skipBytes( sal_Int32 nBytesToSkip )
+ throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ seek ( mxTempSeek->getPosition() + nBytesToSkip );
+}
+
+sal_Int32 SAL_CALL XFileStream::available( )
+ throw( NotConnectedException, IOException, RuntimeException)
+{
+ return static_cast < sal_Int32 > ( mnZipSize - mxTempSeek->getPosition() );
+}
+
+void SAL_CALL XFileStream::closeInput( )
+ throw( NotConnectedException, IOException, RuntimeException)
+{
+}
+void SAL_CALL XFileStream::seek( sal_Int64 location )
+ throw( IllegalArgumentException, IOException, RuntimeException)
+{
+ if ( location > mnZipSize || location < 0 )
+ throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >(), 1 );
+ if ( location > mxTempSeek->getLength() )
+ {
+ sal_Int64 nUntil = location + n_ConstBufferSize > mnZipSize ? mnZipSize : location + n_ConstBufferSize;
+ fill ( nUntil );
+ }
+ mxTempSeek->seek ( location );
+}
+sal_Int64 SAL_CALL XFileStream::getPosition( )
+ throw(IOException, RuntimeException)
+{
+ return mxTempSeek->getPosition();
+}
+sal_Int64 SAL_CALL XFileStream::getLength( )
+ throw(IOException, RuntimeException)
+{
+ return mnZipSize;
+}
diff --git a/package/source/zipapi/XFileStream.hxx b/package/source/zipapi/XFileStream.hxx
new file mode 100644
index 000000000000..0cf82c5f35cd
--- /dev/null
+++ b/package/source/zipapi/XFileStream.hxx
@@ -0,0 +1,96 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _XFILE_STREAM_HXX
+#define _XFILE_STREAM_HXX
+
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <cppuhelper/implbase2.hxx>
+#ifndef _VOS_REF_H_
+#include <vos/ref.hxx>
+#endif
+#ifndef _INFLATER_HXX
+#include <Inflater.hxx>
+#endif
+#include <ZipEntry.hxx>
+
+namespace com { namespace sun { namespace star {
+ namespace io { class XOutputStream; }
+} } }
+class EncryptionData;
+typedef void* rtlCipher;
+class XFileStream : public cppu::WeakImplHelper2
+<
+ com::sun::star::io::XInputStream,
+ com::sun::star::io::XSeekable
+>
+{
+protected:
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > mxZipStream;
+ com::sun::star::uno::Reference < com::sun::star::io::XSeekable > mxZipSeek;
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > mxTempIn;
+ com::sun::star::uno::Reference < com::sun::star::io::XSeekable > mxTempSeek;
+ com::sun::star::uno::Reference < com::sun::star::io::XOutputStream > mxTempOut;
+ com::sun::star::uno::Sequence < sal_Int8 > maBuffer, maCompBuffer;
+ ZipEntry maEntry;
+ vos::ORef < EncryptionData > mxData;
+ rtlCipher maCipher;
+ Inflater maInflater;
+ sal_Bool mbRawStream, mbFinished;
+ sal_Int64 mnZipCurrent, mnZipEnd, mnZipSize;
+ void fill( sal_Int64 nUntil );
+
+public:
+ XFileStream( ZipEntry & rEntry,
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream,
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewTempStream,
+ const vos::ORef < EncryptionData > &rData,
+ sal_Bool bRawStream,
+ sal_Bool bIsEncrypted );
+ virtual ~XFileStream();
+
+ // XInputStream
+ virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL available( )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL closeInput( )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ // XSeekable
+ virtual void SAL_CALL seek( sal_Int64 location )
+ throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int64 SAL_CALL getPosition( )
+ throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int64 SAL_CALL getLength( )
+ throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+};
+#endif
diff --git a/package/source/zipapi/XMemoryStream.cxx b/package/source/zipapi/XMemoryStream.cxx
new file mode 100644
index 000000000000..c5ffe9ac874c
--- /dev/null
+++ b/package/source/zipapi/XMemoryStream.cxx
@@ -0,0 +1,52 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <XMemoryStream.hxx>
+
+using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
+
+XMemoryStream::XMemoryStream ( com::sun::star::uno::Sequence < sal_Int8 > & rNewBuffer )
+: ZipPackageBuffer ( rNewBuffer )
+{
+}
+XMemoryStream::~XMemoryStream(void)
+{
+}
+::com::sun::star::uno::Any SAL_CALL XMemoryStream::queryInterface( const com::sun::star::uno::Type& rType )
+ throw(com::sun::star::uno::RuntimeException)
+{
+ return ::cppu::queryInterface ( rType ,
+ // OWeakObject interfaces
+ reinterpret_cast< XInterface* > ( this ) ,
+ static_cast< XWeak* > ( this ) ,
+ // my interfaces
+ static_cast< XInputStream* > ( this ) ,
+ static_cast< XSeekable* > ( this ) );
+}
diff --git a/package/source/zipapi/XMemoryStream.hxx b/package/source/zipapi/XMemoryStream.hxx
new file mode 100644
index 000000000000..89db08a6c4ed
--- /dev/null
+++ b/package/source/zipapi/XMemoryStream.hxx
@@ -0,0 +1,42 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _XMEMORY_STREAM_HXX
+#define _XMEMORY_STREAM_HXX
+
+#include <ZipPackageBuffer.hxx>
+
+class ZipPackage;
+
+class XMemoryStream: public ZipPackageBuffer
+{
+public:
+ XMemoryStream ( com::sun::star::uno::Sequence < sal_Int8 > & rNewBuffer );
+ virtual ~XMemoryStream(void);
+ virtual com::sun::star::uno::Any SAL_CALL queryInterface( const com::sun::star::uno::Type& rType )
+ throw(com::sun::star::uno::RuntimeException);
+};
+#endif
diff --git a/package/source/zipapi/XUnbufferedStream.cxx b/package/source/zipapi/XUnbufferedStream.cxx
new file mode 100644
index 000000000000..a75af35914a1
--- /dev/null
+++ b/package/source/zipapi/XUnbufferedStream.cxx
@@ -0,0 +1,360 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <XUnbufferedStream.hxx>
+#include <EncryptionData.hxx>
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <com/sun/star/packages/zip/ZipIOException.hpp>
+#include <PackageConstants.hxx>
+#include <rtl/cipher.h>
+#include <ZipFile.hxx>
+#include <EncryptedDataHeader.hxx>
+#include <algorithm>
+#include <string.h>
+
+#include <osl/mutex.hxx>
+
+#if 0
+// for debugging purposes here
+#include <com/sun/star/ucb/XSimpleFileAccess.hpp>
+#include <comphelper/processfactory.hxx>
+using namespace ::com::sun::star;
+#endif
+
+using namespace com::sun::star::packages::zip::ZipConstants;
+using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
+using com::sun::star::lang::IllegalArgumentException;
+using com::sun::star::packages::zip::ZipIOException;
+using ::rtl::OUString;
+
+XUnbufferedStream::XUnbufferedStream( SotMutexHolderRef aMutexHolder,
+ ZipEntry & rEntry,
+ Reference < XInputStream > xNewZipStream,
+ const vos::ORef < EncryptionData > &rData,
+ sal_Int8 nStreamMode,
+ sal_Bool bIsEncrypted,
+ const ::rtl::OUString& aMediaType,
+ sal_Bool bRecoveryMode )
+: maMutexHolder( aMutexHolder.Is() ? aMutexHolder : SotMutexHolderRef( new SotMutexHolder ) )
+, mxZipStream ( xNewZipStream )
+, mxZipSeek ( xNewZipStream, UNO_QUERY )
+, maEntry ( rEntry )
+, mxData ( rData )
+, maCipher ( NULL )
+, maInflater ( sal_True )
+, mbRawStream ( nStreamMode == UNBUFF_STREAM_RAW || nStreamMode == UNBUFF_STREAM_WRAPPEDRAW )
+, mbWrappedRaw ( nStreamMode == UNBUFF_STREAM_WRAPPEDRAW )
+, mbFinished ( sal_False )
+, mnHeaderToRead ( 0 )
+, mnZipCurrent ( 0 )
+, mnZipEnd ( 0 )
+, mnZipSize ( 0 )
+, mnMyCurrent ( 0 )
+, mbCheckCRC( !bRecoveryMode )
+{
+ mnZipCurrent = maEntry.nOffset;
+ if ( mbRawStream )
+ {
+ mnZipSize = maEntry.nMethod == DEFLATED ? maEntry.nCompressedSize : maEntry.nSize;
+ mnZipEnd = maEntry.nOffset + mnZipSize;
+ }
+ else
+ {
+ mnZipSize = maEntry.nSize;
+ mnZipEnd = maEntry.nMethod == DEFLATED ? maEntry.nOffset + maEntry.nCompressedSize : maEntry.nOffset + maEntry.nSize;
+ }
+ sal_Bool bHaveEncryptData = ( !rData.isEmpty() && rData->aSalt.getLength() && rData->aInitVector.getLength() && rData->nIterationCount != 0 ) ? sal_True : sal_False;
+ sal_Bool bMustDecrypt = ( nStreamMode == UNBUFF_STREAM_DATA && bHaveEncryptData && bIsEncrypted ) ? sal_True : sal_False;
+
+ if ( bMustDecrypt )
+ ZipFile::StaticGetCipher ( rData, maCipher, sal_True );
+ if ( bHaveEncryptData && mbWrappedRaw && bIsEncrypted )
+ {
+ // if we have the data needed to decrypt it, but didn't want it decrypted (or
+ // we couldn't decrypt it due to wrong password), then we prepend this
+ // data to the stream
+
+ // Make a buffer big enough to hold both the header and the data itself
+ maHeader.realloc ( n_ConstHeaderSize +
+ rData->aInitVector.getLength() +
+ rData->aSalt.getLength() +
+ rData->aDigest.getLength() +
+ aMediaType.getLength() * sizeof( sal_Unicode ) );
+ sal_Int8 * pHeader = maHeader.getArray();
+ ZipFile::StaticFillHeader ( rData, rEntry.nSize, aMediaType, pHeader );
+ mnHeaderToRead = static_cast < sal_Int16 > ( maHeader.getLength() );
+ }
+}
+
+// allows to read package raw stream
+XUnbufferedStream::XUnbufferedStream( const Reference < XInputStream >& xRawStream,
+ const vos::ORef < EncryptionData > &rData )
+: maMutexHolder( new SotMutexHolder )
+, mxZipStream ( xRawStream )
+, mxZipSeek ( xRawStream, UNO_QUERY )
+, mxData ( rData )
+, maCipher ( NULL )
+, maInflater ( sal_True )
+, mbRawStream ( sal_False )
+, mbWrappedRaw ( sal_False )
+, mbFinished ( sal_False )
+, mnHeaderToRead ( 0 )
+, mnZipCurrent ( 0 )
+, mnZipEnd ( 0 )
+, mnZipSize ( 0 )
+, mnMyCurrent ( 0 )
+, mbCheckCRC( sal_False )
+{
+ // for this scenario maEntry is not set !!!
+ OSL_ENSURE( mxZipSeek.is(), "The stream must be seekable!\n" );
+
+ // skip raw header, it must be already parsed to rData
+ mnZipCurrent = n_ConstHeaderSize + rData->aInitVector.getLength() +
+ rData->aSalt.getLength() + rData->aDigest.getLength();
+
+ try {
+ if ( mxZipSeek.is() )
+ mnZipSize = mxZipSeek->getLength();
+ } catch( Exception& )
+ {
+ // in case of problem the size will stay set to 0
+ }
+
+ mnZipEnd = mnZipCurrent + mnZipSize;
+
+ ZipFile::StaticGetCipher ( rData, maCipher, sal_True );
+}
+
+XUnbufferedStream::~XUnbufferedStream()
+{
+ if ( maCipher )
+ rtl_cipher_destroy ( maCipher );
+}
+
+sal_Int32 SAL_CALL XUnbufferedStream::readBytes( Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ ::osl::MutexGuard aGuard( maMutexHolder->GetMutex() );
+
+ sal_Int32 nRequestedBytes = nBytesToRead;
+ OSL_ENSURE( !mnHeaderToRead || mbWrappedRaw, "Only encrypted raw stream can be provided with header!" );
+ if ( mnMyCurrent + nRequestedBytes > mnZipSize + maHeader.getLength() )
+ nRequestedBytes = static_cast < sal_Int32 > ( mnZipSize + maHeader.getLength() - mnMyCurrent );
+
+ sal_Int32 nRead = 0, nLastRead = 0, nTotal = 0;
+ aData.realloc ( nRequestedBytes );
+ if ( nRequestedBytes )
+ {
+ if ( mbRawStream )
+ {
+ sal_Int64 nDiff = mnZipEnd - mnZipCurrent;
+
+ if ( mbWrappedRaw && mnHeaderToRead )
+ {
+ sal_Int16 nHeadRead = static_cast< sal_Int16 >(( nRequestedBytes > mnHeaderToRead ?
+ mnHeaderToRead : nRequestedBytes ));
+ memcpy ( aData.getArray(), maHeader.getConstArray() + maHeader.getLength() - mnHeaderToRead, nHeadRead );
+ mnHeaderToRead = mnHeaderToRead - nHeadRead;
+
+ if ( nHeadRead < nRequestedBytes )
+ {
+ sal_Int32 nToRead = nRequestedBytes - nHeadRead;
+ nToRead = ( nDiff < nToRead ) ? sal::static_int_cast< sal_Int32 >( nDiff ) : nToRead;
+
+ Sequence< sal_Int8 > aPureData( nToRead );
+ mxZipSeek->seek ( mnZipCurrent );
+ nRead = mxZipStream->readBytes ( aPureData, nToRead );
+ mnZipCurrent += nRead;
+
+ aPureData.realloc( nRead );
+ if ( mbCheckCRC )
+ maCRC.update( aPureData );
+
+ aData.realloc( nHeadRead + nRead );
+
+ sal_Int8* pPureBuffer = aPureData.getArray();
+ sal_Int8* pBuffer = aData.getArray();
+ for ( sal_Int32 nInd = 0; nInd < nRead; nInd++ )
+ pBuffer[ nHeadRead + nInd ] = pPureBuffer[ nInd ];
+ }
+
+ nRead += nHeadRead;
+ }
+ else
+ {
+ mxZipSeek->seek ( mnZipCurrent );
+
+ nRead = mxZipStream->readBytes (
+ aData,
+ static_cast < sal_Int32 > ( nDiff < nRequestedBytes ? nDiff : nRequestedBytes ) );
+
+ mnZipCurrent += nRead;
+
+ aData.realloc( nRead );
+ if ( mbWrappedRaw && mbCheckCRC )
+ maCRC.update( aData );
+ }
+ }
+ else
+ {
+ while ( 0 == ( nLastRead = maInflater.doInflateSegment( aData, nRead, aData.getLength() - nRead ) ) ||
+ ( nRead + nLastRead != nRequestedBytes && mnZipCurrent < mnZipEnd ) )
+ {
+ nRead += nLastRead;
+
+ if ( nRead > nRequestedBytes )
+ throw RuntimeException(
+ OUString( RTL_CONSTASCII_USTRINGPARAM( "Should not be possible to read more then requested!" ) ),
+ Reference< XInterface >() );
+
+ if ( maInflater.finished() || maInflater.getLastInflateError() )
+ throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
+ Reference< XInterface >() );
+
+ if ( maInflater.needsDictionary() )
+ throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "Dictionaries are not supported!" ) ),
+ Reference< XInterface >() );
+
+ sal_Int32 nDiff = static_cast < sal_Int32 > ( mnZipEnd - mnZipCurrent );
+ if ( nDiff > 0 )
+ {
+ mxZipSeek->seek ( mnZipCurrent );
+ sal_Int32 nToRead = std::min ( nDiff, std::max ( nRequestedBytes, static_cast< sal_Int32 >( 8192 ) ) );
+ sal_Int32 nZipRead = mxZipStream->readBytes ( maCompBuffer, nToRead );
+ if ( nZipRead < nToRead )
+ throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "No expected data!" ) ),
+ Reference< XInterface >() );
+
+ mnZipCurrent += nZipRead;
+ // maCompBuffer now has the data, check if we need to decrypt
+ // before passing to the Inflater
+ if ( maCipher )
+ {
+ if ( mbCheckCRC )
+ maCRC.update( maCompBuffer );
+
+ Sequence < sal_Int8 > aCryptBuffer ( nZipRead );
+ rtlCipherError aResult =
+ rtl_cipher_decode ( maCipher,
+ maCompBuffer.getConstArray(),
+ nZipRead,
+ reinterpret_cast < sal_uInt8 * > (aCryptBuffer.getArray()),
+ nZipRead);
+ if( aResult != rtl_Cipher_E_None ) {
+ OSL_ASSERT (aResult == rtl_Cipher_E_None);
+ }
+ maCompBuffer = aCryptBuffer; // Now it holds the decrypted data
+
+ }
+ maInflater.setInput ( maCompBuffer );
+ }
+ else
+ {
+ throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
+ Reference< XInterface >() );
+ }
+ }
+ }
+
+ mnMyCurrent += nRead + nLastRead;
+ nTotal = nRead + nLastRead;
+ if ( nTotal < nRequestedBytes)
+ aData.realloc ( nTotal );
+
+ if ( mbCheckCRC && ( !mbRawStream || mbWrappedRaw ) )
+ {
+ if ( !maCipher && !mbWrappedRaw )
+ maCRC.update( aData );
+
+#if 0
+ // for debugging purposes here
+ if ( mbWrappedRaw )
+ {
+ if ( 0 )
+ {
+ uno::Reference< lang::XMultiServiceFactory > xFactory = comphelper::getProcessServiceFactory();
+ uno::Reference< ucb::XSimpleFileAccess > xAccess( xFactory->createInstance( ::rtl::OUString::createFromAscii( "com.sun.star.ucb.SimpleFileAccess" ) ), uno::UNO_QUERY );
+ uno::Reference< io::XOutputStream > xOut = xAccess->openFileWrite( ::rtl::OUString::createFromAscii( "file:///d:/777/Encrypted/picture" ) );
+ xOut->writeBytes( aData );
+ xOut->closeOutput();
+ }
+ }
+#endif
+
+ if ( mnZipSize + maHeader.getLength() == mnMyCurrent && maCRC.getValue() != maEntry.nCrc )
+ throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
+ Reference< XInterface >() );
+ }
+ }
+
+ return nTotal;
+}
+
+sal_Int32 SAL_CALL XUnbufferedStream::readSomeBytes( Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+ throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ return readBytes ( aData, nMaxBytesToRead );
+}
+void SAL_CALL XUnbufferedStream::skipBytes( sal_Int32 nBytesToSkip )
+ throw( NotConnectedException, BufferSizeExceededException, IOException, RuntimeException)
+{
+ if ( nBytesToSkip )
+ {
+ Sequence < sal_Int8 > aSequence ( nBytesToSkip );
+ readBytes ( aSequence, nBytesToSkip );
+ }
+}
+
+sal_Int32 SAL_CALL XUnbufferedStream::available( )
+ throw( NotConnectedException, IOException, RuntimeException)
+{
+ return static_cast < sal_Int32 > ( mnZipSize - mnMyCurrent );
+}
+
+void SAL_CALL XUnbufferedStream::closeInput( )
+ throw( NotConnectedException, IOException, RuntimeException)
+{
+}
+/*
+void SAL_CALL XUnbufferedStream::seek( sal_Int64 location )
+ throw( IllegalArgumentException, IOException, RuntimeException)
+{
+}
+sal_Int64 SAL_CALL XUnbufferedStream::getPosition( )
+ throw(IOException, RuntimeException)
+{
+ return mnMyCurrent;
+}
+sal_Int64 SAL_CALL XUnbufferedStream::getLength( )
+ throw(IOException, RuntimeException)
+{
+ return mnZipSize;
+}
+*/
diff --git a/package/source/zipapi/XUnbufferedStream.hxx b/package/source/zipapi/XUnbufferedStream.hxx
new file mode 100644
index 000000000000..321ec10b8032
--- /dev/null
+++ b/package/source/zipapi/XUnbufferedStream.hxx
@@ -0,0 +1,108 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+#ifndef _XUNBUFFERED_STREAM_HXX
+#define _XUNBUFFERED_STREAM_HXX
+
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/io/XSeekable.hpp>
+#include <com/sun/star/io/XInputStream.hpp>
+#include <com/sun/star/io/XOutputStream.hpp>
+#include <cppuhelper/implbase1.hxx>
+#include <vos/ref.hxx>
+#include <Inflater.hxx>
+#include <ZipEntry.hxx>
+#include <CRC32.hxx>
+#include <mutexholder.hxx>
+
+#define UNBUFF_STREAM_DATA 0
+#define UNBUFF_STREAM_RAW 1
+#define UNBUFF_STREAM_WRAPPEDRAW 2
+
+class EncryptionData;
+typedef void* rtlCipher;
+class XUnbufferedStream : public cppu::WeakImplHelper1
+<
+ com::sun::star::io::XInputStream
+>
+{
+protected:
+ SotMutexHolderRef maMutexHolder;
+
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > mxZipStream;
+ com::sun::star::uno::Reference < com::sun::star::io::XSeekable > mxZipSeek;
+ com::sun::star::uno::Sequence < sal_Int8 > maCompBuffer, maHeader;
+ ZipEntry maEntry;
+ vos::ORef < EncryptionData > mxData;
+ rtlCipher maCipher;
+ Inflater maInflater;
+ sal_Bool mbRawStream, mbWrappedRaw, mbFinished;
+ sal_Int16 mnHeaderToRead;
+ sal_Int64 mnZipCurrent, mnZipEnd, mnZipSize, mnMyCurrent;
+ CRC32 maCRC;
+ sal_Bool mbCheckCRC;
+
+public:
+ XUnbufferedStream(
+ SotMutexHolderRef aMutexHolder,
+ ZipEntry & rEntry,
+ com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream,
+ const vos::ORef < EncryptionData > &rData,
+ sal_Int8 nStreamMode,
+ sal_Bool bIsEncrypted,
+ const ::rtl::OUString& aMediaType,
+ sal_Bool bRecoveryMode );
+
+ // allows to read package raw stream
+ XUnbufferedStream( const com::sun::star::uno::Reference < com::sun::star::io::XInputStream >& xRawStream,
+ const vos::ORef < EncryptionData > &rData );
+
+
+ virtual ~XUnbufferedStream();
+
+ // XInputStream
+ virtual sal_Int32 SAL_CALL readBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL readSomeBytes( ::com::sun::star::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL skipBytes( sal_Int32 nBytesToSkip )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::BufferSizeExceededException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int32 SAL_CALL available( )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual void SAL_CALL closeInput( )
+ throw(::com::sun::star::io::NotConnectedException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ // XSeekable
+ /*
+ virtual void SAL_CALL seek( sal_Int64 location )
+ throw(::com::sun::star::lang::IllegalArgumentException, ::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int64 SAL_CALL getPosition( )
+ throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ virtual sal_Int64 SAL_CALL getLength( )
+ throw(::com::sun::star::io::IOException, ::com::sun::star::uno::RuntimeException);
+ */
+};
+#endif
diff --git a/package/source/zipapi/ZipEnumeration.cxx b/package/source/zipapi/ZipEnumeration.cxx
new file mode 100644
index 000000000000..367c29f6d4a7
--- /dev/null
+++ b/package/source/zipapi/ZipEnumeration.cxx
@@ -0,0 +1,53 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ZipEnumeration.hxx>
+
+/** Provides an Enumeration over the contents of a Zip file */
+
+ZipEnumeration::ZipEnumeration( EntryHash & rNewEntryHash)
+: rEntryHash(rNewEntryHash)
+, aIterator(rEntryHash.begin())
+{
+}
+ZipEnumeration::~ZipEnumeration( void )
+{
+}
+sal_Bool SAL_CALL ZipEnumeration::hasMoreElements()
+{
+ return (aIterator != rEntryHash.end());
+}
+
+const ZipEntry* SAL_CALL ZipEnumeration::nextElement()
+{
+ if (aIterator != rEntryHash.end())
+ return &((*aIterator++).second);
+ else
+ return NULL;
+}
diff --git a/package/source/zipapi/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx
new file mode 100644
index 000000000000..f01b7ce06f4b
--- /dev/null
+++ b/package/source/zipapi/ZipFile.cxx
@@ -0,0 +1,1057 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ZipFile.hxx>
+#include <ZipEnumeration.hxx>
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <rtl/cipher.h>
+#include <rtl/digest.h>
+/*
+#include <XMemoryStream.hxx>
+#include <XFileStream.hxx>
+*/
+#include <XUnbufferedStream.hxx>
+#include <PackageConstants.hxx>
+#include <EncryptedDataHeader.hxx>
+#include <EncryptionData.hxx>
+#include <MemoryByteGrabber.hxx>
+#include <com/sun/star/lang/XMultiServiceFactory.hpp>
+#include <com/sun/star/ucb/XProgressHandler.hpp>
+
+#ifndef _CRC32_HXX_
+#include <CRC32.hxx>
+#endif
+
+#include <string.h> // for memcpy
+#include <vector>
+
+#include <comphelper/storagehelper.hxx>
+
+using namespace vos;
+using namespace rtl;
+using namespace com::sun::star;
+using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::ucb;
+using namespace com::sun::star::lang;
+using namespace com::sun::star::packages;
+using namespace com::sun::star::packages::zip;
+using namespace com::sun::star::packages::zip::ZipConstants;
+
+
+/** This class is used to read entries from a zip file
+ */
+ZipFile::ZipFile( Reference < XInputStream > &xInput, const Reference < XMultiServiceFactory > &xNewFactory, sal_Bool bInitialise )
+ throw(IOException, ZipException, RuntimeException)
+: aGrabber(xInput)
+, aInflater (sal_True)
+, xStream(xInput)
+, xSeek(xInput, UNO_QUERY)
+, xFactory ( xNewFactory )
+, bRecoveryMode( sal_False )
+{
+ if (bInitialise)
+ {
+ if ( readCEN() == -1 )
+ {
+ aEntries.clear();
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "stream data looks to be broken" ) ), Reference < XInterface > () );
+ }
+ }
+}
+
+
+
+ZipFile::ZipFile( Reference < XInputStream > &xInput, const Reference < XMultiServiceFactory > &xNewFactory, sal_Bool bInitialise, sal_Bool bForceRecovery, Reference < XProgressHandler > xProgress )
+ throw(IOException, ZipException, RuntimeException)
+: aGrabber(xInput)
+, aInflater (sal_True)
+, xStream(xInput)
+, xSeek(xInput, UNO_QUERY)
+, xFactory ( xNewFactory )
+, xProgressHandler( xProgress )
+, bRecoveryMode( bForceRecovery )
+{
+ if (bInitialise)
+ {
+ if ( bForceRecovery )
+ {
+ recover();
+ }
+ else if ( readCEN() == -1 )
+ {
+ aEntries.clear();
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "stream data looks to be broken" ) ), Reference < XInterface > () );
+ }
+ }
+}
+
+ZipFile::~ZipFile()
+{
+ aEntries.clear();
+}
+
+void ZipFile::setInputStream ( Reference < XInputStream > xNewStream )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ xStream = xNewStream;
+ xSeek = Reference < XSeekable > ( xStream, UNO_QUERY );
+ aGrabber.setInputStream ( xStream );
+}
+
+sal_Bool ZipFile::StaticGetCipher ( const ORef < EncryptionData > & xEncryptionData, rtlCipher &rCipher, sal_Bool bDecode )
+{
+ sal_Bool bResult = sal_False;
+ if ( ! xEncryptionData.isEmpty() )
+ {
+ Sequence < sal_uInt8 > aDerivedKey (16);
+ rtlCipherError aResult;
+ Sequence < sal_Int8 > aDecryptBuffer;
+
+ // Get the key
+ rtl_digest_PBKDF2 ( aDerivedKey.getArray(), 16,
+ reinterpret_cast < const sal_uInt8 * > (xEncryptionData->aKey.getConstArray() ),
+ xEncryptionData->aKey.getLength(),
+ reinterpret_cast < const sal_uInt8 * > ( xEncryptionData->aSalt.getConstArray() ),
+ xEncryptionData->aSalt.getLength(),
+ xEncryptionData->nIterationCount );
+
+ rCipher = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream);
+ aResult = rtl_cipher_init( rCipher, bDecode ? rtl_Cipher_DirectionDecode : rtl_Cipher_DirectionEncode,
+ aDerivedKey.getConstArray(),
+ aDerivedKey.getLength(),
+ reinterpret_cast < const sal_uInt8 * > ( xEncryptionData->aInitVector.getConstArray() ),
+ xEncryptionData->aInitVector.getLength());
+ OSL_ASSERT (aResult == rtl_Cipher_E_None);
+
+ bResult = ( aResult == rtl_Cipher_E_None );
+ }
+
+ return bResult;
+}
+
+void ZipFile::StaticFillHeader ( const ORef < EncryptionData > & rData,
+ sal_Int32 nSize,
+ const ::rtl::OUString& aMediaType,
+ sal_Int8 * & pHeader )
+{
+ // I think it's safe to restrict vector and salt length to 2 bytes !
+ sal_Int16 nIVLength = static_cast < sal_Int16 > ( rData->aInitVector.getLength() );
+ sal_Int16 nSaltLength = static_cast < sal_Int16 > ( rData->aSalt.getLength() );
+ sal_Int16 nDigestLength = static_cast < sal_Int16 > ( rData->aDigest.getLength() );
+ sal_Int16 nMediaTypeLength = static_cast < sal_Int16 > ( aMediaType.getLength() * sizeof( sal_Unicode ) );
+
+ // First the header
+ *(pHeader++) = ( n_ConstHeader >> 0 ) & 0xFF;
+ *(pHeader++) = ( n_ConstHeader >> 8 ) & 0xFF;
+ *(pHeader++) = ( n_ConstHeader >> 16 ) & 0xFF;
+ *(pHeader++) = ( n_ConstHeader >> 24 ) & 0xFF;
+
+ // Then the version
+ *(pHeader++) = ( n_ConstCurrentVersion >> 0 ) & 0xFF;
+ *(pHeader++) = ( n_ConstCurrentVersion >> 8 ) & 0xFF;
+
+ // Then the iteration Count
+ sal_Int32 nIterationCount = rData->nIterationCount;
+ *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 0 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 8 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 16 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nIterationCount >> 24 ) & 0xFF);
+
+ // Then the size
+ *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 0 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 8 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 16 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nSize >> 24 ) & 0xFF);
+
+ // Then the salt length
+ *(pHeader++) = static_cast< sal_Int8 >(( nSaltLength >> 0 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nSaltLength >> 8 ) & 0xFF);
+
+ // Then the IV length
+ *(pHeader++) = static_cast< sal_Int8 >(( nIVLength >> 0 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nIVLength >> 8 ) & 0xFF);
+
+ // Then the digest length
+ *(pHeader++) = static_cast< sal_Int8 >(( nDigestLength >> 0 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nDigestLength >> 8 ) & 0xFF);
+
+ // Then the mediatype length
+ *(pHeader++) = static_cast< sal_Int8 >(( nMediaTypeLength >> 0 ) & 0xFF);
+ *(pHeader++) = static_cast< sal_Int8 >(( nMediaTypeLength >> 8 ) & 0xFF);
+
+ // Then the salt content
+ memcpy ( pHeader, rData->aSalt.getConstArray(), nSaltLength );
+ pHeader += nSaltLength;
+
+ // Then the IV content
+ memcpy ( pHeader, rData->aInitVector.getConstArray(), nIVLength );
+ pHeader += nIVLength;
+
+ // Then the digest content
+ memcpy ( pHeader, rData->aDigest.getConstArray(), nDigestLength );
+ pHeader += nDigestLength;
+
+ // Then the mediatype itself
+ memcpy ( pHeader, aMediaType.getStr(), nMediaTypeLength );
+ pHeader += nMediaTypeLength;
+}
+
+sal_Bool ZipFile::StaticFillData ( ORef < EncryptionData > & rData,
+ sal_Int32 &rSize,
+ ::rtl::OUString& aMediaType,
+ Reference < XInputStream > &rStream )
+{
+ sal_Bool bOk = sal_False;
+ const sal_Int32 nHeaderSize = n_ConstHeaderSize - 4;
+ Sequence < sal_Int8 > aBuffer ( nHeaderSize );
+ if ( nHeaderSize == rStream->readBytes ( aBuffer, nHeaderSize ) )
+ {
+ sal_Int16 nPos = 0;
+ sal_Int8 *pBuffer = aBuffer.getArray();
+ sal_Int16 nVersion = pBuffer[nPos++] & 0xFF;
+ nVersion |= ( pBuffer[nPos++] & 0xFF ) << 8;
+ if ( nVersion == n_ConstCurrentVersion )
+ {
+ sal_Int32 nCount = pBuffer[nPos++] & 0xFF;
+ nCount |= ( pBuffer[nPos++] & 0xFF ) << 8;
+ nCount |= ( pBuffer[nPos++] & 0xFF ) << 16;
+ nCount |= ( pBuffer[nPos++] & 0xFF ) << 24;
+ rData->nIterationCount = nCount;
+
+ rSize = pBuffer[nPos++] & 0xFF;
+ rSize |= ( pBuffer[nPos++] & 0xFF ) << 8;
+ rSize |= ( pBuffer[nPos++] & 0xFF ) << 16;
+ rSize |= ( pBuffer[nPos++] & 0xFF ) << 24;
+
+ sal_Int16 nSaltLength = pBuffer[nPos++] & 0xFF;
+ nSaltLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
+ sal_Int16 nIVLength = ( pBuffer[nPos++] & 0xFF );
+ nIVLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
+ sal_Int16 nDigestLength = pBuffer[nPos++] & 0xFF;
+ nDigestLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
+
+ sal_Int16 nMediaTypeLength = pBuffer[nPos++] & 0xFF;
+ nMediaTypeLength |= ( pBuffer[nPos++] & 0xFF ) << 8;
+
+ if ( nSaltLength == rStream->readBytes ( aBuffer, nSaltLength ) )
+ {
+ rData->aSalt.realloc ( nSaltLength );
+ memcpy ( rData->aSalt.getArray(), aBuffer.getConstArray(), nSaltLength );
+ if ( nIVLength == rStream->readBytes ( aBuffer, nIVLength ) )
+ {
+ rData->aInitVector.realloc ( nIVLength );
+ memcpy ( rData->aInitVector.getArray(), aBuffer.getConstArray(), nIVLength );
+ if ( nDigestLength == rStream->readBytes ( aBuffer, nDigestLength ) )
+ {
+ rData->aDigest.realloc ( nDigestLength );
+ memcpy ( rData->aDigest.getArray(), aBuffer.getConstArray(), nDigestLength );
+
+ if ( nMediaTypeLength == rStream->readBytes ( aBuffer, nMediaTypeLength ) )
+ {
+ aMediaType = ::rtl::OUString( (sal_Unicode*)aBuffer.getConstArray(),
+ nMediaTypeLength / sizeof( sal_Unicode ) );
+ bOk = sal_True;
+ }
+ }
+ }
+ }
+ }
+ }
+ return bOk;
+}
+
+Reference< XInputStream > ZipFile::StaticGetDataFromRawStream( const Reference< XInputStream >& xStream,
+ const ORef < EncryptionData > &rData )
+ throw ( packages::WrongPasswordException, ZipIOException, RuntimeException )
+{
+ if ( rData.isEmpty() )
+ throw ZipIOException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ),
+ Reference< XInterface >() );
+
+ if ( !rData->aKey.getLength() )
+ throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ Reference< XSeekable > xSeek( xStream, UNO_QUERY );
+ if ( !xSeek.is() )
+ throw ZipIOException( OUString::createFromAscii( "The stream must be seekable!\n" ),
+ Reference< XInterface >() );
+
+
+ // if we have a digest, then this file is an encrypted one and we should
+ // check if we can decrypt it or not
+ OSL_ENSURE( rData->aDigest.getLength(), "Can't detect password correctness without digest!\n" );
+ if ( rData->aDigest.getLength() )
+ {
+ sal_Int32 nSize = sal::static_int_cast< sal_Int32 >( xSeek->getLength() );
+ nSize = nSize > n_ConstDigestLength ? n_ConstDigestLength : nSize;
+
+ // skip header
+ xSeek->seek( n_ConstHeaderSize + rData->aInitVector.getLength() +
+ rData->aSalt.getLength() + rData->aDigest.getLength() );
+
+ // Only want to read enough to verify the digest
+ Sequence < sal_Int8 > aReadBuffer ( nSize );
+
+ xStream->readBytes( aReadBuffer, nSize );
+
+ if ( !StaticHasValidPassword( aReadBuffer, rData ) )
+ throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ }
+
+ return new XUnbufferedStream ( xStream, rData );
+}
+
+sal_Bool ZipFile::StaticHasValidPassword( const Sequence< sal_Int8 > &aReadBuffer, const ORef < EncryptionData > &rData )
+{
+ if ( !rData.isValid() || !rData->aKey.getLength() )
+ return sal_False;
+
+ sal_Bool bRet = sal_False;
+ sal_Int32 nSize = aReadBuffer.getLength();
+
+ // make a temporary cipher
+ rtlCipher aCipher;
+ StaticGetCipher ( rData, aCipher, sal_True );
+
+ Sequence < sal_Int8 > aDecryptBuffer ( nSize );
+ rtlDigest aDigest = rtl_digest_createSHA1();
+ rtlDigestError aDigestResult;
+ Sequence < sal_uInt8 > aDigestSeq ( RTL_DIGEST_LENGTH_SHA1 );
+ rtlCipherError aResult = rtl_cipher_decode ( aCipher,
+ aReadBuffer.getConstArray(),
+ nSize,
+ reinterpret_cast < sal_uInt8 * > (aDecryptBuffer.getArray()),
+ nSize);
+ if(aResult != rtl_Cipher_E_None ) {
+ OSL_ASSERT ( aResult == rtl_Cipher_E_None);
+ }
+
+ aDigestResult = rtl_digest_updateSHA1 ( aDigest,
+ static_cast < const void * > ( aDecryptBuffer.getConstArray() ), nSize );
+ OSL_ASSERT ( aDigestResult == rtl_Digest_E_None );
+
+ aDigestResult = rtl_digest_getSHA1 ( aDigest, aDigestSeq.getArray(), RTL_DIGEST_LENGTH_SHA1 );
+ OSL_ASSERT ( aDigestResult == rtl_Digest_E_None );
+
+ // If we don't have a digest, then we have to assume that the password is correct
+ if ( rData->aDigest.getLength() != 0 &&
+ ( aDigestSeq.getLength() != rData->aDigest.getLength() ||
+ 0 != rtl_compareMemory ( aDigestSeq.getConstArray(),
+ rData->aDigest.getConstArray(),
+ aDigestSeq.getLength() ) ) )
+ {
+ // We should probably tell the user that the password they entered was wrong
+ }
+ else
+ bRet = sal_True;
+
+ rtl_digest_destroySHA1 ( aDigest );
+
+ return bRet;
+}
+
+sal_Bool ZipFile::hasValidPassword ( ZipEntry & rEntry, const ORef < EncryptionData > &rData )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Bool bRet = sal_False;
+ if ( rData->aKey.getLength() )
+ {
+ xSeek->seek( rEntry.nOffset );
+ sal_Int32 nSize = rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize;
+
+ // Only want to read enough to verify the digest
+ nSize = nSize > n_ConstDigestLength ? n_ConstDigestLength : nSize;
+ Sequence < sal_Int8 > aReadBuffer ( nSize );
+
+ xStream->readBytes( aReadBuffer, nSize );
+
+ bRet = StaticHasValidPassword( aReadBuffer, rData );
+ }
+ return bRet;
+}
+
+#if 0
+Reference < XInputStream > ZipFile::createFileStream(
+ ZipEntry & rEntry,
+ const ORef < EncryptionData > &rData,
+ sal_Bool bRawStream,
+ sal_Bool bIsEncrypted )
+{
+ static OUString sServiceName ( RTL_CONSTASCII_USTRINGPARAM ( "com.sun.star.io.TempFile" ) );
+ Reference < XInputStream > xTempStream = Reference < XInputStream > ( xFactory->createInstance ( sServiceName ), UNO_QUERY );
+ return new XFileStream ( rEntry, xStream, xTempStream, rData, bRawStream, bIsEncrypted );
+}
+Reference < XInputStream > ZipFile::createMemoryStream(
+ ZipEntry & rEntry,
+ const ORef < EncryptionData > &rData,
+ sal_Bool bRawStream,
+ sal_Bool bIsEncrypted )
+{
+ sal_Int32 nUncompressedSize, nEnd;
+ if (bRawStream)
+ {
+ nUncompressedSize = rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize;
+ nEnd = rEntry.nOffset + nUncompressedSize;
+ }
+ else
+ {
+ nUncompressedSize = rEntry.nSize;
+ nEnd = rEntry.nMethod == DEFLATED ? rEntry.nOffset + rEntry.nCompressedSize : rEntry.nOffset + rEntry.nSize;
+ }
+ sal_Int32 nSize = rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize;
+ Sequence < sal_Int8 > aReadBuffer ( nSize ), aDecryptBuffer, aWriteBuffer;
+ rtlCipher aCipher;
+
+ // If the encryption key is zero, we need to return the raw stream. First check if
+ // we have the salt. If we have the salt, then check if we have the encryption key
+ // if not, return rawStream instead.
+
+ sal_Bool bHaveEncryptData = ( !rData.isEmpty() && rData->aSalt.getLength() && rData->aInitVector.getLength() && rData->nIterationCount != 0 ) ? sal_True : sal_False;
+ sal_Bool bMustDecrypt = ( !bRawStream && bHaveEncryptData && bIsEncrypted ) ? sal_True : sal_False;
+
+ if ( bMustDecrypt )
+ {
+ StaticGetCipher ( rData, aCipher, sal_True );
+ aDecryptBuffer.realloc ( nSize );
+ }
+
+ if ( nSize <0 )
+ throw IOException ( );
+
+ xSeek->seek( rEntry.nOffset );
+ xStream->readBytes( aReadBuffer, nSize ); // Now it holds the raw stuff from disk
+
+ if ( bMustDecrypt )
+ {
+ rtlCipherError aResult = rtl_cipher_decode ( aCipher,
+ aReadBuffer.getConstArray(),
+ nSize,
+ reinterpret_cast < sal_uInt8 * > (aDecryptBuffer.getArray()),
+ nSize);
+ OSL_ASSERT (aResult == rtl_Cipher_E_None);
+ aReadBuffer = aDecryptBuffer; // Now it holds the decrypted data
+ }
+ if (bRawStream || rEntry.nMethod == STORED)
+ aWriteBuffer = aReadBuffer; // bRawStream means the caller doesn't want it decompressed
+ else
+ {
+ aInflater.setInputSegment( aReadBuffer, 0, nSize );
+ aWriteBuffer.realloc( nUncompressedSize );
+ aInflater.doInflate( aWriteBuffer );
+ aInflater.reset();
+ }
+
+ if ( bHaveEncryptData && !bMustDecrypt && bIsEncrypted )
+ {
+ // if we have the data needed to decrypt it, but didn't want it decrypted (or
+ // we couldn't decrypt it due to wrong password), then we prepend this
+ // data to the stream
+
+ // Make a buffer big enough to hold both the header and the data itself
+ Sequence < sal_Int8 > aEncryptedDataHeader ( n_ConstHeaderSize +
+ rData->aInitVector.getLength() +
+ rData->aSalt.getLength() +
+ rData->aDigest.getLength() +
+ aWriteBuffer.getLength() );
+ sal_Int8 * pHeader = aEncryptedDataHeader.getArray();
+ StaticFillHeader ( rData, rEntry.nSize, pHeader );
+ memcpy ( pHeader, aWriteBuffer.getConstArray(), aWriteBuffer.getLength() );
+
+ // dump old buffer and point aWriteBuffer to the new one with the header
+ aWriteBuffer = aEncryptedDataHeader;
+ }
+ return Reference < XInputStream > ( new XMemoryStream ( aWriteBuffer ) );
+}
+#endif
+Reference < XInputStream > ZipFile::createUnbufferedStream(
+ SotMutexHolderRef aMutexHolder,
+ ZipEntry & rEntry,
+ const ORef < EncryptionData > &rData,
+ sal_Int8 nStreamMode,
+ sal_Bool bIsEncrypted,
+ ::rtl::OUString aMediaType )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ return new XUnbufferedStream ( aMutexHolder, rEntry, xStream, rData, nStreamMode, bIsEncrypted, aMediaType, bRecoveryMode );
+}
+
+
+ZipEnumeration * SAL_CALL ZipFile::entries( )
+{
+ return new ZipEnumeration ( aEntries );
+}
+
+Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry,
+ const vos::ORef < EncryptionData > &rData,
+ sal_Bool bIsEncrypted,
+ SotMutexHolderRef aMutexHolder )
+ throw(IOException, ZipException, RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( rEntry.nOffset <= 0 )
+ readLOC( rEntry );
+
+ // We want to return a rawStream if we either don't have a key or if the
+ // key is wrong
+
+ sal_Bool bNeedRawStream = rEntry.nMethod == STORED;
+
+ // if we have a digest, then this file is an encrypted one and we should
+ // check if we can decrypt it or not
+ if ( bIsEncrypted && !rData.isEmpty() && rData->aDigest.getLength() )
+ bNeedRawStream = !hasValidPassword ( rEntry, rData );
+
+ return createUnbufferedStream ( aMutexHolder,
+ rEntry,
+ rData,
+ bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA,
+ bIsEncrypted );
+}
+
+Reference< XInputStream > SAL_CALL ZipFile::getDataStream( ZipEntry& rEntry,
+ const vos::ORef < EncryptionData > &rData,
+ sal_Bool bIsEncrypted,
+ SotMutexHolderRef aMutexHolder )
+ throw ( packages::WrongPasswordException,
+ IOException,
+ ZipException,
+ RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( rEntry.nOffset <= 0 )
+ readLOC( rEntry );
+
+ // An exception must be thrown in case stream is encrypted and
+ // there is no key or the key is wrong
+ sal_Bool bNeedRawStream = sal_False;
+ if ( bIsEncrypted )
+ {
+ // in case no digest is provided there is no way
+ // to detect password correctness
+ if ( rData.isEmpty() )
+ throw ZipException( OUString::createFromAscii( "Encrypted stream without encryption data!\n" ),
+ Reference< XInterface >() );
+
+ // if we have a digest, then this file is an encrypted one and we should
+ // check if we can decrypt it or not
+ OSL_ENSURE( rData->aDigest.getLength(), "Can't detect password correctness without digest!\n" );
+ if ( rData->aDigest.getLength() && !hasValidPassword ( rEntry, rData ) )
+ throw packages::WrongPasswordException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+ }
+ else
+ bNeedRawStream = ( rEntry.nMethod == STORED );
+
+ return createUnbufferedStream ( aMutexHolder,
+ rEntry,
+ rData,
+ bNeedRawStream ? UNBUFF_STREAM_RAW : UNBUFF_STREAM_DATA,
+ bIsEncrypted );
+}
+
+Reference< XInputStream > SAL_CALL ZipFile::getRawData( ZipEntry& rEntry,
+ const vos::ORef < EncryptionData > &rData,
+ sal_Bool bIsEncrypted,
+ SotMutexHolderRef aMutexHolder )
+ throw(IOException, ZipException, RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( rEntry.nOffset <= 0 )
+ readLOC( rEntry );
+
+ return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_RAW, bIsEncrypted );
+}
+
+Reference< XInputStream > SAL_CALL ZipFile::getWrappedRawStream(
+ ZipEntry& rEntry,
+ const vos::ORef < EncryptionData > &rData,
+ const ::rtl::OUString& aMediaType,
+ SotMutexHolderRef aMutexHolder )
+ throw ( packages::NoEncryptionException,
+ IOException,
+ ZipException,
+ RuntimeException )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ if ( rData.isEmpty() )
+ throw packages::NoEncryptionException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX ) ), uno::Reference< uno::XInterface >() );
+
+ if ( rEntry.nOffset <= 0 )
+ readLOC( rEntry );
+
+ return createUnbufferedStream ( aMutexHolder, rEntry, rData, UNBUFF_STREAM_WRAPPEDRAW, sal_True, aMediaType );
+}
+
+sal_Bool ZipFile::readLOC( ZipEntry &rEntry )
+ throw(IOException, ZipException, RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nTestSig, nTime, nCRC, nSize, nCompressedSize;
+ sal_Int16 nVersion, nFlag, nHow, nPathLen, nExtraLen;
+ sal_Int32 nPos = -rEntry.nOffset;
+
+ aGrabber.seek(nPos);
+ aGrabber >> nTestSig;
+
+ if (nTestSig != LOCSIG)
+ throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid LOC header (bad signature") ), Reference < XInterface > () );
+ aGrabber >> nVersion;
+ aGrabber >> nFlag;
+ aGrabber >> nHow;
+ aGrabber >> nTime;
+ aGrabber >> nCRC;
+ aGrabber >> nCompressedSize;
+ aGrabber >> nSize;
+ aGrabber >> nPathLen;
+ aGrabber >> nExtraLen;
+ rEntry.nOffset = static_cast < sal_Int32 > (aGrabber.getPosition()) + nPathLen + nExtraLen;
+
+ // read always in UTF8, some tools seem not to set UTF8 bit
+ uno::Sequence < sal_Int8 > aNameBuffer( nPathLen );
+ sal_Int32 nRead = aGrabber.readBytes( aNameBuffer, nPathLen );
+ if ( nRead < aNameBuffer.getLength() )
+ aNameBuffer.realloc( nRead );
+
+ ::rtl::OUString sLOCPath = rtl::OUString::intern( (sal_Char *) aNameBuffer.getArray(),
+ aNameBuffer.getLength(),
+ RTL_TEXTENCODING_UTF8 );
+
+ if ( rEntry.nPathLen == -1 ) // the file was created
+ {
+ rEntry.nPathLen = nPathLen;
+ rEntry.sPath = sLOCPath;
+ }
+
+ // the method can be reset for internal use so it is not checked
+ sal_Bool bBroken = rEntry.nVersion != nVersion
+ || rEntry.nFlag != nFlag
+ || rEntry.nTime != nTime
+ || rEntry.nPathLen != nPathLen
+ || !rEntry.sPath.equals( sLOCPath );
+
+ if ( bBroken && !bRecoveryMode )
+ throw ZipIOException( OUString( RTL_CONSTASCII_USTRINGPARAM( "The stream seems to be broken!" ) ),
+ Reference< XInterface >() );
+
+ return sal_True;
+}
+
+sal_Int32 ZipFile::findEND( )
+ throw(IOException, ZipException, RuntimeException)
+{
+ // this method is called in constructor only, no need for mutex
+ sal_Int32 nLength, nPos, nEnd;
+ Sequence < sal_Int8 > aBuffer;
+ try
+ {
+ nLength = static_cast <sal_Int32 > (aGrabber.getLength());
+ if (nLength == 0 || nLength < ENDHDR)
+ return -1;
+ nPos = nLength - ENDHDR - ZIP_MAXNAMELEN;
+ nEnd = nPos >= 0 ? nPos : 0 ;
+
+ aGrabber.seek( nEnd );
+ aGrabber.readBytes ( aBuffer, nLength - nEnd );
+
+ const sal_Int8 *pBuffer = aBuffer.getConstArray();
+
+ nPos = nLength - nEnd - ENDHDR;
+ while ( nPos >= 0 )
+ {
+ if (pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 5 && pBuffer[nPos+3] == 6 )
+ return nPos + nEnd;
+ nPos--;
+ }
+ }
+ catch ( IllegalArgumentException& )
+ {
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), Reference < XInterface > () );
+ }
+ catch ( NotConnectedException& )
+ {
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), Reference < XInterface > () );
+ }
+ catch ( BufferSizeExceededException& )
+ {
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), Reference < XInterface > () );
+ }
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), Reference < XInterface > () );
+}
+
+sal_Int32 ZipFile::readCEN()
+ throw(IOException, ZipException, RuntimeException)
+{
+ // this method is called in constructor only, no need for mutex
+ sal_Int32 nCenLen, nCenPos = -1, nCenOff, nEndPos, nLocPos;
+ sal_uInt16 nCount, nTotal;
+
+ try
+ {
+ nEndPos = findEND();
+ if (nEndPos == -1)
+ return -1;
+ aGrabber.seek(nEndPos + ENDTOT);
+ aGrabber >> nTotal;
+ aGrabber >> nCenLen;
+ aGrabber >> nCenOff;
+
+ if ( nTotal * CENHDR > nCenLen )
+ throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "invalid END header (bad entry count)") ), Reference < XInterface > () );
+
+ if ( nTotal > ZIP_MAXENTRIES )
+ throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "too many entries in ZIP File") ), Reference < XInterface > () );
+
+ if ( nCenLen < 0 || nCenLen > nEndPos )
+ throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), Reference < XInterface > () );
+
+ nCenPos = nEndPos - nCenLen;
+
+ if ( nCenOff < 0 || nCenOff > nCenPos )
+ throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid END header (bad central directory size)") ), Reference < XInterface > () );
+
+ nLocPos = nCenPos - nCenOff;
+ aGrabber.seek( nCenPos );
+ Sequence < sal_Int8 > aCENBuffer ( nCenLen );
+ sal_Int64 nRead = aGrabber.readBytes ( aCENBuffer, nCenLen );
+ if ( static_cast < sal_Int64 > ( nCenLen ) != nRead )
+ throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( "Error reading CEN into memory buffer!") ), Reference < XInterface > () );
+
+ MemoryByteGrabber aMemGrabber ( aCENBuffer );
+
+ ZipEntry aEntry;
+ sal_Int32 nTestSig;
+ sal_Int16 nCommentLen;
+
+ for (nCount = 0 ; nCount < nTotal; nCount++)
+ {
+ aMemGrabber >> nTestSig;
+ if ( nTestSig != CENSIG )
+ throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad signature)") ), Reference < XInterface > () );
+
+ aMemGrabber.skipBytes ( 2 );
+ aMemGrabber >> aEntry.nVersion;
+
+ if ( ( aEntry.nVersion & 1 ) == 1 )
+ throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (encrypted entry)") ), Reference < XInterface > () );
+
+ aMemGrabber >> aEntry.nFlag;
+ aMemGrabber >> aEntry.nMethod;
+
+ if ( aEntry.nMethod != STORED && aEntry.nMethod != DEFLATED)
+ throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Invalid CEN header (bad compression method)") ), Reference < XInterface > () );
+
+ aMemGrabber >> aEntry.nTime;
+ aMemGrabber >> aEntry.nCrc;
+ aMemGrabber >> aEntry.nCompressedSize;
+ aMemGrabber >> aEntry.nSize;
+ aMemGrabber >> aEntry.nPathLen;
+ aMemGrabber >> aEntry.nExtraLen;
+ aMemGrabber >> nCommentLen;
+ aMemGrabber.skipBytes ( 8 );
+ aMemGrabber >> aEntry.nOffset;
+
+ aEntry.nOffset += nLocPos;
+ aEntry.nOffset *= -1;
+
+ if ( aEntry.nPathLen < 0 )
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected name length" ) ), Reference < XInterface > () );
+
+ if ( nCommentLen < 0 )
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected comment length" ) ), Reference < XInterface > () );
+
+ if ( aEntry.nExtraLen < 0 )
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "unexpected extra header info length") ), Reference < XInterface > () );
+
+ // read always in UTF8, some tools seem not to set UTF8 bit
+ aEntry.sPath = rtl::OUString::intern ( (sal_Char *) aMemGrabber.getCurrentPos(),
+ aEntry.nPathLen,
+ RTL_TEXTENCODING_UTF8 );
+
+ if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( aEntry.sPath, sal_True ) )
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip entry has an invalid name.") ), Reference < XInterface > () );
+
+ aMemGrabber.skipBytes( aEntry.nPathLen + aEntry.nExtraLen + nCommentLen );
+ aEntries[aEntry.sPath] = aEntry;
+ }
+
+ if (nCount != nTotal)
+ throw ZipException(OUString( RTL_CONSTASCII_USTRINGPARAM ( "Count != Total") ), Reference < XInterface > () );
+ }
+ catch ( IllegalArgumentException & )
+ {
+ // seek can throw this...
+ nCenPos = -1; // make sure we return -1 to indicate an error
+ }
+ return nCenPos;
+}
+
+sal_Int32 ZipFile::recover()
+ throw(IOException, ZipException, RuntimeException)
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nLength;
+ Sequence < sal_Int8 > aBuffer;
+ Sequence < sal_Int32 > aHeaderOffsets;
+
+ try
+ {
+ nLength = static_cast <sal_Int32 > (aGrabber.getLength());
+ if (nLength == 0 || nLength < ENDHDR)
+ return -1;
+
+ aGrabber.seek( 0 );
+
+ for( sal_Int32 nGenPos = 0; aGrabber.readBytes( aBuffer, 32000 ) && aBuffer.getLength() > 30; )
+ {
+ const sal_Int8 *pBuffer = aBuffer.getConstArray();
+ sal_Int32 nBufSize = aBuffer.getLength();
+
+ sal_Int32 nPos = 0;
+ while( nPos < nBufSize - 16 )
+ {
+ if ( nPos < nBufSize - 30 && pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 3 && pBuffer[nPos+3] == 4 )
+ {
+ ZipEntry aEntry;
+ MemoryByteGrabber aMemGrabber ( Sequence< sal_Int8 >( ((sal_Int8*)(&(pBuffer[nPos+4]))), 26 ) );
+
+ aMemGrabber >> aEntry.nVersion;
+ if ( ( aEntry.nVersion & 1 ) != 1 )
+ {
+ aMemGrabber >> aEntry.nFlag;
+ aMemGrabber >> aEntry.nMethod;
+
+ if ( aEntry.nMethod == STORED || aEntry.nMethod == DEFLATED )
+ {
+ aMemGrabber >> aEntry.nTime;
+ aMemGrabber >> aEntry.nCrc;
+ aMemGrabber >> aEntry.nCompressedSize;
+ aMemGrabber >> aEntry.nSize;
+ aMemGrabber >> aEntry.nPathLen;
+ aMemGrabber >> aEntry.nExtraLen;
+
+ sal_Int32 nDescrLength =
+ ( aEntry.nMethod == DEFLATED && ( aEntry.nFlag & 8 ) ) ?
+ 16 : 0;
+
+
+ // This is a quick fix for OOo1.1RC
+ // For OOo2.0 the whole package must be switched to unsigned values
+ if ( aEntry.nCompressedSize < 0 ) aEntry.nCompressedSize = 0x7FFFFFFF;
+ if ( aEntry.nSize < 0 ) aEntry.nSize = 0x7FFFFFFF;
+ if ( aEntry.nPathLen < 0 ) aEntry.nPathLen = 0x7FFF;
+ if ( aEntry.nExtraLen < 0 ) aEntry.nExtraLen = 0x7FFF;
+ // End of quick fix
+
+ sal_Int32 nDataSize = ( aEntry.nMethod == DEFLATED ) ? aEntry.nCompressedSize : aEntry.nSize;
+ sal_Int32 nBlockLength = nDataSize + aEntry.nPathLen + aEntry.nExtraLen + 30 + nDescrLength;
+ if ( aEntry.nPathLen >= 0 && aEntry.nExtraLen >= 0
+ && ( nGenPos + nPos + nBlockLength ) <= nLength )
+ {
+ // read always in UTF8, some tools seem not to set UTF8 bit
+ if( nPos + 30 + aEntry.nPathLen <= nBufSize )
+ aEntry.sPath = OUString ( (sal_Char *) &pBuffer[nPos + 30],
+ aEntry.nPathLen,
+ RTL_TEXTENCODING_UTF8 );
+ else
+ {
+ Sequence < sal_Int8 > aFileName;
+ aGrabber.seek( nGenPos + nPos + 30 );
+ aGrabber.readBytes( aFileName, aEntry.nPathLen );
+ aEntry.sPath = OUString ( (sal_Char *) aFileName.getArray(),
+ aFileName.getLength(),
+ RTL_TEXTENCODING_UTF8 );
+ aEntry.nPathLen = static_cast< sal_Int16 >(aFileName.getLength());
+ }
+
+ aEntry.nOffset = nGenPos + nPos + 30 + aEntry.nPathLen + aEntry.nExtraLen;
+
+ if ( ( aEntry.nSize || aEntry.nCompressedSize ) && !checkSizeAndCRC( aEntry ) )
+ {
+ aEntry.nCrc = 0;
+ aEntry.nCompressedSize = 0;
+ aEntry.nSize = 0;
+ }
+
+ if ( aEntries.find( aEntry.sPath ) == aEntries.end() )
+ aEntries[aEntry.sPath] = aEntry;
+ }
+ }
+ }
+
+ nPos += 4;
+ }
+ else if (pBuffer[nPos] == 'P' && pBuffer[nPos+1] == 'K' && pBuffer[nPos+2] == 7 && pBuffer[nPos+3] == 8 )
+ {
+ sal_Int32 nCompressedSize, nSize, nCRC32;
+ MemoryByteGrabber aMemGrabber ( Sequence< sal_Int8 >( ((sal_Int8*)(&(pBuffer[nPos+4]))), 12 ) );
+ aMemGrabber >> nCRC32;
+ aMemGrabber >> nCompressedSize;
+ aMemGrabber >> nSize;
+
+ for( EntryHash::iterator aIter = aEntries.begin(); aIter != aEntries.end(); aIter++ )
+ {
+ ZipEntry aTmp = (*aIter).second;
+
+ // this is a broken package, accept this block not only for DEFLATED streams
+ if( (*aIter).second.nFlag & 8 )
+ {
+ sal_Int32 nStreamOffset = nGenPos + nPos - nCompressedSize;
+ if ( nStreamOffset == (*aIter).second.nOffset && nCompressedSize > (*aIter).second.nCompressedSize )
+ {
+ // only DEFLATED blocks need to be checked
+ sal_Bool bAcceptBlock = ( (*aIter).second.nMethod == STORED && nCompressedSize == nSize );
+
+ if ( !bAcceptBlock )
+ {
+ sal_Int32 nRealSize = 0, nRealCRC = 0;
+ getSizeAndCRC( nStreamOffset, nCompressedSize, &nRealSize, &nRealCRC );
+ bAcceptBlock = ( nRealSize == nSize && nRealCRC == nCRC32 );
+ }
+
+ if ( bAcceptBlock )
+ {
+ (*aIter).second.nCrc = nCRC32;
+ (*aIter).second.nCompressedSize = nCompressedSize;
+ (*aIter).second.nSize = nSize;
+ }
+ }
+#if 0
+// for now ignore clearly broken streams
+ else if( !(*aIter).second.nCompressedSize )
+ {
+ (*aIter).second.nCrc = nCRC32;
+ sal_Int32 nRealStreamSize = nGenPos + nPos - (*aIter).second.nOffset;
+ (*aIter).second.nCompressedSize = nGenPos + nPos - (*aIter).second.nOffset;
+ (*aIter).second.nSize = nSize;
+ }
+#endif
+ }
+ }
+
+ nPos += 4;
+ }
+ else
+ nPos++;
+ }
+
+ nGenPos += nPos;
+ aGrabber.seek( nGenPos );
+ }
+
+ return 0;
+ }
+ catch ( IllegalArgumentException& )
+ {
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), Reference < XInterface > () );
+ }
+ catch ( NotConnectedException& )
+ {
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), Reference < XInterface > () );
+ }
+ catch ( BufferSizeExceededException& )
+ {
+ throw ZipException( OUString( RTL_CONSTASCII_USTRINGPARAM ( "Zip END signature not found!") ), Reference < XInterface > () );
+ }
+}
+
+sal_Bool ZipFile::checkSizeAndCRC( const ZipEntry& aEntry )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ sal_Int32 nSize = 0, nCRC = 0;
+
+ if( aEntry.nMethod == STORED )
+ return ( getCRC( aEntry.nOffset, aEntry.nSize ) == aEntry.nCrc );
+
+ getSizeAndCRC( aEntry.nOffset, aEntry.nCompressedSize, &nSize, &nCRC );
+ return ( aEntry.nSize == nSize && aEntry.nCrc == nCRC );
+}
+
+sal_Int32 ZipFile::getCRC( sal_Int32 nOffset, sal_Int32 nSize )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Sequence < sal_Int8 > aBuffer;
+ CRC32 aCRC;
+ sal_Int32 nBlockSize = ::std::min( nSize, static_cast< sal_Int32 >( 32000 ) );
+
+ aGrabber.seek( nOffset );
+ for ( int ind = 0;
+ aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nSize;
+ ind++ )
+ {
+ aCRC.updateSegment( aBuffer, 0, ::std::min( nBlockSize, nSize - ind * nBlockSize ) );
+ }
+
+ return aCRC.getValue();
+}
+
+void ZipFile::getSizeAndCRC( sal_Int32 nOffset, sal_Int32 nCompressedSize, sal_Int32 *nSize, sal_Int32 *nCRC )
+{
+ ::osl::MutexGuard aGuard( m_aMutex );
+
+ Sequence < sal_Int8 > aBuffer;
+ CRC32 aCRC;
+ sal_Int32 nRealSize = 0;
+ Inflater aInflaterLocal( sal_True );
+ sal_Int32 nBlockSize = ::std::min( nCompressedSize, static_cast< sal_Int32 >( 32000 ) );
+
+ aGrabber.seek( nOffset );
+ for ( int ind = 0;
+ !aInflaterLocal.finished() && aGrabber.readBytes( aBuffer, nBlockSize ) && ind * nBlockSize < nCompressedSize;
+ ind++ )
+ {
+ Sequence < sal_Int8 > aData( nBlockSize );
+ sal_Int32 nLastInflated = 0;
+ sal_Int32 nInBlock = 0;
+
+ aInflaterLocal.setInput( aBuffer );
+ do
+ {
+ nLastInflated = aInflaterLocal.doInflateSegment( aData, 0, nBlockSize );
+ aCRC.updateSegment( aData, 0, nLastInflated );
+ nInBlock += nLastInflated;
+ } while( !aInflater.finished() && nLastInflated );
+
+ nRealSize += nInBlock;
+ }
+
+ *nSize = nRealSize;
+ *nCRC = aCRC.getValue();
+}
+
diff --git a/package/source/zipapi/ZipOutputStream.cxx b/package/source/zipapi/ZipOutputStream.cxx
new file mode 100644
index 000000000000..16457ec12493
--- /dev/null
+++ b/package/source/zipapi/ZipOutputStream.cxx
@@ -0,0 +1,429 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_package.hxx"
+#include <ZipOutputStream.hxx>
+#include <com/sun/star/packages/zip/ZipConstants.hpp>
+#include <osl/time.h>
+#include <EncryptionData.hxx>
+#include <PackageConstants.hxx>
+#include <ZipEntry.hxx>
+#include <ZipFile.hxx>
+#include <vos/ref.hxx>
+#include <com/sun/star/io/XOutputStream.hpp>
+
+#include <comphelper/storagehelper.hxx>
+
+using namespace rtl;
+using namespace com::sun::star::io;
+using namespace com::sun::star::uno;
+using namespace com::sun::star::packages;
+using namespace com::sun::star::packages::zip;
+using namespace com::sun::star::packages::zip::ZipConstants;
+
+/** This class is used to write Zip files
+ */
+ZipOutputStream::ZipOutputStream( Reference < XOutputStream > &xOStream )
+: xStream(xOStream)
+, aBuffer(n_ConstBufferSize)
+, aDeflater(DEFAULT_COMPRESSION, sal_True)
+, aChucker(xOStream)
+, pCurrentEntry(NULL)
+, nMethod(DEFLATED)
+, bFinished(sal_False)
+, bEncryptCurrentEntry(sal_False)
+
+
+{
+}
+
+ZipOutputStream::~ZipOutputStream( void )
+{
+ for (sal_Int32 i = 0, nEnd = aZipList.size(); i < nEnd; i++)
+ delete aZipList[i];
+}
+
+void SAL_CALL ZipOutputStream::setMethod( sal_Int32 nNewMethod )
+ throw(RuntimeException)
+{
+ nMethod = static_cast < sal_Int16 > (nNewMethod);
+}
+void SAL_CALL ZipOutputStream::setLevel( sal_Int32 nNewLevel )
+ throw(RuntimeException)
+{
+ aDeflater.setLevel( nNewLevel);
+}
+
+void SAL_CALL ZipOutputStream::putNextEntry( ZipEntry& rEntry,
+ vos::ORef < EncryptionData > &xEncryptData,
+ sal_Bool bEncrypt)
+ throw(IOException, RuntimeException)
+{
+ if (pCurrentEntry != NULL)
+ closeEntry();
+ if (rEntry.nTime == -1)
+ rEntry.nTime = getCurrentDosTime();
+ if (rEntry.nMethod == -1)
+ rEntry.nMethod = nMethod;
+ rEntry.nVersion = 20;
+ rEntry.nFlag = 1 << 11;
+ if (rEntry.nSize == -1 || rEntry.nCompressedSize == -1 ||
+ rEntry.nCrc == -1)
+ rEntry.nFlag |= 8;
+
+ if (bEncrypt)
+ {
+ bEncryptCurrentEntry = sal_True;
+
+ ZipFile::StaticGetCipher( xEncryptData, aCipher, sal_False );
+
+ aDigest = rtl_digest_createSHA1();
+ mnDigested = 0;
+ rEntry.nFlag |= 1 << 4;
+ pCurrentEncryptData = xEncryptData.getBodyPtr();
+ }
+ sal_Int32 nLOCLength = writeLOC(rEntry);
+ rEntry.nOffset = static_cast < sal_Int32 > (aChucker.GetPosition()) - nLOCLength;
+ aZipList.push_back( &rEntry );
+ pCurrentEntry = &rEntry;
+}
+
+void SAL_CALL ZipOutputStream::closeEntry( )
+ throw(IOException, RuntimeException)
+{
+ ZipEntry *pEntry = pCurrentEntry;
+ if (pEntry)
+ {
+ switch (pEntry->nMethod)
+ {
+ case DEFLATED:
+ aDeflater.finish();
+ while (!aDeflater.finished())
+ doDeflate();
+ if ((pEntry->nFlag & 8) == 0)
+ {
+ if (pEntry->nSize != aDeflater.getTotalIn())
+ {
+ OSL_ENSURE(false,"Invalid entry size");
+ }
+ if (pEntry->nCompressedSize != aDeflater.getTotalOut())
+ {
+ //VOS_DEBUG_ONLY("Invalid entry compressed size");
+ // Different compression strategies make the merit of this
+ // test somewhat dubious
+ pEntry->nCompressedSize = aDeflater.getTotalOut();
+ }
+ if (pEntry->nCrc != aCRC.getValue())
+ {
+ OSL_ENSURE(false,"Invalid entry CRC-32");
+ }
+ }
+ else
+ {
+ pEntry->nSize = aDeflater.getTotalIn();
+ pEntry->nCompressedSize = aDeflater.getTotalOut();
+ pEntry->nCrc = aCRC.getValue();
+ if ( bEncryptCurrentEntry )
+ pEntry->nSize = pEntry->nCompressedSize;
+ writeEXT(*pEntry);
+ }
+ aDeflater.reset();
+ aCRC.reset();
+ break;
+ case STORED:
+ if (!((pEntry->nFlag & 8) == 0))
+ OSL_ENSURE ( false, "Serious error, one of compressed size, size or CRC was -1 in a STORED stream");
+ break;
+ default:
+ OSL_ENSURE(false,"Invalid compression method");
+ break;
+ }
+
+ if (bEncryptCurrentEntry)
+ {
+ rtlDigestError aDigestResult;
+ aEncryptionBuffer.realloc ( 0 );
+ bEncryptCurrentEntry = sal_False;
+ rtl_cipher_destroy ( aCipher );
+ pCurrentEncryptData->aDigest.realloc ( RTL_DIGEST_LENGTH_SHA1 );
+ aDigestResult = rtl_digest_getSHA1 ( aDigest,
+ reinterpret_cast < sal_uInt8 * > ( pCurrentEncryptData->aDigest.getArray() ),
+ RTL_DIGEST_LENGTH_SHA1 );
+ OSL_ASSERT( aDigestResult == rtl_Digest_E_None );
+ rtl_digest_destroySHA1 ( aDigest );
+ }
+ pCurrentEntry = NULL;
+ }
+}
+
+void SAL_CALL ZipOutputStream::write( const Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
+ throw(IOException, RuntimeException)
+{
+ switch (pCurrentEntry->nMethod)
+ {
+ case DEFLATED:
+ if (!aDeflater.finished())
+ {
+ aDeflater.setInputSegment(rBuffer, nNewOffset, nNewLength);
+ while (!aDeflater.needsInput())
+ doDeflate();
+ if (!bEncryptCurrentEntry)
+ aCRC.updateSegment(rBuffer, nNewOffset, nNewLength);
+ }
+ break;
+ case STORED:
+ {
+ Sequence < sal_Int8 > aTmpBuffer ( rBuffer.getConstArray(), nNewLength );
+ aChucker.WriteBytes( aTmpBuffer );
+ }
+ break;
+ }
+}
+
+void SAL_CALL ZipOutputStream::rawWrite( Sequence< sal_Int8 >& rBuffer, sal_Int32 /*nNewOffset*/, sal_Int32 nNewLength )
+ throw(IOException, RuntimeException)
+{
+ Sequence < sal_Int8 > aTmpBuffer ( rBuffer.getConstArray(), nNewLength );
+ aChucker.WriteBytes( aTmpBuffer );
+}
+
+void SAL_CALL ZipOutputStream::rawCloseEntry( )
+ throw(IOException, RuntimeException)
+{
+ if ( pCurrentEntry->nMethod == DEFLATED && ( pCurrentEntry->nFlag & 8 ) )
+ writeEXT(*pCurrentEntry);
+ pCurrentEntry = NULL;
+}
+
+void SAL_CALL ZipOutputStream::finish( )
+ throw(IOException, RuntimeException)
+{
+ if (bFinished)
+ return;
+
+ if (pCurrentEntry != NULL)
+ closeEntry();
+
+ if (aZipList.size() < 1)
+ OSL_ENSURE(false,"Zip file must have at least one entry!\n");
+
+ sal_Int32 nOffset= static_cast < sal_Int32 > (aChucker.GetPosition());
+ for (sal_Int32 i =0, nEnd = aZipList.size(); i < nEnd; i++)
+ writeCEN( *aZipList[i] );
+ writeEND( nOffset, static_cast < sal_Int32 > (aChucker.GetPosition()) - nOffset);
+ bFinished = sal_True;
+ xStream->flush();
+}
+
+void ZipOutputStream::doDeflate()
+{
+ sal_Int32 nLength = aDeflater.doDeflateSegment(aBuffer, 0, aBuffer.getLength());
+ sal_Int32 nOldLength = aBuffer.getLength();
+
+ if ( nLength > 0 )
+ {
+ Sequence < sal_Int8 > aTmpBuffer ( aBuffer.getConstArray(), nLength );
+ const void *pTmpBuffer = static_cast < const void * > ( aTmpBuffer.getConstArray() );
+ if (bEncryptCurrentEntry)
+ {
+ // Need to update our digest before encryption...
+ rtlDigestError aDigestResult = rtl_Digest_E_None;
+ sal_Int16 nDiff = n_ConstDigestLength - mnDigested;
+ if ( nDiff )
+ {
+ sal_Int16 nEat = static_cast < sal_Int16 > ( nDiff > nLength ? nLength : nDiff );
+ aDigestResult = rtl_digest_updateSHA1 ( aDigest, pTmpBuffer, nEat );
+ mnDigested = mnDigested + nEat;
+ }
+ OSL_ASSERT( aDigestResult == rtl_Digest_E_None );
+
+ aEncryptionBuffer.realloc ( nLength );
+
+ rtlCipherError aCipherResult;
+ aCipherResult = rtl_cipher_encode ( aCipher, pTmpBuffer,
+ nLength, reinterpret_cast < sal_uInt8 * > (aEncryptionBuffer.getArray()), nLength );
+ OSL_ASSERT( aCipherResult == rtl_Cipher_E_None );
+
+ aChucker.WriteBytes( aEncryptionBuffer );
+ aCRC.update ( aEncryptionBuffer );
+ aEncryptionBuffer.realloc ( nOldLength );
+ }
+ else
+ aChucker.WriteBytes ( aTmpBuffer );
+ }
+}
+void ZipOutputStream::writeEND(sal_uInt32 nOffset, sal_uInt32 nLength)
+ throw(IOException, RuntimeException)
+{
+ aChucker << ENDSIG;
+ aChucker << static_cast < sal_Int16 > ( 0 );
+ aChucker << static_cast < sal_Int16 > ( 0 );
+ aChucker << static_cast < sal_Int16 > ( aZipList.size() );
+ aChucker << static_cast < sal_Int16 > ( aZipList.size() );
+ aChucker << nLength;
+ aChucker << nOffset;
+ aChucker << static_cast < sal_Int16 > ( 0 );
+}
+void ZipOutputStream::writeCEN( const ZipEntry &rEntry )
+ throw(IOException, RuntimeException)
+{
+ if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( rEntry.sPath, sal_True ) )
+ throw IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected character is used in file name." ) ), Reference< XInterface >() );
+
+ ::rtl::OString sUTF8Name = ::rtl::OUStringToOString( rEntry.sPath, RTL_TEXTENCODING_UTF8 );
+ sal_Int16 nNameLength = static_cast < sal_Int16 > ( sUTF8Name.getLength() );
+
+ aChucker << CENSIG;
+ aChucker << rEntry.nVersion;
+ 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 );
+ aChucker << rEntry.nFlag;
+ aChucker << static_cast < sal_Int16 > ( STORED );
+ }
+ else
+ {
+ aChucker << rEntry.nFlag;
+ aChucker << rEntry.nMethod;
+ }
+ aChucker << static_cast < sal_uInt32> ( rEntry.nTime );
+ aChucker << static_cast < sal_uInt32> ( rEntry.nCrc );
+ aChucker << rEntry.nCompressedSize;
+ aChucker << rEntry.nSize;
+ aChucker << nNameLength;
+ aChucker << static_cast < sal_Int16> (0);
+ aChucker << static_cast < sal_Int16> (0);
+ aChucker << static_cast < sal_Int16> (0);
+ aChucker << static_cast < sal_Int16> (0);
+ aChucker << static_cast < sal_Int32> (0);
+ aChucker << rEntry.nOffset;
+
+ Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() );
+ aChucker.WriteBytes( aSequence );
+}
+void ZipOutputStream::writeEXT( const ZipEntry &rEntry )
+ throw(IOException, RuntimeException)
+{
+ aChucker << EXTSIG;
+ aChucker << static_cast < sal_uInt32> ( rEntry.nCrc );
+ aChucker << rEntry.nCompressedSize;
+ aChucker << rEntry.nSize;
+}
+
+sal_Int32 ZipOutputStream::writeLOC( const ZipEntry &rEntry )
+ throw(IOException, RuntimeException)
+{
+ if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( rEntry.sPath, sal_True ) )
+ throw IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected character is used in file name." ) ), Reference< XInterface >() );
+
+ ::rtl::OString sUTF8Name = ::rtl::OUStringToOString( rEntry.sPath, RTL_TEXTENCODING_UTF8 );
+ sal_Int16 nNameLength = static_cast < sal_Int16 > ( sUTF8Name.getLength() );
+
+ aChucker << LOCSIG;
+ 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 );
+ aChucker << nTmpFlag;
+ aChucker << static_cast < sal_Int16 > ( STORED );
+ }
+ else
+ {
+ aChucker << rEntry.nFlag;
+ aChucker << rEntry.nMethod;
+ }
+
+ aChucker << static_cast < sal_uInt32 > (rEntry.nTime);
+ if ((rEntry.nFlag & 8) == 8 )
+ {
+ aChucker << static_cast < sal_Int32 > (0);
+ aChucker << static_cast < sal_Int32 > (0);
+ aChucker << static_cast < sal_Int32 > (0);
+ }
+ else
+ {
+ aChucker << static_cast < sal_uInt32 > (rEntry.nCrc);
+ aChucker << rEntry.nCompressedSize;
+ aChucker << rEntry.nSize;
+ }
+ aChucker << nNameLength;
+ aChucker << static_cast < sal_Int16 > (0);
+
+ Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() );
+ aChucker.WriteBytes( aSequence );
+
+ return LOCHDR + nNameLength;
+}
+sal_uInt32 ZipOutputStream::getCurrentDosTime( )
+{
+ oslDateTime aDateTime;
+ TimeValue aTimeValue;
+ osl_getSystemTime ( &aTimeValue );
+ osl_getDateTimeFromTimeValue( &aTimeValue, &aDateTime);
+
+ sal_uInt32 nYear = static_cast <sal_uInt32> (aDateTime.Year);
+
+ if (nYear>1980)
+ nYear-=1980;
+ else if (nYear>80)
+ nYear-=80;
+ sal_uInt32 nResult = static_cast < sal_uInt32>( ( ( ( aDateTime.Day) +
+ ( 32 * (aDateTime.Month)) +
+ ( 512 * nYear ) ) << 16) |
+ ( ( aDateTime.Seconds/2) +
+ ( 32 * aDateTime.Minutes) +
+ ( 2048 * static_cast <sal_uInt32 > (aDateTime.Hours) ) ) );
+ return nResult;
+}
+/*
+
+ This is actually never used, so I removed it, but thought that the
+ implementation details may be useful in the future...mtg 20010307
+
+ I stopped using the time library and used the OSL version instead, but
+ it might still be useful to have this code here..
+
+void ZipOutputStream::dosDateToTMDate ( tm &rTime, sal_uInt32 nDosDate)
+{
+ sal_uInt32 nDate = static_cast < sal_uInt32 > (nDosDate >> 16);
+ rTime.tm_mday = static_cast < sal_uInt32 > ( nDate & 0x1F);
+ rTime.tm_mon = static_cast < sal_uInt32 > ( ( ( (nDate) & 0x1E0)/0x20)-1);
+ rTime.tm_year = static_cast < sal_uInt32 > ( ( (nDate & 0x0FE00)/0x0200)+1980);
+
+ rTime.tm_hour = static_cast < sal_uInt32 > ( (nDosDate & 0xF800)/0x800);
+ rTime.tm_min = static_cast < sal_uInt32 > ( (nDosDate & 0x7E0)/0x20);
+ rTime.tm_sec = static_cast < sal_uInt32 > ( 2 * (nDosDate & 0x1F) );
+}
+*/
+
diff --git a/package/source/zipapi/makefile.mk b/package/source/zipapi/makefile.mk
new file mode 100644
index 000000000000..a9548ace659b
--- /dev/null
+++ b/package/source/zipapi/makefile.mk
@@ -0,0 +1,59 @@
+#*************************************************************************
+#
+# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+#
+# Copyright 2000, 2010 Oracle and/or its affiliates.
+#
+# OpenOffice.org - a multi-platform office productivity suite
+#
+# This file is part of OpenOffice.org.
+#
+# OpenOffice.org is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Lesser General Public License version 3
+# only, as published by the Free Software Foundation.
+#
+# OpenOffice.org is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License version 3 for more details
+# (a copy is included in the LICENSE file that accompanied this code).
+#
+# You should have received a copy of the GNU Lesser General Public License
+# version 3 along with OpenOffice.org. If not, see
+# <http://www.openoffice.org/license.html>
+# for a copy of the LGPLv3 License.
+#
+#*************************************************************************
+
+PRJ=..$/..
+PRJNAME=package
+TARGET=zipapi
+
+ENABLE_EXCEPTIONS=TRUE
+
+# --- Settings -----------------------------------------------------
+
+.INCLUDE : settings.mk
+
+# --- Files --------------------------------------------------------
+.IF "$(L10N_framework)"==""
+#CFLAGS+=/Ob0 /Od
+.IF "$(SYSTEM_ZLIB)" == "YES"
+CFLAGS+=-DSYSTEM_ZLIB
+.ENDIF
+SLOFILES= \
+ $(SLO)$/CRC32.obj \
+ $(SLO)$/ByteChucker.obj \
+ $(SLO)$/ByteGrabber.obj \
+ $(SLO)$/Inflater.obj \
+ $(SLO)$/Deflater.obj \
+ $(SLO)$/ZipEnumeration.obj \
+ $(SLO)$/ZipFile.obj \
+ $(SLO)$/ZipOutputStream.obj \
+ $(SLO)$/XUnbufferedStream.obj
+
+.ENDIF # L10N_framework
+
+# --- Targets ------------------------------------------------------
+
+.INCLUDE : target.mk