zipios++  2.0.2
Zipios++ – a small C++ library that provides easy access to .zip files.
zipendofcentraldirectory.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 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21 
31 
33 
34 
35 namespace zipios
36 {
37 
38 
54 namespace
55 {
56 
57 
68 uint32_t const g_signature = 0x06054b50;
69 
70 
71 } // no name namespace
72 
73 
83  //: m_central_directory_entries(0) -- auto-init
84  //, m_central_directory_size(0) -- auto-init
85  //, m_central_directory_offset(0) -- auto-init
86  : m_zip_comment(zip_comment)
87 {
88 }
89 
90 
103 {
105 }
106 
107 
122 {
124 }
125 
126 
143 {
145 }
146 
147 
161 {
163 }
164 
165 
180 {
182 }
183 
184 
201 {
202  m_central_directory_offset = start_offset;
203 }
204 
205 
228 bool ZipEndOfCentralDirectory::read(::zipios::buffer_t const& buf, size_t pos)
229 {
230  // the number of bytes we are going to read in the buffer
231  // (including the signature)
232  ssize_t const HEADER_SIZE(static_cast<ssize_t>(sizeof(uint32_t) * 3 + sizeof(uint16_t) * 5));
233 
234  // enough data in the buffer?
235  //
236  // Note: this quick check assumes a 0 length comment which is possible;
237  // if there is a comment and we find the signature too early, then
238  // it will throw
239  //
240  if(static_cast<ssize_t>(buf.size() - pos) < HEADER_SIZE)
241  {
242  return false;
243  }
244 
245  // first read and check the signature
246  uint32_t signature;
247  zipRead(buf, pos, signature); // 32
248  if(signature != g_signature)
249  {
250  return false;
251  }
252 
253  // next we read the other parameters
254  uint16_t disk_number;
255  uint16_t central_directory_entries;
256  uint16_t central_directory_total_entries;
257  uint32_t central_directory_size;
258  uint32_t central_directory_offset;
259  uint16_t comment_len;
260 
261  zipRead(buf, pos, disk_number); // 16
262  zipRead(buf, pos, disk_number); // 16
263  zipRead(buf, pos, central_directory_entries); // 16
264  zipRead(buf, pos, central_directory_total_entries); // 16
265  zipRead(buf, pos, central_directory_size); // 32
266  zipRead(buf, pos, central_directory_offset); // 32
267  zipRead(buf, pos, comment_len); // 16
268  zipRead(buf, pos, m_zip_comment, comment_len); // string
269 
270  // note that if disk_number is defined, then these following two
271  // numbers should differ too
272  if(central_directory_entries != central_directory_total_entries)
273  {
274  throw FileCollectionException("ZipEndOfCentralDirectory with a number of entries and total entries that differ is not supported, spanned zip files are not supported");
275  }
276 
277  m_central_directory_entries = central_directory_entries;
278  m_central_directory_size = central_directory_size;
279  m_central_directory_offset = central_directory_offset;
280 
281  return true;
282 }
283 
284 
307 void ZipEndOfCentralDirectory::write(std::ostream& os)
308 {
313  if(m_zip_comment.length() > 65535)
314  {
315  throw InvalidStateException("the Zip archive comment is too large");
316  }
317  if(m_central_directory_entries > 65535)
318  {
319  throw InvalidStateException("the number of entries in the Zip archive is too large");
320  }
321 // Solaris defines _ILP32 for 32 bit platforms
322 #if !defined(_ILP32)
323  if(m_central_directory_size >= 0x100000000UL
324  || m_central_directory_offset >= 0x100000000L)
325  {
326  throw FileCollectionException("the Zip archive size or offset are too large"); // LCOV_EXCL_LINE
327  }
328 #endif
329 
330  uint16_t const disk_number(0);
331  uint16_t const central_directory_entries(m_central_directory_entries);
332  uint32_t const central_directory_size(m_central_directory_size);
333  uint32_t const central_directory_offset(m_central_directory_offset);
334  uint16_t const comment_len(m_zip_comment.length());
335 
336  // the total number of entries, across all disks is the same in our
337  // case so we use one number for both fields
338 
339  zipWrite(os, g_signature); // 32
340  zipWrite(os, disk_number); // 16
341  zipWrite(os, disk_number); // 16
342  zipWrite(os, central_directory_entries); // 16
343  zipWrite(os, central_directory_entries); // 16
344  zipWrite(os, central_directory_size); // 32
345  zipWrite(os, central_directory_offset); // 32
346  zipWrite(os, comment_len); // 16
347  zipWrite(os, m_zip_comment); // string
348 }
349 
350 
351 } // zipios namespace
352 
353 // Local Variables:
354 // mode: cpp
355 // indent-tabs-mode: nil
356 // c-basic-offset: 4
357 // tab-width: 4
358 // End:
359 
360 // vim: ts=4 sw=4 et
void setCount(size_t c)
Set the number of entries.
void write(std::ostream &os)
Write the ZipEndOfCentralDirectory structure to a stream.
size_t getCount() const
Retrieve the number of entries.
Various exceptions used throughout the Zipios++ library, all based on zipios::Exception.
void zipRead(std::istream &is, uint32_t &value)
offset_t getOffset() const
Retrieve the offset of the Central Directory.
void setCentralDirectorySize(size_t size)
Define the size of the central directory.
void setOffset(offset_t new_offset)
Offset of the Central Directory.
void zipWrite(std::ostream &os, uint32_t const &value)
std::vector< unsigned char > buffer_t
A buffer of characters.
uint32_t const g_signature
Signature of the ZipEndOfCentralDirectory structure block.
Exception used when it is not possible to move forward.
FileCollectionException is used to signal a FileCollection problem.
Declaration of the zipios::ZipEndOfCentralDirectory class.
std::streamoff offset_t
ZipEndOfCentralDirectory(std::string const &zip_comment="")
Initialize an ZipEndOfCentralDirectory object.
size_t getCentralDirectorySize() const
Retrieve the size of the Central Directory in bytes.
bool read(::zipios::buffer_t const &buf, size_t pos)
Attempt to read an ZipEndOfCentralDirectory structure.