zipios  2.2.0
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-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 
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.
The zipios namespace includes the Zipios library definitions.
Definition: backbuffer.cpp:35
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.