Fix wrong implementation about encoding & decoding bundle raw
[platform/core/base/bundle.git] / src / bundle-internal.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <errno.h>
18 #include <glib.h>
19
20 #include <cstring>
21
22 #include "include/bundle.h"
23
24 #include "bundle-internal.h"
25 #include "exception-internal.h"
26
27 namespace tizen_base {
28 namespace internal {
29
30 static const int CHECKSUM_LENGTH = 32;
31
32 Bundle::Bundle() = default;
33
34 Bundle::Bundle(unsigned char* raw, int size) {
35   int ret = Decode(raw, size);
36   if (ret != BUNDLE_ERROR_NONE)
37     THROW(ret);
38 }
39
40 Bundle::Bundle(int argc, char** argv) {
41   int ret = Import(argc, argv);
42   if (ret != BUNDLE_ERROR_NONE)
43     THROW(ret);
44 }
45
46 Bundle::~Bundle() = default;
47
48 Bundle::Bundle(const Bundle& b) {
49   map_ = b.map_;
50   list_ = b.list_;
51 }
52
53 Bundle& Bundle::operator = (const Bundle& b) {
54   if (this != &b) {
55     map_ = b.map_;
56     list_ = b.list_;
57   }
58   return *this;
59 }
60
61 Bundle::Bundle(Bundle&& b) noexcept {
62   map_ = std::move(b.map_);
63   list_ = std::move(b.list_);
64 }
65
66 Bundle& Bundle::operator = (Bundle&& b) noexcept {
67   if (this != &b) {
68     map_ = std::move(b.map_);
69     list_ = std::move(b.list_);
70   }
71   return *this;
72 }
73
74 bool Bundle::operator == (const Bundle& b) {
75   if (this == &b)
76     return true;
77
78   if (map_.size() != b.map_.size())
79     return false;
80
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())
85       return false;
86
87     auto& rhs = iter->second;
88     if (!(lhs == rhs))
89       return false;
90   }
91
92   return true;
93 }
94
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);
99
100   list_.remove(iter->second);
101   map_.erase(iter);
102 }
103
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);
108
109   map_[key_info->GetKey()] = key_info;
110   list_.push_back(key_info);
111 }
112
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);
118
119   int ret = iter->second->SetValue(index, value);
120   if (ret != BUNDLE_ERROR_NONE)
121     THROW(ret);
122 }
123
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);
128
129   return iter->second;
130 }
131
132 int Bundle::GetSize() {
133   return map_.size();
134 }
135
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);
140
141   return iter->second->GetType();
142 }
143
144 unsigned char* Bundle::Encode() {
145   int size = 0;
146   unsigned char* raw;
147   try {
148     raw = EncodeRaw(&size);
149   } catch (Exception& e) {
150     THROW(e.GetErrorCode());
151   }
152
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);
159
160   return reinterpret_cast<unsigned char*>(encoded_data);
161 }
162
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;
167
168   std::unique_ptr<unsigned char[]> d_ptr(d_str);
169   gint state = 0;
170   guint save = 0;
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;
175
176   return DecodeRaw(d_str, d_len_raw);
177 }
178
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());
184   }
185
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);
192
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);
196
197   unsigned char* raw = static_cast<unsigned char*>(malloc(bytes.size()));
198   if (raw == nullptr)
199     THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
200
201   std::copy(bytes.begin(), bytes.end(), raw);
202   *size = static_cast<int>(bytes.size());
203   return raw;
204 }
205
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;
210
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';
216
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;
222
223   std::unique_ptr<char, decltype(std::free)*> compute_ptr(compute_checksum,
224       std::free);
225   if (strcmp(extract_checksum, compute_checksum) != 0)
226     return BUNDLE_ERROR_INVALID_PARAMETER;
227
228   unsigned char* d_r = d_str + CHECKSUM_LENGTH;
229   unsigned int d_len = d_len_raw - CHECKSUM_LENGTH;
230
231   unsigned int reader = 0;
232   std::vector<unsigned char> bytes(d_r, d_r + d_len);
233
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);
238
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;
243
244     KeyInfo* new_key_info;
245     try {
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;
251     }
252
253     auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
254     auto iter = map_.find(key_info->GetKey());
255     if (iter != map_.end())
256       continue;
257
258     map_[key_info->GetKey()] = key_info;
259     list_.push_back(key_info);
260   }
261
262   return BUNDLE_ERROR_NONE;
263 }
264
265 const std::map<std::string, std::shared_ptr<KeyInfo>>& Bundle::GetMap() {
266   return map_;
267 }
268
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());
273
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);
279
280     std::unique_ptr<char, decltype(std::free)*> base64_bytes_ptr(base64_bytes,
281         std::free);
282     argv.push_back(base64_bytes);
283   }
284
285   return argv;
286 }
287
288 int Bundle::Import(int argc, char** argv) {
289   if (argc < 2)
290     return BUNDLE_ERROR_NONE;
291
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));
298
299       KeyInfo* new_key_info;
300       try {
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;
306       }
307
308       auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
309       auto iter = map_.find(key_info->GetKey());
310       if (iter != map_.end())
311         continue;
312
313       map_[key_info->GetKey()] = key_info;
314       list_.push_back(key_info);
315     }
316     return BUNDLE_ERROR_NONE;
317   }
318
319   for (int idx = 2; idx + 1 < argc; idx += 2) {
320     gsize out_len = 0;
321     auto* bytes = g_base64_decode(argv[idx + 1], &out_len);
322     if (bytes == nullptr)
323       return BUNDLE_ERROR_OUT_OF_MEMORY;
324
325     std::unique_ptr<guchar, decltype(g_free)*> bytes_ptr(bytes, g_free);
326
327     if (out_len < sizeof(std::size_t))
328       continue;
329
330     auto* p = reinterpret_cast<unsigned char*>(bytes);
331     std::vector<unsigned char> decoded_bytes(p, p + (out_len + 1));
332
333     KeyInfo* new_key_info;
334     try {
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;
340     }
341
342     auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
343     auto iter = map_.find(key_info->GetKey());
344     if (iter != map_.end())
345       continue;
346
347     map_[key_info->GetKey()] = key_info;
348     list_.push_back(key_info);
349   }
350
351   return BUNDLE_ERROR_NONE;
352 }
353
354 }  // namespace internal
355 }  // namespace tizen_base