summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/libimobiledevice/mobilebackup.h9
-rw-r--r--src/mobilebackup.c114
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.