summaryrefslogtreecommitdiffstats
path: root/src/bplist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/bplist.c')
-rw-r--r--src/bplist.c339
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
67static void float_byte_convert(uint8_t * address, size_t size) 73static 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
101static void byte_convert(uint8_t * address, size_t size) 107static 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
157static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) 164static 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
183static plist_t parse_real_node(char *bnode, uint8_t size) 190static 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
214static plist_t parse_date_node(char *bnode, uint8_t size) 221static 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
248static 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
241static plist_t parse_unicode_node(char *bnode, uint64_t size) 281static 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
269static plist_t parse_data_node(char *bnode, uint64_t size) 308static 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
281static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size) 320static 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
293static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) 332static 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
423static gpointer copy_plist_data(gconstpointer src, gpointer data) 462static 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
587static guint plist_data_hash(gconstpointer key) 626static 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
634struct serialize_s 671struct serialize_s
635{ 672{
636 GPtrArray *objects; 673 ptrarray_t* objects;
637 GHashTable *ref_table; 674 hashtable_t* ref_table;
638}; 675};
639 676
640static void serialize_plist(GNode * node, gpointer data) 677static 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
666static gboolean free_index(gpointer key, gpointer value, gpointer user_data) 709static 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
674static void write_int(GByteArray * bplist, uint64_t val) 717static 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
694static void write_real(GByteArray * bplist, double val) 737static 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
713static void write_date(GByteArray * bplist, double val) 756static 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
724static void write_raw_data(GByteArray * bplist, uint8_t mark, uint8_t * val, uint64_t size) 767static 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
744static void write_data(GByteArray * bplist, uint8_t * val, uint64_t size) 787static 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
749static void write_string(GByteArray * bplist, char *val) 792static 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
755static void write_unicode(GByteArray * bplist, gunichar2 * val, uint64_t size) 798static 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
767static void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) 810static 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
804static void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) 847static 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
905uint16_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
863void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) 949void 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}