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