Zipios++
|
00001 00002 #include <time.h> 00003 00004 #include "zipios++/zipios-config.h" 00005 00006 #include <algorithm> 00007 #include "zipios++/meta-iostreams.h" 00008 00009 #include <zlib.h> 00010 00011 #include "zipios++/zipoutputstreambuf.h" 00012 00013 namespace zipios { 00014 00015 using std::ios ; 00016 using std::cerr ; 00017 using std::endl ; 00018 //using std::min ; 00019 00020 ZipOutputStreambuf::ZipOutputStreambuf( streambuf *outbuf, bool del_outbuf ) 00021 : DeflateOutputStreambuf( outbuf, false, del_outbuf ), 00022 _open_entry( false ), 00023 _open ( true ), 00024 _method ( DEFLATED ), 00025 _level ( 6 ) 00026 { 00027 } 00028 00029 00030 void ZipOutputStreambuf::closeEntry() { 00031 if ( ! _open_entry ) 00032 return ; 00033 00034 closeStream() ; 00035 00036 updateEntryHeaderInfo() ; 00037 setEntryClosedState( ) ; 00038 } 00039 00040 00041 void ZipOutputStreambuf::close() { 00042 finish() ; 00043 } 00044 00045 00046 void ZipOutputStreambuf::finish() { 00047 if( ! _open ) 00048 return ; 00049 closeEntry() ; 00050 ostream os( _outbuf ) ; 00051 writeCentralDirectory( _entries, EndOfCentralDirectory( _zip_comment), os ) ; 00052 _open = false ; 00053 } 00054 00055 00056 ZipOutputStreambuf::~ZipOutputStreambuf() { 00057 finish() ; 00058 } 00059 00060 00061 void ZipOutputStreambuf::putNextEntry( const ZipCDirEntry &entry ) { 00062 if ( _open_entry ) 00063 closeEntry() ; 00064 00065 if ( ! init( _level ) ) 00066 cerr << "ZipOutputStreambuf::putNextEntry(): init() failed!\n" ; 00067 00068 _entries.push_back( entry ) ; 00069 ZipCDirEntry &ent = _entries.back() ; 00070 00071 ostream os( _outbuf ) ; 00072 00073 // Update entry header info 00074 ent.setLocalHeaderOffset( os.tellp() ) ; 00075 ent.setMethod( _method ) ; 00076 00077 os << static_cast< ZipLocalEntry >( ent ) ; 00078 00079 _open_entry = true ; 00080 } 00081 00082 00083 void ZipOutputStreambuf::setComment( const string &comment ) { 00084 _zip_comment = comment ; 00085 } 00086 00087 00088 void ZipOutputStreambuf::setLevel( int level ) { 00089 _level = level ; 00090 } 00091 00092 00093 void ZipOutputStreambuf::setMethod( StorageMethod method ) { 00094 _method = method ; 00095 if( method == STORED ) 00096 setLevel( NO_COMPRESSION ) ; 00097 else if ( method == DEFLATED ) { 00098 if( _level == NO_COMPRESSION ) 00099 setLevel( DEFAULT_COMPRESSION ) ; 00100 } else 00101 throw FCollException( "Specified compression method not supported" ) ; 00102 } 00103 00104 // 00105 // Protected and private methods 00106 // 00107 00108 int ZipOutputStreambuf::overflow( int c ) { 00109 return DeflateOutputStreambuf::overflow( c ) ; 00110 // // FIXME: implement 00111 00112 // cout << "ZipOutputStreambuf::overflow() not implemented yet!\n" ; 00113 // return EOF ; 00114 } 00115 00116 00117 00118 int ZipOutputStreambuf::sync() { 00119 return DeflateOutputStreambuf::sync() ; 00120 // // FIXME: implement 00121 // cout << "ZipOutputStreambuf::sync() not implemented yet!\n" ; 00122 // return EOF ; 00123 } 00124 00125 00126 00127 void ZipOutputStreambuf::setEntryClosedState() { 00128 _open_entry = false ; 00129 // FIXME: update put pointers to trigger overflow on write. overflow 00130 // should then return EOF while _open_entry is false. 00131 } 00132 00133 00134 void ZipOutputStreambuf::updateEntryHeaderInfo() { 00135 if ( ! _open_entry ) 00136 return ; 00137 00138 ostream os( _outbuf ) ; 00139 int curr_pos = os.tellp() ; 00140 00141 // update fields in _entries.back() 00142 ZipCDirEntry &entry = _entries.back() ; 00143 entry.setSize( getCount() ) ; 00144 entry.setCrc( getCrc32() ) ; 00145 entry.setCompressedSize( curr_pos - entry.getLocalHeaderOffset() 00146 - entry.getLocalHeaderSize() ) ; 00147 00148 // Mark Donszelmann: added current date and time 00149 time_t ltime; 00150 time( <ime ); 00151 struct tm *now; 00152 now = localtime( <ime ); 00153 int dosTime = (now->tm_year - 80) << 25 | (now->tm_mon + 1) << 21 | now->tm_mday << 16 | 00154 now->tm_hour << 11 | now->tm_min << 5 | now->tm_sec >> 1; 00155 entry.setTime(dosTime); 00156 00157 // write ZipLocalEntry header to header position 00158 os.seekp( entry.getLocalHeaderOffset() ) ; 00159 os << static_cast< ZipLocalEntry >( entry ) ; 00160 os.seekp( curr_pos ) ; 00161 } 00162 00163 00164 void ZipOutputStreambuf::writeCentralDirectory( const vector< ZipCDirEntry > &entries, 00165 EndOfCentralDirectory eocd, 00166 ostream &os ) { 00167 int cdir_start = os.tellp() ; 00168 std::vector< ZipCDirEntry >::const_iterator it ; 00169 int cdir_size = 0 ; 00170 00171 for ( it = entries.begin() ; it != entries.end() ; ++it ) { 00172 os << *it ; 00173 cdir_size += it->getCDirHeaderSize() ; 00174 } 00175 eocd.setOffset( cdir_start ) ; 00176 eocd.setCDirSize( cdir_size ) ; 00177 eocd.setTotalCount( entries.size() ) ; 00178 os << eocd ; 00179 } 00180 00181 } // namespace 00182 00187 /* 00188 Zipios++ - a small C++ library that provides easy access to .zip files. 00189 Copyright (C) 2000 Thomas Søndergaard 00190 00191 This library is free software; you can redistribute it and/or 00192 modify it under the terms of the GNU Lesser General Public 00193 License as published by the Free Software Foundation; either 00194 version 2 of the License, or (at your option) any later version. 00195 00196 This library is distributed in the hope that it will be useful, 00197 but WITHOUT ANY WARRANTY; without even the implied warranty of 00198 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00199 Lesser General Public License for more details. 00200 00201 You should have received a copy of the GNU Lesser General Public 00202 License along with this library; if not, write to the Free Software 00203 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00204 */