1 /*
2 * Copyright (c) 2023 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 "raw_data_parser.h"
17
18 #include <chrono>
19
20 #include "multi_platform_endian.h"
21
22 namespace OHOS::NativeRdb {
ParserRawData(const uint8_t * data,size_t length,Asset & asset)23 size_t RawDataParser::ParserRawData(const uint8_t *data, size_t length, Asset &asset)
24 {
25 size_t used = 0;
26 uint16_t size = 0;
27
28 if (sizeof(ASSET_MAGIC) > length - used) {
29 return 0;
30 }
31 std::vector<uint8_t> alignData;
32 alignData.assign(data, data + sizeof(ASSET_MAGIC));
33 used += sizeof(ASSET_MAGIC);
34 auto hostMagicWord = Endian::LeToH(*(reinterpret_cast<decltype(&ASSET_MAGIC)>(alignData.data())));
35 if (hostMagicWord != ASSET_MAGIC) {
36 return 0;
37 }
38
39 if (sizeof(size) > length - used) {
40 return 0;
41 }
42 alignData.assign(data + used, data + used + sizeof(size));
43 used += sizeof(size);
44 size = Endian::LeToH(*(reinterpret_cast<decltype(&size)>(alignData.data())));
45 if (size > length - used) {
46 return 0;
47 }
48 auto rawData = std::string(reinterpret_cast<const char *>(&data[used]), size);
49 InnerAsset innerAsset = InnerAsset(asset);
50 if (!innerAsset.Unmarshall(rawData)) {
51 return 0;
52 }
53 used += size;
54 return used;
55 }
56
ParserRawData(const uint8_t * data,size_t length,Assets & assets)57 size_t RawDataParser::ParserRawData(const uint8_t *data, size_t length, Assets &assets)
58 {
59 size_t used = 0;
60 uint16_t num = 0;
61
62 if (sizeof(ASSETS_MAGIC) > length - used) {
63 return 0;
64 }
65 std::vector<uint8_t> alignData;
66 alignData.assign(data, data + sizeof (ASSETS_MAGIC));
67 used += sizeof (ASSETS_MAGIC);
68 auto hostMagicWord = Endian::LeToH(*(reinterpret_cast<decltype(&ASSETS_MAGIC)>(alignData.data())));
69 if (hostMagicWord != ASSETS_MAGIC) {
70 return 0;
71 }
72
73 if (sizeof(num) > length - used) {
74 return 0;
75 }
76 alignData.assign(data, data + sizeof(num));
77 num = Endian::LeToH(*(reinterpret_cast<decltype(&num)>(alignData.data())));
78 used += sizeof(num);
79 uint16_t count = 0;
80 while (used < length && count < num) {
81 Asset asset;
82 auto dataLen = ParserRawData(&data[used], length - used, asset);
83 if (dataLen == 0) {
84 break;
85 }
86 used += dataLen;
87 assets.push_back(std::move(asset));
88 count++;
89 }
90 return used;
91 }
92
PackageRawData(const Asset & asset)93 std::vector<uint8_t> RawDataParser::PackageRawData(const Asset &asset)
94 {
95 std::vector<uint8_t> rawData;
96 InnerAsset innerAsset(const_cast<Asset &>(asset));
97 auto data = Serializable::Marshall(innerAsset);
98 uint16_t size = Endian::HToLe((uint16_t)data.length());
99 auto leMagic = Endian::HToLe(ASSET_MAGIC);
100 auto magicU8 = reinterpret_cast<uint8_t *>(const_cast<uint32_t *>(&leMagic));
101 rawData.insert(rawData.end(), magicU8, magicU8 + sizeof(ASSET_MAGIC));
102 rawData.insert(rawData.end(), reinterpret_cast<uint8_t *>(&size),
103 reinterpret_cast<uint8_t *>(&size) + sizeof(size));
104 rawData.insert(rawData.end(), data.begin(), data.end());
105 return rawData;
106 }
107
PackageRawData(const Assets & assets)108 std::vector<uint8_t> RawDataParser::PackageRawData(const Assets &assets)
109 {
110 std::vector<uint8_t> rawData;
111 uint16_t num = uint16_t(assets.size());
112 auto leMagic = Endian::HToLe(ASSETS_MAGIC);
113 auto magicU8 = reinterpret_cast<uint8_t *>(const_cast<uint32_t *>(&leMagic));
114 rawData.insert(rawData.end(), magicU8, magicU8 + sizeof(ASSETS_MAGIC));
115 rawData.insert(rawData.end(), reinterpret_cast<uint8_t *>(&num), reinterpret_cast<uint8_t *>(&num) + sizeof(num));
116 for (auto &asset : assets) {
117 auto data = PackageRawData(asset);
118 rawData.insert(rawData.end(), data.begin(), data.end());
119 }
120 return rawData;
121 }
122
ParserRawData(const uint8_t * data,size_t length,std::map<std::string,Asset> & assets)123 size_t RawDataParser::ParserRawData(const uint8_t *data, size_t length, std::map<std::string, Asset> &assets)
124 {
125 Assets res;
126 auto used = ParserRawData(data, length, res);
127 auto it = res.begin();
128 while (it != res.end()) {
129 assets.insert({ it->name, *it });
130 it++;
131 }
132 return used;
133 }
134
PackageRawData(const std::map<std::string,Asset> & assets)135 std::vector<uint8_t> RawDataParser::PackageRawData(const std::map<std::string, Asset> &assets)
136 {
137 Assets res;
138 for (auto asset : assets) {
139 res.push_back(asset.second);
140 }
141 return PackageRawData(res);
142 }
143
Marshal(Serializable::json & node) const144 bool RawDataParser::InnerAsset::Marshal(Serializable::json &node) const
145 {
146 SetValue(node[GET_NAME(version)], asset_.version);
147 SetValue(node[GET_NAME(expiresTime)], asset_.expiresTime);
148 SetValue(node[GET_NAME(id)], asset_.id);
149 SetValue(node[GET_NAME(name)], asset_.name);
150 SetValue(node[GET_NAME(uri)], asset_.uri);
151 SetValue(node[GET_NAME(createTime)], asset_.createTime);
152 SetValue(node[GET_NAME(modifyTime)], asset_.modifyTime);
153 SetValue(node[GET_NAME(size)], asset_.size);
154 SetValue(node[GET_NAME(hash)], asset_.hash);
155 SetValue(node[GET_NAME(path)], asset_.path);
156 SetValue(node[GET_NAME(status)], asset_.status);
157 return true;
158 }
Unmarshal(const Serializable::json & node)159 bool RawDataParser::InnerAsset::Unmarshal(const Serializable::json &node)
160 {
161 bool ret = true;
162 ret = GetValue(node, GET_NAME(version), asset_.version) && ret;
163 ret = GetValue(node, GET_NAME(expiresTime), asset_.expiresTime) && ret;
164 ret = GetValue(node, GET_NAME(id), asset_.id) && ret;
165 ret = GetValue(node, GET_NAME(name), asset_.name) && ret;
166 ret = GetValue(node, GET_NAME(uri), asset_.uri) && ret;
167 ret = GetValue(node, GET_NAME(createTime), asset_.createTime) && ret;
168 ret = GetValue(node, GET_NAME(modifyTime), asset_.modifyTime) && ret;
169 ret = GetValue(node, GET_NAME(size), asset_.size) && ret;
170 ret = GetValue(node, GET_NAME(hash), asset_.hash) && ret;
171 ret = GetValue(node, GET_NAME(path), asset_.path) && ret;
172 ret = GetValue(node, GET_NAME(status), asset_.status) && ret;
173 if (asset_.status == AssetValue::STATUS_DOWNLOADING &&
174 asset_.expiresTime < static_cast<uint64_t>(std::chrono::system_clock::now().time_since_epoch().count())) {
175 asset_.status = AssetValue::STATUS_ABNORMAL;
176 }
177 return ret;
178 }
179 } // namespace OHOS::NativeRdb