2 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "bundle-internal.h"
26 #include "include/bundle.h"
28 #include "exception-internal.h"
30 namespace tizen_base {
33 static const int CHECKSUM_LENGTH = 32;
35 Bundle::Bundle(unsigned char* raw, int size, bool base64) {
37 THROW(BUNDLE_ERROR_INVALID_PARAMETER);
41 ret = Decode(raw, static_cast<size_t>(size));
43 ret = DecodeRaw(raw, static_cast<size_t>(size));
44 if (ret != BUNDLE_ERROR_NONE)
48 Bundle::Bundle(int argc, char** argv) {
49 int ret = Import(argc, argv);
50 if (ret != BUNDLE_ERROR_NONE)
54 Bundle::Bundle(const Bundle& b) {
59 Bundle& Bundle::operator = (const Bundle& b) {
67 Bundle::Bundle(Bundle&& b) noexcept {
68 map_ = std::move(b.map_);
69 list_ = std::move(b.list_);
72 Bundle& Bundle::operator = (Bundle&& b) noexcept {
74 map_ = std::move(b.map_);
75 list_ = std::move(b.list_);
80 bool Bundle::operator == (const Bundle& b) {
84 if (map_.size() != b.map_.size())
87 for (const auto& kv : map_) {
88 auto& lhs = kv.second;
89 auto iter = b.map_.find(lhs->GetKey());
90 if (iter == b.map_.end())
93 auto& rhs = iter->second;
101 void Bundle::Remove(const std::string& key) {
102 auto iter = map_.find(key);
103 if (iter == map_.end())
104 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
106 list_.remove(iter->second);
110 void Bundle::Add(std::shared_ptr<KeyInfo> key_info) {
111 auto iter = map_.find(key_info->GetKey());
112 if (iter != map_.end())
113 THROW(BUNDLE_ERROR_KEY_EXISTS);
115 map_[key_info->GetKey()] = key_info;
116 list_.push_back(std::move(key_info));
119 void Bundle::Set(const std::string& key, int index,
120 std::vector<unsigned char> value) {
121 auto iter = map_.find(key);
122 if (iter == map_.end())
123 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
125 int ret = iter->second->SetValue(index, value);
126 if (ret != BUNDLE_ERROR_NONE)
130 std::shared_ptr<KeyInfo>& Bundle::Get(const std::string& key) {
131 auto iter = map_.find(key.c_str());
132 if (iter == map_.end())
133 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
138 int Bundle::GetSize() {
142 int Bundle::GetType(const std::string& key) {
143 auto iter = map_.find(key);
144 if (iter == map_.end())
145 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
147 return iter->second->GetType();
150 unsigned char* Bundle::Encode() {
154 raw = EncodeRaw(&size);
155 } catch (const Exception& e) {
156 THROW(e.GetErrorCode());
159 std::unique_ptr<unsigned char, decltype(std::free)*> raw_ptr(raw, std::free);
160 char* encoded_data = reinterpret_cast<char*>(
161 g_base64_encode(reinterpret_cast<guchar*>(raw),
162 static_cast<gsize>(size)));
163 if (encoded_data == nullptr)
164 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
166 return reinterpret_cast<unsigned char*>(encoded_data);
169 int Bundle::Decode(unsigned char* raw, size_t size) {
170 unsigned char* d_str = new (std::nothrow) unsigned char[(size / 4) * 3 + 3];
171 if (d_str == nullptr)
172 return BUNDLE_ERROR_OUT_OF_MEMORY;
174 std::unique_ptr<unsigned char[]> d_ptr(d_str);
177 size_t d_len_raw = static_cast<size_t>(g_base64_decode_step(
178 reinterpret_cast<char*>(raw), size, d_str, &state, &save));
179 if (d_len_raw < CHECKSUM_LENGTH)
180 return BUNDLE_ERROR_OUT_OF_MEMORY;
182 return DecodeRaw(d_str, d_len_raw);
185 unsigned char* Bundle::EncodeRaw(int* size) {
186 std::vector<unsigned char> bytes;
187 for (const auto& key_info : list_) {
188 auto encoded_bytes = key_info->Encode();
189 bytes.insert(bytes.end(),
190 std::make_move_iterator(encoded_bytes.begin()),
191 std::make_move_iterator(encoded_bytes.end()));
194 gchar* checksum = g_compute_checksum_for_string(
195 G_CHECKSUM_MD5, reinterpret_cast<gchar*>(&bytes[0]),
196 static_cast<gssize>(bytes.size()));
197 if (checksum == nullptr)
198 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
200 std::unique_ptr<gchar, decltype(g_free)*> ptr(checksum, g_free);
201 unsigned char* p = reinterpret_cast<unsigned char*>(checksum);
202 bytes.insert(bytes.begin(), p, p + CHECKSUM_LENGTH);
204 unsigned char* raw = static_cast<unsigned char*>(malloc(bytes.size()));
206 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
208 std::copy(std::make_move_iterator(bytes.begin()),
209 std::make_move_iterator(bytes.end()), raw);
210 *size = static_cast<int>(bytes.size());
214 int Bundle::DecodeRaw(unsigned char* raw, size_t size) {
215 char* extract_checksum = new (std::nothrow) char[CHECKSUM_LENGTH + 1];
216 if (extract_checksum == nullptr)
217 return BUNDLE_ERROR_OUT_OF_MEMORY;
219 std::unique_ptr<char[]> extract_ptr(extract_checksum);
220 unsigned char* d_str = raw;
221 size_t d_len_raw = size;
222 strncpy(extract_checksum, reinterpret_cast<char*>(d_str), CHECKSUM_LENGTH);
223 extract_checksum[CHECKSUM_LENGTH] = '\0';
225 gchar* compute_checksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,
226 reinterpret_cast<gchar*>(d_str + CHECKSUM_LENGTH),
227 d_len_raw - CHECKSUM_LENGTH);
228 if (compute_checksum == nullptr)
229 return BUNDLE_ERROR_OUT_OF_MEMORY;
231 std::unique_ptr<gchar, decltype(g_free)*> compute_ptr(compute_checksum,
233 if (strcmp(extract_checksum, static_cast<char*>(compute_checksum)) != 0)
234 return BUNDLE_ERROR_INVALID_PARAMETER;
236 unsigned char* d_r = d_str + CHECKSUM_LENGTH;
237 size_t d_len = d_len_raw - CHECKSUM_LENGTH;
239 unsigned int reader = 0;
240 std::vector<unsigned char> bytes(d_r, d_r + d_len);
242 while (reader < bytes.size()) {
243 std::size_t total_size = -1;
244 unsigned char* p = reinterpret_cast<unsigned char*>(&total_size);
245 std::copy(&bytes[reader], &bytes[reader] + sizeof(total_size), p);
247 std::vector<unsigned char> encoded_bytes(
248 &bytes[reader], &bytes[reader] + total_size);
249 reader += total_size;
251 KeyInfo* new_key_info;
253 new_key_info = new KeyInfo(std::move(encoded_bytes));
254 } catch (const Exception& e) {
255 return e.GetErrorCode();
256 } catch (const std::bad_alloc& ba) {
257 return BUNDLE_ERROR_OUT_OF_MEMORY;
260 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
261 auto iter = map_.find(key_info->GetKey());
262 if (iter != map_.end())
265 map_[key_info->GetKey()] = key_info;
266 list_.push_back(std::move(key_info));
269 return BUNDLE_ERROR_NONE;
272 const std::unordered_map<std::string, std::shared_ptr<KeyInfo>>&
273 Bundle::GetMap() const {
277 std::vector<std::string> Bundle::Export() {
278 std::vector<std::string> argv(2);
279 for (const auto& key_info : list_) {
280 argv.push_back(key_info->GetKey());
282 auto encoded_bytes = key_info->Encode();
283 auto* p = reinterpret_cast<unsigned char*>(&encoded_bytes[0]);
284 auto* base64_bytes = g_base64_encode(p, encoded_bytes.size());
285 if (base64_bytes == nullptr)
286 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
288 std::unique_ptr<gchar, decltype(g_free)*> base64_bytes_ptr(base64_bytes,
290 argv.push_back(base64_bytes);
296 int Bundle::Import(int argc, char** argv) {
298 return BUNDLE_ERROR_NONE;
300 if (!argv[1] || std::strcmp(argv[1], TAG_IMPORT_EXPORT_CHECK)) {
301 for (int idx = 1; idx + 1 < argc; idx += 2) {
302 auto* p = reinterpret_cast<unsigned char*>(argv[idx +1]);
303 auto len = strlen(argv[idx + 1]) + 1;
304 std::vector<unsigned char> value(p, p + len);
306 KeyInfo* new_key_info;
308 new_key_info = new KeyInfo(Type::String, argv[idx], std::move(value));
309 } catch (const Exception& e) {
310 return e.GetErrorCode();
311 } catch (const std::bad_alloc& ba) {
312 return BUNDLE_ERROR_OUT_OF_MEMORY;
315 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
316 auto iter = map_.find(key_info->GetKey());
317 if (iter != map_.end())
320 map_[key_info->GetKey()] = key_info;
321 list_.push_back(key_info);
323 return BUNDLE_ERROR_NONE;
326 for (int idx = 2; idx + 1 < argc; idx += 2) {
328 auto* bytes = g_base64_decode(argv[idx + 1], &out_len);
329 if (bytes == nullptr)
330 return BUNDLE_ERROR_OUT_OF_MEMORY;
332 std::unique_ptr<guchar, decltype(g_free)*> bytes_ptr(bytes, g_free);
334 if (out_len < sizeof(std::size_t))
337 auto* p = reinterpret_cast<unsigned char*>(bytes);
338 std::vector<unsigned char> decoded_bytes(p, p + (out_len + 1));
340 KeyInfo* new_key_info;
342 new_key_info = new KeyInfo(std::move(decoded_bytes));
343 } catch (const Exception& e) {
344 return e.GetErrorCode();
345 } catch (const std::bad_alloc& ba) {
346 return BUNDLE_ERROR_OUT_OF_MEMORY;
349 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
350 auto iter = map_.find(key_info->GetKey());
351 if (iter != map_.end())
354 map_[key_info->GetKey()] = key_info;
355 list_.push_back(std::move(key_info));
358 return BUNDLE_ERROR_NONE;
361 } // namespace internal
362 } // namespace tizen_base