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