zipios 2.3.4
Zipios -- a small C++ library providing easy access to .zip files.
ziplocalentry.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
29#include "ziplocalentry.hpp"
30
33
34#include "zipios_common.hpp"
35
36
37namespace zipios
38{
39
40
47namespace
48{
49
59uint32_t const g_signature = 0x04034b50;
60
61
71uint16_t const g_trailing_data_descriptor = 1 << 3;
72
73
89{
90 uint32_t m_signature;
94 uint32_t m_dosdatetime;
95 uint32_t m_crc_32;
100 //uint8_t m_filename[m_filename_len];
101 //uint8_t m_extra_field[m_extra_field_len];
102};
103
104
105} // no name namespace
106
107
108
127
128
138 : FileEntry(src)
139 , m_is_directory(src.isDirectory())
140{
141}
142
143
152{
153 // It makes sense to keep the clone() function for this class
154 // but since it is internal and never allocated as is (we use
155 // the ZipCentralDirectoryEntry instead) it is marked as
156 // non-reachable by the coverage tests
157 return std::make_shared<ZipLocalEntry>(*this); // LCOV_EXCL_LINE
158}
159
160
168
169
179{
180 return m_is_directory;
181}
182
183
201bool ZipLocalEntry::isEqual(FileEntry const & file_entry) const
202{
203 ZipLocalEntry const * const ze(dynamic_cast<ZipLocalEntry const * const>(&file_entry));
204 if(ze == nullptr)
205 {
206 return false;
207 }
208 return FileEntry::isEqual(file_entry)
212 //&& m_compressed_size == ze->m_compressed_size -- ignore in comparison
213}
214
215
225{
226 return m_compressed_size;
227}
228
229
240{
241 // Note that the structure is 32 bytes because of an alignment
242 // and attempting to use options to avoid the alignment would
243 // not be portable so we use a hard coded value (yuck!)
244 return 30 /* sizeof(ZipLocalEntryHeader) */
245 + m_filename.length() + (m_is_directory ? 1 : 0)
246 + m_extra_field.size();
247}
248
249
261{
262 m_compressed_size = size;
263}
264
265
275void ZipLocalEntry::setCrc(uint32_t crc)
276{
277 m_crc_32 = crc;
278 m_has_crc_32 = true;
279}
280
281
306{
307 return (m_general_purpose_bitfield & g_trailing_data_descriptor) != 0;
308}
309
310
328void ZipLocalEntry::read(std::istream & is)
329{
330 m_valid = false; // set to true upon successful completion.
331
332 // // Before reading anything we record the position in the stream
333 // // This is a field in the central directory entry, but not
334 // // in the local entry. After all, we know where we are, anyway.
335 // zlh.rel_offset_loc_head = is.tellg() ;
336
337 uint32_t signature(0);
338 zipRead(is, signature); // 32
339 if(g_signature != signature)
340 {
341 // put stream in error state and return
342 is.setstate(std::ios::failbit);
343 throw IOException("ZipLocalEntry::read() expected a signature but got some other data");
344 }
345
346 uint16_t compress_method(0);
347 uint32_t dosdatetime(0);
348 uint32_t compressed_size(0);
349 uint32_t uncompressed_size(0);
350 uint16_t filename_len(0);
351 uint16_t extra_field_len(0);
352 std::string filename;
353
354 // See the ZipLocalEntryHeader for more details
355 zipRead(is, m_extract_version); // 16
357 zipRead(is, compress_method); // 16
358 zipRead(is, dosdatetime); // 32
359 zipRead(is, m_crc_32); // 32
360 zipRead(is, compressed_size); // 32
361 zipRead(is, uncompressed_size); // 32
362 zipRead(is, filename_len); // 16
363 zipRead(is, extra_field_len); // 16
364 zipRead(is, filename, filename_len); // string
365 zipRead(is, m_extra_field, extra_field_len); // buffer
371 // the FilePath() will remove the trailing slash so make sure
372 // to defined the m_is_directory ahead of time!
373 m_is_directory = !filename.empty() && filename.back() == g_separator;
374
375 m_compress_method = static_cast<StorageMethod>(compress_method);
376 DOSDateTime t;
377 t.setDOSDateTime(dosdatetime);
379 m_compressed_size = compressed_size;
380 m_uncompressed_size = uncompressed_size;
381 m_filename = FilePath(filename);
382
383 m_valid = true;
384}
385
386
398void ZipLocalEntry::write(std::ostream & os)
399{
400 if(m_filename.length() > 0x10000
401 || m_extra_field.size() > 0x10000)
402 {
403 throw InvalidStateException("ZipLocalEntry::write(): file name or extra field too large to save in a Zip file.");
404 }
405
408#if INTPTR_MAX != INT32_MAX
409 if(m_compressed_size >= 0x100000000UL
410 || m_uncompressed_size >= 0x100000000UL)
411 {
412 // these are really big files, we do not currently test such so ignore in coverage
413 //
414 // Note: The compressed size is known at the end, we seek back to
415 // this header and re-save it with the info; thus the error
416 // is caught then if it was not out of bounds earlier.
417 throw InvalidStateException("The size of this file is too large to fit in a 32 bit zip archive."); // LCOV_EXCL_LINE
418 }
419#endif
420
421 std::string filename(m_filename);
423 {
424 filename += g_separator;
425 }
426
427 std::uint16_t compress_method(static_cast<uint8_t>(m_compress_method));
429 {
430 compress_method = static_cast<uint8_t>(StorageMethod::STORED);
431 }
432
433 DOSDateTime t;
435 std::uint32_t dosdatetime(t.getDOSDateTime()); // type could use DOSDateTime::dosdatetime_t
436 std::uint32_t compressed_size(m_compressed_size);
437 std::uint32_t uncompressed_size(m_uncompressed_size);
438 std::uint16_t filename_len(filename.length());
439 std::uint16_t extra_field_len(m_extra_field.size());
440
441 // See the ZipLocalEntryHeader for more details
442 zipWrite(os, g_signature); // 32
443 zipWrite(os, m_extract_version); // 16
445 zipWrite(os, compress_method); // 16
446 zipWrite(os, dosdatetime); // 32
447 zipWrite(os, m_crc_32); // 32
448 zipWrite(os, compressed_size); // 32
449 zipWrite(os, uncompressed_size); // 32
450 zipWrite(os, filename_len); // 16
451 zipWrite(os, extra_field_len); // 16
452 zipWrite(os, filename); // string
453 zipWrite(os, m_extra_field); // buffer
454}
455
456
457} // zipios namespace
458
459// Local Variables:
460// mode: cpp
461// indent-tabs-mode: nil
462// c-basic-offset: 4
463// tab-width: 4
464// End:
465
466// 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
buffer_t m_extra_field
CompressionLevel m_compression_level
static CompressionLevel const COMPRESSION_LEVEL_NONE
Definition fileentry.hpp:90
virtual bool isEqual(FileEntry const &file_entry) const
Compare two file entries for equality.
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.
An implementation of the FileEntry for Zip archives.
virtual pointer_t clone() const override
Create a clone of a ZipLocalEntry object.
virtual void setCrc(crc32_t crc) override
Save the CRC of the entry.
virtual void setCompressedSize(size_t size) override
Set the size when the file is compressed.
virtual ~ZipLocalEntry() override
Clean up a ZipLocalEntry object.
virtual void read(std::istream &is) override
Read one local entry from is.
virtual bool isDirectory() const override
Check whether the filename represents a directory.
uint16_t m_general_purpose_bitfield
virtual void write(std::ostream &os) override
Write a ZipLocalEntry to os.
ZipLocalEntry()
Create a default ZipLocalEntry objects.
virtual bool isEqual(FileEntry const &file_entry) const override
Compare two file entries for equality.
virtual size_t getHeaderSize() const override
Retrieve the size of the header.
bool hasTrailingDataDescriptor() const
Is there a trailing data descriptor?
virtual size_t getCompressedSize() const override
Retrieve the size of the file when compressed.
Define a type to manage date and time in MS-DOS format.
uint16_t const g_trailing_data_descriptor
A bit in the general purpose flags.
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)
Various functions used throughout the library.
Various exceptions used throughout the Zipios library, all based on zipios::Exception.
Declare the zipios::ZipLocalEntry class used to handle Zip entries.