206 lines
5.1 KiB
C++
206 lines
5.1 KiB
C++
|
|
#include "zipios-config.h"
|
|
|
|
#include <algorithm>
|
|
#include <vector>
|
|
#include <time.h>
|
|
#include "meta-iostreams.h"
|
|
|
|
#include <zlib.h>
|
|
|
|
#include "zipoutputstreambuf.h"
|
|
|
|
namespace zipios {
|
|
|
|
using std::ios ;
|
|
using std::cerr ;
|
|
using std::endl ;
|
|
using std::min ;
|
|
using std::vector ;
|
|
|
|
ZipOutputStreambuf::ZipOutputStreambuf( streambuf *outbuf, bool del_outbuf )
|
|
: DeflateOutputStreambuf( outbuf, false, del_outbuf ),
|
|
_open_entry( false ),
|
|
_open ( true ),
|
|
_method ( DEFLATED ),
|
|
_level ( 6 )
|
|
{
|
|
}
|
|
|
|
|
|
void ZipOutputStreambuf::closeEntry() {
|
|
if ( ! _open_entry )
|
|
return ;
|
|
|
|
closeStream() ;
|
|
|
|
updateEntryHeaderInfo() ;
|
|
setEntryClosedState( ) ;
|
|
}
|
|
|
|
|
|
void ZipOutputStreambuf::close() {
|
|
finish() ;
|
|
}
|
|
|
|
|
|
void ZipOutputStreambuf::finish() {
|
|
if( ! _open )
|
|
return ;
|
|
closeEntry() ;
|
|
ostream os( _outbuf ) ;
|
|
writeCentralDirectory( _entries, EndOfCentralDirectory( _zip_comment), os ) ;
|
|
_open = false ;
|
|
}
|
|
|
|
|
|
ZipOutputStreambuf::~ZipOutputStreambuf() {
|
|
finish() ;
|
|
}
|
|
|
|
|
|
void ZipOutputStreambuf::putNextEntry( const ZipCDirEntry &entry ) {
|
|
if ( _open_entry )
|
|
closeEntry() ;
|
|
|
|
if ( ! init( _level ) )
|
|
cerr << "ZipOutputStreambuf::putNextEntry(): init() failed!\n" ;
|
|
|
|
_entries.push_back( entry ) ;
|
|
ZipCDirEntry &ent = _entries.back() ;
|
|
|
|
ostream os( _outbuf ) ;
|
|
|
|
// Update entry header info
|
|
ent.setLocalHeaderOffset( os.tellp() ) ;
|
|
ent.setMethod( _method ) ;
|
|
|
|
os << static_cast< ZipLocalEntry >( ent ) ;
|
|
|
|
_open_entry = true ;
|
|
}
|
|
|
|
|
|
void ZipOutputStreambuf::setComment( const string &comment ) {
|
|
_zip_comment = comment ;
|
|
}
|
|
|
|
|
|
void ZipOutputStreambuf::setLevel( int level ) {
|
|
_level = level ;
|
|
}
|
|
|
|
|
|
void ZipOutputStreambuf::setMethod( StorageMethod method ) {
|
|
_method = method ;
|
|
if( method == STORED )
|
|
setLevel( NO_COMPRESSION ) ;
|
|
else if ( method == DEFLATED ) {
|
|
if( _level == NO_COMPRESSION )
|
|
setLevel( DEFAULT_COMPRESSION ) ;
|
|
} else
|
|
throw FCollException( "Specified compression method not supported" ) ;
|
|
}
|
|
|
|
//
|
|
// Protected and private methods
|
|
//
|
|
|
|
int ZipOutputStreambuf::overflow( int c ) {
|
|
return DeflateOutputStreambuf::overflow( c ) ;
|
|
// // FIXME: implement
|
|
|
|
// cout << "ZipOutputStreambuf::overflow() not implemented yet!\n" ;
|
|
// return EOF ;
|
|
}
|
|
|
|
|
|
|
|
int ZipOutputStreambuf::sync() {
|
|
return DeflateOutputStreambuf::sync() ;
|
|
// // FIXME: implement
|
|
// cout << "ZipOutputStreambuf::sync() not implemented yet!\n" ;
|
|
// return EOF ;
|
|
}
|
|
|
|
|
|
|
|
void ZipOutputStreambuf::setEntryClosedState() {
|
|
_open_entry = false ;
|
|
// FIXME: update put pointers to trigger overflow on write. overflow
|
|
// should then return EOF while _open_entry is false.
|
|
}
|
|
|
|
|
|
void ZipOutputStreambuf::updateEntryHeaderInfo() {
|
|
if ( ! _open_entry )
|
|
return ;
|
|
|
|
ostream os( _outbuf ) ;
|
|
int curr_pos = os.tellp() ;
|
|
|
|
// update fields in _entries.back()
|
|
ZipCDirEntry &entry = _entries.back() ;
|
|
entry.setSize( getCount() ) ;
|
|
entry.setCrc( getCrc32() ) ;
|
|
entry.setCompressedSize( curr_pos - entry.getLocalHeaderOffset()
|
|
- entry.getLocalHeaderSize() ) ;
|
|
|
|
// Mark Donszelmann: added current date and time
|
|
time_t ltime;
|
|
time( <ime );
|
|
struct tm *now;
|
|
now = localtime( <ime );
|
|
int dosTime = (now->tm_year - 80) << 25 | (now->tm_mon + 1) << 21 | now->tm_mday << 16 |
|
|
now->tm_hour << 11 | now->tm_min << 5 | now->tm_sec >> 1;
|
|
entry.setTime(dosTime);
|
|
|
|
// write ZipLocalEntry header to header position
|
|
os.seekp( entry.getLocalHeaderOffset() ) ;
|
|
os << static_cast< ZipLocalEntry >( entry ) ;
|
|
os.seekp( curr_pos ) ;
|
|
}
|
|
|
|
|
|
void ZipOutputStreambuf::writeCentralDirectory( const vector< ZipCDirEntry > &entries,
|
|
EndOfCentralDirectory eocd,
|
|
ostream &os ) {
|
|
int cdir_start = os.tellp() ;
|
|
std::vector< ZipCDirEntry >::const_iterator it ;
|
|
int cdir_size = 0 ;
|
|
|
|
for ( it = entries.begin() ; it != entries.end() ; ++it ) {
|
|
os << *it ;
|
|
cdir_size += it->getCDirHeaderSize() ;
|
|
}
|
|
eocd.setOffset( cdir_start ) ;
|
|
eocd.setCDirSize( cdir_size ) ;
|
|
eocd.setTotalCount( entries.size() ) ;
|
|
os << eocd ;
|
|
}
|
|
|
|
} // namespace
|
|
|
|
/** \file
|
|
Implementation of ZipOutputStreambuf.
|
|
*/
|
|
|
|
/*
|
|
Zipios++ - a small C++ library that provides easy access to .zip files.
|
|
Copyright (C) 2000 Thomas Søndergaard
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Lesser General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
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
|
|
*/
|