merge the formfield patch from ooo-build
[ooovba.git] / package / source / zipapi / EntryInputStream.cxx
blob084fd053a943026f0512cb5437e4b2880a816706
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: EntryInputStream.cxx,v $
10 * $Revision: 1.22 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_package.hxx"
33 #include <EntryInputStream.hxx>
34 #include <com/sun/star/packages/zip/ZipConstants.hpp>
35 #include <rtl/cipher.h>
36 #include <rtl/digest.h>
37 #include <memory.h> // for memcpy
39 using namespace rtl;
40 using namespace com::sun::star;
41 using namespace com::sun::star::uno;
42 using namespace com::sun::star::packages::zip;
43 using namespace com::sun::star::packages::zip::ZipConstants;
45 /** Provides access to the compressed data in a zipfile.
47 * 04/12/00 - uncompresses the stream into memory and seeks on it 'in memory'
48 * This and the ZipPackageBuffer used in the ZipOutputStream are memory hogs
49 * and will hopefully be replaced eventually
51 * Acts on the same underlying XInputStream as both the full Zip File and other
52 * EntryInputStreams, and thus must maintain its current position in the stream and
53 * seek to it before performing any reads.
56 EntryInputStream::EntryInputStream( Reference < io::XInputStream > xNewInput,
57 const ZipEntry & rNewEntry,
58 const vos::ORef < EncryptionData > &xEncryptData,
59 sal_Bool bGetRawStream)
60 : xStream( xNewInput )
61 , xSeek( xNewInput, UNO_QUERY )
62 , aEntry (rNewEntry )
63 , nCurrent( 0 )
64 , bHaveInMemory ( sal_False )
65 , aInflater( sal_True )
66 , aBuffer( 0 )
67 , xEncryptionData (xEncryptData)
68 , bRawStream (bGetRawStream)
70 if (bGetRawStream)
72 nUncompressedSize = aEntry.nMethod == DEFLATED ? aEntry.nCompressedSize : aEntry.nSize;
73 nEnd = aEntry.nOffset + nUncompressedSize;
75 else
77 nEnd = aEntry.nMethod == DEFLATED ? aEntry.nOffset + aEntry.nCompressedSize : aEntry.nOffset + aEntry.nSize;
78 nUncompressedSize = aEntry.nSize;
81 void EntryInputStream::readIntoMemory()
82 throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException)
84 if (!bHaveInMemory)
86 Sequence < sal_Int8 > aReadBuffer;
87 xSeek->seek(aEntry.nOffset);
88 sal_Int32 nSize = aEntry.nMethod == DEFLATED ? aEntry.nCompressedSize : aEntry.nSize;
90 if (nSize <0)
91 throw io::BufferSizeExceededException(::rtl::OUString(), *this);
93 xStream->readBytes( aReadBuffer, nSize ); // Now it holds the raw stuff from disk
95 if (xEncryptionData->aSalt.getLength())
97 // Have salt, will travel
98 Sequence < sal_uInt8 > aDerivedKey (16);
99 rtlCipherError aResult;
100 Sequence < sal_Int8 > aDecryptBuffer;
102 // Get the key
103 rtl_digest_PBKDF2 ( aDerivedKey.getArray(), 16,
104 reinterpret_cast < const sal_uInt8 * > (xEncryptionData->aKey.getConstArray()),
105 xEncryptionData->aKey.getLength(),
106 xEncryptionData->aSalt.getConstArray(),
107 xEncryptionData->aSalt.getLength(),
108 xEncryptionData->nIterationCount );
110 rtlCipher aCipher = rtl_cipher_create (rtl_Cipher_AlgorithmBF, rtl_Cipher_ModeStream);
111 aResult = rtl_cipher_init( aCipher, rtl_Cipher_DirectionDecode,
112 aDerivedKey.getConstArray(),
113 aDerivedKey.getLength(),
114 xEncryptionData->aInitVector.getConstArray(),
115 xEncryptionData->aInitVector.getLength());
116 OSL_ASSERT (aResult == rtl_Cipher_E_None);
117 aDecryptBuffer.realloc ( nSize );
118 aResult = rtl_cipher_decode ( aCipher,
119 aReadBuffer.getConstArray(),
120 nSize,
121 reinterpret_cast < sal_uInt8 * > (aDecryptBuffer.getArray()),
122 nSize);
123 OSL_ASSERT (aResult == rtl_Cipher_E_None);
124 aReadBuffer = aDecryptBuffer; // Now it holds the decrypted data
126 if (bRawStream || aEntry.nMethod == STORED)
127 aBuffer = aReadBuffer; // bRawStream means the caller doesn't want it decompressed
128 else
130 aInflater.setInputSegment(aReadBuffer, 0, nSize );
131 aBuffer.realloc( aEntry.nSize );
132 aInflater.doInflate(aBuffer);
133 aInflater.end();
135 bHaveInMemory = sal_True;
138 EntryInputStream::~EntryInputStream( void )
142 sal_Int32 SAL_CALL EntryInputStream::readBytes( Sequence< sal_Int8 >& aData,
143 sal_Int32 nBytesToRead )
144 throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException)
146 if (nBytesToRead <0)
147 throw io::BufferSizeExceededException(::rtl::OUString(), *this);
148 if (!bHaveInMemory)
149 readIntoMemory();
150 if (nBytesToRead + nCurrent > nUncompressedSize)
151 nBytesToRead = static_cast < sal_Int32> ( nUncompressedSize - nCurrent );
153 aData.realloc( nBytesToRead );
154 memcpy(aData.getArray(), aBuffer.getConstArray() + nCurrent, nBytesToRead);
155 nCurrent+=nBytesToRead;
157 return nBytesToRead;
159 sal_Int32 SAL_CALL EntryInputStream::readSomeBytes( Sequence< sal_Int8 >& aData,
160 sal_Int32 nMaxBytesToRead )
161 throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException)
163 return readBytes( aData, nMaxBytesToRead );
165 void SAL_CALL EntryInputStream::skipBytes( sal_Int32 nBytesToSkip )
166 throw(io::NotConnectedException, io::BufferSizeExceededException, io::IOException, RuntimeException)
168 if (nBytesToSkip < 0)
169 throw io::BufferSizeExceededException(::rtl::OUString(), *this);
171 if (nBytesToSkip + nCurrent > nUncompressedSize)
172 nBytesToSkip = static_cast < sal_Int32 > (nUncompressedSize- nCurrent);
174 nCurrent+=nBytesToSkip;
176 sal_Int32 SAL_CALL EntryInputStream::available( )
177 throw(io::NotConnectedException, io::IOException, RuntimeException)
179 return static_cast < sal_Int32 > (nUncompressedSize - nCurrent);
181 void SAL_CALL EntryInputStream::closeInput( )
182 throw(io::NotConnectedException, io::IOException, RuntimeException)
186 void SAL_CALL EntryInputStream::seek( sal_Int64 location )
187 throw(lang::IllegalArgumentException, io::IOException, RuntimeException)
189 if (location > nUncompressedSize)
190 location = nUncompressedSize;
191 if (location <0)
192 location = 0;
193 nCurrent = location;
195 sal_Int64 SAL_CALL EntryInputStream::getPosition( )
196 throw(io::IOException, RuntimeException)
198 return nCurrent;
200 sal_Int64 SAL_CALL EntryInputStream::getLength( )
201 throw(io::IOException, RuntimeException)
203 return nUncompressedSize;