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 | |
26 | namespace Poco { |
27 | namespace Zip { |
28 | |
29 | |
30 | class ; |
31 | |
32 | |
33 | class Zip_API ZipFileInfo |
34 | /// Stores a Zip directory entry of a file |
35 | { |
36 | public: |
37 | static const char [ZipCommon::HEADER_SIZE]; |
38 | |
39 | (const ZipLocalFileHeader& ); |
40 | /// Creates a ZipFileInfo from a ZipLocalFileHeader |
41 | |
42 | ZipFileInfo(std::istream& in, bool ); |
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 () const; |
94 | |
95 | void setOffset(Poco::UInt64 val); |
96 | |
97 | bool needsZip64() const; |
98 | |
99 | void setZip64Data(); |
100 | |
101 | private: |
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 ); |
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 | |
149 | private: |
150 | enum |
151 | { |
152 | = 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 | = FILENAME_LENGTH_POS + FILENAME_LENGTH_SIZE, |
174 | = 2, |
175 | = EXTRAFIELD_LENGTH_POS + EXTRAFIELD_LENGTH_SIZE, |
176 | = 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 | = EXTERNALFILE_ATTR_POS + EXTERNALFILE_ATTR_SIZE, |
184 | = 4, |
185 | = 46, |
186 | |
187 | = 2, |
188 | = 0, |
189 | = 2, |
190 | = EXTRA_DATA_TAG_POS + EXTRA_DATA_TAG_SIZE, |
191 | = EXTRA_DATA_SIZE_POS + EXTRA_DATA_SIZE_SIZE, |
192 | = 8, |
193 | = 8, |
194 | = 8, |
195 | = 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 ; |
209 | std::string _fileName; |
210 | Poco::DateTime _lastModifiedAt; |
211 | std::string ; |
212 | std::string ; |
213 | }; |
214 | |
215 | |
216 | inline Poco::UInt32 ZipFileInfo::() const |
217 | { |
218 | return ZipUtil::get32BitValue(_rawInfo, CRC32_POS); |
219 | } |
220 | |
221 | |
222 | inline Poco::UInt32 ZipFileInfo::() const |
223 | { |
224 | return ZipUtil::get32BitValue(_rawInfo, COMPRESSED_SIZE_POS); |
225 | } |
226 | |
227 | |
228 | inline Poco::UInt32 ZipFileInfo::() const |
229 | { |
230 | return ZipUtil::get32BitValue(_rawInfo, UNCOMPRESSED_SIZE_POS); |
231 | } |
232 | |
233 | inline Poco::UInt32 ZipFileInfo::() const |
234 | { |
235 | return ZipUtil::get32BitValue(_rawInfo, RELATIVEOFFSETLOCALHEADER_POS); |
236 | } |
237 | |
238 | |
239 | inline void ZipFileInfo::parseDateTime() |
240 | { |
241 | _lastModifiedAt = ZipUtil::parseDateTime(_rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS); |
242 | } |
243 | |
244 | |
245 | inline ZipCommon::CompressionMethod ZipFileInfo::getCompressionMethod() const |
246 | { |
247 | return static_cast<ZipCommon::CompressionMethod>(ZipUtil::get16BitValue(_rawInfo, COMPR_METHOD_POS)); |
248 | } |
249 | |
250 | |
251 | inline bool ZipFileInfo::isEncrypted() const |
252 | { |
253 | // bit 0 indicates encryption |
254 | return ((ZipUtil::get16BitValue(_rawInfo, GENERAL_PURPOSE_POS) & 0x0001) != 0); |
255 | } |
256 | |
257 | |
258 | inline const Poco::DateTime& ZipFileInfo::lastModifiedAt() const |
259 | { |
260 | return _lastModifiedAt; |
261 | } |
262 | |
263 | |
264 | inline Poco::UInt64 ZipFileInfo::getOffset() const |
265 | { |
266 | return _localHeaderOffset; |
267 | } |
268 | |
269 | |
270 | inline Poco::UInt32 ZipFileInfo::getCRC() const |
271 | { |
272 | return _crc32; |
273 | } |
274 | |
275 | |
276 | inline Poco::UInt64 ZipFileInfo::getCompressedSize() const |
277 | { |
278 | return _compressedSize; |
279 | } |
280 | |
281 | |
282 | inline Poco::UInt64 ZipFileInfo::getUncompressedSize() const |
283 | { |
284 | return _uncompressedSize; |
285 | } |
286 | |
287 | |
288 | inline const std::string& ZipFileInfo::getFileName() const |
289 | { |
290 | return _fileName; |
291 | } |
292 | |
293 | |
294 | inline bool ZipFileInfo::isFile() const |
295 | { |
296 | return !isDirectory(); |
297 | } |
298 | |
299 | |
300 | inline bool ZipFileInfo::isDirectory() const |
301 | { |
302 | poco_assert_dbg(!_fileName.empty()); |
303 | return getUncompressedSize() == 0 && _fileName[_fileName.length()-1] == '/'; |
304 | } |
305 | |
306 | |
307 | inline Poco::UInt16 ZipFileInfo::getFileNameLength() const |
308 | { |
309 | return ZipUtil::get16BitValue(_rawInfo, FILENAME_LENGTH_POS); |
310 | } |
311 | |
312 | |
313 | inline Poco::UInt16 ZipFileInfo::() const |
314 | { |
315 | return ZipUtil::get16BitValue(_rawInfo, EXTRAFIELD_LENGTH_POS); |
316 | } |
317 | |
318 | |
319 | inline bool ZipFileInfo::() const |
320 | { |
321 | return getExtraFieldLength() > 0; |
322 | } |
323 | |
324 | |
325 | inline const std::string& ZipFileInfo::() const |
326 | { |
327 | return _extraField; |
328 | } |
329 | |
330 | |
331 | inline const std::string& ZipFileInfo::() const |
332 | { |
333 | return _fileComment; |
334 | } |
335 | |
336 | |
337 | inline Poco::UInt16 ZipFileInfo::() const |
338 | { |
339 | return ZipUtil::get16BitValue(_rawInfo, FILECOMMENT_LENGTH_POS); |
340 | } |
341 | |
342 | |
343 | inline void ZipFileInfo::getVersionMadeBy(int& major, int& minor) const |
344 | { |
345 | major = (_rawInfo[VERSIONMADEBY_POS]/10); |
346 | minor = (_rawInfo[VERSIONMADEBY_POS]%10); |
347 | } |
348 | |
349 | |
350 | inline 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 | |
357 | inline ZipCommon::HostSystem ZipFileInfo::getHostSystem() const |
358 | { |
359 | return static_cast<ZipCommon::HostSystem>(_rawInfo[VERSION_NEEDED_POS + 1]); |
360 | } |
361 | |
362 | |
363 | inline Poco::UInt16 ZipFileInfo::getDiskNumberStart() const |
364 | { |
365 | return ZipUtil::get16BitValue(_rawInfo, DISKNUMBERSTART_POS); |
366 | } |
367 | |
368 | |
369 | inline ZipCommon::FileType ZipFileInfo::getFileType() const |
370 | { |
371 | return static_cast<ZipCommon::FileType>(_rawInfo[INTERNALFILE_ATTR_POS] & 0x01); |
372 | } |
373 | |
374 | |
375 | inline Poco::UInt32 ZipFileInfo::getExternalFileAttributes() const |
376 | { |
377 | return ZipUtil::get32BitValue(_rawInfo, EXTERNALFILE_ATTR_POS); |
378 | } |
379 | |
380 | |
381 | inline Poco::UInt32 ZipFileInfo::() const |
382 | { |
383 | return FULLHEADER_SIZE + getFileNameLength() + getExtraFieldLength() + getFileCommentLength(); |
384 | } |
385 | |
386 | |
387 | inline bool ZipFileInfo::needsZip64() const |
388 | { |
389 | return _localHeaderOffset >= ZipCommon::ZIP64_MAGIC || _compressedSize >= ZipCommon::ZIP64_MAGIC || _uncompressedSize >= ZipCommon::ZIP64_MAGIC; |
390 | } |
391 | |
392 | |
393 | inline 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 | |
420 | inline void ZipFileInfo::setCRC(Poco::UInt32 val) |
421 | { |
422 | _crc32 = val; |
423 | ZipUtil::set32BitValue(val, _rawInfo, CRC32_POS); |
424 | } |
425 | |
426 | |
427 | inline 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 | |
434 | inline 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 | |
441 | inline 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 | |
448 | inline void ZipFileInfo::setCompressionMethod(ZipCommon::CompressionMethod cm) |
449 | { |
450 | ZipUtil::set16BitValue(static_cast<Poco::UInt16>(cm), _rawInfo, COMPR_METHOD_POS); |
451 | } |
452 | |
453 | |
454 | inline 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 | |
464 | inline void ZipFileInfo::setFileNameLength(Poco::UInt16 size) |
465 | { |
466 | ZipUtil::set16BitValue(size, _rawInfo, FILENAME_LENGTH_POS); |
467 | } |
468 | |
469 | |
470 | inline 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 | |
477 | inline 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 | |
487 | inline void ZipFileInfo::setLastModifiedAt(const Poco::DateTime& dt) |
488 | { |
489 | _lastModifiedAt = dt; |
490 | ZipUtil::setDateTime(dt, _rawInfo, LASTMODFILETIME_POS, LASTMODFILEDATE_POS); |
491 | } |
492 | |
493 | |
494 | inline 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 | |
503 | inline void ZipFileInfo::setFileName(const std::string& str) |
504 | { |
505 | _fileName = str; |
506 | setFileNameLength(static_cast<Poco::UInt16>(str.size())); |
507 | } |
508 | |
509 | |
510 | inline 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 | |