#56 ✓resolved
Martin S.

libplist API does not offer a way to clone or modify nodes

Reported by Martin S. | July 8th, 2009 @ 09:16 AM

Attempted to implement lockdown's get/set/remove value request and came up with those signatures:

iphone_error_t lockdownd_get_value(lockdownd_client_t client, char domain, char key, plist_t value);
iphone_error_t lockdownd_set_value(lockdownd_client_t client, char domain, char key, plist_t value);
iphone_error_t lockdownd_remove_value(lockdownd_client_t client, char domain, char *key);

For instance lockdownd_get_value() returns the value plist subnode for the key named "Value". The issue here was that there is no way in libplist to copy/clone an existing node. This also becomes a problem for set_value(), which actually has to clone the passed value node to construct a lockdown request plist with the value node attached to send to lockdownd.

The intermediate solution was to use plist_to_bin() to serialize the plist subnode into a buffer, then use plist_from_bin() to unserialize the plist into a node again effectively ending up with a cloned node.

Also while thinking about implementing a plist GUI editor similar to the one on Mac OS X, libplist should also provide the necessary functions to deal with modifications of node trees.

I think the missing operations are:

  • clone nodes (recurse deep copy) - needed to fix this bug
  • modify node values (e.g.: for quick, plist load -> change <string> value, save modified plist)
  • remove nodes (Does plist_free() also unlink the "destroyed" node from the parent tree?)

Another question is how far this functionality should make sure the strict "<key /><VALUE />" node structure is not compromised or whether allow the "freedom" to work on individual nodes.

Simple idea:

// Return a copy of passed node and it's children
PLIST_API plist_t plist_copy(plist_t node);
// modify value of a node
PLIST_API void plist_set_key_val(plist_t node, char val);
PLIST_API void plist_set_string_val(plist_t node, char val);
PLIST_API void plist_set_bool_val(plist_t node, uint8_t val);
PLIST_API void plist_set_uint_val(plist_t node, uint64_t val);
PLIST_API void plist_set_real_val(plist_t node, double val);
PLIST_API void plist_set_data_val(plist_t node, char *val, uint64_t length);
PLIST_API void plist_set_date_val(plist_t node, int32_t sec, int32_t usec);

Comments and changes to this ticket

  • Jonathan Beck

    Jonathan Beck July 8th, 2009 @ 05:49 PM

    • State changed from “new” to “open”
    • Assigned user set to “Jonathan Beck”

    Hi Martin,

    I updated libplist git HEAD with requested changes.
    Please check that it fits your needs.

    Also I would like to ensure through API that dicts are always well formed (key/value pairs), but that would require to duplicate lots of functions in the API (as single node manipulation is still necessary to handle arrays), so I don't really know what to do here.

    If you did not started yet, I will probably investigate making a GUI plist editor.

  • Martin S.

    Martin S. July 9th, 2009 @ 03:26 PM

    Superb, thanks for looking into this. However I get empty nodes back...

    static plist_t plist_copy_node(GNode * node, gpointer parent_node)
        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));
        newnode = plist_new_node(newdata);
        if (parent_node) {
            g_node_append(parent_node, newnode);
        g_node_children_foreach(node, G_TRAVERSE_ALL, plist_copy_node, newnode);
    plist_t plist_copy(plist_t node)
        plist_copy_node(node, NULL);

    ... as above obviously can't work returning void. :)

  • Jonathan Beck

    Jonathan Beck July 9th, 2009 @ 04:33 PM

    I obviously did that a bit too fast :). Strange gcc didn't moan about that though.

    Should be fixed now.

  • Martin S.

    Martin S. July 10th, 2009 @ 05:07 PM

    Attached patch fixes the last issue I encountered with this. After applying it everything works as expected. Thanks a lot.

  • Martin S.

    Martin S. July 17th, 2009 @ 05:47 PM

    Well, forgot to also copy the string value for "key" which caused issues. Attached corrected patch to use instead of the one before.

  • Jonathan Beck

    Jonathan Beck July 18th, 2009 @ 07:05 PM

    • State changed from “open” to “resolved”

    Changes applied and available in libplist-0.13

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile ยป

A project around supporting the iPhone in Linux.

See http://libimobiledevice.org

People watching this ticket