/** * List archived applications. This function runs synchronously. * * @see instproxy_archive * * @param client The connected installation_proxy client * @param client_options The client options to use, as PLIST_DICT, or NULL. * Currently there are no known client options, so pass NULL here. * @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 client_options, plist_t *result) { if (!client || !client->parent || !result) return INSTPROXY_E_INVALID_ARG; instproxy_lock(client); instproxy_error_t res = instproxy_send_command(client, "LookupArchives", client_options, NULL, NULL); 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; }
/** * Uninstall an application from the device. * * @param client The connected installation proxy client * @param appid ApplicationIdentifier of the app to uninstall * @param client_options The client options to use, as PLIST_DICT, or NULL. * Currently there are no known client options, so pass NULL here. * @param status_cb Callback function for progress and status information. If * NULL is passed, this function will run synchronously. * @param user_data Callback data passed to status_cb. * * @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, plist_t client_options, instproxy_status_cb_t status_cb, void *user_data) { 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_send_command(client, "Uninstall", client_options, appid, NULL); 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", user_data); }
/** * 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 client_options The client options to use, as PLIST_DICT, or NULL. * Currently there are no known client options, so passing NULL is fine. * @param status_cb Callback function for progress and status information. If * NULL is passed, this function will run synchronously. * @param user_data Callback data passed to status_cb. * * @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, plist_t client_options, instproxy_status_cb_t status_cb, void *user_data) { if (!client || !client->parent || !appid) return INSTPROXY_E_INVALID_ARG; if (client->status_updater) { return INSTPROXY_E_OP_IN_PROGRESS; } instproxy_lock(client); instproxy_error_t res = instproxy_send_command(client, "RemoveArchive", client_options, appid, NULL); instproxy_unlock(client); 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", user_data); }
/** * 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 client_options The client options to use, as PLIST_DICT, 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. * @param user_data Callback data passed to status_cb. * * @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 client_options, instproxy_status_cb_t status_cb, const char *command, void *user_data) { if (!client || !client->parent || !pkg_path) { return INSTPROXY_E_INVALID_ARG; } if (client->status_updater) { return INSTPROXY_E_OP_IN_PROGRESS; } instproxy_lock(client); instproxy_error_t res = instproxy_send_command(client, command, client_options, NULL, pkg_path); instproxy_unlock(client); 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, user_data); }
/** * Internal core function to send a command and process the response. * * @param client The connected installation_proxy client * @param command The command specification dictionary. * @param async A boolean indicating whether the receive loop should be run * asynchronously or block until completing the command. * @param status_cb Callback function to call if a command status is received. * @param user_data Callback data passed to status_cb. * * @return INSTPROXY_E_SUCCESS on success or an INSTPROXY_E_* error value if * an error occured. */ static instproxy_error_t instproxy_perform_command(instproxy_client_t client, plist_t command, instproxy_command_type_t async, instproxy_status_cb_t status_cb, void *user_data) { if (!client || !client->parent || !command) { return INSTPROXY_E_INVALID_ARG; } if (client->receive_status_thread) { return INSTPROXY_E_OP_IN_PROGRESS; } instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; /* send command */ instproxy_lock(client); res = instproxy_send_command(client, command); instproxy_unlock(client); /* loop until status or error is received */ res = instproxy_receive_status_loop_with_callback(client, command, async, status_cb, user_data); return res; }
LIBIMOBILEDEVICE_API instproxy_error_t instproxy_uninstall(instproxy_client_t client, const char *appid, plist_t client_options, instproxy_status_cb_t status_cb, void *user_data) { 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; instproxy_lock(client); res = instproxy_send_command(client, "Uninstall", client_options, appid, NULL); instproxy_unlock(client); 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", user_data); }
/** * List installed applications. This function runs synchronously. * * @param client The connected installation_proxy client * @param client_options The client options to use, as PLIST_DICT, or NULL. * Valid client options include: * "ApplicationType" -> "User" * "ApplicationType" -> "System" * @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, plist_t client_options, plist_t *result) { if (!client || !client->parent || !result) return INSTPROXY_E_INVALID_ARG; instproxy_error_t res = INSTPROXY_E_UNKNOWN_ERROR; instproxy_lock(client); res = instproxy_send_command(client, "Browse", client_options, NULL, NULL); if (res != INSTPROXY_E_SUCCESS) { debug_info("could not send plist"); goto leave_unlock; } int browsing = 0; plist_t apps_array = plist_new_array(); plist_t dict = NULL; 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; } else { plist_free(apps_array); } leave_unlock: instproxy_unlock(client); return res; }