zipios++  2.0.2
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 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 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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);
290  m_unix_time = dos2unixtime(dostime);
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
StorageMethod m_compress_method
Definition: fileentry.hpp:136
virtual size_t getHeaderSize() const override
Compute and return the current header size.
Various exceptions used throughout the Zipios++ library, all based on zipios::Exception.
void zipRead(std::istream &is, uint32_t &value)
virtual pointer_t clone() const override
Create a clone of this Central Directory entry.
buffer_t m_extra_field
Definition: fileentry.hpp:139
CompressionLevel m_compression_level
Definition: fileentry.hpp:137
StorageMethod
The types used with FileEntry::setMethod and FileEntry::getMethod.
Definition: fileentry.hpp:47
An implementation of the FileEntry for Zip archives.
dostime_t unix2dostime(time_t unix_time)
Convert a Unix date to a DOS date.
Definition: dostime.c:219
static CompressionLevel const COMPRESSION_LEVEL_NONE
Definition: fileentry.hpp:90
FilePath m_filename
Definition: fileentry.hpp:131
void zipWrite(std::ostream &os, uint32_t const &value)
dostime_t dostime(int year, int month, int day, int hour, int minute, int second)
Definition: dostime.c:188
char const g_separator
The character used as the filename separator.
An IOException is used to signal an I/O error.
ZipCentralDirectoryEntry()
Initializes a default ZipCentralDirectoryEntry object.
virtual ~ZipCentralDirectoryEntry() override
Clean up the entry.
time_t dos2unixtime(dostime_t dostime)
Convert a DOS time to a Unix time.
Definition: dostime.c:131
A FileEntry represents an entry in a FileCollection.
Definition: fileentry.hpp:74
Exception used when it is not possible to move forward.
uint16_t m_general_purpose_bitfield
Declaration of the zipios::ZipCentralDirectoryEntry, which represents a directory Zip archive entry...
Handle a file path and name and its statistics.
Definition: filepath.hpp:46
static uint16_t const g_zip_format_version
Definitions for the MS-DOS to Unix time conversions.
Various functions used throughout the library.
size_t length() const
Get the length of the string.
Definition: filepath.cpp:325
virtual void write(std::ostream &os) override
Write a Central Directory Entry to the output stream.
virtual void read(std::istream &is) override
Read a Central Directory entry.
size_t m_uncompressed_size
Definition: fileentry.hpp:133
std::streampos m_entry_offset
Definition: fileentry.hpp:135
std::shared_ptr< FileEntry > pointer_t
Definition: fileentry.hpp:77
uint32_t const g_signature
The signature of a ZipCentralDirectoryEntry.
std::string m_comment
Definition: fileentry.hpp:132