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
22namespace Poco {
23namespace Zip {
24
25
26const char ZipArchiveInfo::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x05', '\x06'};
27
28
29ZipArchiveInfo::ZipArchiveInfo(std::istream& in, bool assumeHeaderRead):
30 _rawInfo(),
31 _startPos(in.tellg()),
32 _comment()
33{
34 if (assumeHeaderRead)
35 _startPos -= ZipCommon::HEADER_SIZE;
36 parse(in, assumeHeaderRead);
37}
38
39
40ZipArchiveInfo::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
50ZipArchiveInfo::~ZipArchiveInfo()
51{
52}
53
54
55void ZipArchiveInfo::parse(std::istream& inp, bool assumeHeaderRead)
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
82std::string ZipArchiveInfo::createHeader() const
83{
84 std::string result(_rawInfo, FULLHEADER_SIZE);
85 result.append(_comment);
86 return result;
87}
88
89
90void ZipArchiveInfo::setZipComment(const std::string& comment)
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
104const char ZipArchiveInfo64::HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x06', '\x06'};
105const char ZipArchiveInfo64::LOCATOR_HEADER[ZipCommon::HEADER_SIZE] = {'\x50', '\x4b', '\x06', '\x07'};
106
107
108ZipArchiveInfo64::ZipArchiveInfo64(std::istream& in, bool assumeHeaderRead):
109 _rawInfo(),
110 _startPos(in.tellg())
111{
112 if (assumeHeaderRead)
113 _startPos -= ZipCommon::HEADER_SIZE;
114 parse(in, assumeHeaderRead);
115}
116
117
118ZipArchiveInfo64::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
131ZipArchiveInfo64::~ZipArchiveInfo64()
132{
133}
134
135
136void ZipArchiveInfo64::parse(std::istream& inp, bool assumeHeaderRead)
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
181std::string ZipArchiveInfo64::createHeader() 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