Change gchar string free function
[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, bool base64) {
35   int ret;
36   if (base64)
37     ret = Decode(raw, size);
38   else
39     ret = DecodeRaw(raw, size);
40   if (ret != BUNDLE_ERROR_NONE)
41     THROW(ret);
42 }
43
44 Bundle::Bundle(int argc, char** argv) {
45   int ret = Import(argc, argv);
46   if (ret != BUNDLE_ERROR_NONE)
47     THROW(ret);
48 }
49
50 Bundle::~Bundle() = default;
51
52 Bundle::Bundle(const Bundle& b) {
53   map_ = b.map_;
54   list_ = b.list_;
55 }
56
57 Bundle& Bundle::operator = (const Bundle& b) {
58   if (this != &b) {
59     map_ = b.map_;
60     list_ = b.list_;
61   }
62   return *this;
63 }
64
65 Bundle::Bundle(Bundle&& b) noexcept {
66   map_ = std::move(b.map_);
67   list_ = std::move(b.list_);
68 }
69
70 Bundle& Bundle::operator = (Bundle&& b) noexcept {
71   if (this != &b) {
72     map_ = std::move(b.map_);
73     list_ = std::move(b.list_);
74   }
75   return *this;
76 }
77
78 bool Bundle::operator == (const Bundle& b) {
79   if (this == &b)
80     return true;
81
82   if (map_.size() != b.map_.size())
83     return false;
84
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())
89       return false;
90
91     auto& rhs = iter->second;
92     if (!(lhs == rhs))
93       return false;
94   }
95
96   return true;
97 }
98
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);
103
104   list_.remove(iter->second);
105   map_.erase(iter);
106 }
107
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);
112
113   map_[key_info->GetKey()] = key_info;
114   list_.push_back(key_info);
115 }
116
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);
122
123   int ret = iter->second->SetValue(index, value);
124   if (ret != BUNDLE_ERROR_NONE)
125     THROW(ret);
126 }
127
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);
132
133   return iter->second;
134 }
135
136 int Bundle::GetSize() {
137   return map_.size();
138 }
139
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);
144
145   return iter->second->GetType();
146 }
147
148 unsigned char* Bundle::Encode() {
149   int size = 0;
150   unsigned char* raw;
151   try {
152     raw = EncodeRaw(&size);
153   } catch (Exception& e) {
154     THROW(e.GetErrorCode());
155   }
156
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);
163
164   return reinterpret_cast<unsigned char*>(encoded_data);
165 }
166
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;
171
172   std::unique_ptr<unsigned char[]> d_ptr(d_str);
173   gint state = 0;
174   guint save = 0;
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;
179
180   return DecodeRaw(d_str, d_len_raw);
181 }
182
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());
188   }
189
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);
195
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);
199
200   unsigned char* raw = static_cast<unsigned char*>(malloc(bytes.size()));
201   if (raw == nullptr)
202     THROW(BUNDLE_ERROR_OUT_OF_MEMORY);
203
204   std::copy(bytes.begin(), bytes.end(), raw);
205   *size = static_cast<int>(bytes.size());
206   return raw;
207 }
208
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;
213
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';
219
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;
225
226   std::unique_ptr<gchar, decltype(g_free)*> compute_ptr(compute_checksum,
227       g_free);
228   if (strcmp(extract_checksum, static_cast<char*>(compute_checksum)) != 0)
229     return BUNDLE_ERROR_INVALID_PARAMETER;
230
231   unsigned char* d_r = d_str + CHECKSUM_LENGTH;
232   unsigned int d_len = d_len_raw - CHECKSUM_LENGTH;
233
234   unsigned int reader = 0;
235   std::vector<unsigned char> bytes(d_r, d_r + d_len);
236
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);
241
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;
246
247     KeyInfo* new_key_info;
248     try {
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;
254     }
255
256     auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
257     auto iter = map_.find(key_info->GetKey());
258     if (iter != map_.end())
259       continue;
260
261     map_[key_info->GetKey()] = key_info;
262     list_.push_back(key_info);
263   }
264
265   return BUNDLE_ERROR_NONE;
266 }
267
268 const std::map<std::string, std::shared_ptr<KeyInfo>>& Bundle::GetMap() {
269   return map_;
270 }
271
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());
276
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);
282
283     std::unique_ptr<gchar, decltype(g_free)*> base64_bytes_ptr(base64_bytes,
284         g_free);
285     argv.push_back(base64_bytes);
286   }
287
288   return argv;
289 }
290
291 int Bundle::Import(int argc, char** argv) {
292   if (argc < 2)
293     return BUNDLE_ERROR_NONE;
294
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));
301
302       KeyInfo* new_key_info;
303       try {
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;
309       }
310
311       auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
312       auto iter = map_.find(key_info->GetKey());
313       if (iter != map_.end())
314         continue;
315
316       map_[key_info->GetKey()] = key_info;
317       list_.push_back(key_info);
318     }
319     return BUNDLE_ERROR_NONE;
320   }
321
322   for (int idx = 2; idx + 1 < argc; idx += 2) {
323     gsize out_len = 0;
324     auto* bytes = g_base64_decode(argv[idx + 1], &out_len);
325     if (bytes == nullptr)
326       return BUNDLE_ERROR_OUT_OF_MEMORY;
327
328     std::unique_ptr<guchar, decltype(g_free)*> bytes_ptr(bytes, g_free);
329
330     if (out_len < sizeof(std::size_t))
331       continue;
332
333     auto* p = reinterpret_cast<unsigned char*>(bytes);
334     std::vector<unsigned char> decoded_bytes(p, p + (out_len + 1));
335
336     KeyInfo* new_key_info;
337     try {
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;
343     }
344
345     auto key_info = std::shared_ptr<KeyInfo>(new_key_info);
346     auto iter = map_.find(key_info->GetKey());
347     if (iter != map_.end())
348       continue;
349
350     map_[key_info->GetKey()] = key_info;
351     list_.push_back(key_info);
352   }
353
354   return BUNDLE_ERROR_NONE;
355 }
356
357 }  // namespace internal
358 }  // namespace tizen_base