1/*
2 * Copyright (c) 2024-2024 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 *     http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16#include <cinttypes>
17
18#include "endof_central_directory.h"
19#include "signature_tools_log.h"
20
21namespace OHOS {
22namespace SignatureTools {
23std::optional<EndOfCentralDirectory*> EndOfCentralDirectory::GetEOCDByBytes(const std::string& bytes)
24{
25    return GetEOCDByBytes(bytes, 0);
26}
27
28std::optional<EndOfCentralDirectory*> EndOfCentralDirectory::GetEOCDByBytes(const std::string& bytes, int offset)
29{
30    EndOfCentralDirectory* eocd = new EndOfCentralDirectory();
31    int remainingDataLen = bytes.size() - offset;
32    if (remainingDataLen < EOCD_LENGTH) {
33        delete eocd;
34        SIGNATURE_TOOLS_LOGE("remainingDataLen is less than EOCD_LENGTH, remainingDataLen: %d, "
35                             "EOCD_LENGTH: %d", remainingDataLen, EOCD_LENGTH);
36        return std::nullopt;
37    }
38
39    ByteBuffer bf(bytes.c_str(), bytes.size());
40
41    int signValue;
42    bf.GetInt32(signValue);
43    if (signValue != SIGNATURE) {
44        delete eocd;
45        return std::nullopt;
46    }
47
48    SetEndOfCentralDirectoryValues(bf, eocd);
49
50    uint16_t commentLength = eocd->GetCommentLength();
51    if (bf.Remaining() != commentLength) {
52        delete eocd;
53        SIGNATURE_TOOLS_LOGE("bf.Remaining() is not equal to commentLength, bf.Remaining(): %d, "
54                             "commentLength: %" PRIu16, bf.Remaining(), commentLength);
55        return std::nullopt;
56    }
57    if (commentLength > 0) {
58        std::string readComment(commentLength, 0);
59        bf.GetData(&readComment[0], commentLength);
60        eocd->SetComment(readComment);
61    }
62    eocd->SetLength(EOCD_LENGTH + commentLength);
63    if (bf.Remaining() != 0) {
64        delete eocd;
65        SIGNATURE_TOOLS_LOGE("bf.Remaining() is not equal to 0, bf.Remaining(): %d", bf.Remaining());
66        return std::nullopt;
67    }
68    return std::make_optional(eocd);
69}
70
71void EndOfCentralDirectory::SetEndOfCentralDirectoryValues(ByteBuffer& bf, EndOfCentralDirectory* eocd)
72{
73    uint16_t eocdUInt16Value = 0;
74    bf.GetUInt16(eocdUInt16Value);
75    eocd->SetDiskNum(eocdUInt16Value);
76
77    bf.GetUInt16(eocdUInt16Value);
78    eocd->SetcDStartDiskNum(eocdUInt16Value);
79
80    bf.GetUInt16(eocdUInt16Value);
81    eocd->SetThisDiskCDNum(eocdUInt16Value);
82
83    bf.GetUInt16(eocdUInt16Value);
84    eocd->SetcDTotal(eocdUInt16Value);
85
86    uint32_t eocdUInt32Value;
87    bf.GetUInt32(eocdUInt32Value);
88    eocd->SetcDSize(eocdUInt32Value);
89
90    bf.GetUInt32(eocdUInt32Value);
91    eocd->SetOffset(eocdUInt32Value);
92
93    bf.GetUInt16(eocdUInt16Value);
94    eocd->SetCommentLength(eocdUInt16Value);
95}
96
97std::string EndOfCentralDirectory::ToBytes()
98{
99    ByteBuffer bf(m_length);
100
101    bf.PutInt32(SIGNATURE);
102    bf.PutUInt16(m_diskNum);
103    bf.PutUInt16(m_cDStartDiskNum);
104    bf.PutUInt16(m_thisDiskCDNum);
105    bf.PutUInt16(m_cDTotal);
106    bf.PutUInt32(m_cDSize);
107    bf.PutUInt32(m_offset);
108    bf.PutUInt16(m_commentLength);
109
110    if (m_commentLength > 0) {
111        bf.PutData(m_comment.data(), m_comment.size());
112    }
113
114    return bf.ToString();
115}
116
117int EndOfCentralDirectory::GetEocdLength()
118{
119    return EOCD_LENGTH;
120}
121
122int EndOfCentralDirectory::GetSIGNATURE()
123{
124    return SIGNATURE;
125}
126
127uint16_t EndOfCentralDirectory::GetDiskNum()
128{
129    return m_diskNum;
130}
131
132void EndOfCentralDirectory::SetDiskNum(uint16_t diskNum)
133{
134    m_diskNum = diskNum;
135}
136
137uint16_t EndOfCentralDirectory::GetcDStartDiskNum()
138{
139    return m_cDStartDiskNum;
140}
141
142void EndOfCentralDirectory::SetcDStartDiskNum(uint16_t cDStartDiskNum)
143{
144    m_cDStartDiskNum = cDStartDiskNum;
145}
146
147uint16_t EndOfCentralDirectory::GetThisDiskCDNum()
148{
149    return m_thisDiskCDNum;
150}
151
152void EndOfCentralDirectory::SetThisDiskCDNum(uint16_t thisDiskCDNum)
153{
154    m_thisDiskCDNum = thisDiskCDNum;
155}
156
157uint16_t EndOfCentralDirectory::GetcDTotal()
158{
159    return m_cDTotal;
160}
161
162void EndOfCentralDirectory::SetcDTotal(uint16_t cDTotal)
163{
164    m_cDTotal = cDTotal;
165}
166
167uint32_t EndOfCentralDirectory::GetcDSize()
168{
169    return m_cDSize;
170}
171
172void EndOfCentralDirectory::SetcDSize(uint32_t cDSize)
173{
174    m_cDSize = cDSize;
175}
176
177uint32_t EndOfCentralDirectory::GetOffset()
178{
179    return m_offset;
180}
181
182void EndOfCentralDirectory::SetOffset(uint32_t offset)
183{
184    m_offset = offset;
185}
186
187uint16_t EndOfCentralDirectory::GetCommentLength()
188{
189    return m_commentLength;
190}
191
192void EndOfCentralDirectory::SetCommentLength(uint16_t commentLength)
193{
194    m_commentLength = commentLength;
195}
196
197std::string EndOfCentralDirectory::GetComment()
198{
199    return m_comment;
200}
201
202void EndOfCentralDirectory::SetComment(const std::string& comment)
203{
204    m_comment = comment;
205}
206
207int EndOfCentralDirectory::GetLength()
208{
209    return m_length;
210}
211
212void EndOfCentralDirectory::SetLength(uint32_t length)
213{
214    m_length = length;
215}
216} // namespace SignatureTools
217} // namespace OHOS