bump product version to 4.1.6.2
[LibreOffice.git] / filter / source / placeware / zip.cxx
blob37de64a4316b0d9b4d816a2c26792672c5ac76d4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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>
21 #include <rtl/crc.h>
23 #include "zip.hxx"
24 #include "zipfile.hxx"
26 /** this struct describes one entry in a zip file */
27 struct ZipEntry
29 OString name; /* the name we used */
30 sal_Int32 offset; /* where the header starts */
31 sal_Int32 endOffset; /* where the file data ends */
32 sal_Int32 crc;
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 );
44 return nRC;
47 /** write a short to the PlacewareZipFile */
48 void PlacewareZipFile::writeShort( sal_Int16 s)
50 if( !isError() )
52 mnRC = putC( static_cast< unsigned char >( s & 0xff ), mrFile );
53 if( !isError() )
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 )
62 if( !isError() )
64 mnRC = putC( static_cast< unsigned char >( l & 0xff ), mrFile);
65 if( !isError() )
67 mnRC = putC( static_cast< unsigned char >( (l >> 8) & 0xff ), mrFile);
68 if( !isError() )
70 mnRC = putC( static_cast< unsigned char >( (l >> 16) & 0xff ), mrFile);
71 if( !isError() )
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)
83 char buf[2048];
84 sal_uInt64 n, nWritten;
86 e->crc = rtl_crc32( 0, 0L, 0 );
88 while( !isError() )
90 mnRC = rFile.read( buf, sizeof(buf), n );
91 if(n == 0)
92 break;
94 if( !isError() )
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 );
103 if( !isError() )
105 sal_uInt64 nPosition = 0;
106 mnRC = mrFile.getPos( nPosition );
107 if( !isError() )
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();
118 sal_Int32 i;
120 sal_uInt64 nPosition = 0;
121 mnRC = mrFile.getPos( nPosition );
122 if( !isError() )
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)
134 TimeValue aTime;
135 osl_getSystemTime( &aTime );
137 oslDateTime aDate;
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();
145 if(!isError())
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
160 if( !isError() )
162 sal_uInt64 nWritten;
163 mnRC = mrFile.write( e->name.getStr(), e->name.getLength(), nWritten ); // file name
164 OSL_ASSERT( nWritten == (sal_uInt64)e->name.getLength() );
165 if( !isError() )
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
182 writeLong(e->crc);
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
192 if( !isError() )
194 sal_uInt64 nWritten;
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()
228 if( mbOpen )
229 close();
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 );
240 if( !mbOpen )
241 return false;
243 OSL_ASSERT( !rName.isEmpty() );
245 if(rName.isEmpty())
246 return false;
248 mnRC = rFile.open( osl_File_OpenFlag_Read );
250 if( !isError() )
252 ZipEntry *e = new ZipEntry;
253 e->name = rName;
254 maEntries.push_back(e);
256 writeDummyLocalHeader(e);
257 if( !isError() )
259 copyAndCRC(e, rFile);
260 if(!isError())
262 writeLocalHeader(e);
266 rFile.close();
269 return !isError();
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 );
279 if( !mbOpen )
280 return false;
282 if( !isError() )
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++) );
293 if( !isError() )
295 sal_uInt64 nCdSize;
296 mrFile.getPos( nCdSize );
298 nCdSize -= nCdOffset;
300 if( !isError() )
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() )
310 delete (*aIter++);
313 mbOpen = false;
315 return !isError();
318 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */