summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGravatar Jonathan Beck2008-11-30 16:36:18 +0100
committerGravatar Jonathan Beck2008-11-30 16:36:18 +0100
commit889cb32a1231c41762d7e2bbe6c891bd3a6c9a7d (patch)
treee60a593d5806b1fc5398bfa17f6d2feec9c82358
parent831ee461bd03ad809f73b34dc5205d296158a969 (diff)
downloadlibimobiledevice-889cb32a1231c41762d7e2bbe6c891bd3a6c9a7d.tar.gz
libimobiledevice-889cb32a1231c41762d7e2bbe6c891bd3a6c9a7d.tar.bz2
Continue abstraction of xml and binary plist.
-rw-r--r--dev/plutil.c87
-rw-r--r--src/plist.c799
-rw-r--r--src/plist.h48
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 @@
#include <stdio.h>
#include <stdlib.h>
-void print_nodes(bplist_node * root_node)
-{
- // Yay, great. Let's print the list of nodes recursively...
- int i = 0;
- if (!root_node)
- return; // or not, because the programmer's stupid.
-
- switch (root_node->type) {
- case BPLIST_DICT:
- printf("Dictionary node.\nLength %lu\n", (long unsigned int) root_node->length);
- for (i = 0; i < (root_node->length * 2); i += 2) {
- // HI!
- printf("Key: ");
- print_nodes(root_node->subnodes[i]);
- printf("Value: ");
- print_nodes(root_node->subnodes[i + 1]);
- }
- printf("End dictionary node.\n\n");
- break;
-
- case BPLIST_ARRAY:
- printf("Array node.\n");
- for (i = 0; i < root_node->length; i++) {
- printf("\tElement %i: ", i);
- print_nodes(root_node->subnodes[i]);
- }
- break;
-
- case BPLIST_INT:
- if (root_node->length == sizeof(uint8_t)) {
- printf("Integer: %i\n", root_node->intval8);
- } else if (root_node->length == sizeof(uint16_t)) {
- printf("Integer: %i\n", root_node->intval16);
- } else if (root_node->length == sizeof(uint32_t)) {
- printf("Integer: %i\n", root_node->intval32);
- }
- break;
-
- case BPLIST_STRING:
- printf("String: ");
- fwrite(root_node->strval, sizeof(char), root_node->length, stdout);
- fflush(stdout);
- printf("\n");
- break;
-
- case BPLIST_DATA:
- printf("Data: ");
- char *data = g_base64_encode(root_node->strval, root_node->length);
- fwrite(format_string(data, 60, 0), sizeof(char), strlen(data), stdout);
- fflush(stdout);
- printf("\n");
- break;
-
- case BPLIST_UNICODE:
- printf("Unicode data, may appear crappy: ");
- fwrite(root_node->unicodeval, sizeof(wchar_t), root_node->length, stdout);
- fflush(stdout);
- printf("\n");
- break;
-
- case BPLIST_TRUE:
- printf("True.\n");
- break;
-
- case BPLIST_FALSE:
- printf("False.\n");
- break;
-
- case BPLIST_REAL:
- case BPLIST_DATE:
- printf("Real(?): %f\n", root_node->realval);
- break;
-
- default:
- printf("oops\nType set to %x and length is %lu\n", root_node->type, (long unsigned int) root_node->length);
- break;
- }
-}
-
int main(int argc, char *argv[])
{
struct stat *filestats = (struct stat *) malloc(sizeof(struct stat));
@@ -117,15 +38,17 @@ int main(int argc, char *argv[])
fclose(bplist);
printf("or here?\n");
// bplist_entire contains our stuff
- bplist_node *root_node;
- root_node = parse_nodes(bplist_entire, filestats->st_size, &position);
+ plist_t root_node = NULL;
+ bin_to_plist(bplist_entire, filestats->st_size, &root_node);
printf("plutil debug mode\n\n");
printf("file size %i\n\n", (int) filestats->st_size);
if (!root_node) {
printf("Invalid binary plist (or some other error occurred.)\n");
return 0;
}
- print_nodes(root_node);
+ char *plist_xml = NULL;
+ plist_to_xml(root_node, &plist_xml);
+ printf("%s\n", plist_xml);
return 0;
}
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 @@
#include <assert.h>
#include "utils.h"
#include "plist.h"
+#include <wchar.h>
const char *plist_base = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\
@@ -285,147 +286,7 @@ void byte_convert(char *address, size_t size)
}
}
-bplist_node *parse_raw_node(const char *bpbuffer, uint32_t bplength, uint32_t * position, uint8_t ref_size)
-{
- if (!position || !bpbuffer || !bplength)
- return NULL;
-
- uint8_t modifier = 0;
- bplist_node *new_node = (bplist_node *) malloc(sizeof(bplist_node));
- bplist_node *length_stupidity = NULL;
- memset(new_node, 0, sizeof(bplist_node)); // initialize the new struct
-
- int myPos = *position;
- if (myPos == bplength || (myPos + 1) == bplength) {
- free(new_node);
- return NULL;
- } // end of string
-
- uint32_t length = 0;
- if (!myPos) {
- if (strncmp(bpbuffer, "bplist00", strlen("bplist00"))) {
- return NULL; // badness!
- }
- myPos += strlen("bplist00");
- }
- // Get the node's type.
- if (bpbuffer[myPos] == BPLIST_DATE) { // handle date separately, but do it as a real
- // better handling of date; basically interpret as real or double
- new_node->type = BPLIST_DATE;
- new_node->length = 8; // always 8 for "date" (Apple intended it, not me)
- myPos++;
- memcpy(&new_node->realval, bpbuffer + myPos, sizeof(new_node->realval));
- byte_convert((char *) &new_node->realval, sizeof(new_node->realval));
- myPos += new_node->length;
- *position = myPos;
- return new_node;
- }
-
- new_node->type = bpbuffer[myPos] & BPLIST_MASK;
- new_node->length = bpbuffer[myPos] & BPLIST_FILL;
- if (!new_node->type) {
- // what? check if it's a boolean.
- if (bpbuffer[myPos] == BPLIST_TRUE || bpbuffer[myPos] == BPLIST_FALSE) {
- // okay, so it is. Carry on.
- new_node->type = bpbuffer[myPos];
- new_node->length = 0;
- } else {
- // er, what? we have a bad type here. Return NULL.
- free(new_node);
- //printf("parse_raw_node: lol type: type given %x\n", bpbuffer[myPos]);
- return NULL;
- }
- }
-
- myPos++; // puts us in the data.
- if (new_node->length == BPLIST_FILL) { // Data happens to contain length...
- // what? you're going to make me parse an int for the length. You suck.
- *position = myPos;
- length_stupidity = parse_raw_node(bpbuffer, bplength, &myPos, ref_size);
- switch (length_stupidity->length) {
- case sizeof(uint8_t):
- new_node->length = length_stupidity->intval8;
- break;
- case sizeof(uint16_t):
- new_node->length = length_stupidity->intval16;
- break;
- case sizeof(uint32_t):
- new_node->length = length_stupidity->intval32;
- break;
- case sizeof(uint64_t):
- new_node->length = length_stupidity->intval64;
- break;
- default:
- free(new_node);
- free(length_stupidity);
- return NULL;
- }
- // There, we have our fucking length now.
- *position = myPos;
- free(length_stupidity); // cleanup
- }
- // Now we're in the data.
- // Error-checking sorta
- if ((myPos + new_node->length) >= bplength) {
- new_node->length = bplength - myPos; // truncate the object
- }
- // And now for the greatest show on earth: the giant fucking switch statement.
- switch (new_node->type) {
- case BPLIST_INT:
- new_node->length = uipow(2, new_node->length); // make length less misleading
- switch (new_node->length) {
- case sizeof(uint8_t):
- new_node->intval8 = bpbuffer[myPos];
- break;
- case sizeof(uint16_t):
- memcpy(&new_node->intval16, bpbuffer + myPos, sizeof(uint16_t));
- new_node->intval16 = ntohs(new_node->intval16);
- break;
- case sizeof(uint32_t):
- memcpy(&new_node->intval32, bpbuffer + myPos, sizeof(uint32_t));
- new_node->intval32 = ntohl(new_node->intval32);
- break;
- case sizeof(uint64_t):
- memcpy(&new_node->intval64, bpbuffer + myPos, sizeof(uint64_t));
- byte_convert((char *) &new_node->intval64, sizeof(uint64_t));
- break;
- default:
- free(new_node);
- printf("parse_raw_node: lol: invalid int: size given %lu\n", (long unsigned int) new_node->length);
- printf("parse_raw_node: lol: by the way sizeof(uint64) = %i\n", sizeof(uint64_t));
- return NULL;
- }
- break;
- case BPLIST_REAL:
- new_node->length = uipow(2, new_node->length);
- memcpy(&new_node->realval, bpbuffer + myPos, new_node->length); // XXX: probable buffer overflow here
- //new_node->realval = bpbuffer[myPos]; // why not
- byte_convert((char *) &new_node->realval, sizeof(double));
- break;
-
- case BPLIST_DICT: /* returning a raw dict, it forward-references, so. */
- new_node->length = new_node->length * 2; // dicts lie
- case BPLIST_ARRAY: /* returning a raw array, it forward-references, so. */
- 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.
- case BPLIST_STRING:
- case BPLIST_DATA:
- default: /* made to hold raw data. */
- modifier = (new_node->intval8 > 0) ? new_node->intval8 : 1;
- new_node->strval = (char *) malloc(sizeof(char) * (new_node->length * modifier));
- memcpy(new_node->strval, bpbuffer + myPos, (new_node->length * modifier));
- break;
-
- case BPLIST_UNICODE:
- new_node->unicodeval = (wchar_t *) malloc(sizeof(wchar_t) * new_node->length);
- memcpy(new_node->unicodeval, bpbuffer + myPos, new_node->length);
- break;
- }
-
- myPos += new_node->length;
- *position = myPos;
- return new_node;
-}
void print_bytes(char *val, size_t size)
{
@@ -435,180 +296,123 @@ void print_bytes(char *val, size_t size)
}
}
-bplist_node *parse_nodes(const char *bpbuffer, uint32_t bplength, uint32_t * position)
-{
- bplist_node **nodeslist = NULL, **newaddr = NULL;
- bplist_node *new_node = NULL, *root_node = NULL;
-
- uint32_t nodeslength = 0;
- uint8_t offset_size = 0, dict_param_size = 0;
- offset_size = bpbuffer[bplength - 26];
- dict_param_size = bpbuffer[bplength - 25];
- uint64_t current_offset = 0;
- //uint64_t num_objects = *(bpbuffer+(bplength-24)), root_object = *(bpbuffer+(bplength-16)), offset_table_index = *(bpbuffer+(bplength-8));
- uint64_t num_objects = 0, root_object = 0, offset_table_index = 0;
- memcpy(&num_objects, bpbuffer + bplength - 24, sizeof(uint64_t));
- memcpy(&root_object, bpbuffer + bplength - 16, sizeof(uint64_t));
- memcpy(&offset_table_index, bpbuffer + bplength - 8, sizeof(uint64_t));
- byte_convert((char *) &num_objects, sizeof(uint64_t));
- byte_convert((char *) &root_object, sizeof(uint64_t));
- byte_convert((char *) &offset_table_index, sizeof(uint64_t));
-
- log_debug_msg("Offset size: %i\nGiven: %i\n", offset_size, bpbuffer[bplength - 26]);
- log_debug_msg("Ref size: %i\nGiven: %i\n", dict_param_size, bpbuffer[bplength - 25]);
- log_debug_msg("Number of objects: %lli\nGiven: %llu\n", num_objects, *(bpbuffer + bplength - 24));
- log_debug_msg("Root object index: %lli\nGiven: %llu\n", root_object, *(bpbuffer + bplength - 16));
- log_debug_msg("Offset table index: %lli\nGiven: %llu\n", offset_table_index, *(bpbuffer + bplength - 8));
- log_debug_msg("Size of uint64: %i\n", sizeof(uint64_t));
-
- int i = 0, j = 0, k = 0, str_i = 0, str_j = 0;
- uint32_t index1 = 0, index2 = 0;
-
- nodeslist = (bplist_node **) malloc(sizeof(bplist_node *) * num_objects);
- if (!nodeslist)
- return NULL;
-
- for (i = 0; i < num_objects; i++) {
- memcpy(&current_offset, bpbuffer + (offset_table_index + (i * offset_size)), offset_size);
- //current_offset = (offset_size == 2) ? ntohs(current_offset) : (offset_size == 4) ? ntohl(current_offset) : current_offset;
- //if (offset_size == 8) byte_convert(&current_offset, 8);
- byte_convert((char *) &current_offset,
- (offset_size <= sizeof(current_offset)) ? offset_size : sizeof(current_offset));
- log_debug_msg("parse_nodes: current_offset = %x\n", current_offset);
- nodeslist[i] = parse_raw_node(bpbuffer, bplength, (uint32_t *) & current_offset, dict_param_size);
- log_debug_msg("parse_nodes: parse_raw_node done\n");
- }
-
-
- for (i = 0; i < num_objects; i++) {
- // set elements for dicts and arrays and leave the rest alone
- log_debug_msg("parse_nodes: on node %i\n", i);
- switch (nodeslist[i]->type) {
- case BPLIST_DICT:
- log_debug_msg("parse_nodes: dictionary found\n");
- nodeslist[i]->subnodes = (bplist_node **) malloc(sizeof(bplist_node) * nodeslist[i]->length);
- for (j = 0; j < (nodeslist[i]->length / 2); j++) {
- str_i = j * nodeslist[i]->intval8;
- str_j = (j + (nodeslist[i]->length / 2)) * nodeslist[i]->intval8;
-
- memcpy(&index1, nodeslist[i]->strval + str_i, nodeslist[i]->intval8);
- memcpy(&index2, nodeslist[i]->strval + str_j, nodeslist[i]->intval8);
- //index1 = (dict_param_size == 1) ? index1 : (dict_param_size == 2) ? ntohs(index1) : (dict_param_size == 4) ? ntohl(index1) : index1;
- //index2 = (dict_param_size == 1) ? index2 : (dict_param_size == 2) ? ntohs(index2) : (dict_param_size == 4) ? ntohl(index2) : index2;
- byte_convert((char *) &index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index2));
- byte_convert((char *) &index2, (dict_param_size <= sizeof(index2)) ? dict_param_size : sizeof(index2));
- //printf("parse_nodes: key index %i value %i\n", index1, index2);
- //printf("parse_nodes: key type %x and length %i\n", nodeslist[index1]->type, nodeslist[index1]->length);
- //printf("parse_nodes: value type %x and length %i\n", nodeslist[index2]->type, nodeslist[index2]->length);
- nodeslist[i]->subnodes[k++] = nodeslist[index1];
- nodeslist[i]->subnodes[k++] = nodeslist[index2];
- }
-
- nodeslist[i]->length = nodeslist[i]->length / 2;
- free(nodeslist[i]->strval);
- k = 0;
- break;
-
- case BPLIST_ARRAY:
- log_debug_msg("parse_nodes: array found\n");
- nodeslist[i]->subnodes = (bplist_node **) malloc(sizeof(bplist_node) * nodeslist[i]->length); // memory allocation helps a lot when storing data
-
- for (j = 0; j < nodeslist[i]->length; j++) {
- log_debug_msg("parse_nodes: array index %i\n", j);
- str_j = j * nodeslist[i]->intval8;
- //index1 = nodeslist[i]->strval[j];
- memcpy(&index1, nodeslist[i]->strval + str_j, nodeslist[i]->intval8);
- log_debug_msg("parse_nodes: post-memcpy\n");
- //index1 = (dict_param_size == 1) ? index1 : (dict_param_size == 2) ? ntohs(index1) : (dict_param_size == 4) ? ntohl(index1) : index1;
- byte_convert((char *) &index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index1));
- log_debug_msg("parse_nodes: post-ntohl\nindex1 = %i\n", index1);
- nodeslist[i]->subnodes[j] = nodeslist[index1];
- log_debug_msg("parse_nodes: post-assignment\n");
- }
- free(nodeslist[i]->strval);
- break;
- default:
- //printf("lol... type %x\n", nodeslist[i]->type);
- break;
- } // those are the only two we need to correct for.
- }
- root_node = nodeslist[root_object];
- return root_node;
-}
struct plist_data {
union {
- char boolval;
- uint8_t intval8;
+ char boolval;
+ uint8_t intval8;
uint16_t intval16;
uint32_t intval32;
uint64_t intval64;
- float realval32;
- double realval64;
- char *strval;
+ float realval32;
+ double realval64;
+ char *strval;
wchar_t *unicodeval;
- char *buff;
+ struct {
+ char *buff;
+ uint8_t ref_size;
+ };
};
- int index;
+ uint64_t length;
plist_type type;
};
-void plist_new_plist(plist_t* plist)
+enum {
+ BPLIST_TRUE = 0x08,
+ BPLIST_FALSE = 0x09,
+ BPLIST_FILL = 0x0F, /* will be used for length grabbing */
+ BPLIST_INT = 0x10,
+ BPLIST_REAL = 0x20,
+ BPLIST_DATE = 0x33,
+ BPLIST_DATA = 0x40,
+ BPLIST_STRING = 0x50,
+ BPLIST_UNICODE = 0x60,
+ BPLIST_UID = 0x70,
+ BPLIST_ARRAY = 0xA0,
+ BPLIST_SET = 0xC0,
+ BPLIST_DICT = 0xD0,
+ BPLIST_MASK = 0xF0
+};
+
+void plist_new_plist(plist_t * plist)
{
- if (*plist != NULL) return;
- struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1);
+ if (*plist != NULL)
+ return;
+ struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1);
data->type = PLIST_PLIST;
- *plist = g_node_new (data);
+ *plist = g_node_new(data);
}
-void plist_new_dict_in_plist(plist_t plist, dict_t* dict)
+void plist_new_dict_in_plist(plist_t plist, dict_t * dict)
{
- if (!plist || *dict) return;
+ if (!plist || *dict)
+ return;
- struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1);
+ struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1);
data->type = PLIST_DICT;
- *dict = g_node_new (data);
+ *dict = g_node_new(data);
g_node_append(plist, *dict);
}
-void plist_new_array_in_plist(plist_t plist, int length, plist_type type, void** values, array_t* array)
+void plist_new_array_in_plist(plist_t plist, int length, plist_type type, void **values, array_t * array)
{
}
-void plist_add_dict_element(dict_t dict, char* key, plist_type type, void* value)
+void plist_add_dict_element(dict_t dict, char *key, plist_type type, void *value)
{
- if (!dict || !key || !value) return;
+ if (!dict || !key || !value)
+ return;
- struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1);
+ struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1);
data->type = PLIST_KEY;
data->strval = strdup(key);
- GNode* keynode = g_node_new (data);
+ GNode *keynode = g_node_new(data);
g_node_append(dict, keynode);
//now handle value
- struct plist_data* val = (struct plist_data*)calloc(sizeof(struct plist_data), 1);
+ struct plist_data *val = (struct plist_data *) calloc(sizeof(struct plist_data), 1);
val->type = type;
switch (type) {
- case PLIST_BOOLEAN : val->boolval = *((char*)value); break;
- case PLIST_UINT8 : val->intval8 = *((uint8_t*)value); break;
- case PLIST_UINT16 : val->intval16 = *((uint16_t*)value); break;
- case PLIST_UINT32 : val->intval32 = *((uint32_t*)value); break;
- case PLIST_UINT64 : val->intval64 = *((uint64_t*)value); break;
- case PLIST_FLOAT32 : val->realval32 = *((float*)value); break;
- case PLIST_FLOAT64 : val->realval64 = *((double*)value); break;
- case PLIST_STRING : val->strval = strdup((char*) value); break;
- case PLIST_UNICODE : val->unicodeval = wcsdup((wchar_t*) value); break;
- case PLIST_DATA : val->buff = strdup((char*) value); break;
- case PLIST_ARRAY :
- case PLIST_DICT :
- case PLIST_DATE :
- case PLIST_PLIST :
- default:
- break;
+ case PLIST_BOOLEAN:
+ val->boolval = *((char *) value);
+ break;
+ case PLIST_UINT8:
+ val->intval8 = *((uint8_t *) value);
+ break;
+ case PLIST_UINT16:
+ val->intval16 = *((uint16_t *) value);
+ break;
+ case PLIST_UINT32:
+ val->intval32 = *((uint32_t *) value);
+ break;
+ case PLIST_UINT64:
+ val->intval64 = *((uint64_t *) value);
+ break;
+ case PLIST_FLOAT32:
+ val->realval32 = *((float *) value);
+ break;
+ case PLIST_FLOAT64:
+ val->realval64 = *((double *) value);
+ break;
+ case PLIST_STRING:
+ val->strval = strdup((char *) value);
+ break;
+ case PLIST_UNICODE:
+ val->unicodeval = wcsdup((wchar_t *) value);
+ break;
+ case PLIST_DATA:
+ val->buff = strdup((char *) value);
+ break;
+ case PLIST_ARRAY:
+ case PLIST_DICT:
+ case PLIST_DATE:
+ case PLIST_PLIST:
+ default:
+ break;
}
- GNode* valnode = g_node_new (val);
+ GNode *valnode = g_node_new(val);
g_node_append(dict, valnode);
}
@@ -617,97 +421,98 @@ void plist_free(plist_t plist)
g_node_destroy(plist);
}
-void node_to_xml (GNode *node, gpointer data)
+void node_to_xml(GNode * node, gpointer data)
{
- if (!node) return;
+ if (!node)
+ return;
- struct plist_data* node_data = (struct plist_data*)node->data;
+ struct plist_data *node_data = (struct plist_data *) node->data;
xmlNodePtr child_node = NULL;
char isStruct = FALSE;
- gchar* tag = NULL;
- gchar* val = NULL;
+ gchar *tag = NULL;
+ gchar *val = NULL;
switch (node_data->type) {
- case PLIST_BOOLEAN :
- {
+ case PLIST_BOOLEAN:
+ {
if (node_data->boolval)
tag = "true";
else
tag = "false";
- }
- break;
+ }
+ break;
- case PLIST_UINT8 :
- tag = "integer";
- val = g_strdup_printf("%u", node_data->intval8);
- break;
+ case PLIST_UINT8:
+ tag = "integer";
+ val = g_strdup_printf("%u", node_data->intval8);
+ break;
- case PLIST_UINT16 :
- tag = "integer";
- val = g_strdup_printf("%u", node_data->intval16);
- break;
+ case PLIST_UINT16:
+ tag = "integer";
+ val = g_strdup_printf("%u", node_data->intval16);
+ break;
- case PLIST_UINT32 :
- tag = "integer";
- val = g_strdup_printf("%u", node_data->intval32);
- break;
+ case PLIST_UINT32:
+ tag = "integer";
+ val = g_strdup_printf("%u", node_data->intval32);
+ break;
- case PLIST_UINT64 :
- tag = "integer";
- val = g_strdup_printf("%lu", (long unsigned int)node_data->intval64);
- break;
+ case PLIST_UINT64:
+ tag = "integer";
+ val = g_strdup_printf("%lu", (long unsigned int) node_data->intval64);
+ break;
- case PLIST_FLOAT32 :
- tag = "real";
- val = g_strdup_printf("%f", node_data->realval32);
- break;
+ case PLIST_FLOAT32:
+ tag = "real";
+ val = g_strdup_printf("%f", node_data->realval32);
+ break;
- case PLIST_FLOAT64 :
- tag = "real";
- val = g_strdup_printf("%Lf", (long double)node_data->intval64);
- break;
+ case PLIST_FLOAT64:
+ tag = "real";
+ val = g_strdup_printf("%Lf", (long double) node_data->intval64);
+ break;
- case PLIST_STRING :
- tag = "string";
- val = g_strdup(node_data->strval);
- break;
+ case PLIST_STRING:
+ tag = "string";
+ val = g_strdup(node_data->strval);
+ break;
- case PLIST_UNICODE :
- tag = "string";
- val = g_strdup((gchar*)node_data->unicodeval);
- break;
+ case PLIST_UNICODE:
+ tag = "string";
+ val = g_strdup((gchar *) node_data->unicodeval);
+ break;
- case PLIST_KEY :
- tag = "key";
- val = g_strdup((gchar*)node_data->strval);
- break;
+ case PLIST_KEY:
+ tag = "key";
+ val = g_strdup((gchar *) node_data->strval);
+ break;
- case PLIST_DATA :
- tag = "data";
- val = format_string(node_data->buff, 60, 0);
- break;
- case PLIST_ARRAY :
- tag = "array";
- isStruct = TRUE;
- break;
- case PLIST_DICT :
- tag = "dict";
- isStruct = TRUE;
- break;
- case PLIST_PLIST :
- tag = "plist";
- isStruct = TRUE;
- break;
- case PLIST_DATE : //TODO : handle date tag
- default:
- break;
+ case PLIST_DATA:
+ tag = "data";
+ val = format_string(node_data->buff, 60, 0);
+ break;
+ case PLIST_ARRAY:
+ tag = "array";
+ isStruct = TRUE;
+ break;
+ case PLIST_DICT:
+ tag = "dict";
+ isStruct = TRUE;
+ break;
+ case PLIST_PLIST:
+ tag = "plist";
+ isStruct = TRUE;
+ break;
+ case PLIST_DATE: //TODO : handle date tag
+ default:
+ break;
}
- return;
child_node = xmlNewChild(data, NULL, tag, val);
- gfree(val);
+ xmlNodeAddContent(child_node, "\n");
+ g_free(val);
if (isStruct)
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)
return;
}
-void xml_to_node (xmlNodePtr xml_node, GNode *plist_node)
+void xml_to_node(xmlNodePtr xml_node, GNode * plist_node)
{
xmlNodePtr node = NULL;
- struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1);
- GNode* subnode = g_node_new (data);
+ struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1);
+ GNode *subnode = g_node_new(data);
g_node_append(plist_node, subnode);
for (node = xml_node->children; node; node = node->next) {
@@ -737,21 +542,21 @@ void xml_to_node (xmlNodePtr xml_node, GNode *plist_node)
}
if (!xmlStrcmp(node->name, "integer")) {
- char* strval = xmlNodeGetContent(node);
+ char *strval = xmlNodeGetContent(node);
data->intval64 = atoi(strval);
data->type = PLIST_UINT64;
continue;
}
- if (!xmlStrcmp(node->name, "real")){
- char* strval = xmlNodeGetContent(node);
+ if (!xmlStrcmp(node->name, "real")) {
+ char *strval = xmlNodeGetContent(node);
data->realval64 = atof(strval);
data->type = PLIST_FLOAT64;
continue;
}
if (!xmlStrcmp(node->name, "date"))
- continue;//TODO : handle date tag
+ continue; //TODO : handle date tag
if (!xmlStrcmp(node->name, "string")) {
data->strval = strdup(xmlNodeGetContent(node));
@@ -773,45 +578,315 @@ void xml_to_node (xmlNodePtr xml_node, GNode *plist_node)
if (!xmlStrcmp(node->name, "array")) {
data->type = PLIST_ARRAY;
- xml_to_node (node, subnode);
+ xml_to_node(node, subnode);
continue;
}
if (!xmlStrcmp(node->name, "dict")) {
data->type = PLIST_DICT;
- xml_to_node (node, subnode);
+ xml_to_node(node, subnode);
continue;
}
}
}
-void plist_to_xml(plist_t plist, char** plist_xml)
+void plist_to_xml(plist_t plist, char **plist_xml)
{
- if (!plist || !plist_xml || *plist_xml) return;
+ if (!plist || !plist_xml || *plist_xml)
+ return;
xmlDocPtr plist_doc = new_plist();
xmlNodePtr root_node = xmlDocGetRootElement(plist_doc);
g_node_children_foreach(plist, G_TRAVERSE_ALL, node_to_xml, root_node);
int size = 0;
- xmlDocDumpMemory (plist_doc, (xmlChar**)plist_xml, &size);
+ xmlDocDumpMemory(plist_doc, (xmlChar **) plist_xml, &size);
}
+GNode *parse_raw_node(const char *bpbuffer, uint32_t bplength, uint32_t * position, uint8_t ref_size)
+{
+ if (!position || !bpbuffer || !bplength)
+ return NULL;
+
+ uint8_t modifier = 0;
+ struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1);
+ GNode *new_node = g_node_new(data);
+ GNode *length_stupidity = NULL;
+
+ int myPos = *position;
+ if (myPos == bplength || (myPos + 1) == bplength) {
+ g_node_destroy(new_node);
+ return NULL;
+ } // end of string
+
+ uint32_t length = 0;
+ if (!myPos) {
+ if (strncmp(bpbuffer, "bplist00", strlen("bplist00"))) {
+ return NULL; // badness!
+ }
+ myPos += strlen("bplist00");
+ }
+ // Get the node's type.
+ if (bpbuffer[myPos] == BPLIST_DATE) { // handle date separately, but do it as a real
+ // better handling of date; basically interpret as real or double
+ data->type = BPLIST_DATE;
+ length = 8; // always 8 for "date" (Apple intended it, not me)
+ myPos++;
+ memcpy(&data->realval64, bpbuffer + myPos, sizeof(data->realval64));
+ byte_convert((char *) &data->realval64, sizeof(data->realval64));
+ myPos += length;
+ *position = myPos;
+ return new_node;
+ }
+
+ int type = bpbuffer[myPos] & BPLIST_MASK;
+ data->length = bpbuffer[myPos] & BPLIST_FILL;
+
+ if (!type) {
+ // what? check if it's a boolean.
+ if (bpbuffer[myPos] == BPLIST_TRUE || bpbuffer[myPos] == BPLIST_FALSE) {
+ // okay, so it is. Carry on.
+ data->type = PLIST_BOOLEAN;
+ data->boolval = TRUE;
+ data->length = 0;
+ } else {
+ // er, what? we have a bad type here. Return NULL.
+ g_node_destroy(new_node);
+ //printf("parse_raw_node: lol type: type given %x\n", bpbuffer[myPos]);
+ return NULL;
+ }
+ }
+
+ myPos++; // puts us in the data.
+ if (length == BPLIST_FILL) { // Data happens to contain length...
+ // what? you're going to make me parse an int for the length. You suck.
+ *position = myPos;
+ length_stupidity = parse_raw_node(bpbuffer, bplength, &myPos, ref_size);
+ switch (((struct plist_data *) length_stupidity->data)->type) {
+ case PLIST_UINT8:
+ data->length = ((struct plist_data *) length_stupidity->data)->intval8;
+ break;
+ case PLIST_UINT16:
+ data->length = ((struct plist_data *) length_stupidity->data)->intval16;
+ break;
+ case PLIST_UINT32:
+ data->length = ((struct plist_data *) length_stupidity->data)->intval32;
+ break;
+ case PLIST_UINT64:
+ data->length = ((struct plist_data *) length_stupidity->data)->intval64;
+ break;
+ default:
+ g_node_destroy(new_node);
+ g_node_destroy(length_stupidity);
+ return NULL;
+ }
+ // There, we have our fucking length now.
+ *position = myPos;
+ g_node_destroy(length_stupidity); // cleanup
+ }
+ // Now we're in the data.
+ // Error-checking sorta
+ if ((myPos + data->length) >= bplength) {
+ data->length = bplength - myPos; // truncate the object
+ }
+ // And now for the greatest show on earth: the giant fucking switch statement.
+ switch (type) {
+ case BPLIST_INT:
+ data->length = uipow(2, data->length); // make length less misleading
+ switch (data->length) {
+ case sizeof(uint8_t):
+ data->type = PLIST_UINT8;
+ data->intval8 = bpbuffer[myPos];
+ break;
+ case sizeof(uint16_t):
+ data->type = PLIST_UINT16;
+ memcpy(&data->intval16, bpbuffer + myPos, sizeof(uint16_t));
+ data->intval16 = ntohs(data->intval16);
+ break;
+ case sizeof(uint32_t):
+ data->type = PLIST_UINT32;
+ memcpy(&data->intval32, bpbuffer + myPos, sizeof(uint32_t));
+ data->intval32 = ntohl(data->intval32);
+ break;
+ case sizeof(uint64_t):
+ data->type = PLIST_UINT64;
+ memcpy(&data->intval64, bpbuffer + myPos, sizeof(uint64_t));
+ byte_convert((char *) &data->intval64, sizeof(uint64_t));
+ break;
+ default:
+ g_node_destroy(new_node);
+ printf("parse_raw_node: lol: invalid int: size given %lu\n", (long unsigned int) length);
+ printf("parse_raw_node: lol: by the way sizeof(uint64) = %i\n", sizeof(uint64_t));
+ return NULL;
+ }
+ break;
+
+ case BPLIST_REAL:
+ data->length = uipow(2, data->length);
+ switch (data->length) {
+ case sizeof(float):
+ data->type = PLIST_FLOAT32;
+ memcpy(&data->realval32, bpbuffer + myPos, data->length);
+ byte_convert((char *) &data->realval32, sizeof(float)); //necessary ??
+ break;
+ case sizeof(double):
+ data->type = PLIST_FLOAT64;
+ memcpy(&data->realval64, bpbuffer + myPos, data->length);
+ byte_convert((char *) &data->realval64, sizeof(double));
+ break;
+ default:
+ g_node_destroy(new_node);
+ printf("parse_raw_node: lol: invalid real: size given %lu\n", (long unsigned int) length);
+ printf("parse_raw_node: lol: by the way sizeof(uint64) = %i\n", sizeof(uint64_t));
+ return NULL;
+ }
+ break;
+
+ case BPLIST_STRING:
+ data->type = PLIST_STRING;
+ data->strval = (char *) malloc(sizeof(char) * data->length);
+ memcpy(data->strval, bpbuffer + myPos, data->length);
+ break;
+
+ case BPLIST_UNICODE:
+ data->type = PLIST_UNICODE;
+ data->unicodeval = (wchar_t *) malloc(sizeof(wchar_t) * data->length);
+ memcpy(data->unicodeval, bpbuffer + myPos, data->length);
+ break;
+
+ case BPLIST_DICT: /* returning a raw dict, it forward-references, so. */
+ data->length = data->length * 2; // dicts lie
+ data->type = PLIST_DICT;
+
+ case BPLIST_ARRAY: /* returning a raw array, it forward-references, so. */
+ 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.
+ if (data->type == 0)
+ data->type = PLIST_ARRAY;
+ case BPLIST_DATA:
+ if (data->type == 0)
+ data->type = PLIST_DATA;
+ default: /* made to hold raw data. */
+ modifier = (data->ref_size > 0) ? data->ref_size : 1;
+ data->buff = (char *) malloc(sizeof(char) * (data->length * modifier));
+ memcpy(data->buff, bpbuffer + myPos, (data->length * modifier));
+ break;
+
+ }
+
+ myPos += data->length;
+ *position = myPos;
+ return new_node;
+}
+
+plist_t parse_nodes(const char *bpbuffer, uint32_t bplength, uint32_t * position)
+{
+ plist_t *nodeslist = NULL, *newaddr = NULL;
+ plist_t new_node = NULL, root_node = NULL;
+
+ uint32_t nodeslength = 0;
+ uint8_t offset_size = 0, dict_param_size = 0;
+ offset_size = bpbuffer[bplength - 26];
+ dict_param_size = bpbuffer[bplength - 25];
+ uint64_t current_offset = 0;
+ uint64_t num_objects = 0, root_object = 0, offset_table_index = 0;
+ memcpy(&num_objects, bpbuffer + bplength - 24, sizeof(uint64_t));
+ memcpy(&root_object, bpbuffer + bplength - 16, sizeof(uint64_t));
+ memcpy(&offset_table_index, bpbuffer + bplength - 8, sizeof(uint64_t));
+ byte_convert((char *) &num_objects, sizeof(uint64_t));
+ byte_convert((char *) &root_object, sizeof(uint64_t));
+ byte_convert((char *) &offset_table_index, sizeof(uint64_t));
+
+ log_debug_msg("Offset size: %i\nGiven: %i\n", offset_size, bpbuffer[bplength - 26]);
+ log_debug_msg("Ref size: %i\nGiven: %i\n", dict_param_size, bpbuffer[bplength - 25]);
+ log_debug_msg("Number of objects: %lli\nGiven: %llu\n", num_objects, *(bpbuffer + bplength - 24));
+ log_debug_msg("Root object index: %lli\nGiven: %llu\n", root_object, *(bpbuffer + bplength - 16));
+ log_debug_msg("Offset table index: %lli\nGiven: %llu\n", offset_table_index, *(bpbuffer + bplength - 8));
+ log_debug_msg("Size of uint64: %i\n", sizeof(uint64_t));
+
+ int i = 0, j = 0, k = 0, str_i = 0, str_j = 0;
+ uint32_t index1 = 0, index2 = 0;
+
+ nodeslist = (plist_t *) malloc(sizeof(plist_t) * num_objects);
+ if (!nodeslist)
+ return NULL;
+
+ for (i = 0; i < num_objects; i++) {
+ memcpy(&current_offset, bpbuffer + (offset_table_index + (i * offset_size)), offset_size);
+ byte_convert((char *) &current_offset,
+ (offset_size <= sizeof(current_offset)) ? offset_size : sizeof(current_offset));
+ log_debug_msg("parse_nodes: current_offset = %x\n", current_offset);
+ nodeslist[i] = parse_raw_node(bpbuffer, bplength, (uint32_t *) & current_offset, dict_param_size);
+ log_debug_msg("parse_nodes: parse_raw_node done\n");
+ }
+
+
+ for (i = 0; i < num_objects; i++) {
+ // set elements for dicts and arrays and leave the rest alone
+ log_debug_msg("parse_nodes: on node %i\n", i);
+ struct plist_data *data = (struct plist_data *) nodeslist[i]->data;
+
+ switch (data->type) {
+ case PLIST_DICT:
+ log_debug_msg("parse_nodes: dictionary found\n");
+ for (j = 0; j < (data->length / 2); j++) {
+ str_i = j * data->ref_size;
+ str_j = (j + (data->length / 2)) * data->ref_size;
+
+ memcpy(&index1, data->buff + str_i, data->ref_size);
+ memcpy(&index2, data->buff + str_j, data->ref_size);
+
+ byte_convert((char *) &index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index2));
+ byte_convert((char *) &index2, (dict_param_size <= sizeof(index2)) ? dict_param_size : sizeof(index2));
+
+ g_node_append(nodeslist[i], nodeslist[index1]);
+ g_node_append(nodeslist[i], nodeslist[index2]);
+ }
+
+ data->length = data->length / 2;
+ free(data->buff);
+ k = 0;
+ break;
+
+ case PLIST_ARRAY:
+ log_debug_msg("parse_nodes: array found\n");
+ for (j = 0; j < data->length; j++) {
+ log_debug_msg("parse_nodes: array index %i\n", j);
+ str_j = j * data->ref_size;
+ memcpy(&index1, data->buff + str_j, data->ref_size);
+ log_debug_msg("parse_nodes: post-memcpy\n");
+ byte_convert((char *) &index1, (dict_param_size <= sizeof(index1)) ? dict_param_size : sizeof(index1));
+ log_debug_msg("parse_nodes: post-ntohl\nindex1 = %i\n", index1);
+ g_node_append(nodeslist[i], nodeslist[index1]);
+ log_debug_msg("parse_nodes: post-assignment\n");
+ }
+ free(data->buff);
+ break;
+ default:
+ //printf("lol... type %x\n", nodeslist[i]->type);
+ break;
+ } // those are the only two we need to correct for.
+ }
+
+ root_node = nodeslist[root_object];
+ return root_node;
+}
-void plist_to_bin(plist_t plist, char** plist_bin)
+void plist_to_bin(plist_t plist, char **plist_bin, int *length)
{
}
-void xml_to_plist(const char* plist_xml, plist_t* plist)
+void xml_to_plist(const char *plist_xml, plist_t * plist)
{
xmlDocPtr plist_doc = xmlReadMemory(plist_xml, strlen(plist_xml), NULL, NULL, 0);
xmlNodePtr root_node = xmlDocGetRootElement(plist_doc);
- struct plist_data* data = (struct plist_data*)calloc(sizeof(struct plist_data), 1);
- *plist = g_node_new (data);
+ struct plist_data *data = (struct plist_data *) calloc(sizeof(struct plist_data), 1);
+ *plist = g_node_new(data);
data->type = PLIST_PLIST;
- xml_to_node (root_node, *plist);
+ xml_to_node(root_node, *plist);
}
-void bin_to_plist(const char* plist_bin, plist_t* plist)
+void bin_to_plist(const char *plist_bin, int length, plist_t * plist)
{
+ uint32_t pos = 0;
+ *plist = parse_nodes(plist_bin, length, &pos);
}
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);
/* Binary plist stuff */
-enum {
- BPLIST_TRUE = 0x08,
- BPLIST_FALSE = 0x09,
- BPLIST_FILL = 0x0F, /* will be used for length grabbing */
- BPLIST_INT = 0x10,
- BPLIST_REAL = 0x20,
- BPLIST_DATE = 0x33,
- BPLIST_DATA = 0x40,
- BPLIST_STRING = 0x50,
- BPLIST_UNICODE = 0x60,
- BPLIST_UID = 0x70,
- BPLIST_ARRAY = 0xA0,
- BPLIST_SET = 0xC0,
- BPLIST_DICT = 0xD0,
- BPLIST_MASK = 0xF0
-};
-typedef struct _bplist_node {
- struct _bplist_node *next, **subnodes; // subnodes is for arrays, dicts and (potentially) sets.
- uint64_t length, intval64;
- uint32_t intval32; // length = subnodes
- uint16_t intval16;
- uint8_t intval8;
- uint8_t type, *indexes; // indexes for array-types; essentially specify the order in which to access for key => value pairs
- char *strval;
- double realval;
- wchar_t *unicodeval;
-} bplist_node;
-
-bplist_node *parse_nodes(const char *bpbuffer, uint32_t bplength, uint32_t * position);
-
-typedef enum {
+typedef enum {
PLIST_BOOLEAN,
PLIST_UINT8,
PLIST_UINT16,
@@ -100,15 +70,15 @@ typedef GNode *plist_t;
typedef GNode *dict_t;
typedef GNode *array_t;
-void plist_new_plist(plist_t* plist);
-void plist_new_dict_in_plist(plist_t plist, dict_t* dict);
-void plist_new_array_in_plist(plist_t plist, int length, plist_type type, void** values, array_t* array);
-void plist_add_dict_element(dict_t dict, char* key, plist_type type, void* value);
+void plist_new_plist(plist_t * plist);
+void plist_new_dict_in_plist(plist_t plist, dict_t * dict);
+void plist_new_array_in_plist(plist_t plist, int length, plist_type type, void **values, array_t * array);
+void plist_add_dict_element(dict_t dict, char *key, plist_type type, void *value);
void plist_free(plist_t plist);
-void plist_to_xml(plist_t plist, char** plist_xml);
-void plist_to_bin(plist_t plist, char** plist_bin);
+void plist_to_xml(plist_t plist, char **plist_xml);
+void plist_to_bin(plist_t plist, char **plist_bin, int *length);
-void xml_to_plist(const char* plist_xml, plist_t* plist);
-void bin_to_plist(const char* plist_bin, plist_t* plist);
+void xml_to_plist(const char *plist_xml, plist_t * plist);
+void bin_to_plist(const char *plist_bin, int length, plist_t * plist);
#endif