1 | // |
2 | // ZipArchive.cpp |
3 | // |
4 | // Library: Zip |
5 | // Package: Zip |
6 | // Module: ZipArchive |
7 | // |
8 | // Copyright (c) 2007, Applied Informatics Software Engineering GmbH. |
9 | // and Contributors. |
10 | // |
11 | // SPDX-License-Identifier: BSL-1.0 |
12 | // |
13 | |
14 | |
15 | #include "Poco/Zip/ZipArchive.h" |
16 | #include "Poco/Zip/SkipCallback.h" |
17 | #include "Poco/Exception.h" |
18 | #include <cstring> |
19 | |
20 | |
21 | namespace Poco { |
22 | namespace Zip { |
23 | |
24 | |
25 | const std::string ZipArchive::; |
26 | |
27 | |
28 | ZipArchive::ZipArchive(std::istream& in): |
29 | _entries(), |
30 | _infos(), |
31 | _disks(), |
32 | _disks64() |
33 | { |
34 | poco_assert_dbg (in); |
35 | SkipCallback skip; |
36 | parse(in, skip); |
37 | } |
38 | |
39 | |
40 | ZipArchive::(const FileHeaders& entries, const FileInfos& infos, const DirectoryInfos& dirs, const DirectoryInfos64& dirs64): |
41 | _entries(entries), |
42 | _infos(infos), |
43 | _disks(dirs), |
44 | _disks64(dirs64) |
45 | { |
46 | } |
47 | |
48 | |
49 | ZipArchive::ZipArchive(std::istream& in, ParseCallback& pc): |
50 | _entries(), |
51 | _infos(), |
52 | _disks(), |
53 | _disks64() |
54 | { |
55 | poco_assert_dbg (in); |
56 | parse(in, pc); |
57 | } |
58 | |
59 | |
60 | ZipArchive::~ZipArchive() |
61 | { |
62 | } |
63 | |
64 | |
65 | void ZipArchive::parse(std::istream& in, ParseCallback& pc) |
66 | { |
67 | // read 4 bytes |
68 | bool haveSynced = false; |
69 | while (in.good() && !in.eof()) |
70 | { |
71 | char [ZipCommon::HEADER_SIZE]={'\x00', '\x00', '\x00', '\x00'}; |
72 | in.read(header, ZipCommon::HEADER_SIZE); |
73 | if (in.eof()) |
74 | return; |
75 | if (std::memcmp(header, ZipLocalFileHeader::HEADER, ZipCommon::HEADER_SIZE) == 0) |
76 | { |
77 | ZipLocalFileHeader entry(in, true, pc); |
78 | poco_assert (_entries.insert(std::make_pair(entry.getFileName(), entry)).second); |
79 | haveSynced = false; |
80 | } |
81 | else if (std::memcmp(header, ZipFileInfo::HEADER, ZipCommon::HEADER_SIZE) == 0) |
82 | { |
83 | ZipFileInfo info(in, true); |
84 | FileHeaders::iterator it = _entries.find(info.getFileName()); |
85 | if (it != _entries.end()) |
86 | { |
87 | it->second.setStartPos(info.getOffset()); |
88 | } |
89 | poco_assert (_infos.insert(std::make_pair(info.getFileName(), info)).second); |
90 | haveSynced = false; |
91 | } |
92 | else if (std::memcmp(header, ZipArchiveInfo::HEADER, ZipCommon::HEADER_SIZE) == 0) |
93 | { |
94 | ZipArchiveInfo nfo(in, true); |
95 | poco_assert (_disks.insert(std::make_pair(nfo.getDiskNumber(), nfo)).second); |
96 | haveSynced = false; |
97 | } |
98 | else if (std::memcmp(header, ZipArchiveInfo64::HEADER, ZipCommon::HEADER_SIZE) == 0) |
99 | { |
100 | ZipArchiveInfo64 nfo(in, true); |
101 | poco_assert (_disks64.insert(std::make_pair(nfo.getDiskNumber(), nfo)).second); |
102 | haveSynced = false; |
103 | } |
104 | else |
105 | { |
106 | if (!haveSynced) |
107 | { |
108 | // Some Zip files have extra data behind the ZipLocalFileHeader. |
109 | // Try to re-sync. |
110 | ZipUtil::sync(in); |
111 | haveSynced = true; |
112 | } |
113 | else |
114 | { |
115 | if (_disks.empty() && _disks64.empty()) |
116 | throw Poco::IllegalStateException("Illegal header in zip file" ); |
117 | else |
118 | throw Poco::IllegalStateException("Garbage after directory header" ); |
119 | } |
120 | } |
121 | } |
122 | } |
123 | |
124 | |
125 | const std::string& ZipArchive::() const |
126 | { |
127 | // It seems that only the "first" disk is populated (look at Compress::close()), so getting the first ZipArchiveInfo |
128 | DirectoryInfos::const_iterator it = _disks.begin(); |
129 | if (it != _disks.end()) |
130 | { |
131 | return it->second.getZipComment(); |
132 | } |
133 | else |
134 | { |
135 | DirectoryInfos64::const_iterator it64 = _disks64.begin(); |
136 | if (it64 != _disks64.end()) |
137 | return it->second.getZipComment(); |
138 | else |
139 | return EMPTY_COMMENT; |
140 | } |
141 | } |
142 | |
143 | |
144 | } } // namespace Poco::Zip |
145 | |