Commit 889cb32a authored by Jonathan Beck's avatar Jonathan Beck

Continue abstraction of xml and binary plist.

parent 831ee461
......@@ -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;
}
......
......@@ -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);
}
......@@ -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
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment