diff options
Diffstat (limited to 'src/bplist.c')
| -rw-r--r-- | src/bplist.c | 339 |
1 files changed, 212 insertions, 127 deletions
diff --git a/src/bplist.c b/src/bplist.c index 82d1813..77e6245 100644 --- a/src/bplist.c +++ b/src/bplist.c | |||
| @@ -29,6 +29,12 @@ | |||
| 29 | 29 | ||
| 30 | #include <plist/plist.h> | 30 | #include <plist/plist.h> |
| 31 | #include "plist.h" | 31 | #include "plist.h" |
| 32 | #include "hashtable.h" | ||
| 33 | #include "bytearray.h" | ||
| 34 | #include "ptrarray.h" | ||
| 35 | |||
| 36 | #include <node.h> | ||
| 37 | #include <node_iterator.h> | ||
| 32 | 38 | ||
| 33 | /* Magic marker and size. */ | 39 | /* Magic marker and size. */ |
| 34 | #define BPLIST_MAGIC ((uint8_t*)"bplist") | 40 | #define BPLIST_MAGIC ((uint8_t*)"bplist") |
| @@ -66,7 +72,7 @@ enum | |||
| 66 | 72 | ||
| 67 | static void float_byte_convert(uint8_t * address, size_t size) | 73 | static void float_byte_convert(uint8_t * address, size_t size) |
| 68 | { | 74 | { |
| 69 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN && !defined (__VFP_FP__) | 75 | #if PLIST_BYTE_ORDER == PLIST_LITTLE_ENDIAN && !defined (__VFP_FP__) |
| 70 | uint8_t i = 0, j = 0; | 76 | uint8_t i = 0, j = 0; |
| 71 | uint8_t tmp = 0; | 77 | uint8_t tmp = 0; |
| 72 | 78 | ||
| @@ -100,7 +106,7 @@ union plist_uint_ptr | |||
| 100 | 106 | ||
| 101 | static void byte_convert(uint8_t * address, size_t size) | 107 | static void byte_convert(uint8_t * address, size_t size) |
| 102 | { | 108 | { |
| 103 | #if G_BYTE_ORDER == G_LITTLE_ENDIAN | 109 | #if PLIST_BYTE_ORDER == PLIST_LITTLE_ENDIAN |
| 104 | uint8_t i = 0, j = 0; | 110 | uint8_t i = 0, j = 0; |
| 105 | uint8_t tmp = 0; | 111 | uint8_t tmp = 0; |
| 106 | 112 | ||
| @@ -131,10 +137,10 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf) | |||
| 131 | ({ \ | 137 | ({ \ |
| 132 | union plist_uint_ptr __up; \ | 138 | union plist_uint_ptr __up; \ |
| 133 | __up.src = x; \ | 139 | __up.src = x; \ |
| 134 | (n == 8 ? GUINT64_FROM_BE( get_unaligned(__up.u64ptr) ) : \ | 140 | (n == 8 ? be64toh( get_unaligned(__up.u64ptr) ) : \ |
| 135 | (n == 4 ? GUINT32_FROM_BE( get_unaligned(__up.u32ptr) ) : \ | 141 | (n == 4 ? be32toh( get_unaligned(__up.u32ptr) ) : \ |
| 136 | (n == 3 ? uint24_from_be( __up ) : \ | 142 | (n == 3 ? uint24_from_be( __up ) : \ |
| 137 | (n == 2 ? GUINT16_FROM_BE( get_unaligned(__up.u16ptr) ) : \ | 143 | (n == 2 ? be16toh( get_unaligned(__up.u16ptr) ) : \ |
| 138 | *__up.u8ptr )))); \ | 144 | *__up.u8ptr )))); \ |
| 139 | }) | 145 | }) |
| 140 | 146 | ||
| @@ -142,7 +148,7 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf) | |||
| 142 | ({ \ | 148 | ({ \ |
| 143 | union plist_uint_ptr __up; \ | 149 | union plist_uint_ptr __up; \ |
| 144 | __up.src = x; \ | 150 | __up.src = x; \ |
| 145 | GUINT64_FROM_BE( get_unaligned(__up.u64ptr) ); \ | 151 | be64toh( get_unaligned(__up.u64ptr) ); \ |
| 146 | }) | 152 | }) |
| 147 | 153 | ||
| 148 | #define get_needed_bytes(x) \ | 154 | #define get_needed_bytes(x) \ |
| @@ -153,6 +159,7 @@ static uint32_t uint24_from_be(union plist_uint_ptr buf) | |||
| 153 | 159 | ||
| 154 | #define get_real_bytes(x) (x == (float) x ? 4 : 8) | 160 | #define get_real_bytes(x) (x == (float) x ? 4 : 8) |
| 155 | 161 | ||
| 162 | #define NODE_IS_ROOT(x) (((node_t*)x)->isRoot) | ||
| 156 | 163 | ||
| 157 | static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) | 164 | static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) |
| 158 | { | 165 | { |
| @@ -177,7 +184,7 @@ static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) | |||
| 177 | data->type = PLIST_UINT; | 184 | data->type = PLIST_UINT; |
| 178 | data->length = sizeof(uint64_t); | 185 | data->length = sizeof(uint64_t); |
| 179 | 186 | ||
| 180 | return g_node_new(data); | 187 | return node_create(NULL, data); |
| 181 | } | 188 | } |
| 182 | 189 | ||
| 183 | static plist_t parse_real_node(char *bnode, uint8_t size) | 190 | static plist_t parse_real_node(char *bnode, uint8_t size) |
| @@ -208,7 +215,7 @@ static plist_t parse_real_node(char *bnode, uint8_t size) | |||
| 208 | data->type = PLIST_REAL; | 215 | data->type = PLIST_REAL; |
| 209 | data->length = sizeof(double); | 216 | data->length = sizeof(double); |
| 210 | 217 | ||
| 211 | return g_node_new(data); | 218 | return node_create(NULL, data); |
| 212 | } | 219 | } |
| 213 | 220 | ||
| 214 | static plist_t parse_date_node(char *bnode, uint8_t size) | 221 | static plist_t parse_date_node(char *bnode, uint8_t size) |
| @@ -217,10 +224,10 @@ static plist_t parse_date_node(char *bnode, uint8_t size) | |||
| 217 | plist_data_t data = plist_get_data(node); | 224 | plist_data_t data = plist_get_data(node); |
| 218 | 225 | ||
| 219 | double time_real = data->realval; | 226 | double time_real = data->realval; |
| 220 | data->timeval.tv_sec = (glong) time_real; | 227 | data->timeval.tv_sec = (long) time_real; |
| 221 | data->timeval.tv_usec = (time_real - (glong) time_real) * G_USEC_PER_SEC; | 228 | data->timeval.tv_usec = (time_real - (long) time_real) * 1000000; |
| 222 | data->type = PLIST_DATE; | 229 | data->type = PLIST_DATE; |
| 223 | data->length = sizeof(GTimeVal); | 230 | data->length = sizeof(struct timeval); |
| 224 | 231 | ||
| 225 | return node; | 232 | return node; |
| 226 | } | 233 | } |
| @@ -235,26 +242,58 @@ static plist_t parse_string_node(char *bnode, uint64_t size) | |||
| 235 | data->strval[size] = '\0'; | 242 | data->strval[size] = '\0'; |
| 236 | data->length = strlen(data->strval); | 243 | data->length = strlen(data->strval); |
| 237 | 244 | ||
| 238 | return g_node_new(data); | 245 | return node_create(NULL, data); |
| 246 | } | ||
| 247 | |||
| 248 | static char *plist_utf16_to_utf8(uint16_t *unistr, long len, long *items_read, long *items_written) | ||
| 249 | { | ||
| 250 | if (!unistr || (len <= 0)) return NULL; | ||
| 251 | char *outbuf = (char*)malloc(3*(len+1)); | ||
| 252 | int p = 0; | ||
| 253 | int i = 0; | ||
| 254 | |||
| 255 | uint16_t wc; | ||
| 256 | |||
| 257 | while (i < len) { | ||
| 258 | wc = unistr[i++]; | ||
| 259 | if (wc >= 0x800) { | ||
| 260 | outbuf[p++] = (char)(0xE0 + ((wc >> 12) & 0xF)); | ||
| 261 | outbuf[p++] = (char)(0x80 + ((wc >> 6) & 0x3F)); | ||
| 262 | outbuf[p++] = (char)(0x80 + (wc & 0x3F)); | ||
| 263 | } else if (wc >= 0x80) { | ||
| 264 | outbuf[p++] = (char)(0xC0 + ((wc >> 6) & 0x1F)); | ||
| 265 | outbuf[p++] = (char)(0x80 + (wc & 0x3F)); | ||
| 266 | } else { | ||
| 267 | outbuf[p++] = (char)(wc & 0x7F); | ||
| 268 | } | ||
| 269 | } | ||
| 270 | if (items_read) { | ||
| 271 | *items_read = i; | ||
| 272 | } | ||
| 273 | if (items_written) { | ||
| 274 | *items_written = p; | ||
| 275 | } | ||
| 276 | outbuf[p] = 0; | ||
| 277 | |||
| 278 | return outbuf; | ||
| 239 | } | 279 | } |
| 240 | 280 | ||
| 241 | static plist_t parse_unicode_node(char *bnode, uint64_t size) | 281 | static plist_t parse_unicode_node(char *bnode, uint64_t size) |
| 242 | { | 282 | { |
| 243 | plist_data_t data = plist_new_plist_data(); | 283 | plist_data_t data = plist_new_plist_data(); |
| 244 | uint64_t i = 0; | 284 | uint64_t i = 0; |
| 245 | gunichar2 *unicodestr = NULL; | 285 | uint16_t *unicodestr = NULL; |
| 246 | gchar *tmpstr = NULL; | 286 | char *tmpstr = NULL; |
| 247 | glong items_read = 0; | 287 | long items_read = 0; |
| 248 | glong items_written = 0; | 288 | long items_written = 0; |
| 249 | GError *error = NULL; | ||
| 250 | 289 | ||
| 251 | data->type = PLIST_STRING; | 290 | data->type = PLIST_STRING; |
| 252 | unicodestr = (gunichar2 *) malloc(sizeof(gunichar2) * size); | 291 | unicodestr = (uint16_t*) malloc(sizeof(uint16_t) * size); |
| 253 | memcpy(unicodestr, bnode, sizeof(gunichar2) * size); | 292 | memcpy(unicodestr, bnode, sizeof(uint16_t) * size); |
| 254 | for (i = 0; i < size; i++) | 293 | for (i = 0; i < size; i++) |
| 255 | byte_convert((uint8_t *) (unicodestr + i), sizeof(gunichar2)); | 294 | byte_convert((uint8_t *) (unicodestr + i), sizeof(uint16_t)); |
| 256 | 295 | ||
| 257 | tmpstr = g_utf16_to_utf8(unicodestr, size, &items_read, &items_written, &error); | 296 | tmpstr = plist_utf16_to_utf8(unicodestr, size, &items_read, &items_written); |
| 258 | free(unicodestr); | 297 | free(unicodestr); |
| 259 | 298 | ||
| 260 | data->type = PLIST_STRING; | 299 | data->type = PLIST_STRING; |
| @@ -262,8 +301,8 @@ static plist_t parse_unicode_node(char *bnode, uint64_t size) | |||
| 262 | memcpy(data->strval, tmpstr, items_written); | 301 | memcpy(data->strval, tmpstr, items_written); |
| 263 | data->strval[items_written] = '\0'; | 302 | data->strval[items_written] = '\0'; |
| 264 | data->length = strlen(data->strval); | 303 | data->length = strlen(data->strval); |
| 265 | g_free(tmpstr); | 304 | free(tmpstr); |
| 266 | return g_node_new(data); | 305 | return node_create(NULL, data); |
| 267 | } | 306 | } |
| 268 | 307 | ||
| 269 | static plist_t parse_data_node(char *bnode, uint64_t size) | 308 | static plist_t parse_data_node(char *bnode, uint64_t size) |
| @@ -275,7 +314,7 @@ static plist_t parse_data_node(char *bnode, uint64_t size) | |||
| 275 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size); | 314 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size); |
| 276 | memcpy(data->buff, bnode, sizeof(uint8_t) * size); | 315 | memcpy(data->buff, bnode, sizeof(uint8_t) * size); |
| 277 | 316 | ||
| 278 | return g_node_new(data); | 317 | return node_create(NULL, data); |
| 279 | } | 318 | } |
| 280 | 319 | ||
| 281 | static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size) | 320 | static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size) |
| @@ -287,7 +326,7 @@ static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size) | |||
| 287 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size * 2); | 326 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size * 2); |
| 288 | memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size * 2); | 327 | memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size * 2); |
| 289 | 328 | ||
| 290 | return g_node_new(data); | 329 | return node_create(NULL, data); |
| 291 | } | 330 | } |
| 292 | 331 | ||
| 293 | static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) | 332 | static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) |
| @@ -299,7 +338,7 @@ static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) | |||
| 299 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size); | 338 | data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size); |
| 300 | memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size); | 339 | memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size); |
| 301 | 340 | ||
| 302 | return g_node_new(data); | 341 | return node_create(NULL, data); |
| 303 | } | 342 | } |
| 304 | 343 | ||
| 305 | 344 | ||
| @@ -329,7 +368,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec | |||
| 329 | data->type = PLIST_BOOLEAN; | 368 | data->type = PLIST_BOOLEAN; |
| 330 | data->boolval = TRUE; | 369 | data->boolval = TRUE; |
| 331 | data->length = 1; | 370 | data->length = 1; |
| 332 | return g_node_new(data); | 371 | return node_create(NULL, data); |
| 333 | } | 372 | } |
| 334 | 373 | ||
| 335 | case BPLIST_FALSE: | 374 | case BPLIST_FALSE: |
| @@ -338,7 +377,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec | |||
| 338 | data->type = PLIST_BOOLEAN; | 377 | data->type = PLIST_BOOLEAN; |
| 339 | data->boolval = FALSE; | 378 | data->boolval = FALSE; |
| 340 | data->length = 1; | 379 | data->length = 1; |
| 341 | return g_node_new(data); | 380 | return node_create(NULL, data); |
| 342 | } | 381 | } |
| 343 | 382 | ||
| 344 | case BPLIST_NULL: | 383 | case BPLIST_NULL: |
| @@ -420,7 +459,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec | |||
| 420 | return NULL; | 459 | return NULL; |
| 421 | } | 460 | } |
| 422 | 461 | ||
| 423 | static gpointer copy_plist_data(gconstpointer src, gpointer data) | 462 | static void* copy_plist_data(const void* src) |
| 424 | { | 463 | { |
| 425 | plist_data_t srcdata = (plist_data_t) src; | 464 | plist_data_t srcdata = (plist_data_t) src; |
| 426 | plist_data_t dstdata = plist_new_plist_data(); | 465 | plist_data_t dstdata = plist_new_plist_data(); |
| @@ -541,18 +580,18 @@ void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) | |||
| 541 | 580 | ||
| 542 | if (index1 < num_objects) | 581 | if (index1 < num_objects) |
| 543 | { | 582 | { |
| 544 | if (G_NODE_IS_ROOT(nodeslist[index1])) | 583 | if (NODE_IS_ROOT(nodeslist[index1])) |
| 545 | g_node_append(nodeslist[i], nodeslist[index1]); | 584 | node_attach(nodeslist[i], nodeslist[index1]); |
| 546 | else | 585 | else |
| 547 | g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL)); | 586 | node_attach(nodeslist[i], node_copy_deep(nodeslist[index1], copy_plist_data)); |
| 548 | } | 587 | } |
| 549 | 588 | ||
| 550 | if (index2 < num_objects) | 589 | if (index2 < num_objects) |
| 551 | { | 590 | { |
| 552 | if (G_NODE_IS_ROOT(nodeslist[index2])) | 591 | if (NODE_IS_ROOT(nodeslist[index2])) |
| 553 | g_node_append(nodeslist[i], nodeslist[index2]); | 592 | node_attach(nodeslist[i], nodeslist[index2]); |
| 554 | else | 593 | else |
| 555 | g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index2], copy_plist_data, NULL)); | 594 | node_attach(nodeslist[i], node_copy_deep(nodeslist[index2], copy_plist_data)); |
| 556 | } | 595 | } |
| 557 | } | 596 | } |
| 558 | 597 | ||
| @@ -567,10 +606,10 @@ void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) | |||
| 567 | 606 | ||
| 568 | if (index1 < num_objects) | 607 | if (index1 < num_objects) |
| 569 | { | 608 | { |
| 570 | if (G_NODE_IS_ROOT(nodeslist[index1])) | 609 | if (NODE_IS_ROOT(nodeslist[index1])) |
| 571 | g_node_append(nodeslist[i], nodeslist[index1]); | 610 | node_attach(nodeslist[i], nodeslist[index1]); |
| 572 | else | 611 | else |
| 573 | g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL)); | 612 | node_attach(nodeslist[i], node_copy_deep(nodeslist[index1], copy_plist_data)); |
| 574 | } | 613 | } |
| 575 | } | 614 | } |
| 576 | free(data->buff); | 615 | free(data->buff); |
| @@ -584,15 +623,15 @@ void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) | |||
| 584 | free(nodeslist); | 623 | free(nodeslist); |
| 585 | } | 624 | } |
| 586 | 625 | ||
| 587 | static guint plist_data_hash(gconstpointer key) | 626 | static unsigned int plist_data_hash(const void* key) |
| 588 | { | 627 | { |
| 589 | plist_data_t data = plist_get_data((plist_t) key); | 628 | plist_data_t data = plist_get_data((plist_t) key); |
| 590 | 629 | ||
| 591 | guint hash = data->type; | 630 | unsigned int hash = data->type; |
| 592 | guint i = 0; | 631 | unsigned int i = 0; |
| 593 | 632 | ||
| 594 | char *buff = NULL; | 633 | char *buff = NULL; |
| 595 | guint size = 0; | 634 | unsigned int size = 0; |
| 596 | 635 | ||
| 597 | switch (data->type) | 636 | switch (data->type) |
| 598 | { | 637 | { |
| @@ -612,7 +651,7 @@ static guint plist_data_hash(gconstpointer key) | |||
| 612 | case PLIST_DICT: | 651 | case PLIST_DICT: |
| 613 | //for these types only hash pointer | 652 | //for these types only hash pointer |
| 614 | buff = (char *) &key; | 653 | buff = (char *) &key; |
| 615 | size = sizeof(gconstpointer); | 654 | size = sizeof(const void*); |
| 616 | break; | 655 | break; |
| 617 | case PLIST_DATE: | 656 | case PLIST_DATE: |
| 618 | buff = (char *) &(data->timeval); | 657 | buff = (char *) &(data->timeval); |
| @@ -629,22 +668,20 @@ static guint plist_data_hash(gconstpointer key) | |||
| 629 | return hash; | 668 | return hash; |
| 630 | } | 669 | } |
| 631 | 670 | ||
| 632 | |||
| 633 | |||
| 634 | struct serialize_s | 671 | struct serialize_s |
| 635 | { | 672 | { |
| 636 | GPtrArray *objects; | 673 | ptrarray_t* objects; |
| 637 | GHashTable *ref_table; | 674 | hashtable_t* ref_table; |
| 638 | }; | 675 | }; |
| 639 | 676 | ||
| 640 | static void serialize_plist(GNode * node, gpointer data) | 677 | static void serialize_plist(node_t* node, void* data) |
| 641 | { | 678 | { |
| 642 | uint64_t *index_val = NULL; | 679 | uint64_t *index_val = NULL; |
| 643 | struct serialize_s *ser = (struct serialize_s *) data; | 680 | struct serialize_s *ser = (struct serialize_s *) data; |
| 644 | uint64_t current_index = ser->objects->len; | 681 | uint64_t current_index = ser->objects->len; |
| 645 | 682 | ||
| 646 | //first check that node is not yet in objects | 683 | //first check that node is not yet in objects |
| 647 | gpointer val = g_hash_table_lookup(ser->ref_table, node); | 684 | void* val = hash_table_lookup(ser->ref_table, node); |
| 648 | if (val) | 685 | if (val) |
| 649 | { | 686 | { |
| 650 | //data is already in table | 687 | //data is already in table |
| @@ -653,17 +690,23 @@ static void serialize_plist(GNode * node, gpointer data) | |||
| 653 | //insert new ref | 690 | //insert new ref |
| 654 | index_val = (uint64_t *) malloc(sizeof(uint64_t)); | 691 | index_val = (uint64_t *) malloc(sizeof(uint64_t)); |
| 655 | *index_val = current_index; | 692 | *index_val = current_index; |
| 656 | g_hash_table_insert(ser->ref_table, node, index_val); | 693 | hash_table_insert(ser->ref_table, node, index_val); |
| 657 | 694 | ||
| 658 | //now append current node to object array | 695 | //now append current node to object array |
| 659 | g_ptr_array_add(ser->objects, node); | 696 | ptr_array_add(ser->objects, node); |
| 660 | 697 | ||
| 661 | //now recurse on children | 698 | //now recurse on children |
| 662 | g_node_children_foreach(node, G_TRAVERSE_ALL, serialize_plist, data); | 699 | node_iterator_t *ni = node_iterator_create(node->children); |
| 700 | node_t *ch; | ||
| 701 | while ((ch = node_iterator_next(ni))) { | ||
| 702 | serialize_plist(ch, data); | ||
| 703 | } | ||
| 704 | node_iterator_destroy(ni); | ||
| 705 | |||
| 663 | return; | 706 | return; |
| 664 | } | 707 | } |
| 665 | 708 | ||
| 666 | static gboolean free_index(gpointer key, gpointer value, gpointer user_data) | 709 | static int free_index(void* key, void* value, void* user_data) |
| 667 | { | 710 | { |
| 668 | free((uint64_t *) value); | 711 | free((uint64_t *) value); |
| 669 | return TRUE; | 712 | return TRUE; |
| @@ -671,7 +714,7 @@ static gboolean free_index(gpointer key, gpointer value, gpointer user_data) | |||
| 671 | 714 | ||
| 672 | #define Log2(x) (x == 8 ? 3 : (x == 4 ? 2 : (x == 2 ? 1 : 0))) | 715 | #define Log2(x) (x == 8 ? 3 : (x == 4 ? 2 : (x == 2 ? 1 : 0))) |
| 673 | 716 | ||
| 674 | static void write_int(GByteArray * bplist, uint64_t val) | 717 | static void write_int(bytearray_t * bplist, uint64_t val) |
| 675 | { | 718 | { |
| 676 | uint64_t size = get_needed_bytes(val); | 719 | uint64_t size = get_needed_bytes(val); |
| 677 | uint8_t *buff = NULL; | 720 | uint8_t *buff = NULL; |
| @@ -679,7 +722,7 @@ static void write_int(GByteArray * bplist, uint64_t val) | |||
| 679 | if (size == 3) | 722 | if (size == 3) |
| 680 | size++; | 723 | size++; |
| 681 | 724 | ||
| 682 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 725 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 683 | val = val << ((sizeof(uint64_t) - size) * 8); | 726 | val = val << ((sizeof(uint64_t) - size) * 8); |
| 684 | #endif | 727 | #endif |
| 685 | 728 | ||
| @@ -687,11 +730,11 @@ static void write_int(GByteArray * bplist, uint64_t val) | |||
| 687 | buff[0] = BPLIST_UINT | Log2(size); | 730 | buff[0] = BPLIST_UINT | Log2(size); |
| 688 | memcpy(buff + 1, &val, size); | 731 | memcpy(buff + 1, &val, size); |
| 689 | byte_convert(buff + 1, size); | 732 | byte_convert(buff + 1, size); |
| 690 | g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); | 733 | byte_array_append(bplist, buff, sizeof(uint8_t) + size); |
| 691 | free(buff); | 734 | free(buff); |
| 692 | } | 735 | } |
| 693 | 736 | ||
| 694 | static void write_real(GByteArray * bplist, double val) | 737 | static void write_real(bytearray_t * bplist, double val) |
| 695 | { | 738 | { |
| 696 | uint64_t size = get_real_bytes(val); //cheat to know used space | 739 | uint64_t size = get_real_bytes(val); //cheat to know used space |
| 697 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); | 740 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); |
| @@ -706,89 +749,89 @@ static void write_real(GByteArray * bplist, double val) | |||
| 706 | memcpy(buff + 1, &tmpval, size); | 749 | memcpy(buff + 1, &tmpval, size); |
| 707 | } | 750 | } |
| 708 | float_byte_convert(buff + 1, size); | 751 | float_byte_convert(buff + 1, size); |
| 709 | g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); | 752 | byte_array_append(bplist, buff, sizeof(uint8_t) + size); |
| 710 | free(buff); | 753 | free(buff); |
| 711 | } | 754 | } |
| 712 | 755 | ||
| 713 | static void write_date(GByteArray * bplist, double val) | 756 | static void write_date(bytearray_t * bplist, double val) |
| 714 | { | 757 | { |
| 715 | uint64_t size = 8; //dates always use 8 bytes | 758 | uint64_t size = 8; //dates always use 8 bytes |
| 716 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); | 759 | uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); |
| 717 | buff[0] = BPLIST_DATE | Log2(size); | 760 | buff[0] = BPLIST_DATE | Log2(size); |
| 718 | memcpy(buff + 1, &val, size); | 761 | memcpy(buff + 1, &val, size); |
| 719 | float_byte_convert(buff + 1, size); | 762 | float_byte_convert(buff + 1, size); |
| 720 | g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); | 763 | byte_array_append(bplist, buff, sizeof(uint8_t) + size); |
| 721 | free(buff); | 764 | free(buff); |
| 722 | } | 765 | } |
| 723 | 766 | ||
| 724 | static void write_raw_data(GByteArray * bplist, uint8_t mark, uint8_t * val, uint64_t size) | 767 | static void write_raw_data(bytearray_t * bplist, uint8_t mark, uint8_t * val, uint64_t size) |
| 725 | { | 768 | { |
| 726 | uint8_t *buff = NULL; | 769 | uint8_t *buff = NULL; |
| 727 | uint8_t marker = mark | (size < 15 ? size : 0xf); | 770 | uint8_t marker = mark | (size < 15 ? size : 0xf); |
| 728 | g_byte_array_append(bplist, &marker, sizeof(uint8_t)); | 771 | byte_array_append(bplist, &marker, sizeof(uint8_t)); |
| 729 | if (size >= 15) | 772 | if (size >= 15) |
| 730 | { | 773 | { |
| 731 | GByteArray *int_buff = g_byte_array_new(); | 774 | bytearray_t *int_buff = byte_array_new(); |
| 732 | write_int(int_buff, size); | 775 | write_int(int_buff, size); |
| 733 | g_byte_array_append(bplist, int_buff->data, int_buff->len); | 776 | byte_array_append(bplist, int_buff->data, int_buff->len); |
| 734 | g_byte_array_free(int_buff, TRUE); | 777 | byte_array_free(int_buff); |
| 735 | } | 778 | } |
| 736 | //stupid unicode buffer length | 779 | //stupid unicode buffer length |
| 737 | if (BPLIST_UNICODE==mark) size *= 2; | 780 | if (BPLIST_UNICODE==mark) size *= 2; |
| 738 | buff = (uint8_t *) malloc(size); | 781 | buff = (uint8_t *) malloc(size); |
| 739 | memcpy(buff, val, size); | 782 | memcpy(buff, val, size); |
| 740 | g_byte_array_append(bplist, buff, size); | 783 | byte_array_append(bplist, buff, size); |
| 741 | free(buff); | 784 | free(buff); |
| 742 | } | 785 | } |
| 743 | 786 | ||
| 744 | static void write_data(GByteArray * bplist, uint8_t * val, uint64_t size) | 787 | static void write_data(bytearray_t * bplist, uint8_t * val, uint64_t size) |
| 745 | { | 788 | { |
| 746 | write_raw_data(bplist, BPLIST_DATA, val, size); | 789 | write_raw_data(bplist, BPLIST_DATA, val, size); |
| 747 | } | 790 | } |
| 748 | 791 | ||
| 749 | static void write_string(GByteArray * bplist, char *val) | 792 | static void write_string(bytearray_t * bplist, char *val) |
| 750 | { | 793 | { |
| 751 | uint64_t size = strlen(val); | 794 | uint64_t size = strlen(val); |
| 752 | write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size); | 795 | write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size); |
| 753 | } | 796 | } |
| 754 | 797 | ||
| 755 | static void write_unicode(GByteArray * bplist, gunichar2 * val, uint64_t size) | 798 | static void write_unicode(bytearray_t * bplist, uint16_t * val, uint64_t size) |
| 756 | { | 799 | { |
| 757 | uint64_t i = 0; | 800 | uint64_t i = 0; |
| 758 | uint64_t size2 = size * sizeof(gunichar2); | 801 | uint64_t size2 = size * sizeof(uint16_t); |
| 759 | uint8_t *buff = (uint8_t *) malloc(size2); | 802 | uint8_t *buff = (uint8_t *) malloc(size2); |
| 760 | memcpy(buff, val, size2); | 803 | memcpy(buff, val, size2); |
| 761 | for (i = 0; i < size; i++) | 804 | for (i = 0; i < size; i++) |
| 762 | byte_convert(buff + i * sizeof(gunichar2), sizeof(gunichar2)); | 805 | byte_convert(buff + i * sizeof(uint16_t), sizeof(uint16_t)); |
| 763 | write_raw_data(bplist, BPLIST_UNICODE, buff, size); | 806 | write_raw_data(bplist, BPLIST_UNICODE, buff, size); |
| 764 | free(buff); | 807 | free(buff); |
| 765 | } | 808 | } |
| 766 | 809 | ||
| 767 | static void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) | 810 | static void write_array(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t dict_param_size) |
| 768 | { | 811 | { |
| 769 | uint64_t idx = 0; | 812 | uint64_t idx = 0; |
| 770 | uint8_t *buff = NULL; | 813 | uint8_t *buff = NULL; |
| 771 | 814 | ||
| 772 | GNode *cur = NULL; | 815 | node_t* cur = NULL; |
| 773 | uint64_t i = 0; | 816 | uint64_t i = 0; |
| 774 | 817 | ||
| 775 | uint64_t size = g_node_n_children(node); | 818 | uint64_t size = node_n_children(node); |
| 776 | uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf); | 819 | uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf); |
| 777 | g_byte_array_append(bplist, &marker, sizeof(uint8_t)); | 820 | byte_array_append(bplist, &marker, sizeof(uint8_t)); |
| 778 | if (size >= 15) | 821 | if (size >= 15) |
| 779 | { | 822 | { |
| 780 | GByteArray *int_buff = g_byte_array_new(); | 823 | bytearray_t *int_buff = byte_array_new(); |
| 781 | write_int(int_buff, size); | 824 | write_int(int_buff, size); |
| 782 | g_byte_array_append(bplist, int_buff->data, int_buff->len); | 825 | byte_array_append(bplist, int_buff->data, int_buff->len); |
| 783 | g_byte_array_free(int_buff, TRUE); | 826 | byte_array_free(int_buff); |
| 784 | } | 827 | } |
| 785 | 828 | ||
| 786 | buff = (uint8_t *) malloc(size * dict_param_size); | 829 | buff = (uint8_t *) malloc(size * dict_param_size); |
| 787 | 830 | ||
| 788 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next, i++) | 831 | for (i = 0, cur = node_first_child(node); cur && i < size; cur = node_next_sibling(cur), i++) |
| 789 | { | 832 | { |
| 790 | idx = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); | 833 | idx = *(uint64_t *) (hash_table_lookup(ref_table, cur)); |
| 791 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 834 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 792 | idx = idx << ((sizeof(uint64_t) - dict_param_size) * 8); | 835 | idx = idx << ((sizeof(uint64_t) - dict_param_size) * 8); |
| 793 | #endif | 836 | #endif |
| 794 | memcpy(buff + i * dict_param_size, &idx, dict_param_size); | 837 | memcpy(buff + i * dict_param_size, &idx, dict_param_size); |
| @@ -796,44 +839,43 @@ static void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_tabl | |||
| 796 | } | 839 | } |
| 797 | 840 | ||
| 798 | //now append to bplist | 841 | //now append to bplist |
| 799 | g_byte_array_append(bplist, buff, size * dict_param_size); | 842 | byte_array_append(bplist, buff, size * dict_param_size); |
| 800 | free(buff); | 843 | free(buff); |
| 801 | 844 | ||
| 802 | } | 845 | } |
| 803 | 846 | ||
| 804 | static void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) | 847 | static void write_dict(bytearray_t * bplist, node_t* node, hashtable_t* ref_table, uint8_t dict_param_size) |
| 805 | { | 848 | { |
| 806 | uint64_t idx1 = 0; | 849 | uint64_t idx1 = 0; |
| 807 | uint64_t idx2 = 0; | 850 | uint64_t idx2 = 0; |
| 808 | uint8_t *buff = NULL; | 851 | uint8_t *buff = NULL; |
| 809 | 852 | ||
| 810 | GNode *cur = NULL; | 853 | node_t* cur = NULL; |
| 811 | uint64_t i = 0; | 854 | uint64_t i = 0; |
| 812 | 855 | ||
| 813 | uint64_t size = g_node_n_children(node) / 2; | 856 | uint64_t size = node_n_children(node) / 2; |
| 814 | uint8_t marker = BPLIST_DICT | (size < 15 ? size : 0xf); | 857 | uint8_t marker = BPLIST_DICT | (size < 15 ? size : 0xf); |
| 815 | g_byte_array_append(bplist, &marker, sizeof(uint8_t)); | 858 | byte_array_append(bplist, &marker, sizeof(uint8_t)); |
| 816 | if (size >= 15) | 859 | if (size >= 15) |
| 817 | { | 860 | { |
| 818 | GByteArray *int_buff = g_byte_array_new(); | 861 | bytearray_t *int_buff = byte_array_new(); |
| 819 | write_int(int_buff, size); | 862 | write_int(int_buff, size); |
| 820 | g_byte_array_append(bplist, int_buff->data, int_buff->len); | 863 | byte_array_append(bplist, int_buff->data, int_buff->len); |
| 821 | g_byte_array_free(int_buff, TRUE); | 864 | byte_array_free(int_buff); |
| 822 | } | 865 | } |
| 823 | 866 | ||
| 824 | buff = (uint8_t *) malloc(size * 2 * dict_param_size); | 867 | buff = (uint8_t *) malloc(size * 2 * dict_param_size); |
| 825 | 868 | for (i = 0, cur = node_first_child(node); cur && i < size; cur = node_next_sibling(node_next_sibling(cur)), i++) | |
| 826 | for (i = 0, cur = node->children; cur && i < size; cur = cur->next->next, i++) | ||
| 827 | { | 869 | { |
| 828 | idx1 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); | 870 | idx1 = *(uint64_t *) (hash_table_lookup(ref_table, cur)); |
| 829 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 871 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 830 | idx1 = idx1 << ((sizeof(uint64_t) - dict_param_size) * 8); | 872 | idx1 = idx1 << ((sizeof(uint64_t) - dict_param_size) * 8); |
| 831 | #endif | 873 | #endif |
| 832 | memcpy(buff + i * dict_param_size, &idx1, dict_param_size); | 874 | memcpy(buff + i * dict_param_size, &idx1, dict_param_size); |
| 833 | byte_convert(buff + i * dict_param_size, dict_param_size); | 875 | byte_convert(buff + i * dict_param_size, dict_param_size); |
| 834 | 876 | ||
| 835 | idx2 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur->next)); | 877 | idx2 = *(uint64_t *) (hash_table_lookup(ref_table, cur->next)); |
| 836 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 878 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 837 | idx2 = idx2 << ((sizeof(uint64_t) - dict_param_size) * 8); | 879 | idx2 = idx2 << ((sizeof(uint64_t) - dict_param_size) * 8); |
| 838 | #endif | 880 | #endif |
| 839 | memcpy(buff + (i + size) * dict_param_size, &idx2, dict_param_size); | 881 | memcpy(buff + (i + size) * dict_param_size, &idx2, dict_param_size); |
| @@ -841,7 +883,7 @@ static void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table | |||
| 841 | } | 883 | } |
| 842 | 884 | ||
| 843 | //now append to bplist | 885 | //now append to bplist |
| 844 | g_byte_array_append(bplist, buff, size * 2 * dict_param_size); | 886 | byte_array_append(bplist, buff, size * 2 * dict_param_size); |
| 845 | free(buff); | 887 | free(buff); |
| 846 | 888 | ||
| 847 | } | 889 | } |
| @@ -860,38 +902,81 @@ static int is_ascii_string(char* s, int len) | |||
| 860 | return ret; | 902 | return ret; |
| 861 | } | 903 | } |
| 862 | 904 | ||
| 905 | uint16_t *plist_utf8_to_utf16(char *unistr, long size, long *items_read, long *items_written) | ||
| 906 | { | ||
| 907 | uint16_t *outbuf = (uint16_t*)malloc((size+1)*sizeof(uint16_t)); | ||
| 908 | int p = 0; | ||
| 909 | int i = 0; | ||
| 910 | |||
| 911 | unsigned char c0; | ||
| 912 | unsigned char c1; | ||
| 913 | unsigned char c2; | ||
| 914 | |||
| 915 | while (i < size) { | ||
| 916 | c0 = unistr[i]; | ||
| 917 | c1 = (i < size-1) ? unistr[i+1] : 0; | ||
| 918 | c2 = (i < size-2) ? unistr[i+2] : 0; | ||
| 919 | if ((c0 >= 0xE0) && (i < size-2) && (c1 >= 0x80) && (c2 >= 0x80)) { | ||
| 920 | // 3 byte sequence | ||
| 921 | outbuf[p++] = ((c2 & 0x3F) + ((c1 & 3) << 6)) + (((c1 >> 2) & 15) << 8) + ((c0 & 15) << 12); | ||
| 922 | i+=3; | ||
| 923 | } else if ((c0 >= 0xC0) && (i < size-1) && (c1 >= 0x80)) { | ||
| 924 | // 2 byte sequence | ||
| 925 | outbuf[p++] = ((c1 & 0x3F) + ((c0 & 3) << 6)) + (((c0 >> 2) & 7) << 8); | ||
| 926 | i+=2; | ||
| 927 | } else if (c0 < 0x80) { | ||
| 928 | // 1 byte sequence | ||
| 929 | outbuf[p++] = c0; | ||
| 930 | i+=1; | ||
| 931 | } else { | ||
| 932 | // invalid character | ||
| 933 | fprintf(stderr, "invalid utf8 sequence in string at index %d\n", i); | ||
| 934 | break; | ||
| 935 | } | ||
| 936 | } | ||
| 937 | if (items_read) { | ||
| 938 | *items_read = i; | ||
| 939 | } | ||
| 940 | if (items_written) { | ||
| 941 | *items_written = p; | ||
| 942 | } | ||
| 943 | outbuf[p] = 0; | ||
| 944 | |||
| 945 | return outbuf; | ||
| 946 | |||
| 947 | } | ||
| 948 | |||
| 863 | void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | 949 | void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) |
| 864 | { | 950 | { |
| 865 | GPtrArray *objects = NULL; | 951 | ptrarray_t* objects = NULL; |
| 866 | GHashTable *ref_table = NULL; | 952 | hashtable_t* ref_table = NULL; |
| 867 | struct serialize_s ser_s; | 953 | struct serialize_s ser_s; |
| 868 | uint8_t offset_size = 0; | 954 | uint8_t offset_size = 0; |
| 869 | uint8_t dict_param_size = 0; | 955 | uint8_t dict_param_size = 0; |
| 870 | uint64_t num_objects = 0; | 956 | uint64_t num_objects = 0; |
| 871 | uint64_t root_object = 0; | 957 | uint64_t root_object = 0; |
| 872 | uint64_t offset_table_index = 0; | 958 | uint64_t offset_table_index = 0; |
| 873 | GByteArray *bplist_buff = NULL; | 959 | bytearray_t *bplist_buff = NULL; |
| 874 | uint64_t i = 0; | 960 | uint64_t i = 0; |
| 875 | uint8_t *buff = NULL; | 961 | uint8_t *buff = NULL; |
| 876 | uint64_t *offsets = NULL; | 962 | uint64_t *offsets = NULL; |
| 877 | uint8_t pad[6] = { 0, 0, 0, 0, 0, 0 }; | 963 | uint8_t pad[6] = { 0, 0, 0, 0, 0, 0 }; |
| 878 | uint8_t trailer[BPLIST_TRL_SIZE]; | 964 | uint8_t trailer[BPLIST_TRL_SIZE]; |
| 879 | //for string | 965 | //for string |
| 880 | glong len = 0; | 966 | long len = 0; |
| 881 | int type = 0; | 967 | int type = 0; |
| 882 | glong items_read = 0; | 968 | long items_read = 0; |
| 883 | glong items_written = 0; | 969 | long items_written = 0; |
| 884 | GError *error = NULL; | 970 | uint16_t *unicodestr = NULL; |
| 885 | gunichar2 *unicodestr = NULL; | ||
| 886 | 971 | ||
| 887 | //check for valid input | 972 | //check for valid input |
| 888 | if (!plist || !plist_bin || *plist_bin || !length) | 973 | if (!plist || !plist_bin || *plist_bin || !length) |
| 889 | return; | 974 | return; |
| 890 | 975 | ||
| 891 | //list of objects | 976 | //list of objects |
| 892 | objects = g_ptr_array_new(); | 977 | objects = ptr_array_new(256); |
| 893 | //hashtable to write only once same nodes | 978 | //hashtable to write only once same nodes |
| 894 | ref_table = g_hash_table_new(plist_data_hash, plist_data_compare); | 979 | ref_table = hash_table_new(plist_data_hash, plist_data_compare); |
| 895 | 980 | ||
| 896 | //serialize plist | 981 | //serialize plist |
| 897 | ser_s.objects = objects; | 982 | ser_s.objects = objects; |
| @@ -906,18 +991,18 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 906 | offset_table_index = 0; //unknown yet | 991 | offset_table_index = 0; //unknown yet |
| 907 | 992 | ||
| 908 | //setup a dynamic bytes array to store bplist in | 993 | //setup a dynamic bytes array to store bplist in |
| 909 | bplist_buff = g_byte_array_new(); | 994 | bplist_buff = byte_array_new(); |
| 910 | 995 | ||
| 911 | //set magic number and version | 996 | //set magic number and version |
| 912 | g_byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); | 997 | byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); |
| 913 | g_byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE); | 998 | byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE); |
| 914 | 999 | ||
| 915 | //write objects and table | 1000 | //write objects and table |
| 916 | offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t)); | 1001 | offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t)); |
| 917 | for (i = 0; i < num_objects; i++) | 1002 | for (i = 0; i < num_objects; i++) |
| 918 | { | 1003 | { |
| 919 | 1004 | ||
| 920 | plist_data_t data = plist_get_data(g_ptr_array_index(objects, i)); | 1005 | plist_data_t data = plist_get_data(ptr_array_index(objects, i)); |
| 921 | offsets[i] = bplist_buff->len; | 1006 | offsets[i] = bplist_buff->len; |
| 922 | 1007 | ||
| 923 | switch (data->type) | 1008 | switch (data->type) |
| @@ -925,7 +1010,7 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 925 | case PLIST_BOOLEAN: | 1010 | case PLIST_BOOLEAN: |
| 926 | buff = (uint8_t *) malloc(sizeof(uint8_t)); | 1011 | buff = (uint8_t *) malloc(sizeof(uint8_t)); |
| 927 | buff[0] = data->boolval ? BPLIST_TRUE : BPLIST_FALSE; | 1012 | buff[0] = data->boolval ? BPLIST_TRUE : BPLIST_FALSE; |
| 928 | g_byte_array_append(bplist_buff, buff, sizeof(uint8_t)); | 1013 | byte_array_append(bplist_buff, buff, sizeof(uint8_t)); |
| 929 | free(buff); | 1014 | free(buff); |
| 930 | break; | 1015 | break; |
| 931 | 1016 | ||
| @@ -946,21 +1031,21 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 946 | } | 1031 | } |
| 947 | else | 1032 | else |
| 948 | { | 1033 | { |
| 949 | unicodestr = g_utf8_to_utf16(data->strval, len, &items_read, &items_written, &error); | 1034 | unicodestr = plist_utf8_to_utf16(data->strval, len, &items_read, &items_written); |
| 950 | write_unicode(bplist_buff, unicodestr, items_written); | 1035 | write_unicode(bplist_buff, unicodestr, items_written); |
| 951 | g_free(unicodestr); | 1036 | free(unicodestr); |
| 952 | } | 1037 | } |
| 953 | break; | 1038 | break; |
| 954 | case PLIST_DATA: | 1039 | case PLIST_DATA: |
| 955 | write_data(bplist_buff, data->buff, data->length); | 1040 | write_data(bplist_buff, data->buff, data->length); |
| 956 | case PLIST_ARRAY: | 1041 | case PLIST_ARRAY: |
| 957 | write_array(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); | 1042 | write_array(bplist_buff, ptr_array_index(objects, i), ref_table, dict_param_size); |
| 958 | break; | 1043 | break; |
| 959 | case PLIST_DICT: | 1044 | case PLIST_DICT: |
| 960 | write_dict(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); | 1045 | write_dict(bplist_buff, ptr_array_index(objects, i), ref_table, dict_param_size); |
| 961 | break; | 1046 | break; |
| 962 | case PLIST_DATE: | 1047 | case PLIST_DATE: |
| 963 | write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / G_USEC_PER_SEC); | 1048 | write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / 1000000); |
| 964 | break; | 1049 | break; |
| 965 | default: | 1050 | default: |
| 966 | break; | 1051 | break; |
| @@ -968,9 +1053,9 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 968 | } | 1053 | } |
| 969 | 1054 | ||
| 970 | //free intermediate objects | 1055 | //free intermediate objects |
| 971 | g_hash_table_foreach_remove(ref_table, free_index, NULL); | 1056 | //hash_table_foreach_remove(ref_table, free_index, NULL); |
| 972 | g_ptr_array_free(objects, TRUE); | 1057 | ptr_array_free(objects); |
| 973 | g_hash_table_destroy(ref_table); | 1058 | hash_table_destroy(ref_table); |
| 974 | 1059 | ||
| 975 | //write offsets | 1060 | //write offsets |
| 976 | offset_size = get_needed_bytes(bplist_buff->len); | 1061 | offset_size = get_needed_bytes(bplist_buff->len); |
| @@ -979,23 +1064,23 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 979 | { | 1064 | { |
| 980 | uint8_t *offsetbuff = (uint8_t *) malloc(offset_size); | 1065 | uint8_t *offsetbuff = (uint8_t *) malloc(offset_size); |
| 981 | 1066 | ||
| 982 | #if G_BYTE_ORDER == G_BIG_ENDIAN | 1067 | #if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN |
| 983 | offsets[i] = offsets[i] << ((sizeof(uint64_t) - offset_size) * 8); | 1068 | offsets[i] = offsets[i] << ((sizeof(uint64_t) - offset_size) * 8); |
| 984 | #endif | 1069 | #endif |
| 985 | 1070 | ||
| 986 | memcpy(offsetbuff, &offsets[i], offset_size); | 1071 | memcpy(offsetbuff, &offsets[i], offset_size); |
| 987 | byte_convert(offsetbuff, offset_size); | 1072 | byte_convert(offsetbuff, offset_size); |
| 988 | g_byte_array_append(bplist_buff, offsetbuff, offset_size); | 1073 | byte_array_append(bplist_buff, offsetbuff, offset_size); |
| 989 | free(offsetbuff); | 1074 | free(offsetbuff); |
| 990 | } | 1075 | } |
| 991 | 1076 | ||
| 992 | //experimental pad to reflect apple's files | 1077 | //experimental pad to reflect apple's files |
| 993 | g_byte_array_append(bplist_buff, pad, 6); | 1078 | byte_array_append(bplist_buff, pad, 6); |
| 994 | 1079 | ||
| 995 | //setup trailer | 1080 | //setup trailer |
| 996 | num_objects = GUINT64_FROM_BE(num_objects); | 1081 | num_objects = be64toh(num_objects); |
| 997 | root_object = GUINT64_FROM_BE(root_object); | 1082 | root_object = be64toh(root_object); |
| 998 | offset_table_index = GUINT64_FROM_BE(offset_table_index); | 1083 | offset_table_index = be64toh(offset_table_index); |
| 999 | 1084 | ||
| 1000 | memcpy(trailer + BPLIST_TRL_OFFSIZE_IDX, &offset_size, sizeof(uint8_t)); | 1085 | memcpy(trailer + BPLIST_TRL_OFFSIZE_IDX, &offset_size, sizeof(uint8_t)); |
| 1001 | memcpy(trailer + BPLIST_TRL_PARMSIZE_IDX, &dict_param_size, sizeof(uint8_t)); | 1086 | memcpy(trailer + BPLIST_TRL_PARMSIZE_IDX, &dict_param_size, sizeof(uint8_t)); |
| @@ -1003,13 +1088,13 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) | |||
| 1003 | memcpy(trailer + BPLIST_TRL_ROOTOBJ_IDX, &root_object, sizeof(uint64_t)); | 1088 | memcpy(trailer + BPLIST_TRL_ROOTOBJ_IDX, &root_object, sizeof(uint64_t)); |
| 1004 | memcpy(trailer + BPLIST_TRL_OFFTAB_IDX, &offset_table_index, sizeof(uint64_t)); | 1089 | memcpy(trailer + BPLIST_TRL_OFFTAB_IDX, &offset_table_index, sizeof(uint64_t)); |
| 1005 | 1090 | ||
| 1006 | g_byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE); | 1091 | byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE); |
| 1007 | 1092 | ||
| 1008 | //duplicate buffer | 1093 | //duplicate buffer |
| 1009 | *plist_bin = (char *) malloc(bplist_buff->len); | 1094 | *plist_bin = (char *) malloc(bplist_buff->len); |
| 1010 | memcpy(*plist_bin, bplist_buff->data, bplist_buff->len); | 1095 | memcpy(*plist_bin, bplist_buff->data, bplist_buff->len); |
| 1011 | *length = bplist_buff->len; | 1096 | *length = bplist_buff->len; |
| 1012 | 1097 | ||
| 1013 | g_byte_array_free(bplist_buff, TRUE); | 1098 | byte_array_free(bplist_buff); |
| 1014 | free(offsets); | 1099 | free(offsets); |
| 1015 | } | 1100 | } |
