void plist_dict_insert_item(plist_t node, const char* key, plist_t item) { if (node && PLIST_DICT == plist_get_node_type(node)) { node_attach(node, plist_new_key(key)); node_attach(node, item); } return; }
node_t* node_create(node_t* parent, void* data) { int error = 0; node_t* node = (node_t*) malloc(sizeof(node_t)); if(node == NULL) { return NULL; } memset(node, '\0', sizeof(node_t)); node->data = data; node->depth = 0; node->next = NULL; node->prev = NULL; node->count = 0; node->isLeaf = TRUE; node->isRoot = TRUE; node->parent = NULL; node->children = node_list_create(); // Pass NULL to create a root node if(parent != NULL) { // This is a child node so attach it to it's parent error = node_attach(parent, node); if(error < 0) { // Unable to attach nodes printf("ERROR: %d \"Unable to attach nodes\"\n", error); node_destroy(node); return NULL; } } return node; }
void plist_array_append_item(plist_t node, plist_t item) { if (node && PLIST_ARRAY == plist_get_node_type(node)) { node_attach(node, item); } return; }
PLIST_API void plist_dict_set_item(plist_t node, const char* key, plist_t item) { if (node && PLIST_DICT == plist_get_node_type(node)) { node_t* old_item = plist_dict_get_item(node, key); if (old_item) { int idx = plist_free_node(old_item); if (idx < 0) { node_attach(node, item); } else { node_insert(node, idx, item); } } else { node_attach(node, plist_new_key(key)); node_attach(node, item); } } return; }
node_t* node_copy_deep(node_t* node, copy_func_t copy_func) { if (!node) return NULL; void *data = NULL; if (copy_func) { data = copy_func(node->data); } node_t* copy = node_create(NULL, data); node_t* ch; for (ch = node_first_child(node); ch; ch = node_next_sibling(ch)) { node_t* cc = node_copy_deep(ch, copy_func); node_attach(copy, cc); } return copy; }
void plist_array_set_item(plist_t node, plist_t item, uint32_t n) { if (node && PLIST_ARRAY == plist_get_node_type(node)) { plist_t old_item = plist_array_get_item(node, n); if (old_item) { int idx = plist_free_node(old_item); if (idx < 0) { node_attach(node, item); } else { node_insert(node, idx, item); } } } return; }
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); }
void plist_dict_set_item(plist_t node, const char* key, plist_t item) { if (node && PLIST_DICT == plist_get_node_type(node)) { node_t* old_item = (node_t *)plist_dict_get_item(node, key); if (old_item) { int idx = plist_free_node(old_item); if (idx < 0) { node_attach((node_t *)node, (node_t *)item); } else { node_insert((node_t *)node, idx, (node_t *)item); } } } return; }
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 void node_to_xml(node_t* node, void *xml_struct) { struct xml_node *xstruct = NULL; plist_data_t node_data = NULL; xmlNodePtr child_node = NULL; char isStruct = FALSE; char isUIDNode = FALSE; const xmlChar *tag = NULL; char *val = NULL; //for base64 char *valtmp = NULL; uint32_t i = 0; if (!node) return; xstruct = (struct xml_node *) xml_struct; node_data = plist_get_data(node); switch (node_data->type) { case PLIST_BOOLEAN: { if (node_data->boolval) tag = XPLIST_TRUE; else tag = XPLIST_FALSE; } break; case PLIST_UINT: tag = XPLIST_INT; val = (char*)malloc(64); if (node_data->length == 16) { (void)snprintf(val, 64, "%"PRIu64, node_data->intval); } else { (void)snprintf(val, 64, "%"PRIi64, node_data->intval); } break; case PLIST_REAL: tag = XPLIST_REAL; val = (char*)malloc(64); (void)snprintf(val, 64, "%f", node_data->realval); break; case PLIST_STRING: tag = XPLIST_STRING; val = strdup((char*) node_data->strval); break; case PLIST_KEY: tag = XPLIST_KEY; val = strdup((char*) node_data->strval); break; case PLIST_DATA: tag = XPLIST_DATA; if (node_data->length) { size_t len = node_data->length; valtmp = base64encode(node_data->buff, &len); val = format_string(valtmp, len, 68, xstruct->depth); free(valtmp); } break; case PLIST_ARRAY: tag = XPLIST_ARRAY; isStruct = TRUE; break; case PLIST_DICT: tag = XPLIST_DICT; isStruct = TRUE; break; case PLIST_DATE: tag = XPLIST_DATE; { time_t timev = (time_t)node_data->timeval.tv_sec + MAC_EPOCH; struct tm *btime = gmtime(&timev); if (btime) { val = (char*)malloc(24); memset(val, 0, 24); if (strftime(val, 24, "%Y-%m-%dT%H:%M:%SZ", btime) <= 0) { free (val); val = NULL; } } } 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; } for (i = 0; i < xstruct->depth; i++) { xmlNodeAddContent(xstruct->xml, BAD_CAST("\t")); } if (node_data->type == PLIST_STRING || node_data->type == PLIST_KEY) { /* make sure we convert the following predefined xml entities */ /* < = < > = > ' = ' " = " & = & */ child_node = xmlNewTextChild(xstruct->xml, NULL, tag, BAD_CAST(val)); } else child_node = xmlNewChild(xstruct->xml, NULL, tag, BAD_CAST(val)); xmlNodeAddContent(xstruct->xml, BAD_CAST("\n")); if (val) { free(val); } //add return for structured types if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) xmlNodeAddContent(child_node, BAD_CAST("\n")); //make sure we don't produce <data/> if it's empty if ((node_data->type == PLIST_DATA) && !val) { xmlNodeAddContent(child_node, BAD_CAST("\n")); for (i = 0; i < xstruct->depth; i++) { xmlNodeAddContent(child_node, BAD_CAST("\t")); } } if (isStruct) { struct xml_node child = { child_node, xstruct->depth + 1 }; node_iterator_t *ni = node_iterator_create(node->children); node_t *ch; while ((ch = node_iterator_next(ni))) { node_to_xml(ch, &child); } node_iterator_destroy(ni); } //fix indent for structured types if (node_data->type == PLIST_ARRAY || node_data->type == PLIST_DICT) { for (i = 0; i < xstruct->depth; i++) { xmlNodeAddContent(child_node, BAD_CAST("\t")); } } if (isUIDNode) { unsigned int num = node_n_children(node); unsigned int j; for (j = num; j > 0; j--) { node_t* ch = node_nth_child(node, j-1); node_detach(node, ch); node_destroy(ch); } node_data->type = PLIST_UID; } return; }
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; } } }