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"
24 #include "include/bundle.h"
26 #include "exception-internal.h"
28 namespace tizen_base {
31 static const int CHECKSUM_LENGTH = 32;
33 Bundle::Bundle() = default;
35 Bundle::Bundle(unsigned char* raw, int size, bool base64) {
38 ret = Decode(raw, size);
40 ret = DecodeRaw(raw, size);
41 if (ret != BUNDLE_ERROR_NONE)
45 Bundle::Bundle(int argc, char** argv) {
46 int ret = Import(argc, argv);
47 if (ret != BUNDLE_ERROR_NONE)
51 Bundle::~Bundle() = default;
53 Bundle::Bundle(const Bundle& b) {
58 Bundle& Bundle::operator = (const Bundle& b) {
66 Bundle::Bundle(Bundle&& b) noexcept {
67 map_ = std::move(b.map_);
68 list_ = std::move(b.list_);
71 Bundle& Bundle::operator = (Bundle&& b) noexcept {
73 map_ = std::move(b.map_);
74 list_ = std::move(b.list_);
79 bool Bundle::operator == (const Bundle& b) {
83 if (map_.size() != b.map_.size())
86 for (const auto& kv : map_) {
87 auto& lhs = kv.second;
88 auto iter = b.map_.find(lhs->GetKey());
89 if (iter == b.map_.end())
92 auto& rhs = iter->second;
100 void Bundle::Remove(const std::string& key) {
101 auto iter = map_.find(key);
102 if (iter == map_.end())
103 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
105 list_.remove(iter->second);
109 void Bundle::Add(std::shared_ptr<KeyInfo> key_info) {
110 auto iter = map_.find(key_info->GetKey());
111 if (iter != map_.end())
112 THROW(BUNDLE_ERROR_KEY_EXISTS);
114 map_[key_info->GetKey()] = key_info;
115 list_.push_back(std::move(key_info));
118 void Bundle::Set(const std::string& key, int index,
119 std::vector<unsigned char> value) {
120 auto iter = map_.find(key);
121 if (iter == map_.end())
122 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
124 int ret = iter->second->SetValue(index, std::move(value));
125 if (ret != BUNDLE_ERROR_NONE)
129 std::shared_ptr<KeyInfo>& Bundle::Get(const std::string& key) {
130 auto iter = map_.find(key.c_str());
131 if (iter == map_.end())
132 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
137 int Bundle::GetSize() {
141 int Bundle::GetType(const std::string& key) {
142 auto iter = map_.find(key);
143 if (iter == map_.end())
144 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
146 return iter->second->GetType();
149 unsigned char* Bundle::Encode() {
153 raw = EncodeRaw(&size);
154 } catch (const Exception& e) {
155 THROW(e.GetErrorCode());
158 std::unique_ptr<unsigned char, decltype(std::free)*> raw_ptr(raw, std::free);
159 char* encoded_data = reinterpret_cast<char*>(
160 g_base64_encode(reinterpret_cast<guchar*>(raw),
161 static_cast<gsize>(size)));
162 if (encoded_data == nullptr)
163 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
165 return reinterpret_cast<unsigned char*>(encoded_data);
168 int Bundle::Decode(unsigned char* raw, int size) {
169 unsigned char* d_str = new (std::nothrow) unsigned char[(size / 4) * 3 + 3];
170 if (d_str == nullptr)
171 return BUNDLE_ERROR_OUT_OF_MEMORY;
173 std::unique_ptr<unsigned char[]> d_ptr(d_str);
176 unsigned int d_len_raw = g_base64_decode_step(reinterpret_cast<char*>(raw),
177 size, d_str, &state, &save);
178 if (d_len_raw < CHECKSUM_LENGTH)
179 return BUNDLE_ERROR_OUT_OF_MEMORY;
181 return DecodeRaw(d_str, d_len_raw);
184 unsigned char* Bundle::EncodeRaw(int* size) {
185 std::vector<unsigned char> bytes;
186 for (const auto& key_info : list_) {
187 auto encoded_bytes = key_info->Encode();
188 bytes.insert(bytes.end(), encoded_bytes.begin(), encoded_bytes.end());
191 gchar* checksum = g_compute_checksum_for_string(
192 G_CHECKSUM_MD5, reinterpret_cast<gchar*>(&bytes[0]),
193 static_cast<gssize>(bytes.size()));
194 if (checksum == nullptr)
195 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
197 std::unique_ptr<gchar, decltype(g_free)*> ptr(checksum, g_free);
198 unsigned char* p = reinterpret_cast<unsigned char*>(checksum);
199 bytes.insert(bytes.begin(), p, p + CHECKSUM_LENGTH);
201 unsigned char* raw = static_cast<unsigned char*>(malloc(bytes.size()));
203 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
205 std::copy(bytes.begin(), bytes.end(), raw);
206 *size = static_cast<int>(bytes.size());
210 int Bundle::DecodeRaw(unsigned char* raw, int size) {
211 char* extract_checksum = new (std::nothrow) char[CHECKSUM_LENGTH + 1];
212 if (extract_checksum == nullptr)
213 return BUNDLE_ERROR_OUT_OF_MEMORY;
215 std::unique_ptr<char[]> extract_ptr(extract_checksum);
216 unsigned char* d_str = raw;
217 unsigned int d_len_raw = size;
218 strncpy(extract_checksum, reinterpret_cast<char*>(d_str), CHECKSUM_LENGTH);
219 extract_checksum[CHECKSUM_LENGTH] = '\0';
221 gchar* compute_checksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,
222 reinterpret_cast<gchar*>(d_str + CHECKSUM_LENGTH),
223 d_len_raw - CHECKSUM_LENGTH);
224 if (compute_checksum == nullptr)
225 return BUNDLE_ERROR_OUT_OF_MEMORY;
227 std::unique_ptr<gchar, decltype(g_free)*> compute_ptr(compute_checksum,
229 if (strcmp(extract_checksum, static_cast<char*>(compute_checksum)) != 0)
230 return BUNDLE_ERROR_INVALID_PARAMETER;
232 unsigned char* d_r = d_str + CHECKSUM_LENGTH;
233 unsigned int d_len = d_len_raw - CHECKSUM_LENGTH;
235 unsigned int reader = 0;
236 std::vector<unsigned char> bytes(d_r, d_r + d_len);
238 while (reader < bytes.size()) {
239 std::size_t total_size = -1;
240 unsigned char* p = reinterpret_cast<unsigned char*>(&total_size);
241 std::copy(&bytes[reader], &bytes[reader] + sizeof(total_size), p);
243 std::vector<unsigned char> encoded_bytes;
244 std::copy(&bytes[reader], &bytes[reader] + total_size,
245 std::back_inserter(encoded_bytes));
246 reader += total_size;
248 KeyInfo* new_key_info;
250 new_key_info = new KeyInfo(std::move(encoded_bytes));
251 } catch (const Exception& e) {
252 return e.GetErrorCode();
253 } catch (const std::bad_alloc& ba) {
254 return BUNDLE_ERROR_OUT_OF_MEMORY;
257 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
258 auto iter = map_.find(key_info->GetKey());
259 if (iter != map_.end())
262 map_[key_info->GetKey()] = key_info;
263 list_.push_back(std::move(key_info));
266 return BUNDLE_ERROR_NONE;
269 const std::unordered_map<std::string, std::shared_ptr<KeyInfo>>&
270 Bundle::GetMap() const {
274 std::vector<std::string> Bundle::Export() {
275 std::vector<std::string> argv(2);
276 for (const auto& key_info : list_) {
277 argv.push_back(key_info->GetKey());
279 auto encoded_bytes = key_info->Encode();
280 auto* p = reinterpret_cast<unsigned char*>(&encoded_bytes[0]);
281 auto* base64_bytes = g_base64_encode(p, encoded_bytes.size());
282 if (base64_bytes == nullptr)
283 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
285 std::unique_ptr<gchar, decltype(g_free)*> base64_bytes_ptr(base64_bytes,
287 argv.push_back(std::move(base64_bytes));
293 int Bundle::Import(int argc, char** argv) {
295 return BUNDLE_ERROR_NONE;
297 if (!argv[1] || std::strcmp(argv[1], TAG_IMPORT_EXPORT_CHECK)) {
298 for (int idx = 1; idx + 1 < argc; idx += 2) {
299 auto* p = reinterpret_cast<unsigned char*>(argv[idx +1]);
300 auto len = strlen(argv[idx + 1]) + 1;
301 std::vector<unsigned char> value;
302 std::copy(p, p + len, std::back_inserter(value));
304 KeyInfo* new_key_info;
306 new_key_info = new KeyInfo(Type::String, argv[idx], std::move(value));
307 } catch (const Exception& e) {
308 return e.GetErrorCode();
309 } catch (const std::bad_alloc& ba) {
310 return BUNDLE_ERROR_OUT_OF_MEMORY;
313 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
314 auto iter = map_.find(key_info->GetKey());
315 if (iter != map_.end())
318 map_[key_info->GetKey()] = key_info;
319 list_.push_back(key_info);
321 return BUNDLE_ERROR_NONE;
324 for (int idx = 2; idx + 1 < argc; idx += 2) {
326 auto* bytes = g_base64_decode(argv[idx + 1], &out_len);
327 if (bytes == nullptr)
328 return BUNDLE_ERROR_OUT_OF_MEMORY;
330 std::unique_ptr<guchar, decltype(g_free)*> bytes_ptr(bytes, g_free);
332 if (out_len < sizeof(std::size_t))
335 auto* p = reinterpret_cast<unsigned char*>(bytes);
336 std::vector<unsigned char> decoded_bytes(p, p + (out_len + 1));
338 KeyInfo* new_key_info;
340 new_key_info = new KeyInfo(std::move(decoded_bytes));
341 } catch (const Exception& e) {
342 return e.GetErrorCode();
343 } catch (const std::bad_alloc& ba) {
344 return BUNDLE_ERROR_OUT_OF_MEMORY;
347 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
348 auto iter = map_.find(key_info->GetKey());
349 if (iter != map_.end())
352 map_[key_info->GetKey()] = key_info;
353 list_.push_back(std::move(key_info));
356 return BUNDLE_ERROR_NONE;
359 } // namespace internal
360 } // namespace tizen_base