1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: EntryInputStream.cxx,v $
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
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
)
64 , bHaveInMemory ( sal_False
)
65 , aInflater( sal_True
)
67 , xEncryptionData (xEncryptData
)
68 , bRawStream (bGetRawStream
)
72 nUncompressedSize
= aEntry
.nMethod
== DEFLATED
? aEntry
.nCompressedSize
: aEntry
.nSize
;
73 nEnd
= aEntry
.nOffset
+ nUncompressedSize
;
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
)
86 Sequence
< sal_Int8
> aReadBuffer
;
87 xSeek
->seek(aEntry
.nOffset
);
88 sal_Int32 nSize
= aEntry
.nMethod
== DEFLATED
? aEntry
.nCompressedSize
: aEntry
.nSize
;
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
;
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(),
121 reinterpret_cast < sal_uInt8
* > (aDecryptBuffer
.getArray()),
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
130 aInflater
.setInputSegment(aReadBuffer
, 0, nSize
);
131 aBuffer
.realloc( aEntry
.nSize
);
132 aInflater
.doInflate(aBuffer
);
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
)
147 throw io::BufferSizeExceededException(::rtl::OUString(), *this);
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
;
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
;
195 sal_Int64 SAL_CALL
EntryInputStream::getPosition( )
196 throw(io::IOException
, RuntimeException
)
200 sal_Int64 SAL_CALL
EntryInputStream::getLength( )
201 throw(io::IOException
, RuntimeException
)
203 return nUncompressedSize
;