zipfile.cpp
Go to the documentation of this file.00001
00002 #include "zipios-config.h"
00003
00004 #include "meta-iostreams.h"
00005
00006 #include "fcoll.h"
00007 #include "zipfile.h"
00008 #include "zipinputstream.h"
00009 #include "zipios_defs.h"
00010
00011 #include "backbuffer.h"
00012
00013 namespace zipios {
00014
00015
00016
00017
00018
00019 ZipFile ZipFile::openEmbeddedZipFile( const string &name ) {
00020
00021
00022 ifstream ifs( name.c_str(), ios::in | ios::binary ) ;
00023 ifs.seekg( -4, ios::end ) ;
00024 uint32 start_offset = readUint32( ifs ) ;
00025 ifs.close() ;
00026 return ZipFile( name, start_offset, 4 ) ;
00027 }
00028
00029
00030 ZipFile::ZipFile( const string &name , int s_off, int e_off
00031 )
00032 : _vs( s_off, e_off ) {
00033
00034 _filename = name ;
00035
00036 ifstream _zipfile( name.c_str(), ios::in | ios::binary ) ;
00037 init( _zipfile ) ;
00038 }
00039
00040
00041 FileCollection *ZipFile::clone() const {
00042 return new ZipFile( *this ) ;
00043 }
00044
00045
00046 ZipFile::~ZipFile() {
00047 close() ;
00048 }
00049
00050 void ZipFile::close() {
00051 _valid = false ;
00052
00053 }
00054
00055 istream *ZipFile::getInputStream( const ConstEntryPointer &entry ) {
00056 if ( ! _valid )
00057 throw InvalidStateException( "Attempt to use an invalid FileCollection" ) ;
00058 return getInputStream( entry->getName() ) ;
00059 }
00060
00061 istream *ZipFile::getInputStream( const string &entry_name,
00062 MatchPath matchpath ) {
00063 if ( ! _valid )
00064 throw InvalidStateException( "Attempt to use an invalid ZipFile" ) ;
00065
00066 ConstEntryPointer ent = getEntry( entry_name, matchpath ) ;
00067
00068 if ( ent == 0 )
00069 return 0 ;
00070 else
00071 return new ZipInputStream( _filename,
00072 static_cast< const ZipCDirEntry * >( ent.get() )->
00073 getLocalHeaderOffset() + _vs.startOffset() ) ;
00074 }
00075
00076
00077
00078
00079
00080
00081 bool ZipFile::init( istream &_zipfile ) {
00082
00083
00084 if ( ! _zipfile ) {
00085 setError ( "Error reading from file" ) ;
00086 return false ;
00087 }
00088
00089 _valid = readCentralDirectory( _zipfile ) ;
00090
00091 return _valid ;
00092 }
00093
00094
00095 bool ZipFile::readCentralDirectory ( istream &_zipfile ) {
00096
00097 if ( ! readEndOfCentralDirectory( _zipfile ) )
00098 throw FCollException( "Unable to find zip structure: End-of-central-directory" ) ;
00099
00100
00101 _vs.vseekg( _zipfile, _eocd.offset(), ios::beg ) ;
00102
00103 int entry_num = 0 ;
00104
00105 _entries.resize ( _eocd.totalCount(), 0 ) ;
00106 while ( ( entry_num < _eocd.totalCount() ) ) {
00107 ZipCDirEntry *ent = new ZipCDirEntry ;
00108 _entries[ entry_num ] = ent ;
00109 _zipfile >> *ent ;
00110 if ( ! _zipfile ) {
00111 if ( _zipfile.bad() )
00112 throw IOException( "Error reading zip file while reading zip file central directory" ) ;
00113 else if ( _zipfile.fail() )
00114 throw FCollException( "Zip file consistency problem. Failure while reading zip file central directory" ) ;
00115 else if ( _zipfile.eof() )
00116 throw IOException( "Premature end of file while reading zip file central directory" ) ;
00117 }
00118 ++entry_num ;
00119 }
00120
00121
00122
00123 int pos = _vs.vtellg( _zipfile ) ;
00124 _vs.vseekg( _zipfile, 0, ios::end ) ;
00125 int remaining = static_cast< int >( _vs.vtellg( _zipfile ) ) - pos ;
00126 if ( remaining != _eocd.eocdOffSetFromEnd() )
00127 throw FCollException( "Zip file consistency problem. Zip file data fields are inconsistent with zip file layout" ) ;
00128
00129
00130
00131 if ( ! confirmLocalHeaders( _zipfile ) )
00132 throw FCollException( "Zip file consistency problem. Zip file data fields are inconsistent with zip file layout" ) ;
00133
00134 return true ;
00135 }
00136
00137
00138 bool ZipFile::readEndOfCentralDirectory ( istream &_zipfile ) {
00139 BackBuffer bb( _zipfile, _vs ) ;
00140 int read_p = -1 ;
00141 bool found = false ;
00142 while ( ! found ) {
00143 if ( read_p < 0 )
00144 if ( ! bb.readChunk ( read_p ) ) {
00145 found = false ;
00146 break ;
00147 }
00148 if ( _eocd.read( bb, read_p ) ) {
00149 found = true ;
00150 break ;
00151 }
00152 --read_p ;
00153 }
00154
00155 return found ;
00156 }
00157
00158 bool ZipFile::confirmLocalHeaders( istream &_zipfile ) {
00159 Entries::const_iterator it ;
00160 ZipCDirEntry *ent ;
00161 int inconsistencies = 0 ;
00162 ZipLocalEntry zlh ;
00163 for ( it = _entries.begin() ; it != _entries.end() ; it++ ) {
00164 ent = static_cast< ZipCDirEntry * >( (*it).get() ) ;
00165 _vs.vseekg( _zipfile, ent->getLocalHeaderOffset(), ios::beg ) ;
00166 _zipfile >> zlh ;
00167 if ( ! _zipfile || zlh != *ent ) {
00168 inconsistencies++ ;
00169 _zipfile.clear() ;
00170 }
00171 }
00172 return ! inconsistencies ;
00173 }
00174
00175 void ZipFile::setError ( string error_str ) {
00176 _valid = false ;
00177 #ifdef _USE_EXCEPTIONS
00178 throw error_str ;
00179 #else
00180 cerr << error_str << endl ;
00181 #endif
00182 }
00183
00184
00185 }
00186
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208