diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/plist.c | 383 | ||||
| -rw-r--r-- | src/plist.h | 23 |
2 files changed, 356 insertions, 50 deletions
diff --git a/src/plist.c b/src/plist.c index c691c16..431c64a 100644 --- a/src/plist.c +++ b/src/plist.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #include "utils.h" | 25 | #include "utils.h" |
| 26 | #include "plist.h" | 26 | #include "plist.h" |
| 27 | #include <wchar.h> | 27 | #include <wchar.h> |
| 28 | #include <stdlib.h> | ||
| 29 | #include <stdio.h> | ||
| 28 | 30 | ||
| 29 | /********************************************** | 31 | /********************************************** |
| 30 | * * | 32 | * * |
| @@ -127,7 +129,7 @@ void plist_new_plist(plist_t * plist) | |||
| 127 | if (*plist != NULL) | 129 | if (*plist != NULL) |
| 128 | return; | 130 | return; |
| 129 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); | 131 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); |
| 130 | data->type = PLIST_PLIST; | 132 | data->type = PLIST_DICT; |
| 131 | *plist = g_node_new(data); | 133 | *plist = g_node_new(data); |
| 132 | } | 134 | } |
| 133 | 135 | ||
| @@ -191,7 +193,6 @@ void plist_add_dict_element(dict_t dict, char *key, plist_type type, void *value | |||
| 191 | case PLIST_ARRAY: | 193 | case PLIST_ARRAY: |
| 192 | case PLIST_DICT: | 194 | case PLIST_DICT: |
| 193 | case PLIST_DATE: | 195 | case PLIST_DATE: |
| 194 | case PLIST_PLIST: | ||
| 195 | default: | 196 | default: |
| 196 | break; | 197 | break; |
| 197 | } | 198 | } |
| @@ -314,10 +315,6 @@ void node_to_xml(GNode * node, gpointer xml_struct) | |||
| 314 | tag = "dict"; | 315 | tag = "dict"; |
| 315 | isStruct = TRUE; | 316 | isStruct = TRUE; |
| 316 | break; | 317 | break; |
| 317 | case PLIST_PLIST: | ||
| 318 | tag = "plist"; | ||
| 319 | isStruct = TRUE; | ||
| 320 | break; | ||
| 321 | case PLIST_DATE: //TODO : handle date tag | 318 | case PLIST_DATE: //TODO : handle date tag |
| 322 | default: | 319 | default: |
| 323 | break; | 320 | break; |
| @@ -332,8 +329,7 @@ void node_to_xml(GNode * node, gpointer xml_struct) | |||
| 332 | g_free(val); | 329 | g_free(val); |
| 333 | 330 | ||
| 334 | //add return for structured types | 331 | //add return for structured types |
| 335 | if (node_data->type == PLIST_ARRAY || | 332 | if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT || node_data->type == PLIST_DATA) |
| 336 | node_data->type == PLIST_DICT || node_data->type == PLIST_DATA || node_data->type == PLIST_PLIST) | ||
| 337 | xmlNodeAddContent(child_node, "\n"); | 333 | xmlNodeAddContent(child_node, "\n"); |
| 338 | 334 | ||
| 339 | if (isStruct) { | 335 | if (isStruct) { |
| @@ -341,8 +337,7 @@ void node_to_xml(GNode * node, gpointer xml_struct) | |||
| 341 | g_node_children_foreach(node, G_TRAVERSE_ALL, node_to_xml, &child); | 337 | g_node_children_foreach(node, G_TRAVERSE_ALL, node_to_xml, &child); |
| 342 | } | 338 | } |
| 343 | //fix indent for structured types | 339 | //fix indent for structured types |
| 344 | if (node_data->type == PLIST_ARRAY || | 340 | if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT || node_data->type == PLIST_DATA) { |
| 345 | node_data->type == PLIST_DICT || node_data->type == PLIST_DATA || node_data->type == PLIST_PLIST) { | ||
| 346 | 341 | ||
| 347 | for (i = 0; i < xstruct->depth; i++) { | 342 | for (i = 0; i < xstruct->depth; i++) { |
| 348 | xmlNodeAddContent(child_node, "\t"); | 343 | xmlNodeAddContent(child_node, "\t"); |
| @@ -446,7 +441,7 @@ void xml_to_plist(const char *plist_xml, uint32_t length, plist_t * plist) | |||
| 446 | 441 | ||
| 447 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); | 442 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); |
| 448 | *plist = g_node_new(data); | 443 | *plist = g_node_new(data); |
| 449 | data->type = PLIST_PLIST; | 444 | data->type = PLIST_DICT; |
| 450 | xml_to_node(root_node, *plist); | 445 | xml_to_node(root_node, *plist); |
| 451 | } | 446 | } |
| 452 | 447 | ||
| @@ -512,6 +507,9 @@ void byte_convert(char *address, size_t size) | |||
| 512 | 507 | ||
| 513 | #define be64dec(x) bswap_64( *(uint64_t*)(x) ) | 508 | #define be64dec(x) bswap_64( *(uint64_t*)(x) ) |
| 514 | 509 | ||
| 510 | #define get_needed_bytes(x) (x <= 1<<8 ? 1 : ( x <= 1<<16 ? 2 : ( x <= 1<<32 ? 4 : 8))) | ||
| 511 | #define get_real_bytes(x) (x >> 32 ? 4 : 8) | ||
| 512 | |||
| 515 | GNode *parse_uint_node(char *bnode, uint8_t size, char **next_object) | 513 | GNode *parse_uint_node(char *bnode, uint8_t size, char **next_object) |
| 516 | { | 514 | { |
| 517 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); | 515 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); |
| @@ -638,7 +636,6 @@ uint64_t plist_get_node_uint_val(plist_t node) | |||
| 638 | return 0; | 636 | return 0; |
| 639 | } | 637 | } |
| 640 | 638 | ||
| 641 | |||
| 642 | GNode *parse_bin_node(char *object, uint8_t dict_size, char **next_object) | 639 | GNode *parse_bin_node(char *object, uint8_t dict_size, char **next_object) |
| 643 | { | 640 | { |
| 644 | if (!object) | 641 | if (!object) |
| @@ -738,13 +735,6 @@ GNode *parse_bin_node(char *object, uint8_t dict_size, char **next_object) | |||
| 738 | return NULL; | 735 | return NULL; |
| 739 | } | 736 | } |
| 740 | 737 | ||
| 741 | void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | ||
| 742 | { | ||
| 743 | uint64_t num_objects = g_node_n_nodes(plist, G_TRAVERSE_ALL); | ||
| 744 | } | ||
| 745 | |||
| 746 | |||
| 747 | |||
| 748 | gpointer copy_plist_data(gconstpointer src, gpointer data) | 738 | gpointer copy_plist_data(gconstpointer src, gpointer data) |
| 749 | { | 739 | { |
| 750 | struct plist_data *srcdata = (struct plist_data *) src; | 740 | struct plist_data *srcdata = (struct plist_data *) src; |
| @@ -770,7 +760,6 @@ gpointer copy_plist_data(gconstpointer src, gpointer data) | |||
| 770 | case PLIST_UNICODE: | 760 | case PLIST_UNICODE: |
| 771 | dstdata->unicodeval = wcsdup(srcdata->unicodeval); | 761 | dstdata->unicodeval = wcsdup(srcdata->unicodeval); |
| 772 | break; | 762 | break; |
| 773 | case PLIST_PLIST: | ||
| 774 | case PLIST_DATA: | 763 | case PLIST_DATA: |
| 775 | case PLIST_ARRAY: | 764 | case PLIST_ARRAY: |
| 776 | case PLIST_DICT: | 765 | case PLIST_DICT: |
| @@ -856,8 +845,6 @@ void bin_to_plist(const char *plist_bin, uint32_t length, plist_t * plist) | |||
| 856 | 845 | ||
| 857 | //first one is actually a key | 846 | //first one is actually a key |
| 858 | ((struct plist_data *) nodeslist[index1]->data)->type = PLIST_KEY; | 847 | ((struct plist_data *) nodeslist[index1]->data)->type = PLIST_KEY; |
| 859 | //g_node_append(nodeslist[i], nodeslist[index1]); | ||
| 860 | //g_node_append(nodeslist[i], nodeslist[index2]); | ||
| 861 | 848 | ||
| 862 | if (G_NODE_IS_ROOT(nodeslist[index1])) | 849 | if (G_NODE_IS_ROOT(nodeslist[index1])) |
| 863 | g_node_append(nodeslist[i], nodeslist[index1]); | 850 | g_node_append(nodeslist[i], nodeslist[index1]); |
| @@ -895,7 +882,6 @@ void bin_to_plist(const char *plist_bin, uint32_t length, plist_t * plist) | |||
| 895 | *plist = nodeslist[root_object]; | 882 | *plist = nodeslist[root_object]; |
| 896 | } | 883 | } |
| 897 | 884 | ||
| 898 | |||
| 899 | GNode *find_query_node(plist_t plist, char *key, char *request) | 885 | GNode *find_query_node(plist_t plist, char *key, char *request) |
| 900 | { | 886 | { |
| 901 | if (!plist) | 887 | if (!plist) |
| @@ -912,7 +898,7 @@ GNode *find_query_node(plist_t plist, char *key, char *request) | |||
| 912 | if (data->type == PLIST_STRING && !strcmp(data->strval, request)) | 898 | if (data->type == PLIST_STRING && !strcmp(data->strval, request)) |
| 913 | return current->next; | 899 | return current->next; |
| 914 | } | 900 | } |
| 915 | if (data->type == PLIST_DICT || data->type == PLIST_ARRAY || data->type == PLIST_PLIST) { | 901 | if (data->type == PLIST_DICT || data->type == PLIST_ARRAY) { |
| 916 | GNode *sub = find_query_node(current, key, request); | 902 | GNode *sub = find_query_node(current, key, request); |
| 917 | if (sub) | 903 | if (sub) |
| 918 | return sub; | 904 | return sub; |
| @@ -947,7 +933,6 @@ char compare_node_value(plist_type type, struct plist_data *data, void *value) | |||
| 947 | case PLIST_ARRAY: | 933 | case PLIST_ARRAY: |
| 948 | case PLIST_DICT: | 934 | case PLIST_DICT: |
| 949 | case PLIST_DATE: | 935 | case PLIST_DATE: |
| 950 | case PLIST_PLIST: | ||
| 951 | default: | 936 | default: |
| 952 | break; | 937 | break; |
| 953 | } | 938 | } |
| @@ -967,7 +952,7 @@ GNode *find_node(plist_t plist, plist_type type, void *value) | |||
| 967 | if (data->type == type && compare_node_value(type, data, value)) { | 952 | if (data->type == type && compare_node_value(type, data, value)) { |
| 968 | return current; | 953 | return current; |
| 969 | } | 954 | } |
| 970 | if (data->type == PLIST_DICT || data->type == PLIST_ARRAY || data->type == PLIST_PLIST) { | 955 | if (data->type == PLIST_DICT || data->type == PLIST_ARRAY) { |
| 971 | GNode *sub = find_node(current, type, value); | 956 | GNode *sub = find_node(current, type, value); |
| 972 | if (sub) | 957 | if (sub) |
| 973 | return sub; | 958 | return sub; |
| @@ -1008,8 +993,352 @@ void get_type_and_value(GNode * node, plist_type * type, void *value) | |||
| 1008 | case PLIST_ARRAY: | 993 | case PLIST_ARRAY: |
| 1009 | case PLIST_DICT: | 994 | case PLIST_DICT: |
| 1010 | case PLIST_DATE: | 995 | case PLIST_DATE: |
| 1011 | case PLIST_PLIST: | ||
| 1012 | default: | 996 | default: |
| 1013 | break; | 997 | break; |
| 1014 | } | 998 | } |
| 1015 | } | 999 | } |
| 1000 | |||
| 1001 | guint plist_data_hash(gconstpointer key) | ||
| 1002 | { | ||
| 1003 | struct plist_data *data = (struct plist_data *) ((GNode *) key)->data; | ||
| 1004 | |||
| 1005 | guint hash = data->type; | ||
| 1006 | guint i = 0; | ||
| 1007 | |||
| 1008 | char *buff = NULL; | ||
| 1009 | guint size = 0; | ||
| 1010 | |||
| 1011 | switch (data->type) { | ||
| 1012 | case PLIST_BOOLEAN: | ||
| 1013 | case PLIST_UINT: | ||
| 1014 | case PLIST_REAL: | ||
| 1015 | buff = (char *) &data->intval; | ||
| 1016 | size = 8; | ||
| 1017 | |||
| 1018 | case PLIST_KEY: | ||
| 1019 | case PLIST_STRING: | ||
| 1020 | buff = data->strval; | ||
| 1021 | size = strlen(buff); | ||
| 1022 | |||
| 1023 | case PLIST_UNICODE: | ||
| 1024 | buff = data->unicodeval; | ||
| 1025 | size = strlen(buff) * sizeof(wchar_t); | ||
| 1026 | |||
| 1027 | case PLIST_DATA: | ||
| 1028 | case PLIST_ARRAY: | ||
| 1029 | case PLIST_DICT: | ||
| 1030 | //for these types only hash pointer | ||
| 1031 | buff = &key; | ||
| 1032 | size = sizeof(gconstpointer); | ||
| 1033 | break; | ||
| 1034 | case PLIST_DATE: | ||
| 1035 | default: | ||
| 1036 | break; | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | //now perform hash | ||
| 1040 | for (i = 0; i < size; buff++, i++) | ||
| 1041 | hash = hash << 7 ^ (*buff); | ||
| 1042 | |||
| 1043 | return hash; | ||
| 1044 | } | ||
| 1045 | |||
| 1046 | gboolean plist_data_compare(gconstpointer a, gconstpointer b) | ||
| 1047 | { | ||
| 1048 | if (!a || !b) | ||
| 1049 | return FALSE; | ||
| 1050 | |||
| 1051 | if (!((GNode *) a)->data || !((GNode *) b)->data) | ||
| 1052 | return FALSE; | ||
| 1053 | |||
| 1054 | struct plist_data *val_a = (struct plist_data *) ((GNode *) a)->data; | ||
| 1055 | struct plist_data *val_b = (struct plist_data *) ((GNode *) b)->data; | ||
| 1056 | |||
| 1057 | if (val_a->type != val_b->type) | ||
| 1058 | return FALSE; | ||
| 1059 | |||
| 1060 | switch (val_a->type) { | ||
| 1061 | case PLIST_BOOLEAN: | ||
| 1062 | case PLIST_UINT: | ||
| 1063 | case PLIST_REAL: | ||
| 1064 | if (val_a->intval == val_b->intval) //it is an union so this is sufficient | ||
| 1065 | return TRUE; | ||
| 1066 | else | ||
| 1067 | return FALSE; | ||
| 1068 | |||
| 1069 | case PLIST_KEY: | ||
| 1070 | case PLIST_STRING: | ||
| 1071 | if (!strcmp(val_a->strval, val_b->strval)) | ||
| 1072 | return TRUE; | ||
| 1073 | else | ||
| 1074 | return FALSE; | ||
| 1075 | case PLIST_UNICODE: | ||
| 1076 | if (!strcmp(val_a->unicodeval, val_b->unicodeval)) | ||
| 1077 | return TRUE; | ||
| 1078 | else | ||
| 1079 | return FALSE; | ||
| 1080 | |||
| 1081 | case PLIST_DATA: | ||
| 1082 | case PLIST_ARRAY: | ||
| 1083 | case PLIST_DICT: | ||
| 1084 | //compare pointer | ||
| 1085 | if (a == b) | ||
| 1086 | return TRUE; | ||
| 1087 | else | ||
| 1088 | return FALSE; | ||
| 1089 | break; | ||
| 1090 | case PLIST_DATE: | ||
| 1091 | default: | ||
| 1092 | break; | ||
| 1093 | } | ||
| 1094 | return FALSE; | ||
| 1095 | } | ||
| 1096 | |||
| 1097 | struct serialize_s { | ||
| 1098 | GPtrArray *objects; | ||
| 1099 | GHashTable *ref_table; | ||
| 1100 | }; | ||
| 1101 | |||
| 1102 | void serialize_plist(GNode * node, gpointer data) | ||
| 1103 | { | ||
| 1104 | struct serialize_s *ser = (struct serialize_s *) data; | ||
| 1105 | uint64_t current_index = ser->objects->len; | ||
| 1106 | |||
| 1107 | //first check that node is not yet in objects | ||
| 1108 | gpointer val = g_hash_table_lookup(ser->ref_table, node); | ||
| 1109 | if (val) { | ||
| 1110 | //data is already in table | ||
| 1111 | return; | ||
| 1112 | } | ||
| 1113 | //insert new ref | ||
| 1114 | g_hash_table_insert(ser->ref_table, node, GUINT_TO_POINTER(current_index)); | ||
| 1115 | |||
| 1116 | //now append current node to object array | ||
| 1117 | g_ptr_array_add(ser->objects, node); | ||
| 1118 | |||
| 1119 | //now recurse on children | ||
| 1120 | g_node_children_foreach(node, G_TRAVERSE_ALL, serialize_plist, data); | ||
| 1121 | return; | ||
| 1122 | } | ||
| 1123 | |||
| 1124 | |||
| 1125 | |||
| 1126 | void write_int(GByteArray * bplist, uint64_t val) | ||
| 1127 | { | ||
| 1128 | uint64_t size = get_needed_bytes(val); | ||
| 1129 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); | ||
| 1130 | buff[0] = BPLIST_UINT | size >> 1; | ||
| 1131 | memcpy(buff + 1, &val, size); | ||
| 1132 | swap_n_bytes(buff + 1, size); | ||
| 1133 | g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); | ||
| 1134 | free(buff); | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | void write_real(GByteArray * bplist, double val) | ||
| 1138 | { | ||
| 1139 | uint64_t size = get_real_bytes(*((uint64_t *) & val)); //cheat to know used space | ||
| 1140 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); | ||
| 1141 | buff[0] = BPLIST_REAL | size >> 1; | ||
| 1142 | memcpy(buff + 1, &val, size); | ||
| 1143 | swap_n_bytes(buff + 1, size); | ||
| 1144 | g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); | ||
| 1145 | free(buff); | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | void write_raw_data(GByteArray * bplist, uint8_t mark, uint8_t * val, uint64_t size) | ||
| 1149 | { | ||
| 1150 | uint8_t marker = mark | (size < 15 ? size : 0xf); | ||
| 1151 | g_byte_array_append(bplist, &marker, sizeof(uint8_t)); | ||
| 1152 | if (size >= 15) { | ||
| 1153 | GByteArray *int_buff = g_byte_array_new(); | ||
| 1154 | write_int(int_buff, size); | ||
| 1155 | g_byte_array_append(bplist, int_buff->data, int_buff->len); | ||
| 1156 | g_byte_array_free(int_buff, TRUE); | ||
| 1157 | } | ||
| 1158 | uint8_t *buff = (uint8_t *) malloc(size); | ||
| 1159 | memcpy(buff, val, size); | ||
| 1160 | g_byte_array_append(bplist, buff, size); | ||
| 1161 | free(buff); | ||
| 1162 | } | ||
| 1163 | |||
| 1164 | void write_data(GByteArray * bplist, uint8_t * val, uint64_t size) | ||
| 1165 | { | ||
| 1166 | write_raw_data(bplist, BPLIST_DATA, val, size); | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | void write_string(GByteArray * bplist, char *val) | ||
| 1170 | { | ||
| 1171 | uint64_t size = strlen(val); | ||
| 1172 | write_raw_data(bplist, BPLIST_STRING, val, size); | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) | ||
| 1176 | { | ||
| 1177 | uint64_t size = g_node_n_children(node); | ||
| 1178 | uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf); | ||
| 1179 | g_byte_array_append(bplist, &marker, sizeof(uint8_t)); | ||
| 1180 | if (size >= 15) { | ||
| 1181 | GByteArray *int_buff = g_byte_array_new(); | ||
| 1182 | write_int(int_buff, size); | ||
| 1183 | g_byte_array_append(bplist, int_buff->data, int_buff->len); | ||
| 1184 | g_byte_array_free(int_buff, TRUE); | ||
| 1185 | } | ||
| 1186 | |||
| 1187 | uint64_t idx = 0; | ||
| 1188 | uint8_t *buff = (uint8_t *) malloc(size * dict_param_size); | ||
| 1189 | |||
| 1190 | GNode *cur = NULL; | ||
| 1191 | int i = 0; | ||
| 1192 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next, i++) { | ||
| 1193 | idx = GPOINTER_TO_UINT(g_hash_table_lookup(ref_table, cur)); | ||
| 1194 | memcpy(buff + i * dict_param_size, &idx, dict_param_size); | ||
| 1195 | swap_n_bytes(buff + i * dict_param_size, dict_param_size); | ||
| 1196 | } | ||
| 1197 | |||
| 1198 | //now append to bplist | ||
| 1199 | g_byte_array_append(bplist, buff, size * dict_param_size); | ||
| 1200 | free(buff); | ||
| 1201 | |||
| 1202 | } | ||
| 1203 | |||
| 1204 | void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) | ||
| 1205 | { | ||
| 1206 | uint64_t size = g_node_n_children(node) / 2; | ||
| 1207 | uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf); | ||
| 1208 | g_byte_array_append(bplist, &marker, sizeof(uint8_t)); | ||
| 1209 | if (size >= 15) { | ||
| 1210 | GByteArray *int_buff = g_byte_array_new(); | ||
| 1211 | write_int(int_buff, size); | ||
| 1212 | g_byte_array_append(bplist, int_buff->data, int_buff->len); | ||
| 1213 | g_byte_array_free(int_buff, TRUE); | ||
| 1214 | } | ||
| 1215 | |||
| 1216 | uint64_t idx1 = 0; | ||
| 1217 | uint64_t idx2 = 0; | ||
| 1218 | uint8_t *buff = (uint8_t *) malloc(size * 2 * dict_param_size); | ||
| 1219 | |||
| 1220 | GNode *cur = NULL; | ||
| 1221 | int i = 0; | ||
| 1222 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next->next, i++) { | ||
| 1223 | idx1 = GPOINTER_TO_UINT(g_hash_table_lookup(ref_table, cur)); | ||
| 1224 | memcpy(buff + i * dict_param_size, &idx1, dict_param_size); | ||
| 1225 | swap_n_bytes(buff + i * dict_param_size, dict_param_size); | ||
| 1226 | |||
| 1227 | idx2 = GPOINTER_TO_UINT(g_hash_table_lookup(ref_table, cur->next)); | ||
| 1228 | memcpy(buff + (i + size) * dict_param_size, &idx2, dict_param_size); | ||
| 1229 | swap_n_bytes(buff + (i + size) * dict_param_size, dict_param_size); | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | //now append to bplist | ||
| 1233 | g_byte_array_append(bplist, buff, size * dict_param_size); | ||
| 1234 | free(buff); | ||
| 1235 | |||
| 1236 | } | ||
| 1237 | |||
| 1238 | void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | ||
| 1239 | { | ||
| 1240 | //first serialize tree | ||
| 1241 | |||
| 1242 | //list of objects | ||
| 1243 | GPtrArray *objects = g_ptr_array_new(); | ||
| 1244 | //hashtable to write only once same nodes | ||
| 1245 | GHashTable *ref_table = g_hash_table_new(plist_data_hash, plist_data_compare); | ||
| 1246 | |||
| 1247 | //serialize plist | ||
| 1248 | struct serialize_s ser_s = { objects, ref_table }; | ||
| 1249 | g_node_children_foreach(plist, G_TRAVERSE_ALL, serialize_plist, &ser_s); | ||
| 1250 | |||
| 1251 | //now stream to output buffer | ||
| 1252 | uint8_t offset_size = 0; //unknown yet | ||
| 1253 | uint8_t dict_param_size = get_needed_bytes(objects->len); | ||
| 1254 | uint64_t num_objects = objects->len; | ||
| 1255 | uint64_t root_object = 0; //root is first in list | ||
| 1256 | uint64_t offset_table_index = 0; //unknown yet | ||
| 1257 | |||
| 1258 | //setup a dynamic bytes array to store bplist in | ||
| 1259 | GByteArray *bplist_buff = g_byte_array_new(); | ||
| 1260 | |||
| 1261 | //set magic number and version | ||
| 1262 | g_byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); | ||
| 1263 | g_byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE); | ||
| 1264 | |||
| 1265 | //write objects and table | ||
| 1266 | int i = 0; | ||
| 1267 | uint8_t *buff = NULL; | ||
| 1268 | uint8_t size = 0; | ||
| 1269 | uint64_t offsets[num_objects]; | ||
| 1270 | for (i = 0; i <= num_objects; i++) { | ||
| 1271 | |||
| 1272 | offsets[i] = bplist_buff->len; | ||
| 1273 | struct plist_data *data = (struct plist_data *) ((GNode *) g_ptr_array_index(objects, i))->data; | ||
| 1274 | |||
| 1275 | switch (data->type) { | ||
| 1276 | case PLIST_BOOLEAN: | ||
| 1277 | buff = (uint8_t *) malloc(sizeof(uint8_t)); | ||
| 1278 | buff[0] = data->boolval ? BPLIST_TRUE : BPLIST_FALSE; | ||
| 1279 | g_byte_array_append(bplist_buff, buff, sizeof(uint8_t)); | ||
| 1280 | free(buff); | ||
| 1281 | break; | ||
| 1282 | |||
| 1283 | case PLIST_UINT: | ||
| 1284 | write_int(bplist_buff, data->intval); | ||
| 1285 | break; | ||
| 1286 | |||
| 1287 | case PLIST_REAL: | ||
| 1288 | write_real(bplist_buff, data->realval); | ||
| 1289 | break; | ||
| 1290 | |||
| 1291 | case PLIST_KEY: | ||
| 1292 | case PLIST_STRING: | ||
| 1293 | write_string(bplist_buff, data->strval); | ||
| 1294 | break; | ||
| 1295 | case PLIST_UNICODE: | ||
| 1296 | //TODO | ||
| 1297 | break; | ||
| 1298 | case PLIST_DATA: | ||
| 1299 | write_data(bplist_buff, data->strval, data->length); | ||
| 1300 | case PLIST_ARRAY: | ||
| 1301 | write_array(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); | ||
| 1302 | break; | ||
| 1303 | case PLIST_DICT: | ||
| 1304 | write_dict(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); | ||
| 1305 | break; | ||
| 1306 | case PLIST_DATE: | ||
| 1307 | //TODO | ||
| 1308 | break; | ||
| 1309 | default: | ||
| 1310 | break; | ||
| 1311 | } | ||
| 1312 | } | ||
| 1313 | |||
| 1314 | //write offsets | ||
| 1315 | offset_size = get_needed_bytes(bplist_buff->len); | ||
| 1316 | for (i = 0; i <= num_objects; i++) { | ||
| 1317 | uint8_t *buff = (uint8_t *) malloc(offset_size); | ||
| 1318 | memcpy(buff, offsets + i, offset_size); | ||
| 1319 | swap_n_bytes(buff, offset_size); | ||
| 1320 | g_byte_array_append(bplist_buff, buff, offset_size); | ||
| 1321 | free(buff); | ||
| 1322 | } | ||
| 1323 | |||
| 1324 | //setup trailer | ||
| 1325 | num_objects = bswap_64(num_objects); | ||
| 1326 | root_object = bswap_64(root_object); | ||
| 1327 | offset_table_index = bswap_64(offset_table_index); | ||
| 1328 | |||
| 1329 | char trailer[BPLIST_TRL_SIZE]; | ||
| 1330 | memcpy(trailer + BPLIST_TRL_OFFSIZE_IDX, &offset_size, sizeof(uint8_t)); | ||
| 1331 | memcpy(trailer + BPLIST_TRL_PARMSIZE_IDX, &dict_param_size, sizeof(uint8_t)); | ||
| 1332 | memcpy(trailer + BPLIST_TRL_NUMOBJ_IDX, &num_objects, sizeof(uint64_t)); | ||
| 1333 | memcpy(trailer + BPLIST_TRL_ROOTOBJ_IDX, &root_object, sizeof(uint64_t)); | ||
| 1334 | memcpy(trailer + BPLIST_TRL_OFFTAB_IDX, &offset_table_index, sizeof(uint64_t)); | ||
| 1335 | |||
| 1336 | g_byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE); | ||
| 1337 | |||
| 1338 | //duplicate buffer | ||
| 1339 | *plist_bin = (char *) malloc(bplist_buff->len); | ||
| 1340 | memcpy(*plist_bin, bplist_buff->data, bplist_buff->len); | ||
| 1341 | *length = bplist_buff->len; | ||
| 1342 | |||
| 1343 | g_byte_array_free(bplist_buff, TRUE); | ||
| 1344 | } | ||
diff --git a/src/plist.h b/src/plist.h index df1d3e4..63f67f7 100644 --- a/src/plist.h +++ b/src/plist.h | |||
| @@ -33,28 +33,6 @@ | |||
| 33 | char *format_string(const char *buf, int cols, int depth); | 33 | char *format_string(const char *buf, int cols, int depth); |
| 34 | 34 | ||
| 35 | 35 | ||
| 36 | /* Binary plist stuff */ | ||
| 37 | |||
| 38 | /* | ||
| 39 | typedef enum { | ||
| 40 | PLIST_BOOLEAN, | ||
| 41 | PLIST_UINT8, | ||
| 42 | PLIST_UINT16, | ||
| 43 | PLIST_UINT32, | ||
| 44 | PLIST_UINT64, | ||
| 45 | PLIST_FLOAT32, | ||
| 46 | PLIST_FLOAT64, | ||
| 47 | PLIST_STRING, | ||
| 48 | PLIST_UNICODE, | ||
| 49 | PLIST_ARRAY, | ||
| 50 | PLIST_DICT, | ||
| 51 | PLIST_DATE, | ||
| 52 | PLIST_DATA, | ||
| 53 | PLIST_PLIST, | ||
| 54 | PLIST_KEY, | ||
| 55 | } plist_type; | ||
| 56 | */ | ||
| 57 | |||
| 58 | typedef enum { | 36 | typedef enum { |
| 59 | PLIST_BOOLEAN, | 37 | PLIST_BOOLEAN, |
| 60 | PLIST_UINT, | 38 | PLIST_UINT, |
| @@ -65,7 +43,6 @@ typedef enum { | |||
| 65 | PLIST_DICT, | 43 | PLIST_DICT, |
| 66 | PLIST_DATE, | 44 | PLIST_DATE, |
| 67 | PLIST_DATA, | 45 | PLIST_DATA, |
| 68 | PLIST_PLIST, | ||
| 69 | PLIST_KEY, | 46 | PLIST_KEY, |
| 70 | } plist_type; | 47 | } plist_type; |
| 71 | 48 | ||
