diff options
| -rw-r--r-- | dev/plutil.c | 87 | ||||
| -rw-r--r-- | src/plist.c | 799 | ||||
| -rw-r--r-- | src/plist.h | 48 |
3 files changed, 451 insertions, 483 deletions
diff --git a/dev/plutil.c b/dev/plutil.c index d1c3ddd..d1f1cd4 100644 --- a/dev/plutil.c +++ b/dev/plutil.c | |||
| @@ -10,85 +10,6 @@ | |||
| 10 | #include <stdio.h> | 10 | #include <stdio.h> |
| 11 | #include <stdlib.h> | 11 | #include <stdlib.h> |
| 12 | 12 | ||
| 13 | void print_nodes(bplist_node * root_node) | ||
| 14 | { | ||
| 15 | // Yay, great. Let's print the list of nodes recursively... | ||
| 16 | int i = 0; | ||
| 17 | if (!root_node) | ||
| 18 | return; // or not, because the programmer's stupid. | ||
| 19 | |||
| 20 | switch (root_node->type) { | ||
| 21 | case BPLIST_DICT: | ||
| 22 | printf("Dictionary node.\nLength %lu\n", (long unsigned int) root_node->length); | ||
| 23 | for (i = 0; i < (root_node->length * 2); i += 2) { | ||
| 24 | // HI! | ||
| 25 | printf("Key: "); | ||
| 26 | print_nodes(root_node->subnodes[i]); | ||
| 27 | printf("Value: "); | ||
| 28 | print_nodes(root_node->subnodes[i + 1]); | ||
| 29 | } | ||
| 30 | printf("End dictionary node.\n\n"); | ||
| 31 | break; | ||
| 32 | |||
| 33 | case BPLIST_ARRAY: | ||
| 34 | printf("Array node.\n"); | ||
| 35 | for (i = 0; i < root_node->length; i++) { | ||
| 36 | printf("\tElement %i: ", i); | ||
| 37 | print_nodes(root_node->subnodes[i]); | ||
| 38 | } | ||
| 39 | break; | ||
| 40 | |||
| 41 | case BPLIST_INT: | ||
| 42 | if (root_node->length == sizeof(uint8_t)) { | ||
| 43 | printf("Integer: %i\n", root_node->intval8); | ||
| 44 | } else if (root_node->length == sizeof(uint16_t)) { | ||
| 45 | printf("Integer: %i\n", root_node->intval16); | ||
| 46 | } else if (root_node->length == sizeof(uint32_t)) { | ||
| 47 | printf("Integer: %i\n", root_node->intval32); | ||
| 48 | } | ||
| 49 | break; | ||
| 50 | |||
| 51 | case BPLIST_STRING: | ||
| 52 | printf("String: "); | ||
| 53 | fwrite(root_node->strval, sizeof(char), root_node->length, stdout); | ||
| 54 | fflush(stdout); | ||
| 55 | printf("\n"); | ||
| 56 | break; | ||
| 57 | |||
| 58 | case BPLIST_DATA: | ||
| 59 | printf("Data: "); | ||
| 60 | char *data = g_base64_encode(root_node->strval, root_node->length); | ||
| 61 | fwrite(format_string(data, 60, 0), sizeof(char), strlen(data), stdout); | ||
| 62 | fflush(stdout); | ||
| 63 | printf("\n"); | ||
| 64 | break; | ||
| 65 | |||
| 66 | case BPLIST_UNICODE: | ||
| 67 | printf("Unicode data, may appear crappy: "); | ||
| 68 | fwrite(root_node->unicodeval, sizeof(wchar_t), root_node->length, stdout); | ||
| 69 | fflush(stdout); | ||
| 70 | printf("\n"); | ||
| 71 | break; | ||
| 72 | |||
| 73 | case BPLIST_TRUE: | ||
| 74 | printf("True.\n"); | ||
| 75 | break; | ||
| 76 | |||
| 77 | case BPLIST_FALSE: | ||
| 78 | printf("False.\n"); | ||
| 79 | break; | ||
| 80 | |||
| 81 | case BPLIST_REAL: | ||
| 82 | case BPLIST_DATE: | ||
| 83 | printf("Real(?): %f\n", root_node->realval); | ||
| 84 | break; | ||
| 85 | |||
| 86 | default: | ||
| 87 | printf("oops\nType set to %x and length is %lu\n", root_node->type, (long unsigned int) root_node->length); | ||
| 88 | break; | ||
| 89 | } | ||
| 90 | } | ||
| 91 | |||
| 92 | int main(int argc, char *argv[]) | 13 | int main(int argc, char *argv[]) |
| 93 | { | 14 | { |
| 94 | struct stat *filestats = (struct stat *) malloc(sizeof(struct stat)); | 15 | struct stat *filestats = (struct stat *) malloc(sizeof(struct stat)); |
| @@ -117,15 +38,17 @@ int main(int argc, char *argv[]) | |||
| 117 | fclose(bplist); | 38 | fclose(bplist); |
| 118 | printf("or here?\n"); | 39 | printf("or here?\n"); |
| 119 | // bplist_entire contains our stuff | 40 | // bplist_entire contains our stuff |
| 120 | bplist_node *root_node; | 41 | plist_t root_node = NULL; |
| 121 | root_node = parse_nodes(bplist_entire, filestats->st_size, &position); | 42 | bin_to_plist(bplist_entire, filestats->st_size, &root_node); |
| 122 | printf("plutil debug mode\n\n"); | 43 | printf("plutil debug mode\n\n"); |
| 123 | printf("file size %i\n\n", (int) filestats->st_size); | 44 | printf("file size %i\n\n", (int) filestats->st_size); |
| 124 | if (!root_node) { | 45 | if (!root_node) { |
| 125 | printf("Invalid binary plist (or some other error occurred.)\n"); | 46 | printf("Invalid binary plist (or some other error occurred.)\n"); |
| 126 | return 0; | 47 | return 0; |
| 127 | } | 48 | } |
| 128 | print_nodes(root_node); | 49 | char *plist_xml = NULL; |
| 50 | plist_to_xml(root_node, &plist_xml); | ||
| 51 | printf("%s\n", plist_xml); | ||
| 129 | return 0; | 52 | return 0; |
| 130 | } | 53 | } |
| 131 | 54 | ||
diff --git a/src/plist.c b/src/plist.c index 1553c1c..377646d 100644 --- a/src/plist.c +++ b/src/plist.c | |||
| @@ -25,6 +25,7 @@ | |||
| 25 | #include <assert.h> | 25 | #include <assert.h> |
| 26 | #include "utils.h" | 26 | #include "utils.h" |
| 27 | #include "plist.h" | 27 | #include "plist.h" |
| 28 | #include <wchar.h> | ||
| 28 | 29 | ||
| 29 | 30 | ||
| 30 | const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ | 31 | const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\ |
| @@ -285,147 +286,7 @@ void byte_convert(char *address, size_t size) | |||
| 285 | } | 286 | } |
| 286 | } | 287 | } |
| 287 | 288 | ||
| 288 | bplist_node *parse_raw_node(const char *bpbuffer, uint32_t bplength, uint32_t * position, uint8_t ref_size) | ||
| 289 | { | ||
| 290 | if (!position || !bpbuffer || !bplength) | ||
| 291 | return NULL; | ||
| 292 | |||
| 293 | uint8_t modifier = 0; | ||
| 294 | bplist_node *new_node = (bplist_node *) malloc(sizeof(bplist_node)); | ||
| 295 | bplist_node *length_stupidity = NULL; | ||
| 296 | memset(new_node, 0, sizeof(bplist_node)); // initialize the new struct | ||
| 297 | |||
| 298 | int myPos = *position; | ||
| 299 | if (myPos == bplength || (myPos + 1) == bplength) { | ||
| 300 | free(new_node); | ||
| 301 | return NULL; | ||
| 302 | } // end of string | ||
| 303 | |||
| 304 | uint32_t length = 0; | ||
| 305 | if (!myPos) { | ||
| 306 | if (strncmp(bpbuffer, "bplist00", strlen("bplist00"))) { | ||
| 307 | return NULL; // badness! | ||
| 308 | } | ||
| 309 | myPos += strlen("bplist00"); | ||
| 310 | } | ||
| 311 | // Get the node's type. | ||
| 312 | if (bpbuffer[myPos] == BPLIST_DATE) { // handle date separately, but do it as a real | ||
| 313 | // better handling of date; basically interpret as real or double | ||
| 314 | new_node->type = BPLIST_DATE; | ||
| 315 | new_node->length = 8; // always 8 for "date" (Apple intended it, not me) | ||
| 316 | myPos++; | ||
| 317 | memcpy(&new_node->realval, bpbuffer + myPos, sizeof(new_node->realval)); | ||
| 318 | byte_convert((char *) &new_node->realval, sizeof(new_node->realval)); | ||
| 319 | myPos += new_node->length; | ||
| 320 | *position = myPos; | ||
| 321 | return new_node; | ||
| 322 | } | ||
| 323 | |||
| 324 | new_node->type = bpbuffer[myPos] & BPLIST_MASK; | ||
| 325 | new_node->length = bpbuffer[myPos] & BPLIST_FILL; | ||
| 326 | if (!new_node->type) { | ||
| 327 | // what? check if it's a boolean. | ||
| 328 | if (bpbuffer[myPos] == BPLIST_TRUE || bpbuffer[myPos] == BPLIST_FALSE) { | ||
| 329 | // okay, so it is. Carry on. | ||
| 330 | new_node->type = bpbuffer[myPos]; | ||
| 331 | new_node->length = 0; | ||
| 332 | } else { | ||
| 333 | // er, what? we have a bad type here. Return NULL. | ||
| 334 | free(new_node); | ||
| 335 | //printf("parse_raw_node: lol type: type given %x\n", bpbuffer[myPos]); | ||
| 336 | return NULL; | ||
| 337 | } | ||
| 338 | } | ||
| 339 | |||
| 340 | myPos++; // puts us in the data. | ||
| 341 | if (new_node->length == BPLIST_FILL) { // Data happens to contain length... | ||
| 342 | // what? you're going to make me parse an int for the length. You suck. | ||
| 343 | *position = myPos; | ||
| 344 | length_stupidity = parse_raw_node(bpbuffer, bplength, &myPos, ref_size); | ||
| 345 | switch (length_stupidity->length) { | ||
| 346 | case sizeof(uint8_t): | ||
| 347 | new_node->length = length_stupidity->intval8; | ||
| 348 | break; | ||
| 349 | case sizeof(uint16_t): | ||
| 350 | new_node->length = length_stupidity->intval16; | ||
| 351 | break; | ||
| 352 | case sizeof(uint32_t): | ||
| 353 | new_node->length = length_stupidity->intval32; | ||
| 354 | break; | ||
| 355 | case sizeof(uint64_t): | ||
| 356 | new_node->length = length_stupidity->intval64; | ||
| 357 | break; | ||
| 358 | default: | ||
| 359 | free(new_node); | ||
| 360 | free(length_stupidity); | ||
| 361 | return NULL; | ||
| 362 | } | ||
| 363 | // There, we have our fucking length now. | ||
| 364 | *position = myPos; | ||
| 365 | free(length_stupidity); // cleanup | ||
| 366 | } | ||
| 367 | // Now we're in the data. | ||
| 368 | // Error-checking sorta | ||
| 369 | if ((myPos + new_node->length) >= bplength) { | ||
| 370 | new_node->length = bplength - myPos; // truncate the object | ||
| 371 | } | ||
| 372 | // And now for the greatest show on earth: the giant fucking switch statement. | ||
| 373 | switch (new_node->type) { | ||
| 374 | case BPLIST_INT: | ||
| 375 | new_node->length = uipow(2, new_node->length); // make length less misleading | ||
| 376 | switch (new_node->length) { | ||
| 377 | case sizeof(uint8_t): | ||
| 378 | new_node->intval8 = bpbuffer[myPos]; | ||
| 379 | break; | ||
| 380 | case sizeof(uint16_t): | ||
| 381 | memcpy(&new_node->intval16, bpbuffer + myPos, sizeof(uint16_t)); | ||
| 382 | new_node->intval16 = ntohs(new_node->intval16); | ||
| 383 | break; | ||
| 384 | case sizeof(uint32_t): | ||
| 385 | memcpy(&new_node->intval32, bpbuffer + myPos, sizeof(uint32_t)); | ||
| 386 | new_node->intval32 = ntohl(new_node->intval32); | ||
| 387 | break; | ||
| 388 | case sizeof(uint64_t): | ||
| 389 | memcpy(&new_node->intval64, bpbuffer + myPos, sizeof(uint64_t)); | ||
| 390 | byte_convert((char *) &new_node->intval64, sizeof(uint64_t)); | ||
| 391 | break; | ||
| 392 | default: | ||
| 393 | free(new_node); | ||
| 394 | printf("parse_raw_node: lol: invalid int: size given %lu\n", (long unsigned int) new_node->length); | ||
| 395 | printf("parse_raw_node: lol: by the way sizeof(uint64) = %i\n", sizeof(uint64_t)); | ||
| 396 | return NULL; | ||
| 397 | } | ||
| 398 | break; | ||
| 399 | 289 | ||
| 400 | case BPLIST_REAL: | ||
| 401 | new_node->length = uipow(2, new_node->length); | ||
| 402 | memcpy(&new_node->realval, bpbuffer + myPos, new_node->length); // XXX: probable buffer overflow here | ||
| 403 | //new_node->realval = bpbuffer[myPos]; // why not | ||
| 404 | byte_convert((char *) &new_node->realval, sizeof(double)); | ||
| 405 | break; | ||
| 406 | |||
| 407 | case BPLIST_DICT: /* returning a raw dict, it forward-references, so. */ | ||
| 408 | new_node->length = new_node->length * 2; // dicts lie | ||
| 409 | case BPLIST_ARRAY: /* returning a raw array, it forward-references, so. */ | ||
| 410 | new_node->intval8 = ref_size; // in arrays and dicts, the "ref size" alluded to in the trailer applies, and should be stored in intval8 so as to save space. | ||
| 411 | case BPLIST_STRING: | ||
| 412 | case BPLIST_DATA: | ||
| 413 | default: /* made to hold raw data. */ | ||
| 414 | modifier = (new_node->intval8 > 0) ? new_node->intval8 : 1; | ||
| 415 | new_node->strval = (char *) malloc(sizeof(char) * (new_node->length * modifier)); | ||
| 416 | memcpy(new_node->strval, bpbuffer + myPos, (new_node->length * modifier)); | ||
| 417 | break; | ||
| 418 | |||
| 419 | case BPLIST_UNICODE: | ||
| 420 | new_node->unicodeval = (wchar_t *) malloc(sizeof(wchar_t) * new_node->length); | ||
| 421 | memcpy(new_node->unicodeval, bpbuffer + myPos, new_node->length); | ||
| 422 | break; | ||
| 423 | } | ||
| 424 | |||
| 425 | myPos += new_node->length; | ||
| 426 | *position = myPos; | ||
| 427 | return new_node; | ||
| 428 | } | ||
| 429 | 290 | ||
| 430 | void print_bytes(char *val, size_t size) | 291 | void print_bytes(char *val, size_t size) |
| 431 | { | 292 | { |
| @@ -435,180 +296,123 @@ void print_bytes(char *val, size_t size) | |||
| 435 | } | 296 | } |
| 436 | } | 297 | } |
| 437 | 298 | ||
| 438 | bplist_node *parse_nodes(const char *bpbuffer, uint32_t bplength, uint32_t * position) | ||
| 439 | { | ||
| 440 | bplist_node **nodeslist = NULL, **newaddr = NULL; | ||
| 441 | bplist_node *new_node = NULL, *root_node = NULL; | ||
| 442 | |||
| 443 | uint32_t nodeslength = 0; | ||
| 444 | uint8_t offset_size = 0, dict_param_size = 0; | ||
| 445 | offset_size = bpbuffer[bplength - 26]; | ||
| 446 | dict_param_size = bpbuffer[bplength - 25]; | ||
| 447 | uint64_t current_offset = 0; | ||
| 448 | //uint64_t num_objects = *(bpbuffer+(bplength-24)), root_object = *(bpbuffer+(bplength-16)), offset_table_index = *(bpbuffer+(bplength-8)); | ||
| 449 | uint64_t num_objects = 0, root_object = 0, offset_table_index = 0; | ||
| 450 | memcpy(&num_objects, bpbuffer + bplength - 24, sizeof(uint64_t)); | ||
| 451 | memcpy(&root_object, bpbuffer + bplength - 16, sizeof(uint64_t)); | ||
| 452 | memcpy(&offset_table_index, bpbuffer + bplength - 8, sizeof(uint64_t)); | ||
| 453 | byte_convert((char *) &num_objects, sizeof(uint64_t)); | ||
| 454 | byte_convert((char *) &root_object, sizeof(uint64_t)); | ||
| 455 | byte_convert((char *) &offset_table_index, sizeof(uint64_t)); | ||
| 456 | |||
| 457 | log_debug_msg("Offset size: %i\nGiven: %i\n", offset_size, bpbuffer[bplength - 26]); | ||
| 458 | log_debug_msg("Ref size: %i\nGiven: %i\n", dict_param_size, bpbuffer[bplength - 25]); | ||
| 459 | log_debug_msg("Number of objects: %lli\nGiven: %llu\n", num_objects, *(bpbuffer + bplength - 24)); | ||
| 460 | log_debug_msg("Root object index: %lli\nGiven: %llu\n", root_object, *(bpbuffer + bplength - 16)); | ||
| 461 | log_debug_msg("Offset table index: %lli\nGiven: %llu\n", offset_table_index, *(bpbuffer + bplength - 8)); | ||
| 462 | log_debug_msg("Size of uint64: %i\n", sizeof(uint64_t)); | ||
| 463 | |||
| 464 | int i = 0, j = 0, k = 0, str_i = 0, str_j = 0; | ||
| 465 | uint32_t index1 = 0, index2 = 0; | ||
| 466 | |||
| 467 | nodeslist = (bplist_node **) malloc(sizeof(bplist_node *) * num_objects); | ||
| 468 | if (!nodeslist) | ||
| 469 | return NULL; | ||
| 470 | |||
| 471 | for (i = 0; i < num_objects; i++) { | ||
| 472 | memcpy(¤t_offset, bpbuffer + (offset_table_index + (i * offset_size)), offset_size); | ||
| 473 | //current_offset = (offset_size == 2) ? ntohs(current_offset) : (offset_size == 4) ? ntohl(current_offset) : current_offset; | ||
| 474 | //if (offset_size == 8) byte_convert(¤t_offset, 8); | ||
| 475 | byte_convert((char *) ¤t_offset, | ||
| 476 | (offset_size <= sizeof(current_offset)) ? offset_size : sizeof(current_offset)); | ||
| 477 | log_debug_msg("parse_nodes: current_offset = %x\n", current_offset); | ||
| 478 | nodeslist[i] = parse_raw_node(bpbuffer, bplength, (uint32_t *) & current_offset, dict_param_size); | ||
| 479 | log_debug_msg("parse_nodes: parse_raw_node done\n"); | ||
| 480 | } | ||
| 481 | |||
| 482 | |||
| 483 | for (i = 0; i < num_objects; i++) { | ||
| 484 | // set elements for dicts and arrays and leave the rest alone | ||
| 485 | log_debug_msg("parse_nodes: on node %i\n", i); | ||
| 486 | switch (nodeslist[i]->type) { | ||
| 487 | case BPLIST_DICT: | ||
| 488 | log_debug_msg("parse_nodes: dictionary found\n"); | ||
| 489 | nodeslist[i]->subnodes = (bplist_node **) malloc(sizeof(bplist_node) * nodeslist[i]->length); | ||
| 490 | for (j = 0; j < (nodeslist[i]->length / 2); j++) { | ||
| 491 | str_i = j * nodeslist[i]->intval8; | ||
| 492 | str_j = (j + (nodeslist[i]->length / 2)) * nodeslist[i]->intval8; | ||
| 493 | |||
| 494 | memcpy(&index1, nodeslist[i]->strval + str_i, nodeslist[i]->intval8); | ||
| 495 | memcpy(&index2, nodeslist[i]->strval + str_j, nodeslist[i]->intval8); | ||
| 496 | //index1 = (dict_param_size == 1) ? index1 : (dict_param_size == 2) ? ntohs(index1) : (dict_param_size == 4) ? ntohl(index1) : index1; | ||
| 497 | //index2 = (dict_param_size == 1) ? index2 : (dict_param_size == 2) ? ntohs(index2) : (dict_param_size == 4) ? ntohl(index2) : index2; | ||
| 498 | byte_convert((char *) &index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index2)); | ||
| 499 | byte_convert((char *) &index2, (dict_param_size <= sizeof(index2)) ? dict_param_size : sizeof(index2)); | ||
| 500 | //printf("parse_nodes: key index %i value %i\n", index1, index2); | ||
| 501 | //printf("parse_nodes: key type %x and length %i\n", nodeslist[index1]->type, nodeslist[index1]->length); | ||
| 502 | //printf("parse_nodes: value type %x and length %i\n", nodeslist[index2]->type, nodeslist[index2]->length); | ||
| 503 | nodeslist[i]->subnodes[k++] = nodeslist[index1]; | ||
| 504 | nodeslist[i]->subnodes[k++] = nodeslist[index2]; | ||
| 505 | } | ||
| 506 | |||
| 507 | nodeslist[i]->length = nodeslist[i]->length / 2; | ||
| 508 | free(nodeslist[i]->strval); | ||
| 509 | k = 0; | ||
| 510 | break; | ||
| 511 | |||
| 512 | case BPLIST_ARRAY: | ||
| 513 | log_debug_msg("parse_nodes: array found\n"); | ||
| 514 | nodeslist[i]->subnodes = (bplist_node **) malloc(sizeof(bplist_node) * nodeslist[i]->length); // memory allocation helps a lot when storing data | ||
| 515 | |||
| 516 | for (j = 0; j < nodeslist[i]->length; j++) { | ||
| 517 | log_debug_msg("parse_nodes: array index %i\n", j); | ||
| 518 | str_j = j * nodeslist[i]->intval8; | ||
| 519 | //index1 = nodeslist[i]->strval[j]; | ||
| 520 | memcpy(&index1, nodeslist[i]->strval + str_j, nodeslist[i]->intval8); | ||
| 521 | log_debug_msg("parse_nodes: post-memcpy\n"); | ||
| 522 | //index1 = (dict_param_size == 1) ? index1 : (dict_param_size == 2) ? ntohs(index1) : (dict_param_size == 4) ? ntohl(index1) : index1; | ||
| 523 | byte_convert((char *) &index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index1)); | ||
| 524 | log_debug_msg("parse_nodes: post-ntohl\nindex1 = %i\n", index1); | ||
| 525 | nodeslist[i]->subnodes[j] = nodeslist[index1]; | ||
| 526 | log_debug_msg("parse_nodes: post-assignment\n"); | ||
| 527 | } | ||
| 528 | free(nodeslist[i]->strval); | ||
| 529 | break; | ||
| 530 | default: | ||
| 531 | //printf("lol... type %x\n", nodeslist[i]->type); | ||
| 532 | break; | ||
| 533 | } // those are the only two we need to correct for. | ||
| 534 | } | ||
| 535 | 299 | ||
| 536 | root_node = nodeslist[root_object]; | ||
| 537 | return root_node; | ||
| 538 | } | ||
| 539 | 300 | ||
| 540 | struct plist_data { | 301 | struct plist_data { |
| 541 | union { | 302 | union { |
| 542 | char boolval; | 303 | char boolval; |
| 543 | uint8_t intval8; | 304 | uint8_t intval8; |
| 544 | uint16_t intval16; | 305 | uint16_t intval16; |
| 545 | uint32_t intval32; | 306 | uint32_t intval32; |
| 546 | uint64_t intval64; | 307 | uint64_t intval64; |
| 547 | float realval32; | 308 | float realval32; |
| 548 | double realval64; | 309 | double realval64; |
| 549 | char *strval; | 310 | char *strval; |
| 550 | wchar_t *unicodeval; | 311 | wchar_t *unicodeval; |
| 551 | char *buff; | 312 | struct { |
| 313 | char *buff; | ||
| 314 | uint8_t ref_size; | ||
| 315 | }; | ||
| 552 | }; | 316 | }; |
| 553 | int index; | 317 | uint64_t length; |
| 554 | plist_type type; | 318 | plist_type type; |
| 555 | }; | 319 | }; |
| 556 | 320 | ||
| 557 | void plist_new_plist(plist_t* plist) | 321 | enum { |
| 322 | BPLIST_TRUE = 0x08, | ||
| 323 | BPLIST_FALSE = 0x09, | ||
| 324 | BPLIST_FILL = 0x0F, /* will be used for length grabbing */ | ||
| 325 | BPLIST_INT = 0x10, | ||
| 326 | BPLIST_REAL = 0x20, | ||
| 327 | BPLIST_DATE = 0x33, | ||
| 328 | BPLIST_DATA = 0x40, | ||
| 329 | BPLIST_STRING = 0x50, | ||
| 330 | BPLIST_UNICODE = 0x60, | ||
| 331 | BPLIST_UID = 0x70, | ||
| 332 | BPLIST_ARRAY = 0xA0, | ||
| 333 | BPLIST_SET = 0xC0, | ||
| 334 | BPLIST_DICT = 0xD0, | ||
| 335 | BPLIST_MASK = 0xF0 | ||
| 336 | }; | ||
| 337 | |||
| 338 | void plist_new_plist(plist_t * plist) | ||
| 558 | { | 339 | { |
| 559 | if (*plist != NULL) return; | 340 | if (*plist != NULL) |
| 560 | struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1); | 341 | return; |
| 342 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); | ||
| 561 | data->type = PLIST_PLIST; | 343 | data->type = PLIST_PLIST; |
| 562 | *plist = g_node_new (data); | 344 | *plist = g_node_new(data); |
| 563 | } | 345 | } |
| 564 | 346 | ||
| 565 | void plist_new_dict_in_plist(plist_t plist, dict_t* dict) | 347 | void plist_new_dict_in_plist(plist_t plist, dict_t * dict) |
| 566 | { | 348 | { |
| 567 | if (!plist || *dict) return; | 349 | if (!plist || *dict) |
| 350 | return; | ||
| 568 | 351 | ||
| 569 | struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1); | 352 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); |
| 570 | data->type = PLIST_DICT; | 353 | data->type = PLIST_DICT; |
| 571 | *dict = g_node_new (data); | 354 | *dict = g_node_new(data); |
| 572 | g_node_append(plist, *dict); | 355 | g_node_append(plist, *dict); |
| 573 | } | 356 | } |
| 574 | 357 | ||
| 575 | void plist_new_array_in_plist(plist_t plist, int length, plist_type type, void** values, array_t* array) | 358 | void plist_new_array_in_plist(plist_t plist, int length, plist_type type, void **values, array_t * array) |
| 576 | { | 359 | { |
| 577 | } | 360 | } |
| 578 | 361 | ||
| 579 | void plist_add_dict_element(dict_t dict, char* key, plist_type type, void* value) | 362 | void plist_add_dict_element(dict_t dict, char *key, plist_type type, void *value) |
| 580 | { | 363 | { |
| 581 | if (!dict || !key || !value) return; | 364 | if (!dict || !key || !value) |
| 365 | return; | ||
| 582 | 366 | ||
| 583 | struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1); | 367 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); |
| 584 | data->type = PLIST_KEY; | 368 | data->type = PLIST_KEY; |
| 585 | data->strval = strdup(key); | 369 | data->strval = strdup(key); |
| 586 | GNode* keynode = g_node_new (data); | 370 | GNode *keynode = g_node_new(data); |
| 587 | g_node_append(dict, keynode); | 371 | g_node_append(dict, keynode); |
| 588 | 372 | ||
| 589 | //now handle value | 373 | //now handle value |
| 590 | struct plist_data* val = (struct plist_data*)calloc(sizeof(struct plist_data), 1); | 374 | struct plist_data *val = (struct plist_data *) calloc(sizeof(struct plist_data), 1); |
| 591 | val->type = type; | 375 | val->type = type; |
| 592 | 376 | ||
| 593 | switch (type) { | 377 | switch (type) { |
| 594 | case PLIST_BOOLEAN : val->boolval = *((char*)value); break; | 378 | case PLIST_BOOLEAN: |
| 595 | case PLIST_UINT8 : val->intval8 = *((uint8_t*)value); break; | 379 | val->boolval = *((char *) value); |
| 596 | case PLIST_UINT16 : val->intval16 = *((uint16_t*)value); break; | 380 | break; |
| 597 | case PLIST_UINT32 : val->intval32 = *((uint32_t*)value); break; | 381 | case PLIST_UINT8: |
| 598 | case PLIST_UINT64 : val->intval64 = *((uint64_t*)value); break; | 382 | val->intval8 = *((uint8_t *) value); |
| 599 | case PLIST_FLOAT32 : val->realval32 = *((float*)value); break; | 383 | break; |
| 600 | case PLIST_FLOAT64 : val->realval64 = *((double*)value); break; | 384 | case PLIST_UINT16: |
| 601 | case PLIST_STRING : val->strval = strdup((char*) value); break; | 385 | val->intval16 = *((uint16_t *) value); |
| 602 | case PLIST_UNICODE : val->unicodeval = wcsdup((wchar_t*) value); break; | 386 | break; |
| 603 | case PLIST_DATA : val->buff = strdup((char*) value); break; | 387 | case PLIST_UINT32: |
| 604 | case PLIST_ARRAY : | 388 | val->intval32 = *((uint32_t *) value); |
| 605 | case PLIST_DICT : | 389 | break; |
| 606 | case PLIST_DATE : | 390 | case PLIST_UINT64: |
| 607 | case PLIST_PLIST : | 391 | val->intval64 = *((uint64_t *) value); |
| 608 | default: | 392 | break; |
| 609 | break; | 393 | case PLIST_FLOAT32: |
| 394 | val->realval32 = *((float *) value); | ||
| 395 | break; | ||
| 396 | case PLIST_FLOAT64: | ||
| 397 | val->realval64 = *((double *) value); | ||
| 398 | break; | ||
| 399 | case PLIST_STRING: | ||
| 400 | val->strval = strdup((char *) value); | ||
| 401 | break; | ||
| 402 | case PLIST_UNICODE: | ||
| 403 | val->unicodeval = wcsdup((wchar_t *) value); | ||
| 404 | break; | ||
| 405 | case PLIST_DATA: | ||
| 406 | val->buff = strdup((char *) value); | ||
| 407 | break; | ||
| 408 | case PLIST_ARRAY: | ||
| 409 | case PLIST_DICT: | ||
| 410 | case PLIST_DATE: | ||
| 411 | case PLIST_PLIST: | ||
| 412 | default: | ||
| 413 | break; | ||
| 610 | } | 414 | } |
| 611 | GNode* valnode = g_node_new (val); | 415 | GNode *valnode = g_node_new(val); |
| 612 | g_node_append(dict, valnode); | 416 | g_node_append(dict, valnode); |
| 613 | } | 417 | } |
| 614 | 418 | ||
| @@ -617,97 +421,98 @@ void plist_free(plist_t plist) | |||
| 617 | g_node_destroy(plist); | 421 | g_node_destroy(plist); |
| 618 | } | 422 | } |
| 619 | 423 | ||
| 620 | void node_to_xml (GNode *node, gpointer data) | 424 | void node_to_xml(GNode * node, gpointer data) |
| 621 | { | 425 | { |
| 622 | if (!node) return; | 426 | if (!node) |
| 427 | return; | ||
| 623 | 428 | ||
| 624 | struct plist_data* node_data = (struct plist_data*)node->data; | 429 | struct plist_data *node_data = (struct plist_data *) node->data; |
| 625 | 430 | ||
| 626 | xmlNodePtr child_node = NULL; | 431 | xmlNodePtr child_node = NULL; |
| 627 | char isStruct = FALSE; | 432 | char isStruct = FALSE; |
| 628 | 433 | ||
| 629 | gchar* tag = NULL; | 434 | gchar *tag = NULL; |
| 630 | gchar* val = NULL; | 435 | gchar *val = NULL; |
| 631 | 436 | ||
| 632 | switch (node_data->type) { | 437 | switch (node_data->type) { |
| 633 | case PLIST_BOOLEAN : | 438 | case PLIST_BOOLEAN: |
| 634 | { | 439 | { |
| 635 | if (node_data->boolval) | 440 | if (node_data->boolval) |
| 636 | tag = "true"; | 441 | tag = "true"; |
| 637 | else | 442 | else |
| 638 | tag = "false"; | 443 | tag = "false"; |
| 639 | } | 444 | } |
| 640 | break; | 445 | break; |
| 641 | 446 | ||
| 642 | case PLIST_UINT8 : | 447 | case PLIST_UINT8: |
| 643 | tag = "integer"; | 448 | tag = "integer"; |
| 644 | val = g_strdup_printf("%u", node_data->intval8); | 449 | val = g_strdup_printf("%u", node_data->intval8); |
| 645 | break; | 450 | break; |
| 646 | 451 | ||
| 647 | case PLIST_UINT16 : | 452 | case PLIST_UINT16: |
| 648 | tag = "integer"; | 453 | tag = "integer"; |
| 649 | val = g_strdup_printf("%u", node_data->intval16); | 454 | val = g_strdup_printf("%u", node_data->intval16); |
| 650 | break; | 455 | break; |
| 651 | 456 | ||
| 652 | case PLIST_UINT32 : | 457 | case PLIST_UINT32: |
| 653 | tag = "integer"; | 458 | tag = "integer"; |
| 654 | val = g_strdup_printf("%u", node_data->intval32); | 459 | val = g_strdup_printf("%u", node_data->intval32); |
| 655 | break; | 460 | break; |
| 656 | 461 | ||
| 657 | case PLIST_UINT64 : | 462 | case PLIST_UINT64: |
| 658 | tag = "integer"; | 463 | tag = "integer"; |
| 659 | val = g_strdup_printf("%lu", (long unsigned int)node_data->intval64); | 464 | val = g_strdup_printf("%lu", (long unsigned int) node_data->intval64); |
| 660 | break; | 465 | break; |
| 661 | 466 | ||
| 662 | case PLIST_FLOAT32 : | 467 | case PLIST_FLOAT32: |
| 663 | tag = "real"; | 468 | tag = "real"; |
| 664 | val = g_strdup_printf("%f", node_data->realval32); | 469 | val = g_strdup_printf("%f", node_data->realval32); |
| 665 | break; | 470 | break; |
| 666 | 471 | ||
| 667 | case PLIST_FLOAT64 : | 472 | case PLIST_FLOAT64: |
| 668 | tag = "real"; | 473 | tag = "real"; |
| 669 | val = g_strdup_printf("%Lf", (long double)node_data->intval64); | 474 | val = g_strdup_printf("%Lf", (long double) node_data->intval64); |
| 670 | break; | 475 | break; |
| 671 | 476 | ||
| 672 | case PLIST_STRING : | 477 | case PLIST_STRING: |
| 673 | tag = "string"; | 478 | tag = "string"; |
| 674 | val = g_strdup(node_data->strval); | 479 | val = g_strdup(node_data->strval); |
| 675 | break; | 480 | break; |
| 676 | 481 | ||
| 677 | case PLIST_UNICODE : | 482 | case PLIST_UNICODE: |
| 678 | tag = "string"; | 483 | tag = "string"; |
| 679 | val = g_strdup((gchar*)node_data->unicodeval); | 484 | val = g_strdup((gchar *) node_data->unicodeval); |
| 680 | break; | 485 | break; |
| 681 | 486 | ||
| 682 | case PLIST_KEY : | 487 | case PLIST_KEY: |
| 683 | tag = "key"; | 488 | tag = "key"; |
| 684 | val = g_strdup((gchar*)node_data->strval); | 489 | val = g_strdup((gchar *) node_data->strval); |
| 685 | break; | 490 | break; |
| 686 | 491 | ||
| 687 | case PLIST_DATA : | 492 | case PLIST_DATA: |
| 688 | tag = "data"; | 493 | tag = "data"; |
| 689 | val = format_string(node_data->buff, 60, 0); | 494 | val = format_string(node_data->buff, 60, 0); |
| 690 | break; | 495 | break; |
| 691 | case PLIST_ARRAY : | 496 | case PLIST_ARRAY: |
| 692 | tag = "array"; | 497 | tag = "array"; |
| 693 | isStruct = TRUE; | 498 | isStruct = TRUE; |
| 694 | break; | 499 | break; |
| 695 | case PLIST_DICT : | 500 | case PLIST_DICT: |
| 696 | tag = "dict"; | 501 | tag = "dict"; |
| 697 | isStruct = TRUE; | 502 | isStruct = TRUE; |
| 698 | break; | 503 | break; |
| 699 | case PLIST_PLIST : | 504 | case PLIST_PLIST: |
| 700 | tag = "plist"; | 505 | tag = "plist"; |
| 701 | isStruct = TRUE; | 506 | isStruct = TRUE; |
| 702 | break; | 507 | break; |
| 703 | case PLIST_DATE : //TODO : handle date tag | 508 | case PLIST_DATE: //TODO : handle date tag |
| 704 | default: | 509 | default: |
| 705 | break; | 510 | break; |
| 706 | } | 511 | } |
| 707 | return; | ||
| 708 | 512 | ||
| 709 | child_node = xmlNewChild(data, NULL, tag, val); | 513 | child_node = xmlNewChild(data, NULL, tag, val); |
| 710 | gfree(val); | 514 | xmlNodeAddContent(child_node, "\n"); |
| 515 | g_free(val); | ||
| 711 | 516 | ||
| 712 | if (isStruct) | 517 | if (isStruct) |
| 713 | g_node_children_foreach(node, G_TRAVERSE_ALL, node_to_xml, child_node); | 518 | g_node_children_foreach(node, G_TRAVERSE_ALL, node_to_xml, child_node); |
| @@ -715,11 +520,11 @@ void node_to_xml (GNode *node, gpointer data) | |||
| 715 | return; | 520 | return; |
| 716 | } | 521 | } |
| 717 | 522 | ||
| 718 | void xml_to_node (xmlNodePtr xml_node, GNode *plist_node) | 523 | void xml_to_node(xmlNodePtr xml_node, GNode * plist_node) |
| 719 | { | 524 | { |
| 720 | xmlNodePtr node = NULL; | 525 | xmlNodePtr node = NULL; |
| 721 | struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1); | 526 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); |
| 722 | GNode* subnode = g_node_new (data); | 527 | GNode *subnode = g_node_new(data); |
| 723 | g_node_append(plist_node, subnode); | 528 | g_node_append(plist_node, subnode); |
| 724 | 529 | ||
| 725 | for (node = xml_node->children; node; node = node->next) { | 530 | for (node = xml_node->children; node; node = node->next) { |
| @@ -737,21 +542,21 @@ void xml_to_node (xmlNodePtr xml_node, GNode *plist_node) | |||
| 737 | } | 542 | } |
| 738 | 543 | ||
| 739 | if (!xmlStrcmp(node->name, "integer")) { | 544 | if (!xmlStrcmp(node->name, "integer")) { |
| 740 | char* strval = xmlNodeGetContent(node); | 545 | char *strval = xmlNodeGetContent(node); |
| 741 | data->intval64 = atoi(strval); | 546 | data->intval64 = atoi(strval); |
| 742 | data->type = PLIST_UINT64; | 547 | data->type = PLIST_UINT64; |
| 743 | continue; | 548 | continue; |
| 744 | } | 549 | } |
| 745 | 550 | ||
| 746 | if (!xmlStrcmp(node->name, "real")){ | 551 | if (!xmlStrcmp(node->name, "real")) { |
| 747 | char* strval = xmlNodeGetContent(node); | 552 | char *strval = xmlNodeGetContent(node); |
| 748 | data->realval64 = atof(strval); | 553 | data->realval64 = atof(strval); |
| 749 | data->type = PLIST_FLOAT64; | 554 | data->type = PLIST_FLOAT64; |
| 750 | continue; | 555 | continue; |
| 751 | } | 556 | } |
| 752 | 557 | ||
| 753 | if (!xmlStrcmp(node->name, "date")) | 558 | if (!xmlStrcmp(node->name, "date")) |
| 754 | continue;//TODO : handle date tag | 559 | continue; //TODO : handle date tag |
| 755 | 560 | ||
| 756 | if (!xmlStrcmp(node->name, "string")) { | 561 | if (!xmlStrcmp(node->name, "string")) { |
| 757 | data->strval = strdup(xmlNodeGetContent(node)); | 562 | data->strval = strdup(xmlNodeGetContent(node)); |
| @@ -773,45 +578,315 @@ void xml_to_node (xmlNodePtr xml_node, GNode *plist_node) | |||
| 773 | 578 | ||
| 774 | if (!xmlStrcmp(node->name, "array")) { | 579 | if (!xmlStrcmp(node->name, "array")) { |
| 775 | data->type = PLIST_ARRAY; | 580 | data->type = PLIST_ARRAY; |
| 776 | xml_to_node (node, subnode); | 581 | xml_to_node(node, subnode); |
| 777 | continue; | 582 | continue; |
| 778 | } | 583 | } |
| 779 | 584 | ||
| 780 | if (!xmlStrcmp(node->name, "dict")) { | 585 | if (!xmlStrcmp(node->name, "dict")) { |
| 781 | data->type = PLIST_DICT; | 586 | data->type = PLIST_DICT; |
| 782 | xml_to_node (node, subnode); | 587 | xml_to_node(node, subnode); |
| 783 | continue; | 588 | continue; |
| 784 | } | 589 | } |
| 785 | } | 590 | } |
| 786 | } | 591 | } |
| 787 | 592 | ||
| 788 | void plist_to_xml(plist_t plist, char** plist_xml) | 593 | void plist_to_xml(plist_t plist, char **plist_xml) |
| 789 | { | 594 | { |
| 790 | if (!plist || !plist_xml || *plist_xml) return; | 595 | if (!plist || !plist_xml || *plist_xml) |
| 596 | return; | ||
| 791 | xmlDocPtr plist_doc = new_plist(); | 597 | xmlDocPtr plist_doc = new_plist(); |
| 792 | xmlNodePtr root_node = xmlDocGetRootElement(plist_doc); | 598 | xmlNodePtr root_node = xmlDocGetRootElement(plist_doc); |
| 793 | g_node_children_foreach(plist, G_TRAVERSE_ALL, node_to_xml, root_node); | 599 | g_node_children_foreach(plist, G_TRAVERSE_ALL, node_to_xml, root_node); |
| 794 | int size = 0; | 600 | int size = 0; |
| 795 | xmlDocDumpMemory (plist_doc, (xmlChar**)plist_xml, &size); | 601 | xmlDocDumpMemory(plist_doc, (xmlChar **) plist_xml, &size); |
| 796 | } | 602 | } |
| 797 | 603 | ||
| 604 | GNode *parse_raw_node(const char *bpbuffer, uint32_t bplength, uint32_t * position, uint8_t ref_size) | ||
| 605 | { | ||
| 606 | if (!position || !bpbuffer || !bplength) | ||
| 607 | return NULL; | ||
| 608 | |||
| 609 | uint8_t modifier = 0; | ||
| 610 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); | ||
| 611 | GNode *new_node = g_node_new(data); | ||
| 612 | GNode *length_stupidity = NULL; | ||
| 613 | |||
| 614 | int myPos = *position; | ||
| 615 | if (myPos == bplength || (myPos + 1) == bplength) { | ||
| 616 | g_node_destroy(new_node); | ||
| 617 | return NULL; | ||
| 618 | } // end of string | ||
| 619 | |||
| 620 | uint32_t length = 0; | ||
| 621 | if (!myPos) { | ||
| 622 | if (strncmp(bpbuffer, "bplist00", strlen("bplist00"))) { | ||
| 623 | return NULL; // badness! | ||
| 624 | } | ||
| 625 | myPos += strlen("bplist00"); | ||
| 626 | } | ||
| 627 | // Get the node's type. | ||
| 628 | if (bpbuffer[myPos] == BPLIST_DATE) { // handle date separately, but do it as a real | ||
| 629 | // better handling of date; basically interpret as real or double | ||
| 630 | data->type = BPLIST_DATE; | ||
| 631 | length = 8; // always 8 for "date" (Apple intended it, not me) | ||
| 632 | myPos++; | ||
| 633 | memcpy(&data->realval64, bpbuffer + myPos, sizeof(data->realval64)); | ||
| 634 | byte_convert((char *) &data->realval64, sizeof(data->realval64)); | ||
| 635 | myPos += length; | ||
| 636 | *position = myPos; | ||
| 637 | return new_node; | ||
| 638 | } | ||
| 639 | |||
| 640 | int type = bpbuffer[myPos] & BPLIST_MASK; | ||
| 641 | data->length = bpbuffer[myPos] & BPLIST_FILL; | ||
| 642 | |||
| 643 | if (!type) { | ||
| 644 | // what? check if it's a boolean. | ||
| 645 | if (bpbuffer[myPos] == BPLIST_TRUE || bpbuffer[myPos] == BPLIST_FALSE) { | ||
| 646 | // okay, so it is. Carry on. | ||
| 647 | data->type = PLIST_BOOLEAN; | ||
| 648 | data->boolval = TRUE; | ||
| 649 | data->length = 0; | ||
| 650 | } else { | ||
| 651 | // er, what? we have a bad type here. Return NULL. | ||
| 652 | g_node_destroy(new_node); | ||
| 653 | //printf("parse_raw_node: lol type: type given %x\n", bpbuffer[myPos]); | ||
| 654 | return NULL; | ||
| 655 | } | ||
| 656 | } | ||
| 657 | |||
| 658 | myPos++; // puts us in the data. | ||
| 659 | if (length == BPLIST_FILL) { // Data happens to contain length... | ||
| 660 | // what? you're going to make me parse an int for the length. You suck. | ||
| 661 | *position = myPos; | ||
| 662 | length_stupidity = parse_raw_node(bpbuffer, bplength, &myPos, ref_size); | ||
| 663 | switch (((struct plist_data *) length_stupidity->data)->type) { | ||
| 664 | case PLIST_UINT8: | ||
| 665 | data->length = ((struct plist_data *) length_stupidity->data)->intval8; | ||
| 666 | break; | ||
| 667 | case PLIST_UINT16: | ||
| 668 | data->length = ((struct plist_data *) length_stupidity->data)->intval16; | ||
| 669 | break; | ||
| 670 | case PLIST_UINT32: | ||
| 671 | data->length = ((struct plist_data *) length_stupidity->data)->intval32; | ||
| 672 | break; | ||
| 673 | case PLIST_UINT64: | ||
| 674 | data->length = ((struct plist_data *) length_stupidity->data)->intval64; | ||
| 675 | break; | ||
| 676 | default: | ||
| 677 | g_node_destroy(new_node); | ||
| 678 | g_node_destroy(length_stupidity); | ||
| 679 | return NULL; | ||
| 680 | } | ||
| 681 | // There, we have our fucking length now. | ||
| 682 | *position = myPos; | ||
| 683 | g_node_destroy(length_stupidity); // cleanup | ||
| 684 | } | ||
| 685 | // Now we're in the data. | ||
| 686 | // Error-checking sorta | ||
| 687 | if ((myPos + data->length) >= bplength) { | ||
| 688 | data->length = bplength - myPos; // truncate the object | ||
| 689 | } | ||
| 690 | // And now for the greatest show on earth: the giant fucking switch statement. | ||
| 691 | switch (type) { | ||
| 692 | case BPLIST_INT: | ||
| 693 | data->length = uipow(2, data->length); // make length less misleading | ||
| 694 | switch (data->length) { | ||
| 695 | case sizeof(uint8_t): | ||
| 696 | data->type = PLIST_UINT8; | ||
| 697 | data->intval8 = bpbuffer[myPos]; | ||
| 698 | break; | ||
| 699 | case sizeof(uint16_t): | ||
| 700 | data->type = PLIST_UINT16; | ||
| 701 | memcpy(&data->intval16, bpbuffer + myPos, sizeof(uint16_t)); | ||
| 702 | data->intval16 = ntohs(data->intval16); | ||
| 703 | break; | ||
| 704 | case sizeof(uint32_t): | ||
| 705 | data->type = PLIST_UINT32; | ||
| 706 | memcpy(&data->intval32, bpbuffer + myPos, sizeof(uint32_t)); | ||
| 707 | data->intval32 = ntohl(data->intval32); | ||
| 708 | break; | ||
| 709 | case sizeof(uint64_t): | ||
| 710 | data->type = PLIST_UINT64; | ||
| 711 | memcpy(&data->intval64, bpbuffer + myPos, sizeof(uint64_t)); | ||
| 712 | byte_convert((char *) &data->intval64, sizeof(uint64_t)); | ||
| 713 | break; | ||
| 714 | default: | ||
| 715 | g_node_destroy(new_node); | ||
| 716 | printf("parse_raw_node: lol: invalid int: size given %lu\n", (long unsigned int) length); | ||
| 717 | printf("parse_raw_node: lol: by the way sizeof(uint64) = %i\n", sizeof(uint64_t)); | ||
| 718 | return NULL; | ||
| 719 | } | ||
| 720 | break; | ||
| 721 | |||
| 722 | case BPLIST_REAL: | ||
| 723 | data->length = uipow(2, data->length); | ||
| 724 | switch (data->length) { | ||
| 725 | case sizeof(float): | ||
| 726 | data->type = PLIST_FLOAT32; | ||
| 727 | memcpy(&data->realval32, bpbuffer + myPos, data->length); | ||
| 728 | byte_convert((char *) &data->realval32, sizeof(float)); //necessary ?? | ||
| 729 | break; | ||
| 730 | case sizeof(double): | ||
| 731 | data->type = PLIST_FLOAT64; | ||
| 732 | memcpy(&data->realval64, bpbuffer + myPos, data->length); | ||
| 733 | byte_convert((char *) &data->realval64, sizeof(double)); | ||
| 734 | break; | ||
| 735 | default: | ||
| 736 | g_node_destroy(new_node); | ||
| 737 | printf("parse_raw_node: lol: invalid real: size given %lu\n", (long unsigned int) length); | ||
| 738 | printf("parse_raw_node: lol: by the way sizeof(uint64) = %i\n", sizeof(uint64_t)); | ||
| 739 | return NULL; | ||
| 740 | } | ||
| 741 | break; | ||
| 742 | |||
| 743 | case BPLIST_STRING: | ||
| 744 | data->type = PLIST_STRING; | ||
| 745 | data->strval = (char *) malloc(sizeof(char) * data->length); | ||
| 746 | memcpy(data->strval, bpbuffer + myPos, data->length); | ||
| 747 | break; | ||
| 748 | |||
| 749 | case BPLIST_UNICODE: | ||
| 750 | data->type = PLIST_UNICODE; | ||
| 751 | data->unicodeval = (wchar_t *) malloc(sizeof(wchar_t) * data->length); | ||
| 752 | memcpy(data->unicodeval, bpbuffer + myPos, data->length); | ||
| 753 | break; | ||
| 754 | |||
| 755 | case BPLIST_DICT: /* returning a raw dict, it forward-references, so. */ | ||
| 756 | data->length = data->length * 2; // dicts lie | ||
| 757 | data->type = PLIST_DICT; | ||
| 758 | |||
| 759 | case BPLIST_ARRAY: /* returning a raw array, it forward-references, so. */ | ||
| 760 | data->ref_size = ref_size; // in arrays and dicts, the "ref size" alluded to in the trailer applies, and should be stored in intval8 so as to save space. | ||
| 761 | if (data->type == 0) | ||
| 762 | data->type = PLIST_ARRAY; | ||
| 763 | case BPLIST_DATA: | ||
| 764 | if (data->type == 0) | ||
| 765 | data->type = PLIST_DATA; | ||
| 766 | default: /* made to hold raw data. */ | ||
| 767 | modifier = (data->ref_size > 0) ? data->ref_size : 1; | ||
| 768 | data->buff = (char *) malloc(sizeof(char) * (data->length * modifier)); | ||
| 769 | memcpy(data->buff, bpbuffer + myPos, (data->length * modifier)); | ||
| 770 | break; | ||
| 771 | |||
| 772 | } | ||
| 773 | |||
| 774 | myPos += data->length; | ||
| 775 | *position = myPos; | ||
| 776 | return new_node; | ||
| 777 | } | ||
| 778 | |||
| 779 | plist_t parse_nodes(const char *bpbuffer, uint32_t bplength, uint32_t * position) | ||
| 780 | { | ||
| 781 | plist_t *nodeslist = NULL, *newaddr = NULL; | ||
| 782 | plist_t new_node = NULL, root_node = NULL; | ||
| 783 | |||
| 784 | uint32_t nodeslength = 0; | ||
| 785 | uint8_t offset_size = 0, dict_param_size = 0; | ||
| 786 | offset_size = bpbuffer[bplength - 26]; | ||
| 787 | dict_param_size = bpbuffer[bplength - 25]; | ||
| 788 | uint64_t current_offset = 0; | ||
| 789 | uint64_t num_objects = 0, root_object = 0, offset_table_index = 0; | ||
| 790 | memcpy(&num_objects, bpbuffer + bplength - 24, sizeof(uint64_t)); | ||
| 791 | memcpy(&root_object, bpbuffer + bplength - 16, sizeof(uint64_t)); | ||
| 792 | memcpy(&offset_table_index, bpbuffer + bplength - 8, sizeof(uint64_t)); | ||
| 793 | byte_convert((char *) &num_objects, sizeof(uint64_t)); | ||
| 794 | byte_convert((char *) &root_object, sizeof(uint64_t)); | ||
| 795 | byte_convert((char *) &offset_table_index, sizeof(uint64_t)); | ||
| 796 | |||
| 797 | log_debug_msg("Offset size: %i\nGiven: %i\n", offset_size, bpbuffer[bplength - 26]); | ||
| 798 | log_debug_msg("Ref size: %i\nGiven: %i\n", dict_param_size, bpbuffer[bplength - 25]); | ||
| 799 | log_debug_msg("Number of objects: %lli\nGiven: %llu\n", num_objects, *(bpbuffer + bplength - 24)); | ||
| 800 | log_debug_msg("Root object index: %lli\nGiven: %llu\n", root_object, *(bpbuffer + bplength - 16)); | ||
| 801 | log_debug_msg("Offset table index: %lli\nGiven: %llu\n", offset_table_index, *(bpbuffer + bplength - 8)); | ||
| 802 | log_debug_msg("Size of uint64: %i\n", sizeof(uint64_t)); | ||
| 803 | |||
| 804 | int i = 0, j = 0, k = 0, str_i = 0, str_j = 0; | ||
| 805 | uint32_t index1 = 0, index2 = 0; | ||
| 806 | |||
| 807 | nodeslist = (plist_t *) malloc(sizeof(plist_t) * num_objects); | ||
| 808 | if (!nodeslist) | ||
| 809 | return NULL; | ||
| 810 | |||
| 811 | for (i = 0; i < num_objects; i++) { | ||
| 812 | memcpy(¤t_offset, bpbuffer + (offset_table_index + (i * offset_size)), offset_size); | ||
| 813 | byte_convert((char *) ¤t_offset, | ||
| 814 | (offset_size <= sizeof(current_offset)) ? offset_size : sizeof(current_offset)); | ||
| 815 | log_debug_msg("parse_nodes: current_offset = %x\n", current_offset); | ||
| 816 | nodeslist[i] = parse_raw_node(bpbuffer, bplength, (uint32_t *) & current_offset, dict_param_size); | ||
| 817 | log_debug_msg("parse_nodes: parse_raw_node done\n"); | ||
| 818 | } | ||
| 819 | |||
| 820 | |||
| 821 | for (i = 0; i < num_objects; i++) { | ||
| 822 | // set elements for dicts and arrays and leave the rest alone | ||
| 823 | log_debug_msg("parse_nodes: on node %i\n", i); | ||
| 824 | struct plist_data *data = (struct plist_data *) nodeslist[i]->data; | ||
| 825 | |||
| 826 | switch (data->type) { | ||
| 827 | case PLIST_DICT: | ||
| 828 | log_debug_msg("parse_nodes: dictionary found\n"); | ||
| 829 | for (j = 0; j < (data->length / 2); j++) { | ||
| 830 | str_i = j * data->ref_size; | ||
| 831 | str_j = (j + (data->length / 2)) * data->ref_size; | ||
| 832 | |||
| 833 | memcpy(&index1, data->buff + str_i, data->ref_size); | ||
| 834 | memcpy(&index2, data->buff + str_j, data->ref_size); | ||
| 835 | |||
| 836 | byte_convert((char *) &index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index2)); | ||
| 837 | byte_convert((char *) &index2, (dict_param_size <= sizeof(index2)) ? dict_param_size : sizeof(index2)); | ||
| 838 | |||
| 839 | g_node_append(nodeslist[i], nodeslist[index1]); | ||
| 840 | g_node_append(nodeslist[i], nodeslist[index2]); | ||
| 841 | } | ||
| 842 | |||
| 843 | data->length = data->length / 2; | ||
| 844 | free(data->buff); | ||
| 845 | k = 0; | ||
| 846 | break; | ||
| 847 | |||
| 848 | case PLIST_ARRAY: | ||
| 849 | log_debug_msg("parse_nodes: array found\n"); | ||
| 850 | for (j = 0; j < data->length; j++) { | ||
| 851 | log_debug_msg("parse_nodes: array index %i\n", j); | ||
| 852 | str_j = j * data->ref_size; | ||
| 853 | memcpy(&index1, data->buff + str_j, data->ref_size); | ||
| 854 | log_debug_msg("parse_nodes: post-memcpy\n"); | ||
| 855 | byte_convert((char *) &index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index1)); | ||
| 856 | log_debug_msg("parse_nodes: post-ntohl\nindex1 = %i\n", index1); | ||
| 857 | g_node_append(nodeslist[i], nodeslist[index1]); | ||
| 858 | log_debug_msg("parse_nodes: post-assignment\n"); | ||
| 859 | } | ||
| 860 | free(data->buff); | ||
| 861 | break; | ||
| 862 | default: | ||
| 863 | //printf("lol... type %x\n", nodeslist[i]->type); | ||
| 864 | break; | ||
| 865 | } // those are the only two we need to correct for. | ||
| 866 | } | ||
| 867 | |||
| 868 | root_node = nodeslist[root_object]; | ||
| 869 | return root_node; | ||
| 870 | } | ||
| 798 | 871 | ||
| 799 | void plist_to_bin(plist_t plist, char** plist_bin) | 872 | void plist_to_bin(plist_t plist, char **plist_bin, int *length) |
| 800 | { | 873 | { |
| 801 | } | 874 | } |
| 802 | 875 | ||
| 803 | void xml_to_plist(const char* plist_xml, plist_t* plist) | 876 | void xml_to_plist(const char *plist_xml, plist_t * plist) |
| 804 | { | 877 | { |
| 805 | xmlDocPtr plist_doc = xmlReadMemory(plist_xml, strlen(plist_xml), NULL, NULL, 0); | 878 | xmlDocPtr plist_doc = xmlReadMemory(plist_xml, strlen(plist_xml), NULL, NULL, 0); |
| 806 | xmlNodePtr root_node = xmlDocGetRootElement(plist_doc); | 879 | xmlNodePtr root_node = xmlDocGetRootElement(plist_doc); |
| 807 | 880 | ||
| 808 | struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1); | 881 | struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1); |
| 809 | *plist = g_node_new (data); | 882 | *plist = g_node_new(data); |
| 810 | data->type = PLIST_PLIST; | 883 | data->type = PLIST_PLIST; |
| 811 | xml_to_node (root_node, *plist); | 884 | xml_to_node(root_node, *plist); |
| 812 | 885 | ||
| 813 | } | 886 | } |
| 814 | 887 | ||
| 815 | void bin_to_plist(const char* plist_bin, plist_t* plist) | 888 | void bin_to_plist(const char *plist_bin, int length, plist_t * plist) |
| 816 | { | 889 | { |
| 890 | uint32_t pos = 0; | ||
| 891 | *plist = parse_nodes(plist_bin, length, &pos); | ||
| 817 | } | 892 | } |
diff --git a/src/plist.h b/src/plist.h index 4586d6f..1ca55f9 100644 --- a/src/plist.h +++ b/src/plist.h | |||
| @@ -46,38 +46,8 @@ void free_dictionary(char **dictionary); | |||
| 46 | 46 | ||
| 47 | /* Binary plist stuff */ | 47 | /* Binary plist stuff */ |
| 48 | 48 | ||
| 49 | enum { | ||
| 50 | BPLIST_TRUE = 0x08, | ||
| 51 | BPLIST_FALSE = 0x09, | ||
| 52 | BPLIST_FILL = 0x0F, /* will be used for length grabbing */ | ||
| 53 | BPLIST_INT = 0x10, | ||
| 54 | BPLIST_REAL = 0x20, | ||
| 55 | BPLIST_DATE = 0x33, | ||
| 56 | BPLIST_DATA = 0x40, | ||
| 57 | BPLIST_STRING = 0x50, | ||
| 58 | BPLIST_UNICODE = 0x60, | ||
| 59 | BPLIST_UID = 0x70, | ||
| 60 | BPLIST_ARRAY = 0xA0, | ||
| 61 | BPLIST_SET = 0xC0, | ||
| 62 | BPLIST_DICT = 0xD0, | ||
| 63 | BPLIST_MASK = 0xF0 | ||
| 64 | }; | ||
| 65 | 49 | ||
| 66 | typedef struct _bplist_node { | 50 | typedef enum { |
| 67 | struct _bplist_node *next, **subnodes; // subnodes is for arrays, dicts and (potentially) sets. | ||
| 68 | uint64_t length, intval64; | ||
| 69 | uint32_t intval32; // length = subnodes | ||
| 70 | uint16_t intval16; | ||
| 71 | uint8_t intval8; | ||
| 72 | uint8_t type, *indexes; // indexes for array-types; essentially specify the order in which to access for key => value pairs | ||
| 73 | char *strval; | ||
| 74 | double realval; | ||
| 75 | wchar_t *unicodeval; | ||
| 76 | } bplist_node; | ||
| 77 | |||
| 78 | bplist_node *parse_nodes(const char *bpbuffer, uint32_t bplength, uint32_t * position); | ||
| 79 | |||
| 80 | typedef enum { | ||
| 81 | PLIST_BOOLEAN, | 51 | PLIST_BOOLEAN, |
| 82 | PLIST_UINT8, | 52 | PLIST_UINT8, |
| 83 | PLIST_UINT16, | 53 | PLIST_UINT16, |
| @@ -100,15 +70,15 @@ typedef GNode *plist_t; | |||
| 100 | typedef GNode *dict_t; | 70 | typedef GNode *dict_t; |
| 101 | typedef GNode *array_t; | 71 | typedef GNode *array_t; |
| 102 | 72 | ||
| 103 | void plist_new_plist(plist_t* plist); | 73 | void plist_new_plist(plist_t * plist); |
| 104 | void plist_new_dict_in_plist(plist_t plist, dict_t* dict); | 74 | void plist_new_dict_in_plist(plist_t plist, dict_t * dict); |
| 105 | void plist_new_array_in_plist(plist_t plist, int length, plist_type type, void** values, array_t* array); | 75 | void plist_new_array_in_plist(plist_t plist, int length, plist_type type, void **values, array_t * array); |
| 106 | void plist_add_dict_element(dict_t dict, char* key, plist_type type, void* value); | 76 | void plist_add_dict_element(dict_t dict, char *key, plist_type type, void *value); |
| 107 | void plist_free(plist_t plist); | 77 | void plist_free(plist_t plist); |
| 108 | 78 | ||
| 109 | void plist_to_xml(plist_t plist, char** plist_xml); | 79 | void plist_to_xml(plist_t plist, char **plist_xml); |
| 110 | void plist_to_bin(plist_t plist, char** plist_bin); | 80 | void plist_to_bin(plist_t plist, char **plist_bin, int *length); |
| 111 | 81 | ||
| 112 | void xml_to_plist(const char* plist_xml, plist_t* plist); | 82 | void xml_to_plist(const char *plist_xml, plist_t * plist); |
| 113 | void bin_to_plist(const char* plist_bin, plist_t* plist); | 83 | void bin_to_plist(const char *plist_bin, int length, plist_t * plist); |
| 114 | #endif | 84 | #endif |
