zipios++  2.0.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 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 
29 #include "ziplocalentry.hpp"
30 
32 
33 #include "dostime.h"
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_dostime;
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)
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 dostime(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, dostime); // 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  m_unix_time = dos2unixtime(dostime);
384  m_compressed_size = compressed_size;
385  m_uncompressed_size = uncompressed_size;
386  m_filename = FilePath(filename);
387 
388  m_valid = true;
389 }
390 
391 
403 void ZipLocalEntry::write(std::ostream& os)
404 {
405  if(m_filename.length() > 0x10000
406  || m_extra_field.size() > 0x10000)
407  {
408  throw InvalidStateException("ZipLocalEntry::write(): file name or extra field too large to save in a Zip file.");
409  }
410 
413 // Solaris defines _ILP32 for 32 bit platforms
414 #if !defined(_ILP32)
415  if(m_compressed_size >= 0x100000000UL
416  || m_uncompressed_size >= 0x100000000UL)
417  {
418  // these are really big files, we do not currently test such so ignore in coverage
419  //
420  // Note: The compressed size is known at the end, we seek back to
421  // this header and resave it with the info; thus the error
422  // is caught then if it was not out of bounds earlier.
423  throw InvalidStateException("The size of this file is too large to fit in a zip archive."); // LCOV_EXCL_LINE
424  }
425 #endif
426 
427  std::string filename(m_filename);
428  if(m_is_directory)
429  {
430  filename += g_separator;
431  }
432 
433  uint16_t compress_method(static_cast<uint8_t>(m_compress_method));
435  {
436  compress_method = static_cast<uint8_t>(StorageMethod::STORED);
437  }
438 
439  uint32_t dostime(unix2dostime(m_unix_time));
440  uint32_t compressed_size(m_compressed_size);
441  uint32_t uncompressed_size(m_uncompressed_size);
442  uint16_t filename_len(filename.length());
443  uint16_t extra_field_len(m_extra_field.size());
444 
445  // See the ZipLocalEntryHeader for more details
446  zipWrite(os, g_signature); // 32
447  zipWrite(os, m_extract_version); // 16
449  zipWrite(os, compress_method); // 16
450  zipWrite(os, dostime); // 32
451  zipWrite(os, m_crc_32); // 32
452  zipWrite(os, compressed_size); // 32
453  zipWrite(os, uncompressed_size); // 32
454  zipWrite(os, filename_len); // 16
455  zipWrite(os, extra_field_len); // 16
456  zipWrite(os, filename); // string
457  zipWrite(os, m_extra_field); // buffer
458 }
459 
460 
461 } // zipios namespace
462 
463 // Local Variables:
464 // mode: cpp
465 // indent-tabs-mode: nil
466 // c-basic-offset: 4
467 // tab-width: 4
468 // End:
469 
470 // vim: ts=4 sw=4 et
StorageMethod m_compress_method
Definition: fileentry.hpp:136
virtual void setCompressedSize(size_t size) override
Set the size when the file is compressed.
Various exceptions used throughout the Zipios++ library, all based on zipios::Exception.
void zipRead(std::istream &is, uint32_t &value)
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
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.
dostime_t unix2dostime(time_t unix_time)
Convert a Unix date to a DOS date.
Definition: dostime.c:219
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:131
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:425
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
virtual size_t getCompressedSize() const override
Retrive 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.
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.
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
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
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.
size_t m_uncompressed_size
Definition: fileentry.hpp:133
std::shared_ptr< FileEntry > pointer_t
Definition: fileentry.hpp:77