zipios  2.3.2
Zipios -- a small C++ library that provides 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 
32 #include "zipios/dosdatetime.hpp"
33 
34 #include "zipios_common.hpp"
35 
36 
37 namespace zipios
38 {
39 
40 
47 namespace
48 {
49 
59 uint32_t const g_signature = 0x04034b50;
60 
61 
71 uint16_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;
98  uint16_t m_filename_len;
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 
124  : FileEntry(FilePath(""))
125 {
126 }
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 
166 {
167 }
168 
169 
179 {
180  return m_is_directory;
181 }
182 
183 
201 bool 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)
211  && m_is_directory == ze->m_is_directory;
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 
275 void ZipLocalEntry::setCrc(uint32_t crc)
276 {
277  m_crc_32 = crc;
278  m_has_crc_32 = true;
279 }
280 
281 
306 {
308 }
309 
310 
328 void 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 
398 void 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);
422  if(m_is_directory)
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
Define a type to manage date and time in MS-DOS format.
StorageMethod m_compress_method
Definition: fileentry.hpp:137
virtual void setCompressedSize(size_t size) override
Set the size when the file is compressed.
The zipios namespace includes the Zipios library definitions.
Definition: backbuffer.cpp:35
bool hasTrailingDataDescriptor() const
Is there a trailing data descriptor?
size_t length() const
Get the length of the string.
Definition: filepath.cpp:336
dosdatetime_t getDOSDateTime() const
Retrieve the DOSDateTime value as is.
Various exceptions used throughout the Zipios library, all based on zipios::Exception.
std::time_t getUnixTimestamp() const
Retrieve the DOSDateTime as a Unix timestamp.
void setUnixTimestamp(std::time_t unix_timestamp)
Set the DOSDateTime value from a Unix timestamp.
void zipRead(std::istream &is, uint32_t &value)
buffer_t m_extra_field
Definition: fileentry.hpp:140
CompressionLevel m_compression_level
Definition: fileentry.hpp:138
StorageMethod
The types used with FileEntry::setMethod and FileEntry::getMethod.
Definition: fileentry.hpp:48
virtual bool isEqual(FileEntry const &file_entry) const
Compare two file entries for equality.
Definition: fileentry.cpp:430
virtual size_t getHeaderSize() const override
Retrieve the size of the header.
An implementation of the FileEntry for Zip archives.
uint32_t const g_signature
The signature of a local entry.
virtual pointer_t clone() const override
Create a clone of a ZipLocalEntry object.
static CompressionLevel const COMPRESSION_LEVEL_NONE
Definition: fileentry.hpp:90
FilePath m_filename
Definition: fileentry.hpp:132
virtual bool isDirectory() const override
Check whether the filename represents a directory.
ZipLocalEntry()
Create a default ZipLocalEntry objects.
void zipWrite(std::ostream &os, uint32_t const &value)
virtual size_t getCompressedSize() const override
Retrieve the size of the file when compressed.
char const g_separator
The character used as the filename separator.
An IOException is used to signal an I/O error.
virtual void write(std::ostream &os) override
Write a ZipLocalEntry to os.
Declare the zipios::ZipLocalEntry class used to handle Zip entries.
virtual void setCrc(crc32_t crc) override
Save the CRC of the entry.
A FileEntry represents an entry in a FileCollection.
Definition: fileentry.hpp:75
Exception used when it is not possible to move forward.
virtual void read(std::istream &is) override
Read one local entry from is.
uint16_t m_general_purpose_bitfield
Handle a file path and name and its statistics.
Definition: filepath.hpp:46
Various functions used throughout the library.
uint16_t const g_trailing_data_descriptor
A bit in the general purpose flags.
virtual ~ZipLocalEntry() override
Clean up a ZipLocalEntry object.
virtual bool isEqual(FileEntry const &file_entry) const override
Compare two file entries for equality.
void setDOSDateTime(dosdatetime_t datetime)
Set the DOSDateTime value as is.
std::shared_ptr< FileEntry > pointer_t
Definition: fileentry.hpp:78
std::size_t m_uncompressed_size
Definition: fileentry.hpp:134