2000-11-13 12:38:03 +00:00
/*************************************************************************
*
* $ RCSfile : ZipFile . cxx , v $
*
2001-06-14 16:36:15 +00:00
* $ Revision : 1.23 $
2000-11-13 12:38:03 +00:00
*
2001-06-14 16:36:15 +00:00
* last change : $ Author : mtg $ $ Date : 2001 - 06 - 14 17 : 36 : 15 $
2000-11-13 12:38:03 +00:00
*
* The Contents of this file are made available subject to the terms of
* either of the following licenses
*
* - GNU Lesser General Public License Version 2.1
* - Sun Industry Standards Source License Version 1.1
*
* Sun Microsystems Inc . , October , 2000
*
* GNU Lesser General Public License Version 2.1
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* Copyright 2000 by Sun Microsystems , Inc .
* 901 San Antonio Road , Palo Alto , CA 94303 , USA
*
* This library is free software ; you can redistribute it and / or
* modify it under the terms of the GNU Lesser General Public
* License version 2.1 , as published by the Free Software Foundation .
*
* This library 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 for more details .
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library ; if not , write to the Free Software
* Foundation , Inc . , 59 Temple Place , Suite 330 , Boston ,
* MA 02111 - 1307 USA
*
*
* Sun Industry Standards Source License Version 1.1
* = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
* The contents of this file are subject to the Sun Industry Standards
* Source License Version 1.1 ( the " License " ) ; You may not use this file
* except in compliance with the License . You may obtain a copy of the
* License at http : //www.openoffice.org/license.html.
*
* Software provided under this License is provided on an " AS IS " basis ,
* WITHOUT WARRANTY OF ANY KIND , EITHER EXPRESSED OR IMPLIED , INCLUDING ,
* WITHOUT LIMITATION , WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS ,
* MERCHANTABLE , FIT FOR A PARTICULAR PURPOSE , OR NON - INFRINGING .
* See the License for the specific provisions governing your rights and
* obligations concerning the Software .
*
* The Initial Developer of the Original Code is : Sun Microsystems , Inc .
*
* Copyright : 2000 by Sun Microsystems , Inc .
*
* All Rights Reserved .
*
2000-12-19 20:55:41 +00:00
* Contributor ( s ) : Martin Gallwey ( gallwey @ sun . com )
2000-11-13 12:38:03 +00:00
*
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
# ifndef _ZIP_FILE_HXX
2001-04-19 13:13:40 +00:00
# include <ZipFile.hxx>
2000-11-13 12:38:03 +00:00
# endif
2001-04-19 13:13:40 +00:00
# ifndef _ENTRY_INPUT_STREAM_HXX
# include <EntryInputStream.hxx>
# endif
# ifndef _ZIP_ENUMERATION_HXX
# include <ZipEnumeration.hxx>
# endif
# ifndef _VOS_DIAGNOSE_H_
# include <vos/diagnose.hxx>
# endif
# ifndef _COM_SUN_STAR_PACKAGES_ZIPCONSTANTS_HPP_
# include <com/sun/star/packages/ZipConstants.hpp>
# endif
# include <vector>
2000-11-13 12:38:03 +00:00
using namespace rtl ;
using namespace com : : sun : : star ;
2001-04-27 13:56:07 +00:00
using namespace com : : sun : : star : : uno ;
using namespace com : : sun : : star : : packages ;
2001-03-16 16:11:42 +00:00
using namespace com : : sun : : star : : packages : : ZipConstants ;
2000-11-13 12:38:03 +00:00
/** This class is used to read entries from a zip file
*/
2001-04-27 13:56:07 +00:00
ZipFile : : ZipFile ( Reference < io : : XInputStream > & xInput , sal_Bool bInitialise )
throw ( io : : IOException , ZipException , RuntimeException )
2000-12-04 10:30:09 +00:00
: xStream ( xInput )
, aGrabber ( xInput )
2001-03-07 18:24:15 +00:00
, aInflater ( sal_True )
2000-12-04 10:30:09 +00:00
{
if ( bInitialise )
readCEN ( ) ;
}
2001-04-27 13:56:07 +00:00
void ZipFile : : setInputStream ( Reference < io : : XInputStream > xNewStream )
2000-12-13 16:00:47 +00:00
{
xStream = xNewStream ;
aGrabber . setInputStream ( xStream ) ;
}
2000-11-29 02:21:56 +00:00
2000-11-13 12:38:03 +00:00
ZipFile : : ~ ZipFile ( )
{
2001-03-07 15:09:44 +00:00
aEntries . clear ( ) ;
2000-11-13 12:38:03 +00:00
}
2000-12-04 10:30:09 +00:00
2000-11-24 09:34:27 +00:00
void SAL_CALL ZipFile : : close ( )
2001-04-27 13:56:07 +00:00
throw ( io : : IOException , RuntimeException )
2000-11-13 12:38:03 +00:00
{
}
2001-04-27 13:56:07 +00:00
ZipEnumeration * SAL_CALL ZipFile : : entries ( )
2000-11-13 12:38:03 +00:00
{
2001-04-27 13:56:07 +00:00
return new ZipEnumeration ( aEntries ) ;
2000-11-13 12:38:03 +00:00
}
2000-12-04 10:30:09 +00:00
2000-11-24 09:34:27 +00:00
: : rtl : : OUString SAL_CALL ZipFile : : getName ( )
2001-04-27 13:56:07 +00:00
throw ( RuntimeException )
2000-11-13 12:38:03 +00:00
{
return sName ;
}
2000-12-04 10:30:09 +00:00
2000-11-24 09:34:27 +00:00
sal_Int32 SAL_CALL ZipFile : : getSize ( )
2001-04-27 13:56:07 +00:00
throw ( RuntimeException )
2000-11-13 12:38:03 +00:00
{
2000-11-29 02:21:56 +00:00
return aEntries . size ( ) ;
2000-11-13 12:38:03 +00:00
}
2001-04-27 13:56:07 +00:00
Type SAL_CALL ZipFile : : getElementType ( )
throw ( RuntimeException )
2000-11-13 12:38:03 +00:00
{
2001-04-27 13:56:07 +00:00
return : : getCppuType ( ( ZipEntry * ) 0 ) ;
2000-11-13 12:38:03 +00:00
}
2000-12-04 10:30:09 +00:00
2000-11-24 09:34:27 +00:00
sal_Bool SAL_CALL ZipFile : : hasElements ( )
2001-04-27 13:56:07 +00:00
throw ( RuntimeException )
2000-11-13 12:38:03 +00:00
{
2000-11-29 02:21:56 +00:00
return ( aEntries . size ( ) > 0 ) ;
2000-11-13 12:38:03 +00:00
}
2001-04-27 13:56:07 +00:00
Any SAL_CALL ZipFile : : getByName ( const : : rtl : : OUString & aName )
throw ( container : : NoSuchElementException , lang : : WrappedTargetException , RuntimeException )
2000-11-13 12:38:03 +00:00
{
2001-04-27 13:56:07 +00:00
Any aAny ;
2000-11-29 02:21:56 +00:00
EntryHash : : const_iterator aCI = aEntries . find ( sName ) ;
2001-04-27 13:56:07 +00:00
if ( aCI = = aEntries . end ( ) )
throw container : : NoSuchElementException ( ) ;
2000-11-29 02:21:56 +00:00
aAny < < = ( * aCI ) . second ;
2000-11-13 12:38:03 +00:00
return aAny ;
}
2000-12-04 10:30:09 +00:00
2001-04-27 13:56:07 +00:00
Sequence < : : rtl : : OUString > SAL_CALL ZipFile : : getElementNames ( )
throw ( RuntimeException )
2000-11-13 12:38:03 +00:00
{
2000-11-29 02:21:56 +00:00
sal_uInt32 i = 0 , nSize = aEntries . size ( ) ;
OUString * pNames = new OUString [ aEntries . size ( ) ] ;
for ( EntryHash : : const_iterator aIterator = aEntries . begin ( ) ; aIterator ! = aEntries . end ( ) ; aIterator + + , i + + )
pNames [ i ] = ( * aIterator ) . first ;
2001-04-27 13:56:07 +00:00
return Sequence < OUString > ( pNames , nSize ) ;
2000-11-13 12:38:03 +00:00
}
2000-12-04 10:30:09 +00:00
2000-11-24 09:34:27 +00:00
sal_Bool SAL_CALL ZipFile : : hasByName ( const : : rtl : : OUString & aName )
2001-04-27 13:56:07 +00:00
throw ( RuntimeException )
2000-11-13 12:38:03 +00:00
{
2001-04-27 13:56:07 +00:00
return aEntries . find ( aName ) ! = aEntries . end ( ) ;
2000-11-13 12:38:03 +00:00
}
2000-12-04 10:30:09 +00:00
2001-04-27 13:56:07 +00:00
Reference < io : : XInputStream > SAL_CALL ZipFile : : getInputStream ( ZipEntry & rEntry ,
const vos : : ORef < EncryptionData > & rData )
throw ( io : : IOException , ZipException , RuntimeException )
2000-11-13 12:38:03 +00:00
{
if ( rEntry . nOffset < = 0 )
readLOC ( rEntry ) ;
2001-04-30 17:19:09 +00:00
Reference < io : : XInputStream > xStreamRef = new EntryInputStream ( xStream , rEntry , rData , sal_False ) ;
2000-11-13 12:38:03 +00:00
return xStreamRef ;
}
2000-12-04 10:30:09 +00:00
2001-04-27 13:56:07 +00:00
Reference < io : : XInputStream > SAL_CALL ZipFile : : getRawStream ( ZipEntry & rEntry ,
const vos : : ORef < EncryptionData > & rData )
throw ( io : : IOException , ZipException , RuntimeException )
2000-12-13 16:00:47 +00:00
{
if ( rEntry . nOffset < = 0 )
readLOC ( rEntry ) ;
2001-04-30 17:19:09 +00:00
Reference < io : : XInputStream > xStreamRef = new EntryInputStream ( xStream , rEntry , rData , sal_True ) ;
2000-12-13 16:00:47 +00:00
return xStreamRef ;
}
2001-04-27 13:56:07 +00:00
sal_Bool ZipFile : : readLOC ( ZipEntry & rEntry )
throw ( io : : IOException , ZipException , RuntimeException )
2000-11-13 12:38:03 +00:00
{
sal_uInt32 nTestSig , nTime , nCRC , nSize , nCompressedSize ;
sal_uInt16 nVersion , nFlag , nHow , nNameLen , nExtraLen ;
sal_Int32 nPos = - rEntry . nOffset ;
aGrabber . seek ( nPos ) ;
aGrabber > > nTestSig ;
if ( nTestSig ! = LOCSIG )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Invalid LOC header (bad signature " ) ) , Reference < XInterface > ( ) ) ;
2000-11-13 12:38:03 +00:00
aGrabber > > nVersion ;
aGrabber > > nFlag ;
aGrabber > > nHow ;
aGrabber > > nTime ;
aGrabber > > nCRC ;
aGrabber > > nCompressedSize ;
aGrabber > > nSize ;
aGrabber > > nNameLen ;
aGrabber > > nExtraLen ;
2001-04-27 13:56:07 +00:00
rEntry . nOffset = static_cast < sal_Int32 > ( aGrabber . getPosition ( ) ) + nNameLen + nExtraLen ;
2000-11-13 12:38:03 +00:00
return sal_True ;
}
sal_Int32 ZipFile : : findEND ( )
2001-04-27 13:56:07 +00:00
throw ( io : : IOException , ZipException , RuntimeException )
2000-11-13 12:38:03 +00:00
{
2000-12-01 09:50:49 +00:00
sal_Int32 nLength = 0 , nPos = 0 ;
2001-04-27 13:56:07 +00:00
Sequence < sal_Int8 > aByteSeq ;
2000-12-01 09:50:49 +00:00
nLength = nPos = static_cast < sal_Int32 > ( aGrabber . getLength ( ) ) ;
2000-12-04 10:30:09 +00:00
2000-11-29 12:47:18 +00:00
if ( nLength = = 0 )
return - 1 ;
2001-04-27 13:56:07 +00:00
//throw (ZipException( OUString::createFromAscii("Trying to find Zip END signature in a zero length file!"), Reference < XInterface> () ));
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
aGrabber . seek ( nLength ) ;
while ( nLength - nPos < 0xFFFF )
{
2000-11-21 16:57:07 +00:00
sal_uInt32 nCount = 0xFFFF - ( nLength - nPos ) ;
2000-11-13 12:38:03 +00:00
if ( nCount > ENDHDR )
nCount = ENDHDR ;
nPos - = nCount ;
for ( sal_uInt16 i = 0 ; i < nCount ; i + + )
{
sal_uInt32 nTest = 0 , nFoo = ENDSIG ;
aGrabber . seek ( nPos + i ) ;
aGrabber > > nTest ;
if ( nTest = = ENDSIG )
{
2001-06-14 16:36:15 +00:00
2000-11-13 12:38:03 +00:00
sal_uInt16 nCommentLength ;
2000-12-01 09:50:49 +00:00
sal_Int32 nEndPos = nPos + i ;
2000-11-13 12:38:03 +00:00
aGrabber . seek ( nEndPos + ENDCOM ) ;
aGrabber > > nCommentLength ;
2001-06-14 16:36:15 +00:00
/*
2000-11-13 12:38:03 +00:00
if ( nEndPos + ENDHDR + nCommentLength = = nLength )
{
2001-06-14 16:36:15 +00:00
Since we don ' t actually use the comment ourselves , we ' ll just ignore it , and also skip the check
below . Neither WinZip nor InfoZip ' s unzip perform such checking and happily open files with
garbage bytes on the end , so we should do so too ! I will ' assert ' however that the file has garbage
at the end , and hope that the file hasn ' t suffered any other abuse
2000-11-13 12:38:03 +00:00
if ( nCommentLength > 0 )
{
aByteSeq . realloc ( nCommentLength + 1 ) ;
2001-04-27 13:56:07 +00:00
aGrabber . readBytes ( Sequence < sal_Int8 > ( aByteSeq . getArray ( ) , nCommentLength ) , nCommentLength ) ;
2000-11-13 12:38:03 +00:00
aByteSeq [ nCommentLength ] = ' \0 ' ;
sComment = OUString ( ( sal_Char * ) aByteSeq . getConstArray ( ) , nCommentLength + 1 , RTL_TEXTENCODING_ASCII_US ) ;
}
}
2001-06-14 16:36:15 +00:00
*/
VOS_ENSURE ( nEndPos + ENDHDR + nCommentLength = = nLength , " This Zip File is potentially corrupt - it has garbage after the END descriptor! Hoping for the best...! " ) ;
return nPos + i ;
2000-11-13 12:38:03 +00:00
}
}
}
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Zip END signature not found! " ) ) , Reference < XInterface > ( ) ) ;
2000-11-13 12:38:03 +00:00
}
sal_Int32 ZipFile : : readCEN ( )
2001-04-27 13:56:07 +00:00
throw ( io : : IOException , ZipException , RuntimeException )
2000-11-13 12:38:03 +00:00
{
2000-12-01 09:50:49 +00:00
sal_Int32 nEndPos , nLocPos ;
2000-11-29 02:21:56 +00:00
sal_Int16 nCount , nTotal ;
2000-12-01 09:50:49 +00:00
sal_Int32 nCenLen , nCenPos , nCenOff ;
2000-11-13 12:38:03 +00:00
nEndPos = findEND ( ) ;
2000-11-29 12:47:18 +00:00
if ( nEndPos = = - 1 )
return - 1 ;
2000-11-13 12:38:03 +00:00
aGrabber . seek ( nEndPos + ENDTOT ) ;
aGrabber > > nTotal ;
aGrabber > > nCenLen ;
aGrabber > > nCenOff ;
if ( nTotal < 0 | | nTotal * CENHDR > nCenLen )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " invalid END header (bad entry count) " ) ), Reference < XInterface > ()) ;
2000-11-13 12:38:03 +00:00
2000-12-04 10:30:09 +00:00
if ( nTotal > ZIP_MAXENTRIES )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " too many entries in ZIP File " ) ) , Reference < XInterface > ( ) ) ;
2000-11-13 12:38:03 +00:00
if ( nCenLen < 0 | | nCenLen > nEndPos )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Invalid END header (bad central directory size) " ) ), Reference < XInterface > ()) ;
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
nCenPos = nEndPos - nCenLen ;
if ( nCenOff < 0 | | nCenOff > nCenPos )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Invalid END header (bad central directory size) " ) ), Reference < XInterface > ()) ;
2000-11-13 12:38:03 +00:00
2000-12-04 10:30:09 +00:00
nLocPos = nCenPos - nCenOff ;
2000-11-13 12:38:03 +00:00
aGrabber . seek ( nCenPos ) ;
2000-12-04 10:30:09 +00:00
2001-04-27 13:56:07 +00:00
ZipEntry * pEntry = new ZipEntry ;
2000-11-13 12:38:03 +00:00
for ( nCount = 0 ; nCount < nTotal ; nCount + + )
{
sal_Int32 nTestSig , nCRC , nCompressedSize , nTime , nSize , nExtAttr , nOffset ;
sal_Int16 nVerMade , nVersion , nFlag , nHow , nNameLen , nExtraLen , nCommentLen ;
sal_Int16 nDisk , nIntAttr ;
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
if ( aGrabber . getPosition ( ) - nCenPos + CENHDR > nCenLen )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Invalid CEN header (bad header size check 1) " ) ), Reference < XInterface > ()) ;
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
aGrabber > > nTestSig ;
if ( nTestSig ! = CENSIG )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Invalid CEN header (bad signature) " ) ), Reference < XInterface > ()) ;
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
aGrabber > > nVerMade ;
aGrabber > > nVersion ;
if ( ( nVersion & 1 ) = = 1 )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Invalid CEN header (encrypted entry) " ) ), Reference < XInterface > ()) ;
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
aGrabber > > nFlag ;
aGrabber > > nHow ;
if ( nHow ! = STORED & & nHow ! = DEFLATED )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Invalid CEN header (bad compression method) " ) ), Reference < XInterface > ()) ;
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
aGrabber > > nTime ;
aGrabber > > nCRC ;
aGrabber > > nCompressedSize ;
aGrabber > > nSize ;
aGrabber > > nNameLen ;
aGrabber > > nExtraLen ;
aGrabber > > nCommentLen ;
aGrabber > > nDisk ;
aGrabber > > nIntAttr ;
aGrabber > > nExtAttr ;
aGrabber > > nOffset ;
if ( aGrabber . getPosition ( ) - nCenPos + nNameLen + nExtraLen + nCommentLen > nCenLen )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Invalid CEN header (bad header size check 2) " ) ), Reference < XInterface > ()) ;
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
if ( nNameLen > ZIP_MAXNAMELEN )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " name length exceeds 512 bytes " ) ) , Reference < XInterface > ( ) ) ;
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
if ( nExtraLen > ZIP_MAXEXTRA )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " extra header info exceeds 256 bytes " ) ) , Reference < XInterface > ( ) ) ;
2000-11-13 12:38:03 +00:00
pEntry - > nTime = nTime ;
pEntry - > nCrc = nCRC ;
pEntry - > nSize = nSize ;
pEntry - > nCompressedSize = nCompressedSize ;
pEntry - > nMethod = nHow ;
pEntry - > nFlag = nFlag ;
pEntry - > nVersion = nVersion ;
pEntry - > nOffset = nOffset + nLocPos ;
pEntry - > nOffset * = - 1 ;
2000-11-23 13:15:52 +00:00
/*
2000-11-13 12:38:03 +00:00
if ( nHow = = STORED )
pEntry - > nCompressedSize = 0 ;
2000-11-23 13:15:52 +00:00
*/
2001-04-27 13:56:07 +00:00
Sequence < sal_Int8 > aSequence ( nNameLen ) ;
2000-11-13 12:38:03 +00:00
aGrabber . readBytes ( aSequence , nNameLen ) ;
pEntry - > sName = OUString ( ( sal_Char * ) aSequence . getConstArray ( ) , nNameLen , RTL_TEXTENCODING_ASCII_US ) ;
aGrabber . seek ( aGrabber . getPosition ( ) + nExtraLen ) ;
if ( nCommentLen > 0 )
{
2001-04-27 13:56:07 +00:00
Sequence < sal_Int8 > aCommentSeq ( nCommentLen ) ;
2000-11-13 12:38:03 +00:00
aGrabber . readBytes ( aCommentSeq , nCommentLen ) ;
pEntry - > sComment = OUString ( ( sal_Char * ) aCommentSeq . getConstArray ( ) , nNameLen , RTL_TEXTENCODING_ASCII_US ) ;
}
2000-11-29 02:21:56 +00:00
aEntries [ pEntry - > sName ] = * pEntry ;
2000-11-13 12:38:03 +00:00
}
2000-12-13 16:00:47 +00:00
delete pEntry ;
2000-11-13 12:38:03 +00:00
if ( nCount ! = nTotal )
2001-04-27 13:56:07 +00:00
throw ZipException ( OUString ( RTL_CONSTASCII_USTRINGPARAM ( " Count != Total " ) ) , Reference < XInterface > ( ) ) ;
2000-12-04 10:30:09 +00:00
2000-11-13 12:38:03 +00:00
return nCenPos ;
}