00001 00002 #include "zipios-config.h" 00003 00004 #include "meta-iostreams.h" 00005 #include <iterator> 00006 #include <string> 00007 #include <cassert> 00008 00009 #include "zipios_common.h" 00010 #include "ziphead.h" 00011 #include "zipheadio.h" 00012 #include "zipios_defs.h" 00013 00014 #include "outputstringstream.h" 00015 00016 namespace zipios { 00017 00018 using std::ios ; 00019 00020 bool operator== ( const ZipLocalEntry &zlh, const ZipCDirEntry &ze ) { 00021 // Not all fields need to be identical. Some of the information 00022 // may be put in a data descriptor that trails the compressed 00023 // data, according to the specs (The trailing data descriptor 00024 // can contain crc_32, compress_size and uncompress_size.) 00025 00026 // Experience has shown that extra_field and extra_field_len 00027 // can differ too. 00028 00029 // cerr << "----- BEGIN -----" << endl ; 00030 // cerr << ( zlh.extract_version == ze.extract_version ) << endl ; 00031 // cerr << ( zlh.gp_bitfield == ze.gp_bitfield ) << endl ; 00032 // cerr << ( zlh.compress_method == ze.compress_method ) << endl ; 00033 // cerr << ( zlh.last_mod_ftime == ze.last_mod_ftime ) << endl ; 00034 // cerr << ( zlh.last_mod_fdate == ze.last_mod_fdate ) << endl ; 00035 00036 // cerr << ( zlh.filename_len == ze.filename_len ) << endl ; 00037 00038 // cerr << ( zlh.filename == ze.filename ) << endl ; 00039 // cerr << "----- END -----" << endl ; 00040 return ( zlh.extract_version == ze.extract_version && 00041 zlh.gp_bitfield == ze.gp_bitfield && 00042 zlh.compress_method == ze.compress_method && 00043 zlh.last_mod_ftime == ze.last_mod_ftime && 00044 zlh.last_mod_fdate == ze.last_mod_fdate && 00045 zlh.filename_len == ze.filename_len && 00046 00047 zlh.filename == ze.filename ) ; 00048 } 00049 00050 // 00051 // ZipLocalEntry methods 00052 // 00053 00054 const uint32 ZipLocalEntry::signature = 0x04034b50 ; 00055 00056 00057 00058 ZipCDirEntry &ZipCDirEntry::operator=( const class ZipCDirEntry &src ) { 00059 writer_version = src.writer_version ; 00060 extract_version = src.extract_version ; 00061 gp_bitfield = src.gp_bitfield ; 00062 compress_method = src.compress_method ; 00063 last_mod_ftime = src.last_mod_ftime ; 00064 last_mod_fdate = src.last_mod_fdate ; 00065 crc_32 = src.crc_32 ; 00066 compress_size = src.compress_size ; 00067 uncompress_size = src.uncompress_size ; 00068 filename_len = src.filename_len ; 00069 extra_field_len = src.extra_field_len ; 00070 file_comment_len = src.file_comment_len ; 00071 disk_num_start = src.disk_num_start ; 00072 intern_file_attr = src.intern_file_attr ; 00073 extern_file_attr = src.extern_file_attr ; 00074 rel_offset_loc_head = src.rel_offset_loc_head ; 00075 00076 filename = src.filename ; 00077 extra_field = src.extra_field ; 00078 file_comment = src.file_comment ; 00079 00080 return *this ; 00081 } 00082 00083 bool EndOfCentralDirectory::checkSignature ( uint32 sig ) const { 00084 return signature == sig ; 00085 } 00086 00087 void ZipLocalEntry::setDefaultExtract() { 00088 extract_version = 20 ; // version number 00089 } 00090 00091 string ZipLocalEntry::getComment() const { 00092 return "" ; // No comment in a local entry 00093 } 00094 00095 uint32 ZipLocalEntry::getCompressedSize() const { 00096 return compress_size ; 00097 } 00098 00099 uint32 ZipLocalEntry::getCrc() const { 00100 return crc_32 ; 00101 } 00102 00103 vector< unsigned char > ZipLocalEntry::getExtra() const { 00104 return extra_field ; 00105 } 00106 00107 StorageMethod ZipLocalEntry::getMethod() const { 00108 return static_cast< StorageMethod >( compress_method ) ; 00109 } 00110 00111 string ZipLocalEntry::getName() const { 00112 return filename ; 00113 } 00114 00115 string ZipLocalEntry::getFileName() const { 00116 if ( isDirectory() ) 00117 return string() ; 00118 string::size_type pos ; 00119 pos = filename.find_last_of( separator ) ; 00120 if ( pos != string::npos ) { // separator found! 00121 // isDirectory() check means pos should not be last, so pos+1 is ok 00122 return filename.substr( pos + 1 ) ; 00123 } else { 00124 return filename ; 00125 } 00126 } 00127 00128 uint32 ZipLocalEntry::getSize() const { 00129 return uncompress_size ; 00130 } 00131 00132 int ZipLocalEntry::getTime() const { 00133 return ( last_mod_fdate << 16 ) + last_mod_ftime ; 00134 // FIXME: what to do with this time date thing? (not only here?) 00135 } 00136 00137 bool ZipLocalEntry::isValid() const { 00138 return _valid ; 00139 } 00140 00141 bool ZipLocalEntry::isDirectory() const { 00142 //std::assert( filename.size() != 0 ) ; 00143 return filename[ filename.size() - 1 ] == separator ; 00144 } 00145 00146 00147 void ZipLocalEntry::setComment( const string & ) { 00148 // A local entry cannot hold a comment 00149 } 00150 00151 void ZipLocalEntry::setCompressedSize( uint32 size ) { 00152 compress_size = size ; 00153 } 00154 00155 void ZipLocalEntry::setCrc( uint32 crc ) { 00156 crc_32 = crc ; 00157 } 00158 00159 void ZipLocalEntry::setExtra( const vector< unsigned char > &extra ) { 00160 extra_field = extra ; 00161 extra_field_len = extra_field.size() ; 00162 } 00163 00164 void ZipLocalEntry::setMethod( StorageMethod method ) { 00165 compress_method = static_cast< uint16 >( method ) ; 00166 } 00167 00168 void ZipLocalEntry::setName( const string &name ) { 00169 filename = name ; 00170 filename_len = filename.size() ; 00171 } 00172 00173 void ZipLocalEntry::setSize( uint32 size ) { 00174 uncompress_size = size ; 00175 } 00176 00177 void ZipLocalEntry::setTime( int time ) { 00178 // FIXME: fix time setting here, and ind flist and elsewhere. Define the 00179 // date time semantics before mucking about - how surprising 00180 00181 // Mark Donszelmann: added these lines to make zip work for winzip 00182 last_mod_fdate = (time >> 16) & 0x0000FFFF; 00183 last_mod_ftime = time & 0x0000FFFF; 00184 } 00185 00186 string ZipLocalEntry::toString() const { 00187 OutputStringStream sout ; 00188 sout << filename << " (" << uncompress_size << " bytes, " ; 00189 sout << compress_size << " bytes compressed)" ; 00190 return sout.str() ; 00191 } 00192 00193 int ZipLocalEntry::getLocalHeaderSize() const { 00194 return 30 + filename.size() + extra_field.size() ; 00195 } 00196 00197 bool ZipLocalEntry::trailingDataDescriptor() const { 00198 // gp_bitfield bit 3 is one, if this entry uses a trailing data 00199 // descriptor to keep size, compressed size and crc-32 00200 // fields. 00201 if ( ( gp_bitfield & 4 ) == 1 ) 00202 return true ; 00203 else 00204 return false ; 00205 } 00206 00207 FileEntry *ZipLocalEntry::clone() const { 00208 return new ZipLocalEntry( *this ) ; 00209 } 00210 00211 00212 // 00213 // ZipCDirEntry methods 00214 // 00215 00216 const uint32 ZipCDirEntry::signature = 0x02014b50 ; 00217 00218 void ZipCDirEntry::setDefaultWriter() { 00219 writer_version = 0 ; 00220 #ifdef WIN32 00221 writer_version |= static_cast< uint16 >( 0 ) << 8 ; // Windows, DOS 00222 #else 00223 writer_version |= static_cast< uint16 >( 3 ) << 8 ; // Unix 00224 #endif 00225 writer_version |= 20 ; // version number 00226 } 00227 00228 string ZipCDirEntry::getComment() const { 00229 return file_comment ; 00230 } 00231 00232 uint32 ZipCDirEntry::getLocalHeaderOffset() const { 00233 return rel_offset_loc_head ; 00234 } 00235 00236 void ZipCDirEntry::setLocalHeaderOffset( uint32 offset ) { 00237 rel_offset_loc_head = offset ; 00238 } 00239 00240 00241 void ZipCDirEntry::setComment( const string &comment ) { 00242 file_comment = comment ; 00243 file_comment_len = file_comment.size() ; 00244 } 00245 00246 00247 string ZipCDirEntry::toString() const { 00248 OutputStringStream sout ; 00249 sout << filename << " (" << uncompress_size << " bytes, " ; 00250 sout << compress_size << " bytes compressed)" ; 00251 return sout.str() ; 00252 } 00253 00254 00255 int ZipCDirEntry::getCDirHeaderSize() const { 00256 return 46 + filename.size() + extra_field.size() + file_comment.size() ; 00257 } 00258 00259 00260 FileEntry *ZipCDirEntry::clone() const { 00261 return new ZipCDirEntry( *this ) ; 00262 } 00263 00264 00265 // 00266 // EndOfCentralDirectory methods 00267 // 00268 00269 const uint32 EndOfCentralDirectory::signature = 0x06054b50 ; 00270 00271 bool EndOfCentralDirectory::read( vector<unsigned char> &buf, int pos ) { 00272 if ( ( buf.size() - pos < sizeof( uint32 ) ) || 00273 ( ! checkSignature( &( buf[ pos ] ) ) ) ) 00274 return false ; 00275 00276 eocd_offset_from_end = buf.size() - pos ; 00277 pos += sizeof( uint32 ) ; 00278 disk_num = ztohs( &( buf[ pos ] ) ) ; pos += sizeof( uint16 ) ; 00279 cdir_disk_num = ztohs( &( buf[ pos ] ) ) ; pos += sizeof( uint16 ) ; 00280 cdir_entries = ztohs( &( buf[ pos ] ) ) ; pos += sizeof( uint16 ) ; 00281 cdir_tot_entries = ztohs( &( buf[ pos ] ) ) ; pos += sizeof( uint16 ) ; 00282 cdir_size = ztohl( &( buf[ pos ] ) ) ; pos += sizeof( uint32 ) ; 00283 cdir_offset = ztohl( &( buf[ pos ] ) ) ; pos += sizeof( uint32 ) ; 00284 zip_comment_len = ztohs( &( buf[ pos ] ) ) ; pos += sizeof( uint16 ) ; 00285 // cerr << "Zip comment length = " << zip_comment_len << endl ; 00286 // cerr << "Length of remaining file = " << buf.size() - pos << endl ; 00287 00288 return true ; // Dummy 00289 } 00290 00291 bool EndOfCentralDirectory::checkSignature ( unsigned char *buf ) const { 00292 // cerr << "potential header: " << ztohl( buf ) << endl ; 00293 return checkSignature( ztohl( buf ) ) ; 00294 } 00295 00296 00297 00298 } // namespace 00299 00300 00301 00307 /* 00308 Zipios++ - a small C++ library that provides easy access to .zip files. 00309 Copyright (C) 2000 Thomas Søndergaard 00310 00311 This library is free software; you can redistribute it and/or 00312 modify it under the terms of the GNU Lesser General Public 00313 License as published by the Free Software Foundation; either 00314 version 2 of the License, or (at your option) any later version. 00315 00316 This library is distributed in the hope that it will be useful, 00317 but WITHOUT ANY WARRANTY; without even the implied warranty of 00318 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00319 Lesser General Public License for more details. 00320 00321 You should have received a copy of the GNU Lesser General Public 00322 License along with this library; if not, write to the Free Software 00323 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00324 */