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-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
29#include "ziplocalentry.hpp"
30
32
33#include "dostime.h"
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_dostime;
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
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
208bool 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)
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
282void ZipLocalEntry::setCrc(uint32_t crc)
283{
284 m_crc_32 = crc;
285 m_has_crc_32 = true;
286}
287
288
313{
314 return (m_general_purpose_bitfield & g_trailing_data_descriptor) != 0;
315}
316
317
335void 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);
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
403void 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);
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
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
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
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
static CompressionLevel const COMPRESSION_LEVEL_NONE
Definition: fileentry.hpp:90
FilePath m_filename
Definition: fileentry.hpp:131
virtual bool isEqual(FileEntry const &file_entry) const
Compare two file entries for equality.
Definition: fileentry.cpp:425
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.
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
Retrive the size of the file when compressed.
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.
uint16_t const g_trailing_data_descriptor
A bit in the general purpose flags.
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)
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.