zipios  2.2.0
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-2019 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 
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  //, m_extract_version(g_zip_format_version) -- auto-init
126  //, m_general_purpose_bitfield(0) -- auto-init
127  //, m_is_directory(false)
128  //, m_compressed_size(0) -- auto-init
129 {
130 }
131 
132 
142  : FileEntry(src)
143  //, m_extract_version(g_zip_format_version) -- auto-init
144  //, m_general_purpose_bitfield(0) -- auto-init
145  , m_is_directory(src.isDirectory())
146  //, m_compressed_size(0) -- auto-init
147 {
148 }
149 
150 
159 {
160  // It makes sense to keep the clone() function for this class
161  // but since it is internal and never allocated as is (we use
162  // the ZipCentralDirectoryEntry instead) it is marked as none
163  // reachable by the coverage tests
164  return FileEntry::pointer_t(new ZipLocalEntry(*this)); // LCOV_EXCL_LINE
165 }
166 
167 
173 {
174 }
175 
176 
186 {
187  return m_is_directory;
188 }
189 
190 
208 bool ZipLocalEntry::isEqual(FileEntry const & file_entry) const
209 {
210  ZipLocalEntry const * const ze(dynamic_cast<ZipLocalEntry const * const>(&file_entry));
211  if(ze == nullptr)
212  {
213  return false;
214  }
215  return FileEntry::isEqual(file_entry)
218  && m_is_directory == ze->m_is_directory;
219  //&& m_compressed_size == ze->m_compressed_size -- ignore in comparison
220 }
221 
222 
232 {
233  return m_compressed_size;
234 }
235 
236 
247 {
248  // Note that the structure is 32 bytes because of an alignment
249  // and attempting to use options to avoid the alignment would
250  // not be portable so we use a hard coded value (yuck!)
251  return 30 /* sizeof(ZipLocalEntryHeader) */
252  + m_filename.length() + (m_is_directory ? 1 : 0)
253  + m_extra_field.size();
254 }
255 
256 
268 {
269  m_compressed_size = size;
270 }
271 
272 
282 void ZipLocalEntry::setCrc(uint32_t crc)
283 {
284  m_crc_32 = crc;
285  m_has_crc_32 = true;
286 }
287 
288 
313 {
315 }
316 
317 
335 void ZipLocalEntry::read(std::istream& is)
336 {
337  m_valid = false; // set to true upon successful completion.
338 
339  // // Before reading anything we record the position in the stream
340  // // This is a field in the central directory entry, but not
341  // // in the local entry. After all, we know where we are, anyway.
342  // zlh.rel_offset_loc_head = is.tellg() ;
343 
344  uint32_t signature;
345  zipRead(is, signature); // 32
346  if(g_signature != signature)
347  {
348  // put stream in error state and return
349  is.setstate(std::ios::failbit);
350  throw IOException("ZipLocalEntry::read() expected a signature but got some other data");
351  }
352 
353  uint16_t compress_method(0);
354  uint32_t dosdatetime(0);
355  uint32_t compressed_size(0);
356  uint32_t uncompressed_size(0);
357  uint16_t filename_len(0);
358  uint16_t extra_field_len(0);
359  std::string filename;
360 
361  // See the ZipLocalEntryHeader for more details
362  zipRead(is, m_extract_version); // 16
364  zipRead(is, compress_method); // 16
365  zipRead(is, dosdatetime); // 32
366  zipRead(is, m_crc_32); // 32
367  zipRead(is, compressed_size); // 32
368  zipRead(is, uncompressed_size); // 32
369  zipRead(is, filename_len); // 16
370  zipRead(is, extra_field_len); // 16
371  zipRead(is, filename, filename_len); // string
372  zipRead(is, m_extra_field, extra_field_len); // buffer
378  // the FilePath() will remove the trailing slash so make sure
379  // to defined the m_is_directory ahead of time!
380  m_is_directory = !filename.empty() && filename.back() == g_separator;
381 
382  m_compress_method = static_cast<StorageMethod>(compress_method);
383  DOSDateTime t;
384  t.setDOSDateTime(dosdatetime);
386  m_compressed_size = compressed_size;
387  m_uncompressed_size = uncompressed_size;
388  m_filename = FilePath(filename);
389 
390  m_valid = true;
391 }
392 
393 
405 void ZipLocalEntry::write(std::ostream& os)
406 {
407  if(m_filename.length() > 0x10000
408  || m_extra_field.size() > 0x10000)
409  {
410  throw InvalidStateException("ZipLocalEntry::write(): file name or extra field too large to save in a Zip file.");
411  }
412 
415 // Solaris defines _ILP32 for 32 bit platforms
416 #if !defined(_ILP32)
417  if(m_compressed_size >= 0x100000000UL
418  || m_uncompressed_size >= 0x100000000UL)
419  {
420  // these are really big files, we do not currently test such so ignore in coverage
421  //
422  // Note: The compressed size is known at the end, we seek back to
423  // this header and resave it with the info; thus the error
424  // is caught then if it was not out of bounds earlier.
425  throw InvalidStateException("The size of this file is too large to fit in a zip archive."); // LCOV_EXCL_LINE
426  }
427 #endif
428 
429  std::string filename(m_filename);
430  if(m_is_directory)
431  {
432  filename += g_separator;
433  }
434 
435  uint16_t compress_method(static_cast<uint8_t>(m_compress_method));
437  {
438  compress_method = static_cast<uint8_t>(StorageMethod::STORED);
439  }
440 
441  DOSDateTime t;
443  uint32_t dosdatetime(t.getDOSDateTime()); // type could use DOSDateTime::dosdatetime_t
444  uint32_t compressed_size(m_compressed_size);
445  uint32_t uncompressed_size(m_uncompressed_size);
446  uint16_t filename_len(filename.length());
447  uint16_t extra_field_len(m_extra_field.size());
448 
449  // See the ZipLocalEntryHeader for more details
450  zipWrite(os, g_signature); // 32
451  zipWrite(os, m_extract_version); // 16
453  zipWrite(os, compress_method); // 16
454  zipWrite(os, dosdatetime); // 32
455  zipWrite(os, m_crc_32); // 32
456  zipWrite(os, compressed_size); // 32
457  zipWrite(os, uncompressed_size); // 32
458  zipWrite(os, filename_len); // 16
459  zipWrite(os, extra_field_len); // 16
460  zipWrite(os, filename); // string
461  zipWrite(os, m_extra_field); // buffer
462 }
463 
464 
465 } // zipios namespace
466 
467 // Local Variables:
468 // mode: cpp
469 // indent-tabs-mode: nil
470 // c-basic-offset: 4
471 // tab-width: 4
472 // End:
473 
474 // vim: ts=4 sw=4 et
Define a type to manage date and time in MS-DOS format.
std::time_t getUnixTimestamp() const
Retrieve the DOSDateTime as a Unix timestamp.
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
Various exceptions used throughout the Zipios library, all based on zipios::Exception.
dosdatetime_t getDOSDateTime() const
Retrieve the DOSDateTime value as is.
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 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.
virtual bool isEqual(FileEntry const &file_entry) const
Compare two file entries for equality.
Definition: fileentry.cpp:431
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.
bool hasTrailingDataDescriptor() const
Is there a trailing data descriptor?
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.
size_t length() const
Get the length of the string.
Definition: filepath.cpp:327
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.
size_t m_uncompressed_size
Definition: fileentry.hpp:134
std::shared_ptr< FileEntry > pointer_t
Definition: fileentry.hpp:78