Skip to content

Commit

Permalink
iOS backup creation
Browse files Browse the repository at this point in the history
  • Loading branch information
artehe committed Jul 25, 2023
1 parent 3b0cf09 commit c232217
Show file tree
Hide file tree
Showing 13 changed files with 1,649 additions and 1 deletion.
38 changes: 38 additions & 0 deletions Netimobiledevice/Backup/BackupFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using System.IO;

namespace Netimobiledevice.Backup
{
/// <summary>
/// Represents a file in the backup process.
/// </summary>
public class BackupFile
{
/// <summary>
/// The absolute path in the device.
/// </summary>
public string DevicePath { get; }

/// <summary>
/// Relative path to the backup folder, includes the device UDID.
/// </summary>
public string BackupPath { get; }

/// <summary>
/// The absolute path in the local backup folder.
/// </summary>
public string LocalPath { get; }

/// <summary>
/// Creates an instance of a BackupFile
/// </summary>
/// <param name="devicePath">The absolute path in the device.</param>
/// <param name="backupPath">Relative path to the backup folder, includes the device UDID.</param>
/// <param name="backupDirectory">Absolute path to the backup directory</param>
public BackupFile(string devicePath, string backupPath, string backupDirectory)
{
DevicePath = devicePath;
BackupPath = backupPath;
LocalPath = Path.Combine(backupDirectory, backupPath);
}
}
}
15 changes: 15 additions & 0 deletions Netimobiledevice/Backup/BackupFileErrorEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
namespace Netimobiledevice.Backup
{
/// <summary>
/// EventArgs for File Transfer Error events.
/// </summary>
public class BackupFileErrorEventArgs : BackupFileEventArgs
{
/// <summary>
/// Indicates whether the backup should be cancelled.
/// </summary>
public bool Cancel { get; set; }

public BackupFileErrorEventArgs(BackupFile file) : base(file) { }
}
}
40 changes: 40 additions & 0 deletions Netimobiledevice/Backup/BackupFileEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using System;

namespace Netimobiledevice.Backup
{
/// <summary>
/// EventArgs for BackupFile related events.
/// </summary>
public class BackupFileEventArgs : EventArgs
{
/// <summary>
/// The BackupFile related to the event.
/// </summary>
public BackupFile File { get; }
/// <summary>
/// The file contents associated with the backup file
/// </summary>
public byte[] Data { get; }

/// <summary>
/// Creates an instance of the BackupFileEventArgs class.
/// </summary>
/// <param name="file">The BackupFile related to the event.</param>
public BackupFileEventArgs(BackupFile file)
{
File = file;
Data = Array.Empty<byte>();
}

/// <summary>
/// Creates an instance of the BackupFileEventArgs class.
/// </summary>
/// <param name="file">The BackupFile related to the event.</param>
/// <param name="data">The content of the BackupFile</param>
public BackupFileEventArgs(BackupFile file, byte[] data)
{
File = file;
Data = data;
}
}
}
32 changes: 32 additions & 0 deletions Netimobiledevice/Backup/BackupResultEventArgs.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
using System;
using System.Collections.Generic;

namespace Netimobiledevice.Backup
{
/// <summary>
/// EventArgs including information about the backup process result.
/// </summary>
public class BackupResultEventArgs : EventArgs
{
/// <summary>
/// Indicates whether the user cancelled the backup process.
/// </summary>
public bool UserCancelled { get; }

/// <summary>
/// Indicates whether the backup has finished due to a device disconnection.
/// </summary>
public bool DeviceDisconnected { get; }

/// <summary>
/// The files that failed to transfer during the backup.
/// </summary>
public IReadOnlyList<BackupFile> TransferErrors { get; }

public BackupResultEventArgs(IEnumerable<BackupFile> failedFiles, bool userCancelled, bool deviceDisconnected)
{
UserCancelled = userCancelled;
TransferErrors = new List<BackupFile>(failedFiles);
}
}
}
11 changes: 11 additions & 0 deletions Netimobiledevice/Backup/BackupState.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace Netimobiledevice.Backup
{
/// <summary>
/// The backup state.
/// </summary>
public enum BackupState
{
Empty,
New,
}
}
69 changes: 69 additions & 0 deletions Netimobiledevice/Backup/BackupStatus.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
using Netimobiledevice.Plist;
using System;
using System.Diagnostics;
using System.Globalization;

namespace Netimobiledevice.Backup
{
/// <summary>
/// Represents the Status.plist of a backup
/// </summary>
public class BackupStatus
{
/// <summary>
/// The backup unique identifier.
/// </summary>
public string UUID { get; }
/// <summary>
/// The backup timestamp.
/// </summary>
public DateTime Date { get; }
/// <summary>
/// Indicates whether the backup is a full one or incremental.
/// </summary>
public bool IsFullBackup { get; }
/// <summary>
/// Version of the backup protocol.
/// </summary>
public Version Version { get; }
/// <summary>
/// The backup state.
/// </summary>
public BackupState BackupState { get; }
/// <summary>
/// The snapshot state.
/// </summary>
public SnapshotState SnapshotState { get; }

/// <summary>
/// Creates an instance of BackupStatus.
/// </summary>
/// <param name="status">The dictionary from the Status.plist file.</param>
public BackupStatus(DictionaryNode status)
{
UUID = status["UUID"].AsStringNode().Value;
Date = status["Date"].AsDateNode().Value;
Version = Version.Parse(status["Version"].AsStringNode().Value);
IsFullBackup = status["IsFullBackup"].AsBooleanNode().Value;

CultureInfo cultureInfo = CultureInfo.InvariantCulture;
TextInfo textInfo = cultureInfo.TextInfo;

string backupStateString = textInfo.ToTitleCase(status["BackupState"].AsStringNode().Value);
if (Enum.TryParse(backupStateString, out BackupState state)) {
BackupState = state;
}
else {
Debug.WriteLine($"WARNING: New Backup state found: {backupStateString}");
}

string snapshotStateString = textInfo.ToTitleCase(status["SnapshotState"].AsStringNode().Value);
if (Enum.TryParse(snapshotStateString, out SnapshotState snapshotState)) {
SnapshotState = snapshotState;
}
else {
Debug.WriteLine($"WARNING: New Snapshot state found: {snapshotStateString}");
}
}
}
}
Loading

0 comments on commit c232217

Please sign in to comment.