1//
2// ZipFileInfo.h
3//
4// Library: Zip
5// Package: Zip
6// Module: ZipFileInfo
7//
8// Definition of the ZipFileInfo class.
9//
10// Copyright (c) 2007, Applied Informatics Software Engineering GmbH.
11// and Contributors.
12//
13// SPDX-License-Identifier: BSL-1.0
14//
15
16
17#ifndef Zip_ZipFileInfo_INCLUDED
18#define Zip_ZipFileInfo_INCLUDED
19
20
21#include "Poco/Zip/Zip.h"
22#include "Poco/Zip/ZipCommon.h"
23#include "Poco/Zip/ZipUtil.h"
24
25
26namespace Poco {
27namespace Zip {
28
29
30class ZipLocalFileHeader;
31
32
33class Zip_API ZipFileInfo
34 /// Stores a Zip directory entry of a file
35{
36public:
37 static const char HEADER[ZipCommon::HEADER_SIZE];
38
39 ZipFileInfo(const ZipLocalFileHeader& header);
40 /// Creates a ZipFileInfo from a ZipLocalFileHeader
41
42 ZipFileInfo(std::istream& in, bool assumeHeaderRead);
43 /// Creates the ZipFileInfo by parsing the input stream.
44 /// If assumeHeaderRead is true we assume that the first 4 bytes were already read outside.
45
46 ~ZipFileInfo();
47 /// Destroys the ZipFileInfo.
48
49 ZipCommon::CompressionMethod getCompressionMethod() const;
50
51 bool isEncrypted() const;
52
53 const Poco::DateTime& lastModifiedAt() const;
54
55 Poco::UInt32 getCRC() const;
56
57 Poco::UInt32 getHeaderSize() const;
58 /// Returns the total size of the header including filename + other additional fields
59
60 Poco::UInt64 getCompressedSize() const;
61
62 Poco::UInt64 getUncompressedSize() const;
63
64 Poco::UInt64 getOffset() const;
65 /// Where on the disk starts the localheader. Combined with the disk number gives the exact location of the header
66
67 const std::string& getFileName() const;
68
69 bool isFile() const;
70
71 bool isDirectory() const;
72
73 bool hasExtraField() const;
74
75 const std::string& getExtraField() const;
76
77 const std::string& getFileComment() const;
78
79 void getVersionMadeBy(int& major, int& minor) const;
80 /// The ZIP version used to create the file
81
82 void getRequiredVersion(int& major, int& minor) const;
83 /// The minimum version required to extract the data
84
85 ZipCommon::HostSystem getHostSystem() const;
86
87 Poco::UInt16 getDiskNumberStart() const;
88 /// The number of the disk on which this file begins (multidisk archives)
89
90 ZipCommon::FileType getFileType() const;
91 /// Binary or ASCII file?
92
93 std::string createHeader() const;
94
95 void setOffset(Poco::UInt64 val);
96
97 bool needsZip64() const;
98
99 void setZip64Data();
100
101private:
102
103 void setCRC(Poco::UInt32 val);
104
105 void setCompressedSize(Poco::UInt64 val);
106
107 void setUncompressedSize(Poco::UInt64 val);
108
109 void setCompressionMethod(ZipCommon::CompressionMethod cm);
110
111 void setCompressionLevel(ZipCommon::CompressionLevel cl);
112
113 void setRequiredVersion(int major, int minor);
114
115 void setHostSystem(ZipCommon::HostSystem hs);
116
117 void setLastModifiedAt(const Poco::DateTime& dt);
118
119 void setEncryption(bool val);
120
121 void setFileNameLength(Poco::UInt16 size);
122
123 void setFileName(const std::string& str);
124
125 void setExternalFileAttributes(Poco::UInt32 attrs);
126
127 void parse(std::istream& in, bool assumeHeaderRead);
128
129 void parseDateTime();
130
131 Poco::UInt32 getCRCFromHeader() const;
132
133 Poco::UInt32 getCompressedSizeFromHeader() const;
134
135 Poco::UInt32 getUncompressedSizeFromHeader() const;
136
137 Poco::UInt32 getOffsetFromHeader() const;
138
139 Poco::UInt16 getFileNameLength() const;
140
141 Poco::UInt16 getExtraFieldLength() const;
142
143 Poco::UInt16 getFileCommentLength() const;
144
145 Poco::UInt32 getExternalFileAttributes() const;
146
147 void setUnixAttributes();
148
149private:
150 enum
151 {
152 HEADER_POS = 0,
153 VERSIONMADEBY_POS = HEADER_POS + ZipCommon::HEADER_SIZE,
154 VERSIONMADEBY_SIZE = 2,
155 VERSION_NEEDED_POS = VERSIONMADEBY_POS + VERSIONMADEBY_SIZE,
156 VERSION_NEEDED_SIZE = 2,
157 GENERAL_PURPOSE_POS = VERSION_NEEDED_POS + VERSION_NEEDED_SIZE,
158 GENERAL_PURPOSE_SIZE = 2,
159 COMPR_METHOD_POS = GENERAL_PURPOSE_POS + GENERAL_PURPOSE_SIZE,
160 COMPR_METHOD_SIZE = 2,
161 LASTMODFILETIME_POS = COMPR_METHOD_POS + COMPR_METHOD_SIZE,
162 LASTMODFILETIME_SIZE = 2,
163 LASTMODFILEDATE_POS = LASTMODFILETIME_POS + LASTMODFILETIME_SIZE,
164 LASTMODFILEDATE_SIZE = 2,
165 CRC32_POS = LASTMODFILEDATE_POS + LASTMODFILEDATE_SIZE,
166 CRC32_SIZE = 4,
167 COMPRESSED_SIZE_POS = CRC32_POS + CRC32_SIZE,
168 COMPRESSED_SIZE_SIZE = 4,
169 UNCOMPRESSED_SIZE_POS = COMPRESSED_SIZE_POS + COMPRESSED_SIZE_SIZE,
170 UNCOMPRESSED_SIZE_SIZE = 4,
171 FILENAME_LENGTH_POS = UNCOMPRESSED_SIZE_POS + UNCOMPRESSED_SIZE_SIZE,
172 FILENAME_LENGTH_SIZE = 2,
173 EXTRAFIELD_LENGTH_POS = FILENAME_LENGTH_POS + FILENAME_LENGTH_SIZE,
174 EXTRAFIELD_LENGTH_SIZE = 2,
175 FILECOMMENT_LENGTH_POS = EXTRAFIELD_LENGTH_POS + EXTRAFIELD_LENGTH_SIZE,
176 FILECOMMENT_LENGTH_SIZE = 2,
177 DISKNUMBERSTART_POS = FILECOMMENT_LENGTH_POS + FILECOMMENT_LENGTH_SIZE,
178 DISKNUMBERSTART_SIZE = 2,
179 INTERNALFILE_ATTR_POS = DISKNUMBERSTART_POS + DISKNUMBERSTART_SIZE,
180 INTERNALFILE_ATTR_SIZE = 2,
181 EXTERNALFILE_ATTR_POS = INTERNALFILE_ATTR_POS + INTERNALFILE_ATTR_SIZE,
182 EXTERNALFILE_ATTR_SIZE = 4,
183 RELATIVEOFFSETLOCALHEADER_POS = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE,
184 RELATIVEOFFSETLOCALHEADER_SIZE = 4,
185 FULLHEADER_SIZE = 46,
186
187 EXTRA_DATA_TAG_SIZE = 2,
188 EXTRA_DATA_TAG_POS = 0,
189 EXTRA_DATA_SIZE_SIZE = 2,
190 EXTRA_DATA_SIZE_POS = EXTRA_DATA_TAG_POS + EXTRA_DATA_TAG_SIZE,
191 EXTRA_DATA_POS = EXTRA_DATA_SIZE_POS + EXTRA_DATA_SIZE_SIZE,
192 EXTRA_DATA_UNCOMPRESSED_SIZE_SIZE = 8,
193 EXTRA_DATA_COMPRESSED_SIZE_SIZE = 8,
194 EXTRA_DATA_OFFSET_SIZE = 8,
195 FULLEXTRA_DATA_SIZE = 28
196 };
197
198 enum
199 {
200 DEFAULT_UNIX_FILE_MODE = 0640,
201 DEFAULT_UNIX_DIR_MODE = 0755
202 };
203
204 char _rawInfo[FULLHEADER_SIZE];
205 Poco::UInt32 _crc32;
206 Poco::UInt64 _compressedSize;
207 Poco::UInt64 _uncompressedSize;
208 Poco::UInt64 _localHeaderOffset;
209 std::string _fileName;
210 Poco::DateTime _lastModifiedAt;
211 std::string _extraField;
212 std::string _fileComment;
213};
214
215
216inline Poco::UInt32 ZipFileInfo::getCRCFromHeader() const
217{
218 return ZipUtil::get32BitValue(_rawInfo, CRC32_POS);
219}
220
221
222inline Poco::UInt32 ZipFileInfo::getCompressedSizeFromHeader() const
223{
224 return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_SIZE_POS);
225}
226
227
228inline Poco::UInt32 ZipFileInfo::getUncompressedSizeFromHeader() const
229{
230 return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS);
231}
232
233inline Poco::UInt32 ZipFileInfo::getOffsetFromHeader() const
234{
235 return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
236}
237
238
239inline void ZipFileInfo::parseDateTime()
240{
241 _lastModifiedAt = ZipUtil::parseDateTime(_rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
242}
243
244
245inline ZipCommon::CompressionMethod ZipFileInfo::getCompressionMethod() const
246{
247 return static_cast<ZipCommon::CompressionMethod>(ZipUtil::get16BitValue(_rawInfo, COMPR_METHOD_POS));
248}
249
250
251inline bool ZipFileInfo::isEncrypted() const
252{
253 // bit 0 indicates encryption
254 return ((ZipUtil::get16BitValue(_rawInfo, GENERAL_PURPOSE_POS) & 0x0001) != 0);
255}
256
257
258inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const
259{
260 return _lastModifiedAt;
261}
262
263
264inline Poco::UInt64 ZipFileInfo::getOffset() const
265{
266 return _localHeaderOffset;
267}
268
269
270inline Poco::UInt32 ZipFileInfo::getCRC() const
271{
272 return _crc32;
273}
274
275
276inline Poco::UInt64 ZipFileInfo::getCompressedSize() const
277{
278 return _compressedSize;
279}
280
281
282inline Poco::UInt64 ZipFileInfo::getUncompressedSize() const
283{
284 return _uncompressedSize;
285}
286
287
288inline const std::string& ZipFileInfo::getFileName() const
289{
290 return _fileName;
291}
292
293
294inline bool ZipFileInfo::isFile() const
295{
296 return !isDirectory();
297}
298
299
300inline bool ZipFileInfo::isDirectory() const
301{
302 poco_assert_dbg(!_fileName.empty());
303 return getUncompressedSize() == 0 && _fileName[_fileName.length()-1] == '/';
304}
305
306
307inline Poco::UInt16 ZipFileInfo::getFileNameLength() const
308{
309 return ZipUtil::get16BitValue(_rawInfo, FILENAME_LENGTH_POS);
310}
311
312
313inline Poco::UInt16 ZipFileInfo::getExtraFieldLength() const
314{
315 return ZipUtil::get16BitValue(_rawInfo, EXTRAFIELD_LENGTH_POS);
316}
317
318
319inline bool ZipFileInfo::hasExtraField() const
320{
321 return getExtraFieldLength() > 0;
322}
323
324
325inline const std::string& ZipFileInfo::getExtraField() const
326{
327 return _extraField;
328}
329
330
331inline const std::string& ZipFileInfo::getFileComment() const
332{
333 return _fileComment;
334}
335
336
337inline Poco::UInt16 ZipFileInfo::getFileCommentLength() const
338{
339 return ZipUtil::get16BitValue(_rawInfo, FILECOMMENT_LENGTH_POS);
340}
341
342
343inline void ZipFileInfo::getVersionMadeBy(int& major, int& minor) const
344{
345 major = (_rawInfo[VERSIONMADEBY_POS]/10);
346 minor = (_rawInfo[VERSIONMADEBY_POS]%10);
347}
348
349
350inline void ZipFileInfo::getRequiredVersion(int& major, int& minor) const
351{
352 major = (_rawInfo[VERSION_NEEDED_POS]/10);
353 minor = (_rawInfo[VERSION_NEEDED_POS]%10);
354}
355
356
357inline ZipCommon::HostSystem ZipFileInfo::getHostSystem() const
358{
359 return static_cast<ZipCommon::HostSystem>(_rawInfo[VERSION_NEEDED_POS + 1]);
360}
361
362
363inline Poco::UInt16 ZipFileInfo::getDiskNumberStart() const
364{
365 return ZipUtil::get16BitValue(_rawInfo, DISKNUMBERSTART_POS);
366}
367
368
369inline ZipCommon::FileType ZipFileInfo::getFileType() const
370{
371 return static_cast<ZipCommon::FileType>(_rawInfo[INTERNALFILE_ATTR_POS] & 0x01);
372}
373
374
375inline Poco::UInt32 ZipFileInfo::getExternalFileAttributes() const
376{
377 return ZipUtil::get32BitValue(_rawInfo, EXTERNALFILE_ATTR_POS);
378}
379
380
381inline Poco::UInt32 ZipFileInfo::getHeaderSize() const
382{
383 return FULLHEADER_SIZE + getFileNameLength() + getExtraFieldLength() + getFileCommentLength();
384}
385
386
387inline bool ZipFileInfo::needsZip64() const
388{
389 return _localHeaderOffset >= ZipCommon::ZIP64_MAGIC || _compressedSize >= ZipCommon::ZIP64_MAGIC || _uncompressedSize >= ZipCommon::ZIP64_MAGIC;
390}
391
392
393inline void ZipFileInfo::setZip64Data()
394{
395 if (needsZip64())
396 {
397 setRequiredVersion(4, 5);
398 char data[FULLEXTRA_DATA_SIZE];
399 ZipUtil::set16BitValue(ZipCommon::ZIP64_EXTRA_ID, data, EXTRA_DATA_TAG_POS);
400 Poco::UInt16 pos = EXTRA_DATA_POS;
401 if (_uncompressedSize >= ZipCommon::ZIP64_MAGIC)
402 {
403 ZipUtil::set64BitValue(_uncompressedSize, data, pos); pos += 8;
404 }
405 if (_compressedSize >= ZipCommon::ZIP64_MAGIC)
406 {
407 ZipUtil::set64BitValue(_compressedSize, data, pos); pos += 8;
408 }
409 if (_localHeaderOffset >= ZipCommon::ZIP64_MAGIC)
410 {
411 ZipUtil::set64BitValue(_localHeaderOffset, data, pos); pos += 8;
412 }
413 ZipUtil::set16BitValue(pos - EXTRA_DATA_POS, data, EXTRA_DATA_SIZE_POS);
414 _extraField = std::string(data, pos);
415 ZipUtil::set16BitValue(pos, _rawInfo, EXTRAFIELD_LENGTH_POS);
416 }
417}
418
419
420inline void ZipFileInfo::setCRC(Poco::UInt32 val)
421{
422 _crc32 = val;
423 ZipUtil::set32BitValue(val, _rawInfo, CRC32_POS);
424}
425
426
427inline void ZipFileInfo::setOffset(Poco::UInt64 val)
428{
429 _localHeaderOffset = val;
430 ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawInfo, RELATIVEOFFSETLOCALHEADER_POS);
431}
432
433
434inline void ZipFileInfo::setCompressedSize(Poco::UInt64 val)
435{
436 _compressedSize = val;
437 ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawInfo, COMPRESSED_SIZE_POS);
438}
439
440
441inline void ZipFileInfo::setUncompressedSize(Poco::UInt64 val)
442{
443 _uncompressedSize = val;
444 ZipUtil::set32BitValue(val >= ZipCommon::ZIP64_MAGIC ? ZipCommon::ZIP64_MAGIC : static_cast<Poco::UInt32>(val), _rawInfo, UNCOMPRESSED_SIZE_POS);
445}
446
447
448inline void ZipFileInfo::setCompressionMethod(ZipCommon::CompressionMethod cm)
449{
450 ZipUtil::set16BitValue(static_cast<Poco::UInt16>(cm), _rawInfo, COMPR_METHOD_POS);
451}
452
453
454inline void ZipFileInfo::setCompressionLevel(ZipCommon::CompressionLevel cl)
455{
456 // bit 1 and 2 indicate the level
457 Poco::UInt16 val = static_cast<Poco::UInt16>(cl);
458 val <<= 1;
459 Poco::UInt16 mask = 0xfff9;
460 _rawInfo[GENERAL_PURPOSE_POS] = ((_rawInfo[GENERAL_PURPOSE_POS] & mask) | val);
461}
462
463
464inline void ZipFileInfo::setFileNameLength(Poco::UInt16 size)
465{
466 ZipUtil::set16BitValue(size, _rawInfo, FILENAME_LENGTH_POS);
467}
468
469
470inline void ZipFileInfo::setHostSystem(ZipCommon::HostSystem hs)
471{
472 _rawInfo[VERSIONMADEBY_POS + 1] = static_cast<char>(hs);
473 _rawInfo[VERSION_NEEDED_POS + 1] = static_cast<char>(hs);
474}
475
476
477inline void ZipFileInfo::setRequiredVersion(int major, int minor)
478{
479 poco_assert (minor < 10);
480 poco_assert (major < 24);
481 Poco::UInt8 val = static_cast<unsigned char>(major)*10+static_cast<unsigned char>(minor);
482 _rawInfo[VERSIONMADEBY_POS] = static_cast<char>(val);
483 _rawInfo[VERSION_NEEDED_POS] = static_cast<char>(val);
484}
485
486
487inline void ZipFileInfo::setLastModifiedAt(const Poco::DateTime& dt)
488{
489 _lastModifiedAt = dt;
490 ZipUtil::setDateTime(dt, _rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS);
491}
492
493
494inline void ZipFileInfo::setEncryption(bool val)
495{
496 if (val)
497 _rawInfo[GENERAL_PURPOSE_POS] |= 0x01;
498 else
499 _rawInfo[GENERAL_PURPOSE_POS] &= 0xfe;
500}
501
502
503inline void ZipFileInfo::setFileName(const std::string& str)
504{
505 _fileName = str;
506 setFileNameLength(static_cast<Poco::UInt16>(str.size()));
507}
508
509
510inline void ZipFileInfo::setExternalFileAttributes(Poco::UInt32 attrs)
511{
512 ZipUtil::set32BitValue(attrs, _rawInfo, EXTERNALFILE_ATTR_POS);
513}
514
515
516} } // namespace Poco::Zip
517
518
519#endif // Zip_ZipFileInfo_INCLUDED
520