summaryrefslogtreecommitdiffstats
path: root/src/bplist.c
diff options
context:
space:
mode:
authorGravatar Jonathan Beck2009-10-28 18:31:34 +0100
committerGravatar Jonathan Beck2009-10-28 18:31:34 +0100
commit6710f4bfb980dd0fe6e75e4d6cba75532cde30e8 (patch)
tree6429eb306d3d464ebbcc0de558559b636d8058c2 /src/bplist.c
parentfed2573566c2da1c5489260069a99ae9d2abf255 (diff)
downloadlibplist-6710f4bfb980dd0fe6e75e4d6cba75532cde30e8.tar.gz
libplist-6710f4bfb980dd0fe6e75e4d6cba75532cde30e8.tar.bz2
Format sources to ANSI style using AStyle (astyle --style=ansi).
Diffstat (limited to 'src/bplist.c')
-rw-r--r--src/bplist.c1445
1 files changed, 741 insertions, 704 deletions
diff --git a/src/bplist.c b/src/bplist.c
index 6e3007a..d37ed7a 100644
--- a/src/bplist.c
+++ b/src/bplist.c
@@ -8,15 +8,15 @@
8 * modify it under the terms of the GNU Lesser General Public 8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either 9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version. 10 * version 2.1 of the License, or (at your option) any later version.
11 * 11 *
12 * This library is distributed in the hope that it will be useful, 12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details. 15 * Lesser General Public License for more details.
16 * 16 *
17 * You should have received a copy of the GNU Lesser General Public 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 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 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */ 20 */
21 21
22 22
@@ -44,46 +44,48 @@
44#define BPLIST_TRL_ROOTOBJ_IDX 10 44#define BPLIST_TRL_ROOTOBJ_IDX 10
45#define BPLIST_TRL_OFFTAB_IDX 18 45#define BPLIST_TRL_OFFTAB_IDX 18
46 46
47enum { 47enum
48 BPLIST_NULL = 0x00, 48{
49 BPLIST_FALSE = 0x08, 49 BPLIST_NULL = 0x00,
50 BPLIST_TRUE = 0x09, 50 BPLIST_FALSE = 0x08,
51 BPLIST_FILL = 0x0F, /* will be used for length grabbing */ 51 BPLIST_TRUE = 0x09,
52 BPLIST_UINT = 0x10, 52 BPLIST_FILL = 0x0F, /* will be used for length grabbing */
53 BPLIST_REAL = 0x20, 53 BPLIST_UINT = 0x10,
54 BPLIST_DATE = 0x30, 54 BPLIST_REAL = 0x20,
55 BPLIST_DATA = 0x40, 55 BPLIST_DATE = 0x30,
56 BPLIST_STRING = 0x50, 56 BPLIST_DATA = 0x40,
57 BPLIST_UNICODE = 0x60, 57 BPLIST_STRING = 0x50,
58 BPLIST_UID = 0x70, 58 BPLIST_UNICODE = 0x60,
59 BPLIST_ARRAY = 0xA0, 59 BPLIST_UID = 0x70,
60 BPLIST_SET = 0xC0, 60 BPLIST_ARRAY = 0xA0,
61 BPLIST_DICT = 0xD0, 61 BPLIST_SET = 0xC0,
62 BPLIST_MASK = 0xF0 62 BPLIST_DICT = 0xD0,
63 BPLIST_MASK = 0xF0
63}; 64};
64 65
65static void byte_convert(uint8_t * address, size_t size) 66static void byte_convert(uint8_t * address, size_t size)
66{ 67{
67#if G_BYTE_ORDER == G_LITTLE_ENDIAN 68#if G_BYTE_ORDER == G_LITTLE_ENDIAN
68 uint8_t i = 0, j = 0; 69 uint8_t i = 0, j = 0;
69 uint8_t tmp = 0; 70 uint8_t tmp = 0;
70 71
71 for (i = 0; i < (size / 2); i++) { 72 for (i = 0; i < (size / 2); i++)
72 tmp = address[i]; 73 {
73 j = ((size - 1) + 0) - i; 74 tmp = address[i];
74 address[i] = address[j]; 75 j = ((size - 1) + 0) - i;
75 address[j] = tmp; 76 address[i] = address[j];
76 } 77 address[j] = tmp;
78 }
77#endif 79#endif
78} 80}
79 81
80static uint32_t uint24_from_be(char *buff) 82static uint32_t uint24_from_be(char *buff)
81{ 83{
82 uint32_t ret = 0; 84 uint32_t ret = 0;
83 char *tmp = (char *) &ret; 85 char *tmp = (char *) &ret;
84 memcpy(tmp + 1, buff, 3 * sizeof(char)); 86 memcpy(tmp + 1, buff, 3 * sizeof(char));
85 byte_convert(tmp, sizeof(uint32_t)); 87 byte_convert(tmp, sizeof(uint32_t));
86 return ret; 88 return ret;
87} 89}
88 90
89#define UINT_TO_HOST(x, n) \ 91#define UINT_TO_HOST(x, n) \
@@ -106,787 +108,822 @@ static uint32_t uint24_from_be(char *buff)
106 108
107static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object) 109static plist_t parse_uint_node(char *bnode, uint8_t size, char **next_object)
108{ 110{
109 plist_data_t data = plist_new_plist_data(); 111 plist_data_t data = plist_new_plist_data();
110 112
111 size = 1 << size; // make length less misleading 113 size = 1 << size; // make length less misleading
112 switch (size) { 114 switch (size)
113 case sizeof(uint8_t): 115 {
114 case sizeof(uint16_t): 116 case sizeof(uint8_t):
115 case sizeof(uint32_t): 117 case sizeof(uint16_t):
116 case sizeof(uint64_t): 118 case sizeof(uint32_t):
117 memcpy(&data->intval, bnode, size); 119 case sizeof(uint64_t):
118 data->intval = UINT_TO_HOST(&data->intval, size); 120 memcpy(&data->intval, bnode, size);
119 break; 121 data->intval = UINT_TO_HOST(&data->intval, size);
120 default: 122 break;
121 free(data); 123 default:
122 return NULL; 124 free(data);
123 }; 125 return NULL;
124 126 };
125 *next_object = bnode + size; 127
126 data->type = PLIST_UINT; 128 *next_object = bnode + size;
127 data->length = sizeof(uint64_t); 129 data->type = PLIST_UINT;
128 130 data->length = sizeof(uint64_t);
129 return g_node_new(data); 131
132 return g_node_new(data);
130} 133}
131 134
132static plist_t parse_real_node(char *bnode, uint8_t size) 135static plist_t parse_real_node(char *bnode, uint8_t size)
133{ 136{
134 plist_data_t data = plist_new_plist_data(); 137 plist_data_t data = plist_new_plist_data();
135 float floatval = 0.0; 138 float floatval = 0.0;
136 139
137 size = 1 << size; // make length less misleading 140 size = 1 << size; // make length less misleading
138 switch (size) { 141 switch (size)
139 case sizeof(float): 142 {
140 floatval = *(float *) bnode; 143 case sizeof(float):
141 byte_convert((uint8_t *) & floatval, sizeof(float)); 144 floatval = *(float *) bnode;
142 data->realval = floatval; 145 byte_convert((uint8_t *) & floatval, sizeof(float));
143 break; 146 data->realval = floatval;
144 case sizeof(double): 147 break;
145 data->realval = *(double *) bnode; 148 case sizeof(double):
146 byte_convert((uint8_t *) & (data->realval), sizeof(double)); 149 data->realval = *(double *) bnode;
147 break; 150 byte_convert((uint8_t *) & (data->realval), sizeof(double));
148 default: 151 break;
149 free(data); 152 default:
150 return NULL; 153 free(data);
151 } 154 return NULL;
152 data->type = PLIST_REAL; 155 }
153 data->length = sizeof(double); 156 data->type = PLIST_REAL;
154 157 data->length = sizeof(double);
155 return g_node_new(data); 158
159 return g_node_new(data);
156} 160}
157 161
158static plist_t parse_date_node(char *bnode, uint8_t size) 162static plist_t parse_date_node(char *bnode, uint8_t size)
159{ 163{
160 plist_t node = parse_real_node(bnode, size); 164 plist_t node = parse_real_node(bnode, size);
161 plist_data_t data = plist_get_data(node); 165 plist_data_t data = plist_get_data(node);
162 166
163 double time_real = data->realval; 167 double time_real = data->realval;
164 data->timeval.tv_sec = (glong) time_real; 168 data->timeval.tv_sec = (glong) time_real;
165 data->timeval.tv_usec = (time_real - (glong) time_real) * G_USEC_PER_SEC; 169 data->timeval.tv_usec = (time_real - (glong) time_real) * G_USEC_PER_SEC;
166 data->type = PLIST_DATE; 170 data->type = PLIST_DATE;
167 data->length = sizeof(GTimeVal); 171 data->length = sizeof(GTimeVal);
168 172
169 return node; 173 return node;
170} 174}
171 175
172static plist_t parse_string_node(char *bnode, uint64_t size) 176static plist_t parse_string_node(char *bnode, uint64_t size)
173{ 177{
174 plist_data_t data = plist_new_plist_data(); 178 plist_data_t data = plist_new_plist_data();
175 179
176 data->type = PLIST_STRING; 180 data->type = PLIST_STRING;
177 data->strval = (char *) malloc(sizeof(char) * (size + 1)); 181 data->strval = (char *) malloc(sizeof(char) * (size + 1));
178 memcpy(data->strval, bnode, size); 182 memcpy(data->strval, bnode, size);
179 data->strval[size] = '\0'; 183 data->strval[size] = '\0';
180 data->length = strlen(data->strval); 184 data->length = strlen(data->strval);
181 185
182 return g_node_new(data); 186 return g_node_new(data);
183} 187}
184 188
185static plist_t parse_unicode_node(char *bnode, uint64_t size) 189static plist_t parse_unicode_node(char *bnode, uint64_t size)
186{ 190{
187 plist_data_t data = plist_new_plist_data(); 191 plist_data_t data = plist_new_plist_data();
188 uint64_t i = 0; 192 uint64_t i = 0;
189 gunichar2 *unicodestr = NULL; 193 gunichar2 *unicodestr = NULL;
190 gchar *tmpstr = NULL; 194 gchar *tmpstr = NULL;
191 int type = 0; 195 int type = 0;
192 glong items_read = 0; 196 glong items_read = 0;
193 glong items_written = 0; 197 glong items_written = 0;
194 GError *error = NULL; 198 GError *error = NULL;
195 199
196 data->type = PLIST_STRING; 200 data->type = PLIST_STRING;
197 unicodestr = (gunichar2 *) malloc(sizeof(gunichar2) * size); 201 unicodestr = (gunichar2 *) malloc(sizeof(gunichar2) * size);
198 memcpy(unicodestr, bnode, sizeof(gunichar2) * size); 202 memcpy(unicodestr, bnode, sizeof(gunichar2) * size);
199 for (i = 0; i < size; i++) 203 for (i = 0; i < size; i++)
200 byte_convert((uint8_t *) (unicodestr + i), sizeof(gunichar2)); 204 byte_convert((uint8_t *) (unicodestr + i), sizeof(gunichar2));
201 205
202 tmpstr = g_utf16_to_utf8(unicodestr, size, &items_read, &items_written, &error); 206 tmpstr = g_utf16_to_utf8(unicodestr, size, &items_read, &items_written, &error);
203 free(unicodestr); 207 free(unicodestr);
204 208
205 data->type = PLIST_STRING; 209 data->type = PLIST_STRING;
206 data->strval = (char *) malloc(sizeof(char) * (items_written + 1)); 210 data->strval = (char *) malloc(sizeof(char) * (items_written + 1));
207 memcpy(data->strval, tmpstr, items_written); 211 memcpy(data->strval, tmpstr, items_written);
208 data->strval[items_written] = '\0'; 212 data->strval[items_written] = '\0';
209 data->length = strlen(data->strval); 213 data->length = strlen(data->strval);
210 g_free(tmpstr); 214 g_free(tmpstr);
211 return g_node_new(data); 215 return g_node_new(data);
212} 216}
213 217
214static plist_t parse_data_node(char *bnode, uint64_t size) 218static plist_t parse_data_node(char *bnode, uint64_t size)
215{ 219{
216 plist_data_t data = plist_new_plist_data(); 220 plist_data_t data = plist_new_plist_data();
217 221
218 data->type = PLIST_DATA; 222 data->type = PLIST_DATA;
219 data->length = size; 223 data->length = size;
220 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size); 224 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size);
221 memcpy(data->buff, bnode, sizeof(uint8_t) * size); 225 memcpy(data->buff, bnode, sizeof(uint8_t) * size);
222 226
223 return g_node_new(data); 227 return g_node_new(data);
224} 228}
225 229
226static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size) 230static plist_t parse_dict_node(char *bnode, uint64_t size, uint32_t ref_size)
227{ 231{
228 plist_data_t data = plist_new_plist_data(); 232 plist_data_t data = plist_new_plist_data();
229 233
230 data->type = PLIST_DICT; 234 data->type = PLIST_DICT;
231 data->length = size; 235 data->length = size;
232 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size * 2); 236 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size * 2);
233 memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size * 2); 237 memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size * 2);
234 238
235 return g_node_new(data); 239 return g_node_new(data);
236} 240}
237 241
238static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) 242static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size)
239{ 243{
240 plist_data_t data = plist_new_plist_data(); 244 plist_data_t data = plist_new_plist_data();
241 245
242 data->type = PLIST_ARRAY; 246 data->type = PLIST_ARRAY;
243 data->length = size; 247 data->length = size;
244 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size); 248 data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size);
245 memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size); 249 memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size);
246 250
247 return g_node_new(data); 251 return g_node_new(data);
248} 252}
249 253
250 254
251 255
252static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_object) 256static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_object)
253{ 257{
254 uint16_t type = 0; 258 uint16_t type = 0;
255 uint64_t size = 0; 259 uint64_t size = 0;
256 260
257 if (!object) 261 if (!object)
258 return NULL; 262 return NULL;
259 263
260 type = (*object) & 0xF0; 264 type = (*object) & 0xF0;
261 size = (*object) & 0x0F; 265 size = (*object) & 0x0F;
262 object++; 266 object++;
263 267
264 switch (type) { 268 switch (type)
265 269 {
266 case BPLIST_NULL: 270
267 switch (size) { 271 case BPLIST_NULL:
268 272 switch (size)
269 case BPLIST_TRUE: 273 {
270 { 274
271 plist_data_t data = plist_new_plist_data(); 275 case BPLIST_TRUE:
272 data->type = PLIST_BOOLEAN; 276 {
273 data->boolval = TRUE; 277 plist_data_t data = plist_new_plist_data();
274 data->length = 1; 278 data->type = PLIST_BOOLEAN;
275 return g_node_new(data); 279 data->boolval = TRUE;
276 } 280 data->length = 1;
277 281 return g_node_new(data);
278 case BPLIST_FALSE: 282 }
279 { 283
280 plist_data_t data = plist_new_plist_data(); 284 case BPLIST_FALSE:
281 data->type = PLIST_BOOLEAN; 285 {
282 data->boolval = FALSE; 286 plist_data_t data = plist_new_plist_data();
283 data->length = 1; 287 data->type = PLIST_BOOLEAN;
284 return g_node_new(data); 288 data->boolval = FALSE;
285 } 289 data->length = 1;
286 290 return g_node_new(data);
287 case BPLIST_NULL: 291 }
288 default: 292
289 return NULL; 293 case BPLIST_NULL:
290 } 294 default:
291 295 return NULL;
292 case BPLIST_UINT: 296 }
293 return parse_uint_node(object, size, next_object); 297
294 298 case BPLIST_UINT:
295 case BPLIST_REAL: 299 return parse_uint_node(object, size, next_object);
296 return parse_real_node(object, size); 300
297 301 case BPLIST_REAL:
298 case BPLIST_DATE: 302 return parse_real_node(object, size);
299 if (3 != size) 303
300 return NULL; 304 case BPLIST_DATE:
301 else 305 if (3 != size)
302 return parse_date_node(object, size); 306 return NULL;
303 307 else
304 case BPLIST_DATA: 308 return parse_date_node(object, size);
305 if (0x0F == size) { 309
306 plist_t size_node = parse_bin_node(object, dict_size, &object); 310 case BPLIST_DATA:
307 if (plist_get_node_type(size_node) != PLIST_UINT) 311 if (0x0F == size)
308 return NULL; 312 {
309 plist_get_uint_val(size_node, &size); 313 plist_t size_node = parse_bin_node(object, dict_size, &object);
310 plist_free(size_node); 314 if (plist_get_node_type(size_node) != PLIST_UINT)
311 } 315 return NULL;
312 return parse_data_node(object, size); 316 plist_get_uint_val(size_node, &size);
313 317 plist_free(size_node);
314 case BPLIST_STRING: 318 }
315 if (0x0F == size) { 319 return parse_data_node(object, size);
316 plist_t size_node = parse_bin_node(object, dict_size, &object); 320
317 if (plist_get_node_type(size_node) != PLIST_UINT) 321 case BPLIST_STRING:
318 return NULL; 322 if (0x0F == size)
319 plist_get_uint_val(size_node, &size); 323 {
320 plist_free(size_node); 324 plist_t size_node = parse_bin_node(object, dict_size, &object);
321 } 325 if (plist_get_node_type(size_node) != PLIST_UINT)
322 return parse_string_node(object, size); 326 return NULL;
323 327 plist_get_uint_val(size_node, &size);
324 case BPLIST_UNICODE: 328 plist_free(size_node);
325 if (0x0F == size) { 329 }
326 plist_t size_node = parse_bin_node(object, dict_size, &object); 330 return parse_string_node(object, size);
327 if (plist_get_node_type(size_node) != PLIST_UINT) 331
328 return NULL; 332 case BPLIST_UNICODE:
329 plist_get_uint_val(size_node, &size); 333 if (0x0F == size)
330 plist_free(size_node); 334 {
331 } 335 plist_t size_node = parse_bin_node(object, dict_size, &object);
332 return parse_unicode_node(object, size); 336 if (plist_get_node_type(size_node) != PLIST_UINT)
333 337 return NULL;
334 case BPLIST_UID: 338 plist_get_uint_val(size_node, &size);
335 case BPLIST_ARRAY: 339 plist_free(size_node);
336 if (0x0F == size) { 340 }
337 plist_t size_node = parse_bin_node(object, dict_size, &object); 341 return parse_unicode_node(object, size);
338 if (plist_get_node_type(size_node) != PLIST_UINT) 342
339 return NULL; 343 case BPLIST_UID:
340 plist_get_uint_val(size_node, &size); 344 case BPLIST_ARRAY:
341 plist_free(size_node); 345 if (0x0F == size)
342 } 346 {
343 return parse_array_node(object, size, dict_size); 347 plist_t size_node = parse_bin_node(object, dict_size, &object);
344 348 if (plist_get_node_type(size_node) != PLIST_UINT)
345 case BPLIST_SET: 349 return NULL;
346 case BPLIST_DICT: 350 plist_get_uint_val(size_node, &size);
347 if (0x0F == size) { 351 plist_free(size_node);
348 plist_t size_node = parse_bin_node(object, dict_size, &object); 352 }
349 if (plist_get_node_type(size_node) != PLIST_UINT) 353 return parse_array_node(object, size, dict_size);
350 return NULL; 354
351 plist_get_uint_val(size_node, &size); 355 case BPLIST_SET:
352 plist_free(size_node); 356 case BPLIST_DICT:
353 } 357 if (0x0F == size)
354 return parse_dict_node(object, size, dict_size); 358 {
355 default: 359 plist_t size_node = parse_bin_node(object, dict_size, &object);
356 return NULL; 360 if (plist_get_node_type(size_node) != PLIST_UINT)
357 } 361 return NULL;
358 return NULL; 362 plist_get_uint_val(size_node, &size);
363 plist_free(size_node);
364 }
365 return parse_dict_node(object, size, dict_size);
366 default:
367 return NULL;
368 }
369 return NULL;
359} 370}
360 371
361static gpointer copy_plist_data(gconstpointer src, gpointer data) 372static gpointer copy_plist_data(gconstpointer src, gpointer data)
362{ 373{
363 plist_data_t srcdata = (plist_data_t) src; 374 plist_data_t srcdata = (plist_data_t) src;
364 plist_data_t dstdata = plist_new_plist_data(); 375 plist_data_t dstdata = plist_new_plist_data();
365 376
366 dstdata->type = srcdata->type; 377 dstdata->type = srcdata->type;
367 dstdata->length = srcdata->length; 378 dstdata->length = srcdata->length;
368 switch (dstdata->type) { 379 switch (dstdata->type)
369 case PLIST_BOOLEAN: 380 {
370 dstdata->boolval = srcdata->boolval; 381 case PLIST_BOOLEAN:
371 break; 382 dstdata->boolval = srcdata->boolval;
372 case PLIST_UINT: 383 break;
373 dstdata->intval = srcdata->intval; 384 case PLIST_UINT:
374 break; 385 dstdata->intval = srcdata->intval;
375 case PLIST_DATE: 386 break;
376 dstdata->timeval.tv_sec = srcdata->timeval.tv_sec; 387 case PLIST_DATE:
377 dstdata->timeval.tv_usec = srcdata->timeval.tv_usec; 388 dstdata->timeval.tv_sec = srcdata->timeval.tv_sec;
378 break; 389 dstdata->timeval.tv_usec = srcdata->timeval.tv_usec;
379 case PLIST_REAL: 390 break;
380 dstdata->realval = srcdata->realval; 391 case PLIST_REAL:
381 break; 392 dstdata->realval = srcdata->realval;
382 case PLIST_KEY: 393 break;
383 case PLIST_STRING: 394 case PLIST_KEY:
384 dstdata->strval = strdup(srcdata->strval); 395 case PLIST_STRING:
385 break; 396 dstdata->strval = strdup(srcdata->strval);
386 case PLIST_DATA: 397 break;
387 case PLIST_ARRAY: 398 case PLIST_DATA:
388 dstdata->buff = (uint8_t *) malloc(sizeof(uint8_t *) * srcdata->length); 399 case PLIST_ARRAY:
389 memcpy(dstdata->buff, srcdata->buff, sizeof(uint8_t *) * srcdata->length); 400 dstdata->buff = (uint8_t *) malloc(sizeof(uint8_t *) * srcdata->length);
390 break; 401 memcpy(dstdata->buff, srcdata->buff, sizeof(uint8_t *) * srcdata->length);
391 case PLIST_DICT: 402 break;
392 dstdata->buff = (uint8_t *) malloc(sizeof(uint8_t *) * srcdata->length * 2); 403 case PLIST_DICT:
393 memcpy(dstdata->buff, srcdata->buff, sizeof(uint8_t *) * srcdata->length * 2); 404 dstdata->buff = (uint8_t *) malloc(sizeof(uint8_t *) * srcdata->length * 2);
394 break; 405 memcpy(dstdata->buff, srcdata->buff, sizeof(uint8_t *) * srcdata->length * 2);
395 default: 406 break;
396 break; 407 default:
397 } 408 break;
398 409 }
399 return dstdata; 410
411 return dstdata;
400} 412}
401 413
402void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist) 414void plist_from_bin(const char *plist_bin, uint32_t length, plist_t * plist)
403{ 415{
404 char *trailer = NULL; 416 char *trailer = NULL;
405 417
406 uint8_t offset_size = 0; 418 uint8_t offset_size = 0;
407 uint8_t dict_param_size = 0; 419 uint8_t dict_param_size = 0;
408 uint64_t num_objects = 0; 420 uint64_t num_objects = 0;
409 uint64_t root_object = 0; 421 uint64_t root_object = 0;
410 uint64_t offset_table_index = 0; 422 uint64_t offset_table_index = 0;
411 423
412 plist_t *nodeslist = NULL; 424 plist_t *nodeslist = NULL;
413 uint64_t i = 0; 425 uint64_t i = 0;
414 uint64_t current_offset = 0; 426 uint64_t current_offset = 0;
415 char *offset_table = NULL; 427 char *offset_table = NULL;
416 uint32_t j = 0, str_i = 0, str_j = 0; 428 uint32_t j = 0, str_i = 0, str_j = 0;
417 uint32_t index1 = 0, index2 = 0; 429 uint32_t index1 = 0, index2 = 0;
418 430
419 431
420 //first check we have enough data 432 //first check we have enough data
421 if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + BPLIST_TRL_SIZE)) 433 if (!(length >= BPLIST_MAGIC_SIZE + BPLIST_VERSION_SIZE + BPLIST_TRL_SIZE))
422 return; 434 return;
423 //check that plist_bin in actually a plist 435 //check that plist_bin in actually a plist
424 if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0) 436 if (memcmp(plist_bin, BPLIST_MAGIC, BPLIST_MAGIC_SIZE) != 0)
425 return; 437 return;
426 //check for known version 438 //check for known version
427 if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0) 439 if (memcmp(plist_bin + BPLIST_MAGIC_SIZE, BPLIST_VERSION, BPLIST_VERSION_SIZE) != 0)
428 return; 440 return;
429 441
430 //now parse trailer 442 //now parse trailer
431 trailer = (char *) (plist_bin + (length - BPLIST_TRL_SIZE)); 443 trailer = (char *) (plist_bin + (length - BPLIST_TRL_SIZE));
432 444
433 offset_size = trailer[BPLIST_TRL_OFFSIZE_IDX]; 445 offset_size = trailer[BPLIST_TRL_OFFSIZE_IDX];
434 dict_param_size = trailer[BPLIST_TRL_PARMSIZE_IDX]; 446 dict_param_size = trailer[BPLIST_TRL_PARMSIZE_IDX];
435 num_objects = be64dec(trailer + BPLIST_TRL_NUMOBJ_IDX); 447 num_objects = be64dec(trailer + BPLIST_TRL_NUMOBJ_IDX);
436 root_object = be64dec(trailer + BPLIST_TRL_ROOTOBJ_IDX); 448 root_object = be64dec(trailer + BPLIST_TRL_ROOTOBJ_IDX);
437 offset_table_index = be64dec(trailer + BPLIST_TRL_OFFTAB_IDX); 449 offset_table_index = be64dec(trailer + BPLIST_TRL_OFFTAB_IDX);
438 450
439 if (num_objects == 0) 451 if (num_objects == 0)
440 return; 452 return;
441 453
442 //allocate serialized array of nodes 454 //allocate serialized array of nodes
443 nodeslist = (plist_t *) malloc(sizeof(plist_t) * num_objects); 455 nodeslist = (plist_t *) malloc(sizeof(plist_t) * num_objects);
444 456
445 if (!nodeslist) 457 if (!nodeslist)
446 return; 458 return;
447 459
448 //parse serialized nodes 460 //parse serialized nodes
449 offset_table = (char *) (plist_bin + offset_table_index); 461 offset_table = (char *) (plist_bin + offset_table_index);
450 for (i = 0; i < num_objects; i++) { 462 for (i = 0; i < num_objects; i++)
451 char *obj = NULL; 463 {
452 current_offset = UINT_TO_HOST(offset_table + i * offset_size, offset_size); 464 char *obj = NULL;
453 465 current_offset = UINT_TO_HOST(offset_table + i * offset_size, offset_size);
454 obj = (char *) (plist_bin + current_offset); 466
455 nodeslist[i] = parse_bin_node(obj, dict_param_size, &obj); 467 obj = (char *) (plist_bin + current_offset);
456 } 468 nodeslist[i] = parse_bin_node(obj, dict_param_size, &obj);
457 469 }
458 //setup children for structured types 470
459 for (i = 0; i < num_objects; i++) { 471 //setup children for structured types
460 472 for (i = 0; i < num_objects; i++)
461 plist_data_t data = plist_get_data(nodeslist[i]); 473 {
462 474
463 switch (data->type) { 475 plist_data_t data = plist_get_data(nodeslist[i]);
464 case PLIST_DICT: 476
465 for (j = 0; j < data->length; j++) { 477 switch (data->type)
466 str_i = j * dict_param_size; 478 {
467 str_j = (j + data->length) * dict_param_size; 479 case PLIST_DICT:
468 480 for (j = 0; j < data->length; j++)
469 index1 = UINT_TO_HOST(data->buff + str_i, dict_param_size); 481 {
470 index2 = UINT_TO_HOST(data->buff + str_j, dict_param_size); 482 str_i = j * dict_param_size;
471 483 str_j = (j + data->length) * dict_param_size;
472 //first one is actually a key 484
473 plist_get_data(nodeslist[index1])->type = PLIST_KEY; 485 index1 = UINT_TO_HOST(data->buff + str_i, dict_param_size);
474 486 index2 = UINT_TO_HOST(data->buff + str_j, dict_param_size);
475 if (index1 < num_objects) { 487
476 if (G_NODE_IS_ROOT(nodeslist[index1])) 488 //first one is actually a key
477 g_node_append(nodeslist[i], nodeslist[index1]); 489 plist_get_data(nodeslist[index1])->type = PLIST_KEY;
478 else 490
479 g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL)); 491 if (index1 < num_objects)
480 } 492 {
481 493 if (G_NODE_IS_ROOT(nodeslist[index1]))
482 if (index2 < num_objects) { 494 g_node_append(nodeslist[i], nodeslist[index1]);
483 if (G_NODE_IS_ROOT(nodeslist[index2])) 495 else
484 g_node_append(nodeslist[i], nodeslist[index2]); 496 g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL));
485 else 497 }
486 g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index2], copy_plist_data, NULL)); 498
487 } 499 if (index2 < num_objects)
488 } 500 {
489 501 if (G_NODE_IS_ROOT(nodeslist[index2]))
490 free(data->buff); 502 g_node_append(nodeslist[i], nodeslist[index2]);
491 break; 503 else
492 504 g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index2], copy_plist_data, NULL));
493 case PLIST_ARRAY: 505 }
494 for (j = 0; j < data->length; j++) { 506 }
495 str_j = j * dict_param_size; 507
496 index1 = UINT_TO_HOST(data->buff + str_j, dict_param_size); 508 free(data->buff);
497 509 break;
498 if (index1 < num_objects) { 510
499 if (G_NODE_IS_ROOT(nodeslist[index1])) 511 case PLIST_ARRAY:
500 g_node_append(nodeslist[i], nodeslist[index1]); 512 for (j = 0; j < data->length; j++)
501 else 513 {
502 g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL)); 514 str_j = j * dict_param_size;
503 } 515 index1 = UINT_TO_HOST(data->buff + str_j, dict_param_size);
504 } 516
505 free(data->buff); 517 if (index1 < num_objects)
506 break; 518 {
507 default: 519 if (G_NODE_IS_ROOT(nodeslist[index1]))
508 break; 520 g_node_append(nodeslist[i], nodeslist[index1]);
509 } 521 else
510 } 522 g_node_append(nodeslist[i], g_node_copy_deep(nodeslist[index1], copy_plist_data, NULL));
511 523 }
512 *plist = nodeslist[root_object]; 524 }
513 free(nodeslist); 525 free(data->buff);
526 break;
527 default:
528 break;
529 }
530 }
531
532 *plist = nodeslist[root_object];
533 free(nodeslist);
514} 534}
515 535
516static guint plist_data_hash(gconstpointer key) 536static guint plist_data_hash(gconstpointer key)
517{ 537{
518 plist_data_t data = plist_get_data((plist_t) key); 538 plist_data_t data = plist_get_data((plist_t) key);
519 539
520 guint hash = data->type; 540 guint hash = data->type;
521 guint i = 0; 541 guint i = 0;
522 542
523 char *buff = NULL; 543 char *buff = NULL;
524 guint size = 0; 544 guint size = 0;
525 545
526 switch (data->type) { 546 switch (data->type)
527 case PLIST_BOOLEAN: 547 {
528 case PLIST_UINT: 548 case PLIST_BOOLEAN:
529 case PLIST_REAL: 549 case PLIST_UINT:
530 buff = (char *) &data->intval; //works also for real as we use an union 550 case PLIST_REAL:
531 size = 8; 551 buff = (char *) &data->intval; //works also for real as we use an union
532 break; 552 size = 8;
533 case PLIST_KEY: 553 break;
534 case PLIST_STRING: 554 case PLIST_KEY:
535 buff = data->strval; 555 case PLIST_STRING:
536 size = strlen(buff); 556 buff = data->strval;
537 break; 557 size = strlen(buff);
538 case PLIST_DATA: 558 break;
539 case PLIST_ARRAY: 559 case PLIST_DATA:
540 case PLIST_DICT: 560 case PLIST_ARRAY:
541 //for these types only hash pointer 561 case PLIST_DICT:
542 buff = (char *) &key; 562 //for these types only hash pointer
543 size = sizeof(gconstpointer); 563 buff = (char *) &key;
544 break; 564 size = sizeof(gconstpointer);
545 case PLIST_DATE: 565 break;
546 buff = (char *) &(data->timeval); 566 case PLIST_DATE:
547 size = data->length; 567 buff = (char *) &(data->timeval);
548 break; 568 size = data->length;
549 default: 569 break;
550 break; 570 default:
551 } 571 break;
552 572 }
553 //now perform hash 573
554 for (i = 0; i < size; buff++, i++) 574 //now perform hash
555 hash = hash << 7 ^ (*buff); 575 for (i = 0; i < size; buff++, i++)
556 576 hash = hash << 7 ^ (*buff);
557 return hash; 577
578 return hash;
558} 579}
559 580
560 581
561 582
562struct serialize_s { 583struct serialize_s
563 GPtrArray *objects; 584{
564 GHashTable *ref_table; 585 GPtrArray *objects;
586 GHashTable *ref_table;
565}; 587};
566 588
567static void serialize_plist(GNode * node, gpointer data) 589static void serialize_plist(GNode * node, gpointer data)
568{ 590{
569 uint64_t *index_val = NULL; 591 uint64_t *index_val = NULL;
570 struct serialize_s *ser = (struct serialize_s *) data; 592 struct serialize_s *ser = (struct serialize_s *) data;
571 uint64_t current_index = ser->objects->len; 593 uint64_t current_index = ser->objects->len;
572 594
573 //first check that node is not yet in objects 595 //first check that node is not yet in objects
574 gpointer val = g_hash_table_lookup(ser->ref_table, node); 596 gpointer val = g_hash_table_lookup(ser->ref_table, node);
575 if (val) { 597 if (val)
576 //data is already in table 598 {
577 return; 599 //data is already in table
578 } 600 return;
579 //insert new ref 601 }
580 index_val = (uint64_t *) malloc(sizeof(uint64_t)); 602 //insert new ref
581 *index_val = current_index; 603 index_val = (uint64_t *) malloc(sizeof(uint64_t));
582 g_hash_table_insert(ser->ref_table, node, index_val); 604 *index_val = current_index;
583 605 g_hash_table_insert(ser->ref_table, node, index_val);
584 //now append current node to object array 606
585 g_ptr_array_add(ser->objects, node); 607 //now append current node to object array
586 608 g_ptr_array_add(ser->objects, node);
587 //now recurse on children 609
588 g_node_children_foreach(node, G_TRAVERSE_ALL, serialize_plist, data); 610 //now recurse on children
589 return; 611 g_node_children_foreach(node, G_TRAVERSE_ALL, serialize_plist, data);
612 return;
590} 613}
591 614
592static gboolean free_index(gpointer key, gpointer value, gpointer user_data) 615static gboolean free_index(gpointer key, gpointer value, gpointer user_data)
593{ 616{
594 free((uint64_t *) value); 617 free((uint64_t *) value);
595 return TRUE; 618 return TRUE;
596} 619}
597 620
598#define Log2(x) (x == 8 ? 3 : (x == 4 ? 2 : (x == 2 ? 1 : 0))) 621#define Log2(x) (x == 8 ? 3 : (x == 4 ? 2 : (x == 2 ? 1 : 0)))
599 622
600static void write_int(GByteArray * bplist, uint64_t val) 623static void write_int(GByteArray * bplist, uint64_t val)
601{ 624{
602 uint64_t size = get_needed_bytes(val); 625 uint64_t size = get_needed_bytes(val);
603 uint8_t *buff = NULL; 626 uint8_t *buff = NULL;
604 //do not write 3bytes int node 627 //do not write 3bytes int node
605 if (size == 3) 628 if (size == 3)
606 size++; 629 size++;
607 buff = (uint8_t *) malloc(sizeof(uint8_t) + size); 630 buff = (uint8_t *) malloc(sizeof(uint8_t) + size);
608 buff[0] = BPLIST_UINT | Log2(size); 631 buff[0] = BPLIST_UINT | Log2(size);
609 memcpy(buff + 1, &val, size); 632 memcpy(buff + 1, &val, size);
610 byte_convert(buff + 1, size); 633 byte_convert(buff + 1, size);
611 g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); 634 g_byte_array_append(bplist, buff, sizeof(uint8_t) + size);
612 free(buff); 635 free(buff);
613} 636}
614 637
615static void write_real(GByteArray * bplist, double val) 638static void write_real(GByteArray * bplist, double val)
616{ 639{
617 uint64_t size = get_real_bytes(*((uint64_t *) & val)); //cheat to know used space 640 uint64_t size = get_real_bytes(*((uint64_t *) & val)); //cheat to know used space
618 uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); 641 uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size);
619 buff[0] = BPLIST_REAL | Log2(size); 642 buff[0] = BPLIST_REAL | Log2(size);
620 if (size == sizeof(double)) { 643 if (size == sizeof(double))
621 memcpy(buff + 1, &val, size); 644 {
622 } else if (size == sizeof(float)) { 645 memcpy(buff + 1, &val, size);
623 float tmpval = (float) val; 646 }
624 memcpy(buff + 1, &tmpval, size); 647 else if (size == sizeof(float))
625 } 648 {
626 byte_convert(buff + 1, size); 649 float tmpval = (float) val;
627 g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); 650 memcpy(buff + 1, &tmpval, size);
628 free(buff); 651 }
652 byte_convert(buff + 1, size);
653 g_byte_array_append(bplist, buff, sizeof(uint8_t) + size);
654 free(buff);
629} 655}
630 656
631static void write_date(GByteArray * bplist, double val) 657static void write_date(GByteArray * bplist, double val)
632{ 658{
633 uint64_t size = 8; //dates always use 8 bytes 659 uint64_t size = 8; //dates always use 8 bytes
634 uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size); 660 uint8_t *buff = (uint8_t *) malloc(sizeof(uint8_t) + size);
635 buff[0] = BPLIST_DATE | Log2(size); 661 buff[0] = BPLIST_DATE | Log2(size);
636 memcpy(buff + 1, &val, size); 662 memcpy(buff + 1, &val, size);
637 byte_convert(buff + 1, size); 663 byte_convert(buff + 1, size);
638 g_byte_array_append(bplist, buff, sizeof(uint8_t) + size); 664 g_byte_array_append(bplist, buff, sizeof(uint8_t) + size);
639 free(buff); 665 free(buff);
640} 666}
641 667
642static void write_raw_data(GByteArray * bplist, uint8_t mark, uint8_t * val, uint64_t size) 668static void write_raw_data(GByteArray * bplist, uint8_t mark, uint8_t * val, uint64_t size)
643{ 669{
644 uint8_t *buff = NULL; 670 uint8_t *buff = NULL;
645 uint8_t marker = mark | (size < 15 ? size : 0xf); 671 uint8_t marker = mark | (size < 15 ? size : 0xf);
646 g_byte_array_append(bplist, &marker, sizeof(uint8_t)); 672 g_byte_array_append(bplist, &marker, sizeof(uint8_t));
647 if (size >= 15) { 673 if (size >= 15)
648 GByteArray *int_buff = g_byte_array_new(); 674 {
649 write_int(int_buff, size); 675 GByteArray *int_buff = g_byte_array_new();
650 g_byte_array_append(bplist, int_buff->data, int_buff->len); 676 write_int(int_buff, size);
651 g_byte_array_free(int_buff, TRUE); 677 g_byte_array_append(bplist, int_buff->data, int_buff->len);
652 } 678 g_byte_array_free(int_buff, TRUE);
653 buff = (uint8_t *) malloc(size); 679 }
654 memcpy(buff, val, size); 680 buff = (uint8_t *) malloc(size);
655 g_byte_array_append(bplist, buff, size); 681 memcpy(buff, val, size);
656 free(buff); 682 g_byte_array_append(bplist, buff, size);
683 free(buff);
657} 684}
658 685
659static void write_data(GByteArray * bplist, uint8_t * val, uint64_t size) 686static void write_data(GByteArray * bplist, uint8_t * val, uint64_t size)
660{ 687{
661 write_raw_data(bplist, BPLIST_DATA, val, size); 688 write_raw_data(bplist, BPLIST_DATA, val, size);
662} 689}
663 690
664static void write_string(GByteArray * bplist, char *val) 691static void write_string(GByteArray * bplist, char *val)
665{ 692{
666 uint64_t size = strlen(val); 693 uint64_t size = strlen(val);
667 write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size); 694 write_raw_data(bplist, BPLIST_STRING, (uint8_t *) val, size);
668} 695}
669 696
670static void write_unicode(GByteArray * bplist, gunichar2 * val, uint64_t size) 697static void write_unicode(GByteArray * bplist, gunichar2 * val, uint64_t size)
671{ 698{
672 uint64_t i = 0; 699 uint64_t i = 0;
673 uint64_t size2 = size * sizeof(gunichar2); 700 uint64_t size2 = size * sizeof(gunichar2);
674 uint8_t *buff = (uint8_t *) malloc(size2); 701 uint8_t *buff = (uint8_t *) malloc(size2);
675 memcpy(buff, val, size2); 702 memcpy(buff, val, size2);
676 for (i = 0; i < size; i++) 703 for (i = 0; i < size; i++)
677 byte_convert(buff + i * sizeof(gunichar2), sizeof(gunichar2)); 704 byte_convert(buff + i * sizeof(gunichar2), sizeof(gunichar2));
678 write_raw_data(bplist, BPLIST_STRING, buff, size2); 705 write_raw_data(bplist, BPLIST_STRING, buff, size2);
679} 706}
680 707
681static void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) 708static void write_array(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size)
682{ 709{
683 uint64_t idx = 0; 710 uint64_t idx = 0;
684 uint8_t *buff = NULL; 711 uint8_t *buff = NULL;
685 712
686 GNode *cur = NULL; 713 GNode *cur = NULL;
687 uint64_t i = 0; 714 uint64_t i = 0;
688 715
689 uint64_t size = g_node_n_children(node); 716 uint64_t size = g_node_n_children(node);
690 uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf); 717 uint8_t marker = BPLIST_ARRAY | (size < 15 ? size : 0xf);
691 g_byte_array_append(bplist, &marker, sizeof(uint8_t)); 718 g_byte_array_append(bplist, &marker, sizeof(uint8_t));
692 if (size >= 15) { 719 if (size >= 15)
693 GByteArray *int_buff = g_byte_array_new(); 720 {
694 write_int(int_buff, size); 721 GByteArray *int_buff = g_byte_array_new();
695 g_byte_array_append(bplist, int_buff->data, int_buff->len); 722 write_int(int_buff, size);
696 g_byte_array_free(int_buff, TRUE); 723 g_byte_array_append(bplist, int_buff->data, int_buff->len);
697 } 724 g_byte_array_free(int_buff, TRUE);
698 725 }
699 buff = (uint8_t *) malloc(size * dict_param_size); 726
700 727 buff = (uint8_t *) malloc(size * dict_param_size);
701 for (i = 0, cur = node->children; cur && i < size; cur = cur->next, i++) { 728
702 idx = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); 729 for (i = 0, cur = node->children; cur && i < size; cur = cur->next, i++)
703 memcpy(buff + i * dict_param_size, &idx, dict_param_size); 730 {
704 byte_convert(buff + i * dict_param_size, dict_param_size); 731 idx = *(uint64_t *) (g_hash_table_lookup(ref_table, cur));
705 } 732 memcpy(buff + i * dict_param_size, &idx, dict_param_size);
706 733 byte_convert(buff + i * dict_param_size, dict_param_size);
707 //now append to bplist 734 }
708 g_byte_array_append(bplist, buff, size * dict_param_size); 735
709 free(buff); 736 //now append to bplist
737 g_byte_array_append(bplist, buff, size * dict_param_size);
738 free(buff);
710 739
711} 740}
712 741
713static void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size) 742static void write_dict(GByteArray * bplist, GNode * node, GHashTable * ref_table, uint8_t dict_param_size)
714{ 743{
715 uint64_t idx1 = 0; 744 uint64_t idx1 = 0;
716 uint64_t idx2 = 0; 745 uint64_t idx2 = 0;
717 uint8_t *buff = NULL; 746 uint8_t *buff = NULL;
718 747
719 GNode *cur = NULL; 748 GNode *cur = NULL;
720 uint64_t i = 0; 749 uint64_t i = 0;
721 750
722 uint64_t size = g_node_n_children(node) / 2; 751 uint64_t size = g_node_n_children(node) / 2;
723 uint8_t marker = BPLIST_DICT | (size < 15 ? size : 0xf); 752 uint8_t marker = BPLIST_DICT | (size < 15 ? size : 0xf);
724 g_byte_array_append(bplist, &marker, sizeof(uint8_t)); 753 g_byte_array_append(bplist, &marker, sizeof(uint8_t));
725 if (size >= 15) { 754 if (size >= 15)
726 GByteArray *int_buff = g_byte_array_new(); 755 {
727 write_int(int_buff, size); 756 GByteArray *int_buff = g_byte_array_new();
728 g_byte_array_append(bplist, int_buff->data, int_buff->len); 757 write_int(int_buff, size);
729 g_byte_array_free(int_buff, TRUE); 758 g_byte_array_append(bplist, int_buff->data, int_buff->len);
730 } 759 g_byte_array_free(int_buff, TRUE);
731 760 }
732 buff = (uint8_t *) malloc(size * 2 * dict_param_size); 761
733 762 buff = (uint8_t *) malloc(size * 2 * dict_param_size);
734 for (i = 0, cur = node->children; cur && i < size; cur = cur->next->next, i++) { 763
735 idx1 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur)); 764 for (i = 0, cur = node->children; cur && i < size; cur = cur->next->next, i++)
736 memcpy(buff + i * dict_param_size, &idx1, dict_param_size); 765 {
737 byte_convert(buff + i * dict_param_size, dict_param_size); 766 idx1 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur));
738 767 memcpy(buff + i * dict_param_size, &idx1, dict_param_size);
739 idx2 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur->next)); 768 byte_convert(buff + i * dict_param_size, dict_param_size);
740 memcpy(buff + (i + size) * dict_param_size, &idx2, dict_param_size); 769
741 byte_convert(buff + (i + size) * dict_param_size, dict_param_size); 770 idx2 = *(uint64_t *) (g_hash_table_lookup(ref_table, cur->next));
742 } 771 memcpy(buff + (i + size) * dict_param_size, &idx2, dict_param_size);
743 772 byte_convert(buff + (i + size) * dict_param_size, dict_param_size);
744 //now append to bplist 773 }
745 g_byte_array_append(bplist, buff, size * 2 * dict_param_size); 774
746 free(buff); 775 //now append to bplist
776 g_byte_array_append(bplist, buff, size * 2 * dict_param_size);
777 free(buff);
747 778
748} 779}
749 780
750void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length) 781void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
751{ 782{
752 GPtrArray *objects = NULL; 783 GPtrArray *objects = NULL;
753 GHashTable *ref_table = NULL; 784 GHashTable *ref_table = NULL;
754 struct serialize_s ser_s; 785 struct serialize_s ser_s;
755 uint8_t offset_size = 0; 786 uint8_t offset_size = 0;
756 uint8_t dict_param_size = 0; 787 uint8_t dict_param_size = 0;
757 uint64_t num_objects = 0; 788 uint64_t num_objects = 0;
758 uint64_t root_object = 0; 789 uint64_t root_object = 0;
759 uint64_t offset_table_index = 0; 790 uint64_t offset_table_index = 0;
760 GByteArray *bplist_buff = NULL; 791 GByteArray *bplist_buff = NULL;
761 uint64_t i = 0; 792 uint64_t i = 0;
762 uint8_t *buff = NULL; 793 uint8_t *buff = NULL;
763 uint64_t *offsets = NULL; 794 uint64_t *offsets = NULL;
764 uint8_t pad[6] = { 0, 0, 0, 0, 0, 0 }; 795 uint8_t pad[6] = { 0, 0, 0, 0, 0, 0 };
765 uint8_t trailer[BPLIST_TRL_SIZE]; 796 uint8_t trailer[BPLIST_TRL_SIZE];
766 //for string 797 //for string
767 glong len = 0; 798 glong len = 0;
768 int type = 0; 799 int type = 0;
769 glong items_read = 0; 800 glong items_read = 0;
770 glong items_written = 0; 801 glong items_written = 0;
771 GError *error = NULL; 802 GError *error = NULL;
772 gunichar2 *unicodestr = NULL; 803 gunichar2 *unicodestr = NULL;
773 804
774 //check for valid input 805 //check for valid input
775 if (!plist || !plist_bin || *plist_bin || !length) 806 if (!plist || !plist_bin || *plist_bin || !length)
776 return; 807 return;
777 808
778 //list of objects 809 //list of objects
779 objects = g_ptr_array_new(); 810 objects = g_ptr_array_new();
780 //hashtable to write only once same nodes 811 //hashtable to write only once same nodes
781 ref_table = g_hash_table_new(plist_data_hash, plist_data_compare); 812 ref_table = g_hash_table_new(plist_data_hash, plist_data_compare);
782 813
783 //serialize plist 814 //serialize plist
784 ser_s.objects = objects; 815 ser_s.objects = objects;
785 ser_s.ref_table = ref_table; 816 ser_s.ref_table = ref_table;
786 serialize_plist(plist, &ser_s); 817 serialize_plist(plist, &ser_s);
787 818
788 //now stream to output buffer 819 //now stream to output buffer
789 offset_size = 0; //unknown yet 820 offset_size = 0; //unknown yet
790 dict_param_size = get_needed_bytes(objects->len); 821 dict_param_size = get_needed_bytes(objects->len);
791 num_objects = objects->len; 822 num_objects = objects->len;
792 root_object = 0; //root is first in list 823 root_object = 0; //root is first in list
793 offset_table_index = 0; //unknown yet 824 offset_table_index = 0; //unknown yet
794 825
795 //setup a dynamic bytes array to store bplist in 826 //setup a dynamic bytes array to store bplist in
796 bplist_buff = g_byte_array_new(); 827 bplist_buff = g_byte_array_new();
797 828
798 //set magic number and version 829 //set magic number and version
799 g_byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE); 830 g_byte_array_append(bplist_buff, BPLIST_MAGIC, BPLIST_MAGIC_SIZE);
800 g_byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE); 831 g_byte_array_append(bplist_buff, BPLIST_VERSION, BPLIST_VERSION_SIZE);
801 832
802 //write objects and table 833 //write objects and table
803 offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t)); 834 offsets = (uint64_t *) malloc(num_objects * sizeof(uint64_t));
804 for (i = 0; i < num_objects; i++) { 835 for (i = 0; i < num_objects; i++)
805 836 {
806 plist_data_t data = plist_get_data(g_ptr_array_index(objects, i)); 837
807 offsets[i] = bplist_buff->len; 838 plist_data_t data = plist_get_data(g_ptr_array_index(objects, i));
808 839 offsets[i] = bplist_buff->len;
809 switch (data->type) { 840
810 case PLIST_BOOLEAN: 841 switch (data->type)
811 buff = (uint8_t *) malloc(sizeof(uint8_t)); 842 {
812 buff[0] = data->boolval ? BPLIST_TRUE : BPLIST_FALSE; 843 case PLIST_BOOLEAN:
813 g_byte_array_append(bplist_buff, buff, sizeof(uint8_t)); 844 buff = (uint8_t *) malloc(sizeof(uint8_t));
814 free(buff); 845 buff[0] = data->boolval ? BPLIST_TRUE : BPLIST_FALSE;
815 break; 846 g_byte_array_append(bplist_buff, buff, sizeof(uint8_t));
816 847 free(buff);
817 case PLIST_UINT: 848 break;
818 write_int(bplist_buff, data->intval); 849
819 break; 850 case PLIST_UINT:
820 851 write_int(bplist_buff, data->intval);
821 case PLIST_REAL: 852 break;
822 write_real(bplist_buff, data->realval); 853
823 break; 854 case PLIST_REAL:
824 855 write_real(bplist_buff, data->realval);
825 case PLIST_KEY: 856 break;
826 case PLIST_STRING: 857
827 len = strlen(data->strval); 858 case PLIST_KEY:
828 type = xmlDetectCharEncoding(data->strval, len); 859 case PLIST_STRING:
829 if (XML_CHAR_ENCODING_UTF8 == type) { 860 len = strlen(data->strval);
830 unicodestr = g_utf8_to_utf16(data->strval, len, &items_read, &items_written, &error); 861 type = xmlDetectCharEncoding(data->strval, len);
831 write_unicode(bplist_buff, unicodestr, items_written); 862 if (XML_CHAR_ENCODING_UTF8 == type)
832 g_free(unicodestr); 863 {
833 } else if (XML_CHAR_ENCODING_ASCII == type || XML_CHAR_ENCODING_NONE == type) { 864 unicodestr = g_utf8_to_utf16(data->strval, len, &items_read, &items_written, &error);
834 write_string(bplist_buff, data->strval); 865 write_unicode(bplist_buff, unicodestr, items_written);
835 } 866 g_free(unicodestr);
836 break; 867 }
837 case PLIST_DATA: 868 else if (XML_CHAR_ENCODING_ASCII == type || XML_CHAR_ENCODING_NONE == type)
838 write_data(bplist_buff, data->buff, data->length); 869 {
839 case PLIST_ARRAY: 870 write_string(bplist_buff, data->strval);
840 write_array(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); 871 }
841 break; 872 break;
842 case PLIST_DICT: 873 case PLIST_DATA:
843 write_dict(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size); 874 write_data(bplist_buff, data->buff, data->length);
844 break; 875 case PLIST_ARRAY:
845 case PLIST_DATE: 876 write_array(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size);
846 write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / G_USEC_PER_SEC); 877 break;
847 break; 878 case PLIST_DICT:
848 default: 879 write_dict(bplist_buff, g_ptr_array_index(objects, i), ref_table, dict_param_size);
849 break; 880 break;
850 } 881 case PLIST_DATE:
851 } 882 write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / G_USEC_PER_SEC);
852 883 break;
853 //free intermediate objects 884 default:
854 g_hash_table_foreach_remove(ref_table, free_index, NULL); 885 break;
855 g_ptr_array_free(objects, TRUE); 886 }
856 g_hash_table_destroy(ref_table); 887 }
857 888
858 //write offsets 889 //free intermediate objects
859 offset_size = get_needed_bytes(bplist_buff->len); 890 g_hash_table_foreach_remove(ref_table, free_index, NULL);
860 offset_table_index = bplist_buff->len; 891 g_ptr_array_free(objects, TRUE);
861 for (i = 0; i < num_objects; i++) { 892 g_hash_table_destroy(ref_table);
862 uint8_t *offsetbuff = (uint8_t *) malloc(offset_size); 893
863 memcpy(offsetbuff, offsets + i, offset_size); 894 //write offsets
864 byte_convert(offsetbuff, offset_size); 895 offset_size = get_needed_bytes(bplist_buff->len);
865 g_byte_array_append(bplist_buff, offsetbuff, offset_size); 896 offset_table_index = bplist_buff->len;
866 free(offsetbuff); 897 for (i = 0; i < num_objects; i++)
867 } 898 {
868 899 uint8_t *offsetbuff = (uint8_t *) malloc(offset_size);
869 //experimental pad to reflect apple's files 900 memcpy(offsetbuff, offsets + i, offset_size);
870 g_byte_array_append(bplist_buff, pad, 6); 901 byte_convert(offsetbuff, offset_size);
871 902 g_byte_array_append(bplist_buff, offsetbuff, offset_size);
872 //setup trailer 903 free(offsetbuff);
873 num_objects = GUINT64_FROM_BE(num_objects); 904 }
874 root_object = GUINT64_FROM_BE(root_object); 905
875 offset_table_index = GUINT64_FROM_BE(offset_table_index); 906 //experimental pad to reflect apple's files
876 907 g_byte_array_append(bplist_buff, pad, 6);
877 memcpy(trailer + BPLIST_TRL_OFFSIZE_IDX, &offset_size, sizeof(uint8_t)); 908
878 memcpy(trailer + BPLIST_TRL_PARMSIZE_IDX, &dict_param_size, sizeof(uint8_t)); 909 //setup trailer
879 memcpy(trailer + BPLIST_TRL_NUMOBJ_IDX, &num_objects, sizeof(uint64_t)); 910 num_objects = GUINT64_FROM_BE(num_objects);
880 memcpy(trailer + BPLIST_TRL_ROOTOBJ_IDX, &root_object, sizeof(uint64_t)); 911 root_object = GUINT64_FROM_BE(root_object);
881 memcpy(trailer + BPLIST_TRL_OFFTAB_IDX, &offset_table_index, sizeof(uint64_t)); 912 offset_table_index = GUINT64_FROM_BE(offset_table_index);
882 913
883 g_byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE); 914 memcpy(trailer + BPLIST_TRL_OFFSIZE_IDX, &offset_size, sizeof(uint8_t));
884 915 memcpy(trailer + BPLIST_TRL_PARMSIZE_IDX, &dict_param_size, sizeof(uint8_t));
885 //duplicate buffer 916 memcpy(trailer + BPLIST_TRL_NUMOBJ_IDX, &num_objects, sizeof(uint64_t));
886 *plist_bin = (char *) malloc(bplist_buff->len); 917 memcpy(trailer + BPLIST_TRL_ROOTOBJ_IDX, &root_object, sizeof(uint64_t));
887 memcpy(*plist_bin, bplist_buff->data, bplist_buff->len); 918 memcpy(trailer + BPLIST_TRL_OFFTAB_IDX, &offset_table_index, sizeof(uint64_t));
888 *length = bplist_buff->len; 919
889 920 g_byte_array_append(bplist_buff, trailer, BPLIST_TRL_SIZE);
890 g_byte_array_free(bplist_buff, TRUE); 921
891 free(offsets); 922 //duplicate buffer
923 *plist_bin = (char *) malloc(bplist_buff->len);
924 memcpy(*plist_bin, bplist_buff->data, bplist_buff->len);
925 *length = bplist_buff->len;
926
927 g_byte_array_free(bplist_buff, TRUE);
928 free(offsets);
892} 929}