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.
22 #include "include/bundle.h"
24 #include "bundle-internal.h"
25 #include "exception-internal.h"
27 namespace tizen_base {
30 static const int CHECKSUM_LENGTH = 32;
32 Bundle::Bundle() = default;
34 Bundle::Bundle(unsigned char* raw, int size, bool base64) {
37 ret = Decode(raw, size);
39 ret = DecodeRaw(raw, size);
40 if (ret != BUNDLE_ERROR_NONE)
44 Bundle::Bundle(int argc, char** argv) {
45 int ret = Import(argc, argv);
46 if (ret != BUNDLE_ERROR_NONE)
50 Bundle::~Bundle() = default;
52 Bundle::Bundle(const Bundle& b) {
57 Bundle& Bundle::operator = (const Bundle& b) {
65 Bundle::Bundle(Bundle&& b) noexcept {
66 map_ = std::move(b.map_);
67 list_ = std::move(b.list_);
70 Bundle& Bundle::operator = (Bundle&& b) noexcept {
72 map_ = std::move(b.map_);
73 list_ = std::move(b.list_);
78 bool Bundle::operator == (const Bundle& b) {
82 if (map_.size() != b.map_.size())
85 for (const auto& kv : map_) {
86 auto& lhs = kv.second;
87 auto iter = b.map_.find(lhs->GetKey());
88 if (iter == b.map_.end())
91 auto& rhs = iter->second;
99 void Bundle::Remove(const std::string& key) {
100 auto iter = map_.find(key);
101 if (iter == map_.end())
102 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
104 list_.remove(iter->second);
108 void Bundle::Add(std::shared_ptr<KeyInfo> key_info) {
109 auto iter = map_.find(key_info->GetKey());
110 if (iter != map_.end())
111 THROW(BUNDLE_ERROR_KEY_EXISTS);
113 map_[key_info->GetKey()] = key_info;
114 list_.push_back(key_info);
117 void Bundle::Set(const std::string& key, int index,
118 std::vector<unsigned char> value) {
119 auto iter = map_.find(key);
120 if (iter == map_.end())
121 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
123 int ret = iter->second->SetValue(index, value);
124 if (ret != BUNDLE_ERROR_NONE)
128 std::shared_ptr<KeyInfo>& Bundle::Get(const std::string& key) {
129 auto iter = map_.find(key.c_str());
130 if (iter == map_.end())
131 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
136 int Bundle::GetSize() {
140 int Bundle::GetType(const std::string& key) {
141 auto iter = map_.find(key);
142 if (iter == map_.end())
143 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
145 return iter->second->GetType();
148 unsigned char* Bundle::Encode() {
152 raw = EncodeRaw(&size);
153 } catch (Exception& e) {
154 THROW(e.GetErrorCode());
157 std::unique_ptr<unsigned char, decltype(std::free)*> raw_ptr(raw, std::free);
158 char* encoded_data = reinterpret_cast<char*>(
159 g_base64_encode(reinterpret_cast<guchar*>(raw),
160 static_cast<gsize>(size)));
161 if (encoded_data == nullptr)
162 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
164 return reinterpret_cast<unsigned char*>(encoded_data);
167 int Bundle::Decode(unsigned char* raw, int size) {
168 unsigned char* d_str = new (std::nothrow) unsigned char[(size / 4) * 3 + 3];
169 if (d_str == nullptr)
170 return BUNDLE_ERROR_OUT_OF_MEMORY;
172 std::unique_ptr<unsigned char[]> d_ptr(d_str);
175 unsigned int d_len_raw = g_base64_decode_step(reinterpret_cast<char*>(raw),
176 size, d_str, &state, &save);
177 if (d_len_raw < CHECKSUM_LENGTH)
178 return BUNDLE_ERROR_OUT_OF_MEMORY;
180 return DecodeRaw(d_str, d_len_raw);
183 unsigned char* Bundle::EncodeRaw(int* size) {
184 std::vector<unsigned char> bytes;
185 for (const auto& key_info : list_) {
186 auto encoded_bytes = key_info->Encode();
187 bytes.insert(bytes.end(), encoded_bytes.begin(), encoded_bytes.end());
190 gchar* checksum = g_compute_checksum_for_string(
191 G_CHECKSUM_MD5, reinterpret_cast<gchar*>(&bytes[0]),
192 static_cast<gssize>(bytes.size()));
193 if (checksum == nullptr)
194 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
196 std::unique_ptr<gchar, decltype(g_free)*> ptr(checksum, g_free);
197 unsigned char* p = reinterpret_cast<unsigned char*>(checksum);
198 bytes.insert(bytes.begin(), p, p + CHECKSUM_LENGTH);
200 unsigned char* raw = static_cast<unsigned char*>(malloc(bytes.size()));
202 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
204 std::copy(bytes.begin(), bytes.end(), raw);
205 *size = static_cast<int>(bytes.size());
209 int Bundle::DecodeRaw(unsigned char* raw, int size) {
210 char* extract_checksum = new (std::nothrow) char[CHECKSUM_LENGTH + 1];
211 if (extract_checksum == nullptr)
212 return BUNDLE_ERROR_OUT_OF_MEMORY;
214 std::unique_ptr<char[]> extract_ptr(extract_checksum);
215 unsigned char* d_str = raw;
216 unsigned int d_len_raw = size;
217 strncpy(extract_checksum, reinterpret_cast<char*>(d_str), CHECKSUM_LENGTH);
218 extract_checksum[CHECKSUM_LENGTH] = '\0';
220 gchar* compute_checksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,
221 reinterpret_cast<gchar*>(d_str + CHECKSUM_LENGTH),
222 d_len_raw - CHECKSUM_LENGTH);
223 if (compute_checksum == nullptr)
224 return BUNDLE_ERROR_OUT_OF_MEMORY;
226 std::unique_ptr<gchar, decltype(g_free)*> compute_ptr(compute_checksum,
228 if (strcmp(extract_checksum, static_cast<char*>(compute_checksum)) != 0)
229 return BUNDLE_ERROR_INVALID_PARAMETER;
231 unsigned char* d_r = d_str + CHECKSUM_LENGTH;
232 unsigned int d_len = d_len_raw - CHECKSUM_LENGTH;
234 unsigned int reader = 0;
235 std::vector<unsigned char> bytes(d_r, d_r + d_len);
237 while (reader < bytes.size()) {
238 std::size_t total_size = -1;
239 unsigned char* p = reinterpret_cast<unsigned char*>(&total_size);
240 std::copy(&bytes[reader], &bytes[reader] + sizeof(total_size), p);
242 std::vector<unsigned char> encoded_bytes;
243 std::copy(&bytes[reader], &bytes[reader] + total_size,
244 std::back_inserter(encoded_bytes));
245 reader += total_size;
247 KeyInfo* new_key_info;
249 new_key_info = new KeyInfo(encoded_bytes);
250 } catch (Exception& e) {
251 return e.GetErrorCode();
252 } catch (const std::bad_alloc& ba) {
253 return BUNDLE_ERROR_OUT_OF_MEMORY;
256 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
257 auto iter = map_.find(key_info->GetKey());
258 if (iter != map_.end())
261 map_[key_info->GetKey()] = key_info;
262 list_.push_back(key_info);
265 return BUNDLE_ERROR_NONE;
268 const std::map<std::string, std::shared_ptr<KeyInfo>>& Bundle::GetMap() {
272 std::vector<std::string> Bundle::Export() {
273 std::vector<std::string> argv(2);
274 for (const auto& key_info : list_) {
275 argv.push_back(key_info->GetKey());
277 auto encoded_bytes = key_info->Encode();
278 auto* p = reinterpret_cast<unsigned char*>(&encoded_bytes[0]);
279 auto* base64_bytes = g_base64_encode(p, encoded_bytes.size());
280 if (base64_bytes == nullptr)
281 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
283 std::unique_ptr<gchar, decltype(g_free)*> base64_bytes_ptr(base64_bytes,
285 argv.push_back(base64_bytes);
291 int Bundle::Import(int argc, char** argv) {
293 return BUNDLE_ERROR_NONE;
295 if (!argv[1] || std::strcmp(argv[1], TAG_IMPORT_EXPORT_CHECK)) {
296 for (int idx = 1; idx + 1 < argc; idx += 2) {
297 auto* p = reinterpret_cast<unsigned char*>(argv[idx +1]);
298 auto len = strlen(argv[idx + 1]) + 1;
299 std::vector<unsigned char> value;
300 std::copy(p, p + len, std::back_inserter(value));
302 KeyInfo* new_key_info;
304 new_key_info = new KeyInfo(Type::String, argv[idx], value);
305 } catch (Exception& e) {
306 return e.GetErrorCode();
307 } catch (const std::bad_alloc& ba) {
308 return BUNDLE_ERROR_OUT_OF_MEMORY;
311 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
312 auto iter = map_.find(key_info->GetKey());
313 if (iter != map_.end())
316 map_[key_info->GetKey()] = key_info;
317 list_.push_back(key_info);
319 return BUNDLE_ERROR_NONE;
322 for (int idx = 2; idx + 1 < argc; idx += 2) {
324 auto* bytes = g_base64_decode(argv[idx + 1], &out_len);
325 if (bytes == nullptr)
326 return BUNDLE_ERROR_OUT_OF_MEMORY;
328 std::unique_ptr<guchar, decltype(g_free)*> bytes_ptr(bytes, g_free);
330 if (out_len < sizeof(std::size_t))
333 auto* p = reinterpret_cast<unsigned char*>(bytes);
334 std::vector<unsigned char> decoded_bytes(p, p + (out_len + 1));
336 KeyInfo* new_key_info;
338 new_key_info = new KeyInfo(decoded_bytes);
339 } catch (Exception& e) {
340 return e.GetErrorCode();
341 } catch (const std::bad_alloc& ba) {
342 return BUNDLE_ERROR_OUT_OF_MEMORY;
345 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
346 auto iter = map_.find(key_info->GetKey());
347 if (iter != map_.end())
350 map_[key_info->GetKey()] = key_info;
351 list_.push_back(key_info);
354 return BUNDLE_ERROR_NONE;
357 } // namespace internal
358 } // namespace tizen_base