1 | // |
2 | // ZipArchiveInfo.cpp |
3 | // |
4 | // Library: Zip |
5 | // Package: Zip |
6 | // Module: ZipArchiveInfo |
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/ZipArchiveInfo.h" |
16 | #include "Poco/Zip/ZipException.h" |
17 | #include "Poco/Buffer.h" |
18 | #include <istream> |
19 | #include <cstring> |
20 | |
21 | |
22 | namespace Poco { |
23 | namespace Zip { |
24 | |
25 | |
26 | const char ZipArchiveInfo::[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x05', '\x06'}; |
27 | |
28 | |
29 | ZipArchiveInfo::ZipArchiveInfo(std::istream& in, bool ): |
30 | _rawInfo(), |
31 | _startPos(in.tellg()), |
32 | _comment() |
33 | { |
34 | if (assumeHeaderRead) |
35 | _startPos -= ZipCommon::HEADER_SIZE; |
36 | parse(in, assumeHeaderRead); |
37 | } |
38 | |
39 | |
40 | ZipArchiveInfo::ZipArchiveInfo(): |
41 | _rawInfo(), |
42 | _startPos(0), |
43 | _comment() |
44 | { |
45 | std::memset(_rawInfo, 0, FULLHEADER_SIZE); |
46 | std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); |
47 | } |
48 | |
49 | |
50 | ZipArchiveInfo::~ZipArchiveInfo() |
51 | { |
52 | } |
53 | |
54 | |
55 | void ZipArchiveInfo::parse(std::istream& inp, bool ) |
56 | { |
57 | if (!assumeHeaderRead) |
58 | { |
59 | inp.read(_rawInfo, ZipCommon::HEADER_SIZE); |
60 | if (inp.gcount() != ZipCommon::HEADER_SIZE) |
61 | throw Poco::IOException("Failed to read archive info header" ); |
62 | if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) |
63 | throw Poco::DataFormatException("Bad archive info header" ); |
64 | } |
65 | else |
66 | { |
67 | std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); |
68 | } |
69 | |
70 | // read the rest of the header |
71 | inp.read(_rawInfo + ZipCommon::HEADER_SIZE, FULLHEADER_SIZE - ZipCommon::HEADER_SIZE); |
72 | Poco::UInt16 len = getZipCommentSize(); |
73 | if (len > 0) |
74 | { |
75 | Poco::Buffer<char> buf(len); |
76 | inp.read(buf.begin(), len); |
77 | _comment = std::string(buf.begin(), len); |
78 | } |
79 | } |
80 | |
81 | |
82 | std::string ZipArchiveInfo::() const |
83 | { |
84 | std::string result(_rawInfo, FULLHEADER_SIZE); |
85 | result.append(_comment); |
86 | return result; |
87 | } |
88 | |
89 | |
90 | void ZipArchiveInfo::(const std::string& ) |
91 | { |
92 | // Confirm string is of valid size |
93 | if (comment.size() > 65535) |
94 | throw ZipException("Maximum number of entries for a ZIP file reached: 65535" ); |
95 | |
96 | // Change the value of the ZIP Comment Size to reflect new comment size |
97 | ZipUtil::set16BitValue(static_cast<Poco::UInt16>(comment.size()), _rawInfo, ZIPCOMMENT_LENGTH_POS); |
98 | |
99 | // Now change our internal comment |
100 | _comment = comment; |
101 | } |
102 | |
103 | |
104 | const char ZipArchiveInfo64::[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x06', '\x06'}; |
105 | const char ZipArchiveInfo64::[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x06', '\x07'}; |
106 | |
107 | |
108 | ZipArchiveInfo64::ZipArchiveInfo64(std::istream& in, bool ): |
109 | _rawInfo(), |
110 | _startPos(in.tellg()) |
111 | { |
112 | if (assumeHeaderRead) |
113 | _startPos -= ZipCommon::HEADER_SIZE; |
114 | parse(in, assumeHeaderRead); |
115 | } |
116 | |
117 | |
118 | ZipArchiveInfo64::ZipArchiveInfo64(): |
119 | _rawInfo(), |
120 | _startPos(0) |
121 | { |
122 | std::memset(_rawInfo, 0, FULL_HEADER_SIZE); |
123 | std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); |
124 | ZipUtil::set64BitValue(FULL_HEADER_SIZE - (RECORDSIZE_POS + RECORDSIZE_SIZE), _rawInfo, RECORDSIZE_POS); |
125 | std::memset(_locInfo, 0, FULL_LOCATOR_SIZE); |
126 | std::memcpy(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE); |
127 | setRequiredVersion(4, 5); |
128 | } |
129 | |
130 | |
131 | ZipArchiveInfo64::~ZipArchiveInfo64() |
132 | { |
133 | } |
134 | |
135 | |
136 | void ZipArchiveInfo64::parse(std::istream& inp, bool ) |
137 | { |
138 | if (!assumeHeaderRead) |
139 | { |
140 | inp.read(_rawInfo, ZipCommon::HEADER_SIZE); |
141 | if (inp.gcount() != ZipCommon::HEADER_SIZE) |
142 | throw Poco::IOException("Failed to read archive info header" ); |
143 | if (std::memcmp(_rawInfo, HEADER, ZipCommon::HEADER_SIZE) != 0) |
144 | throw Poco::DataFormatException("Bad archive info header" ); |
145 | } |
146 | else |
147 | { |
148 | std::memcpy(_rawInfo, HEADER, ZipCommon::HEADER_SIZE); |
149 | } |
150 | |
151 | std::memset(_rawInfo + ZipCommon::HEADER_SIZE, 0, FULL_HEADER_SIZE - ZipCommon::HEADER_SIZE); |
152 | |
153 | // read the rest of the header |
154 | Poco::UInt64 offset = RECORDSIZE_POS; |
155 | inp.read(_rawInfo + ZipCommon::HEADER_SIZE, RECORDSIZE_SIZE); |
156 | offset += RECORDSIZE_SIZE; |
157 | Poco::UInt64 len = ZipUtil::get64BitValue(_rawInfo, RECORDSIZE_POS); |
158 | if (len <= FULL_HEADER_SIZE - offset) |
159 | { |
160 | inp.read(_rawInfo + offset, len); |
161 | ZipUtil::set64BitValue(FULL_HEADER_SIZE - offset, _rawInfo, RECORDSIZE_POS); |
162 | } |
163 | else |
164 | { |
165 | inp.read(_rawInfo + offset, FULL_HEADER_SIZE - offset); |
166 | len -= (FULL_HEADER_SIZE - offset); |
167 | Poco::Buffer<char> xtra(len); |
168 | inp.read(xtra.begin(), len); |
169 | _extraField = std::string(xtra.begin(), len); |
170 | ZipUtil::set64BitValue(FULL_HEADER_SIZE + len - offset, _rawInfo, RECORDSIZE_POS); |
171 | } |
172 | inp.read(_locInfo, FULL_LOCATOR_SIZE); |
173 | if (inp.gcount() != FULL_LOCATOR_SIZE) |
174 | throw Poco::IOException("Failed to read locator" ); |
175 | if (std::memcmp(_locInfo, LOCATOR_HEADER, ZipCommon::HEADER_SIZE) != 0) |
176 | throw Poco::DataFormatException("Bad locator header" ); |
177 | |
178 | } |
179 | |
180 | |
181 | std::string ZipArchiveInfo64::() const |
182 | { |
183 | std::string result(_rawInfo, FULL_HEADER_SIZE); |
184 | result.append(_extraField); |
185 | result.append(_locInfo, FULL_LOCATOR_SIZE); |
186 | return result; |
187 | } |
188 | |
189 | |
190 | } } // namespace Poco::Zip |
191 | |