zipios 2.3.4
Zipios -- a small C++ library providing easy access to .zip files.
zipcentraldirectoryentry.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
34
35#include "zipios_common.hpp"
36
37
38namespace zipios
39{
40
41
42
43namespace
44{
45
46
57uint32_t const g_signature = 0x02014b50;
58
59
60// The zip codes (values are pre-shifted)
61uint16_t const g_msdos = 0x0000;
62uint16_t const g_amiga = 0x0100;
63uint16_t const g_open_vms = 0x0200;
64uint16_t const g_unix = 0x0300;
65uint16_t const g_vm_cms = 0x0400;
66uint16_t const g_atari_st = 0x0500;
67uint16_t const g_os2_hpfs = 0x0600;
68uint16_t const g_macintosh = 0x0700;
69uint16_t const g_z_system = 0x0800;
70uint16_t const g_cpm = 0x0900;
71uint16_t const g_windows = 0x0A00;
72uint16_t const g_mvs = 0x0B00;
73uint16_t const g_vse = 0x0C00;
74uint16_t const g_acorn_risc = 0x0D00;
75uint16_t const g_vfat = 0x0E00;
76uint16_t const g_alternate_vms = 0x0F00;
77uint16_t const g_beos = 0x1000;
78uint16_t const g_tandem = 0x1100;
79uint16_t const g_os400 = 0x1200;
80uint16_t const g_osx = 0x1300;
81
82
103{
104 uint32_t m_signature;
110 uint32_t m_crc_32;
120 //uint8_t m_filename[m_filename_len];
121 //uint8_t m_extra_field[m_extra_field_len];
122 //uint8_t m_file_comment[m_file_comment_len];
123};
124
125
126} // no name namespace
127
128
147
148
162
163
171
172
181{
187 // Note that the structure is 48 bytes because of an alignment
188 // and attempting to use options to avoid the alignment would
189 // not be portable so we use a hard coded value (yuck!)
190 return 46 /* sizeof(ZipCentralDirectoryEntryHeader) */
191 + m_filename.length() + (m_is_directory ? 1 : 0)
192 + m_extra_field.size()
193 + m_comment.length();
194}
195
196
205{
206 return std::make_shared<ZipCentralDirectoryEntry>(*this);
207}
208
209
234void ZipCentralDirectoryEntry::read(std::istream & is)
235{
236 m_valid = false; // set back to true upon successful completion below.
237
238 // verify the signature
239 uint32_t signature;
240 zipRead(is, signature);
241 if(g_signature != signature)
242 {
243 is.setstate(std::ios::failbit);
244 throw IOException("ZipCentralDirectoryEntry::read(): Expected Central Directory entry signature not found");
245 }
246
247 uint16_t writer_version(0);
248 uint16_t compress_method(0);
249 uint32_t dosdatetime(0);
250 uint32_t compressed_size(0);
251 uint32_t uncompressed_size(0);
252 uint32_t rel_offset_loc_head(0);
253 uint16_t filename_len(0);
254 uint16_t extra_field_len(0);
255 uint16_t file_comment_len(0);
256 uint16_t intern_file_attr(0);
257 uint32_t extern_file_attr(0);
258 uint16_t disk_num_start(0);
259 std::string filename;
260
261 // read the header
262 zipRead(is, writer_version); // 16
263 zipRead(is, m_extract_version); // 16
265 zipRead(is, compress_method); // 16
266 zipRead(is, dosdatetime); // 32
267 zipRead(is, m_crc_32); // 32
268 zipRead(is, compressed_size); // 32
269 zipRead(is, uncompressed_size); // 32
270 zipRead(is, filename_len); // 16
271 zipRead(is, extra_field_len); // 16
272 zipRead(is, file_comment_len); // 16
273 zipRead(is, disk_num_start); // 16
274 zipRead(is, intern_file_attr); // 16
275 zipRead(is, extern_file_attr); // 32
276 zipRead(is, rel_offset_loc_head); // 32
277 zipRead(is, filename, filename_len); // string
278 zipRead(is, m_extra_field, extra_field_len); // buffer
279 zipRead(is, m_comment, file_comment_len); // string
284 // the FilePath() will remove the trailing slash so make sure
285 // to defined the m_is_directory ahead of time!
286 m_is_directory = !filename.empty() && filename.back() == g_separator;
287
288 m_compress_method = static_cast<StorageMethod>(compress_method);
289 DOSDateTime t;
290 t.setDOSDateTime(dosdatetime);
292 m_compressed_size = compressed_size;
293 m_uncompressed_size = uncompressed_size;
294 m_entry_offset = rel_offset_loc_head;
295 m_filename = FilePath(filename);
296
297 // the zipRead() should throw if it is false...
298 m_valid = true;
299}
300
301
327void ZipCentralDirectoryEntry::write(std::ostream & os)
328{
332 if(m_filename.length() > 0x10000
333 || m_extra_field.size() > 0x10000
334 || m_comment.length() > 0x10000)
335 {
336 throw InvalidStateException("ZipCentralDirectoryEntry::write(): file name, comment, or extra field too large to save in a Zip file.");
337 }
338
339// Solaris defines _ILP32 for 32 bit platforms
340#if INTPTR_MAX != INT32_MAX
341 if(m_compressed_size >= 0x100000000ULL
342 || m_uncompressed_size >= 0x100000000ULL
343 || m_entry_offset >= 0x100000000LL)
344 {
345 // This represents really large files which we do not test at this point
346 throw InvalidStateException("ZipCentralDirectoryEntry::write(): The size of this file is too large to fit in a zip archive."); // LCOV_EXCL_LINE
347 }
348#endif
349
350 // define version
351 uint16_t writer_version = g_zip_format_version;
352 // including the "compatibility" code
353#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
354 // MS-Windows
355 // TBD: should we use g_msdos instead?
356 writer_version |= g_windows;
357#elif defined(__APPLE__) && defined(__MACH__)
358 // OS/X
359 writer_version |= g_osx;
360#else
361 // Other Unices
362 writer_version |= g_unix;
363#endif
364
365 std::string filename(m_filename);
367 {
368 // add a trailing separator for directories
369 // (this is VERY important for zip files which do not otherwise
370 // indicate that a file is a directory)
371 filename += g_separator;
372 }
373
374 uint16_t compress_method(static_cast<uint8_t>(m_compress_method));
376 {
377 compress_method = static_cast<uint8_t>(StorageMethod::STORED);
378 }
379
380 DOSDateTime t;
382 uint32_t dosdatetime(t.getDOSDateTime()); // type could be set to DOSDateTime::dosdatetime_t
383 uint32_t compressed_size(m_compressed_size);
384 uint32_t uncompressed_size(m_uncompressed_size);
385 uint16_t filename_len(filename.length());
386 uint16_t extra_field_len(m_extra_field.size());
387 uint16_t file_comment_len(m_comment.length());
388 uint16_t disk_num_start(0);
389 uint16_t intern_file_attr(0);
409 uint32_t extern_file_attr(m_is_directory ? 0x41FD0010 : 0x81B40000);
410 uint32_t rel_offset_loc_head(m_entry_offset);
411
412 zipWrite(os, g_signature); // 32
413 zipWrite(os, writer_version); // 16
414 zipWrite(os, m_extract_version); // 16
416 zipWrite(os, compress_method); // 16
417 zipWrite(os, dosdatetime); // 32
418 zipWrite(os, m_crc_32); // 32
419 zipWrite(os, compressed_size); // 32
420 zipWrite(os, uncompressed_size); // 32
421 zipWrite(os, filename_len); // 16
422 zipWrite(os, extra_field_len); // 16
423 zipWrite(os, file_comment_len); // 16
424 zipWrite(os, disk_num_start); // 16
425 zipWrite(os, intern_file_attr); // 16
426 zipWrite(os, extern_file_attr); // 32
427 zipWrite(os, rel_offset_loc_head); // 32
428 zipWrite(os, filename); // string
429 zipWrite(os, m_extra_field); // buffer
430 zipWrite(os, m_comment); // string
431}
432
433
434} // zipios namespace
435
436// Local Variables:
437// mode: cpp
438// indent-tabs-mode: nil
439// c-basic-offset: 4
440// tab-width: 4
441// End:
442
443// vim: ts=4 sw=4 et
dosdatetime_t getDOSDateTime() const
Retrieve the DOSDateTime value as is.
std::time_t getUnixTimestamp() const
Retrieve the DOSDateTime as a Unix timestamp.
void setDOSDateTime(dosdatetime_t datetime)
Set the DOSDateTime value as is.
void setUnixTimestamp(std::time_t unix_timestamp)
Set the DOSDateTime value from a Unix timestamp.
A FileEntry represents an entry in a FileCollection.
Definition fileentry.hpp:76
std::size_t m_uncompressed_size
std::shared_ptr< FileEntry > pointer_t
Definition fileentry.hpp:78
StorageMethod m_compress_method
std::string m_comment
buffer_t m_extra_field
CompressionLevel m_compression_level
std::streampos m_entry_offset
static CompressionLevel const COMPRESSION_LEVEL_NONE
Definition fileentry.hpp:90
Handle a file path and name and its statistics.
Definition filepath.hpp:47
size_t length() const
Get the length of the string.
Definition filepath.cpp:336
An IOException is used to signal an I/O error.
Exception used when it is not possible to move forward.
virtual ~ZipCentralDirectoryEntry() override
Clean up the entry.
virtual size_t getHeaderSize() const override
Compute and return the current header size.
virtual void write(std::ostream &os) override
Write a Central Directory Entry to the output stream.
ZipCentralDirectoryEntry()
Initializes a default ZipCentralDirectoryEntry object.
virtual pointer_t clone() const override
Create a clone of this Central Directory entry.
virtual void read(std::istream &is) override
Read a Central Directory entry.
An implementation of the FileEntry for Zip archives.
uint16_t m_general_purpose_bitfield
static uint16_t const g_zip_format_version
Define a type to manage date and time in MS-DOS format.
uint32_t const g_signature
The signature of a ZipCentralDirectoryEntry.
The zipios namespace includes the Zipios library definitions.
void zipRead(std::istream &is, uint32_t &value)
StorageMethod
The types used with FileEntry::setMethod and FileEntry::getMethod.
Definition fileentry.hpp:49
char const g_separator
The character used as the filename separator.
void zipWrite(std::ostream &os, uint32_t const &value)
Declaration of the zipios::ZipCentralDirectoryEntry, which represents a directory Zip archive entry.
Various functions used throughout the library.
Various exceptions used throughout the Zipios library, all based on zipios::Exception.