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 */