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