libimobiledevice / libplist

A library to handle Apple Property List format in binary or XML
https://libimobiledevice.org
GNU Lesser General Public License v2.1
548 stars 304 forks source link

About the conversion of plist and Objective-C object #232

Open AiXanadu opened 1 year ago

AiXanadu commented 1 year ago

In the instrument service, the Selector and Auxiliaries used for communication are Object-C objects, and the structure includes $top, $objects and $archiver Can we add a packing and unpacking operation?

An example of a string is as follows:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <string>example</string>
</plist>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
    <key>$archiver</key>
    <string>NSKeyedArchiver</string>
    <key>$objects</key>
    <array>
        <string>$null</string>
        <string>example</string>
    </array>
    <key>$top</key>
    <dict>
        <key>root</key>
        <uid>1</uid>
    </dict>
    <key>$version</key>
    <integer>100000</integer>
</plist>

An example of an empty array is as follows

    auto        vObject = plist_new_array();
    if(vObject)
    {
        plist_array_append_item(vObject, plist_new_string("$null"));            // 0

        auto        vNode1 = plist_new_dict();                  // 1
        if(vNode1)
        {
            // <key>$class</key>
            plist_dict_set_item(vNode1, "$class", plist_new_uid(2));

            // <key>NS.objects</key>
            auto        vNS_Objects = plist_new_array();
            if(vNS_Objects)
            {
                plist_dict_set_item(vNode1, "NS.objects", vNS_Objects);
            }
            plist_array_append_item(vObject, vNode1);
        }

        auto        vNode2 = plist_new_dict();                  // 2
        if(vNode2)
        {
            // <key>$classes</key>
            auto        vNS_Classes = plist_new_array();
            if(vNS_Classes)
            {
                plist_array_append_item(vNS_Classes, plist_new_string("NSArray"));
                plist_array_append_item(vNS_Classes, plist_new_string("NSObject"));

                plist_dict_set_item(vNode2, "$classes", vNS_Classes);
            }
            // <key>$classname</key>
            plist_dict_set_item(vNode2, "$classname", plist_new_string("NSArray"));

            plist_array_append_item(vObject, vNode2);
        }
    }

An example of an empty object is as follows

auto        vObject = plist_new_array();
    if(vObject)
    {
        plist_array_append_item(vObject, plist_new_string("$null"));            // 0

        auto        vNode1 = plist_new_dict();                  // 1
        if(vNode1)
        {
            // <key>$class</key>
            plist_dict_set_item(vNode1, "$class", plist_new_uid(2));

            // <key>NS.keys</key>
            auto        vNS_Keys = plist_new_array();
            if(vNS_Keys)
            {
                plist_dict_set_item(vNode1, "NS.keys", vNS_Keys);
            }

            // <key>NS.objects</key>
            auto        vNS_Objects = plist_new_array();
            if(vNS_Objects)
            {
                plist_dict_set_item(vNode1, "NS.objects", vNS_Objects);
            }
            plist_array_append_item(vObject, vNode1);
        }

        auto        vNode2 = plist_new_dict();                  // 2
        if(vNode2)
        {
            // <key>$classes</key>
            auto        vNS_Classes = plist_new_array();
            if(vNS_Classes)
            {
                plist_array_append_item(vNS_Classes, plist_new_string("NSDictionary"));
                plist_array_append_item(vNS_Classes, plist_new_string("NSObject"));

                plist_dict_set_item(vNode2, "$classes", vNS_Classes);
            }
            // <key>$classname</key>
            plist_dict_set_item(vNode2, "$classname", plist_new_string("NSDictionary"));

            plist_array_append_item(vObject, vNode2);
        }
    }
AiXanadu commented 1 year ago

Comes with some other samples:

<This is setting 1> >> 1
<This is setting 2> >> 2
    auto        vObject = plist_new_array();
    if(vObject)
    {
        plist_array_append_item(vObject, plist_new_string("$null"));            // 0

        auto        vNode1 = plist_new_dict();                  // 1
        if(vNode1)
        {
            // <key>$class</key>
            plist_dict_set_item(vNode1, "$class", plist_new_uid(6));

            // <key>NS.keys</key>
            auto        vNS_Keys = plist_new_array();
            if(vNS_Keys)
            {
                plist_array_append_item(vNS_Keys, plist_new_uid(2));
                plist_array_append_item(vNS_Keys, plist_new_uid(3));
                plist_dict_set_item(vNode1, "NS.keys", vNS_Keys);
            }

            // <key>NS.objects</key>
            auto        vNS_Objects = plist_new_array();
            if(vNS_Objects)
            {
                plist_array_append_item(vNS_Objects, plist_new_uid(4));
                plist_array_append_item(vNS_Objects, plist_new_uid(5));
                plist_dict_set_item(vNode1, "NS.objects", vNS_Objects);
            }
            plist_array_append_item(vObject, vNode1);
        }

        plist_array_append_item(vObject, plist_new_string("This is setting 1"));    // 2
        plist_array_append_item(vObject, plist_new_string("This is setting 2"));    // 3
        plist_array_append_item(vObject, plist_new_int(1));             // 4
        plist_array_append_item(vObject, plist_new_int(2));             // 5

        auto        vNode2 = plist_new_dict();                  // 6
        if(vNode2)
        {
            // <key>$classes</key>
            auto        vNS_Classes = plist_new_array();
            if(vNS_Classes)
            {
                plist_array_append_item(vNS_Classes, plist_new_string("NSDictionary"));
                plist_array_append_item(vNS_Classes, plist_new_string("NSObject"));

                plist_dict_set_item(vNode2, "$classes", vNS_Classes);
            }
            // <key>$classname</key>
            plist_dict_set_item(vNode2, "$classname", plist_new_string("NSDictionary"));

            plist_array_append_item(vObject, vNode2);
        }
    }
