Zipios++
zipoutputstreambuf.cpp
Go to the documentation of this file.
1 
2 #include <time.h>
3 
4 #include "zipios++/zipios-config.h"
5 
6 #include <algorithm>
7 #include "zipios++/meta-iostreams.h"
8 
9 #include <zlib.h>
10 
12 
13 namespace zipios {
14 
15 using std::ios ;
16 using std::cerr ;
17 using std::endl ;
18 //using std::min ;
19 
20 ZipOutputStreambuf::ZipOutputStreambuf( streambuf *outbuf, bool del_outbuf )
21  : DeflateOutputStreambuf( outbuf, false, del_outbuf ),
22  _open_entry( false ),
23  _open ( true ),
24  _method ( DEFLATED ),
25  _level ( 6 )
26 {
27 }
28 
29 
31  if ( ! _open_entry )
32  return ;
33 
34  closeStream() ;
35 
36  updateEntryHeaderInfo() ;
37  setEntryClosedState( ) ;
38 }
39 
40 
42  finish() ;
43 }
44 
45 
47  if( ! _open )
48  return ;
49  closeEntry() ;
50  ostream os( _outbuf ) ;
51  writeCentralDirectory( _entries, EndOfCentralDirectory( _zip_comment), os ) ;
52  _open = false ;
53 }
54 
55 
57  finish() ;
58 }
59 
60 
62  if ( _open_entry )
63  closeEntry() ;
64 
65  if ( ! init( _level ) )
66  cerr << "ZipOutputStreambuf::putNextEntry(): init() failed!\n" ;
67 
68  _entries.push_back( entry ) ;
69  ZipCDirEntry &ent = _entries.back() ;
70 
71  ostream os( _outbuf ) ;
72 
73  // Update entry header info
74  ent.setLocalHeaderOffset( os.tellp() ) ;
75  ent.setMethod( _method ) ;
76 
77  os << static_cast< ZipLocalEntry >( ent ) ;
78 
79  _open_entry = true ;
80 }
81 
82 
83 void ZipOutputStreambuf::setComment( const string &comment ) {
84  _zip_comment = comment ;
85 }
86 
87 
88 void ZipOutputStreambuf::setLevel( int level ) {
89  _level = level ;
90 }
91 
92 
93 void ZipOutputStreambuf::setMethod( StorageMethod method ) {
94  _method = method ;
95  if( method == STORED )
96  setLevel( NO_COMPRESSION ) ;
97  else if ( method == DEFLATED ) {
98  if( _level == NO_COMPRESSION )
99  setLevel( DEFAULT_COMPRESSION ) ;
100  } else
101  throw FCollException( "Specified compression method not supported" ) ;
102 }
103 
104 //
105 // Protected and private methods
106 //
107 
108 int ZipOutputStreambuf::overflow( int c ) {
109  return DeflateOutputStreambuf::overflow( c ) ;
110 // // FIXME: implement
111 
112 // cout << "ZipOutputStreambuf::overflow() not implemented yet!\n" ;
113 // return EOF ;
114 }
115 
116 
117 
118 int ZipOutputStreambuf::sync() {
119  return DeflateOutputStreambuf::sync() ;
120 // // FIXME: implement
121 // cout << "ZipOutputStreambuf::sync() not implemented yet!\n" ;
122 // return EOF ;
123 }
124 
125 
126 
127 void ZipOutputStreambuf::setEntryClosedState() {
128  _open_entry = false ;
129  // FIXME: update put pointers to trigger overflow on write. overflow
130  // should then return EOF while _open_entry is false.
131 }
132 
133 
134 void ZipOutputStreambuf::updateEntryHeaderInfo() {
135  if ( ! _open_entry )
136  return ;
137 
138  ostream os( _outbuf ) ;
139  int curr_pos = os.tellp() ;
140 
141  // update fields in _entries.back()
142  ZipCDirEntry &entry = _entries.back() ;
143  entry.setSize( getCount() ) ;
144  entry.setCrc( getCrc32() ) ;
145  entry.setCompressedSize( curr_pos - entry.getLocalHeaderOffset()
146  - entry.getLocalHeaderSize() ) ;
147 
148  // Mark Donszelmann: added current date and time
149  time_t ltime;
150  time( &ltime );
151  struct tm *now;
152  now = localtime( &ltime );
153  int dosTime = (now->tm_year - 80) << 25 | (now->tm_mon + 1) << 21 | now->tm_mday << 16 |
154  now->tm_hour << 11 | now->tm_min << 5 | now->tm_sec >> 1;
155  entry.setTime(dosTime);
156 
157  // write ZipLocalEntry header to header position
158  os.seekp( entry.getLocalHeaderOffset() ) ;
159  os << static_cast< ZipLocalEntry >( entry ) ;
160  os.seekp( curr_pos ) ;
161 }
162 
163 
164 void ZipOutputStreambuf::writeCentralDirectory( const vector< ZipCDirEntry > &entries,
165  EndOfCentralDirectory eocd,
166  ostream &os ) {
167  int cdir_start = os.tellp() ;
168  std::vector< ZipCDirEntry >::const_iterator it ;
169  int cdir_size = 0 ;
170 
171  for ( it = entries.begin() ; it != entries.end() ; ++it ) {
172  os << *it ;
173  cdir_size += it->getCDirHeaderSize() ;
174  }
175  eocd.setOffset( cdir_start ) ;
176  eocd.setCDirSize( cdir_size ) ;
177  eocd.setTotalCount( entries.size() ) ;
178  os << eocd ;
179 }
180 
181 } // namespace
182 
187 /*
188  Zipios++ - a small C++ library that provides easy access to .zip files.
189  Copyright (C) 2000 Thomas Søndergaard
190 
191  This library is free software; you can redistribute it and/or
192  modify it under the terms of the GNU Lesser General Public
193  License as published by the Free Software Foundation; either
194  version 2 of the License, or (at your option) any later version.
195 
196  This library is distributed in the hope that it will be useful,
197  but WITHOUT ANY WARRANTY; without even the implied warranty of
198  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
199  Lesser General Public License for more details.
200 
201  You should have received a copy of the GNU Lesser General Public
202  License along with this library; if not, write to the Free Software
203  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
204 */
Header file that defines ZipOutputStreambuf.
The end of the Central directory structure.
Definition: ziphead.h:159
ZipOutputStreambuf(streambuf *outbuf, bool del_outbuf=false)
ZipOutputStreambuf constructor.
virtual void setMethod(StorageMethod method)
Sets the storage method field for the entry.
Definition: ziphead.cpp:135
void setComment(const string &comment)
Sets the global comment for the Zip archive.
Specialization of ZipLocalEntry, that add fields for storing the extra information, that is only present in the entries in the zip central directory and not in the local entry headers.
Definition: ziphead.h:102
DeflateOutputStreambuf is an output stream filter, that deflates the data that is written to it befor...
void closeEntry()
Closes the current entry, and positions the stream read pointer at the beginning of the next entry (i...
void setMethod(StorageMethod method)
Sets the compression method to be used.
virtual ~ZipOutputStreambuf()
Destructor.
uint32 getCount() const
Returns the number of bytes written to the streambuf, that has been processed from the input buffer b...
An FCollException is used to signal a problem with a FileCollection.
void putNextEntry(const ZipCDirEntry &entry)
Begins writing the next entry.
void finish()
Closes the current entry (if one is open), then writes the Zip Central Directory Structure closing th...
uint32 getCrc32() const
Returns the CRC32 for the current stream.
void setLevel(int level)
Sets the compression level to be used for subsequent entries.