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
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;
109 uint32_t m_dostime;
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 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
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);
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
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
A FileEntry represents an entry in a FileCollection.
Definition: fileentry.hpp:75
std::shared_ptr< FileEntry > pointer_t
Definition: fileentry.hpp:77
StorageMethod m_compress_method
Definition: fileentry.hpp:136
std::string m_comment
Definition: fileentry.hpp:132
buffer_t m_extra_field
Definition: fileentry.hpp:139
size_t m_uncompressed_size
Definition: fileentry.hpp:133
CompressionLevel m_compression_level
Definition: fileentry.hpp:137
std::streampos m_entry_offset
Definition: fileentry.hpp:135
static CompressionLevel const COMPRESSION_LEVEL_NONE
Definition: fileentry.hpp:90
FilePath m_filename
Definition: fileentry.hpp:131
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:325
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
time_t dos2unixtime(dostime_t dostime)
Convert a DOS time to a Unix time.
Definition: dostime.c:131
dostime_t unix2dostime(time_t unix_time)
Convert a Unix date to a DOS date.
Definition: dostime.c:219
dostime_t dostime(int year, int month, int day, int hour, int minute, int second)
Definition: dostime.c:188
Definitions for the MS-DOS to Unix time conversions.
uint32_t const g_signature
The signature of a ZipCentralDirectoryEntry.
The zipios namespace includes the Zipios++ library definitions.
Definition: backbuffer.cpp:36
void zipRead(std::istream &is, uint32_t &value)
StorageMethod
The types used with FileEntry::setMethod and FileEntry::getMethod.
Definition: fileentry.hpp:48
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.