summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt20
-rw-r--r--src/base64.c127
-rw-r--r--src/base64.h29
-rw-r--r--src/bplist.c339
-rw-r--r--src/bytearray.c52
-rw-r--r--src/bytearray.h36
-rw-r--r--src/common.h15
-rw-r--r--src/hashtable.c107
-rw-r--r--src/hashtable.h48
-rw-r--r--src/plist.c101
-rw-r--r--src/plist.h13
-rw-r--r--src/ptrarray.c61
-rw-r--r--src/ptrarray.h37
-rw-r--r--src/xplist.c85
14 files changed, 866 insertions, 204 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 85ce6eb..76f323a 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -1,10 +1,14 @@
1 1
2INCLUDE_DIRECTORIES( ${LIBXML2_INCLUDE_DIR} ${GLIB2_INCLUDE_DIR} ) 2INCLUDE_DIRECTORIES( ${LIBXML2_INCLUDE_DIR} ${CMAKE_SOURCE_DIR}/libcnary/include )
3 3
4 4
5SET(libplist_SRC 5SET(libplist_SRC
6 plist.c 6 plist.c
7 hashtable.c
8 bytearray.c
9 ptrarray.c
7 bplist.c 10 bplist.c
11 base64.c
8 xplist.c ) 12 xplist.c )
9 13
10SET(libplist++_SRC 14SET(libplist++_SRC
@@ -20,8 +24,18 @@ SET(libplist++_SRC
20 Dictionary.cpp 24 Dictionary.cpp
21 ) 25 )
22 26
23ADD_LIBRARY( plist SHARED ${libplist_SRC} ) 27SET(libcnary_object_files
24TARGET_LINK_LIBRARIES( plist ${LIBXML2_LIBRARIES} ${GLIB2_LIBRARIES} ) 28 ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/iterator.c.o
29 ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/list.c.o
30 ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/node.c.o
31 ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/node_iterator.c.o
32 ${CMAKE_BINARY_DIR}/libcnary/CMakeFiles/libcnary.dir/node_list.c.o
33)
34
35SET_SOURCE_FILES_PROPERTIES(${libcnary_object_files} PROPERTIES EXTERNAL_OBJECT true GENERATED true)
36
37ADD_LIBRARY( plist SHARED ${libplist_SRC} ${libcnary_object_files} )
38TARGET_LINK_LIBRARIES( plist ${LIBXML2_LIBRARIES} )
25SET_TARGET_PROPERTIES( plist PROPERTIES VERSION ${LIBPLIST_LIBVERSION} ) 39SET_TARGET_PROPERTIES( plist PROPERTIES VERSION ${LIBPLIST_LIBVERSION} )
26SET_TARGET_PROPERTIES( plist PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} ) 40SET_TARGET_PROPERTIES( plist PROPERTIES SOVERSION ${LIBPLIST_SOVERSION} )
27if(APPLE) 41if(APPLE)
diff --git a/src/base64.c b/src/base64.c
new file mode 100644
index 0000000..066494e
--- /dev/null
+++ b/src/base64.c
@@ -0,0 +1,127 @@
1/*
2 * base64.c
3 * base64 encode/decode implementation
4 *
5 * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#include <string.h>
22#include "base64.h"
23
24static const char base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
25static const char base64_pad = '=';
26
27static const int8_t base64_table[256] = {
28 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
29 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
30 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63,
31 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1,
32 -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
33 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1,
34 -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
35 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1,
36 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
37 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
38 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
39 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
40 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
41 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
42 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
43 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
44};
45
46char *base64encode(const unsigned char *buf, size_t *size)
47{
48 if (!buf || !size || !(*size > 0)) return NULL;
49 int outlen = (*size / 3) * 4;
50 char *outbuf = (char*)malloc(outlen+5); // 4 spare bytes + 1 for '\0'
51 size_t n = 0;
52 size_t m = 0;
53 unsigned char input[3];
54 unsigned int output[4];
55 while (n < *size) {
56 input[0] = buf[n++];
57 input[1] = (n < *size) ? buf[n++] : 0;
58 input[2] = (n < *size) ? buf[n++] : 0;
59 output[0] = input[0] >> 2;
60 output[1] = ((input[0] & 3) << 4) + (input[1] >> 4);
61 output[2] = ((input[1] & 15) << 2) + (input[2] >> 6);
62 output[3] = input[2] & 63;
63 outbuf[m++] = base64_str[(int)output[0]];
64 outbuf[m++] = base64_str[(int)output[1]];
65 outbuf[m++] = base64_str[(int)output[2]];
66 outbuf[m++] = base64_str[(int)output[3]];
67 }
68 while ((m % 4) != 0) {
69 outbuf[m++] = base64_pad;
70 }
71 outbuf[m] = 0; // 0-termination!
72 *size = m;
73 return outbuf;
74}
75
76static int base64decode_block(unsigned char *target, const char *data, size_t data_size)
77{
78 int w1,w2,w3,w4;
79 int n,i;
80
81 if (!data || (data_size <= 0)) {
82 return 0;
83 }
84
85 n = 0;
86 i = 0;
87 while (n < data_size-3) {
88 w1 = base64_table[(int)data[n]];
89 w2 = base64_table[(int)data[n+1]];
90 w3 = base64_table[(int)data[n+2]];
91 w4 = base64_table[(int)data[n+3]];
92
93 if (w2 >= 0) {
94 target[i++] = (char)((w1*4 + (w2 >> 4)) & 255);
95 }
96 if (w3 >= 0) {
97 target[i++] = (char)((w2*16 + (w3 >> 2)) & 255);
98 }
99 if (w4 >= 0) {
100 target[i++] = (char)((w3*64 + w4) & 255);
101 }
102 n+=4;
103 }
104 return i;
105}
106
107unsigned char *base64decode(const char *buf, size_t *size)
108{
109 if (!buf) return;
110 size_t len = strlen(buf);
111 if (len <= 0) return;
112 unsigned char *outbuf = (unsigned char*)malloc((len/4)*3+3);
113
114 unsigned char *line;
115 int p = 0;
116
117 line = (unsigned char*)strtok((char*)buf, "\r\n\t ");
118 while (line) {
119 p+=base64decode_block(outbuf+p, line, strlen((char*)line));
120
121 // get next line of base64 encoded block
122 line = (unsigned char*)strtok(NULL, "\r\n\t ");
123 }
124 outbuf[p] = 0;
125 *size = p;
126 return outbuf;
127}
diff --git a/src/base64.h b/src/base64.h
new file mode 100644
index 0000000..dbaf104
--- /dev/null
+++ b/src/base64.h
@@ -0,0 +1,29 @@
1/*
2 * base64.h
3 * base64 encode/decode implementation
4 *
5 * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#ifndef BASE64_H
22#define BASE64_H
23#include <stdlib.h>
24#include "common.h"
25
26_PLIST_INTERNAL char *base64encode(const unsigned char *buf, size_t *size);
27_PLIST_INTERNAL unsigned char *base64decode(const char *buf, size_t *size);
28
29#endif
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}
diff --git a/src/bytearray.c b/src/bytearray.c
new file mode 100644
index 0000000..0abfe49
--- /dev/null
+++ b/src/bytearray.c
@@ -0,0 +1,52 @@
1/*
2 * bytearray.c
3 * simple byte array implementation
4 *
5 * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#include <string.h>
22#include "bytearray.h"
23
24bytearray_t *byte_array_new()
25{
26 bytearray_t *a = (bytearray_t*)malloc(sizeof(bytearray_t));
27 a->data = malloc(256);
28 a->len = 0;
29 a->capacity = 256;
30 return a;
31}
32
33void byte_array_free(bytearray_t *ba)
34{
35 if (!ba) return;
36 if (ba->data) {
37 free(ba->data);
38 }
39 free(ba);
40}
41
42void byte_array_append(bytearray_t *ba, void *buf, size_t len)
43{
44 if (!ba || !ba->data || (len <= 0)) return;
45 size_t remaining = ba->capacity-ba->len;
46 if (len > remaining) {
47 ba->data = realloc(ba->data, ba->capacity + (len - remaining));
48 ba->capacity += (len - remaining);
49 }
50 memcpy(ba->data+ba->len, buf, len);
51 ba->len += len;
52}
diff --git a/src/bytearray.h b/src/bytearray.h
new file mode 100644
index 0000000..3e67d7e
--- /dev/null
+++ b/src/bytearray.h
@@ -0,0 +1,36 @@
1/*
2 * bytearray.h
3 * header file for simple byte array implementation
4 *
5 * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#ifndef BYTEARRAY_H
22#define BYTEARRAY_H
23#include <stdlib.h>
24#include "common.h"
25
26typedef struct bytearray_t {
27 void *data;
28 size_t len;
29 size_t capacity;
30} bytearray_t;
31
32_PLIST_INTERNAL bytearray_t *byte_array_new();
33_PLIST_INTERNAL void byte_array_free(bytearray_t *ba);
34_PLIST_INTERNAL void byte_array_append(bytearray_t *ba, void *buf, size_t len);
35
36#endif
diff --git a/src/common.h b/src/common.h
new file mode 100644
index 0000000..4f16df7
--- /dev/null
+++ b/src/common.h
@@ -0,0 +1,15 @@
1#ifndef COMMON_H
2#define COMMON_H
3
4#define PLIST_LITTLE_ENDIAN 0
5#define PLIST_BIG_ENDIAN 1
6
7#if defined(__GNUC__) && (__GNUC__ >= 4) && !defined(__CYGWIN__)
8# define _PLIST_INTERNAL __attribute__((visibility("hidden")))
9#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x550)
10# define _PLIST_INTERNAL __hidden
11#else /* not gcc >= 4 and not Sun Studio >= 8 */
12# define _PLIST_INTERNAL
13#endif /* GNUC >= 4 */
14
15#endif
diff --git a/src/hashtable.c b/src/hashtable.c
new file mode 100644
index 0000000..9716c25
--- /dev/null
+++ b/src/hashtable.c
@@ -0,0 +1,107 @@
1/*
2 * hashtable.c
3 * really simple hash table implementation
4 *
5 * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#include "hashtable.h"
22
23hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func)
24{
25 hashtable_t* ht = (hashtable_t*)malloc(sizeof(hashtable_t));
26 int i;
27 for (i = 0; i < 256; i++) {
28 ht->entries[i] = NULL;
29 }
30 ht->count = 0;
31 ht->hash_func = hash_func;
32 ht->compare_func = compare_func;
33 return ht;
34}
35
36void hash_table_destroy(hashtable_t *ht)
37{
38 if (!ht) return;
39
40 int i = 0;
41 for (i = 0; i < 256; i++) {
42 if (ht->entries[i]) {
43 hashentry_t* e = ht->entries[i];
44 while (e) {
45 free(e->value);
46 hashentry_t* old = e;
47 e = e->next;
48 free(old);
49 }
50 }
51 }
52 free(ht);
53}
54
55void hash_table_insert(hashtable_t* ht, void *key, void *value)
56{
57 if (!ht || !key) return;
58 int i;
59
60 unsigned int hash = ht->hash_func(key);
61
62 int idx0 = hash & 0xFF;
63
64 // get the idx0 list
65 hashentry_t* e = ht->entries[idx0];
66 while (e) {
67 if (ht->compare_func(e->key, key)) {
68 // element already present. replace value.
69 e->value = value;
70 return;
71 }
72 e = e->next;
73 }
74
75 // if we get here, the element is not yet in the list.
76
77 // make a new entry.
78 hashentry_t* entry = (hashentry_t*)malloc(sizeof(hashentry_t));
79 entry->key = key;
80 entry->value = value;
81 if (!ht->entries[idx0]) {
82 // first entry
83 entry->next = NULL;
84 } else {
85 // add to list
86 entry->next = ht->entries[idx0];
87 }
88 ht->entries[idx0] = entry;
89 ht->count++;
90}
91
92void* hash_table_lookup(hashtable_t* ht, void *key)
93{
94 if (!ht || !key) return NULL;
95 unsigned int hash = ht->hash_func(key);
96
97 int idx0 = hash & 0xFF;
98
99 hashentry_t* e = ht->entries[idx0];
100 while (e) {
101 if (ht->compare_func(e->key, key)) {
102 return e->value;
103 }
104 e = e->next;
105 }
106 return NULL;
107}
diff --git a/src/hashtable.h b/src/hashtable.h
new file mode 100644
index 0000000..8c72c82
--- /dev/null
+++ b/src/hashtable.h
@@ -0,0 +1,48 @@
1/*
2 * hashtable.h
3 * header file for really simple hash table implementation
4 *
5 * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#ifndef HASHTABLE_H
22#define HASHTABLE_H
23#include <stdlib.h>
24#include "common.h"
25
26typedef struct hashentry_t {
27 void *key;
28 void *value;
29 void *next;
30} hashentry_t;
31
32typedef unsigned int(*hash_func_t)(const void* key);
33typedef int (*compare_func_t)(const void *a, const void *b);
34
35typedef struct hashtable_t {
36 hashentry_t *entries[256];
37 size_t count;
38 hash_func_t hash_func;
39 compare_func_t compare_func;
40} hashtable_t;
41
42_PLIST_INTERNAL hashtable_t* hash_table_new(hash_func_t hash_func, compare_func_t compare_func);
43_PLIST_INTERNAL void hash_table_destroy(hashtable_t *ht);
44
45_PLIST_INTERNAL void hash_table_insert(hashtable_t* ht, void *key, void *value);
46_PLIST_INTERNAL void* hash_table_lookup(hashtable_t* ht, void *key);
47
48#endif
diff --git a/src/plist.c b/src/plist.c
index 7028d81..6ee54cd 100644
--- a/src/plist.c
+++ b/src/plist.c
@@ -26,16 +26,19 @@
26#include <stdlib.h> 26#include <stdlib.h>
27#include <stdio.h> 27#include <stdio.h>
28 28
29#include <node.h>
30#include <node_iterator.h>
31
29plist_t plist_new_node(plist_data_t data) 32plist_t plist_new_node(plist_data_t data)
30{ 33{
31 return (plist_t) g_node_new(data); 34 return (plist_t) node_create(NULL, data);
32} 35}
33 36
34plist_data_t plist_get_data(const plist_t node) 37plist_data_t plist_get_data(const plist_t node)
35{ 38{
36 if (!node) 39 if (!node)
37 return NULL; 40 return NULL;
38 return ((GNode *) node)->data; 41 return ((node_t*)node)->data;
39} 42}
40 43
41plist_data_t plist_new_plist_data(void) 44plist_data_t plist_new_plist_data(void)
@@ -64,15 +67,22 @@ static void plist_free_data(plist_data_t data)
64 } 67 }
65} 68}
66 69
67static void plist_free_node(GNode * node, gpointer none) 70static void plist_free_node(node_t* node)
68{ 71{
69 plist_data_t data = NULL; 72 plist_data_t data = NULL;
70 g_node_unlink(node); 73 node_detach(node->parent, node);
71 data = plist_get_data(node); 74 data = plist_get_data(node);
72 plist_free_data(data); 75 plist_free_data(data);
73 node->data = NULL; 76 node->data = NULL;
74 g_node_children_foreach(node, G_TRAVERSE_ALL, plist_free_node, NULL); 77
75 g_node_destroy(node); 78 node_iterator_t *ni = node_iterator_create(node->children);
79 node_t *ch;
80 while ((ch = node_iterator_next(ni))) {
81 plist_free_node(ch);
82 }
83 node_iterator_destroy(ni);
84
85 node_destroy(node);
76} 86}
77 87
78plist_t plist_new_dict(void) 88plist_t plist_new_dict(void)
@@ -151,7 +161,7 @@ plist_t plist_new_date(int32_t sec, int32_t usec)
151 data->type = PLIST_DATE; 161 data->type = PLIST_DATE;
152 data->timeval.tv_sec = sec; 162 data->timeval.tv_sec = sec;
153 data->timeval.tv_usec = usec; 163 data->timeval.tv_usec = usec;
154 data->length = sizeof(GTimeVal); 164 data->length = sizeof(struct timeval);
155 return plist_new_node(data); 165 return plist_new_node(data);
156} 166}
157 167
@@ -159,11 +169,11 @@ void plist_free(plist_t plist)
159{ 169{
160 if (plist) 170 if (plist)
161 { 171 {
162 plist_free_node(plist, NULL); 172 plist_free_node(plist);
163 } 173 }
164} 174}
165 175
166static void plist_copy_node(GNode * node, gpointer parent_node_ptr) 176static void plist_copy_node(node_t *node, void *parent_node_ptr)
167{ 177{
168 plist_type node_type = PLIST_NONE; 178 plist_type node_type = PLIST_NONE;
169 plist_t newnode = NULL; 179 plist_t newnode = NULL;
@@ -195,14 +205,19 @@ static void plist_copy_node(GNode * node, gpointer parent_node_ptr)
195 205
196 if (*(plist_t*)parent_node_ptr) 206 if (*(plist_t*)parent_node_ptr)
197 { 207 {
198 g_node_append(*(plist_t*)parent_node_ptr, newnode); 208 node_attach(*(plist_t*)parent_node_ptr, newnode);
199 } 209 }
200 else 210 else
201 { 211 {
202 *(plist_t*)parent_node_ptr = newnode; 212 *(plist_t*)parent_node_ptr = newnode;
203 } 213 }
204 214
205 g_node_children_foreach(node, G_TRAVERSE_ALL, plist_copy_node, &newnode); 215 node_iterator_t *ni = node_iterator_create(node->children);
216 node_t *ch;
217 while ((ch = node_iterator_next(ni))) {
218 plist_copy_node(ch, &newnode);
219 }
220 node_iterator_destroy(ni);
206} 221}
207 222
208plist_t plist_copy(plist_t node) 223plist_t plist_copy(plist_t node)
@@ -217,7 +232,7 @@ uint32_t plist_array_get_size(plist_t node)
217 uint32_t ret = 0; 232 uint32_t ret = 0;
218 if (node && PLIST_ARRAY == plist_get_node_type(node)) 233 if (node && PLIST_ARRAY == plist_get_node_type(node))
219 { 234 {
220 ret = g_node_n_children(node); 235 ret = node_n_children(node);
221 } 236 }
222 return ret; 237 return ret;
223} 238}
@@ -227,7 +242,7 @@ plist_t plist_array_get_item(plist_t node, uint32_t n)
227 plist_t ret = NULL; 242 plist_t ret = NULL;
228 if (node && PLIST_ARRAY == plist_get_node_type(node)) 243 if (node && PLIST_ARRAY == plist_get_node_type(node))
229 { 244 {
230 ret = (plist_t)g_node_nth_child(node, n); 245 ret = (plist_t)node_nth_child(node, n);
231 } 246 }
232 return ret; 247 return ret;
233} 248}
@@ -237,7 +252,7 @@ uint32_t plist_array_get_item_index(plist_t node)
237 plist_t father = plist_get_parent(node); 252 plist_t father = plist_get_parent(node);
238 if (PLIST_ARRAY == plist_get_node_type(father)) 253 if (PLIST_ARRAY == plist_get_node_type(father))
239 { 254 {
240 return g_node_child_position(father, node); 255 return node_child_position(father, node);
241 } 256 }
242 return 0; 257 return 0;
243} 258}
@@ -249,7 +264,7 @@ void plist_array_set_item(plist_t node, plist_t item, uint32_t n)
249 plist_t old_item = plist_array_get_item(node, n); 264 plist_t old_item = plist_array_get_item(node, n);
250 if (old_item) 265 if (old_item)
251 { 266 {
252 plist_free_node(old_item, NULL); 267 plist_free_node(old_item);
253 old_item = NULL; 268 old_item = NULL;
254 plist_copy_node(item, &old_item); 269 plist_copy_node(item, &old_item);
255 } 270 }
@@ -261,7 +276,7 @@ void plist_array_append_item(plist_t node, plist_t item)
261{ 276{
262 if (node && PLIST_ARRAY == plist_get_node_type(node)) 277 if (node && PLIST_ARRAY == plist_get_node_type(node))
263 { 278 {
264 g_node_append(node, item); 279 node_attach(node, item);
265 } 280 }
266 return; 281 return;
267} 282}
@@ -270,7 +285,7 @@ void plist_array_insert_item(plist_t node, plist_t item, uint32_t n)
270{ 285{
271 if (node && PLIST_ARRAY == plist_get_node_type(node)) 286 if (node && PLIST_ARRAY == plist_get_node_type(node))
272 { 287 {
273 g_node_insert(node, n, item); 288 node_insert(node, n, item);
274 } 289 }
275 return; 290 return;
276} 291}
@@ -293,7 +308,7 @@ uint32_t plist_dict_get_size(plist_t node)
293 uint32_t ret = 0; 308 uint32_t ret = 0;
294 if (node && PLIST_DICT == plist_get_node_type(node)) 309 if (node && PLIST_DICT == plist_get_node_type(node))
295 { 310 {
296 ret = g_node_n_children(node) / 2; 311 ret = node_n_children(node) / 2;
297 } 312 }
298 return ret; 313 return ret;
299} 314}
@@ -321,17 +336,17 @@ void plist_dict_next_item(plist_t node, plist_dict_iter iter, char **key, plist_
321 *val = NULL; 336 *val = NULL;
322 } 337 }
323 338
324 if (node && PLIST_DICT == plist_get_node_type(node) && *iter_int < g_node_n_children(node)) 339 if (node && PLIST_DICT == plist_get_node_type(node) && *iter_int < node_n_children(node))
325 { 340 {
326 341
327 if (key) 342 if (key)
328 { 343 {
329 plist_get_key_val((plist_t)g_node_nth_child(node, *iter_int), key); 344 plist_get_key_val((plist_t)node_nth_child(node, *iter_int), key);
330 } 345 }
331 346
332 if (val) 347 if (val)
333 { 348 {
334 *val = (plist_t) g_node_nth_child(node, *iter_int + 1); 349 *val = (plist_t) node_nth_child(node, *iter_int + 1);
335 } 350 }
336 351
337 *iter_int += 2; 352 *iter_int += 2;
@@ -344,7 +359,7 @@ void plist_dict_get_item_key(plist_t node, char **key)
344 plist_t father = plist_get_parent(node); 359 plist_t father = plist_get_parent(node);
345 if (PLIST_DICT == plist_get_node_type(father)) 360 if (PLIST_DICT == plist_get_node_type(father))
346 { 361 {
347 plist_get_key_val( (plist_t) g_node_prev_sibling(node), key); 362 plist_get_key_val( (plist_t) node_prev_sibling(node), key);
348 } 363 }
349} 364}
350 365
@@ -356,9 +371,9 @@ plist_t plist_dict_get_item(plist_t node, const char* key)
356 { 371 {
357 372
358 plist_t current = NULL; 373 plist_t current = NULL;
359 for (current = (plist_t)g_node_first_child(node); 374 for (current = (plist_t)node_first_child(node);
360 current; 375 current;
361 current = (plist_t)g_node_next_sibling(g_node_next_sibling(current))) 376 current = (plist_t)node_next_sibling(node_next_sibling(current)))
362 { 377 {
363 378
364 plist_data_t data = plist_get_data(current); 379 plist_data_t data = plist_get_data(current);
@@ -366,7 +381,7 @@ plist_t plist_dict_get_item(plist_t node, const char* key)
366 381
367 if (data && !strcmp(key, data->strval)) 382 if (data && !strcmp(key, data->strval))
368 { 383 {
369 ret = (plist_t)g_node_next_sibling(current); 384 ret = (plist_t)node_next_sibling(current);
370 break; 385 break;
371 } 386 }
372 } 387 }
@@ -381,7 +396,7 @@ void plist_dict_set_item(plist_t node, const char* key, plist_t item)
381 plist_t old_item = plist_dict_get_item(node, key); 396 plist_t old_item = plist_dict_get_item(node, key);
382 if (old_item) 397 if (old_item)
383 { 398 {
384 plist_free_node(old_item, NULL); 399 plist_free_node(old_item);
385 old_item = NULL; 400 old_item = NULL;
386 plist_copy_node(item, &old_item); 401 plist_copy_node(item, &old_item);
387 } 402 }
@@ -393,8 +408,8 @@ void plist_dict_insert_item(plist_t node, const char* key, plist_t item)
393{ 408{
394 if (node && PLIST_DICT == plist_get_node_type(node)) 409 if (node && PLIST_DICT == plist_get_node_type(node))
395 { 410 {
396 g_node_append(node, plist_new_key(key)); 411 node_attach(node, plist_new_key(key));
397 g_node_append(node, item); 412 node_attach(node, item);
398 } 413 }
399 return; 414 return;
400} 415}
@@ -406,7 +421,7 @@ void plist_dict_remove_item(plist_t node, const char* key)
406 plist_t old_item = plist_dict_get_item(node, key); 421 plist_t old_item = plist_dict_get_item(node, key);
407 if (old_item) 422 if (old_item)
408 { 423 {
409 plist_t key_node = g_node_prev_sibling(old_item); 424 plist_t key_node = node_prev_sibling(old_item);
410 plist_free(key_node); 425 plist_free(key_node);
411 plist_free(old_item); 426 plist_free(old_item);
412 } 427 }
@@ -482,8 +497,8 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu
482 break; 497 break;
483 case PLIST_DATE: 498 case PLIST_DATE:
484 //exception : here we use memory on the stack since it is just a temporary buffer 499 //exception : here we use memory on the stack since it is just a temporary buffer
485 ((GTimeVal *) value)->tv_sec = data->timeval.tv_sec; 500 ((struct timeval*) value)->tv_sec = data->timeval.tv_sec;
486 ((GTimeVal *) value)->tv_usec = data->timeval.tv_usec; 501 ((struct timeval*) value)->tv_usec = data->timeval.tv_usec;
487 break; 502 break;
488 case PLIST_ARRAY: 503 case PLIST_ARRAY:
489 case PLIST_DICT: 504 case PLIST_DICT:
@@ -494,7 +509,7 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu
494 509
495plist_t plist_get_parent(plist_t node) 510plist_t plist_get_parent(plist_t node)
496{ 511{
497 return node ? (plist_t) ((GNode *) node)->parent : NULL; 512 return node ? (plist_t) ((node_t*) node)->parent : NULL;
498} 513}
499 514
500plist_type plist_get_node_type(plist_t node) 515plist_type plist_get_node_type(plist_t node)
@@ -564,15 +579,15 @@ void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec)
564{ 579{
565 plist_type type = plist_get_node_type(node); 580 plist_type type = plist_get_node_type(node);
566 uint64_t length = 0; 581 uint64_t length = 0;
567 GTimeVal val = { 0, 0 }; 582 struct timeval val = { 0, 0 };
568 if (PLIST_DATE == type) 583 if (PLIST_DATE == type)
569 plist_get_type_and_value(node, &type, (void *) &val, &length); 584 plist_get_type_and_value(node, &type, (void *) &val, &length);
570 assert(length == sizeof(GTimeVal)); 585 assert(length == sizeof(struct timeval));
571 *sec = val.tv_sec; 586 *sec = val.tv_sec;
572 *usec = val.tv_usec; 587 *usec = val.tv_usec;
573} 588}
574 589
575gboolean plist_data_compare(gconstpointer a, gconstpointer b) 590int plist_data_compare(const void *a, const void *b)
576{ 591{
577 plist_data_t val_a = NULL; 592 plist_data_t val_a = NULL;
578 plist_data_t val_b = NULL; 593 plist_data_t val_b = NULL;
@@ -580,7 +595,7 @@ gboolean plist_data_compare(gconstpointer a, gconstpointer b)
580 if (!a || !b) 595 if (!a || !b)
581 return FALSE; 596 return FALSE;
582 597
583 if (!((GNode *) a)->data || !((GNode *) b)->data) 598 if (!((node_t*) a)->data || !((node_t*) b)->data)
584 return FALSE; 599 return FALSE;
585 600
586 val_a = plist_get_data((plist_t) a); 601 val_a = plist_get_data((plist_t) a);
@@ -620,7 +635,7 @@ gboolean plist_data_compare(gconstpointer a, gconstpointer b)
620 return FALSE; 635 return FALSE;
621 break; 636 break;
622 case PLIST_DATE: 637 case PLIST_DATE:
623 if (!memcmp(&(val_a->timeval), &(val_b->timeval), sizeof(GTimeVal))) 638 if (!memcmp(&(val_a->timeval), &(val_b->timeval), sizeof(struct timeval)))
624 return TRUE; 639 return TRUE;
625 else 640 else
626 return FALSE; 641 return FALSE;
@@ -681,8 +696,8 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val
681 memcpy(data->buff, value, length); 696 memcpy(data->buff, value, length);
682 break; 697 break;
683 case PLIST_DATE: 698 case PLIST_DATE:
684 data->timeval.tv_sec = ((GTimeVal *) value)->tv_sec; 699 data->timeval.tv_sec = ((struct timeval*) value)->tv_sec;
685 data->timeval.tv_usec = ((GTimeVal *) value)->tv_usec; 700 data->timeval.tv_usec = ((struct timeval*) value)->tv_usec;
686 break; 701 break;
687 case PLIST_ARRAY: 702 case PLIST_ARRAY:
688 case PLIST_DICT: 703 case PLIST_DICT:
@@ -693,7 +708,7 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val
693 708
694void plist_set_type(plist_t node, plist_type type) 709void plist_set_type(plist_t node, plist_type type)
695{ 710{
696 if ( g_node_n_children(node) == 0 ) 711 if ( node_n_children(node) == 0 )
697 { 712 {
698 plist_data_t data = plist_get_data(node); 713 plist_data_t data = plist_get_data(node);
699 plist_free_data( data ); 714 plist_free_data( data );
@@ -711,7 +726,7 @@ void plist_set_type(plist_t node, plist_type type)
711 data->length = sizeof(double); 726 data->length = sizeof(double);
712 break; 727 break;
713 case PLIST_DATE: 728 case PLIST_DATE:
714 data->length = sizeof(GTimeVal); 729 data->length = sizeof(struct timeval);
715 break; 730 break;
716 default: 731 default:
717 data->length = 0; 732 data->length = 0;
@@ -752,7 +767,7 @@ void plist_set_data_val(plist_t node, const char *val, uint64_t length)
752 767
753void plist_set_date_val(plist_t node, int32_t sec, int32_t usec) 768void plist_set_date_val(plist_t node, int32_t sec, int32_t usec)
754{ 769{
755 GTimeVal val = { sec, usec }; 770 struct timeval val = { sec, usec };
756 plist_set_element_val(node, PLIST_DATE, &val, sizeof(GTimeVal)); 771 plist_set_element_val(node, PLIST_DATE, &val, sizeof(struct timeval));
757} 772}
758 773
diff --git a/src/plist.h b/src/plist.h
index 12578af..036fd42 100644
--- a/src/plist.h
+++ b/src/plist.h
@@ -23,11 +23,10 @@
23#define PLIST_H 23#define PLIST_H
24 24
25#include "plist/plist.h" 25#include "plist/plist.h"
26 26#include "common.h"
27 27
28#include <sys/types.h> 28#include <sys/types.h>
29#include <sys/stat.h> 29#include <sys/stat.h>
30#include <glib.h>
31 30
32#ifdef _MSC_VER 31#ifdef _MSC_VER
33#pragma warning(disable:4996) 32#pragma warning(disable:4996)
@@ -44,7 +43,7 @@ struct plist_data_s
44 double realval; 43 double realval;
45 char *strval; 44 char *strval;
46 uint8_t *buff; 45 uint8_t *buff;
47 GTimeVal timeval; 46 struct timeval timeval;
48 }; 47 };
49 uint64_t length; 48 uint64_t length;
50 plist_type type; 49 plist_type type;
@@ -52,10 +51,10 @@ struct plist_data_s
52 51
53typedef struct plist_data_s *plist_data_t; 52typedef struct plist_data_s *plist_data_t;
54 53
55G_GNUC_INTERNAL plist_t plist_new_node(plist_data_t data); 54_PLIST_INTERNAL plist_t plist_new_node(plist_data_t data);
56G_GNUC_INTERNAL plist_data_t plist_get_data(const plist_t node); 55_PLIST_INTERNAL plist_data_t plist_get_data(const plist_t node);
57G_GNUC_INTERNAL plist_data_t plist_new_plist_data(void); 56_PLIST_INTERNAL plist_data_t plist_new_plist_data(void);
58G_GNUC_INTERNAL gboolean plist_data_compare(gconstpointer a, gconstpointer b); 57_PLIST_INTERNAL int plist_data_compare(const void *a, const void *b);
59 58
60 59
61#endif 60#endif
diff --git a/src/ptrarray.c b/src/ptrarray.c
new file mode 100644
index 0000000..8567752
--- /dev/null
+++ b/src/ptrarray.c
@@ -0,0 +1,61 @@
1/*
2 * ptrarray.c
3 * simple pointer array implementation
4 *
5 * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#include "ptrarray.h"
22
23ptrarray_t *ptr_array_new(int capacity)
24{
25 ptrarray_t *pa = (ptrarray_t*)malloc(sizeof(ptrarray_t));
26 pa->pdata = (void**)malloc(sizeof(void*) * capacity);
27 pa->capacity = capacity;
28 pa->capacity_step = (capacity > 64) ? 64 : capacity;
29 pa->len = 0;
30 return pa;
31}
32
33void ptr_array_free(ptrarray_t *pa)
34{
35 if (!pa) return;
36 if (pa->pdata) {
37 free(pa->pdata);
38 }
39 free(pa);
40}
41
42void ptr_array_add(ptrarray_t *pa, void *data)
43{
44 if (!pa || !pa->pdata || !data) return;
45 size_t remaining = pa->capacity-pa->len;
46 if (remaining == 0) {
47 pa->pdata = realloc(pa->pdata, sizeof(void*) * (pa->capacity + pa->capacity_step));
48 pa->capacity += pa->capacity_step;
49 }
50 pa->pdata[pa->len] = data;
51 pa->len++;
52}
53
54void* ptr_array_index(ptrarray_t *pa, size_t index)
55{
56 if (!pa) return NULL;
57 if (index >= pa->len) {
58 return NULL;
59 }
60 return pa->pdata[index];
61}
diff --git a/src/ptrarray.h b/src/ptrarray.h
new file mode 100644
index 0000000..84f9ef0
--- /dev/null
+++ b/src/ptrarray.h
@@ -0,0 +1,37 @@
1/*
2 * ptrarray.h
3 * header file for simple pointer array implementation
4 *
5 * Copyright (c) 2011 Nikias Bassen, All Rights Reserved.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21#ifndef PTRARRAY_H
22#define PTRARRAY_H
23#include <stdlib.h>
24#include "common.h"
25
26typedef struct ptrarray_t {
27 void **pdata;
28 size_t len;
29 size_t capacity;
30 size_t capacity_step;
31} ptrarray_t;
32
33_PLIST_INTERNAL ptrarray_t *ptr_array_new(int capacity);
34_PLIST_INTERNAL void ptr_array_free(ptrarray_t *pa);
35_PLIST_INTERNAL void ptr_array_add(ptrarray_t *pa, void *data);
36_PLIST_INTERNAL void* ptr_array_index(ptrarray_t *pa, size_t index);
37#endif
diff --git a/src/xplist.c b/src/xplist.c
index 1319f56..899cc81 100644
--- a/src/xplist.c
+++ b/src/xplist.c
@@ -24,6 +24,7 @@
24#include <assert.h> 24#include <assert.h>
25#include <stdlib.h> 25#include <stdlib.h>
26#include <stdio.h> 26#include <stdio.h>
27#include <time.h>
27 28
28#include <inttypes.h> 29#include <inttypes.h>
29#include <locale.h> 30#include <locale.h>
@@ -31,7 +32,12 @@
31#include <libxml/parser.h> 32#include <libxml/parser.h>
32#include <libxml/tree.h> 33#include <libxml/tree.h>
33 34
35#include <node.h>
36#include <node_list.h>
37#include <node_iterator.h>
38
34#include "plist.h" 39#include "plist.h"
40#include "base64.h"
35 41
36#define XPLIST_TEXT BAD_CAST("text") 42#define XPLIST_TEXT BAD_CAST("text")
37#define XPLIST_KEY BAD_CAST("key") 43#define XPLIST_KEY BAD_CAST("key")
@@ -61,18 +67,22 @@ static const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
61 * 67 *
62 * @return The formatted string. 68 * @return The formatted string.
63 */ 69 */
64static gchar *format_string(const char *buf, int cols, int depth) 70static char *format_string(const char *buf, size_t len, int cols, int depth)
65{ 71{
72 if (!buf || !(len > 0)) return NULL;
66 int colw = depth + cols + 1; 73 int colw = depth + cols + 1;
67 int len = strlen(buf);
68 int nlines = len / cols + 1; 74 int nlines = len / cols + 1;
69 gchar *new_buf = (gchar *) g_malloc0(nlines * colw + depth + 1); 75 char *new_buf = NULL;
70 int i = 0; 76 int i = 0;
71 int j = 0; 77 int j = 0;
72 78
73 assert(cols >= 0); 79 assert(cols >= 0);
74 assert(depth >= 0); 80 assert(depth >= 0);
75 81
82 new_buf = (char*) malloc(nlines * colw + depth + 1);
83 assert(new_buf != 0);
84 memset(new_buf, 0, nlines * colw + depth + 1);
85
76 // Inserts new lines and tabs at appropriate locations 86 // Inserts new lines and tabs at appropriate locations
77 for (i = 0; i < nlines; i++) 87 for (i = 0; i < nlines; i++)
78 { 88 {
@@ -116,7 +126,7 @@ static xmlDocPtr new_xml_plist(void)
116 return plist_xml; 126 return plist_xml;
117} 127}
118 128
119static void node_to_xml(GNode * node, gpointer xml_struct) 129static void node_to_xml(node_t* node, void *xml_struct)
120{ 130{
121 struct xml_node *xstruct = NULL; 131 struct xml_node *xstruct = NULL;
122 plist_data_t node_data = NULL; 132 plist_data_t node_data = NULL;
@@ -125,10 +135,10 @@ static void node_to_xml(GNode * node, gpointer xml_struct)
125 char isStruct = FALSE; 135 char isStruct = FALSE;
126 136
127 const xmlChar *tag = NULL; 137 const xmlChar *tag = NULL;
128 gchar *val = NULL; 138 char *val = NULL;
129 139
130 //for base64 140 //for base64
131 gchar *valtmp = NULL; 141 char *valtmp = NULL;
132 142
133 uint32_t i = 0; 143 uint32_t i = 0;
134 144
@@ -151,31 +161,32 @@ static void node_to_xml(GNode * node, gpointer xml_struct)
151 161
152 case PLIST_UINT: 162 case PLIST_UINT:
153 tag = XPLIST_INT; 163 tag = XPLIST_INT;
154 val = g_strdup_printf("%"PRIu64, node_data->intval); 164 (void)asprintf(&val, "%"PRIu64, node_data->intval);
155 break; 165 break;
156 166
157 case PLIST_REAL: 167 case PLIST_REAL:
158 tag = XPLIST_REAL; 168 tag = XPLIST_REAL;
159 val = g_strdup_printf("%f", node_data->realval); 169 (void)asprintf(&val, "%f", node_data->realval);
160 break; 170 break;
161 171
162 case PLIST_STRING: 172 case PLIST_STRING:
163 tag = XPLIST_STRING; 173 tag = XPLIST_STRING;
164 val = g_strdup(node_data->strval); 174 val = strdup(node_data->strval);
165 break; 175 break;
166 176
167 case PLIST_KEY: 177 case PLIST_KEY:
168 tag = XPLIST_KEY; 178 tag = XPLIST_KEY;
169 val = g_strdup((gchar *) node_data->strval); 179 val = strdup((char*) node_data->strval);
170 break; 180 break;
171 181
172 case PLIST_DATA: 182 case PLIST_DATA:
173 tag = XPLIST_DATA; 183 tag = XPLIST_DATA;
174 if (node_data->length) 184 if (node_data->length)
175 { 185 {
176 valtmp = g_base64_encode(node_data->buff, node_data->length); 186 size_t len = node_data->length;
177 val = format_string(valtmp, 68, xstruct->depth); 187 valtmp = base64encode(node_data->buff, &len);
178 g_free(valtmp); 188 val = format_string(valtmp, len, 68, xstruct->depth);
189 free(valtmp);
179 } 190 }
180 break; 191 break;
181 case PLIST_ARRAY: 192 case PLIST_ARRAY:
@@ -188,7 +199,18 @@ static void node_to_xml(GNode * node, gpointer xml_struct)
188 break; 199 break;
189 case PLIST_DATE: 200 case PLIST_DATE:
190 tag = XPLIST_DATE; 201 tag = XPLIST_DATE;
191 val = g_time_val_to_iso8601(&node_data->timeval); 202 {
203 time_t time = (time_t)node_data->timeval.tv_sec;
204 struct tm *btime = localtime(&time);
205 if (btime) {
206 val = (char*)malloc(24);
207 memset(val, 0, 24);
208 if (strftime(val, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) {
209 free (val);
210 val = NULL;
211 }
212 }
213 }
192 break; 214 break;
193 default: 215 default:
194 break; 216 break;
@@ -205,7 +227,9 @@ static void node_to_xml(GNode * node, gpointer xml_struct)
205 } else 227 } else
206 child_node = xmlNewChild(xstruct->xml, NULL, tag, BAD_CAST(val)); 228 child_node = xmlNewChild(xstruct->xml, NULL, tag, BAD_CAST(val));
207 xmlNodeAddContent(xstruct->xml, BAD_CAST("\n")); 229 xmlNodeAddContent(xstruct->xml, BAD_CAST("\n"));
208 g_free(val); 230 if (val) {
231 free(val);
232 }
209 233
210 //add return for structured types 234 //add return for structured types
211 if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) 235 if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT)
@@ -214,7 +238,12 @@ static void node_to_xml(GNode * node, gpointer xml_struct)
214 if (isStruct) 238 if (isStruct)
215 { 239 {
216 struct xml_node child = { child_node, xstruct->depth + 1 }; 240 struct xml_node child = { child_node, xstruct->depth + 1 };
217 g_node_children_foreach(node, G_TRAVERSE_ALL, node_to_xml, &child); 241 node_iterator_t *ni = node_iterator_create(node->children);
242 node_t *ch;
243 while ((ch = node_iterator_next(ni))) {
244 node_to_xml(ch, &child);
245 }
246 node_iterator_destroy(ni);
218 } 247 }
219 //fix indent for structured types 248 //fix indent for structured types
220 if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) 249 if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT)
@@ -236,7 +265,7 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node)
236 plist_t subnode = NULL; 265 plist_t subnode = NULL;
237 266
238 //for string 267 //for string
239 glong len = 0; 268 long len = 0;
240 int type = 0; 269 int type = 0;
241 270
242 if (!xml_node) 271 if (!xml_node)
@@ -253,7 +282,7 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node)
253 data = plist_new_plist_data(); 282 data = plist_new_plist_data();
254 subnode = plist_new_node(data); 283 subnode = plist_new_node(data);
255 if (*plist_node) 284 if (*plist_node)
256 g_node_append(*plist_node, subnode); 285 node_attach(*plist_node, subnode);
257 else 286 else
258 *plist_node = subnode; 287 *plist_node = subnode;
259 288
@@ -276,7 +305,7 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node)
276 if (!xmlStrcmp(node->name, XPLIST_INT)) 305 if (!xmlStrcmp(node->name, XPLIST_INT))
277 { 306 {
278 xmlChar *strval = xmlNodeGetContent(node); 307 xmlChar *strval = xmlNodeGetContent(node);
279 data->intval = g_ascii_strtoull((char *) strval, NULL, 0); 308 data->intval = strtoull((char*)strval, NULL, 0);
280 data->type = PLIST_UINT; 309 data->type = PLIST_UINT;
281 data->length = 8; 310 data->length = 8;
282 xmlFree(strval); 311 xmlFree(strval);
@@ -296,9 +325,17 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node)
296 if (!xmlStrcmp(node->name, XPLIST_DATE)) 325 if (!xmlStrcmp(node->name, XPLIST_DATE))
297 { 326 {
298 xmlChar *strval = xmlNodeGetContent(node); 327 xmlChar *strval = xmlNodeGetContent(node);
299 g_time_val_from_iso8601((char *) strval, &data->timeval); 328 time_t time = 0;
329 if (strlen(strval) >= 11) {
330 struct tm btime;
331 memset(&btime, 0, sizeof(struct tm));
332 strptime((char*)strval, "%Y-%m-%dT%H:%M:%SZ", &btime);
333 time = mktime(&btime);
334 }
335 data->timeval.tv_sec = (long)time;
336 data->timeval.tv_usec = 0;
300 data->type = PLIST_DATE; 337 data->type = PLIST_DATE;
301 data->length = sizeof(GTimeVal); 338 data->length = sizeof(struct timeval);
302 xmlFree(strval); 339 xmlFree(strval);
303 continue; 340 continue;
304 } 341 }
@@ -332,11 +369,11 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node)
332 if (!xmlStrcmp(node->name, XPLIST_DATA)) 369 if (!xmlStrcmp(node->name, XPLIST_DATA))
333 { 370 {
334 xmlChar *strval = xmlNodeGetContent(node); 371 xmlChar *strval = xmlNodeGetContent(node);
335 gsize size = 0; 372 size_t size = 0;
336 guchar *dec = g_base64_decode((char *) strval, &size); 373 unsigned char *dec = base64decode((char*)strval, &size);
337 data->buff = (uint8_t *) malloc(size * sizeof(uint8_t)); 374 data->buff = (uint8_t *) malloc(size * sizeof(uint8_t));
338 memcpy(data->buff, dec, size * sizeof(uint8_t)); 375 memcpy(data->buff, dec, size * sizeof(uint8_t));
339 g_free(dec); 376 free(dec);
340 data->length = size; 377 data->length = size;
341 data->type = PLIST_DATA; 378 data->type = PLIST_DATA;
342 xmlFree(strval); 379 xmlFree(strval);