mirror of
https://github.com/libimobiledevice/libplist
synced 2026-06-08 15:29:34 +00:00
implemented handling of UID keyed encoding type
This commit is contained in:
@@ -83,6 +83,7 @@ extern "C"
|
||||
PLIST_DATE, /**< Date, scalar type */
|
||||
PLIST_DATA, /**< Binary data, scalar type */
|
||||
PLIST_KEY, /**< Key in dictionaries (ASCII String), scalar type */
|
||||
PLIST_UID, /**< Special type used for 'keyed encoding' */
|
||||
PLIST_NONE /**< No type */
|
||||
} plist_type;
|
||||
|
||||
@@ -165,6 +166,15 @@ extern "C"
|
||||
*/
|
||||
PLIST_API plist_t plist_new_date(int32_t sec, int32_t usec);
|
||||
|
||||
/**
|
||||
* Create a new plist_t type #PLIST_UID
|
||||
*
|
||||
* @param val the unsigned integer value
|
||||
* @return the created item
|
||||
* @sa #plist_type
|
||||
*/
|
||||
PLIST_API plist_t plist_new_uid(uint64_t val);
|
||||
|
||||
/**
|
||||
* Destruct a plist_t node and all its children recursively
|
||||
*
|
||||
@@ -416,6 +426,15 @@ extern "C"
|
||||
*/
|
||||
PLIST_API void plist_get_date_val(plist_t node, int32_t * sec, int32_t * usec);
|
||||
|
||||
/**
|
||||
* Get the value of a #PLIST_UID node.
|
||||
* This function does nothing if node is not of type #PLIST_UID
|
||||
*
|
||||
* @param node the node
|
||||
* @param val a pointer to a uint64_t variable.
|
||||
*/
|
||||
PLIST_API void plist_get_uid_val(plist_t node, uint64_t * val);
|
||||
|
||||
|
||||
/********************************************
|
||||
* *
|
||||
@@ -496,6 +515,15 @@ extern "C"
|
||||
*/
|
||||
PLIST_API void plist_set_date_val(plist_t node, int32_t sec, int32_t usec);
|
||||
|
||||
/**
|
||||
* Set the value of a node.
|
||||
* Forces type of node to #PLIST_UID
|
||||
*
|
||||
* @param node the node
|
||||
* @param val the unsigned integer value
|
||||
*/
|
||||
PLIST_API void plist_set_uid_val(plist_t node, uint64_t val);
|
||||
|
||||
|
||||
/********************************************
|
||||
* *
|
||||
|
||||
+58
-2
@@ -63,7 +63,8 @@ enum
|
||||
BPLIST_DATA = 0x40,
|
||||
BPLIST_STRING = 0x50,
|
||||
BPLIST_UNICODE = 0x60,
|
||||
BPLIST_UID = 0x70,
|
||||
BPLIST_UNK_0x70 = 0x70,
|
||||
BPLIST_UID = 0x80,
|
||||
BPLIST_ARRAY = 0xA0,
|
||||
BPLIST_SET = 0xC0,
|
||||
BPLIST_DICT = 0xD0,
|
||||
@@ -375,6 +376,31 @@ static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size)
|
||||
return node_create(NULL, data);
|
||||
}
|
||||
|
||||
static plist_t parse_uid_node(char *bnode, uint8_t size, char **next_object)
|
||||
{
|
||||
plist_data_t data = plist_new_plist_data();
|
||||
|
||||
size = 1 << size; // make length less misleading
|
||||
switch (size)
|
||||
{
|
||||
case sizeof(uint8_t):
|
||||
case sizeof(uint16_t):
|
||||
case sizeof(uint32_t):
|
||||
case sizeof(uint64_t):
|
||||
memcpy(&data->intval, bnode, size);
|
||||
data->intval = UINT_TO_HOST(&data->intval, size);
|
||||
break;
|
||||
default:
|
||||
free(data);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
*next_object = bnode + size;
|
||||
data->type = PLIST_UID;
|
||||
data->length = sizeof(uint64_t);
|
||||
|
||||
return node_create(NULL, data);
|
||||
}
|
||||
|
||||
|
||||
static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_object)
|
||||
@@ -464,7 +490,7 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
|
||||
}
|
||||
return parse_unicode_node(object, size);
|
||||
|
||||
case BPLIST_UID:
|
||||
case BPLIST_UNK_0x70:
|
||||
case BPLIST_ARRAY:
|
||||
if (0x0F == size)
|
||||
{
|
||||
@@ -476,6 +502,9 @@ static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_objec
|
||||
}
|
||||
return parse_array_node(object, size, dict_size);
|
||||
|
||||
case BPLIST_UID:
|
||||
return parse_uid_node(object, size, next_object);
|
||||
|
||||
case BPLIST_SET:
|
||||
case BPLIST_DICT:
|
||||
if (0x0F == size)
|
||||
@@ -528,6 +557,9 @@ static void* copy_plist_data(const void* src)
|
||||
dstdata->buff = (uint8_t*) malloc(sizeof(uint8_t) * srcdata->length * 2);
|
||||
memcpy(dstdata->buff, srcdata->buff, sizeof(uint8_t) * srcdata->length * 2);
|
||||
break;
|
||||
case PLIST_UID:
|
||||
dstdata->intval = srcdata->intval;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -672,6 +704,7 @@ static unsigned int plist_data_hash(const void* key)
|
||||
case PLIST_BOOLEAN:
|
||||
case PLIST_UINT:
|
||||
case PLIST_REAL:
|
||||
case PLIST_UID:
|
||||
buff = (char *) &data->intval; //works also for real as we use an union
|
||||
size = 8;
|
||||
break;
|
||||
@@ -916,6 +949,26 @@ static void write_dict(bytearray_t * bplist, node_t* node, hashtable_t* ref_tabl
|
||||
|
||||
}
|
||||
|
||||
static void write_uid(bytearray_t * bplist, uint64_t val)
|
||||
{
|
||||
uint64_t size = get_needed_bytes(val);
|
||||
uint8_t *buff = NULL;
|
||||
//do not write 3bytes int node
|
||||
if (size == 3)
|
||||
size++;
|
||||
|
||||
#if PLIST_BYTE_ORDER == PLIST_BIG_ENDIAN
|
||||
val = val << ((sizeof(uint64_t) - size) * 8);
|
||||
#endif
|
||||
|
||||
buff = (uint8_t *) malloc(sizeof(uint8_t) + size);
|
||||
buff[0] = BPLIST_UID | Log2(size);
|
||||
memcpy(buff + 1, &val, size);
|
||||
byte_convert(buff + 1, size);
|
||||
byte_array_append(bplist, buff, sizeof(uint8_t) + size);
|
||||
free(buff);
|
||||
}
|
||||
|
||||
static int is_ascii_string(char* s, int len)
|
||||
{
|
||||
int ret = 1, i = 0;
|
||||
@@ -1074,6 +1127,9 @@ void plist_to_bin(plist_t plist, char **plist_bin, uint32_t * length)
|
||||
case PLIST_DATE:
|
||||
write_date(bplist_buff, data->timeval.tv_sec + (double) data->timeval.tv_usec / 1000000);
|
||||
break;
|
||||
case PLIST_UID:
|
||||
write_uid(bplist_buff, data->intval);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
+27
@@ -138,6 +138,15 @@ plist_t plist_new_uint(uint64_t val)
|
||||
return plist_new_node(data);
|
||||
}
|
||||
|
||||
plist_t plist_new_uid(uint64_t val)
|
||||
{
|
||||
plist_data_t data = plist_new_plist_data();
|
||||
data->type = PLIST_UID;
|
||||
data->intval = val;
|
||||
data->length = sizeof(uint64_t);
|
||||
return plist_new_node(data);
|
||||
}
|
||||
|
||||
plist_t plist_new_real(double val)
|
||||
{
|
||||
plist_data_t data = plist_new_plist_data();
|
||||
@@ -490,6 +499,7 @@ static void plist_get_type_and_value(plist_t node, plist_type * type, void *valu
|
||||
*((char *) value) = data->boolval;
|
||||
break;
|
||||
case PLIST_UINT:
|
||||
case PLIST_UID:
|
||||
*((uint64_t *) value) = data->intval;
|
||||
break;
|
||||
case PLIST_REAL:
|
||||
@@ -567,6 +577,15 @@ void plist_get_uint_val(plist_t node, uint64_t * val)
|
||||
assert(length == sizeof(uint64_t));
|
||||
}
|
||||
|
||||
void plist_get_uid_val(plist_t node, uint64_t * val)
|
||||
{
|
||||
plist_type type = plist_get_node_type(node);
|
||||
uint64_t length = 0;
|
||||
if (PLIST_UID == type)
|
||||
plist_get_type_and_value(node, &type, (void *) val, &length);
|
||||
assert(length == sizeof(uint64_t));
|
||||
}
|
||||
|
||||
void plist_get_real_val(plist_t node, double *val)
|
||||
{
|
||||
plist_type type = plist_get_node_type(node);
|
||||
@@ -617,6 +636,7 @@ int plist_data_compare(const void *a, const void *b)
|
||||
case PLIST_BOOLEAN:
|
||||
case PLIST_UINT:
|
||||
case PLIST_REAL:
|
||||
case PLIST_UID:
|
||||
if (val_a->intval == val_b->intval) //it is an union so this is sufficient
|
||||
return TRUE;
|
||||
else
|
||||
@@ -690,6 +710,7 @@ static void plist_set_element_val(plist_t node, plist_type type, const void *val
|
||||
data->boolval = *((char *) value);
|
||||
break;
|
||||
case PLIST_UINT:
|
||||
case PLIST_UID:
|
||||
data->intval = *((uint64_t *) value);
|
||||
break;
|
||||
case PLIST_REAL:
|
||||
@@ -728,6 +749,7 @@ void plist_set_type(plist_t node, plist_type type)
|
||||
data->length = sizeof(uint8_t);
|
||||
break;
|
||||
case PLIST_UINT:
|
||||
case PLIST_UID:
|
||||
data->length = sizeof(uint64_t);
|
||||
break;
|
||||
case PLIST_REAL:
|
||||
@@ -763,6 +785,11 @@ void plist_set_uint_val(plist_t node, uint64_t val)
|
||||
plist_set_element_val(node, PLIST_UINT, &val, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
void plist_set_uid_val(plist_t node, uint64_t val)
|
||||
{
|
||||
plist_set_element_val(node, PLIST_UID, &val, sizeof(uint64_t));
|
||||
}
|
||||
|
||||
void plist_set_real_val(plist_t node, double val)
|
||||
{
|
||||
plist_set_element_val(node, PLIST_REAL, &val, sizeof(double));
|
||||
|
||||
@@ -126,6 +126,25 @@ static xmlDocPtr new_xml_plist(void)
|
||||
return plist_xml;
|
||||
}
|
||||
|
||||
static struct node_t* new_key_node(const char* name)
|
||||
{
|
||||
plist_data_t data = plist_new_plist_data();
|
||||
data->type = PLIST_KEY;
|
||||
int size = strlen(name);
|
||||
data->strval = strdup(name);
|
||||
data->length = size;
|
||||
return node_create(NULL, data);
|
||||
}
|
||||
|
||||
static struct node_t* new_uint_node(uint64_t uint)
|
||||
{
|
||||
plist_data_t data = plist_new_plist_data();
|
||||
data->type = PLIST_UINT;
|
||||
data->intval = uint;
|
||||
data->length = sizeof(uint64_t);
|
||||
return node_create(NULL, data);
|
||||
}
|
||||
|
||||
static void node_to_xml(node_t* node, void *xml_struct)
|
||||
{
|
||||
struct xml_node *xstruct = NULL;
|
||||
@@ -133,6 +152,7 @@ static void node_to_xml(node_t* node, void *xml_struct)
|
||||
|
||||
xmlNodePtr child_node = NULL;
|
||||
char isStruct = FALSE;
|
||||
char isUIDNode = FALSE;
|
||||
|
||||
const xmlChar *tag = NULL;
|
||||
char *val = NULL;
|
||||
@@ -214,6 +234,15 @@ static void node_to_xml(node_t* node, void *xml_struct)
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PLIST_UID:
|
||||
// special case for keyed encoding
|
||||
tag = XPLIST_DICT;
|
||||
isStruct = TRUE;
|
||||
isUIDNode = TRUE;
|
||||
node_data->type = PLIST_DICT;
|
||||
node_attach(node, new_key_node("CF$UID"));
|
||||
node_attach(node, new_uint_node(node_data->intval));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -256,6 +285,17 @@ static void node_to_xml(node_t* node, void *xml_struct)
|
||||
xmlNodeAddContent(child_node, BAD_CAST("\t"));
|
||||
}
|
||||
}
|
||||
if (isUIDNode)
|
||||
{
|
||||
unsigned int num = node_n_children(node);
|
||||
unsigned int i;
|
||||
for (i = num; i > 0; i--) {
|
||||
node_t* ch = node_nth_child(node, i-1);
|
||||
node_detach(node, ch);
|
||||
node_destroy(ch);
|
||||
}
|
||||
node_data->type = PLIST_UID;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -406,6 +446,21 @@ static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node)
|
||||
{
|
||||
data->type = PLIST_DICT;
|
||||
xml_to_node(node, &subnode);
|
||||
if (plist_get_node_type(subnode) == PLIST_DICT) {
|
||||
if (plist_dict_get_size(subnode) == 1) {
|
||||
plist_t uid = plist_dict_get_item(subnode, "CF$UID");
|
||||
if (uid) {
|
||||
uint64_t val = 0;
|
||||
plist_get_uint_val(uid, &val);
|
||||
plist_dict_remove_item(subnode, "CF$UID");
|
||||
plist_data_t nodedata = plist_get_data((node_t*)subnode);
|
||||
free(nodedata->buff);
|
||||
nodedata->type = PLIST_UID;
|
||||
nodedata->length = sizeof(uint64_t);
|
||||
nodedata->intval = val;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user