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: XFileStream.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 <XFileStream.hxx>
34 #include <EncryptionData.hxx>
35 #include <com/sun/star/packages/zip/ZipConstants.hpp>
36 #include <PackageConstants.hxx>
37 #include <rtl/cipher.h>
38 #include <ZipFile.hxx>
39 #include <EncryptedDataHeader.hxx>
40 #include <com/sun/star/io/XOutputStream.hpp>
42 using namespace com::sun::star::packages::zip::ZipConstants
;
43 using namespace com::sun::star::io
;
44 using namespace com::sun::star::uno
;
45 using com::sun::star::lang::IllegalArgumentException
;
46 using ::rtl::OUString
;
48 XFileStream::XFileStream( ZipEntry
& rEntry
,
49 com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
> xNewZipStream
,
50 com::sun::star::uno::Reference
< com::sun::star::io::XInputStream
> xNewTempStream
,
51 const vos::ORef
< EncryptionData
> &rData
,
52 sal_Bool bNewRawStream
,
53 sal_Bool bIsEncrypted
)
56 , mbRawStream ( bNewRawStream
)
57 , mbFinished ( sal_False
)
58 , mxTempIn ( xNewTempStream
)
59 , mxTempSeek ( xNewTempStream
, UNO_QUERY
)
60 , mxTempOut ( xNewTempStream
, UNO_QUERY
)
61 , mxZipStream ( xNewZipStream
)
62 , mxZipSeek ( xNewZipStream
, UNO_QUERY
)
63 , maInflater ( sal_True
)
66 mnZipCurrent
= maEntry
.nOffset
;
69 mnZipSize
= maEntry
.nMethod
== DEFLATED
? maEntry
.nCompressedSize
: maEntry
.nSize
;
70 mnZipEnd
= maEntry
.nOffset
+ mnZipSize
;
74 mnZipSize
= maEntry
.nSize
;
75 mnZipEnd
= maEntry
.nMethod
== DEFLATED
? maEntry
.nOffset
+ maEntry
.nCompressedSize
: maEntry
.nOffset
+ maEntry
.nSize
;
80 sal_Bool bHaveEncryptData
= ( !rData
.isEmpty() && rData
->aSalt
.getLength() && rData
->aInitVector
.getLength() && rData
->nIterationCount
!= 0 ) ? sal_True
: sal_False
;
82 // if we have all the encrypted data, and want a raw stream, then prepend it to the stream, otherwise
83 // make a cipher so we can decrypt it
84 if ( bHaveEncryptData
)
87 ZipFile::StaticGetCipher ( rData
, maCipher
, sal_True
);
90 // Put in the EncryptedDataHeader
91 Sequence
< sal_Int8
> aEncryptedDataHeader ( n_ConstHeaderSize
+
92 rData
->aInitVector
.getLength() +
93 rData
->aSalt
.getLength() +
94 rData
->aDigest
.getLength() );
95 sal_Int8
* pHeader
= aEncryptedDataHeader
.getArray();
96 ZipFile::StaticFillHeader ( rData
, rEntry
.nSize
, pHeader
);
97 mxTempOut
->writeBytes ( aEncryptedDataHeader
);
98 mnZipSize
+= mxTempSeek
->getPosition();
99 mxTempSeek
->seek ( 0 );
105 XFileStream::~XFileStream()
108 rtl_cipher_destroy ( maCipher
);
111 void XFileStream::fill( sal_Int64 nUntil
)
114 sal_Int64 nPosition
= mxTempSeek
->getPosition();
115 mxTempSeek
->seek ( mxTempSeek
->getLength() );
116 maBuffer
.realloc ( n_ConstBufferSize
);
118 while ( mxTempSeek
->getLength() < nUntil
)
122 while ( 0 == ( nRead
= maInflater
.doInflate( maBuffer
) ) )
124 if ( maInflater
.finished() || maInflater
.needsDictionary() )
126 // some error handling ?
130 sal_Int64 nDiff
= mnZipEnd
- mnZipCurrent
;
133 mxZipSeek
->seek ( mnZipCurrent
);
134 nRead
= mxZipStream
->readBytes ( maCompBuffer
, static_cast < sal_Int32
> ( nDiff
< n_ConstBufferSize
? nDiff
: n_ConstBufferSize
) );
135 mnZipCurrent
+= nRead
;
136 // maCompBuffer now has the uncompressed data, check if we need to decrypt
137 // before passing to the Inflater
140 Sequence
< sal_Int8
> aCryptBuffer ( nRead
);
141 rtlCipherError aResult
= rtl_cipher_decode ( maCipher
,
142 maCompBuffer
.getConstArray(),
144 reinterpret_cast < sal_uInt8
* > (aCryptBuffer
.getArray()),
146 OSL_ASSERT (aResult
== rtl_Cipher_E_None
);
147 maCompBuffer
= aCryptBuffer
; // Now it holds the decrypted data
150 maInflater
.setInput ( maCompBuffer
);
154 // some error handling ?
161 sal_Int64 nDiff
= mnZipEnd
- mnZipCurrent
;
162 mxZipSeek
->seek ( mnZipCurrent
);
163 nRead
= mxZipStream
->readBytes ( maBuffer
, static_cast < sal_Int32
> ( nDiff
< n_ConstBufferSize
? nDiff
: n_ConstBufferSize
) );
164 mnZipCurrent
+= nRead
;
166 Sequence
< sal_Int8
> aTmpBuffer ( maBuffer
.getConstArray(), nRead
);
167 mxTempOut
->writeBytes ( aTmpBuffer
);
169 mxTempSeek
->seek ( nPosition
);
172 sal_Int32 SAL_CALL
XFileStream::readBytes( Sequence
< sal_Int8
>& aData
, sal_Int32 nBytesToRead
)
173 throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
175 sal_Int64 nPosition
= mxTempSeek
->getPosition();
176 if ( nPosition
+ nBytesToRead
> mnZipSize
)
177 nBytesToRead
= static_cast < sal_Int32
> ( mnZipSize
- nPosition
);
179 sal_Int64 nUntil
= nBytesToRead
+ nPosition
+ n_ConstBufferSize
;
180 if (nUntil
> mnZipSize
)
182 if ( nUntil
> mxTempSeek
->getLength() )
184 sal_Int32 nRead
= mxTempIn
->readBytes ( aData
, nBytesToRead
);
188 sal_Int32 SAL_CALL
XFileStream::readSomeBytes( Sequence
< sal_Int8
>& aData
, sal_Int32 nMaxBytesToRead
)
189 throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
191 return readBytes ( aData
, nMaxBytesToRead
);
193 void SAL_CALL
XFileStream::skipBytes( sal_Int32 nBytesToSkip
)
194 throw( NotConnectedException
, BufferSizeExceededException
, IOException
, RuntimeException
)
196 seek ( mxTempSeek
->getPosition() + nBytesToSkip
);
199 sal_Int32 SAL_CALL
XFileStream::available( )
200 throw( NotConnectedException
, IOException
, RuntimeException
)
202 return static_cast < sal_Int32
> ( mnZipSize
- mxTempSeek
->getPosition() );
205 void SAL_CALL
XFileStream::closeInput( )
206 throw( NotConnectedException
, IOException
, RuntimeException
)
209 void SAL_CALL
XFileStream::seek( sal_Int64 location
)
210 throw( IllegalArgumentException
, IOException
, RuntimeException
)
212 if ( location
> mnZipSize
|| location
< 0 )
213 throw IllegalArgumentException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( OSL_LOG_PREFIX
) ), uno::Reference
< uno::XInterface
>(), 1 );
214 if ( location
> mxTempSeek
->getLength() )
216 sal_Int64 nUntil
= location
+ n_ConstBufferSize
> mnZipSize
? mnZipSize
: location
+ n_ConstBufferSize
;
219 mxTempSeek
->seek ( location
);
221 sal_Int64 SAL_CALL
XFileStream::getPosition( )
222 throw(IOException
, RuntimeException
)
224 return mxTempSeek
->getPosition();
226 sal_Int64 SAL_CALL
XFileStream::getLength( )
227 throw(IOException
, RuntimeException
)