Update ooo320-m1
[ooovba.git] / filter / source / placeware / zip.cxx
blob9a91b6ff7e47fa73d9c7680d814a790f763872d2
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: zip.cxx,v $
10 * $Revision: 1.7 $
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>
38 #include <rtl/crc.h>
40 #include "zip.hxx"
41 #include "zipfile.hxx"
43 using namespace rtl;
45 /** this struct describes one entry in a zip file */
46 struct ZipEntry
48 OString name; /* the name we used */
49 sal_Int32 offset; /* where the header starts */
50 sal_Int32 endOffset; /* where the file data ends */
51 sal_Int32 crc;
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 );
63 return nRC;
66 /** write a short to the ZipFile */
67 void ZipFile::writeShort( sal_Int16 s)
69 if( !isError() )
71 mnRC = putC( static_cast< unsigned char >( s & 0xff ), mrFile );
72 if( !isError() )
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 )
81 if( !isError() )
83 mnRC = putC( static_cast< unsigned char >( l & 0xff ), mrFile);
84 if( !isError() )
86 mnRC = putC( static_cast< unsigned char >( (l >> 8) & 0xff ), mrFile);
87 if( !isError() )
89 mnRC = putC( static_cast< unsigned char >( (l >> 16) & 0xff ), mrFile);
90 if( !isError() )
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)
102 char buf[2048];
103 sal_uInt64 n, nWritten;
105 e->crc = rtl_crc32( 0, 0L, 0 );
107 while( !isError() )
109 mnRC = rFile.read( buf, sizeof(buf), n );
110 if(n == 0)
111 break;
113 if( !isError() )
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 );
122 if( !isError() )
124 sal_uInt64 nPosition = 0;
125 mnRC = mrFile.getPos( nPosition );
126 if( !isError() )
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();
137 sal_Int32 i;
139 sal_uInt64 nPosition = 0;
140 mnRC = mrFile.getPos( nPosition );
141 if( !isError() )
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)
153 TimeValue aTime;
154 osl_getSystemTime( &aTime );
156 oslDateTime aDate;
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();
164 if(!isError())
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
179 if( !isError() )
181 sal_uInt64 nWritten;
182 mnRC = mrFile.write( e->name.getStr(), e->name.getLength(), nWritten ); // file name
183 OSL_ASSERT( nWritten == (sal_uInt64)e->name.getLength() );
184 if( !isError() )
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
201 writeLong(e->crc);
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
211 if( !isError() )
213 sal_uInt64 nWritten;
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 )
245 ZipFile::~ZipFile()
247 if( mbOpen )
248 close();
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 );
259 if( !mbOpen )
260 return false;
262 OSL_ASSERT( 0 != rName.getLength() );
264 if(0 == rName.getLength())
265 return false;
267 mnRC = rFile.open( osl_File_OpenFlag_Read );
269 if( !isError() )
271 ZipEntry *e = new ZipEntry;
272 e->name = rName;
273 maEntries.push_back(e);
275 writeDummyLocalHeader(e);
276 if( !isError() )
278 copyAndCRC(e, rFile);
279 if(!isError())
281 writeLocalHeader(e);
285 rFile.close();
288 return !isError();
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 );
298 if( !mbOpen )
299 return false;
301 if( !isError() )
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++) );
312 if( !isError() )
314 sal_uInt64 nCdSize;
315 mrFile.getPos( nCdSize );
317 nCdSize -= nCdOffset;
319 if( !isError() )
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() )
329 delete (*aIter++);
332 mbOpen = false;
334 return !isError();