zipios  2.3.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-2022 Made to Order Software Corp. All Rights Reserved
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_zip_comment(zip_comment)
84 {
85 }
86 
87 
100 {
102 }
103 
104 
119 {
121 }
122 
123 
140 {
142 }
143 
144 
158 {
160 }
161 
162 
177 {
179 }
180 
181 
198 {
199  m_central_directory_offset = start_offset;
200 }
201 
202 
225 bool ZipEndOfCentralDirectory::read(::zipios::buffer_t const & buf, size_t pos)
226 {
227  // the number of bytes we are going to read in the buffer
228  // (including the signature)
229  ssize_t const HEADER_SIZE(static_cast<ssize_t>(sizeof(uint32_t) * 3 + sizeof(uint16_t) * 5));
230 
231  // enough data in the buffer?
232  //
233  // Note: this quick check assumes a 0 length comment which is possible;
234  // if there is a comment and we find the signature too early, then
235  // it will throw
236  //
237  if(static_cast<ssize_t>(buf.size() - pos) < HEADER_SIZE)
238  {
239  return false;
240  }
241 
242  // first read and check the signature
243  uint32_t signature;
244  zipRead(buf, pos, signature); // 32
245  if(signature != g_signature)
246  {
247  return false;
248  }
249 
250  // next we read the other parameters
251  uint16_t disk_number;
252  uint16_t central_directory_entries;
253  uint16_t central_directory_total_entries;
254  uint32_t central_directory_size;
255  uint32_t central_directory_offset;
256  uint16_t comment_len;
257 
258  zipRead(buf, pos, disk_number); // 16
259  zipRead(buf, pos, disk_number); // 16
260  zipRead(buf, pos, central_directory_entries); // 16
261  zipRead(buf, pos, central_directory_total_entries); // 16
262  zipRead(buf, pos, central_directory_size); // 32
263  zipRead(buf, pos, central_directory_offset); // 32
264  zipRead(buf, pos, comment_len); // 16
265  zipRead(buf, pos, m_zip_comment, comment_len); // string
266 
267  // note that if disk_number is defined, then these following two
268  // numbers should differ too
269  if(central_directory_entries != central_directory_total_entries)
270  {
271  throw FileCollectionException("ZipEndOfCentralDirectory with a number of entries and total entries that differ is not supported, spanned zip files are not supported");
272  }
273 
274  m_central_directory_entries = central_directory_entries;
275  m_central_directory_size = central_directory_size;
276  m_central_directory_offset = central_directory_offset;
277 
278  return true;
279 }
280 
281 
304 void ZipEndOfCentralDirectory::write(std::ostream & os)
305 {
310  if(m_zip_comment.length() > 65535)
311  {
312  throw InvalidStateException("the Zip archive comment is too large");
313  }
314  if(m_central_directory_entries > 65535)
315  {
316  throw InvalidStateException("the number of entries in the Zip archive is too large");
317  }
318 // Solaris defines _ILP32 for 32 bit platforms
319 #if INTPTR_MAX != INT32_MAX
320  if(m_central_directory_size >= 0x100000000UL
321  || m_central_directory_offset >= 0x100000000L)
322  {
323  throw FileCollectionException("the Zip archive size or offset are too large"); // LCOV_EXCL_LINE
324  }
325 #endif
326 
327  uint16_t const disk_number(0);
328  uint16_t const central_directory_entries(m_central_directory_entries);
329  uint32_t const central_directory_size(m_central_directory_size);
330  uint32_t const central_directory_offset(m_central_directory_offset);
331  uint16_t const comment_len(m_zip_comment.length());
332 
333  // the total number of entries, across all disks is the same in our
334  // case so we use one number for both fields
335 
336  zipWrite(os, g_signature); // 32
337  zipWrite(os, disk_number); // 16
338  zipWrite(os, disk_number); // 16
339  zipWrite(os, central_directory_entries); // 16
340  zipWrite(os, central_directory_entries); // 16
341  zipWrite(os, central_directory_size); // 32
342  zipWrite(os, central_directory_offset); // 32
343  zipWrite(os, comment_len); // 16
344  zipWrite(os, m_zip_comment); // string
345 }
346 
347 
348 } // zipios namespace
349 
350 // Local Variables:
351 // mode: cpp
352 // indent-tabs-mode: nil
353 // c-basic-offset: 4
354 // tab-width: 4
355 // End:
356 
357 // 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.
Various exceptions used throughout the Zipios library, all based on zipios::Exception.
void zipRead(std::istream &is, uint32_t &value)
size_t getCount() const
Retrieve the number of entries.
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.
ZipEndOfCentralDirectory(std::string const &zip_comment=std::string())
Initialize an ZipEndOfCentralDirectory object.
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
size_t getCentralDirectorySize() const
Retrieve the size of the Central Directory in bytes.
offset_t getOffset() const
Retrieve the offset of the Central Directory.
bool read(::zipios::buffer_t const &buf, size_t pos)
Attempt to read an ZipEndOfCentralDirectory structure.