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-2017 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 #include "dostime.h"
35 #include "zipios_common.hpp"
36 
37 
38 namespace zipios
39 {
40 
41 
42 
43 namespace
44 {
45 
46 
57 uint32_t const g_signature = 0x02014b50;
58 
59 
60 // The zip codes (values are pre-shifted)
61 uint16_t const g_msdos = 0x0000;
62 uint16_t const g_amiga = 0x0100;
63 uint16_t const g_open_vms = 0x0200;
64 uint16_t const g_unix = 0x0300;
65 uint16_t const g_vm_cms = 0x0400;
66 uint16_t const g_atari_st = 0x0500;
67 uint16_t const g_os2_hpfs = 0x0600;
68 uint16_t const g_macintosh = 0x0700;
69 uint16_t const g_z_system = 0x0800;
70 uint16_t const g_cpm = 0x0900;
71 uint16_t const g_windows = 0x0A00;
72 uint16_t const g_mvs = 0x0B00;
73 uint16_t const g_vse = 0x0C00;
74 uint16_t const g_acorn_risc = 0x0D00;
75 uint16_t const g_vfat = 0x0E00;
76 uint16_t const g_alternate_vms = 0x0F00;
77 uint16_t const g_beos = 0x1000;
78 uint16_t const g_tandem = 0x1100;
79 uint16_t const g_os400 = 0x1200;
80 uint16_t const g_osx = 0x1300;
81 
82 
103 {
104  uint32_t m_signature;
109  uint32_t m_dostime;
110  uint32_t m_crc_32;
113  uint16_t m_filename_len;
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 
235 void 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 dostime(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, dostime); // 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);
291  m_compressed_size = compressed_size;
292  m_uncompressed_size = uncompressed_size;
293  m_entry_offset = rel_offset_loc_head;
294  m_filename = FilePath(filename);
295 
296  // the zipRead() should throw if it is false...
297  m_valid = true;
298 }
299 
300 
326 void ZipCentralDirectoryEntry::write(std::ostream& os)
327 {
331  if(m_filename.length() > 0x10000
332  || m_extra_field.size() > 0x10000
333  || m_comment.length() > 0x10000)
334  {
335  throw InvalidStateException("ZipCentralDirectoryEntry::write(): file name, comment, or extra field too large to save in a Zip file.");
336  }
337 
338 // Solaris defines _ILP32 for 32 bit platforms
339 #if !defined(_ILP32)
340  if(m_compressed_size >= 0x100000000ULL
341  || m_uncompressed_size >= 0x100000000ULL
342  || m_entry_offset >= 0x100000000LL)
343  {
344  // This represents really large files which we do not test at this point
345  throw InvalidStateException("ZipCentralDirectoryEntry::write(): The size of this file is too large to fit in a zip archive."); // LCOV_EXCL_LINE
346  }
347 #endif
348 
349  // define version
350  uint16_t writer_version = g_zip_format_version;
351  // including the "compatibility" code
352 #if defined(WIN32) || defined(_WIN32) || defined(__WIN32)
353  // MS-Windows
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);
366  if(m_is_directory)
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  uint32_t dostime(unix2dostime(m_unix_time));
381  uint32_t compressed_size(m_compressed_size);
382  uint32_t uncompressed_size(m_uncompressed_size);
383  uint16_t filename_len(filename.length());
384  uint16_t extra_field_len(m_extra_field.size());
385  uint16_t file_comment_len(m_comment.length());
386  uint16_t disk_num_start(0);
387  uint16_t intern_file_attr(0);
407  uint32_t extern_file_attr(m_is_directory ? 0x41FD0010 : 0x81B40000);
408  uint32_t rel_offset_loc_head(m_entry_offset);
409 
410  zipWrite(os, g_signature); // 32
411  zipWrite(os, writer_version); // 16
412  zipWrite(os, m_extract_version); // 16
414  zipWrite(os, compress_method); // 16
415  zipWrite(os, dostime); // 32
416  zipWrite(os, m_crc_32); // 32
417  zipWrite(os, compressed_size); // 32
418  zipWrite(os, uncompressed_size); // 32
419  zipWrite(os, filename_len); // 16
420  zipWrite(os, extra_field_len); // 16
421  zipWrite(os, file_comment_len); // 16
422  zipWrite(os, disk_num_start); // 16
423  zipWrite(os, intern_file_attr); // 16
424  zipWrite(os, extern_file_attr); // 32
425  zipWrite(os, rel_offset_loc_head); // 32
426  zipWrite(os, filename); // string
427  zipWrite(os, m_extra_field); // buffer
428  zipWrite(os, m_comment); // string
429 }
430 
431 
432 } // zipios namespace
433 
434 // Local Variables:
435 // mode: cpp
436 // indent-tabs-mode: nil
437 // c-basic-offset: 4
438 // tab-width: 4
439 // End:
440 
441 // vim: ts=4 sw=4 et
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_extra_field_len
uint16_t m_extra_field_len
Definition: zipcentraldirectoryentry.cpp:114
zipios::FileEntry::m_extra_field
buffer_t m_extra_field
Definition: fileentry.hpp:139
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_unix
const uint16_t g_unix
Definition: zipcentraldirectoryentry.cpp:64
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_alternate_vms
const uint16_t g_alternate_vms
Definition: zipcentraldirectoryentry.cpp:76
dostime
dostime_t dostime(int year, int month, int day, int hour, int minute, int second)
Definition: dostime.c:188
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_atari_st
const uint16_t g_atari_st
Definition: zipcentraldirectoryentry.cpp:66
unix2dostime
dostime_t unix2dostime(time_t unix_time)
Convert a Unix date to a DOS date.
Definition: dostime.c:219
zipios::FileEntry::m_valid
bool m_valid
Definition: fileentry.hpp:141
zipios::FileEntry::m_compression_level
CompressionLevel m_compression_level
Definition: fileentry.hpp:137
zipios::ZipCentralDirectoryEntry::~ZipCentralDirectoryEntry
virtual ~ZipCentralDirectoryEntry() override
Clean up the entry.
Definition: zipcentraldirectoryentry.cpp:169
zipios::FileEntry::m_uncompressed_size
size_t m_uncompressed_size
Definition: fileentry.hpp:133
zipios::ZipLocalEntry::m_compressed_size
size_t m_compressed_size
Definition: ziplocalentry.hpp:69
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_os400
const uint16_t g_os400
Definition: zipcentraldirectoryentry.cpp:79
zipios::FileEntry
A FileEntry represents an entry in a FileCollection.
Definition: fileentry.hpp:74
zipios::ZipCentralDirectoryEntry::write
virtual void write(std::ostream &os) override
Write a Central Directory Entry to the output stream.
Definition: zipcentraldirectoryentry.cpp:326
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_disk_num_start
uint16_t m_disk_num_start
Definition: zipcentraldirectoryentry.cpp:116
zipiosexceptions.hpp
Various exceptions used throughout the Zipios++ library, all based on zipios::Exception.
zipios::FileEntry::m_filename
FilePath m_filename
Definition: fileentry.hpp:131
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_signature
uint32_t m_signature
Definition: zipcentraldirectoryentry.cpp:104
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_compressed_size
uint32_t m_compressed_size
Definition: zipcentraldirectoryentry.cpp:111
zipios_common.hpp
Various functions used throughout the library.
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_vse
const uint16_t g_vse
Definition: zipcentraldirectoryentry.cpp:73
zipios::FileEntry::pointer_t
std::shared_ptr< FileEntry > pointer_t
Definition: fileentry.hpp:77
zipios::FileEntry::m_comment
std::string m_comment
Definition: fileentry.hpp:132
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_relative_offset_location_header
uint32_t m_relative_offset_location_header
Definition: zipcentraldirectoryentry.cpp:119
zipios::InvalidStateException
Exception used when it is not possible to move forward.
Definition: zipiosexceptions.hpp:107
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_dostime
uint32_t m_dostime
Definition: zipcentraldirectoryentry.cpp:109
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_extern_file_attr
uint32_t m_extern_file_attr
Definition: zipcentraldirectoryentry.cpp:118
zipios::FileEntry::COMPRESSION_LEVEL_NONE
static const CompressionLevel COMPRESSION_LEVEL_NONE
Definition: fileentry.hpp:90
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_signature
const uint32_t g_signature
The signature of a ZipCentralDirectoryEntry.
Definition: zipcentraldirectoryentry.cpp:57
dostime.h
Definitions for the MS-DOS to Unix time conversions.
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader
The header of a ZipCentralDirectoryEntry in a Zip archive.
Definition: zipcentraldirectoryentry.cpp:102
zipios::FilePath
Handle a file path and name and its statistics.
Definition: filepath.hpp:46
zipios::ZipLocalEntry::m_is_directory
bool m_is_directory
Definition: ziplocalentry.hpp:68
zipios::IOException
An IOException is used to signal an I/O error.
Definition: zipiosexceptions.hpp:70
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_cpm
const uint16_t g_cpm
Definition: zipcentraldirectoryentry.cpp:70
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_mvs
const uint16_t g_mvs
Definition: zipcentraldirectoryentry.cpp:72
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_filename_len
uint16_t m_filename_len
Definition: zipcentraldirectoryentry.cpp:113
zipios::FilePath::length
size_t length() const
Get the length of the string.
Definition: filepath.cpp:325
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_uncompressed_size
uint32_t m_uncompressed_size
Definition: zipcentraldirectoryentry.cpp:112
zipcentraldirectoryentry.hpp
Declaration of the zipios::ZipCentralDirectoryEntry, which represents a directory Zip archive entry.
zipios::ZipCentralDirectoryEntry::read
virtual void read(std::istream &is) override
Read a Central Directory entry.
Definition: zipcentraldirectoryentry.cpp:235
zipios::ZipLocalEntry::g_zip_format_version
static const uint16_t g_zip_format_version
Definition: ziplocalentry.hpp:46
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_extract_version
uint16_t m_extract_version
Definition: zipcentraldirectoryentry.cpp:106
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_os2_hpfs
const uint16_t g_os2_hpfs
Definition: zipcentraldirectoryentry.cpp:67
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_file_comment_len
uint16_t m_file_comment_len
Definition: zipcentraldirectoryentry.cpp:115
zipios::FileEntry::m_compress_method
StorageMethod m_compress_method
Definition: fileentry.hpp:136
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_macintosh
const uint16_t g_macintosh
Definition: zipcentraldirectoryentry.cpp:68
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_z_system
const uint16_t g_z_system
Definition: zipcentraldirectoryentry.cpp:69
zipios::ZipLocalEntry
An implementation of the FileEntry for Zip archives.
Definition: ziplocalentry.hpp:42
zipios::g_separator
const char g_separator
The character used as the filename separator.
Definition: zipios_common.cpp:51
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_osx
const uint16_t g_osx
Definition: zipcentraldirectoryentry.cpp:80
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_acorn_risc
const uint16_t g_acorn_risc
Definition: zipcentraldirectoryentry.cpp:74
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_compress_method
uint16_t m_compress_method
Definition: zipcentraldirectoryentry.cpp:108
zipios::ZipCentralDirectoryEntry::getHeaderSize
virtual size_t getHeaderSize() const override
Compute and return the current header size.
Definition: zipcentraldirectoryentry.cpp:181
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_writer_version
uint16_t m_writer_version
Definition: zipcentraldirectoryentry.cpp:105
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_vm_cms
const uint16_t g_vm_cms
Definition: zipcentraldirectoryentry.cpp:65
zipios::ZipLocalEntry::m_general_purpose_bitfield
uint16_t m_general_purpose_bitfield
Definition: ziplocalentry.hpp:67
zipios::zipWrite
void zipWrite(std::ostream &os, uint32_t const &value)
Definition: zipios_common.cpp:237
zipios::ZipLocalEntry::m_extract_version
uint16_t m_extract_version
Definition: ziplocalentry.hpp:66
zipios::zipRead
void zipRead(std::istream &is, uint32_t &value)
Definition: zipios_common.cpp:74
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_vfat
const uint16_t g_vfat
Definition: zipcentraldirectoryentry.cpp:75
zipios::ZipCentralDirectoryEntry::clone
virtual pointer_t clone() const override
Create a clone of this Central Directory entry.
Definition: zipcentraldirectoryentry.cpp:205
zipios::StorageMethod::STORED
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_general_purpose_bitfield
uint16_t m_general_purpose_bitfield
Definition: zipcentraldirectoryentry.cpp:107
zipios::FileEntry::m_unix_time
time_t m_unix_time
Definition: fileentry.hpp:134
zipios::ZipCentralDirectoryEntry::ZipCentralDirectoryEntry
ZipCentralDirectoryEntry()
Initializes a default ZipCentralDirectoryEntry object.
Definition: zipcentraldirectoryentry.cpp:144
dos2unixtime
time_t dos2unixtime(dostime_t dostime)
Convert a DOS time to a Unix time.
Definition: dostime.c:131
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_intern_file_attr
uint16_t m_intern_file_attr
Definition: zipcentraldirectoryentry.cpp:117
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_beos
const uint16_t g_beos
Definition: zipcentraldirectoryentry.cpp:77
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_tandem
const uint16_t g_tandem
Definition: zipcentraldirectoryentry.cpp:78
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_open_vms
const uint16_t g_open_vms
Definition: zipcentraldirectoryentry.cpp:63
zipios::FileEntry::m_entry_offset
std::streampos m_entry_offset
Definition: fileentry.hpp:135
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::ZipCentralDirectoryEntryHeader::m_crc_32
uint32_t m_crc_32
Definition: zipcentraldirectoryentry.cpp:110
zipios
The zipios namespace includes the Zipios++ library definitions.
Definition: backbuffer.cpp:35
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_windows
const uint16_t g_windows
Definition: zipcentraldirectoryentry.cpp:71
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_amiga
const uint16_t g_amiga
Definition: zipcentraldirectoryentry.cpp:62
zipios::anonymous_namespace{zipcentraldirectoryentry.cpp}::g_msdos
const uint16_t g_msdos
Definition: zipcentraldirectoryentry.cpp:61
zipios::FileEntry::m_crc_32
uint32_t m_crc_32
Definition: fileentry.hpp:138