static plist_t parse_real_node(char *bnode, uint8_t size) { plist_data_t data = plist_new_plist_data(); float floatval = 0.0; uint8_t* buf; size = 1 << size; // make length less misleading buf = malloc (size); memcpy (buf, bnode, size); switch (size) { case sizeof(float): float_byte_convert(buf, size); floatval = *(float *) buf; data->realval = floatval; break; case sizeof(double): float_byte_convert(buf, size); data->realval = *(double *) buf; break; default: free(data); return NULL; } free (buf); data->type = PLIST_REAL; data->length = sizeof(double); return g_node_new(data); }
static plist_t parse_uint_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_UINT; data->length = sizeof(uint64_t); return g_node_new(data); }
static plist_t parse_unicode_node(char *bnode, uint64_t size) { plist_data_t data = plist_new_plist_data(); uint64_t i = 0; gunichar2 *unicodestr = NULL; gchar *tmpstr = NULL; glong items_read = 0; glong items_written = 0; GError *error = NULL; data->type = PLIST_STRING; unicodestr = (gunichar2 *) malloc(sizeof(gunichar2) * size); memcpy(unicodestr, bnode, sizeof(gunichar2) * size); for (i = 0; i < size; i++) byte_convert((uint8_t *) (unicodestr + i), sizeof(gunichar2)); tmpstr = g_utf16_to_utf8(unicodestr, size, &items_read, &items_written, &error); free(unicodestr); data->type = PLIST_STRING; data->strval = (char *) malloc(sizeof(char) * (items_written + 1)); memcpy(data->strval, tmpstr, items_written); data->strval[items_written] = '\0'; data->length = strlen(data->strval); g_free(tmpstr); return g_node_new(data); }
void plist_set_type(plist_t node, plist_type type) { if ( node_n_children(node) == 0 ) { plist_data_t data = plist_get_data(node); plist_free_data( data ); data = plist_new_plist_data(); data->type = type; switch (type) { case PLIST_BOOLEAN: data->length = sizeof(uint8_t); break; case PLIST_UINT: case PLIST_UID: data->length = sizeof(uint64_t); break; case PLIST_REAL: data->length = sizeof(double); break; case PLIST_DATE: data->length = sizeof(struct timeval); break; default: data->length = 0; break; } } }
static void plist_copy_node(GNode * node, gpointer parent_node_ptr) { plist_t newnode = NULL; plist_data_t data = plist_get_data(node); plist_data_t newdata = plist_new_plist_data(); assert(data); // plist should always have data memcpy(newdata, data, sizeof(struct plist_data_s)); plist_type node_type = plist_get_node_type(node); if (node_type == PLIST_DATA || node_type == PLIST_STRING || node_type == PLIST_KEY) { switch (node_type) { case PLIST_DATA: newdata->buff = (uint8_t *) malloc(data->length); memcpy(newdata->buff, data->buff, data->length); case PLIST_KEY: case PLIST_STRING: newdata->strval = strdup((char *) data->strval); default: break; } } newnode = plist_new_node(newdata); if (*(plist_t*)parent_node_ptr) { g_node_append(*(plist_t*)parent_node_ptr, newnode); } else { *(plist_t*)parent_node_ptr = newnode; } g_node_children_foreach(node, G_TRAVERSE_ALL, plist_copy_node, &newnode); }
plist_t plist_new_bool(uint8_t val) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_BOOLEAN; data->boolval = val; data->length = sizeof(uint8_t); 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(); data->type = PLIST_REAL; data->realval = val; data->length = sizeof(double); return plist_new_node(data); }
plist_t plist_new_string(const char *val) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_STRING; data->strval = strdup(val); data->length = strlen(val); return plist_new_node(data); }
//These nodes should not be handled by users static plist_t plist_new_key(const char *val) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_KEY; data->strval = strdup(val); data->length = strlen(val); return plist_new_node(data); }
static struct node_t* new_uint_node(uint64_t value) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_UINT; data->intval = value; data->length = sizeof(uint64_t); return node_create(NULL, data); }
plist_t plist_new_date(int32_t sec, int32_t usec) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_DATE; data->timeval.tv_sec = sec; data->timeval.tv_usec = usec; data->length = sizeof(struct timeval); return plist_new_node(data); }
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); }
plist_t plist_new_data(const char *val, uint64_t length) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_DATA; data->buff = (uint8_t *) malloc(length); memcpy(data->buff, val, length); data->length = length; return plist_new_node(data); }
static plist_t parse_array_node(char *bnode, uint64_t size, uint32_t ref_size) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_ARRAY; data->length = size; data->buff = (uint8_t *) malloc(sizeof(uint8_t) * size * ref_size); memcpy(data->buff, bnode, sizeof(uint8_t) * size * ref_size); return g_node_new(data); }
static plist_t parse_string_node(char *bnode, uint64_t size) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_STRING; data->strval = (char *) malloc(sizeof(char) * (size + 1)); memcpy(data->strval, bnode, size); data->strval[size] = '\0'; data->length = strlen(data->strval); return g_node_new(data); }
static plist_t plist_add_sub_element(plist_t node, plist_type type, const void *value, uint64_t length) { //only structured types can have children plist_type node_type = plist_get_node_type(node); if (node_type == PLIST_DICT || node_type == PLIST_ARRAY) { //only structured types are allowed to have nulll value if (value || (!value && (type == PLIST_DICT || type == PLIST_ARRAY))) { plist_t subnode = NULL; //now handle value plist_data_t data = plist_new_plist_data(); data->type = type; data->length = length; switch (type) { case PLIST_BOOLEAN: data->boolval = *((char *) value); break; case PLIST_UINT: data->intval = *((uint64_t *) value); break; case PLIST_REAL: data->realval = *((double *) value); break; case PLIST_KEY: case PLIST_STRING: data->strval = strdup((char *) value); break; case PLIST_DATA: data->buff = (uint8_t *) malloc(length); memcpy(data->buff, value, length); break; case PLIST_DATE: data->timeval.tv_sec = ((GTimeVal *) value)->tv_sec; data->timeval.tv_usec = ((GTimeVal *) value)->tv_usec; break; case PLIST_ARRAY: case PLIST_DICT: default: break; } subnode = plist_new_node(data); if (node) g_node_append(node, subnode); return subnode; } else return NULL; } return NULL; }
static void plist_copy_node(node_t *node, void *parent_node_ptr) { plist_type node_type = PLIST_NONE; plist_t newnode = NULL; plist_data_t data = plist_get_data(node); plist_data_t newdata = plist_new_plist_data(); assert(data); // plist should always have data memcpy(newdata, data, sizeof(struct plist_data_s)); node_type = plist_get_node_type(node); if (node_type == PLIST_DATA || node_type == PLIST_STRING || node_type == PLIST_KEY) { switch (node_type) { case PLIST_DATA: newdata->buff = (uint8_t *) malloc(data->length); memcpy(newdata->buff, data->buff, data->length); break; case PLIST_KEY: case PLIST_STRING: newdata->strval = strdup((char *) data->strval); break; default: break; } } newnode = plist_new_node(newdata); if (*(plist_t*)parent_node_ptr) { node_attach(*(plist_t*)parent_node_ptr, newnode); } else { *(plist_t*)parent_node_ptr = newnode; } node_iterator_t *ni = node_iterator_create(node->children); node_t *ch; while ((ch = node_iterator_next(ni))) { plist_copy_node(ch, &newnode); } node_iterator_destroy(ni); }
static gpointer copy_plist_data(gconstpointer src, gpointer data) { plist_data_t srcdata = (plist_data_t) src; plist_data_t dstdata = plist_new_plist_data(); dstdata->type = srcdata->type; dstdata->length = srcdata->length; switch (dstdata->type) { case PLIST_BOOLEAN: dstdata->boolval = srcdata->boolval; break; case PLIST_UINT: dstdata->intval = srcdata->intval; break; case PLIST_DATE: dstdata->timeval.tv_sec = srcdata->timeval.tv_sec; dstdata->timeval.tv_usec = srcdata->timeval.tv_usec; break; case PLIST_REAL: dstdata->realval = srcdata->realval; break; case PLIST_KEY: case PLIST_STRING: dstdata->strval = strdup(srcdata->strval); break; case PLIST_DATA: case PLIST_ARRAY: dstdata->buff = (uint8_t *) malloc(sizeof(uint8_t *) * srcdata->length); memcpy(dstdata->buff, srcdata->buff, sizeof(uint8_t *) * srcdata->length); break; case PLIST_DICT: dstdata->buff = (uint8_t *) malloc(sizeof(uint8_t *) * srcdata->length * 2); memcpy(dstdata->buff, srcdata->buff, sizeof(uint8_t *) * srcdata->length * 2); break; default: break; } return dstdata; }
static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) { xmlNodePtr node = NULL; plist_data_t data = NULL; plist_t subnode = NULL; //for string long len = 0; int type = 0; if (!xml_node) return; for (node = xml_node->children; node; node = node->next) { while (node && !xmlStrcmp(node->name, XPLIST_TEXT)) node = node->next; if (!node) break; if (!xmlStrcmp(node->name, BAD_CAST("comment"))) { continue; } data = plist_new_plist_data(); subnode = plist_new_node(data); if (*plist_node) node_attach(*plist_node, subnode); else *plist_node = subnode; if (!xmlStrcmp(node->name, XPLIST_TRUE)) { data->boolval = TRUE; data->type = PLIST_BOOLEAN; data->length = 1; continue; } if (!xmlStrcmp(node->name, XPLIST_FALSE)) { data->boolval = FALSE; data->type = PLIST_BOOLEAN; data->length = 1; continue; } if (!xmlStrcmp(node->name, XPLIST_INT)) { xmlChar *strval = xmlNodeGetContent(node); int is_negative = 0; char *str = (char*)strval; if ((str[0] == '-') || (str[0] == '+')) { if (str[0] == '-') { is_negative = 1; } str++; } char* endp = NULL; data->intval = strtoull((char*)str, &endp, 0); if ((endp != NULL) && (strlen(endp) > 0)) { fprintf(stderr, "%s: integer parse error: string contains invalid characters: '%s'\n", __func__, endp); } if (is_negative || (data->intval <= INT64_MAX)) { int64_t v = data->intval; if (is_negative) { v = -v; } data->intval = (uint64_t)v; data->length = 8; } else { data->length = 16; } data->type = PLIST_UINT; xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_REAL)) { xmlChar *strval = xmlNodeGetContent(node); data->realval = atof((char *) strval); data->type = PLIST_REAL; data->length = 8; xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_DATE)) { xmlChar *strval = xmlNodeGetContent(node); time_t timev = 0; if (strlen((const char*)strval) >= 11) { struct tm btime; struct tm* tm_utc; parse_date((const char*)strval, &btime); timev = mktime(&btime); tm_utc = gmtime(&timev); timev -= (mktime(tm_utc) - timev); } data->timeval.tv_sec = (long)(timev - MAC_EPOCH); data->timeval.tv_usec = 0; data->type = PLIST_DATE; data->length = sizeof(struct timeval); xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_STRING)) { xmlChar *strval = xmlNodeGetContent(node); len = strlen((char *) strval); type = xmlDetectCharEncoding(strval, len); if (XML_CHAR_ENCODING_UTF8 == type || XML_CHAR_ENCODING_ASCII == type || XML_CHAR_ENCODING_NONE == type) { data->strval = strdup((char *) strval); data->type = PLIST_STRING; data->length = strlen(data->strval); } xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_KEY)) { xmlChar *strval = xmlNodeGetContent(node); len = strlen((char *) strval); type = xmlDetectCharEncoding(strval, len); if (XML_CHAR_ENCODING_UTF8 == type || XML_CHAR_ENCODING_ASCII == type || XML_CHAR_ENCODING_NONE == type) { data->strval = strdup((char *) strval); data->type = PLIST_KEY; data->length = strlen(data->strval); } xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_DATA)) { xmlChar *strval = xmlNodeGetContent(node); size_t size = 0; unsigned char *dec = base64decode((char*)strval, &size); data->buff = (uint8_t *) malloc(size * sizeof(uint8_t)); memcpy(data->buff, dec, size * sizeof(uint8_t)); free(dec); data->length = size; data->type = PLIST_DATA; xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_ARRAY)) { data->type = PLIST_ARRAY; xml_to_node(node, &subnode); continue; } if (!xmlStrcmp(node->name, XPLIST_DICT)) { 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; } } }
static plist_t parse_bin_node(char *object, uint8_t dict_size, char **next_object) { uint16_t type = 0; uint64_t size = 0; if (!object) return NULL; type = (*object) & 0xF0; size = (*object) & 0x0F; object++; switch (type) { case BPLIST_NULL: switch (size) { case BPLIST_TRUE: { plist_data_t data = plist_new_plist_data(); data->type = PLIST_BOOLEAN; data->boolval = TRUE; data->length = 1; return g_node_new(data); } case BPLIST_FALSE: { plist_data_t data = plist_new_plist_data(); data->type = PLIST_BOOLEAN; data->boolval = FALSE; data->length = 1; return g_node_new(data); } case BPLIST_NULL: default: return NULL; } case BPLIST_UINT: return parse_uint_node(object, size, next_object); case BPLIST_REAL: return parse_real_node(object, size); case BPLIST_DATE: if (3 != size) return NULL; else return parse_date_node(object, size); case BPLIST_DATA: if (0x0F == size) { plist_t size_node = parse_bin_node(object, dict_size, &object); if (plist_get_node_type(size_node) != PLIST_UINT) return NULL; plist_get_uint_val(size_node, &size); plist_free(size_node); } return parse_data_node(object, size); case BPLIST_STRING: if (0x0F == size) { plist_t size_node = parse_bin_node(object, dict_size, &object); if (plist_get_node_type(size_node) != PLIST_UINT) return NULL; plist_get_uint_val(size_node, &size); plist_free(size_node); } return parse_string_node(object, size); case BPLIST_UNICODE: if (0x0F == size) { plist_t size_node = parse_bin_node(object, dict_size, &object); if (plist_get_node_type(size_node) != PLIST_UINT) return NULL; plist_get_uint_val(size_node, &size); plist_free(size_node); } return parse_unicode_node(object, size); case BPLIST_UID: case BPLIST_ARRAY: if (0x0F == size) { plist_t size_node = parse_bin_node(object, dict_size, &object); if (plist_get_node_type(size_node) != PLIST_UINT) return NULL; plist_get_uint_val(size_node, &size); plist_free(size_node); } return parse_array_node(object, size, dict_size); case BPLIST_SET: case BPLIST_DICT: if (0x0F == size) { plist_t size_node = parse_bin_node(object, dict_size, &object); if (plist_get_node_type(size_node) != PLIST_UINT) return NULL; plist_get_uint_val(size_node, &size); plist_free(size_node); } return parse_dict_node(object, size, dict_size); default: return NULL; } return NULL; }
plist_t plist_new_array(void) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_ARRAY; return plist_new_node(data); }
plist_t plist_new_dict(void) { plist_data_t data = plist_new_plist_data(); data->type = PLIST_DICT; return plist_new_node(data); }
static void xml_to_node(xmlNodePtr xml_node, plist_t * plist_node) { xmlNodePtr node = NULL; plist_data_t data = NULL; plist_t subnode = NULL; //for string long len = 0; int type = 0; if (!xml_node) return; for (node = xml_node->children; node; node = node->next) { while (node && !xmlStrcmp(node->name, XPLIST_TEXT)) node = node->next; if (!node) break; if (!xmlStrcmp(node->name, BAD_CAST("comment"))) { continue; } data = plist_new_plist_data(); subnode = plist_new_node(data); if (*plist_node) node_attach(*plist_node, subnode); else *plist_node = subnode; if (!xmlStrcmp(node->name, XPLIST_TRUE)) { data->boolval = TRUE; data->type = PLIST_BOOLEAN; data->length = 1; continue; } if (!xmlStrcmp(node->name, XPLIST_FALSE)) { data->boolval = FALSE; data->type = PLIST_BOOLEAN; data->length = 1; continue; } if (!xmlStrcmp(node->name, XPLIST_INT)) { xmlChar *strval = xmlNodeGetContent(node); data->intval = strtoull((char*)strval, NULL, 0); data->type = PLIST_UINT; data->length = 8; xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_REAL)) { xmlChar *strval = xmlNodeGetContent(node); data->realval = atof((char *) strval); data->type = PLIST_REAL; data->length = 8; xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_DATE)) { xmlChar *strval = xmlNodeGetContent(node); time_t time = 0; if (strlen((const char*)strval) >= 11) { struct tm btime; parse_date((const char*)strval, &btime); time = mktime(&btime); } data->timeval.tv_sec = (long)time; data->timeval.tv_usec = 0; data->type = PLIST_DATE; data->length = sizeof(struct timeval); xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_STRING)) { xmlChar *strval = xmlNodeGetContent(node); len = strlen((char *) strval); type = xmlDetectCharEncoding(strval, len); if (XML_CHAR_ENCODING_UTF8 == type || XML_CHAR_ENCODING_ASCII == type || XML_CHAR_ENCODING_NONE == type) { data->strval = strdup((char *) strval); data->type = PLIST_STRING; data->length = strlen(data->strval); } xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_KEY)) { xmlChar *strval = xmlNodeGetContent(node); data->strval = strdup((char *) strval); data->type = PLIST_KEY; data->length = strlen(data->strval); xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_DATA)) { xmlChar *strval = xmlNodeGetContent(node); size_t size = 0; unsigned char *dec = base64decode((char*)strval, &size); data->buff = (uint8_t *) malloc(size * sizeof(uint8_t)); memcpy(data->buff, dec, size * sizeof(uint8_t)); free(dec); data->length = size; data->type = PLIST_DATA; xmlFree(strval); continue; } if (!xmlStrcmp(node->name, XPLIST_ARRAY)) { data->type = PLIST_ARRAY; xml_to_node(node, &subnode); continue; } if (!xmlStrcmp(node->name, XPLIST_DICT)) { 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; } } }