1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include <osl/diagnose.h>
24 #include "zipfile.hxx"
26 /** this struct describes one entry in a zip file */
29 OString name
; /* the name we used */
30 sal_Int32 offset
; /* where the header starts */
31 sal_Int32 endOffset
; /* where the file data ends */
33 sal_Int32 modTime
; /* dos mod time & date */
34 sal_Int32 fileLen
; /* file size, in bytes */
37 /** put one byte inside this stream */
38 static osl::File::RC
putC( unsigned char c
, osl::File
& rFile
)
40 sal_uInt64 nBytesWritten
;
41 osl::File::RC nRC
= rFile
.write( &c
, 1, nBytesWritten
);
43 OSL_ASSERT( nBytesWritten
== 1 );
47 /** write a short to the PlacewareZipFile */
48 void PlacewareZipFile::writeShort( sal_Int16 s
)
52 mnRC
= putC( static_cast< unsigned char >( s
& 0xff ), mrFile
);
54 mnRC
= putC( static_cast< unsigned char >( (s
>> 8) & 0xff ), mrFile
);
58 /** write a long to the PlacewareZipFile */
60 void PlacewareZipFile::writeLong( sal_Int32 l
)
64 mnRC
= putC( static_cast< unsigned char >( l
& 0xff ), mrFile
);
67 mnRC
= putC( static_cast< unsigned char >( (l
>> 8) & 0xff ), mrFile
);
70 mnRC
= putC( static_cast< unsigned char >( (l
>> 16) & 0xff ), mrFile
);
73 mnRC
= putC( static_cast< unsigned char >( (l
>> 24) & 0xff ), mrFile
);
80 /** copy the zipentries file to the zipfile and updates the crc of that zipentry */
81 void PlacewareZipFile::copyAndCRC(ZipEntry
*e
, osl::File
& rFile
)
84 sal_uInt64 n
, nWritten
;
86 e
->crc
= rtl_crc32( 0, 0L, 0 );
90 mnRC
= rFile
.read( buf
, sizeof(buf
), n
);
96 sal_uInt32 nTemp
= static_cast<sal_uInt32
>(n
);
97 e
->crc
= rtl_crc32( e
->crc
, (const void *) buf
, nTemp
);
98 mnRC
= mrFile
.write( buf
, n
, nWritten
);
99 OSL_ASSERT( n
== nWritten
);
105 sal_uInt64 nPosition
= 0;
106 mnRC
= mrFile
.getPos( nPosition
);
109 e
->endOffset
= static_cast< sal_Int32
>( nPosition
);
114 /** write a yet empty local header for a zipentry to the zipfile */
115 void PlacewareZipFile::writeDummyLocalHeader(ZipEntry
*e
)
117 sal_Int32 len
= zf_lfhSIZE
+ e
->name
.getLength();
120 sal_uInt64 nPosition
= 0;
121 mnRC
= mrFile
.getPos( nPosition
);
124 e
->offset
= static_cast< sal_Int32
>( nPosition
);
126 for (i
= 0; (i
< len
) && !isError(); ++i
)
127 mnRC
= putC(0, mrFile
);
131 /** write the local header for a zipentry to the zipfile */
132 void PlacewareZipFile::writeLocalHeader(ZipEntry
*e
)
135 osl_getSystemTime( &aTime
);
138 osl_getDateTimeFromTimeValue( &aTime
, &aDate
);
140 e
->modTime
= ((aDate
.Year
- 1980) << 25) | (aDate
.Month
<< 21) | (aDate
.Day
<< 16) |
141 (aDate
.Hours
<< 11) | (aDate
.Minutes
<< 5) | (aDate
.Seconds
>> 1);
143 e
->fileLen
= e
->endOffset
- e
->offset
- zf_lfhSIZE
- e
->name
.getLength();
147 mnRC
= mrFile
.setPos( osl_Pos_Absolut
, e
->offset
);
149 writeLong(zf_LFHSIGValue
); // magic number
150 writeShort(zf_Vers(1, 0)); // extract version
151 writeShort(0); // flags
152 writeShort(zf_compNone
); // compression method
153 writeLong(e
->modTime
); // file mod date & time
154 writeLong(e
->crc
); // file crc
155 writeLong(e
->fileLen
); // compressed size
156 writeLong(e
->fileLen
); // uncompressed size
157 writeShort((sal_Int16
) e
->name
.getLength()); // name length
158 writeShort(0); // extra length field
163 mnRC
= mrFile
.write( e
->name
.getStr(), e
->name
.getLength(), nWritten
); // file name
164 OSL_ASSERT( nWritten
== (sal_uInt64
)e
->name
.getLength() );
167 mnRC
= mrFile
.setPos( osl_Pos_Absolut
, e
->endOffset
);
173 /* write a zipentry in the central dir to the zipfile */
174 void PlacewareZipFile::writeCentralDir(ZipEntry
*e
)
176 writeLong(zf_CDHSIGValue
); // magic number
177 writeShort(zf_Vers(1, 0)); // version made by
178 writeShort(zf_Vers(1, 0)); // vers to extract
179 writeShort(0); // flags
180 writeShort(zf_compNone
); // compression method
181 writeLong(e
->modTime
); // file mod time & date
183 writeLong(e
->fileLen
); // compressed file size
184 writeLong(e
->fileLen
); // uncompressed file size
185 writeShort((sal_Int16
) e
->name
.getLength()); // name length
186 writeShort(0); // extra field length
187 writeShort(0); // file comment length
188 writeShort(0); // disk number start
189 writeShort(0); // internal file attributes
190 writeLong(0); // external file attributes
191 writeLong(e
->offset
); // offset w.r.t disk
195 mrFile
.write( e
->name
.getStr(), e
->name
.getLength(), nWritten
); // file name
196 OSL_ASSERT( nWritten
== (sal_uInt64
)e
->name
.getLength() );
200 /* write the end of the central dir to the zipfile */
201 void PlacewareZipFile::writeEndCentralDir(sal_Int32 nCdOffset
, sal_Int32 nCdSize
)
203 writeLong(zf_ECDSIGValue
); // magic number
204 writeShort(0); // disk num
205 writeShort(0); // disk with central dir
206 writeShort( static_cast< sal_Int16
>( maEntries
.size() ) ); // number of file entries
207 writeShort( static_cast< sal_Int16
>( maEntries
.size() ) ); // number of file entries
208 writeLong(nCdSize
); // central dir size
209 writeLong(nCdOffset
);
210 writeShort(0); // comment len
214 /****************************************************************
215 * The exported functions
216 ****************************************************************/
218 /* Create a zip file for writing, return a handle for it.
219 * RETURNS: A new zip-file output object, or NULL if it failed, in
220 * which case *errMsgBuffer will contain an error message string. */
221 PlacewareZipFile::PlacewareZipFile(osl::File
& rFile
)
222 : mrFile( rFile
), mbOpen( true ), mnRC( osl::File::E_None
)
226 PlacewareZipFile::~PlacewareZipFile()
232 /* Add a file to this zip with the given name.
233 * RETURNS: true if successful, else false. If false, the caller should
234 * call zip_Close() and delete the bum zip file.
236 bool PlacewareZipFile::addFile( osl::File
& rFile
, const OString
& rName
)
238 OSL_ASSERT( mbOpen
);
243 OSL_ASSERT( !rName
.isEmpty() );
248 mnRC
= rFile
.open( osl_File_OpenFlag_Read
);
252 ZipEntry
*e
= new ZipEntry
;
254 maEntries
.push_back(e
);
256 writeDummyLocalHeader(e
);
259 copyAndCRC(e
, rFile
);
272 /* Finish up the zip file, close it, and deallocate the zip file object.
273 * RETURNS: true if successful, else false.
275 bool PlacewareZipFile::close()
277 OSL_ASSERT( mbOpen
);
284 sal_uInt64 nCdOffset
;
285 mrFile
.getPos( nCdOffset
);
287 std::vector
< ZipEntry
* >::iterator
aIter( maEntries
.begin() );
288 while((aIter
!= maEntries
.end()) && !isError())
290 writeCentralDir( (*aIter
++) );
296 mrFile
.getPos( nCdSize
);
298 nCdSize
-= nCdOffset
;
302 writeEndCentralDir(static_cast<sal_Int32
>(nCdOffset
), static_cast<sal_Int32
>(nCdSize
));
307 std::vector
< ZipEntry
* >::iterator
aIter( maEntries
.begin() );
308 while( aIter
!= maEntries
.end() )
318 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */