From 9f1677222b06f41c4ab309918511f3c3918a822e Mon Sep 17 00:00:00 2001
From: Martin Szulecki
Date: Mon, 25 Jan 2010 01:31:10 +0100
Subject: Implement storing received files as backup including new Manifest
---
tools/iphonebackup.c | 315 +++++++++++++++++++++++++--------------------------
1 file changed, 157 insertions(+), 158 deletions(-)
(limited to 'tools')
diff --git a/tools/iphonebackup.c b/tools/iphonebackup.c
index 611c0f2..1ad4116 100644
--- a/tools/iphonebackup.c
+++ b/tools/iphonebackup.c
@@ -40,7 +40,8 @@ static int quit_flag = 0;
enum cmd_mode {
CMD_BACKUP,
- CMD_RESTORE
+ CMD_RESTORE,
+ CMD_LEAVE
};
static plist_t mobilebackup_factory_info_plist()
@@ -102,150 +103,24 @@ static plist_t mobilebackup_factory_info_plist()
return ret;
}
-static plist_t mobilebackup_factory_metadata_plist()
-{
- plist_t ret = NULL;
-/*
-Metadata key is:
-
- Path
- Library/SMS/sms.db
- Version
- 3.0
- Greylist
-
- Domain
- HomeDomain
-
-*/
-/*
-
- Metadata
-
- YnBsaXN0MDDUAQIDBAUGBwhUUGF0aFdWZXJzaW9uWEdyZXlsaXN0VkRvbWFp
- bl8QEkxpYnJhcnkvU01TL3Ntcy5kYlMzLjAIWkhvbWVEb21haW4IERYeJy5D
- R0gAAAAAAAABAQAAAAAAAAAJAAAAAAAAAAAAAAAAAAAAUw==
-
- StorageVersion
- 1.0
- Version
- 3.0
- AuthVersion
- 1.0
- IsEncrypted
-
-
-*/
- return ret;
-}
-
-/**
- * Generates a manifest data plist with all files and corresponding hashes
- */
-static plist_t mobilebackup_factory_manifest_data_plist()
-{
- plist_t ret = NULL;
- plist_t value_node = NULL;
- char *uuid = NULL;
- GTimeVal tv = {0, 0};
-
- ret = plist_new_dict();
-
- /* get basic device information in one go */
- lockdownd_get_value(client, NULL, "IntegratedCircuitCardIdentity", &value_node);
-
- iphone_device_get_uuid(phone, &uuid);
- plist_dict_insert_item(ret, "DeviceId", plist_new_string(uuid));
- free(uuid);
-
- plist_dict_insert_item(ret, "Version", plist_new_string("6.2"));
-
- /* TODO: add all Applications */
-
- /* TODO: add all Files */
- plist_t files = plist_new_dict();
-
- /* single file entry */
- plist_t info_node = plist_new_dict();
- g_get_current_time(&tv);
- plist_dict_insert_item(info_node, "ModificationTime", plist_new_date(tv.tv_sec, tv.tv_usec));
- plist_dict_insert_item(info_node, "FileLength", plist_new_uint(131072));
- plist_dict_insert_item(info_node, "Domain", plist_new_string("HomeDomain"));
-
- /* FIXME: calculate correct data hash */
- /* Data hash is: sha1() */
- plist_dict_insert_item(info_node, "DataHash", plist_new_data(NULL, 0));
- plist_dict_insert_item(info_node, "Group ID", plist_new_uint(501));
- plist_dict_insert_item(info_node, "User ID", plist_new_uint(501));
- plist_dict_insert_item(info_node, "Mode ID", plist_new_uint(420));
-
- /* FIXME: calculate correct file hash */
- /* File hash is: sha1(-) */
- plist_dict_insert_item(files, "3d0d7e5fb2ce288813306e4d4636395e047a3d28", info_node);
- plist_dict_insert_item(ret, "Files", files);
-
- /* last node with ICCID */
- if (value_node)
- plist_dict_insert_item(ret, "DeviceICCID", &value_node);
-
- return ret;
-}
-
-/**
- * Generates a manifest plist with all needed information and hashes
- */
-static plist_t mobilebackup_factory_manifest_plist(plist_t manifest_data)
-{
- char *buffer = NULL;
- char *s = NULL;
- uint32_t length;
- unsigned char sha1[20];
- gsize sha1_len;
- GChecksum *checksum;
- plist_t ret = NULL;
-
- if (!manifest_data)
- return ret;
-
- ret = plist_new_dict();
- plist_dict_insert_item(ret, "AuthVersion", plist_new_string("2.0"));
-
- /* AuthSignature Hash is: sha1() */
- plist_to_bin(manifest_data, &buffer, &length);
-
- sha1_len = g_checksum_type_get_length(G_CHECKSUM_SHA1);
- checksum = g_checksum_new(G_CHECKSUM_SHA1);
- g_checksum_update(checksum, (guchar *)buffer, length);
- g_checksum_get_digest(checksum, sha1, &sha1_len);
- s = (char *)g_checksum_get_string(checksum);
- printf("SHA1 AuthSignature: %s\n", s);
- plist_dict_insert_item(ret, "AuthSignature", plist_new_data((char*)sha1, sha1_len));
- g_checksum_free(checksum);
-
-
- plist_dict_insert_item(ret, "IsEncrypted", plist_new_uint(0));
- plist_dict_insert_item(ret, "Data", plist_new_data(buffer, length));
-
- free(buffer);
-
- return ret;
-}
-
enum plist_format_t {
PLIST_FORMAT_XML,
PLIST_FORMAT_BINARY
};
-static int plist_read_from_filename(char *filename, plist_t *plist)
+static void buffer_to_filename(char *filename, char *buffer, uint32_t length)
{
- return 1;
+ FILE *f;
+
+ f = fopen(filename, "ab");
+ fwrite(buffer, sizeof(char), length, f);
+ fclose(f);
}
static int plist_write_to_filename(plist_t plist, char *filename, enum plist_format_t format)
{
char *buffer = NULL;
uint32_t length;
- FILE *f;
if (!plist || !filename)
return 0;
@@ -257,9 +132,7 @@ static int plist_write_to_filename(plist_t plist, char *filename, enum plist_for
else
return 0;
- f = fopen(filename, "wb");
- fwrite(buffer, sizeof(char), length, f);
- fclose(f);
+ buffer_to_filename(filename, buffer, length);
free(buffer);
@@ -281,25 +154,50 @@ static int plist_strcmp(plist_t node, const char *str)
return ret;
}
+static plist_t device_link_message_factory_process_message_new(plist_t content)
+{
+ plist_t ret = plist_new_array();
+ plist_array_append_item(ret, plist_new_string("DLMessageProcessMessage"));
+ plist_array_append_item(ret, content);
+ return ret;
+}
+
+static void mobilebackup_cancel_backup_with_error(const char *reason)
+{
+ plist_t node = plist_new_dict();
+ plist_dict_insert_item(node, "BackupMessageTypeKey", plist_new_string("BackupMessageError"));
+ plist_dict_insert_item(node, "BackupErrorReasonKey", plist_new_string(reason));
+
+ plist_t message = device_link_message_factory_process_message_new(node);
+
+ mobilebackup_send(mobilebackup, message);
+
+ plist_free(message);
+ message = NULL;
+}
+
static void mobilebackup_write_status(char *path, int status)
{
+ struct stat st;
plist_t status_plist = plist_new_dict();
plist_dict_insert_item(status_plist, "Backup Success", plist_new_bool(status));
char *file_path = g_build_path(G_DIR_SEPARATOR_S, path, "Status.plist", NULL);
+ if (stat(file_path, &st) == 0)
+ remove(file_path);
plist_write_to_filename(status_plist, file_path, PLIST_FORMAT_XML);
g_free(file_path);
plist_free(status_plist);
}
-static void debug_plist(plist_t plist)
+static void debug_plist(plist_t a)
{
char *buffer = NULL;
uint32_t length = 0;
- if (!plist)
+ if (a == NULL)
return;
- plist_to_xml(plist, &buffer, &length);
+ plist_to_xml(a, &buffer, &length);
printf("Printing %i bytes plist:\n%s\n", length, buffer);
free(buffer);
@@ -341,6 +239,9 @@ int main(int argc, char *argv[])
char *backup_directory = NULL;
struct stat st;
plist_t node = NULL;
+ plist_t node_tmp = NULL;
+ char *buffer = NULL;
+ uint64_t length = 0;
/* we need to exit cleanly on running backups and restores or we cause havok */
signal(SIGINT, clean_exit);
@@ -440,6 +341,11 @@ int main(int argc, char *argv[])
printf("Started \"%s\" service on port %d.\n", MOBILEBACKUP_SERVICE_NAME, port);
mobilebackup_client_new(phone, port, &mobilebackup);
+ if (quit_flag > 0) {
+ printf("Aborting backup. Cancelled by user.\n");
+ cmd = CMD_LEAVE;
+ }
+
switch(cmd) {
case CMD_BACKUP:
printf("Starting backup...\n");
@@ -451,29 +357,32 @@ int main(int argc, char *argv[])
/* create Info.plist (Device infos, IC-Info.sidb, photos, app_ids, iTunesPrefs) */
printf("Creating \"%s/Info.plist\".\n", backup_directory);
plist_t info_plist = mobilebackup_factory_info_plist();
+ if (stat(info_path, &st) == 0)
+ remove(info_path);
plist_write_to_filename(info_plist, info_path, PLIST_FORMAT_XML);
g_free(info_path);
+ if (client) {
+ lockdownd_client_free(client);
+ client = NULL;
+ }
+
/* create Manifest.plist (backup manifest (backup state)) */
printf("Creating \"%s/Manifest.plist\".\n", backup_directory);
char *manifest_path = g_build_path(G_DIR_SEPARATOR_S, backup_directory, "Manifest.plist", NULL);
- plist_t manifest_data = mobilebackup_factory_manifest_data_plist();
- plist_t manifest_plist = mobilebackup_factory_manifest_plist(manifest_data);
- plist_write_to_filename(manifest_plist, manifest_path, PLIST_FORMAT_XML);
- g_free(manifest_path);
+ plist_t manifest_plist = NULL;
+ if (stat(manifest_path, &st) == 0)
+ remove(manifest_path);
/* create Status.plist with failed status for now */
mobilebackup_write_status(backup_directory, 0);
- /* close down lockdown connection as it is no longer needed */
- lockdownd_client_free(client);
- client = NULL;
-
- /* request backup from device with manifest */
+ /* request backup from device with manifest from last backup */
printf("Sending manifest and requesting backup.\n");
node = plist_new_dict();
- plist_dict_insert_item(node, "BackupManifestKey", manifest_plist);
+ if (manifest_plist)
+ plist_dict_insert_item(node, "BackupManifestKey", manifest_plist);
plist_dict_insert_item(node, "BackupComputerBasePathKey", plist_new_string("/"));
plist_dict_insert_item(node, "BackupMessageTypeKey", plist_new_string("BackupMessageBackupRequest"));
plist_dict_insert_item(node, "BackupProtocolVersion", plist_new_string("1.6"));
@@ -514,21 +423,66 @@ int main(int argc, char *argv[])
/* receive and save DLSendFile files and metadata, ACK each */
int file_index = 0;
+ char *file_path = NULL;
+ char *file_ext = NULL;
+ char *filename_mdinfo = NULL;
+ char *filename_mddata = NULL;
+ char *filename_source = NULL;
do {
mobilebackup_receive(mobilebackup, &message);
node = plist_array_get_item(message, 0);
if (plist_strcmp(node, "DLSendFile"))
break;
- printf("Receiving file %d...\n", file_index);
- /* TODO: save .mdinfo */
- /* TODO: save .mddata */
- debug_plist(message);
+ /* get source filename and print it */
+ node_tmp = plist_array_get_item(message, 2);
+ node = plist_dict_get_item(node_tmp, "DLFileSource");
+ plist_get_string_val(node, &filename_source);
+ printf("Received file %s...", filename_source);
+ free(filename_source);
+
+ /* save .mdinfo */
+ node = plist_dict_get_item(node_tmp, "BackupFileInfo");
+ if (node) {
+ node = plist_dict_get_item(node_tmp, "DLFileDest");
+ plist_get_string_val(node, &file_path);
+ file_ext = (char *)g_strconcat(file_path, ".mdinfo", NULL);
+ filename_mdinfo = g_build_path(G_DIR_SEPARATOR_S, backup_directory, file_ext, NULL);
+ node = plist_dict_get_item(node_tmp, "BackupFileInfo");
+ plist_write_to_filename(node, filename_mdinfo, PLIST_FORMAT_BINARY);
+ g_free(file_ext);
+ g_free(filename_mdinfo);
+ }
+
+ /* save .mddata */
+ node = plist_dict_get_item(node_tmp, "BackupFileInfo");
+ if (node_tmp && file_path) {
+ node = plist_dict_get_item(node_tmp, "DLFileDest");
+ plist_get_string_val(node, &file_path);
+ file_ext = (char *)g_strconcat(file_path, ".mddata", NULL);
+ filename_mddata = g_build_path(G_DIR_SEPARATOR_S, backup_directory, file_ext, NULL);
+ node_tmp = plist_array_get_item(message, 1);
+ plist_get_data_val(node_tmp, &buffer, &length);
+ buffer_to_filename(filename_mddata, buffer, length);
+ free(buffer);
+ buffer = NULL;
+ g_free(filename_mddata);
+ }
+
+ printf("DONE\n");
+
+ if (file_ext)
+ free(file_ext);
+
plist_free(message);
message = NULL;
- if (quit_flag) {
- /* FIXME: need to cancel the backup here */
+ if (quit_flag > 0) {
+ /* need to cancel the backup here */
+ mobilebackup_cancel_backup_with_error("Cancelling DLSendFile");
+
+ plist_free(message);
+ message = NULL;
break;
}
@@ -550,17 +504,58 @@ int main(int argc, char *argv[])
printf("Received %d files from device.\n", file_index);
if (!plist_strcmp(node, "DLMessageProcessMessage")) {
- node = plist_array_get_item(message, 1);
- node = plist_dict_get_item(node, "BackupMessageTypeKey");
+ node_tmp = plist_array_get_item(message, 1);
+ node = plist_dict_get_item(node_tmp, "BackupMessageTypeKey");
/* wait until received final backup finished message */
if (node && !plist_strcmp(node, "BackupMessageBackupFinished")) {
/* backup finished */
+
+ /* process BackupFilesToDeleteKey */
+ node = plist_dict_get_item(node_tmp, "BackupFilesToDeleteKey");
+ if (node) {
+ length = plist_array_get_size(node);
+ i = 0;
+ while ((node_tmp = plist_array_get_item(node, i++)) != NULL) {
+ plist_get_string_val(node_tmp, &file_path);
+
+ file_ext = (char *)g_strconcat(file_path, ".mddata", NULL);
+ filename_mddata = g_build_path(G_DIR_SEPARATOR_S, backup_directory, file_ext, NULL);
+ g_free(file_ext);
+ printf("Removing \"%s\"... ", filename_mddata);
+ if (!remove( filename_mddata )) {
+ printf("DONE\n");
+ } else
+ printf("FAILED\n");
+
+ file_ext = (char *)g_strconcat(file_path, ".mdinfo", NULL);
+ filename_mdinfo = g_build_path(G_DIR_SEPARATOR_S, backup_directory, file_ext, NULL);
+ g_free(file_ext);
+ printf("Removing \"%s\"... ", filename_mdinfo);
+ if (!remove( filename_mdinfo )) {
+ printf("DONE\n");
+ } else
+ printf("FAILED\n");
+ }
+ }
+
+ /* save new Manifest.plist */
+ node_tmp = plist_array_get_item(message, 1);
+ manifest_plist = plist_dict_get_item(node_tmp, "BackupManifestKey");
+ if (manifest_plist) {
+ if (stat(manifest_path, &st) != 0)
+ remove(manifest_path);
+ plist_write_to_filename(manifest_plist, manifest_path, PLIST_FORMAT_XML);
+ }
+
/* create: Status.plist (Info on how the backup process turned out) */
printf("Backup Successful.\n");
mobilebackup_write_status(backup_directory, 1);
}
}
+ if (manifest_path)
+ g_free(manifest_path);
+
if (node)
plist_free(node);
@@ -575,6 +570,7 @@ int main(int argc, char *argv[])
lockdownd_client_free(client);
client = NULL;
break;
+ case CMD_LEAVE:
default:
break;
}
@@ -584,11 +580,14 @@ int main(int argc, char *argv[])
client = NULL;
}
- if (client)
+ if (client) {
lockdownd_client_free(client);
+ client = NULL;
+ }
if (mobilebackup)
mobilebackup_client_free(mobilebackup);
+
iphone_device_free(phone);
return 0;
--
cgit v1.1-32-gdbae