AiXanadu commented 1 year ago

These transfers belong to DTXMessage dependencies, which can provide preparations for us to add the instrument interface in the future.

These transfers belong to DTXMessage dependencies, which can provide preparations for us to add the instrument interface in the future.

See the format: https://github.com/troybowman/dtxmsg and: https://recon.cx/2018/montreal/schedule/system/event_attachments/attachments/000/000/043/original/RECON-MTL-2018-Discovering_the_iOS_Instruments_Server.pdf

AiXanadu commented 1 year ago

like this


static plist_err_t plist_node_from_objc(plist_t objc, plist_t *plist)
{
    return PLIST_ERR_UNKNOWN;
}

static plist_err_t plist_node_to_objc(plist_t node, plist_t *objc)
{
    plist_t     objc_array = plist_new_array();
    if(NULL == objc_array)
    {
        return PLIST_ERR_NO_MEM;
    }
    plist_type  type = plist_get_node_type(node);
    plist_array_append_item(objc_array, plist_new_string("$null"));
    if (type == PLIST_ARRAY)
    {
        uint32_t    vSize = plist_array_get_size(objc_array);

        // Add child information
        plist_t     node_desc_i = plist_new_dict();             // 1
        if(node_desc_i)
        {
            // <key>$class</key>
            plist_dict_set_item(node_desc_i, "$class", plist_new_uid(2));

            // <key>NS.objects</key>
            plist_t     vNS_Objects = plist_new_array();
            if(vNS_Objects)
            {
                for(uint32_t vIndex = 0; vIndex < vSize; ++vIndex)
                {
                    plist_array_append_item(vNS_Objects, plist_new_uid(vIndex + 2));
                }
                plist_dict_set_item(node_desc_i, "NS.objects", vNS_Objects);
            }
            plist_array_append_item(objc_array, node_desc_i);
        }

        // Add object information
        plist_t     node_desc_o = plist_new_dict();             // 2
        if(vNode2)
        {
            // <key>$classes</key>
            plist_t     vNS_Classes = plist_new_array();
            if(vNS_Classes)
            {
                plist_array_append_item(vNS_Classes, plist_new_string("NSArray"));
                plist_array_append_item(vNS_Classes, plist_new_string("NSObject"));

                plist_dict_set_item(node_desc_o, "$classes", vNS_Classes);
            }
            // <key>$classname</key>
            plist_dict_set_item(node_desc_o, "$classname", plist_new_string("NSArray"));

            plist_array_append_item(objc_array, node_desc_o);
        }

        // Add child information
        for(uint32_t vIndex = 0; vIndex < vSize; ++vIndex)
        {
            plist_t     child_node = plist_array_get_item(objc_array, vIndex);
            plist_type  child_type = plist_get_node_type(child_node);
            if(child_type == PLIST_ARRAY || child_type == PLIST_DICT)
            {
                plist_t     node_objc = NULL;
                plist_node_to_objc(child_node, &node_objc);
                plist_array_append_item(objc_array, node_objc);
            }
            else
            {
                plist_array_append_item(objc_array, plist_copy(child_node));
            }
        }
    }
    else if (type == PLIST_DICT)
    {
    }
    else
    {
        plist_array_append_item(objc_array, plist_copy(node));

        *objc = objc_array;
        return PLIST_ERR_SUCCESS;
    }
    plist_free(objc_array);
    return PLIST_ERR_UNKNOWN;
}

plist_err_t plist_from_objc(plist_t objc, plist_t *plist)
{
    return PLIST_ERR_UNKNOWN;
}

plist_err_t plist_to_objc(plist_t plist, plist_t *objc)
{
    if(NULL == plist || NULL == objc)
    {
        return PLIST_ERR_INVALID_ARG;
    }

    plist_err_t err = plist_node_to_objc(plist, objc);
    if(PLIST_ERR_SUCCESS == err)
    {
        plist_t     root = plist_new_dict();
        if(NULL == root)
        {
            plist_free(*objc);
            *objc = NULL;
            return PLIST_ERR_NO_MEM;
        }
        plist_dict_set_item(root, "$archiver", plist_new_string("NSKeyedArchiver"));
        plist_dict_set_item(root, "$objects", *objc);
        auto        top = plist_new_dict();
        if(NULL == top)
        {
            plist_free(root);
            plist_free(*objc);
            *objc = NULL;
            return PLIST_ERR_NO_MEM;
        }
        plist_dict_set_item(top, "root", plist_new_uid(1));
        plist_dict_set_item(root, "$top", top);

        plist_dict_set_item(root, "$version", plist_new_uint(100000));

        *objc = root;
    }
    return err;
}