summaryrefslogtreecommitdiff
path: root/filter/source/placeware/zip.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'filter/source/placeware/zip.cxx')
-rw-r--r--filter/source/placeware/zip.cxx332
1 files changed, 332 insertions, 0 deletions
diff --git a/filter/source/placeware/zip.cxx b/filter/source/placeware/zip.cxx
new file mode 100644
index 000000000000..494ce2e576c4
--- /dev/null
+++ b/filter/source/placeware/zip.cxx
@@ -0,0 +1,332 @@
+/*************************************************************************
+ *
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * Copyright 2000, 2010 Oracle and/or its affiliates.
+ *
+ * OpenOffice.org - a multi-platform office productivity suite
+ *
+ * This file is part of OpenOffice.org.
+ *
+ * OpenOffice.org is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 3
+ * only, as published by the Free Software Foundation.
+ *
+ * OpenOffice.org is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License version 3 for more details
+ * (a copy is included in the LICENSE file that accompanied this code).
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * version 3 along with OpenOffice.org. If not, see
+ * <http://www.openoffice.org/license.html>
+ * for a copy of the LGPLv3 License.
+ *
+ ************************************************************************/
+
+// MARKER(update_precomp.py): autogen include statement, do not remove
+#include "precompiled_filter.hxx"
+
+/*
+#include <tools/datetime.hxx>
+*/
+#include <osl/diagnose.h>
+#include <rtl/crc.h>
+
+#include "zip.hxx"
+#include "zipfile.hxx"
+
+using namespace rtl;
+
+/** this struct describes one entry in a zip file */
+struct ZipEntry
+{
+ OString name; /* the name we used */
+ sal_Int32 offset; /* where the header starts */
+ sal_Int32 endOffset; /* where the file data ends */
+ sal_Int32 crc;
+ sal_Int32 modTime; /* dos mod time & date */
+ sal_Int32 fileLen; /* file size, in bytes */
+};
+
+/** put one byte inside this stream */
+static osl::File::RC putC( unsigned char c, osl::File& rFile )
+{
+ sal_uInt64 nBytesWritten;
+ osl::File::RC nRC = rFile.write( &c, 1, nBytesWritten );
+
+ OSL_ASSERT( nBytesWritten == 1 );
+ return nRC;
+}
+
+/** write a short to the ZipFile */
+void ZipFile::writeShort( sal_Int16 s)
+{
+ if( !isError() )
+ {
+ mnRC = putC( static_cast< unsigned char >( s & 0xff ), mrFile );
+ if( !isError() )
+ mnRC = putC( static_cast< unsigned char >( (s >> 8) & 0xff ), mrFile );
+ }
+}
+
+/** write a long to the ZipFile */
+
+void ZipFile::writeLong( sal_Int32 l )
+{
+ if( !isError() )
+ {
+ mnRC = putC( static_cast< unsigned char >( l & 0xff ), mrFile);
+ if( !isError() )
+ {
+ mnRC = putC( static_cast< unsigned char >( (l >> 8) & 0xff ), mrFile);
+ if( !isError() )
+ {
+ mnRC = putC( static_cast< unsigned char >( (l >> 16) & 0xff ), mrFile);
+ if( !isError() )
+ {
+ mnRC = putC( static_cast< unsigned char >( (l >> 24) & 0xff ), mrFile);
+ }
+ }
+ }
+ }
+}
+
+/** copy the zipentries file to the zipfile and updates the crc of that zipentry */
+void ZipFile::copyAndCRC(ZipEntry *e, osl::File& rFile)
+{
+ char buf[2048];
+ sal_uInt64 n, nWritten;
+
+ e->crc = rtl_crc32( 0, 0L, 0 );
+
+ while( !isError() )
+ {
+ mnRC = rFile.read( buf, sizeof(buf), n );
+ if(n == 0)
+ break;
+
+ if( !isError() )
+ {
+ sal_uInt32 nTemp = static_cast<sal_uInt32>(n);
+ e->crc = rtl_crc32( e->crc, (const void *) buf, nTemp );
+ mnRC = mrFile.write( buf, n, nWritten );
+ OSL_ASSERT( n == nWritten );
+ }
+ }
+
+ if( !isError() )
+ {
+ sal_uInt64 nPosition = 0;
+ mnRC = mrFile.getPos( nPosition );
+ if( !isError() )
+ {
+ e->endOffset = static_cast< sal_Int32 >( nPosition );
+ }
+ }
+}
+
+/** write a yet empty local header for a zipentry to the zipfile */
+void ZipFile::writeDummyLocalHeader(ZipEntry *e)
+{
+ sal_Int32 len = zf_lfhSIZE + e->name.getLength();
+ sal_Int32 i;
+
+ sal_uInt64 nPosition = 0;
+ mnRC = mrFile.getPos( nPosition );
+ if( !isError() )
+ {
+ e->offset = static_cast< sal_Int32 >( nPosition );
+
+ for (i = 0; (i < len) && !isError(); ++i)
+ mnRC = putC(0, mrFile);
+ }
+}
+
+/** write the local header for a zipentry to the zipfile */
+void ZipFile::writeLocalHeader(ZipEntry *e)
+{
+ TimeValue aTime;
+ osl_getSystemTime( &aTime );
+
+ oslDateTime aDate;
+ osl_getDateTimeFromTimeValue( &aTime, &aDate );
+
+ e->modTime = ((aDate.Year - 1980) << 25) | (aDate.Month << 21) | (aDate.Day << 16) |
+ (aDate.Hours << 11) | (aDate.Minutes << 5) | (aDate.Seconds >> 1);
+
+ e->fileLen = e->endOffset - e->offset - zf_lfhSIZE - e->name.getLength();
+
+ if(!isError())
+ {
+ mnRC = mrFile.setPos( Pos_Absolut, e->offset );
+
+ writeLong(zf_LFHSIGValue); // magic number
+ writeShort(zf_Vers(1, 0)); // extract version
+ writeShort(0); // flags
+ writeShort(zf_compNone); // compression method
+ writeLong(e->modTime); // file mod date & time
+ writeLong(e->crc); // file crc
+ writeLong(e->fileLen); // compressed size
+ writeLong(e->fileLen); // uncompressed size
+ writeShort((sal_Int16) e->name.getLength()); // name length
+ writeShort(0); // extra length field
+
+ if( !isError() )
+ {
+ sal_uInt64 nWritten;
+ mnRC = mrFile.write( e->name.getStr(), e->name.getLength(), nWritten ); // file name
+ OSL_ASSERT( nWritten == (sal_uInt64)e->name.getLength() );
+ if( !isError() )
+ {
+ mnRC = mrFile.setPos( Pos_Absolut, e->endOffset );
+ }
+ }
+ }
+}
+
+/* write a zipentry in the central dir to the zipfile */
+void ZipFile::writeCentralDir(ZipEntry *e)
+{
+ writeLong(zf_CDHSIGValue); // magic number
+ writeShort(zf_Vers(1, 0)); // version made by
+ writeShort(zf_Vers(1, 0)); // vers to extract
+ writeShort(0); // flags
+ writeShort(zf_compNone); // compression method
+ writeLong(e->modTime); // file mod time & date
+ writeLong(e->crc);
+ writeLong(e->fileLen); // compressed file size
+ writeLong(e->fileLen); // uncompressed file size
+ writeShort((sal_Int16) e->name.getLength()); // name length
+ writeShort(0); // extra field length
+ writeShort(0); // file comment length
+ writeShort(0); // disk number start
+ writeShort(0); // internal file attributes
+ writeLong(0); // external file attributes
+ writeLong(e->offset); // offset w.r.t disk
+ if( !isError() )
+ {
+ sal_uInt64 nWritten;
+ mrFile.write( e->name.getStr(), e->name.getLength(), nWritten ); // file name
+ OSL_ASSERT( nWritten == (sal_uInt64)e->name.getLength() );
+ }
+}
+
+/* write the end of the central dir to the zipfile */
+void ZipFile::writeEndCentralDir(sal_Int32 nCdOffset, sal_Int32 nCdSize)
+{
+ writeLong(zf_ECDSIGValue); // magic number
+ writeShort(0); // disk num
+ writeShort(0); // disk with central dir
+ writeShort( static_cast< sal_Int16 >( maEntries.size() ) ); // number of file entries
+ writeShort( static_cast< sal_Int16 >( maEntries.size() ) ); // number of file entries
+ writeLong(nCdSize); // central dir size
+ writeLong(nCdOffset);
+ writeShort(0); // comment len
+}
+
+
+/****************************************************************
+ * The exported functions
+ ****************************************************************/
+
+/* Create a zip file for writing, return a handle for it.
+ * RETURNS: A new zip-file output object, or NULL if it failed, in
+ * which case *errMsgBuffer will contain an error message string. */
+ZipFile::ZipFile(osl::File& rFile )
+: mrFile( rFile ), mbOpen( true ), mnRC( osl::File::E_None )
+{
+}
+
+ZipFile::~ZipFile()
+{
+ if( mbOpen )
+ close();
+}
+
+/* Add a file to this zip with the given name.
+ * RETURNS: true if successful, else false. If false, the caller should
+ * call zip_Close() and delete the bum zip file.
+*/
+bool ZipFile::addFile( osl::File& rFile, const OString& rName )
+{
+ OSL_ASSERT( mbOpen );
+
+ if( !mbOpen )
+ return false;
+
+ OSL_ASSERT( 0 != rName.getLength() );
+
+ if(0 == rName.getLength())
+ return false;
+
+ mnRC = rFile.open( osl_File_OpenFlag_Read );
+
+ if( !isError() )
+ {
+ ZipEntry *e = new ZipEntry;
+ e->name = rName;
+ maEntries.push_back(e);
+
+ writeDummyLocalHeader(e);
+ if( !isError() )
+ {
+ copyAndCRC(e, rFile);
+ if(!isError())
+ {
+ writeLocalHeader(e);
+ }
+ }
+
+ rFile.close();
+ }
+
+ return !isError();
+}
+
+/* Finish up the zip file, close it, and deallocate the zip file object.
+ * RETURNS: true if successful, else false.
+*/
+bool ZipFile::close()
+{
+ OSL_ASSERT( mbOpen );
+
+ if( !mbOpen )
+ return false;
+
+ if( !isError() )
+ {
+ sal_uInt64 nCdOffset;
+ mrFile.getPos( nCdOffset );
+
+ std::vector< ZipEntry* >::iterator aIter( maEntries.begin() );
+ while((aIter != maEntries.end()) && !isError())
+ {
+ writeCentralDir( (*aIter++) );
+ }
+
+ if( !isError() )
+ {
+ sal_uInt64 nCdSize;
+ mrFile.getPos( nCdSize );
+
+ nCdSize -= nCdOffset;
+
+ if( !isError() )
+ {
+ writeEndCentralDir(static_cast<sal_Int32>(nCdOffset), static_cast<sal_Int32>(nCdSize));
+ }
+ }
+ }
+
+ std::vector< ZipEntry* >::iterator aIter( maEntries.begin() );
+ while( aIter != maEntries.end() )
+ {
+ delete (*aIter++);
+ }
+
+ mbOpen = false;
+
+ return !isError();
+}