4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jayoun Lee <airjany@samsung.com>, Sewook Park <sewook7.park@samsung.com>,
7 * Jaeho Lee <jaeho81.lee@samsung.com>
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
13 * http://www.apache.org/licenses/LICENSE-2.0
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.
30 #include "bundle_internal.h"
32 #include "keyval_array.h"
33 #include "keyval_type.h"
34 #include "bundle_log.h"
37 #include <stdlib.h> /* calloc, free */
38 #include <string.h> /* strdup */
40 #define CHECKSUM_LENGTH 32
41 #define TAG_IMPORT_EXPORT_CHECK "`zaybxcwdveuftgsh`"
49 * Find a kv from bundle
52 _bundle_find_kv(bundle *b, const char *key)
56 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
60 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
66 if (0 == strcmp(key, kv->key))
71 set_last_result(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
76 * Append kv into bundle
79 _bundle_append_kv(bundle *b, keyval_t *new_kv)
83 if (NULL == b->kv_head)
87 while (NULL != kv->next)
91 return BUNDLE_ERROR_NONE;
95 _bundle_add_kv(bundle *b, const char *key, const void *val,
96 const size_t size, const int type, const unsigned int len)
98 /* basic value check */
100 return BUNDLE_ERROR_INVALID_PARAMETER;
102 return BUNDLE_ERROR_INVALID_PARAMETER;
103 if (0 == strlen(key))
104 return BUNDLE_ERROR_INVALID_PARAMETER;
106 keyval_t *kv = _bundle_find_kv(b, key);
107 if (kv) { /* Key already exists */
108 return BUNDLE_ERROR_KEY_EXISTS;
111 keyval_t *new_kv = NULL;
112 if (keyval_type_is_array(type)) {
114 keyval_array_t *kva = keyval_array_new(NULL, key, type,
115 (const void **) val, len);
116 new_kv = (keyval_t *)kva;
119 new_kv = keyval_new(NULL, key, type, val, size);
122 return BUNDLE_ERROR_OUT_OF_MEMORY;
124 _bundle_append_kv(b, new_kv);
126 return BUNDLE_ERROR_NONE;
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)
134 keyval_t *kv = _bundle_find_kv(b, key);
135 if (!kv) /* Key doesn't exist */
136 return get_last_result();
138 if (BUNDLE_TYPE_ANY != type && type != kv->type)
139 return BUNDLE_ERROR_INVALID_PARAMETER;
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);
146 keyval_get_data(kv, NULL, val, size);
149 return BUNDLE_ERROR_NONE;
152 /** global initialization
156 _bundle_global_init(void)
163 /* Run init functions */
177 _bundle_global_init();
179 b = calloc(1, sizeof(bundle)); /* fill mem with NULL */
181 BUNDLE_EXCEPTION_PRINT("Unable to allocate memory for bundle\n");
182 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
186 set_last_result(BUNDLE_ERROR_NONE);
194 bundle_free(bundle *b)
196 keyval_t *kv, *tmp_kv;
199 BUNDLE_EXCEPTION_PRINT("Bundle is already freed\n");
200 return BUNDLE_ERROR_INVALID_PARAMETER;
203 /* Free keyval list */
208 tmp_kv->method->free(tmp_kv, 1);
214 return BUNDLE_ERROR_NONE;
218 bundle_add_str(bundle *b, const char *key, const char *str)
221 return BUNDLE_ERROR_INVALID_PARAMETER;
222 return _bundle_add_kv(b, key, str, strlen(str)+1, BUNDLE_TYPE_STR, 1);
226 bundle_get_str(bundle *b, const char *key, char **str)
228 return _bundle_get_val(b, key, BUNDLE_TYPE_STR, (void **) str,
233 bundle_add(bundle *b, const char *key, const char *val)
235 return bundle_add_str(b, key, val);
239 bundle_del(bundle *b, const char *key)
241 keyval_t *kv = NULL, *prev_kv = NULL;
243 /* basic value check */
245 return BUNDLE_ERROR_INVALID_PARAMETER;
247 return BUNDLE_ERROR_INVALID_PARAMETER;
248 if (0 == strlen(key))
249 return BUNDLE_ERROR_INVALID_PARAMETER;
253 if (0 == strcmp(key, kv->key))
259 return BUNDLE_ERROR_KEY_NOT_AVAILABLE;
262 prev_kv->next = kv->next;
263 if (kv == b->kv_head)
264 b->kv_head = kv->next;
265 kv->method->free(kv, 1);
267 return BUNDLE_ERROR_NONE;
272 bundle_get_val(bundle *b, const char *key)
277 ret = bundle_get_str(b, key, &val);
278 set_last_result(ret);
285 * @brief used by bundle_get_count() API, to count number of items in a bundle
288 _bundle_get_count_iter(const char *k, const int type,
289 const bundle_keyval_t *kv, void *user_data)
291 int *count = (int *)user_data;
296 bundle_get_count(bundle *b)
301 bundle_foreach(b, _bundle_get_count_iter, &count);
306 bundle_iterate(bundle *b, bundle_iterate_cb_t callback, void *data)
310 if (NULL == b || NULL == callback) {
311 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
317 callback(kv->key, kv->val, data);
320 set_last_result(BUNDLE_ERROR_NONE);
324 bundle_foreach(bundle *b, bundle_iterator_t iter, void *user_data)
326 if (NULL == b || NULL == iter) {
327 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
328 return; /*TC_FIX if b=NULL- error handling */
331 keyval_t *kv = b->kv_head;
333 iter(kv->key, kv->type, kv, user_data);
336 set_last_result(BUNDLE_ERROR_NONE);
339 /* keyval functions */
341 bundle_keyval_get_type(bundle_keyval_t *kv)
344 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
347 set_last_result(BUNDLE_ERROR_NONE);
352 bundle_keyval_type_is_array(bundle_keyval_t *kv)
355 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
358 set_last_result(BUNDLE_ERROR_NONE);
359 return keyval_type_is_array(kv->type);
363 bundle_keyval_type_is_measurable(bundle_keyval_t *kv)
366 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
369 set_last_result(BUNDLE_ERROR_NONE);
370 return keyval_type_is_measurable(kv->type);
374 bundle_keyval_get_basic_val(bundle_keyval_t *kv, void **val, size_t *size)
376 return keyval_get_data(kv, NULL, val, size);
380 bundle_keyval_get_array_val(bundle_keyval_t *kv, void ***array_val,
381 unsigned int *array_len, size_t **array_item_size)
383 return keyval_array_get_data((keyval_array_t *)kv, NULL,
384 array_val, array_len, array_item_size);
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)
392 bundle *b_to = (bundle *)user_data;
394 _bundle_add_kv(b_to, key, val, size, type, len);
399 bundle_dup(bundle *b_from)
404 if (NULL == b_from) {
405 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
408 b_to = bundle_create();
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);
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]);
428 _bundle_append_kv(b_to, kv_to);
430 if (_bundle_add_kv(b_to, kv_from->key, kv_from->val,
431 kv_from->size, kv_from->type, 0))
435 kv_from = kv_from->next;
446 bundle_encode(bundle *b, bundle_raw **r, int *len)
455 if (NULL == b || NULL == r || NULL == len)
456 return BUNDLE_ERROR_INVALID_PARAMETER;
458 /* calculate memory size */
459 size_t msize = 0; /* Sum of required size */
463 msize += kv->method->get_encoded_size(kv);
466 m = calloc(msize + CHECKSUM_LENGTH, sizeof(unsigned char));
467 if (unlikely(NULL == m))
468 return BUNDLE_ERROR_OUT_OF_MEMORY;
470 p_m = m + CHECKSUM_LENGTH; /* temporary pointer */
477 kv->method->encode(kv, &byte, &byte_len);
478 memcpy(p_m, byte, byte_len);
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);
492 /*base64 encode for whole string checksum and data*/
493 *r = (unsigned char *)g_base64_encode(m, msize + CHECKSUM_LENGTH);
495 *len = strlen((char *)*r);
498 g_free(chksum_val);/*free checksum string */
500 return BUNDLE_ERROR_NONE;
504 bundle_free_encoded_rawdata(bundle_raw **r)
507 return BUNDLE_ERROR_INVALID_PARAMETER;
508 /*TC_FIX - double free sigabrt handling */
512 return BUNDLE_ERROR_NONE;
516 bundle_decode(const bundle_raw *r, const int data_size)
520 unsigned char *d_str;
523 unsigned int d_len_raw;
527 gchar *compute_cksum;
530 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
534 extract_cksum = calloc(CHECKSUM_LENGTH+1, sizeof(char));
535 if (unlikely(NULL == extract_cksum)) {
536 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
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
544 d_str = malloc((data_size / 4) * 3 + 3);
545 if (unlikely(NULL == d_str)) {
546 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
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);
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
567 if (strcmp(extract_cksum, compute_cksum) != 0) {
569 g_free(compute_cksum);
572 d_r = d_str + CHECKSUM_LENGTH;
573 d_len = d_len_raw - CHECKSUM_LENGTH;
575 /* re-construct bundle */
578 p_r = (bundle_raw *)d_r;
583 while (p_r < d_r + d_len - 1) {
584 kv = NULL; /* To get a new kv */
586 /* Find type, and use decode function according to type */
587 int type = keyval_get_type_from_encoded_byte(p_r);
589 if (keyval_type_is_array(type))
590 bytes_read = keyval_array_decode(p_r, (keyval_array_t **) &kv);
592 bytes_read = keyval_decode(p_r, &kv);
595 _bundle_append_kv(b, kv);
602 g_free(compute_cksum);
605 set_last_result(BUNDLE_ERROR_NONE);
616 bundle_encode_raw(bundle *b, bundle_raw **r, int *len)
619 unsigned char *m = NULL;
620 unsigned char *p_m = NULL;
621 unsigned char *byte = NULL;
623 gchar *chksum_val = NULL;
625 if (NULL == b || NULL == r)
626 return BUNDLE_ERROR_INVALID_PARAMETER;
628 /* calculate memory size */
629 size_t msize = 0; /* Sum of required size */
633 msize += kv->method->get_encoded_size(kv);
636 m = calloc(msize+CHECKSUM_LENGTH, sizeof(unsigned char));
637 if (unlikely(NULL == m))
638 return BUNDLE_ERROR_OUT_OF_MEMORY;
640 p_m = m + CHECKSUM_LENGTH; /* temporary pointer */
647 kv->method->encode(kv, &byte, &byte_len);
648 memcpy(p_m, byte, byte_len);
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);
662 *r =(unsigned char*)g_base64_encode(m,msize+CHECKSUM_LENGTH);
663 if ( NULL != len ) *len = strlen((char*)*r);
667 *len = msize + CHECKSUM_LENGTH;
668 g_free(chksum_val);/*free checksum string */
670 return BUNDLE_ERROR_NONE;
674 bundle_decode_raw(const bundle_raw *r, const int data_size)
677 bundle_raw *p_r = NULL;
678 unsigned char *d_str = NULL;
679 unsigned int d_len_raw;
680 unsigned char *d_r = NULL;
682 char *extract_cksum = NULL;
683 gchar *compute_cksum = NULL;
686 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
690 extract_cksum = calloc(CHECKSUM_LENGTH + 1, sizeof(char));
691 if (unlikely(NULL == extract_cksum)) {
692 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
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
709 if (strcmp(extract_cksum, compute_cksum) != 0) {
711 g_free(compute_cksum);
712 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
715 d_r = d_str + CHECKSUM_LENGTH;
716 d_len = d_len_raw - CHECKSUM_LENGTH;
718 /* re-construct bundle */
721 p_r = (bundle_raw *)d_r;
726 while (p_r < d_r + d_len - 1) {
727 kv = NULL; /* To get a new kv */
729 /* Find type, and use decode function according to type */
730 int type = keyval_get_type_from_encoded_byte(p_r);
732 if (keyval_type_is_array(type))
733 bytes_read = keyval_array_decode(p_r, (keyval_array_t **) &kv);
735 bytes_read = keyval_decode(p_r, &kv);
738 _bundle_append_kv(b, kv);
745 g_free(compute_cksum);
747 set_last_result(BUNDLE_ERROR_NONE);
753 _iter_export_to_argv(const char *key, const int type, const keyval_t *kv,
756 struct _argv_idx *vi = (struct _argv_idx *)user_data;
758 vi->argv[vi->idx] = (char *)key;
760 unsigned char *byte = NULL, *encoded_byte = NULL;
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);
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");
775 vi->argv[vi->idx + 1] = (char *)encoded_byte;
782 bundle_export_to_argv(bundle *b, char ***argv)
784 int argc, item_count;
786 if (b == NULL || argv == NULL) {
787 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
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 *));
796 set_last_result(BUNDLE_ERROR_OUT_OF_MEMORY);
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]);*/
807 bundle_foreach(b, _iter_export_to_argv, &vi);
809 set_last_result(BUNDLE_ERROR_NONE);
813 int bundle_free_exported_argv(int argc, char ***argv)
816 return BUNDLE_ERROR_INVALID_PARAMETER;
818 if (!*argv || argc < 2)
819 return BUNDLE_ERROR_INVALID_PARAMETER;
822 for (i = 3; i < argc; i += 2) {
824 /* need to free value from g_base64_encode() */
829 return BUNDLE_ERROR_NONE;
833 bundle_import_from_argv(int argc, char **argv)
836 set_last_result(BUNDLE_ERROR_INVALID_PARAMETER);
837 return NULL; /* TC_FIX error handling for argv =NULL*/
840 bundle *b = bundle_create();
847 for(i=0; i<argc; i++) {
848 BUNDLE_LOG_PRINT("[bundle-dbg] argv[%d]='%s'\n", i, argv[i]);
852 if (!argv[1] || strcmp(argv[1], TAG_IMPORT_EXPORT_CHECK)) {
853 /*BUNDLE_LOG_PRINT("\nit is not encoded");*/
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]);
861 /*BUNDLE_LOG_PRINT("\nit is encoded");*/
864 keyval_array_t *kva = NULL;
865 unsigned char *byte = NULL;
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) {
873 encoded_byte = argv[idx+1];
876 byte = g_base64_decode(encoded_byte, &byte_size);
879 set_last_result(bundle_free(b));
883 type = keyval_get_type_from_encoded_byte(byte);
884 if (keyval_type_is_array(type)) {
885 if (0 == keyval_array_decode(byte, &kva)) {
887 BUNDLE_EXCEPTION_PRINT("Unable to Decode array\n");
889 kv = (keyval_t *)kva;
891 if (0 == keyval_decode(byte, &kv)) {
893 BUNDLE_EXCEPTION_PRINT("Unable to Decode\n");
896 _bundle_append_kv(b, kv);
901 set_last_result(BUNDLE_ERROR_NONE);
907 bundle_get_type(bundle *b, const char *key)
909 keyval_t *kv = _bundle_find_kv(b, key);
913 set_last_result(BUNDLE_ERROR_KEY_NOT_AVAILABLE);
914 return BUNDLE_TYPE_NONE;
918 /** Get length of an array
921 bundle_get_array_len(bundle *b, const char *key)
923 return BUNDLE_ERROR_NONE;
926 /** Get size of an item in byte, of given pointer
929 bundle_get_array_val_size(bundle *b, const char *key, const void *val_ptr)
931 return BUNDLE_ERROR_NONE;
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)
937 keyval_t *kv = _bundle_find_kv(b, key);
939 return get_last_result();
941 if (type != kv->type)
942 return BUNDLE_ERROR_INVALID_PARAMETER;
944 /* TODO: Is this needed? */
945 if (!keyval_type_is_array(kv->type))
946 return BUNDLE_ERROR_INVALID_PARAMETER;
948 keyval_array_t *kva = (keyval_array_t *)kv;
950 if (!keyval_array_is_idx_valid(kva, idx))
951 return BUNDLE_ERROR_INVALID_PARAMETER;
953 /* NULL value test (TODO: is this needed?) */
955 return BUNDLE_ERROR_INVALID_PARAMETER;
957 return keyval_array_set_element(kva, idx, (void *)val, size);
962 bundle_add_str_array(bundle *b, const char *key, const char **str_array,
965 return _bundle_add_kv(b, key, str_array, 0, BUNDLE_TYPE_STR_ARRAY, len);
970 bundle_get_val_array(bundle *b, const char *key, char ***str_array, int *len)
972 return _bundle_get_val(b, key, BUNDLE_TYPE_STR_ARRAY,
973 (void **)str_array, NULL, (unsigned int *)len, NULL);
976 const char **bundle_get_str_array(bundle *b, const char *key, int *len)
978 int ret = BUNDLE_ERROR_NONE;
979 const char **arr_val = NULL;
981 ret = bundle_get_val_array(b, key, (char ***)&arr_val, len);
982 set_last_result(ret);
989 bundle_compare(bundle *b1, bundle *b2)
996 if (bundle_get_count(b1) != bundle_get_count(b2))
998 for (kv1 = b1->kv_head; kv1 != NULL; kv1 = kv1->next) {
999 kv2 = _bundle_find_kv(b2, kv1->key);
1002 if (kv1->method->compare(kv1, kv2))
1011 bundle_set_str_array_element(bundle *b, const char *key,
1012 const unsigned int idx, const char *val)
1015 return BUNDLE_ERROR_INVALID_PARAMETER;
1017 return bundle_set_array_val(b, key, BUNDLE_TYPE_STR_ARRAY,
1018 idx, val, strlen(val)+1);
1023 bundle_add_byte(bundle *b, const char *key, const void *byte,
1026 return _bundle_add_kv(b, key, byte, size, BUNDLE_TYPE_BYTE, 1);
1030 bundle_get_byte(bundle *b, const char *key, void **byte, size_t *size)
1032 return _bundle_get_val(b, key, BUNDLE_TYPE_BYTE, (void **) byte,
1037 bundle_add_byte_array(bundle *b, const char *key, void **byte_array,
1038 const unsigned int len)
1040 return _bundle_add_kv(b, key, byte_array, 0, BUNDLE_TYPE_BYTE_ARRAY, len);
1044 bundle_get_byte_array(bundle *b, const char *key, void ***byte_array,
1045 unsigned int *len, unsigned int **array_element_size)
1047 return _bundle_get_val(b, key, BUNDLE_TYPE_BYTE_ARRAY,
1048 (void **)byte_array, NULL, len, array_element_size);
1053 bundle_set_byte_array_element(bundle *b, const char *key,
1054 const unsigned int idx, const void *val, const size_t size)
1056 return bundle_set_array_val(b, key, BUNDLE_TYPE_BYTE_ARRAY,