zipios  2.2.6
Zipios -- a small C++ library that provides easy access to .zip files.
zipoutputstreambuf.cpp
Go to the documentation of this file.
1 /*
2  Zipios -- a small C++ library that provides easy access to .zip files.
3 
4  Copyright (C) 2000-2007 Thomas Sondergaard
5  Copyright (C) 2015-2019 Made to Order Software Corporation
6 
7  This library is free software; you can redistribute it and/or
8  modify it under the terms of the GNU Lesser General Public
9  License as published by the Free Software Foundation; either
10  version 2.1 of the License, or (at your option) any later version.
11 
12  This library is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  Lesser General Public License for more details.
16 
17  You should have received a copy of the GNU Lesser General Public
18  License along with this library; if not, write to the Free Software
19  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21 
29 #include "zipoutputstreambuf.hpp"
30 
32 
33 #include "ziplocalentry.hpp"
35 
36 
37 namespace zipios
38 {
39 
40 
41 namespace
42 {
43 
44 
56 void writeZipCentralDirectory(std::ostream &os, FileEntry::vector_t& entries, std::string const& comment)
57 {
58  ZipEndOfCentralDirectory eocd(comment);
59  eocd.setOffset(os.tellp()); // start position
60  eocd.setCount(entries.size());
61 
62  size_t central_directory_size(0);
63  for(auto it = entries.begin(); it != entries.end(); ++it)
64  {
65  (*it)->write(os);
66  central_directory_size += (*it)->getHeaderSize();
67  }
68 
69  eocd.setCentralDirectorySize(central_directory_size);
70  eocd.write(os);
71 }
72 
73 
74 } // no name namespace
75 
76 
93  : DeflateOutputStreambuf(outbuf)
94  //, m_zip_comment("") -- auto-init
95  //, m_entries() -- auto-init
96  //, m_compression_level(FileEntry::COMPRESSION_LEVEL_DEFAULT) -- auto-init
97  //, m_open_entry(false) -- auto-init
98  //, m_open(true) -- auto-init
99 {
100 }
101 
102 
117 {
118  // avoid possible exceptions when writing the central directory
119  try
120  {
121  finish();
122  }
123  catch(...)
124  {
125  }
126 }
127 
128 
135 {
136  if(!m_open_entry)
137  {
138  return;
139  }
140 
141  switch(m_compression_level)
142  {
144  overflow(); // flush
145  break;
146 
147  default:
148  closeStream();
149  break;
150 
151  }
152 
155 }
156 
157 
164 {
165  finish();
166 }
167 
168 
177 {
178  if(!m_open)
179  {
180  return;
181  }
182  m_open = false;
183 
184  std::ostream os(m_outbuf);
185  closeEntry();
187 }
188 
189 
201 {
202  closeEntry();
203 
204  // if the method is STORED force uncompressed data
205  if(entry->getMethod() == StorageMethod::STORED)
206  {
207  // force to "no compression" when the method is STORED
209  }
210  else
211  {
212  // get the user defined compression level
213  m_compression_level = entry->getLevel();
214  }
215  m_overflown_bytes = 0;
216  switch(m_compression_level)
217  {
219  setp(&m_invec[0], &m_invec[0] + getBufferSize());
220  break;
221 
222  default:
224  break;
225 
226  }
227 
228  m_entries.push_back(entry);
229 
230  std::ostream os(m_outbuf);
231 
232  // Update entry header info
233  entry->setEntryOffset(os.tellp());
238  static_cast<ZipLocalEntry *>(entry.get())->ZipLocalEntry::write(os);
239 
240  m_open_entry = true;
241 }
242 
243 
256 void ZipOutputStreambuf::setComment(std::string const& comment)
257 {
258  m_zip_comment = comment;
259 }
260 
261 
262 //
263 // Protected and private methods
264 //
265 
277 {
278  size_t const size(pptr() - pbase());
279  m_overflown_bytes += size;
280  switch(m_compression_level)
281  {
283  {
284  // Ok, we are STORED, so we handle it ourselves to avoid "side
285  // effects" from zlib, which adds markers every now and then.
286  size_t const bc(m_outbuf->sputn(&m_invec[0], size));
287  if(size != bc)
288  {
289  // Without implementing our own stream in our test, this
290  // cannot really be reached because it is all happening
291  // inside the same loop in ZipFile::saveCollectionToArchive()
292  throw IOException("ZipOutputStreambuf::overflow(): write to buffer failed."); // LCOV_EXCL_LINE
293  }
294  setp(&m_invec[0], &m_invec[0] + getBufferSize());
295 
296  if(c != EOF)
297  {
298  *pptr() = c;
299  pbump(1);
300  }
301 
302  return 0;
303  }
304 
305  default:
307 
308  }
309 }
310 
311 
312 
321 int ZipOutputStreambuf::sync() // LCOV_EXCL_LINE
322 {
323  return DeflateOutputStreambuf::sync(); // LCOV_EXCL_LINE
324 }
325 
326 
327 
335 {
336  m_open_entry = false;
337 
342 }
343 
344 
357 {
358  if(!m_open_entry)
359  {
360  return;
361  }
362 
363  std::ostream os(m_outbuf);
364  int const curr_pos(os.tellp());
365 
366  // update fields in m_entries.back()
367  FileEntry::pointer_t entry(m_entries.back());
368  entry->setSize(getSize());
369  entry->setCrc(getCrc32());
374  entry->setCompressedSize(curr_pos - entry->getEntryOffset() - static_cast<ZipLocalEntry *>(entry.get())->ZipLocalEntry::getHeaderSize());
375 
376  // write ZipLocalEntry header to header position
377  os.seekp(entry->getEntryOffset());
382  static_cast<ZipLocalEntry *>(entry.get())->ZipLocalEntry::write(os);
383  os.seekp(curr_pos);
384 }
385 
386 
387 } // zipios namespace
388 
389 // Local Variables:
390 // mode: cpp
391 // indent-tabs-mode: nil
392 // c-basic-offset: 4
393 // tab-width: 4
394 // End:
395 
396 // vim: ts=4 sw=4 et
zipios::anonymous_namespace{zipoutputstreambuf.cpp}::writeZipCentralDirectory
void writeZipCentralDirectory(std::ostream &os, FileEntry::vector_t &entries, std::string const &comment)
Help function used to write the central directory.
Definition: zipoutputstreambuf.cpp:56
ziplocalentry.hpp
Declare the zipios::ZipLocalEntry class used to handle Zip entries.
zipios::ZipEndOfCentralDirectory::setOffset
void setOffset(offset_t new_offset)
Offset of the Central Directory.
Definition: zipendofcentraldirectory.cpp:200
zipios::DeflateOutputStreambuf::getSize
size_t getSize() const
Retrieve the size of the file deflated.
Definition: deflateoutputstreambuf.cpp:256
zipios::ZipOutputStreambuf::putNextEntry
void putNextEntry(FileEntry::pointer_t entry)
Start saving an entry in the output buffer.
Definition: zipoutputstreambuf.cpp:200
zipios::ZipOutputStreambuf::setComment
void setComment(std::string const &comment)
Set the archive comment.
Definition: zipoutputstreambuf.cpp:256
zipios::DeflateOutputStreambuf::m_invec
std::vector< char > m_invec
Definition: deflateoutputstreambuf.hpp:65
zipios::DeflateOutputStreambuf::init
bool init(FileEntry::CompressionLevel compression_level)
Initialize the zlib library.
Definition: deflateoutputstreambuf.cpp:106
zipios::DeflateOutputStreambuf::overflow
virtual int overflow(int c=EOF)
Handle an overflow.
Definition: deflateoutputstreambuf.cpp:275
zipios::DeflateOutputStreambuf::sync
virtual int sync()
Synchronize the buffer.
Definition: deflateoutputstreambuf.cpp:340
zipiosexceptions.hpp
Various exceptions used throughout the Zipios library, all based on zipios::Exception.
zipios::ZipOutputStreambuf::m_entries
FileEntry::vector_t m_entries
Definition: zipoutputstreambuf.hpp:64
zipios::FileEntry::pointer_t
std::shared_ptr< FileEntry > pointer_t
Definition: fileentry.hpp:78
zipios::ZipOutputStreambuf::overflow
virtual int overflow(int c=EOF) override
Implementation of the overflow() function.
Definition: zipoutputstreambuf.cpp:276
zipios::ZipEndOfCentralDirectory::write
void write(std::ostream &os)
Write the ZipEndOfCentralDirectory structure to a stream.
Definition: zipendofcentraldirectory.cpp:307
zipios::ZipOutputStreambuf::m_compression_level
FileEntry::CompressionLevel m_compression_level
Definition: zipoutputstreambuf.hpp:65
zipios::ZipOutputStreambuf::updateEntryHeaderInfo
void updateEntryHeaderInfo()
Save the header information.
Definition: zipoutputstreambuf.cpp:356
zipios::ZipOutputStreambuf::setEntryClosedState
void setEntryClosedState()
Mark the current entry as closed.
Definition: zipoutputstreambuf.cpp:334
zipios::DeflateOutputStreambuf::getCrc32
uint32_t getCrc32() const
Get the CRC32 of the file.
Definition: deflateoutputstreambuf.cpp:239
zipios::ZipOutputStreambuf::closeEntry
void closeEntry()
Close this buffer entry.
Definition: zipoutputstreambuf.cpp:134
zipios::IOException
An IOException is used to signal an I/O error.
Definition: zipiosexceptions.hpp:71
zipios::ZipEndOfCentralDirectory::setCentralDirectorySize
void setCentralDirectorySize(size_t size)
Define the size of the central directory.
Definition: zipendofcentraldirectory.cpp:160
zipios::DeflateOutputStreambuf::closeStream
void closeStream()
Closing the stream.
Definition: deflateoutputstreambuf.cpp:205
zipios::ZipLocalEntry::write
virtual void write(std::ostream &os) override
Write a ZipLocalEntry to os.
Definition: ziplocalentry.cpp:405
zipios::FileEntry::COMPRESSION_LEVEL_NONE
static CompressionLevel const COMPRESSION_LEVEL_NONE
Definition: fileentry.hpp:90
zipios::ZipOutputStreambuf::m_open_entry
bool m_open_entry
Definition: zipoutputstreambuf.hpp:66
zipios::ZipOutputStreambuf::close
void close()
Close the output stream buffer.
Definition: zipoutputstreambuf.cpp:163
zipios::ZipLocalEntry
An implementation of the FileEntry for Zip archives.
Definition: ziplocalentry.hpp:43
zipios::ZipOutputStreambuf::~ZipOutputStreambuf
virtual ~ZipOutputStreambuf()
Clean up the buffer.
Definition: zipoutputstreambuf.cpp:116
zipios::ZipOutputStreambuf::m_zip_comment
std::string m_zip_comment
Definition: zipoutputstreambuf.hpp:63
zipios::DeflateOutputStreambuf
A class to handle stream deflate on the fly.
Definition: deflateoutputstreambuf.hpp:48
zipoutputstreambuf.hpp
Define the zipios::ZipOutputStreambuf class.
zipios::ZipOutputStreambuf::m_open
bool m_open
Definition: zipoutputstreambuf.hpp:67
zipios::ZipOutputStreambuf::finish
void finish()
Finish up an output stream buffer.
Definition: zipoutputstreambuf.cpp:176
zipios::ZipOutputStreambuf::ZipOutputStreambuf
ZipOutputStreambuf(std::streambuf *outbuf)
Initialize a ZipOutputStreambuf object.
Definition: zipoutputstreambuf.cpp:92
zipios::getBufferSize
size_t getBufferSize()
Definition: zipios-config.hpp.in:62
zipios::ZipEndOfCentralDirectory::setCount
void setCount(size_t c)
Set the number of entries.
Definition: zipendofcentraldirectory.cpp:179
zipios::ZipOutputStreambuf::sync
virtual int sync() override
Implement the sync() functionality.
Definition: zipoutputstreambuf.cpp:321
zipios::ZipEndOfCentralDirectory
Marker at the end of a Zip archive file.
Definition: zipendofcentraldirectory.hpp:46
zipios::FilterOutputStreambuf::m_outbuf
std::streambuf * m_outbuf
Definition: filteroutputstreambuf.hpp:49
zipendofcentraldirectory.hpp
Declaration of the zipios::ZipEndOfCentralDirectory class.
zipios::DeflateOutputStreambuf::m_overflown_bytes
uint32_t m_overflown_bytes
Definition: deflateoutputstreambuf.hpp:64
zipios::FileEntry::vector_t
std::vector< pointer_t > vector_t
Definition: fileentry.hpp:79
zipios
The zipios namespace includes the Zipios library definitions.
Definition: backbuffer.cpp:36