diff options
Diffstat (limited to 'src/InstallationProxy.c')
-rw-r--r-- | src/InstallationProxy.c | 740 |
1 files changed, 0 insertions, 740 deletions
diff --git a/src/InstallationProxy.c b/src/InstallationProxy.c deleted file mode 100644 index 9ada994..0000000 --- a/src/InstallationProxy.c +++ /dev/null @@ -1,740 +0,0 @@ -/* - * InstallationProxy.c - * Installation Proxy implementation. - * - * Copyright (c) 2009 Nikias Bassen, All Rights Reserved. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include <string.h> -#include <stdlib.h> -#include <unistd.h> -#include <arpa/inet.h> -#include <plist/plist.h> - -#include "InstallationProxy.h" -#include "property_list_service.h" -#include "debug.h" - -struct instproxy_status_data { - instproxy_client_t client; - instproxy_status_cb_t cbfunc; - char *operation; -}; - -/** Locks an installation_proxy client, done for thread safety stuff. - * - * @param client The installation_proxy client to lock - */ -static void instproxy_lock(instproxy_client_t client) -{ - debug_info("InstallationProxy: Locked"); - g_mutex_lock(client->mutex); -} - -/** Unlocks an installation_proxy client, done for thread safety stuff. - * - * @param client The installation_proxy client to lock - */ -static void instproxy_unlock(instproxy_client_t client) -{ - debug_info("InstallationProxy: Unlocked"); - g_mutex_unlock(client->mutex); -} - -/** - * Convert a property_list_service_error_t value to an instproxy_error_t value. - * Used internally to get correct error codes. - * - * @param err A property_list_service_error_t error code - * - * @return A matching instproxy_error_t error code, - * INSTPROXY_E_UNKNOWN_ERROR otherwise. - */ -static instproxy_error_t instproxy_error(property_list_service_error_t err) -{ - switch (err) { - case PROPERTY_LIST_SERVICE_E_SUCCESS: - return INSTPROXY_E_SUCCESS; - case PROPERTY_LIST_SERVICE_E_INVALID_ARG: - return INSTPROXY_E_INVALID_ARG; - case PROPERTY_LIST_SERVICE_E_PLIST_ERROR: - return INSTPROXY_E_PLIST_ERROR; - case PROPERTY_LIST_SERVICE_E_MUX_ERROR: - return INSTPROXY_E_CONN_FAILED; - default: - break; - } - return INSTPROXY_E_UNKNOWN_ERROR; -} - -/** - * Creates a new installation_proxy client - * - * @param device The device to connect to - * @param port Destination port (usually given by lockdownd_start_service). - * @param client Pointer that will be set to a newly allocated - * instproxy_client_t upon successful return. - * - * @return INSTPROXY_E_SUCCESS on success, or an INSTPROXY_E_* error value - * when an error occured. - */ -instproxy_error_t instproxy_client_new(iphone_device_t device, uint16_t port, instproxy_client_t *client) -{ - /* makes sure thread environment is available */ - if (!g_thread_supported()) - g_thread_init(NULL); - - if (!device) - return INSTPROXY_E_INVALID_ARG; - - property_list_service_client_t plistclient = NULL; - if (property_list_service_client_new(device, port, &plistclient) != PROPERTY_LIST_SERVICE_E_SUCCESS) { - return INSTPROXY_E_CONN_FAILED; - } - - instproxy_client_t client_loc = (instproxy_client_t) malloc(sizeof(struct instproxy_client_int)); - client_loc->parent = plistclient; - client_loc->mutex = g_mutex_new(); - client_loc->status_updater = NULL; - - *client = client_loc; - return INSTPROXY_E_SUCCESS; -} - -/** - * Frees an installation_proxy client. - * - * @param client The installation_proxy client to free. - * - * @return INSTPROXY_E_SUCCESS on success - * or INSTPROXY_E_INVALID_ARG if client is NULL. - */ -instproxy_error_t instproxy_client_free(instproxy_client_t client) -{ - if (!client) - return INSTPROXY_E_INVALID_ARG; - - property_list_service_client_free(client->parent); - client->parent = NULL; - if (client->status_updater) { - debug_info("joining status_updater"); - g_thread_join(client->status_updater); - } - if (client->mutex) { - g_mutex_free(client->mutex); - } - free(client); - - return INSTPROXY_E_SUCCESS; -} - -/** - * List installed applications. This function runs synchronously. - * - * @param client The connected installation_proxy client - * @param apptype The type of applications to list. - * @param result Pointer that will be set to a plist that will hold an array - * of PLIST_DICT holding information about the applications found. - * - * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if - * an error occured. - */ -instproxy_error_t instproxy_browse(instproxy_client_t client, instproxy_apptype_t apptype, plist_t *result) -{ - if (!client || !client->parent || !result) - return INSTPROXY_E_INVALID_ARG; - - instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; - int browsing = 0; - plist_t apps_array = NULL; - - plist_t dict = plist_new_dict(); - if (apptype != INSTPROXY_APPTYPE_ALL) { - plist_t client_opts = plist_new_dict(); - plist_t p_apptype = NULL; - switch (apptype) { - case INSTPROXY_APPTYPE_SYSTEM: - p_apptype = plist_new_string("System"); - break; - case INSTPROXY_APPTYPE_USER: - p_apptype = plist_new_string("User"); - break; - default: - debug_info("unknown apptype %d given, using INSTPROXY_APPTYPE_USER instead", apptype); - p_apptype = plist_new_string("User"); - break; - } - plist_dict_insert_item(client_opts, "ApplicationType", p_apptype); - plist_dict_insert_item(dict, "ClientOptions", client_opts); - } - plist_dict_insert_item(dict, "Command", plist_new_string("Browse")); - - instproxy_lock(client); - res = instproxy_error(property_list_service_send_xml_plist(client->parent, dict)); - plist_free(dict); - if (res != INSTPROXY_E_SUCCESS) { - debug_info("could not send plist"); - goto leave_unlock; - } - - apps_array = plist_new_array(); - - do { - browsing = 0; - dict = NULL; - res = instproxy_error(property_list_service_receive_plist(client->parent, &dict)); - if (res != INSTPROXY_E_SUCCESS) { - break; - } - if (dict) { - uint64_t i; - uint64_t current_amount = 0; - char *status = NULL; - plist_t camount = plist_dict_get_item(dict, "CurrentAmount"); - plist_t pstatus = plist_dict_get_item(dict, "Status"); - if (camount) { - plist_get_uint_val(camount, ¤t_amount); - } - if (current_amount > 0) { - plist_t current_list = plist_dict_get_item(dict, "CurrentList"); - for (i = 0; current_list && (i < current_amount); i++) { - plist_t item = plist_array_get_item(current_list, i); - plist_array_append_item(apps_array, plist_copy(item)); - } - } - if (pstatus) { - plist_get_string_val(pstatus, &status); - } - if (status) { - if (!strcmp(status, "BrowsingApplications")) { - browsing = 1; - } else if (!strcmp(status, "Complete")) { - debug_info("Browsing applications completed"); - res = INSTPROXY_E_SUCCESS; - } - free(status); - } - plist_free(dict); - } - } while (browsing); - - if (res == INSTPROXY_E_SUCCESS) { - *result = apps_array; - } - -leave_unlock: - instproxy_unlock(client); - return res; -} - -/** - * Internally used function that will synchronously receive messages from - * the specified installation_proxy until it completes or an error occurs. - * - * If status_cb is not NULL, the callback function will be called each time - * a status update or error message is received. - * - * @param client The connected installation proxy client - * @param status_cb Pointer to a callback function or NULL - * @param operation Operation name. Will be passed to the callback function - * in async mode or shown in debug messages in sync mode. - */ -static instproxy_error_t instproxy_perform_operation(instproxy_client_t client, instproxy_status_cb_t status_cb, const char *operation) -{ - instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; - int ok = 1; - plist_t dict = NULL; - - do { - instproxy_lock(client); - res = instproxy_error(property_list_service_receive_plist_with_timeout(client->parent, &dict, 30000)); - instproxy_unlock(client); - if (res != INSTPROXY_E_SUCCESS) { - debug_info("could not receive plist, error %d", res); - break; - } - if (dict) { - /* invoke callback function */ - if (status_cb) { - status_cb(operation, dict); - } - /* check for 'Error', so we can abort cleanly */ - plist_t err = plist_dict_get_item(dict, "Error"); - if (err) { -#ifndef STRIP_DEBUG_CODE - char *err_msg = NULL; - plist_get_string_val(err, &err_msg); - if (err_msg) { - debug_info("(%s): ERROR: %s", operation, err_msg); - free(err_msg); - } -#endif - ok = 0; - res = INSTPROXY_E_OP_FAILED; - } - /* get 'Status' */ - plist_t status = plist_dict_get_item(dict, "Status"); - if (status) { - char *status_msg = NULL; - plist_get_string_val(status, &status_msg); - if (status_msg) { - if (!strcmp(status_msg, "Complete")) { - ok = 0; - res = INSTPROXY_E_SUCCESS; - } -#ifndef STRIP_DEBUG_CODE - plist_t npercent = plist_dict_get_item(dict, "PercentComplete"); - if (npercent) { - uint64_t val = 0; - int percent; - plist_get_uint_val(npercent, &val); - percent = val; - debug_info("(%s): %s (%d%%)", operation, status_msg, percent); - } else { - debug_info("(%s): %s", operation, status_msg); - } -#endif - free(status_msg); - } - } - plist_free(dict); - dict = NULL; - } - } while (ok && client->parent); - - return res; -} - -/** - * Internally used status updater thread function that will call the specified - * callback function when status update messages (or error messages) are - * received. - * - * @param arg Pointer to an allocated struct instproxy_status_data that holds - * the required data about the connected client and the callback function. - * - * @return Always NULL. - */ -static gpointer instproxy_status_updater(gpointer arg) -{ - struct instproxy_status_data *data = (struct instproxy_status_data*)arg; - - /* run until the operation is complete or an error occurs */ - (void)instproxy_perform_operation(data->client, data->cbfunc, data->operation); - - /* cleanup */ - instproxy_lock(data->client); - debug_info("done, cleaning up."); - if (data->operation) { - free(data->operation); - } - data->client->status_updater = NULL; - instproxy_unlock(data->client); - free(data); - - return NULL; -} - -/** - * Internally used helper function that creates a status updater thread which - * will call the passed callback function when status updates occur. - * If status_cb is NULL no thread will be created, but the operation will - * run synchronously until it completes or an error occurs. - * - * @param client The connected installation proxy client - * @param status_cb Pointer to a callback function or NULL - * @param operation Operation name. Will be passed to the callback function - * in async mode or shown in debug messages in sync mode. - * - * @return INSTPROXY_E_SUCCESS when the thread was created (async mode), or - * when the operation completed successfully (sync). - * An INSTPROXY_E_* error value is returned if an error occured. - */ -static instproxy_error_t instproxy_create_status_updater(instproxy_client_t client, instproxy_status_cb_t status_cb, const char *operation) -{ - instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; - if (status_cb) { - /* async mode */ - struct instproxy_status_data *data = (struct instproxy_status_data*)malloc(sizeof(struct instproxy_status_data)); - if (data) { - data->client = client; - data->cbfunc = status_cb; - data->operation = strdup(operation); - - client->status_updater = g_thread_create(instproxy_status_updater, data, TRUE, NULL); - if (client->status_updater) { - res = INSTPROXY_E_SUCCESS; - } - } - } else { - /* sync mode */ - res = instproxy_perform_operation(client, NULL, operation); - } - return res; -} - - -/** - * Internal function used by instproxy_install and instproxy_upgrade. - * - * @param client The connected installation_proxy client - * @param pkg_path Path of the installation package (inside the AFC jail) - * @param sinf PLIST_DATA node holding the package's SINF data or NULL. - * @param metadata PLIST_DATA node holding the packages's Metadata or NULL. - * @param status_cb Callback function for progress and status information. If - * NULL is passed, this function will run synchronously. - * @param command The command to execute. - * - * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if - * an error occured. - */ -static instproxy_error_t instproxy_install_or_upgrade(instproxy_client_t client, const char *pkg_path, plist_t sinf, plist_t metadata, instproxy_status_cb_t status_cb, const char *command) -{ - if (!client || !client->parent || !pkg_path) { - return INSTPROXY_E_INVALID_ARG; - } - if (sinf && (plist_get_node_type(sinf) != PLIST_DATA)) { - debug_info("(%s): ERROR: sinf data is not a PLIST_DATA node!", command); - return INSTPROXY_E_INVALID_ARG; - } - if (metadata && (plist_get_node_type(metadata) != PLIST_DATA)) { - debug_info("(%s): ERROR: metadata is not a PLIST_DATA node!", command); - return INSTPROXY_E_INVALID_ARG; - } - - if (client->status_updater) { - return INSTPROXY_E_OP_IN_PROGRESS; - } - - instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; - - plist_t dict = plist_new_dict(); - if (sinf && metadata) { - plist_t client_opts = plist_new_dict(); - plist_dict_insert_item(client_opts, "ApplicationSINF", plist_copy(sinf)); - plist_dict_insert_item(client_opts, "iTunesMetadata", plist_copy(metadata)); - plist_dict_insert_item(dict, "ClientOptions", client_opts); - } - plist_dict_insert_item(dict, "Command", plist_new_string(command)); - plist_dict_insert_item(dict, "PackagePath", plist_new_string(pkg_path)); - - instproxy_lock(client); - res = instproxy_error(property_list_service_send_xml_plist(client->parent, dict)); - instproxy_unlock(client); - - plist_free(dict); - - if (res != INSTPROXY_E_SUCCESS) { - debug_info("could not send plist, error %d", res); - return res; - } - - return instproxy_create_status_updater(client, status_cb, command); -} - -/** - * Install an application on the device. - * - * @param client The connected installation_proxy client - * @param pkg_path Path of the installation package (inside the AFC jail) - * @param sinf PLIST_DATA node holding the package's SINF data or NULL. - * @param metadata PLIST_DATA node holding the packages's Metadata or NULL. - * @param status_cb Callback function for progress and status information. If - * NULL is passed, this function will run synchronously. - * - * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if - * an error occured. - * - * @note If a callback function is given (async mode), this function returns - * INSTPROXY_E_SUCCESS immediately if the status updater thread has been - * created successfully; any error occuring during the operation has to be - * handled inside the specified callback function. - */ -instproxy_error_t instproxy_install(instproxy_client_t client, const char *pkg_path, plist_t sinf, plist_t metadata, instproxy_status_cb_t status_cb) -{ - return instproxy_install_or_upgrade(client, pkg_path, sinf, metadata, status_cb, "Install"); -} - -/** - * Upgrade an application on the device. This function is nearly the same as - * instproxy_install; the difference is that the installation progress on the - * device is faster if the application is already installed. - * - * @param client The connected installation_proxy client - * @param pkg_path Path of the installation package (inside the AFC jail) - * @param sinf PLIST_DATA node holding the package's SINF data or NULL. - * @param metadata PLIST_DATA node holding the packages's Metadata or NULL. - * @param status_cb Callback function for progress and status information. If - * NULL is passed, this function will run synchronously. - * - * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if - * an error occured. - * - * @note If a callback function is given (async mode), this function returns - * INSTPROXY_E_SUCCESS immediately if the status updater thread has been - * created successfully; any error occuring during the operation has to be - * handled inside the specified callback function. - */ -instproxy_error_t instproxy_upgrade(instproxy_client_t client, const char *pkg_path, plist_t sinf, plist_t metadata, instproxy_status_cb_t status_cb) -{ - return instproxy_install_or_upgrade(client, pkg_path, sinf, metadata, status_cb, "Upgrade"); -} - -/** - * Uninstall an application from the device. - * - * @param client The connected installation proxy client - * @param appid ApplicationIdentifier of the app to uninstall - * @param status_cb Callback function for progress and status information. If - * NULL is passed, this function will run synchronously. - * - * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if - * an error occured. - * - * @note If a callback function is given (async mode), this function returns - * INSTPROXY_E_SUCCESS immediately if the status updater thread has been - * created successfully; any error occuring during the operation has to be - * handled inside the specified callback function. - */ -instproxy_error_t instproxy_uninstall(instproxy_client_t client, const char *appid, instproxy_status_cb_t status_cb) -{ - if (!client || !client->parent || !appid) { - return INSTPROXY_E_INVALID_ARG; - } - - if (client->status_updater) { - return INSTPROXY_E_OP_IN_PROGRESS; - } - - instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; - plist_t dict = plist_new_dict(); - plist_dict_insert_item(dict, "ApplicationIdentifier", plist_new_string(appid)); - plist_dict_insert_item(dict, "Command", plist_new_string("Uninstall")); - - instproxy_lock(client); - res = instproxy_error(property_list_service_send_xml_plist(client->parent, dict)); - instproxy_unlock(client); - - plist_free(dict); - - if (res != INSTPROXY_E_SUCCESS) { - debug_info("could not send plist, error %d", res); - return res; - } - - return instproxy_create_status_updater(client, status_cb, "Uninstall"); -} - -/** - * List archived applications. This function runs synchronously. - * - * @see instproxy_archive - * - * @param client The connected installation_proxy client - * @param result Pointer that will be set to a plist containing a PLIST_DICT - * holding information about the archived applications found. - * - * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if - * an error occured. - */ -instproxy_error_t instproxy_lookup_archives(instproxy_client_t client, plist_t *result) -{ - if (!client || !client->parent || !result) - return INSTPROXY_E_INVALID_ARG; - - instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; - - plist_t dict = plist_new_dict(); - plist_dict_insert_item(dict, "Command", plist_new_string("LookupArchives")); - - instproxy_lock(client); - - res = instproxy_error(property_list_service_send_xml_plist(client->parent, dict)); - plist_free(dict); - - if (res != INSTPROXY_E_SUCCESS) { - debug_info("could not send plist, error %d", res); - goto leave_unlock; - } - - res = instproxy_error(property_list_service_receive_plist(client->parent, result)); - if (res != INSTPROXY_E_SUCCESS) { - debug_info("could not receive plist, error %d", res); - goto leave_unlock; - } - - res = INSTPROXY_E_SUCCESS; - -leave_unlock: - instproxy_unlock(client); - return res; -} - -/** - * Archive an application on the device. - * This function tells the device to make an archive of the specified - * application. This results in the device creating a ZIP archive in the - * 'ApplicationArchives' directory and uninstalling the application. - * - * @param client The connected installation proxy client - * @param appid ApplicationIdentifier of the app to archive. - * @param options This is either 0 for default behaviour (make an archive - * including app/user settings etc. AND uninstall the application), - * or one or a combination of the following options: - * INSTPROXY_ARCHIVE_APP_ONLY (1) - * INSTPROXY_ARCHIVE_SKIP_UNINSTALL (2) - * @param status_cb Callback function for progress and status information. If - * NULL is passed, this function will run synchronously. - * - * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if - * an error occured. - * - * @note If a callback function is given (async mode), this function returns - * INSTPROXY_E_SUCCESS immediately if the status updater thread has been - * created successfully; any error occuring during the operation has to be - * handled inside the specified callback function. - */ -instproxy_error_t instproxy_archive(instproxy_client_t client, const char *appid, uint32_t options, instproxy_status_cb_t status_cb) -{ - if (!client || !client->parent || !appid) - return INSTPROXY_E_INVALID_ARG; - - if (client->status_updater) { - return INSTPROXY_E_OP_IN_PROGRESS; - } - - instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; - - plist_t dict = plist_new_dict(); - plist_dict_insert_item(dict, "ApplicationIdentifier", plist_new_string(appid)); - if (options > 0) { - plist_t client_opts = plist_new_dict(); - if (options & INSTPROXY_ARCHIVE_APP_ONLY) { - plist_dict_insert_item(client_opts, "ArchiveType", plist_new_string("ApplicationOnly")); - } - if (options & INSTPROXY_ARCHIVE_SKIP_UNINSTALL) { - plist_dict_insert_item(client_opts, "SkipUninstall", plist_new_bool(1)); - } - plist_dict_insert_item(dict, "ClientOptions", client_opts); - } - plist_dict_insert_item(dict, "Command", plist_new_string("Archive")); - - instproxy_lock(client); - res = instproxy_error(property_list_service_send_xml_plist(client->parent, dict)); - instproxy_unlock(client); - - plist_free(dict); - - if (res != INSTPROXY_E_SUCCESS) { - debug_info("could not send plist, error %d", res); - return res; - } - return instproxy_create_status_updater(client, status_cb, "Archive"); -} - -/** - * Restore a previously archived application on the device. - * This function is the counterpart to instproxy_archive. - * @see instproxy_archive - * - * @param client The connected installation proxy client - * @param appid ApplicationIdentifier of the app to restore. - * @param status_cb Callback function for progress and status information. If - * NULL is passed, this function will run synchronously. - * - * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if - * an error occured. - * - * @note If a callback function is given (async mode), this function returns - * INSTPROXY_E_SUCCESS immediately if the status updater thread has been - * created successfully; any error occuring during the operation has to be - * handled inside the specified callback function. - */ -instproxy_error_t instproxy_restore(instproxy_client_t client, const char *appid, instproxy_status_cb_t status_cb) -{ - if (!client || !client->parent || !appid) - return INSTPROXY_E_INVALID_ARG; - - if (client->status_updater) { - return INSTPROXY_E_OP_IN_PROGRESS; - } - - instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; - - plist_t dict = plist_new_dict(); - plist_dict_insert_item(dict, "ApplicationIdentifier", plist_new_string(appid)); - plist_dict_insert_item(dict, "Command", plist_new_string("Restore")); - - instproxy_lock(client); - res = instproxy_error(property_list_service_send_xml_plist(client->parent, dict)); - instproxy_unlock(client); - - plist_free(dict); - - if (res != INSTPROXY_E_SUCCESS) { - debug_info("could not send plist, error %d", res); - return res; - } - return instproxy_create_status_updater(client, status_cb, "Restore"); -} - -/** - * Removes a previously archived application from the device. - * This function removes the ZIP archive from the 'ApplicationArchives' - * directory. - * - * @param client The connected installation proxy client - * @param appid ApplicationIdentifier of the archived app to remove. - * @param status_cb Callback function for progress and status information. If - * NULL is passed, this function will run synchronously. - * - * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if - * an error occured. - * - * @note If a callback function is given (async mode), this function returns - * INSTPROXY_E_SUCCESS immediately if the status updater thread has been - * created successfully; any error occuring during the operation has to be - * handled inside the specified callback function. - */ -instproxy_error_t instproxy_remove_archive(instproxy_client_t client, const char *appid, instproxy_status_cb_t status_cb) -{ - if (!client || !client->parent || !appid) - return INSTPROXY_E_INVALID_ARG; - - if (client->status_updater) { - return INSTPROXY_E_OP_IN_PROGRESS; - } - - instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; - - plist_t dict = plist_new_dict(); - plist_dict_insert_item(dict, "ApplicationIdentifier", plist_new_string(appid)); - plist_dict_insert_item(dict, "Command", plist_new_string("RemoveArchive")); - - instproxy_lock(client); - res = instproxy_error(property_list_service_send_xml_plist(client->parent, dict)); - instproxy_unlock(client); - - plist_free(dict); - - if (res != INSTPROXY_E_SUCCESS) { - debug_info("could not send plist, error %d", res); - return res; - } - return instproxy_create_status_updater(client, status_cb, "RemoveArchive"); -} - |