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: zip.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_filter.hxx"
35 #include <tools/datetime.hxx>
37 #include <osl/diagnose.h>
41 #include "zipfile.hxx"
45 /** this struct describes one entry in a zip file */
48 OString name
; /* the name we used */
49 sal_Int32 offset
; /* where the header starts */
50 sal_Int32 endOffset
; /* where the file data ends */
52 sal_Int32 modTime
; /* dos mod time & date */
53 sal_Int32 fileLen
; /* file size, in bytes */
56 /** put one byte inside this stream */
57 static osl::File::RC
putC( unsigned char c
, osl::File
& rFile
)
59 sal_uInt64 nBytesWritten
;
60 osl::File::RC nRC
= rFile
.write( &c
, 1, nBytesWritten
);
62 OSL_ASSERT( nBytesWritten
== 1 );
66 /** write a short to the ZipFile */
67 void ZipFile::writeShort( sal_Int16 s
)
71 mnRC
= putC( static_cast< unsigned char >( s
& 0xff ), mrFile
);
73 mnRC
= putC( static_cast< unsigned char >( (s
>> 8) & 0xff ), mrFile
);
77 /** write a long to the ZipFile */
79 void ZipFile::writeLong( sal_Int32 l
)
83 mnRC
= putC( static_cast< unsigned char >( l
& 0xff ), mrFile
);
86 mnRC
= putC( static_cast< unsigned char >( (l
>> 8) & 0xff ), mrFile
);
89 mnRC
= putC( static_cast< unsigned char >( (l
>> 16) & 0xff ), mrFile
);
92 mnRC
= putC( static_cast< unsigned char >( (l
>> 24) & 0xff ), mrFile
);
99 /** copy the zipentries file to the zipfile and updates the crc of that zipentry */
100 void ZipFile::copyAndCRC(ZipEntry
*e
, osl::File
& rFile
)
103 sal_uInt64 n
, nWritten
;
105 e
->crc
= rtl_crc32( 0, 0L, 0 );
109 mnRC
= rFile
.read( buf
, sizeof(buf
), n
);
115 sal_uInt32 nTemp
= static_cast<sal_uInt32
>(n
);
116 e
->crc
= rtl_crc32( e
->crc
, (const void *) buf
, nTemp
);
117 mnRC
= mrFile
.write( buf
, n
, nWritten
);
118 OSL_ASSERT( n
== nWritten
);
124 sal_uInt64 nPosition
= 0;
125 mnRC
= mrFile
.getPos( nPosition
);
128 e
->endOffset
= static_cast< sal_Int32
>( nPosition
);
133 /** write a yet empty local header for a zipentry to the zipfile */
134 void ZipFile::writeDummyLocalHeader(ZipEntry
*e
)
136 sal_Int32 len
= zf_lfhSIZE
+ e
->name
.getLength();
139 sal_uInt64 nPosition
= 0;
140 mnRC
= mrFile
.getPos( nPosition
);
143 e
->offset
= static_cast< sal_Int32
>( nPosition
);
145 for (i
= 0; (i
< len
) && !isError(); ++i
)
146 mnRC
= putC(0, mrFile
);
150 /** write the local header for a zipentry to the zipfile */
151 void ZipFile::writeLocalHeader(ZipEntry
*e
)
154 osl_getSystemTime( &aTime
);
157 osl_getDateTimeFromTimeValue( &aTime
, &aDate
);
159 e
->modTime
= ((aDate
.Year
- 1980) << 25) | (aDate
.Month
<< 21) | (aDate
.Day
<< 16) |
160 (aDate
.Hours
<< 11) | (aDate
.Minutes
<< 5) | (aDate
.Seconds
>> 1);
162 e
->fileLen
= e
->endOffset
- e
->offset
- zf_lfhSIZE
- e
->name
.getLength();
166 mnRC
= mrFile
.setPos( Pos_Absolut
, e
->offset
);
168 writeLong(zf_LFHSIGValue
); // magic number
169 writeShort(zf_Vers(1, 0)); // extract version
170 writeShort(0); // flags
171 writeShort(zf_compNone
); // compression method
172 writeLong(e
->modTime
); // file mod date & time
173 writeLong(e
->crc
); // file crc
174 writeLong(e
->fileLen
); // compressed size
175 writeLong(e
->fileLen
); // uncompressed size
176 writeShort((sal_Int16
) e
->name
.getLength()); // name length
177 writeShort(0); // extra length field
182 mnRC
= mrFile
.write( e
->name
.getStr(), e
->name
.getLength(), nWritten
); // file name
183 OSL_ASSERT( nWritten
== (sal_uInt64
)e
->name
.getLength() );
186 mnRC
= mrFile
.setPos( Pos_Absolut
, e
->endOffset
);
192 /* write a zipentry in the central dir to the zipfile */
193 void ZipFile::writeCentralDir(ZipEntry
*e
)
195 writeLong(zf_CDHSIGValue
); // magic number
196 writeShort(zf_Vers(1, 0)); // version made by
197 writeShort(zf_Vers(1, 0)); // vers to extract
198 writeShort(0); // flags
199 writeShort(zf_compNone
); // compression method
200 writeLong(e
->modTime
); // file mod time & date
202 writeLong(e
->fileLen
); // compressed file size
203 writeLong(e
->fileLen
); // uncompressed file size
204 writeShort((sal_Int16
) e
->name
.getLength()); // name length
205 writeShort(0); // extra field length
206 writeShort(0); // file comment length
207 writeShort(0); // disk number start
208 writeShort(0); // internal file attributes
209 writeLong(0); // external file attributes
210 writeLong(e
->offset
); // offset w.r.t disk
214 mrFile
.write( e
->name
.getStr(), e
->name
.getLength(), nWritten
); // file name
215 OSL_ASSERT( nWritten
== (sal_uInt64
)e
->name
.getLength() );
219 /* write the end of the central dir to the zipfile */
220 void ZipFile::writeEndCentralDir(sal_Int32 nCdOffset
, sal_Int32 nCdSize
)
222 writeLong(zf_ECDSIGValue
); // magic number
223 writeShort(0); // disk num
224 writeShort(0); // disk with central dir
225 writeShort( static_cast< sal_Int16
>( maEntries
.size() ) ); // number of file entries
226 writeShort( static_cast< sal_Int16
>( maEntries
.size() ) ); // number of file entries
227 writeLong(nCdSize
); // central dir size
228 writeLong(nCdOffset
);
229 writeShort(0); // comment len
233 /****************************************************************
234 * The exported functions
235 ****************************************************************/
237 /* Create a zip file for writing, return a handle for it.
238 * RETURNS: A new zip-file output object, or NULL if it failed, in
239 * which case *errMsgBuffer will contain an error message string. */
240 ZipFile::ZipFile(osl::File
& rFile
)
241 : mrFile( rFile
), mbOpen( true ), mnRC( osl::File::E_None
)
251 /* Add a file to this zip with the given name.
252 * RETURNS: true if successful, else false. If false, the caller should
253 * call zip_Close() and delete the bum zip file.
255 bool ZipFile::addFile( osl::File
& rFile
, const OString
& rName
)
257 OSL_ASSERT( mbOpen
);
262 OSL_ASSERT( 0 != rName
.getLength() );
264 if(0 == rName
.getLength())
267 mnRC
= rFile
.open( osl_File_OpenFlag_Read
);
271 ZipEntry
*e
= new ZipEntry
;
273 maEntries
.push_back(e
);
275 writeDummyLocalHeader(e
);
278 copyAndCRC(e
, rFile
);
291 /* Finish up the zip file, close it, and deallocate the zip file object.
292 * RETURNS: true if successful, else false.
294 bool ZipFile::close()
296 OSL_ASSERT( mbOpen
);
303 sal_uInt64 nCdOffset
;
304 mrFile
.getPos( nCdOffset
);
306 std::vector
< ZipEntry
* >::iterator
aIter( maEntries
.begin() );
307 while((aIter
!= maEntries
.end()) && !isError())
309 writeCentralDir( (*aIter
++) );
315 mrFile
.getPos( nCdSize
);
317 nCdSize
-= nCdOffset
;
321 writeEndCentralDir(static_cast<sal_Int32
>(nCdOffset
), static_cast<sal_Int32
>(nCdSize
));
326 std::vector
< ZipEntry
* >::iterator
aIter( maEntries
.begin() );
327 while( aIter
!= maEntries
.end() )