zipios 2.2.0
Zipios -- a small C++ library that provides 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-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
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
145 //: ZipLocalEntry() -- auto-init
146{
147}
148
149
160 : ZipLocalEntry(entry)
161{
162}
163
164
170{
171}
172
173
182{
188 // Note that the structure is 48 bytes because of an alignment
189 // and attempting to use options to avoid the alignment would
190 // not be portable so we use a hard coded value (yuck!)
191 return 46 /* sizeof(ZipCentralDirectoryEntryHeader) */
192 + m_filename.length() + (m_is_directory ? 1 : 0)
193 + m_extra_field.size()
194 + m_comment.length();
195}
196
197
206{
208}
209
210
235void ZipCentralDirectoryEntry::read(std::istream& is)
236{
237 m_valid = false; // set back to true upon successful completion below.
238
239 // verify the signature
240 uint32_t signature;
241 zipRead(is, signature);
242 if(g_signature != signature)
243 {
244 is.setstate(std::ios::failbit);
245 throw IOException("ZipCentralDirectoryEntry::read(): Expected Central Directory entry signature not found");
246 }
247
248 uint16_t writer_version(0);
249 uint16_t compress_method(0);
250 uint32_t dosdatetime(0);
251 uint32_t compressed_size(0);
252 uint32_t uncompressed_size(0);
253 uint32_t rel_offset_loc_head(0);
254 uint16_t filename_len(0);
255 uint16_t extra_field_len(0);
256 uint16_t file_comment_len(0);
257 uint16_t intern_file_attr(0);
258 uint32_t extern_file_attr(0);
259 uint16_t disk_num_start(0);
260 std::string filename;
261
262 // read the header
263 zipRead(is, writer_version); // 16
264 zipRead(is, m_extract_version); // 16
266 zipRead(is, compress_method); // 16
267 zipRead(is, dosdatetime); // 32
268 zipRead(is, m_crc_32); // 32
269 zipRead(is, compressed_size); // 32
270 zipRead(is, uncompressed_size); // 32
271 zipRead(is, filename_len); // 16
272 zipRead(is, extra_field_len); // 16
273 zipRead(is, file_comment_len); // 16
274 zipRead(is, disk_num_start); // 16
275 zipRead(is, intern_file_attr); // 16
276 zipRead(is, extern_file_attr); // 32
277 zipRead(is, rel_offset_loc_head); // 32
278 zipRead(is, filename, filename_len); // string
279 zipRead(is, m_extra_field, extra_field_len); // buffer
280 zipRead(is, m_comment, file_comment_len); // string
285 // the FilePath() will remove the trailing slash so make sure
286 // to defined the m_is_directory ahead of time!
287 m_is_directory = !filename.empty() && filename.back() == g_separator;
288
289 m_compress_method = static_cast<StorageMethod>(compress_method);
290 DOSDateTime t;
291 t.setDOSDateTime(dosdatetime);
293 m_compressed_size = compressed_size;
294 m_uncompressed_size = uncompressed_size;
295 m_entry_offset = rel_offset_loc_head;
296 m_filename = FilePath(filename);
297
298 // the zipRead() should throw if it is false...
299 m_valid = true;
300}
301
302
329{
333 if(m_filename.length() > 0x10000
334 || m_extra_field.size() > 0x10000
335 || m_comment.length() > 0x10000)
336 {
337 throw InvalidStateException("ZipCentralDirectoryEntry::write(): file name, comment, or extra field too large to save in a Zip file.");
338 }
339
340// Solaris defines _ILP32 for 32 bit platforms
341#if !defined(_ILP32)
342 if(m_compressed_size >= 0x100000000ULL
343 || m_uncompressed_size >= 0x100000000ULL
344 || m_entry_offset >= 0x100000000LL)
345 {
346 // This represents really large files which we do not test at this point
347 throw InvalidStateException("ZipCentralDirectoryEntry::write(): The size of this file is too large to fit in a zip archive."); // LCOV_EXCL_LINE
348 }
349#endif
350
351 // define version
352 uint16_t writer_version = g_zip_format_version;
353 // including the "compatibility" code
354#if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
355 // MS-Windows
356 // TBD: should we use g_msdos instead?
357 writer_version |= g_windows;
358#elif defined(__APPLE__) && defined(__MACH__)
359 // OS/X
360 writer_version |= g_osx;
361#else
362 // Other Unices
363 writer_version |= g_unix;
364#endif
365
366 std::string filename(m_filename);
368 {
369 // add a trailing separator for directories
370 // (this is VERY important for zip files which do not otherwise
371 // indicate that a file is a directory)
372 filename += g_separator;
373 }
374
375 uint16_t compress_method(static_cast<uint8_t>(m_compress_method));
377 {
378 compress_method = static_cast<uint8_t>(StorageMethod::STORED);
379 }
380
381 DOSDateTime t;
383 uint32_t dosdatetime(t.getDOSDateTime()); // type could be set to DOSDateTime::dosdatetime_t
384 uint32_t compressed_size(m_compressed_size);
385 uint32_t uncompressed_size(m_uncompressed_size);
386 uint16_t filename_len(filename.length());
387 uint16_t extra_field_len(m_extra_field.size());
388 uint16_t file_comment_len(m_comment.length());
389 uint16_t disk_num_start(0);
390 uint16_t intern_file_attr(0);
410 uint32_t extern_file_attr(m_is_directory ? 0x41FD0010 : 0x81B40000);
411 uint32_t rel_offset_loc_head(m_entry_offset);
412
413 zipWrite(os, g_signature); // 32
414 zipWrite(os, writer_version); // 16
415 zipWrite(os, m_extract_version); // 16
417 zipWrite(os, compress_method); // 16
418 zipWrite(os, dosdatetime); // 32
419 zipWrite(os, m_crc_32); // 32
420 zipWrite(os, compressed_size); // 32
421 zipWrite(os, uncompressed_size); // 32
422 zipWrite(os, filename_len); // 16
423 zipWrite(os, extra_field_len); // 16
424 zipWrite(os, file_comment_len); // 16
425 zipWrite(os, disk_num_start); // 16
426 zipWrite(os, intern_file_attr); // 16
427 zipWrite(os, extern_file_attr); // 32
428 zipWrite(os, rel_offset_loc_head); // 32
429 zipWrite(os, filename); // string
430 zipWrite(os, m_extra_field); // buffer
431 zipWrite(os, m_comment); // string
432}
433
434
435} // zipios namespace
436
437// Local Variables:
438// mode: cpp
439// indent-tabs-mode: nil
440// c-basic-offset: 4
441// tab-width: 4
442// End:
443
444// 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::shared_ptr< FileEntry > pointer_t
Definition fileentry.hpp:78
StorageMethod m_compress_method
std::string m_comment
buffer_t m_extra_field
size_t m_uncompressed_size
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:327
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.