zipoutputstreambuf.cpp

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

Generated on Wed Nov 23 19:01:12 2011 for FreeCAD by  doxygen 1.6.1