From b8954b7df90c9904d7cf2c1e859ce95d9fc754e8 Mon Sep 17 00:00:00 2001 From: Martin Gallwey Date: Tue, 4 Dec 2001 16:45:30 +0000 Subject: #95155# add support for unbuffered streams --- package/source/zipapi/XUnbufferedStream.cxx | 262 ++++++++++++++++++++++++++++ package/source/zipapi/XUnbufferedStream.hxx | 141 +++++++++++++++ package/source/zipapi/ZipFile.cxx | 22 ++- 3 files changed, 423 insertions(+), 2 deletions(-) create mode 100644 package/source/zipapi/XUnbufferedStream.cxx create mode 100644 package/source/zipapi/XUnbufferedStream.hxx diff --git a/package/source/zipapi/XUnbufferedStream.cxx b/package/source/zipapi/XUnbufferedStream.cxx new file mode 100644 index 000000000000..923588645d3a --- /dev/null +++ b/package/source/zipapi/XUnbufferedStream.cxx @@ -0,0 +1,262 @@ +/************************************************************************* + * + * $RCSfile: XUnbufferedStream.cxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: mtg $ $Date: 2001-12-04 17:41:17 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + * + ************************************************************************/ +#ifndef _XUNBUFFERED_STREAM_HXX +#include +#endif +#ifndef _ENCRYPTION_DATA_HXX_ +#include +#endif +#ifndef _COM_SUN_STAR_PACKAGES_ZIP_ZIPCONSTANTS_HPP_ +#include +#endif +#ifndef _PACKAGE_CONSTANTS_HXX_ +#include +#endif +#ifndef _RTL_CIPHER_H_ +#include +#endif +#ifndef _ZIP_FILE_HXX +#include +#endif +#ifndef _ENCRYPTED_DATA_HEADER_HXX_ +#include +#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 ::rtl::OUString; + +XUnbufferedStream::XUnbufferedStream( ZipEntry & rEntry, + com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream, + const vos::ORef < EncryptionData > &rData, + sal_Bool bNewRawStream, + sal_Bool bIsEncrypted ) +: maEntry ( rEntry ) +, mxData ( rData ) +, mbRawStream ( bNewRawStream ) +, mbFinished ( sal_False ) +, mxZipStream ( xNewZipStream ) +, mxZipSeek ( xNewZipStream, UNO_QUERY ) +, maInflater ( sal_True ) +, maCipher ( NULL ) +, mnMyCurrent ( 0 ) +, mnZipEnd ( 0 ) +, mnZipSize ( 0 ) +, mnZipCurrent ( 0 ) +, mnHeaderToRead ( 0 ) +{ + 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 = ( !bNewRawStream && bHaveEncryptData && bIsEncrypted ) ? sal_True : sal_False; + + if ( bMustDecrypt ) + ZipFile::StaticGetCipher ( rData, maCipher ); + 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 + maHeader.realloc ( n_ConstHeaderSize + + rData->aInitVector.getLength() + + rData->aSalt.getLength() + + rData->aDigest.getLength() ); + sal_Int8 * pHeader = maHeader.getArray(); + ZipFile::StaticFillHeader ( rData, rEntry.nSize, pHeader ); + mnHeaderToRead = static_cast < sal_Int16 > ( maHeader.getLength() ); + } +} + +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) +{ + sal_Int32 nRequestedBytes = nBytesToRead; + if ( mnMyCurrent + nRequestedBytes > mnZipSize ) + nRequestedBytes = static_cast < sal_Int32 > ( mnZipSize - mnMyCurrent ); + + sal_Int32 nRead = 0, nLastRead = 0, nTotal = 0; + aData.realloc ( nRequestedBytes ); + if ( nRequestedBytes ) + { + if ( mnHeaderToRead ) + { + sal_Int16 nToRead = nRequestedBytes > mnHeaderToRead ? mnHeaderToRead : nRequestedBytes; + memcpy ( aData.getArray(), maHeader.getConstArray() + maHeader.getLength() - mnHeaderToRead, nToRead ); + mnHeaderToRead -= nToRead; + if ( mnHeaderToRead == 0 ) + maHeader.realloc ( 0 ); + } + + + if ( !mbRawStream ) + { + while ( 0 == ( nRead = maInflater.doInflateSegment( aData, nRead, aData.getLength() - nRead ) ) || + ( nRead + nLastRead < nRequestedBytes && mnZipCurrent < mnZipEnd ) ) + { + nLastRead = nRead; + if ( maInflater.finished() || maInflater.needsDictionary() ) + { + // some error handling ? + return nRead + nLastRead; + } + + sal_Int64 nDiff = mnZipEnd - mnZipCurrent; + if ( nDiff > 0 ) + { + mxZipSeek->seek ( mnZipCurrent ); + sal_Int32 nZipRead = mxZipStream->readBytes ( maCompBuffer, static_cast < sal_Int32 > ( nDiff < nRequestedBytes ? nDiff : nRequestedBytes ) ); + mnZipCurrent += nZipRead; + // maCompBuffer now has the uncompressed data, check if we need to decrypt + // before passing to the Inflater + if ( maCipher ) + { + Sequence < sal_Int8 > aCryptBuffer ( nZipRead ); + rtlCipherError aResult = rtl_cipher_decode ( maCipher, + maCompBuffer.getConstArray(), + nZipRead, + reinterpret_cast < sal_uInt8 * > (aCryptBuffer.getArray()), + nZipRead); + OSL_ASSERT (aResult == rtl_Cipher_E_None); + maCompBuffer = aCryptBuffer; // Now it holds the decrypted data + + } + maInflater.setInput ( maCompBuffer ); + } + else + { + // some error handling ? + return nRead + nLastRead; + } + } + } + else + { + sal_Int64 nDiff = mnZipEnd - mnZipCurrent; + mxZipSeek->seek ( mnZipCurrent ); + nRead = mxZipStream->readBytes ( aData, static_cast < sal_Int32 > ( nDiff < nRequestedBytes ? nDiff : nRequestedBytes ) ); + mnZipCurrent += nRead; + } + mnMyCurrent += nRead; + nTotal = nRead + nLastRead; + if ( nTotal < nBytesToRead ) + aData.realloc ( nTotal ); + } + 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) +{ + 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..b2494545a745 --- /dev/null +++ b/package/source/zipapi/XUnbufferedStream.hxx @@ -0,0 +1,141 @@ +/************************************************************************* + * + * $RCSfile: XUnbufferedStream.hxx,v $ + * + * $Revision: 1.1 $ + * + * last change: $Author: mtg $ $Date: 2001-12-04 17:41:17 $ + * + * The Contents of this file are made available subject to the terms of + * either of the following licenses + * + * - GNU Lesser General Public License Version 2.1 + * - Sun Industry Standards Source License Version 1.1 + * + * Sun Microsystems Inc., October, 2000 + * + * GNU Lesser General Public License Version 2.1 + * ============================================= + * Copyright 2000 by Sun Microsystems, Inc. + * 901 San Antonio Road, Palo Alto, CA 94303, USA + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software Foundation. + * + * This library 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 for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + * + * + * Sun Industry Standards Source License Version 1.1 + * ================================================= + * The contents of this file are subject to the Sun Industry Standards + * Source License Version 1.1 (the "License"); You may not use this file + * except in compliance with the License. You may obtain a copy of the + * License at http://www.openoffice.org/license.html. + * + * Software provided under this License is provided on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, + * WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS, + * MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING. + * See the License for the specific provisions governing your rights and + * obligations concerning the Software. + * + * The Initial Developer of the Original Code is: Sun Microsystems, Inc. + * + * Copyright: 2000 by Sun Microsystems, Inc. + * + * All Rights Reserved. + * + * Contributor(s): Martin Gallwey (gallwey@sun.com) + * + * + ************************************************************************/ +#ifndef _XUNBUFFERED_STREAM_HXX +#define _XUNBUFFERED_STREAM_HXX + +#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_LANG_ILLEGALARGUMENTEXCEPTION_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_IO_XSEEKABLE_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_IO_XINPUTSTREAM_HPP_ +#include +#endif +#ifndef _COM_SUN_STAR_IO_XOUTPUTSTREAM_HPP_ +#include +#endif +#ifndef _CPPUHELPER_IMPLBASE1_HXX_ +#include +#endif +#ifndef _VOS_REF_H_ +#include +#endif +#ifndef _INFLATER_HXX +#include +#endif +#ifndef _ZIP_ENTRY_HXX_ +#include +#endif + +class EncryptionData; +typedef void* rtlCipher; +class XUnbufferedStream : public cppu::WeakImplHelper1 +< + com::sun::star::io::XInputStream +> +{ +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::Sequence < sal_Int8 > maCompBuffer, maHeader; + ZipEntry maEntry; + vos::ORef < EncryptionData > mxData; + rtlCipher maCipher; + Inflater maInflater; + sal_Bool mbRawStream, mbFinished; + sal_Int16 mnHeaderToRead; + sal_Int64 mnZipCurrent, mnZipEnd, mnZipSize, mnMyCurrent; + +public: + XUnbufferedStream( ZipEntry & rEntry, + com::sun::star::uno::Reference < com::sun::star::io::XInputStream > xNewZipStream, + const vos::ORef < EncryptionData > &rData, + sal_Bool bRawStream, + sal_Bool bIsEncrypted); + + 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/ZipFile.cxx b/package/source/zipapi/ZipFile.cxx index 8e3c0dc4f3dc..3a35b1624931 100644 --- a/package/source/zipapi/ZipFile.cxx +++ b/package/source/zipapi/ZipFile.cxx @@ -2,9 +2,9 @@ * * $RCSfile: ZipFile.cxx,v $ * - * $Revision: 1.33 $ + * $Revision: 1.34 $ * - * last change: $Author: mtg $ $Date: 2001-11-15 20:22:18 $ + * last change: $Author: mtg $ $Date: 2001-12-04 17:45:30 $ * * The Contents of this file are made available subject to the terms of * either of the following licenses @@ -76,6 +76,9 @@ #ifndef _XMEMORY_STREAM_HXX #include #endif +#ifndef _XUNBUFFERED_STREAM_HXX +#include +#endif #ifndef _XFILE_STREAM_HXX #include #endif @@ -411,6 +414,15 @@ Reference < XInputStream > ZipFile::createMemoryStream( } return Reference < XInputStream > ( new XMemoryStream ( aWriteBuffer ) ); } +Reference < XInputStream > ZipFile::createUnbufferedStream( + ZipEntry & rEntry, + const ORef < EncryptionData > &rData, + sal_Bool bRawStream, + sal_Bool bIsEncrypted ) +{ + return new XUnbufferedStream ( rEntry, xStream, rData, bRawStream, bIsEncrypted ); +} + ZipEnumeration * SAL_CALL ZipFile::entries( ) { @@ -447,9 +459,12 @@ Reference< XInputStream > SAL_CALL ZipFile::getInputStream( ZipEntry& rEntry, if ( bIsEncrypted && !rData.isEmpty() && rData->aDigest.getLength() ) bNeedRawStream = !hasValidPassword ( rEntry, rData ); + return createUnbufferedStream ( rEntry, rData, bNeedRawStream, bIsEncrypted ); + /* return rEntry.nSize > n_ConstMaxMemoryStreamSize ? createFileStream ( rEntry, rData, bNeedRawStream, bIsEncrypted ) : createMemoryStream ( rEntry, rData, bNeedRawStream, bIsEncrypted); + */ //return createMemoryStream( rEntry, rData, sal_False ); } @@ -462,9 +477,12 @@ Reference< XInputStream > SAL_CALL ZipFile::getRawStream( ZipEntry& rEntry, if ( rEntry.nOffset <= 0 ) readLOC( rEntry ); + return createUnbufferedStream ( rEntry, rData, sal_True, bIsEncrypted ); + /* return ( rEntry.nMethod == DEFLATED ? rEntry.nCompressedSize : rEntry.nSize > n_ConstMaxMemoryStreamSize ) ? createFileStream ( rEntry, rData, sal_True, bIsEncrypted ) : createMemoryStream ( rEntry, rData, sal_True, bIsEncrypted ); + */ //return createMemoryStream( rEntry, rData, sal_True ); } -- cgit v1.2.1