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) {
35 int ret = Decode(raw, size);
36 if (ret != BUNDLE_ERROR_NONE)
40 Bundle::Bundle(int argc, char** argv) {
41 int ret = Import(argc, argv);
42 if (ret != BUNDLE_ERROR_NONE)
46 Bundle::~Bundle() = default;
48 Bundle::Bundle(const Bundle& b) {
53 Bundle& Bundle::operator = (const Bundle& b) {
61 Bundle::Bundle(Bundle&& b) noexcept {
62 map_ = std::move(b.map_);
63 list_ = std::move(b.list_);
66 Bundle& Bundle::operator = (Bundle&& b) noexcept {
68 map_ = std::move(b.map_);
69 list_ = std::move(b.list_);
74 bool Bundle::operator == (const Bundle& b) {
78 if (map_.size() != b.map_.size())
81 for (const auto& kv : map_) {
82 auto& lhs = kv.second;
83 auto iter = b.map_.find(lhs->GetKey());
84 if (iter == b.map_.end())
87 auto& rhs = iter->second;
95 void Bundle::Remove(const std::string& key) {
96 auto iter = map_.find(key);
97 if (iter == map_.end())
98 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
100 list_.remove(iter->second);
104 void Bundle::Add(std::shared_ptr<KeyInfo> key_info) {
105 auto iter = map_.find(key_info->GetKey());
106 if (iter != map_.end())
107 THROW(BUNDLE_ERROR_KEY_EXISTS);
109 map_[key_info->GetKey()] = key_info;
110 list_.push_back(key_info);
113 void Bundle::Set(const std::string& key, int index,
114 std::vector<unsigned char> value) {
115 auto iter = map_.find(key);
116 if (iter == map_.end())
117 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
119 int ret = iter->second->SetValue(index, value);
120 if (ret != BUNDLE_ERROR_NONE)
124 std::shared_ptr<KeyInfo>& Bundle::Get(const std::string& key) {
125 auto iter = map_.find(key.c_str());
126 if (iter == map_.end())
127 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
132 int Bundle::GetSize() {
136 int Bundle::GetType(const std::string& key) {
137 auto iter = map_.find(key);
138 if (iter == map_.end())
139 THROW(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
141 return iter->second->GetType();
144 unsigned char* Bundle::Encode() {
148 raw = EncodeRaw(&size);
149 } catch (Exception& e) {
150 THROW(e.GetErrorCode());
153 std::unique_ptr<unsigned char, decltype(std::free)*> raw_ptr(raw, std::free);
154 char* encoded_data = reinterpret_cast<char*>(
155 g_base64_encode(reinterpret_cast<guchar*>(raw),
156 static_cast<gsize>(size)));
157 if (encoded_data == nullptr)
158 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
160 return reinterpret_cast<unsigned char*>(encoded_data);
163 int Bundle::Decode(unsigned char* raw, int size) {
164 unsigned char* d_str = new (std::nothrow) unsigned char[(size / 4) * 3 + 3];
165 if (d_str == nullptr)
166 return BUNDLE_ERROR_OUT_OF_MEMORY;
168 std::unique_ptr<unsigned char[]> d_ptr(d_str);
171 unsigned int d_len_raw = g_base64_decode_step(reinterpret_cast<char*>(raw),
172 size, d_str, &state, &save);
173 if (d_len_raw < CHECKSUM_LENGTH)
174 return BUNDLE_ERROR_OUT_OF_MEMORY;
176 return DecodeRaw(d_str, d_len_raw);
179 unsigned char* Bundle::EncodeRaw(int* size) {
180 std::vector<unsigned char> bytes;
181 for (const auto& key_info : list_) {
182 auto encoded_bytes = key_info->Encode();
183 bytes.insert(bytes.end(), encoded_bytes.begin(), encoded_bytes.end());
186 char* checksum = static_cast<char*>(
187 g_compute_checksum_for_string(G_CHECKSUM_MD5,
188 reinterpret_cast<gchar*>(&bytes[0]),
189 static_cast<gssize>(bytes.size())));
190 if (checksum == nullptr)
191 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
193 std::unique_ptr<char, decltype(std::free)*> ptr(checksum, std::free);
194 unsigned char* p = reinterpret_cast<unsigned char*>(checksum);
195 bytes.insert(bytes.begin(), p, p + CHECKSUM_LENGTH);
197 unsigned char* raw = static_cast<unsigned char*>(malloc(bytes.size()));
199 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
201 std::copy(bytes.begin(), bytes.end(), raw);
202 *size = static_cast<int>(bytes.size());
206 int Bundle::DecodeRaw(unsigned char* raw, int size) {
207 char* extract_checksum = new (std::nothrow) char[CHECKSUM_LENGTH + 1];
208 if (extract_checksum == nullptr)
209 return BUNDLE_ERROR_OUT_OF_MEMORY;
211 std::unique_ptr<char[]> extract_ptr(extract_checksum);
212 unsigned char* d_str = raw;
213 unsigned int d_len_raw = size;
214 strncpy(extract_checksum, reinterpret_cast<char*>(d_str), CHECKSUM_LENGTH);
215 extract_checksum[CHECKSUM_LENGTH] = '\0';
217 char* compute_checksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,
218 reinterpret_cast<char*>(d_str + CHECKSUM_LENGTH),
219 d_len_raw - CHECKSUM_LENGTH);
220 if (compute_checksum == nullptr)
221 return BUNDLE_ERROR_OUT_OF_MEMORY;
223 std::unique_ptr<char, decltype(std::free)*> compute_ptr(compute_checksum,
225 if (strcmp(extract_checksum, compute_checksum) != 0)
226 return BUNDLE_ERROR_INVALID_PARAMETER;
228 unsigned char* d_r = d_str + CHECKSUM_LENGTH;
229 unsigned int d_len = d_len_raw - CHECKSUM_LENGTH;
231 unsigned int reader = 0;
232 std::vector<unsigned char> bytes(d_r, d_r + d_len);
234 while (reader < bytes.size()) {
235 std::size_t total_size = -1;
236 unsigned char* p = reinterpret_cast<unsigned char*>(&total_size);
237 std::copy(&bytes[reader], &bytes[reader] + sizeof(total_size), p);
239 std::vector<unsigned char> encoded_bytes;
240 std::copy(&bytes[reader], &bytes[reader] + total_size,
241 std::back_inserter(encoded_bytes));
242 reader += total_size;
244 KeyInfo* new_key_info;
246 new_key_info = new KeyInfo(encoded_bytes);
247 } catch (Exception& e) {
248 return e.GetErrorCode();
249 } catch (const std::bad_alloc& ba) {
250 return BUNDLE_ERROR_OUT_OF_MEMORY;
253 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
254 auto iter = map_.find(key_info->GetKey());
255 if (iter != map_.end())
258 map_[key_info->GetKey()] = key_info;
259 list_.push_back(key_info);
262 return BUNDLE_ERROR_NONE;
265 const std::map<std::string, std::shared_ptr<KeyInfo>>& Bundle::GetMap() {
269 std::vector<std::string> Bundle::Export() {
270 std::vector<std::string> argv(2);
271 for (const auto& key_info : list_) {
272 argv.push_back(key_info->GetKey());
274 auto encoded_bytes = key_info->Encode();
275 auto* p = reinterpret_cast<unsigned char*>(&encoded_bytes[0]);
276 auto* base64_bytes = g_base64_encode(p, encoded_bytes.size());
277 if (base64_bytes == nullptr)
278 THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
280 std::unique_ptr<char, decltype(std::free)*> base64_bytes_ptr(base64_bytes,
282 argv.push_back(base64_bytes);
288 int Bundle::Import(int argc, char** argv) {
290 return BUNDLE_ERROR_NONE;
292 if (!argv[1] || std::strcmp(argv[1], TAG_IMPORT_EXPORT_CHECK)) {
293 for (int idx = 1; idx + 1 < argc; idx += 2) {
294 auto* p = reinterpret_cast<unsigned char*>(argv[idx +1]);
295 auto len = strlen(argv[idx + 1]) + 1;
296 std::vector<unsigned char> value;
297 std::copy(p, p + len, std::back_inserter(value));
299 KeyInfo* new_key_info;
301 new_key_info = new KeyInfo(Type::String, argv[idx], value);
302 } catch (Exception& e) {
303 return e.GetErrorCode();
304 } catch (const std::bad_alloc& ba) {
305 return BUNDLE_ERROR_OUT_OF_MEMORY;
308 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
309 auto iter = map_.find(key_info->GetKey());
310 if (iter != map_.end())
313 map_[key_info->GetKey()] = key_info;
314 list_.push_back(key_info);
316 return BUNDLE_ERROR_NONE;
319 for (int idx = 2; idx + 1 < argc; idx += 2) {
321 auto* bytes = g_base64_decode(argv[idx + 1], &out_len);
322 if (bytes == nullptr)
323 return BUNDLE_ERROR_OUT_OF_MEMORY;
325 std::unique_ptr<guchar, decltype(g_free)*> bytes_ptr(bytes, g_free);
327 if (out_len < sizeof(std::size_t))
330 auto* p = reinterpret_cast<unsigned char*>(bytes);
331 std::vector<unsigned char> decoded_bytes(p, p + (out_len + 1));
333 KeyInfo* new_key_info;
335 new_key_info = new KeyInfo(decoded_bytes);
336 } catch (Exception& e) {
337 return e.GetErrorCode();
338 } catch (const std::bad_alloc& ba) {
339 return BUNDLE_ERROR_OUT_OF_MEMORY;
342 auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
343 auto iter = map_.find(key_info->GetKey());
344 if (iter != map_.end())
347 map_[key_info->GetKey()] = key_info;
348 list_.push_back(key_info);
351 return BUNDLE_ERROR_NONE;
354 } // namespace internal
355 } // namespace tizen_base