1*a3872823SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*a3872823SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*a3872823SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*a3872823SAndrew Rist  * distributed with this work for additional information
6*a3872823SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*a3872823SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*a3872823SAndrew Rist  * "License"); you may not use this file except in compliance
9*a3872823SAndrew Rist  * with the License.  You may obtain a copy of the License at
10*a3872823SAndrew Rist  *
11*a3872823SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12*a3872823SAndrew Rist  *
13*a3872823SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*a3872823SAndrew Rist  * software distributed under the License is distributed on an
15*a3872823SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*a3872823SAndrew Rist  * KIND, either express or implied.  See the License for the
17*a3872823SAndrew Rist  * specific language governing permissions and limitations
18*a3872823SAndrew Rist  * under the License.
19*a3872823SAndrew Rist  *
20*a3872823SAndrew Rist  *************************************************************/
21*a3872823SAndrew Rist 
22*a3872823SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_package.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <com/sun/star/packages/zip/ZipConstants.hpp>
28cdf0e10cSrcweir #include <com/sun/star/io/XOutputStream.hpp>
29cdf0e10cSrcweir #include <comphelper/storagehelper.hxx>
30cdf0e10cSrcweir 
31cdf0e10cSrcweir #include <osl/time.h>
32cdf0e10cSrcweir 
33cdf0e10cSrcweir #include <EncryptionData.hxx>
34cdf0e10cSrcweir #include <PackageConstants.hxx>
35cdf0e10cSrcweir #include <ZipEntry.hxx>
36cdf0e10cSrcweir #include <ZipFile.hxx>
37cdf0e10cSrcweir #include <ZipPackageStream.hxx>
38cdf0e10cSrcweir #include <ZipOutputStream.hxx>
39cdf0e10cSrcweir 
40cdf0e10cSrcweir using namespace rtl;
41cdf0e10cSrcweir using namespace com::sun::star;
42cdf0e10cSrcweir using namespace com::sun::star::io;
43cdf0e10cSrcweir using namespace com::sun::star::uno;
44cdf0e10cSrcweir using namespace com::sun::star::packages;
45cdf0e10cSrcweir using namespace com::sun::star::packages::zip;
46cdf0e10cSrcweir using namespace com::sun::star::packages::zip::ZipConstants;
47cdf0e10cSrcweir 
48cdf0e10cSrcweir /** This class is used to write Zip files
49cdf0e10cSrcweir  */
ZipOutputStream(const uno::Reference<lang::XMultiServiceFactory> & xFactory,const uno::Reference<XOutputStream> & xOStream)50cdf0e10cSrcweir ZipOutputStream::ZipOutputStream( const uno::Reference< lang::XMultiServiceFactory >& xFactory,
51cdf0e10cSrcweir                                   const uno::Reference < XOutputStream > &xOStream )
52cdf0e10cSrcweir : m_xFactory( xFactory )
53cdf0e10cSrcweir , xStream(xOStream)
54cdf0e10cSrcweir , m_aDeflateBuffer(n_ConstBufferSize)
55cdf0e10cSrcweir , aDeflater(DEFAULT_COMPRESSION, sal_True)
56cdf0e10cSrcweir , aChucker(xOStream)
57cdf0e10cSrcweir , pCurrentEntry(NULL)
58cdf0e10cSrcweir , nMethod(DEFLATED)
59cdf0e10cSrcweir , bFinished(sal_False)
60cdf0e10cSrcweir , bEncryptCurrentEntry(sal_False)
61cdf0e10cSrcweir , m_pCurrentStream(NULL)
62cdf0e10cSrcweir {
63cdf0e10cSrcweir }
64cdf0e10cSrcweir 
~ZipOutputStream(void)65cdf0e10cSrcweir ZipOutputStream::~ZipOutputStream( void )
66cdf0e10cSrcweir {
67cdf0e10cSrcweir 	for (sal_Int32 i = 0, nEnd = aZipList.size(); i < nEnd; i++)
68cdf0e10cSrcweir 		delete aZipList[i];
69cdf0e10cSrcweir }
70cdf0e10cSrcweir 
setMethod(sal_Int32 nNewMethod)71cdf0e10cSrcweir void SAL_CALL ZipOutputStream::setMethod( sal_Int32 nNewMethod )
72cdf0e10cSrcweir 	throw(RuntimeException)
73cdf0e10cSrcweir {
74cdf0e10cSrcweir 	nMethod = static_cast < sal_Int16 > (nNewMethod);
75cdf0e10cSrcweir }
setLevel(sal_Int32 nNewLevel)76cdf0e10cSrcweir void SAL_CALL ZipOutputStream::setLevel( sal_Int32 nNewLevel )
77cdf0e10cSrcweir 	throw(RuntimeException)
78cdf0e10cSrcweir {
79cdf0e10cSrcweir 	aDeflater.setLevel( nNewLevel);
80cdf0e10cSrcweir }
81cdf0e10cSrcweir 
putNextEntry(ZipEntry & rEntry,ZipPackageStream * pStream,sal_Bool bEncrypt)82cdf0e10cSrcweir void SAL_CALL ZipOutputStream::putNextEntry( ZipEntry& rEntry,
83cdf0e10cSrcweir                         ZipPackageStream* pStream,
84cdf0e10cSrcweir 						sal_Bool bEncrypt)
85cdf0e10cSrcweir 	throw(IOException, RuntimeException)
86cdf0e10cSrcweir {
87cdf0e10cSrcweir 	if (pCurrentEntry != NULL)
88cdf0e10cSrcweir 		closeEntry();
89cdf0e10cSrcweir 	if (rEntry.nTime == -1)
90cdf0e10cSrcweir 		rEntry.nTime = getCurrentDosTime();
91cdf0e10cSrcweir 	if (rEntry.nMethod == -1)
92cdf0e10cSrcweir 		rEntry.nMethod = nMethod;
93cdf0e10cSrcweir 	rEntry.nVersion = 20;
94cdf0e10cSrcweir 	rEntry.nFlag = 1 << 11;
95cdf0e10cSrcweir 	if (rEntry.nSize == -1 || rEntry.nCompressedSize == -1 ||
96cdf0e10cSrcweir 		rEntry.nCrc == -1)
97cdf0e10cSrcweir     {
98cdf0e10cSrcweir         rEntry.nSize = rEntry.nCompressedSize = 0;
99cdf0e10cSrcweir 		rEntry.nFlag |= 8;
100cdf0e10cSrcweir     }
101cdf0e10cSrcweir 
102cdf0e10cSrcweir 	if (bEncrypt)
103cdf0e10cSrcweir 	{
104cdf0e10cSrcweir 		bEncryptCurrentEntry = sal_True;
105cdf0e10cSrcweir 
106cdf0e10cSrcweir         m_xCipherContext = ZipFile::StaticGetCipher( m_xFactory, pStream->GetEncryptionData(), true );
107cdf0e10cSrcweir         m_xDigestContext = ZipFile::StaticGetDigestContextForChecksum( m_xFactory, pStream->GetEncryptionData() );
108cdf0e10cSrcweir 		mnDigested = 0;
109cdf0e10cSrcweir 		rEntry.nFlag |= 1 << 4;
110cdf0e10cSrcweir 		m_pCurrentStream = pStream;
111cdf0e10cSrcweir 	}
112cdf0e10cSrcweir 	sal_Int32 nLOCLength = writeLOC(rEntry);
113cdf0e10cSrcweir 	rEntry.nOffset = static_cast < sal_Int32 > (aChucker.GetPosition()) - nLOCLength;
114cdf0e10cSrcweir 	aZipList.push_back( &rEntry );
115cdf0e10cSrcweir 	pCurrentEntry = &rEntry;
116cdf0e10cSrcweir }
117cdf0e10cSrcweir 
closeEntry()118cdf0e10cSrcweir void SAL_CALL ZipOutputStream::closeEntry(  )
119cdf0e10cSrcweir 	throw(IOException, RuntimeException)
120cdf0e10cSrcweir {
121cdf0e10cSrcweir 	ZipEntry *pEntry = pCurrentEntry;
122cdf0e10cSrcweir 	if (pEntry)
123cdf0e10cSrcweir 	{
124cdf0e10cSrcweir 		switch (pEntry->nMethod)
125cdf0e10cSrcweir 		{
126cdf0e10cSrcweir 			case DEFLATED:
127cdf0e10cSrcweir 				aDeflater.finish();
128cdf0e10cSrcweir 				while (!aDeflater.finished())
129cdf0e10cSrcweir 					doDeflate();
130cdf0e10cSrcweir 				if ((pEntry->nFlag & 8) == 0)
131cdf0e10cSrcweir 				{
132cdf0e10cSrcweir 					if (pEntry->nSize != aDeflater.getTotalIn())
133cdf0e10cSrcweir 					{
134cdf0e10cSrcweir 						OSL_ENSURE(false,"Invalid entry size");
135cdf0e10cSrcweir 					}
136cdf0e10cSrcweir 					if (pEntry->nCompressedSize != aDeflater.getTotalOut())
137cdf0e10cSrcweir 					{
138cdf0e10cSrcweir 						//VOS_DEBUG_ONLY("Invalid entry compressed size");
139cdf0e10cSrcweir 						// Different compression strategies make the merit of this
140cdf0e10cSrcweir 						// test somewhat dubious
141cdf0e10cSrcweir 						pEntry->nCompressedSize = aDeflater.getTotalOut();
142cdf0e10cSrcweir 					}
143cdf0e10cSrcweir 					if (pEntry->nCrc != aCRC.getValue())
144cdf0e10cSrcweir 					{
145cdf0e10cSrcweir 						OSL_ENSURE(false,"Invalid entry CRC-32");
146cdf0e10cSrcweir 					}
147cdf0e10cSrcweir 				}
148cdf0e10cSrcweir 				else
149cdf0e10cSrcweir 				{
150cdf0e10cSrcweir 					if ( !bEncryptCurrentEntry )
151cdf0e10cSrcweir                     {
152cdf0e10cSrcweir                         pEntry->nSize = aDeflater.getTotalIn();
153cdf0e10cSrcweir                         pEntry->nCompressedSize = aDeflater.getTotalOut();
154cdf0e10cSrcweir                     }
155cdf0e10cSrcweir 					pEntry->nCrc = aCRC.getValue();
156cdf0e10cSrcweir 					writeEXT(*pEntry);
157cdf0e10cSrcweir 				}
158cdf0e10cSrcweir 				aDeflater.reset();
159cdf0e10cSrcweir 				aCRC.reset();
160cdf0e10cSrcweir 				break;
161cdf0e10cSrcweir 			case STORED:
162cdf0e10cSrcweir 				if (!((pEntry->nFlag & 8) == 0))
163cdf0e10cSrcweir 					OSL_ENSURE ( false, "Serious error, one of compressed size, size or CRC was -1 in a STORED stream");
164cdf0e10cSrcweir 				break;
165cdf0e10cSrcweir 			default:
166cdf0e10cSrcweir 				OSL_ENSURE(false,"Invalid compression method");
167cdf0e10cSrcweir 				break;
168cdf0e10cSrcweir 		}
169cdf0e10cSrcweir 
170cdf0e10cSrcweir 		if (bEncryptCurrentEntry)
171cdf0e10cSrcweir 		{
172cdf0e10cSrcweir 			bEncryptCurrentEntry = sal_False;
173cdf0e10cSrcweir 
174cdf0e10cSrcweir             m_xCipherContext.clear();
175cdf0e10cSrcweir 
176cdf0e10cSrcweir             uno::Sequence< sal_Int8 > aDigestSeq;
177cdf0e10cSrcweir             if ( m_xDigestContext.is() )
178cdf0e10cSrcweir             {
179cdf0e10cSrcweir                 aDigestSeq = m_xDigestContext->finalizeDigestAndDispose();
180cdf0e10cSrcweir                 m_xDigestContext.clear();
181cdf0e10cSrcweir             }
182cdf0e10cSrcweir 
183cdf0e10cSrcweir             if ( m_pCurrentStream )
184cdf0e10cSrcweir                 m_pCurrentStream->setDigest( aDigestSeq );
185cdf0e10cSrcweir 		}
186cdf0e10cSrcweir 		pCurrentEntry = NULL;
187cdf0e10cSrcweir         m_pCurrentStream = NULL;
188cdf0e10cSrcweir 	}
189cdf0e10cSrcweir }
190cdf0e10cSrcweir 
write(const Sequence<sal_Int8> & rBuffer,sal_Int32 nNewOffset,sal_Int32 nNewLength)191cdf0e10cSrcweir void SAL_CALL ZipOutputStream::write( const Sequence< sal_Int8 >& rBuffer, sal_Int32 nNewOffset, sal_Int32 nNewLength )
192cdf0e10cSrcweir 	throw(IOException, RuntimeException)
193cdf0e10cSrcweir {
194cdf0e10cSrcweir 	switch (pCurrentEntry->nMethod)
195cdf0e10cSrcweir 	{
196cdf0e10cSrcweir 		case DEFLATED:
197cdf0e10cSrcweir 			if (!aDeflater.finished())
198cdf0e10cSrcweir 			{
199cdf0e10cSrcweir 				aDeflater.setInputSegment(rBuffer, nNewOffset, nNewLength);
200cdf0e10cSrcweir  				while (!aDeflater.needsInput())
201cdf0e10cSrcweir 					doDeflate();
202cdf0e10cSrcweir 				if (!bEncryptCurrentEntry)
203cdf0e10cSrcweir 					aCRC.updateSegment(rBuffer, nNewOffset, nNewLength);
204cdf0e10cSrcweir 			}
205cdf0e10cSrcweir 			break;
206cdf0e10cSrcweir 		case STORED:
207cdf0e10cSrcweir 			{
208cdf0e10cSrcweir 				Sequence < sal_Int8 > aTmpBuffer ( rBuffer.getConstArray(), nNewLength );
209cdf0e10cSrcweir 				aChucker.WriteBytes( aTmpBuffer );
210cdf0e10cSrcweir 			}
211cdf0e10cSrcweir 			break;
212cdf0e10cSrcweir 	}
213cdf0e10cSrcweir }
214cdf0e10cSrcweir 
rawWrite(Sequence<sal_Int8> & rBuffer,sal_Int32,sal_Int32 nNewLength)215cdf0e10cSrcweir void SAL_CALL ZipOutputStream::rawWrite( Sequence< sal_Int8 >& rBuffer, sal_Int32 /*nNewOffset*/, sal_Int32 nNewLength )
216cdf0e10cSrcweir 	throw(IOException, RuntimeException)
217cdf0e10cSrcweir {
218cdf0e10cSrcweir 	Sequence < sal_Int8 > aTmpBuffer ( rBuffer.getConstArray(), nNewLength );
219cdf0e10cSrcweir 	aChucker.WriteBytes( aTmpBuffer );
220cdf0e10cSrcweir }
221cdf0e10cSrcweir 
rawCloseEntry()222cdf0e10cSrcweir void SAL_CALL ZipOutputStream::rawCloseEntry(  )
223cdf0e10cSrcweir 	throw(IOException, RuntimeException)
224cdf0e10cSrcweir {
225cdf0e10cSrcweir 	if ( pCurrentEntry->nMethod == DEFLATED && ( pCurrentEntry->nFlag & 8 ) )
226cdf0e10cSrcweir 		writeEXT(*pCurrentEntry);
227cdf0e10cSrcweir 	pCurrentEntry = NULL;
228cdf0e10cSrcweir }
229cdf0e10cSrcweir 
finish()230cdf0e10cSrcweir void SAL_CALL ZipOutputStream::finish(  )
231cdf0e10cSrcweir 	throw(IOException, RuntimeException)
232cdf0e10cSrcweir {
233cdf0e10cSrcweir 	if (bFinished)
234cdf0e10cSrcweir 		return;
235cdf0e10cSrcweir 
236cdf0e10cSrcweir 	if (pCurrentEntry != NULL)
237cdf0e10cSrcweir 		closeEntry();
238cdf0e10cSrcweir 
239cdf0e10cSrcweir 	if (aZipList.size() < 1)
240cdf0e10cSrcweir 		OSL_ENSURE(false,"Zip file must have at least one entry!\n");
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 	sal_Int32 nOffset= static_cast < sal_Int32 > (aChucker.GetPosition());
243cdf0e10cSrcweir 	for (sal_Int32 i =0, nEnd = aZipList.size(); i < nEnd; i++)
244cdf0e10cSrcweir 		writeCEN( *aZipList[i] );
245cdf0e10cSrcweir 	writeEND( nOffset, static_cast < sal_Int32 > (aChucker.GetPosition()) - nOffset);
246cdf0e10cSrcweir 	bFinished = sal_True;
247cdf0e10cSrcweir 	xStream->flush();
248cdf0e10cSrcweir }
249cdf0e10cSrcweir 
doDeflate()250cdf0e10cSrcweir void ZipOutputStream::doDeflate()
251cdf0e10cSrcweir {
252cdf0e10cSrcweir 	sal_Int32 nLength = aDeflater.doDeflateSegment(m_aDeflateBuffer, 0, m_aDeflateBuffer.getLength());
253cdf0e10cSrcweir 
254cdf0e10cSrcweir     if ( nLength > 0 )
255cdf0e10cSrcweir     {
256cdf0e10cSrcweir         uno::Sequence< sal_Int8 > aTmpBuffer( m_aDeflateBuffer.getConstArray(), nLength );
257cdf0e10cSrcweir         if ( bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is() )
258cdf0e10cSrcweir         {
259cdf0e10cSrcweir             // Need to update our digest before encryption...
260cdf0e10cSrcweir             sal_Int32 nDiff = n_ConstDigestLength - mnDigested;
261cdf0e10cSrcweir             if ( nDiff )
262cdf0e10cSrcweir             {
263cdf0e10cSrcweir                 sal_Int32 nEat = ::std::min( nLength, nDiff );
264cdf0e10cSrcweir                 uno::Sequence< sal_Int8 > aTmpSeq( aTmpBuffer.getConstArray(), nEat );
265cdf0e10cSrcweir                 m_xDigestContext->updateDigest( aTmpSeq );
266cdf0e10cSrcweir                 mnDigested = mnDigested + static_cast< sal_Int16 >( nEat );
267cdf0e10cSrcweir             }
268cdf0e10cSrcweir 
269cdf0e10cSrcweir             uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->convertWithCipherContext( aTmpBuffer );
270cdf0e10cSrcweir 
271cdf0e10cSrcweir             aChucker.WriteBytes( aEncryptionBuffer );
272cdf0e10cSrcweir 
273cdf0e10cSrcweir             // the sizes as well as checksum for encrypted streams is calculated here
274cdf0e10cSrcweir             pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength();
275cdf0e10cSrcweir             pCurrentEntry->nSize = pCurrentEntry->nCompressedSize;
276cdf0e10cSrcweir             aCRC.update( aEncryptionBuffer );
277cdf0e10cSrcweir         }
278cdf0e10cSrcweir         else
279cdf0e10cSrcweir         {
280cdf0e10cSrcweir             aChucker.WriteBytes ( aTmpBuffer );
281cdf0e10cSrcweir         }
282cdf0e10cSrcweir     }
283cdf0e10cSrcweir 
284cdf0e10cSrcweir     if ( aDeflater.finished() && bEncryptCurrentEntry && m_xDigestContext.is() && m_xCipherContext.is() )
285cdf0e10cSrcweir     {
286cdf0e10cSrcweir         uno::Sequence< sal_Int8 > aEncryptionBuffer = m_xCipherContext->finalizeCipherContextAndDispose();
287cdf0e10cSrcweir         if ( aEncryptionBuffer.getLength() )
288cdf0e10cSrcweir         {
289cdf0e10cSrcweir             aChucker.WriteBytes( aEncryptionBuffer );
290cdf0e10cSrcweir 
291cdf0e10cSrcweir             // the sizes as well as checksum for encrypted streams is calculated hier
292cdf0e10cSrcweir             pCurrentEntry->nCompressedSize += aEncryptionBuffer.getLength();
293cdf0e10cSrcweir             pCurrentEntry->nSize = pCurrentEntry->nCompressedSize;
294cdf0e10cSrcweir             aCRC.update( aEncryptionBuffer );
295cdf0e10cSrcweir         }
296cdf0e10cSrcweir     }
297cdf0e10cSrcweir }
298cdf0e10cSrcweir 
writeEND(sal_uInt32 nOffset,sal_uInt32 nLength)299cdf0e10cSrcweir void ZipOutputStream::writeEND(sal_uInt32 nOffset, sal_uInt32 nLength)
300cdf0e10cSrcweir 	throw(IOException, RuntimeException)
301cdf0e10cSrcweir {
302cdf0e10cSrcweir 	aChucker << ENDSIG;
303cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16 > ( 0 );
304cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16 > ( 0 );
305cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16 > ( aZipList.size() );
306cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16 > ( aZipList.size() );
307cdf0e10cSrcweir 	aChucker << nLength;
308cdf0e10cSrcweir 	aChucker << nOffset;
309cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16 > ( 0 );
310cdf0e10cSrcweir }
writeCEN(const ZipEntry & rEntry)311cdf0e10cSrcweir void ZipOutputStream::writeCEN( const ZipEntry &rEntry )
312cdf0e10cSrcweir 	throw(IOException, RuntimeException)
313cdf0e10cSrcweir {
314cdf0e10cSrcweir     if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( rEntry.sPath, sal_True ) )
315cdf0e10cSrcweir         throw IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected character is used in file name." ) ), uno::Reference< XInterface >() );
316cdf0e10cSrcweir 
317cdf0e10cSrcweir     ::rtl::OString sUTF8Name = ::rtl::OUStringToOString( rEntry.sPath, RTL_TEXTENCODING_UTF8 );
318cdf0e10cSrcweir 	sal_Int16 nNameLength 		= static_cast < sal_Int16 > ( sUTF8Name.getLength() );
319cdf0e10cSrcweir 
320cdf0e10cSrcweir 	aChucker << CENSIG;
321cdf0e10cSrcweir 	aChucker << rEntry.nVersion;
322cdf0e10cSrcweir 	aChucker << rEntry.nVersion;
323cdf0e10cSrcweir 	if (rEntry.nFlag & (1 << 4) )
324cdf0e10cSrcweir 	{
325cdf0e10cSrcweir 		// If it's an encrypted entry, we pretend its stored plain text
326cdf0e10cSrcweir 		ZipEntry *pEntry = const_cast < ZipEntry * > ( &rEntry );
327cdf0e10cSrcweir 		pEntry->nFlag &= ~(1 <<4 );
328cdf0e10cSrcweir 		aChucker << rEntry.nFlag;
329cdf0e10cSrcweir 		aChucker << static_cast < sal_Int16 > ( STORED );
330cdf0e10cSrcweir 	}
331cdf0e10cSrcweir 	else
332cdf0e10cSrcweir 	{
333cdf0e10cSrcweir 		aChucker << rEntry.nFlag;
334cdf0e10cSrcweir 		aChucker << rEntry.nMethod;
335cdf0e10cSrcweir 	}
336cdf0e10cSrcweir 	aChucker << static_cast < sal_uInt32> ( rEntry.nTime );
337cdf0e10cSrcweir 	aChucker << static_cast < sal_uInt32> ( rEntry.nCrc );
338cdf0e10cSrcweir 	aChucker << rEntry.nCompressedSize;
339cdf0e10cSrcweir 	aChucker << rEntry.nSize;
340cdf0e10cSrcweir 	aChucker << nNameLength;
341cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16> (0);
342cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16> (0);
343cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16> (0);
344cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16> (0);
345cdf0e10cSrcweir 	aChucker << static_cast < sal_Int32> (0);
346cdf0e10cSrcweir 	aChucker << rEntry.nOffset;
347cdf0e10cSrcweir 
348cdf0e10cSrcweir 	Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() );
349cdf0e10cSrcweir 	aChucker.WriteBytes( aSequence );
350cdf0e10cSrcweir }
writeEXT(const ZipEntry & rEntry)351cdf0e10cSrcweir void ZipOutputStream::writeEXT( const ZipEntry &rEntry )
352cdf0e10cSrcweir 	throw(IOException, RuntimeException)
353cdf0e10cSrcweir {
354cdf0e10cSrcweir 	aChucker << EXTSIG;
355cdf0e10cSrcweir 	aChucker << static_cast < sal_uInt32> ( rEntry.nCrc );
356cdf0e10cSrcweir 	aChucker << rEntry.nCompressedSize;
357cdf0e10cSrcweir 	aChucker << rEntry.nSize;
358cdf0e10cSrcweir }
359cdf0e10cSrcweir 
writeLOC(const ZipEntry & rEntry)360cdf0e10cSrcweir sal_Int32 ZipOutputStream::writeLOC( const ZipEntry &rEntry )
361cdf0e10cSrcweir 	throw(IOException, RuntimeException)
362cdf0e10cSrcweir {
363cdf0e10cSrcweir     if ( !::comphelper::OStorageHelper::IsValidZipEntryFileName( rEntry.sPath, sal_True ) )
364cdf0e10cSrcweir         throw IOException( ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM( "Unexpected character is used in file name." ) ), uno::Reference< XInterface >() );
365cdf0e10cSrcweir 
366cdf0e10cSrcweir     ::rtl::OString sUTF8Name = ::rtl::OUStringToOString( rEntry.sPath, RTL_TEXTENCODING_UTF8 );
367cdf0e10cSrcweir 	sal_Int16 nNameLength 		= static_cast < sal_Int16 > ( sUTF8Name.getLength() );
368cdf0e10cSrcweir 
369cdf0e10cSrcweir 	aChucker << LOCSIG;
370cdf0e10cSrcweir 	aChucker << rEntry.nVersion;
371cdf0e10cSrcweir 
372cdf0e10cSrcweir 	if (rEntry.nFlag & (1 << 4) )
373cdf0e10cSrcweir 	{
374cdf0e10cSrcweir 		// If it's an encrypted entry, we pretend its stored plain text
375cdf0e10cSrcweir 		sal_Int16 nTmpFlag = rEntry.nFlag;
376cdf0e10cSrcweir 		nTmpFlag &= ~(1 <<4 );
377cdf0e10cSrcweir 		aChucker << nTmpFlag;
378cdf0e10cSrcweir 		aChucker << static_cast < sal_Int16 > ( STORED );
379cdf0e10cSrcweir 	}
380cdf0e10cSrcweir 	else
381cdf0e10cSrcweir 	{
382cdf0e10cSrcweir 		aChucker << rEntry.nFlag;
383cdf0e10cSrcweir 		aChucker << rEntry.nMethod;
384cdf0e10cSrcweir 	}
385cdf0e10cSrcweir 
386cdf0e10cSrcweir 	aChucker << static_cast < sal_uInt32 > (rEntry.nTime);
387cdf0e10cSrcweir 	if ((rEntry.nFlag & 8) == 8 )
388cdf0e10cSrcweir 	{
389cdf0e10cSrcweir 		aChucker << static_cast < sal_Int32 > (0);
390cdf0e10cSrcweir 		aChucker << static_cast < sal_Int32 > (0);
391cdf0e10cSrcweir 		aChucker << static_cast < sal_Int32 > (0);
392cdf0e10cSrcweir 	}
393cdf0e10cSrcweir 	else
394cdf0e10cSrcweir 	{
395cdf0e10cSrcweir 		aChucker << static_cast < sal_uInt32 > (rEntry.nCrc);
396cdf0e10cSrcweir 		aChucker << rEntry.nCompressedSize;
397cdf0e10cSrcweir 		aChucker << rEntry.nSize;
398cdf0e10cSrcweir 	}
399cdf0e10cSrcweir 	aChucker << nNameLength;
400cdf0e10cSrcweir 	aChucker << static_cast < sal_Int16 > (0);
401cdf0e10cSrcweir 
402cdf0e10cSrcweir 	Sequence < sal_Int8 > aSequence( (sal_Int8*)sUTF8Name.getStr(), sUTF8Name.getLength() );
403cdf0e10cSrcweir 	aChucker.WriteBytes( aSequence );
404cdf0e10cSrcweir 
405cdf0e10cSrcweir 	return LOCHDR + nNameLength;
406cdf0e10cSrcweir }
getCurrentDosTime()407cdf0e10cSrcweir sal_uInt32 ZipOutputStream::getCurrentDosTime( )
408cdf0e10cSrcweir {
409cdf0e10cSrcweir 	oslDateTime aDateTime;
410cdf0e10cSrcweir 	TimeValue aTimeValue;
411cdf0e10cSrcweir 	osl_getSystemTime ( &aTimeValue );
412cdf0e10cSrcweir 	osl_getDateTimeFromTimeValue( &aTimeValue, &aDateTime);
413cdf0e10cSrcweir 
414cdf0e10cSrcweir 	sal_uInt32 nYear = static_cast <sal_uInt32> (aDateTime.Year);
415cdf0e10cSrcweir 
416cdf0e10cSrcweir 	if (nYear>1980)
417cdf0e10cSrcweir 		nYear-=1980;
418cdf0e10cSrcweir 	else if (nYear>80)
419cdf0e10cSrcweir 		nYear-=80;
420cdf0e10cSrcweir 	sal_uInt32 nResult = static_cast < sal_uInt32>( ( ( ( aDateTime.Day) +
421cdf0e10cSrcweir 									      ( 32 * (aDateTime.Month)) +
422cdf0e10cSrcweir 									      ( 512 * nYear ) ) << 16) |
423cdf0e10cSrcweir 									    ( ( aDateTime.Seconds/2) +
424cdf0e10cSrcweir 									  	  ( 32 * aDateTime.Minutes) +
425cdf0e10cSrcweir 										  ( 2048 * static_cast <sal_uInt32 > (aDateTime.Hours) ) ) );
426cdf0e10cSrcweir     return nResult;
427cdf0e10cSrcweir }
428cdf0e10cSrcweir /*
429cdf0e10cSrcweir 
430cdf0e10cSrcweir    This is actually never used, so I removed it, but thought that the
431cdf0e10cSrcweir    implementation details may be useful in the future...mtg 20010307
432cdf0e10cSrcweir 
433cdf0e10cSrcweir    I stopped using the time library and used the OSL version instead, but
434cdf0e10cSrcweir    it might still be useful to have this code here..
435cdf0e10cSrcweir 
436cdf0e10cSrcweir void ZipOutputStream::dosDateToTMDate ( tm &rTime, sal_uInt32 nDosDate)
437cdf0e10cSrcweir {
438cdf0e10cSrcweir 	sal_uInt32 nDate = static_cast < sal_uInt32 > (nDosDate >> 16);
439cdf0e10cSrcweir 	rTime.tm_mday = static_cast < sal_uInt32 > ( nDate & 0x1F);
440cdf0e10cSrcweir 	rTime.tm_mon  = static_cast < sal_uInt32 > ( ( ( (nDate) & 0x1E0)/0x20)-1);
441cdf0e10cSrcweir 	rTime.tm_year = static_cast < sal_uInt32 > ( ( (nDate & 0x0FE00)/0x0200)+1980);
442cdf0e10cSrcweir 
443cdf0e10cSrcweir 	rTime.tm_hour = static_cast < sal_uInt32 > ( (nDosDate & 0xF800)/0x800);
444cdf0e10cSrcweir 	rTime.tm_min  = static_cast < sal_uInt32 > ( (nDosDate & 0x7E0)/0x20);
445cdf0e10cSrcweir 	rTime.tm_sec  = static_cast < sal_uInt32 > ( 2 * (nDosDate & 0x1F) );
446cdf0e10cSrcweir }
447cdf0e10cSrcweir */
448cdf0e10cSrcweir 
449