Add IsEmpty() method
[platform/core/base/bundle.git] / src / bundle.c
1 /*
2  * Copyright (c) 2000 - 2016 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 /**
18  * bundle.c
19  */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <glib.h>
24
25 #include "bundle.h"
26 #include "bundle_internal.h"
27 #include "bundle_log.h"
28 #include "bundle_private.h"
29 #include "keyval.h"
30 #include "keyval_array.h"
31 #include "keyval_type.h"
32
33 #define CHECKSUM_LENGTH 32
34 #define TAG_IMPORT_EXPORT_CHECK "`zaybxcwdveuftgsh`"
35
36 /* ADT */
37 struct _bundle_t {
38         keyval_t *kv_head;
39 };
40
41 /**
42  * Find a kv from bundle
43  */
44 static keyval_t *_bundle_find_kv(bundle *b, const char *key)
45 {
46         keyval_t *kv;
47
48         if (b == NULL) {
49                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
50                 return NULL;
51         }
52
53         if (key == NULL) {
54                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
55                 return NULL;
56         }
57
58         kv = b->kv_head;
59         while (kv != NULL) {
60                 if (strcmp(key, kv->key) == 0) {
61                         set_last_result(BUNDLE_ERROR_NONE);
62                         return kv;
63                 }
64                 kv = kv->next;
65         }
66         /* Not found */
67         set_last_result(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
68         return NULL;
69 }
70
71 /**
72  * Append kv into bundle
73  */
74 static int _bundle_append_kv(bundle *b, keyval_t *new_kv)
75 {
76         keyval_t *kv;
77
78         if (b->kv_head == NULL) {
79                 b->kv_head = new_kv;
80         } else {
81                 kv = b->kv_head;
82                 while (kv->next)
83                         kv = kv->next;
84                 kv->next = new_kv;
85         }
86
87         return BUNDLE_ERROR_NONE;
88 }
89
90 static int _bundle_add_kv(bundle *b, const char *key, const void *val,
91                 const size_t size, const int type, const unsigned int len)
92 {
93         keyval_t *kv;
94         keyval_t *new_kv;
95         keyval_array_t *kva;
96
97         /* basic value check */
98         if (b == NULL)
99                 return BUNDLE_ERROR_INVALID_PARAMETER;
100         if (key == NULL)
101                 return BUNDLE_ERROR_INVALID_PARAMETER;
102         if (strlen(key) == 0)
103                 return BUNDLE_ERROR_INVALID_PARAMETER;
104
105         kv = _bundle_find_kv(b, key);
106         if (kv) /* Key already exists */
107                 return BUNDLE_ERROR_KEY_EXISTS;
108
109         if (keyval_type_is_array(type)) {
110                 /* array type */
111                 kva = keyval_array_new(NULL, key, type,
112                                 (const void **) val, len);
113                 new_kv = (keyval_t *)kva;
114         } else {
115                 /* normal type */
116                 new_kv = keyval_new(NULL, key, type, val, size);
117         }
118
119         if (!new_kv)
120                 return BUNDLE_ERROR_OUT_OF_MEMORY;
121
122         _bundle_append_kv(b, new_kv);
123
124         return BUNDLE_ERROR_NONE;
125 }
126
127 static int _bundle_get_val(bundle *b, const char *key, const int type,
128                 void **val, size_t *size, unsigned int *len,
129                 size_t **array_element_size)
130 {
131         keyval_t *kv;
132         keyval_array_t *kva;
133
134         kv = _bundle_find_kv(b, key);
135         if (!kv) /* Key doesn't exist */
136                 return get_last_result();
137
138         if (BUNDLE_TYPE_ANY != type && type != kv->type)
139                 return BUNDLE_ERROR_INVALID_PARAMETER;
140
141         if (keyval_type_is_array(type)) {
142                 kva = (keyval_array_t *)kv;
143                 keyval_array_get_data(kva, NULL, (void ***)val,
144                                 len, array_element_size);
145         } else {
146                 keyval_get_data(kv, NULL, val, size);
147         }
148
149         return BUNDLE_ERROR_NONE;
150 }
151
152 /**
153  * global initialization
154  * Run only once.
155  */
156 static void _bundle_global_init(void)
157 {
158         static int _is_done;
159
160         if (_is_done)
161                 return;
162
163         /* Run init functions */
164         keyval_type_init();
165
166         _is_done = 1;
167         return;
168 }
169
170 /* APIs */
171 API bundle *bundle_create(void)
172 {
173         bundle *b = NULL;
174
175         _bundle_global_init();
176
177         b = calloc(1, sizeof(bundle));  /* fill mem with NULL */
178         if (b == NULL) {
179                 BUNDLE_EXCEPTION_PRINT(
180                                 "Unable to allocate memory for bundle\n");
181                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
182                 goto exception;
183         }
184
185         set_last_result(BUNDLE_ERROR_NONE);
186         return b;
187
188 exception:
189         return NULL;
190 }
191
192 API int bundle_free(bundle *b)
193 {
194         keyval_t *kv;
195         keyval_t *tmp_kv;
196
197         if (b == NULL) {
198                 BUNDLE_EXCEPTION_PRINT("Bundle is already freed\n");
199                 return BUNDLE_ERROR_INVALID_PARAMETER;
200         }
201
202         /* Free keyval list */
203         kv = b->kv_head;
204         while (kv) {
205                 tmp_kv = kv;
206                 kv = kv->next;
207                 tmp_kv->method->free(tmp_kv, 1);
208         }
209
210         /* free bundle */
211         free(b);
212
213         return BUNDLE_ERROR_NONE;
214 }
215
216 API int bundle_add_str(bundle *b, const char *key, const char *str)
217 {
218         if (!str)
219                 return BUNDLE_ERROR_INVALID_PARAMETER;
220         return _bundle_add_kv(b, key, str, strlen(str) + 1, BUNDLE_TYPE_STR, 1);
221 }
222
223 API int bundle_get_str(bundle *b, const char *key, char **str)
224 {
225         return _bundle_get_val(b, key, BUNDLE_TYPE_STR, (void **)str,
226                         NULL, NULL, NULL);
227 }
228
229 API int bundle_add(bundle *b, const char *key, const char *val)
230 {
231         return bundle_add_str(b, key, val);
232 }
233
234 API int bundle_del(bundle *b, const char *key)
235 {
236         keyval_t *kv;
237         keyval_t *prev_kv = NULL;
238
239         /* basic value check */
240         if (b == NULL)
241                 return BUNDLE_ERROR_INVALID_PARAMETER;
242         if (key == NULL)
243                 return BUNDLE_ERROR_INVALID_PARAMETER;
244         if (strlen(key) == 0)
245                 return BUNDLE_ERROR_INVALID_PARAMETER;
246
247         kv = b->kv_head;
248         while (kv) {
249                 if (strcmp(key, kv->key) == 0)
250                         break;
251                 prev_kv = kv;
252                 kv = kv->next;
253         }
254
255         if (kv == NULL) {
256                 return BUNDLE_ERROR_KEY_NOT_AVAILABLE;
257         } else {
258                 if (prev_kv)
259                         prev_kv->next = kv->next;
260                 if (kv == b->kv_head)
261                         b->kv_head = kv->next;
262                 kv->method->free(kv, 1);
263         }
264
265         return BUNDLE_ERROR_NONE;
266 }
267
268 API const char *bundle_get_val(bundle *b, const char *key)
269 {
270         char *val = NULL;
271         int ret = BUNDLE_ERROR_NONE;
272
273         ret = bundle_get_str(b, key, &val);
274         set_last_result(ret);
275
276         return val;
277 }
278
279 /**
280  * @brief used by bundle_get_count() API, to count number of items in a bundle
281  */
282 static void _bundle_get_count_iter(const char *k, const int type,
283                 const bundle_keyval_t *kv, void *user_data)
284 {
285         int *count = (int *)user_data;
286         *count += 1;
287 }
288
289 API int bundle_get_count(bundle *b)
290 {
291         int count = 0;
292
293         if (b == NULL)
294                 return count;
295         bundle_foreach(b, _bundle_get_count_iter, &count);
296         return count;
297 }
298
299 API void bundle_iterate(bundle *b, bundle_iterate_cb_t callback, void *data)
300 {
301         keyval_t *kv;
302
303         if (b == NULL || callback == NULL) {
304                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
305                 return;
306         }
307
308         kv = b->kv_head;
309         while (kv) {
310                 callback(kv->key, kv->val, data);
311                 kv = kv->next;
312         }
313
314         set_last_result(BUNDLE_ERROR_NONE);
315 }
316
317 API void bundle_foreach(bundle *b, bundle_iterator_t iter, void *user_data)
318 {
319         keyval_t *kv;
320
321         if (b == NULL || iter == NULL) {
322                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
323                 return; /* TC_FIX if b = NULL- error handling */
324         }
325
326         kv = b->kv_head;
327         while (kv) {
328                 iter(kv->key, kv->type, kv, user_data);
329                 kv = kv->next;
330         }
331
332         set_last_result(BUNDLE_ERROR_NONE);
333 }
334
335 /* keyval functions */
336 API int bundle_keyval_get_type(bundle_keyval_t *kv)
337 {
338         if (kv == NULL) {
339                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
340                 return -1;
341         }
342         set_last_result(BUNDLE_ERROR_NONE);
343         return kv->type;
344 }
345
346 API int bundle_keyval_type_is_array(bundle_keyval_t *kv)
347 {
348         if (kv == NULL) {
349                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
350                 return -1;
351         }
352         set_last_result(BUNDLE_ERROR_NONE);
353         return keyval_type_is_array(kv->type);
354 }
355
356 API int bundle_keyval_type_is_measurable(bundle_keyval_t *kv)
357 {
358         if (kv == NULL) {
359                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
360                 return -1;
361         }
362         set_last_result(BUNDLE_ERROR_NONE);
363         return keyval_type_is_measurable(kv->type);
364 }
365
366 API int bundle_keyval_get_basic_val(bundle_keyval_t *kv, void **val,
367                 size_t *size)
368 {
369         return keyval_get_data(kv, NULL, val, size);
370 }
371
372 API int bundle_keyval_get_array_val(bundle_keyval_t *kv, void ***array_val,
373                 unsigned int *array_len, size_t **array_item_size)
374 {
375         return keyval_array_get_data((keyval_array_t *)kv, NULL,
376                         array_val, array_len, array_item_size);
377 }
378
379 API bundle_keyval_t *bundle_keyval_dup(const bundle_keyval_t *kv)
380 {
381         bundle_keyval_t *ret_kv = NULL;
382         void *byte = NULL;
383         size_t byte_len;
384         size_t len;
385
386         if (!kv)
387                 return NULL;
388
389         if (keyval_type_is_array(kv->type)) {
390                 len = keyval_array_encode(
391                         (keyval_array_t *)kv, &byte, &byte_len);
392                 if (len == 0)
393                         return NULL;
394                 len = keyval_array_decode(byte,
395                         (keyval_array_t **)&ret_kv, byte_len);
396                 free(byte);
397                 if (len == 0)
398                         return NULL;
399         } else {
400                 len = keyval_encode((keyval_t *)kv,
401                         (unsigned char **)&byte, &byte_len);
402                 if (len == 0)
403                         return NULL;
404                 len = keyval_decode(
405                         (unsigned char *)byte, (keyval_t **)&ret_kv, byte_len);
406                 free(byte);
407                 if (len == 0)
408                         return NULL;
409         }
410         return ret_kv;
411 }
412
413 API bundle *bundle_dup(bundle *b_from)
414 {
415         bundle *b_to;
416         keyval_t *kv_from;
417         keyval_t *kv_to;
418         keyval_array_t *kva_from;
419         int i;
420
421         if (b_from == NULL) {
422                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
423                 return NULL;
424         }
425
426         b_to = bundle_create();
427         if (b_to == NULL)
428                 return NULL;
429
430         kv_from = b_from->kv_head;
431         while (kv_from != NULL) {
432                 if (keyval_type_is_array(kv_from->type)) {
433                         kva_from = (keyval_array_t *)kv_from;
434                         kv_to = (keyval_t *)keyval_array_new(NULL, kv_from->key,
435                                         kv_from->type, NULL, kva_from->len);
436                         if (!kv_to)
437                                 goto err;
438
439                         for (i = 0; i < kva_from->len; i++) {
440                                 if (((keyval_array_t *)kv_from)->array_val[i]) {
441                                         keyval_array_set_element(
442                                                         (keyval_array_t *)kv_to, i,
443                                                         ((keyval_array_t *)kv_from)->array_val[i],
444                                                         ((keyval_array_t *)kv_from)->array_element_size[i]);
445                                 }
446                         }
447
448                         _bundle_append_kv(b_to, kv_to);
449                 } else {
450                         if (_bundle_add_kv(b_to, kv_from->key,
451                                 kv_from->val, kv_from->size, kv_from->type, 0))
452                                 goto err;
453                 }
454
455                 kv_from = kv_from->next;
456         }
457
458         return b_to;
459
460 err:
461         bundle_free(b_to);
462         return NULL;
463 }
464
465 API int bundle_encode(bundle *b, bundle_raw **r, int *len)
466 {
467         keyval_t *kv;
468         unsigned char *m;
469         unsigned char *p_m;
470         unsigned char *byte;
471         size_t byte_len;
472         gchar *chksum_val;
473         size_t msize = 0;
474
475         if (b == NULL || r == NULL || len == NULL)
476                 return BUNDLE_ERROR_INVALID_PARAMETER;
477
478         /* calculate memory size */
479         kv = b->kv_head;
480         while (kv != NULL) {
481                 msize += kv->method->get_encoded_size(kv);
482                 kv = kv->next;
483         }
484
485         m = calloc(msize + CHECKSUM_LENGTH, sizeof(unsigned char));
486         if (unlikely(m == NULL))
487                 return BUNDLE_ERROR_OUT_OF_MEMORY;
488
489         p_m = m + CHECKSUM_LENGTH; /* temporary pointer */
490
491         kv = b->kv_head;
492         while (kv != NULL) {
493                 byte = NULL;
494                 byte_len = 0;
495
496                 kv->method->encode(kv, &byte, &byte_len);
497                 memcpy(p_m, byte, byte_len);
498
499                 p_m += byte_len;
500                 kv = kv->next;
501
502                 free(byte);
503         }
504
505         /* compute checksum from the data */
506         chksum_val = g_compute_checksum_for_string(G_CHECKSUM_MD5,
507                         (const char *)(m + CHECKSUM_LENGTH), msize);
508         /* prefix checksum to the data */
509         memcpy(m, chksum_val, CHECKSUM_LENGTH);
510         if (r) {
511                 /* base64 encode for whole string checksum and data */
512                 *r = (unsigned char *)g_base64_encode(m, msize + CHECKSUM_LENGTH);
513                 if (len)
514                         *len = strlen((char *)*r);
515         }
516         free(m);
517         g_free(chksum_val); /* free checksum string */
518
519         return BUNDLE_ERROR_NONE;
520 }
521
522 API int bundle_free_encoded_rawdata(bundle_raw **r)
523 {
524         if (!*r)
525                 return BUNDLE_ERROR_INVALID_PARAMETER; /* TC_FIX - double free sigabrt handling */
526
527         free(*r);
528         *r = NULL;
529         return BUNDLE_ERROR_NONE;
530 }
531
532 API bundle *bundle_decode(const bundle_raw *r, const int data_size)
533 {
534         bundle *b;
535         bundle_raw *p_r;
536         unsigned char *d_str;
537         gint state = 0;
538         guint save = 0;
539         unsigned int d_len_raw;
540         unsigned char *d_r;
541         unsigned int d_len;
542         char *extract_cksum;
543         gchar *compute_cksum;
544         size_t bytes_read;
545         keyval_t *kv;
546         int type;
547         size_t byte_size;
548
549         if (r == NULL) {
550                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
551                 return NULL;
552         }
553
554         extract_cksum = calloc(CHECKSUM_LENGTH + 1, sizeof(char));
555         if (unlikely(extract_cksum == NULL)) {
556                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
557                 return NULL;
558         }
559
560         /*
561          * base 64 decode of input string
562          * Since base64 encodes 3 bytes in 4 chars (+3 may be needed in case of non-zero state)
563          * refer to: https://developer.gnome.org/glib/stable/glib-Base64-Encoding.html#g-base64-decode-step
564          */
565         d_str = malloc((data_size / 4) * 3 + 3);
566         if (unlikely(d_str == NULL)) {
567                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
568                 free(extract_cksum);
569                 return NULL;
570         }
571
572         d_len_raw = g_base64_decode_step((char *)r, data_size, d_str, &state, &save);
573         if (d_len_raw < CHECKSUM_LENGTH) {
574                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
575                 free(d_str);
576                 free(extract_cksum);
577                 return NULL;
578         }
579
580         /* extract checksum from the received string */
581         strncpy(extract_cksum, (const char *)d_str, CHECKSUM_LENGTH);
582         /* compute checksum for the data */
583         compute_cksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,
584                         (const char *)(d_str + CHECKSUM_LENGTH),
585                         d_len_raw - CHECKSUM_LENGTH);
586         /*
587          * compare checksum values- extracted from the received
588          * string and computed from the data
589          */
590         if (strcmp(extract_cksum, compute_cksum) != 0) {
591                 free(d_str);
592                 free(extract_cksum);
593                 g_free(compute_cksum);
594                 return NULL;
595         }
596         d_r = d_str + CHECKSUM_LENGTH;
597         d_len = d_len_raw - CHECKSUM_LENGTH;
598
599         /* re-construct bundle */
600         b = bundle_create();
601         if (b == NULL) {
602                 free(d_str);
603                 free(extract_cksum);
604                 g_free(compute_cksum);
605                 return NULL;
606         }
607
608         p_r = (bundle_raw *)d_r;
609         while (p_r < d_r + d_len - 1) {
610                 kv = NULL;      /* To get a new kv */
611
612                 byte_size = d_r + d_len - 1 - p_r;
613                 if (byte_size < sizeof(size_t))
614                         break;
615
616                 /* Find type, and use decode function according to type */
617                 type = keyval_get_type_from_encoded_byte(p_r);
618                 if (keyval_type_is_array(type)) {
619                         bytes_read = keyval_array_decode(p_r,
620                                         (keyval_array_t **)&kv, byte_size + 1);
621                 } else {
622                         bytes_read = keyval_decode(p_r, &kv, byte_size + 1);
623                 }
624
625                 if (kv)
626                         _bundle_append_kv(b, kv);
627                 else
628                         break;
629                 p_r += bytes_read;
630         }
631
632         free(extract_cksum);
633         g_free(compute_cksum);
634         free(d_str);
635
636         set_last_result(BUNDLE_ERROR_NONE);
637         return b;
638 }
639
640 struct _argv_idx {
641         int argc;
642         char **argv;
643         int idx;
644 };
645
646 API int bundle_encode_raw(bundle *b, bundle_raw **r, int *len)
647 {
648         keyval_t *kv = NULL;
649         unsigned char *m = NULL;
650         unsigned char *p_m = NULL;
651         unsigned char *byte = NULL;
652         size_t byte_len;
653         gchar *chksum_val = NULL;
654         size_t msize = 0;
655
656         if (b == NULL || r == NULL)
657                 return BUNDLE_ERROR_INVALID_PARAMETER;
658
659         /* calculate memory size */
660         kv = b->kv_head;
661         while (kv != NULL) {
662                 msize += kv->method->get_encoded_size(kv);
663                 kv = kv->next;
664         }
665
666         m = calloc(msize+CHECKSUM_LENGTH, sizeof(unsigned char));
667         if (unlikely(m == NULL))
668                 return BUNDLE_ERROR_OUT_OF_MEMORY;
669
670         p_m = m + CHECKSUM_LENGTH;      /* temporary pointer */
671
672         kv = b->kv_head;
673         while (kv != NULL) {
674                 byte = NULL;
675                 byte_len = 0;
676
677                 kv->method->encode(kv, &byte, &byte_len);
678                 memcpy(p_m, byte, byte_len);
679
680                 p_m += byte_len;
681                 kv = kv->next;
682
683                 free(byte);
684         }
685
686         /* compute checksum from the data */
687         chksum_val = g_compute_checksum_for_string(G_CHECKSUM_MD5,
688                         (const char *)(m + CHECKSUM_LENGTH), msize);
689         /* prefix checksum to the data */
690         memcpy(m, chksum_val, CHECKSUM_LENGTH);
691
692         *r = m;
693         *len = msize + CHECKSUM_LENGTH;
694         g_free(chksum_val); /* free checksum string */
695
696         return BUNDLE_ERROR_NONE;
697 }
698
699 API bundle *bundle_decode_raw(const bundle_raw *r, const int data_size)
700 {
701         bundle *b = NULL;
702         bundle_raw *p_r = NULL;
703         unsigned char *d_str = NULL;
704         unsigned int d_len_raw;
705         unsigned char *d_r = NULL;
706         unsigned int d_len;
707         char *extract_cksum;
708         gchar *compute_cksum = NULL;
709         size_t bytes_read;
710         keyval_t *kv;
711         int type;
712         size_t byte_size;
713
714         if (r == NULL) {
715                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
716                 return NULL;
717         }
718
719         extract_cksum = calloc(CHECKSUM_LENGTH + 1, sizeof(char));
720         if (unlikely(extract_cksum == NULL)) {
721                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
722                 return NULL;
723         }
724
725         /* base 64 decode of input string*/
726         /* d_str = g_base64_decode((char*)r, &d_len_raw); */
727         d_str = (unsigned char *)r;
728         d_len_raw = data_size;
729         /* extract checksum from the received string */
730         strncpy(extract_cksum, (const char *)d_str, CHECKSUM_LENGTH);
731         /* compute checksum for the data */
732         compute_cksum = g_compute_checksum_for_string(G_CHECKSUM_MD5,
733                         (const char *)(d_str + CHECKSUM_LENGTH),
734                         d_len_raw - CHECKSUM_LENGTH);
735         /*
736          * compare checksum values- extracted from the received
737          * string and computed from the data
738          */
739         if (strcmp(extract_cksum, compute_cksum) != 0) {
740                 free(extract_cksum);
741                 g_free(compute_cksum);
742                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
743                 return NULL;
744         }
745         d_r = d_str + CHECKSUM_LENGTH;
746         d_len = d_len_raw - CHECKSUM_LENGTH;
747
748         /* re-construct bundle */
749         b = bundle_create();
750         if (b == NULL) {
751                 free(extract_cksum);
752                 g_free(compute_cksum);
753                 return NULL;
754         }
755
756         p_r = (bundle_raw *)d_r;
757         while (p_r < d_r + d_len - 1) {
758                 kv = NULL;      /* To get a new kv */
759
760                 byte_size = d_r + d_len - 1 - p_r;
761                 if (byte_size < sizeof(size_t))
762                         break;
763
764                 /* Find type, and use decode function according to type */
765                 type = keyval_get_type_from_encoded_byte(p_r);
766                 if (keyval_type_is_array(type)) {
767                         bytes_read = keyval_array_decode(p_r,
768                                         (keyval_array_t **)&kv, byte_size + 1);
769                 } else {
770                         bytes_read = keyval_decode(p_r, &kv, byte_size + 1);
771                 }
772
773                 if (kv)
774                         _bundle_append_kv(b, kv);
775                 else
776                         break;
777                 p_r += bytes_read;
778         }
779
780         free(extract_cksum);
781         g_free(compute_cksum);
782         set_last_result(BUNDLE_ERROR_NONE);
783
784         return b;
785 }
786
787 void _iter_export_to_argv(const char *key, const int type, const keyval_t *kv,
788                 void *user_data)
789 {
790         struct _argv_idx *vi = (struct _argv_idx *)user_data;
791         unsigned char *byte = NULL;
792         unsigned char *encoded_byte = NULL;
793         size_t byte_len = 0;
794
795         vi->argv[vi->idx] = strdup(key);
796         if (kv->method->encode((struct keyval_t *)kv, &byte, &byte_len) == 0) {
797                 /* TODO: encode FAILED! */
798                 BUNDLE_EXCEPTION_PRINT("bundle: FAILED to encode keyval: %s\n",
799                                 key);
800                 return;
801         }
802
803         encoded_byte = (unsigned char *)g_base64_encode(byte, byte_len);
804         if (encoded_byte == NULL) {
805                 BUNDLE_EXCEPTION_PRINT("bundle: failed to encode byte\n");
806                 return;
807         }
808
809         vi->argv[vi->idx + 1] = (char *)encoded_byte;
810         (vi->idx) += 2;
811
812         free(byte);
813 }
814
815 API int bundle_export_to_argv(bundle *b, char ***argv)
816 {
817         struct _argv_idx vi;
818         int argc;
819         int item_count;
820
821         if (b == NULL || argv == NULL) {
822                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
823                 return -1;
824         }
825
826         item_count = bundle_get_count(b);
827         argc = 2 * item_count + 2;
828         /* 2 more count for argv[0] and arv[1] = encoded */
829         *argv = calloc(argc + 1, sizeof(char *));
830         if (!*argv) {
831                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
832                 return -1;
833         }
834
835         vi.argc = argc;
836         vi.argv = *argv;
837         vi.idx = 2;                             /* start from index 2*/
838         vi.argv[1] = TAG_IMPORT_EXPORT_CHECK;   /* set argv[1] as encoded*/
839         /* BUNDLE_LOG_PRINT("\nargument 1 is %s",vi.argv[1]); */
840
841         bundle_foreach(b, _iter_export_to_argv, &vi);
842
843         set_last_result(BUNDLE_ERROR_NONE);
844         return argc;
845 }
846
847 API int bundle_free_exported_argv(int argc, char ***argv)
848 {
849         int i;
850
851         if (argc < 1)
852                 return BUNDLE_ERROR_INVALID_PARAMETER;
853
854         if (!*argv || argc < 2)
855                 return BUNDLE_ERROR_INVALID_PARAMETER;
856
857         for (i = 2; i < argc; i++)
858                 free((*argv)[i]);
859         free(*argv);
860         *argv = NULL;
861
862         return BUNDLE_ERROR_NONE;
863 }
864
865 API bundle *bundle_import_from_argv(int argc, char **argv)
866 {
867         int idx;
868         int type;
869         keyval_t *kv;
870         keyval_array_t *kva;
871         unsigned char *byte;
872         char *encoded_byte;
873         unsigned int byte_size;
874         bundle *b;
875
876         if (!argv) {
877                 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
878                 return NULL;  /* TC_FIX error handling for argv =NULL*/
879         }
880
881         b = bundle_create();
882         if (!b) {
883                 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
884                 return NULL;
885         }
886
887         if (argc < 2) {
888                 set_last_result(BUNDLE_ERROR_NONE);
889                 return b;
890         }
891
892         if (!argv[1] || strcmp(argv[1], TAG_IMPORT_EXPORT_CHECK)) {
893                 /* start idx from one as argv[1] is user given argument */
894                 for (idx = 1; idx + 1 < argc; idx = idx + 2)
895                         bundle_add(b, argv[idx], argv[idx + 1]);
896
897                 return b;
898         }
899
900         /* start idx from 2 as argv[1] is encoded */
901         for (idx = 2; idx + 1 < argc; idx = idx + 2) {
902                 kv = NULL;
903                 kva = NULL;
904
905                 encoded_byte = argv[idx+1];
906
907                 /* base64_decode */
908                 byte = g_base64_decode(encoded_byte, (gsize *)&byte_size);
909                 if (byte == NULL) {
910                         if (b)
911                                 set_last_result(bundle_free(b));
912                         return NULL;
913                 }
914
915                 if (byte_size < sizeof(size_t)) {
916                         free(byte);
917                         byte = NULL;
918                         byte_size = 0;
919                         continue;
920                 }
921
922                 type = keyval_get_type_from_encoded_byte(byte);
923                 if (keyval_type_is_array(type)) {
924                         if (keyval_array_decode(byte, &kva, byte_size + 1) == 0) /* TODO: error! */
925                                 BUNDLE_EXCEPTION_PRINT("Unable to Decode array\n");
926                         kv = (keyval_t *)kva;
927                 } else {
928                         if (keyval_decode(byte, &kv, byte_size + 1) == 0) /* TODO: error! */
929                                 BUNDLE_EXCEPTION_PRINT("Unable to Decode\n");
930                 }
931                 _bundle_append_kv(b, kv);
932
933                 free(byte);
934                 byte = NULL;
935                 byte_size = 0;
936         }
937
938         set_last_result(BUNDLE_ERROR_NONE);
939         return b;
940 }
941
942 API int bundle_get_type(bundle *b, const char *key)
943 {
944         keyval_t *kv = _bundle_find_kv(b, key);
945
946         if (kv) {
947                 return kv->type;
948         } else {
949                 set_last_result(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
950                 return BUNDLE_TYPE_NONE;
951         }
952 }
953
954 /*
955  * Get length of an array
956  */
957 /* LCOV_EXCL_START */
958 unsigned int bundle_get_array_len(bundle *b, const char *key)
959 {
960         return BUNDLE_ERROR_NONE;
961 }
962 /* LCOV_EXCL_STOP */
963
964 /*
965  * Get size of an item in byte, of given pointer
966  */
967 /* LCOV_EXCL_START */
968 size_t bundle_get_array_val_size(bundle *b, const char *key,
969                 const void *val_ptr)
970 {
971         return BUNDLE_ERROR_NONE;
972 }
973 /* LCOV_EXCL_STOP */
974
975 static int bundle_set_array_val(bundle *b, const char *key, const int type,
976                 const unsigned int idx, const void *val, const size_t size)
977 {
978         keyval_t *kv;
979         keyval_array_t *kva;
980
981         kv = _bundle_find_kv(b, key);
982         if (kv == NULL)
983                 return get_last_result();
984
985         if (type != kv->type)
986                 return BUNDLE_ERROR_INVALID_PARAMETER;
987
988         /* TODO: Is this needed? */
989         if (!keyval_type_is_array(kv->type))
990                 return BUNDLE_ERROR_INVALID_PARAMETER;
991
992         kva = (keyval_array_t *)kv;
993         if (!keyval_array_is_idx_valid(kva, idx))
994                 return BUNDLE_ERROR_ARRAY_INDEX_OUT_OF_BOUNDS;
995
996         /* NULL value test (TODO: is this needed?) */
997         if (!kva->array_val)
998                 return BUNDLE_ERROR_INVALID_PARAMETER;
999
1000         return keyval_array_set_element(kva, idx, (void *)val, size);
1001 }
1002
1003 API int bundle_add_str_array(bundle *b, const char *key, const char **str_array,
1004                 const int len)
1005 {
1006         return _bundle_add_kv(b, key, str_array, 0, BUNDLE_TYPE_STR_ARRAY, len);
1007 }
1008
1009 /* LCOV_EXCL_START */
1010 int bundle_get_val_array(bundle *b, const char *key, char ***str_array,
1011                 int *len)
1012 {
1013         return _bundle_get_val(b, key, BUNDLE_TYPE_STR_ARRAY,
1014                         (void **)str_array, NULL, (unsigned int *)len, NULL);
1015 }
1016 /* LCOV_EXCL_STOP */
1017
1018 API const char **bundle_get_str_array(bundle *b, const char *key, int *len)
1019 {
1020         int ret = BUNDLE_ERROR_NONE;
1021         const char **arr_val = NULL;
1022
1023         ret = bundle_get_val_array(b, key, (char ***)&arr_val, len);
1024         set_last_result(ret);
1025
1026         return arr_val;
1027 }
1028
1029 /* LCOV_EXCL_START */
1030 API int bundle_compare(bundle *b1, bundle *b2)
1031 {
1032         keyval_t *kv1;
1033         keyval_t *kv2;
1034
1035         if (!b1 || !b2)
1036                 return -1;
1037
1038         if (bundle_get_count(b1) != bundle_get_count(b2))
1039                 return 1;
1040
1041         for (kv1 = b1->kv_head; kv1 != NULL; kv1 = kv1->next) {
1042                 kv2 = _bundle_find_kv(b2, kv1->key);
1043                 if (!kv2)
1044                         return 1;
1045                 if (kv1->method->compare(kv1, kv2))
1046                         return 1;
1047         }
1048
1049         return 0;
1050 }
1051 /* LCOV_EXCL_STOP */
1052
1053 API int bundle_set_str_array_element(bundle *b, const char *key,
1054                 const unsigned int idx, const char *val)
1055 {
1056         if (!val)
1057                 return BUNDLE_ERROR_INVALID_PARAMETER;
1058
1059         return bundle_set_array_val(b, key, BUNDLE_TYPE_STR_ARRAY,
1060                         idx, val, strlen(val) + 1);
1061 }
1062
1063 API int bundle_add_byte(bundle *b, const char *key, const void *bytes,
1064                 const size_t size)
1065 {
1066         return _bundle_add_kv(b, key, bytes, size, BUNDLE_TYPE_BYTE, 1);
1067 }
1068
1069 API int bundle_get_byte(bundle *b, const char *key, void **bytes, size_t *size)
1070 {
1071         return _bundle_get_val(b, key, BUNDLE_TYPE_BYTE, (void **)bytes,
1072                         size, NULL, NULL);
1073 }
1074
1075 API int bundle_add_byte_array(bundle *b, const char *key,
1076                 const unsigned int len)
1077 {
1078         return bundle_init_byte_array(b, key, len);
1079 }
1080
1081 API int bundle_init_byte_array(bundle *b, const char *key,
1082                 const unsigned int len)
1083 {
1084         return _bundle_add_kv(b, key, NULL, 0, BUNDLE_TYPE_BYTE_ARRAY, len);
1085 }
1086
1087 API int bundle_get_byte_array(bundle *b, const char *key, void ***byte_array,
1088                 unsigned int *len, unsigned int **array_element_size)
1089 {
1090         int ret;
1091
1092         ret = _bundle_get_val(b, key, BUNDLE_TYPE_BYTE_ARRAY,
1093                         (void **)byte_array, NULL, len,
1094                         (size_t **)array_element_size);
1095         return ret;
1096 }
1097
1098 API int bundle_set_byte_array_element(bundle *b, const char *key,
1099                 const unsigned int idx, const void *bytes, const size_t size)
1100 {
1101         return bundle_set_array_val(b, key, BUNDLE_TYPE_BYTE_ARRAY,
1102                         idx, bytes, size);
1103 }