diff options
| -rw-r--r-- | include/plist/plist.h | 28 | ||||
| -rw-r--r-- | src/bplist.c | 60 | ||||
| -rw-r--r-- | src/plist.c | 27 | ||||
| -rw-r--r-- | src/xplist.c | 55 | 
4 files changed, 168 insertions, 2 deletions
| diff --git a/include/plist/plist.h b/include/plist/plist.h index 1b1ac52..546e108 100644 --- a/include/plist/plist.h +++ b/include/plist/plist.h @@ -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; @@ -166,6 +167,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       *       * @param plist the plist to free @@ -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); +      /********************************************       *                                          * diff --git a/src/bplist.c b/src/bplist.c index eff44fc..7893ff5 100644 --- a/src/bplist.c +++ b/src/bplist.c @@ -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;          } diff --git a/src/plist.c b/src/plist.c index 2b31fdd..ee79cf4 100644 --- a/src/plist.c +++ b/src/plist.c @@ -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)); diff --git a/src/xplist.c b/src/xplist.c index ba312a1..b551179 100644 --- a/src/xplist.c +++ b/src/xplist.c @@ -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;          }      } | 
