diff options
| -rw-r--r-- | include/libimobiledevice/mobilebackup.h | 9 | ||||
| -rw-r--r-- | src/mobilebackup.c | 114 | 
2 files changed, 123 insertions, 0 deletions
diff --git a/include/libimobiledevice/mobilebackup.h b/include/libimobiledevice/mobilebackup.h index 7dbc3fe..bf405f9 100644 --- a/include/libimobiledevice/mobilebackup.h +++ b/include/libimobiledevice/mobilebackup.h @@ -47,12 +47,21 @@ typedef int16_t mobilebackup_error_t;  typedef struct mobilebackup_client_private mobilebackup_client_private;  typedef mobilebackup_client_private *mobilebackup_client_t; /**< The client handle. */ +typedef enum { +	MB_RESTORE_NOTIFY_SPRINGBOARD = 1 << 0, +	MB_RESTORE_PRESERVE_SETTINGS = 1 << 1, +	MB_RESTORE_PRESERVE_CAMERA_ROLL = 1 << 2 +} mobilebackup_flags_t; +  mobilebackup_error_t mobilebackup_client_new(idevice_t device, uint16_t port, mobilebackup_client_t * client);  mobilebackup_error_t mobilebackup_client_free(mobilebackup_client_t client);  mobilebackup_error_t mobilebackup_receive(mobilebackup_client_t client, plist_t *plist);  mobilebackup_error_t mobilebackup_send(mobilebackup_client_t client, plist_t plist);  mobilebackup_error_t mobilebackup_request_backup(mobilebackup_client_t client, plist_t backup_manifest, const char *base_path, const char *proto_version);  mobilebackup_error_t mobilebackup_send_backup_file_received(mobilebackup_client_t client); +mobilebackup_error_t mobilebackup_request_restore(mobilebackup_client_t client, plist_t backup_manifest, mobilebackup_flags_t flags, const char *proto_version); +mobilebackup_error_t mobilebackup_receive_restore_file_received(mobilebackup_client_t client, plist_t *result); +mobilebackup_error_t mobilebackup_send_restore_complete(mobilebackup_client_t client);  mobilebackup_error_t mobilebackup_send_error(mobilebackup_client_t client, const char *reason);  #ifdef __cplusplus diff --git a/src/mobilebackup.c b/src/mobilebackup.c index d71a494..6277d45 100644 --- a/src/mobilebackup.c +++ b/src/mobilebackup.c @@ -30,6 +30,8 @@  #define MBACKUP_VERSION_INT1 100  #define MBACKUP_VERSION_INT2 0 +#define IS_FLAG_SET(x, y) ((x & y) == y) +  /**   * Convert an device_link_service_error_t value to an mobilebackup_error_t value.   * Used internally to get correct error codes when using device_link_service stuff. @@ -353,6 +355,118 @@ mobilebackup_error_t mobilebackup_send_backup_file_received(mobilebackup_client_  }  /** + * Request that a backup should be restored to the connected device. + * + * @param client The connected MobileBackup client to use. + * @param backup_manifest The backup manifest, a plist_t of type PLIST_DICT + *    containing the backup state to be restored. + * @param flags Flags to send with the request. Currently this is a combination + *    of the following mobilebackup_flags_t: + *    MB_RESTORE_NOTIFY_SPRINGBOARD - let SpringBoard show a 'Restore' screen + *    MB_RESTORE_PRESERVE_SETTINGS - do not overwrite any settings + *    MB_RESTORE_PRESERVE_CAMERA_ROLL - preserve the photos of the camera roll + * @param proto_version A string denoting the version of the backup protocol + *    to use. Latest known version is "1.6". Ideally this value should be + *    extracted from the given manifest plist. + * + * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if + *    one of the parameters is invalid, MOBILEBACKUP_E_PLIST_ERROR if + *    backup_manifest is not of type PLIST_DICT, MOBILEBACKUP_E_MUX_ERROR + *    if a communication error occurs, or MOBILEBACKUP_E_REPLY_NOT_OK + *    if the device did not accept the request. + */ +mobilebackup_error_t mobilebackup_request_restore(mobilebackup_client_t client, plist_t backup_manifest, mobilebackup_flags_t flags, const char *proto_version) +{ +	if (!client || !client->parent || !backup_manifest || !proto_version) +		return MOBILEBACKUP_E_INVALID_ARG; + +	if (backup_manifest && (plist_get_node_type(backup_manifest) != PLIST_DICT)) +		return MOBILEBACKUP_E_PLIST_ERROR; + +	mobilebackup_error_t err; + +	/* construct request plist */ +	plist_t dict = plist_new_dict(); +	plist_dict_insert_item(dict, "BackupManifestKey", plist_copy(backup_manifest)); +	plist_dict_insert_item(dict, "BackupMessageTypeKey", plist_new_string("BackupMessageRestoreRequest")); +	plist_dict_insert_item(dict, "BackupProtocolVersion", plist_new_string(proto_version)); +	/* add flags */ +	plist_dict_insert_item(dict, "BackupNotifySpringBoard", plist_new_bool(IS_FLAG_SET(flags, MB_RESTORE_NOTIFY_SPRINGBOARD))); +	plist_dict_insert_item(dict, "BackupPreserveSettings", plist_new_bool(IS_FLAG_SET(flags, MB_RESTORE_PRESERVE_SETTINGS))); +	plist_dict_insert_item(dict, "BackupPreserveCameraRoll", plist_new_bool(IS_FLAG_SET(flags, MB_RESTORE_PRESERVE_CAMERA_ROLL))); + +	/* send request */ +	err = mobilebackup_send_message(client, NULL, dict); +	plist_free(dict); +	dict = NULL; +	if (err != MOBILEBACKUP_E_SUCCESS) { +		debug_info("ERROR: Could not send restore request message (%d)!", err); +		goto leave; +	} + +	/* now receive and hopefully get a BackupMessageRestoreReplyOK */ +	err = mobilebackup_receive_message(client, "BackupMessageRestoreReplyOK", &dict); +	if (err != MOBILEBACKUP_E_SUCCESS) { +		debug_info("ERROR: Could not receive RestoreReplyOK message (%d)!", err); +		goto leave; +	} + +	plist_t node = plist_dict_get_item(dict, "BackupProtocolVersion"); +	if (node) { +		char *str = NULL; +		plist_get_string_val(node, &str); +		if (str) { +			if (strcmp(str, proto_version) != 0) { +				err = MOBILEBACKUP_E_BAD_VERSION; +			} +			free(str); +		} +	} + +leave: +	if (dict) +		plist_free(dict); +	return err; +} + +/** + * Receive a confirmation from the device that it successfully received + * a restore file. + * + * @param client The connected MobileBackup client to use. + * @param result Pointer to a plist_t that will be set to the received plist + *    for further processing. The caller has to free it using plist_free(). + *    Note that it will be set to NULL if the operation itself fails due to + *    a communication or plist error. + *    If this parameter is NULL, it will be ignored.  + * + * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if + *    client is invalid, MOBILEBACKUP_E_REPLY_NOT_OK if the expected + *    'BackupMessageRestoreFileReceived' message could not be received, + *    MOBILEBACKUP_E_PLIST_ERROR if the received message is not a valid backup + *    message plist, or MOBILEBACKUP_E_MUX_ERROR if a communication error + *    occurs. + */ +mobilebackup_error_t mobilebackup_receive_restore_file_received(mobilebackup_client_t client, plist_t *result) +{ +	return mobilebackup_receive_message(client, "BackupMessageRestoreFileReceived", result); +} + +/** + * Tells the device that the restore process is complete. + * + * @param client The connected MobileBackup client to use. + *  + * @return MOBILEBACKUP_E_SUCCESS on success, MOBILEBACKUP_E_INVALID_ARG if + *    client is invalid, or MOBILEBACKUP_E_MUX_ERROR if a communication error + *    occurs. + */ +mobilebackup_error_t mobilebackup_send_restore_complete(mobilebackup_client_t client) +{ +	return mobilebackup_send_message(client, "BackupMessageRestoreComplete", NULL); +} + +/**   * Sends a backup error message to the device.   *   * @param client The connected MobileBackup client to use.  | 
