148 lines
6.1 KiB
C#
148 lines
6.1 KiB
C#
/*
|
|
A simple Backup Client / Server
|
|
Copyright (C) 2023 Mike Nolan
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Net.Http;
|
|
using System.Security.Cryptography;
|
|
using System.Threading.Tasks;
|
|
using Tesses.Backup.Models;
|
|
using Tesses.VirtualFilesystem;
|
|
|
|
namespace Tesses.Backup
|
|
{
|
|
public class BackupSession
|
|
{
|
|
public BackupSession(LoginResponse response,BackupClient client)
|
|
{
|
|
this.clt = client;
|
|
this.LoginResponse = response;
|
|
}
|
|
BackupClient clt;
|
|
public LoginResponse LoginResponse {get;set;}
|
|
|
|
public long DeviceId {get;set;}=-1;
|
|
|
|
|
|
public async Task<LogoutResponse> LogoutAsync()
|
|
{
|
|
LogoutRequest request = new LogoutRequest();
|
|
request.Key = LoginResponse.Key;
|
|
return await clt.MakeJsonPostRequestAsync<LogoutResponse>("/api/v1/Logout",request);
|
|
}
|
|
public async Task<EnumerateBackupsResponse> EnumerateBackupsAsync()
|
|
{
|
|
EnumerateBackupsRequest request=new EnumerateBackupsRequest();
|
|
request.DeviceId = DeviceId;
|
|
request.Key = LoginResponse.Key;
|
|
return await clt.MakeJsonPostRequestAsync<EnumerateBackupsResponse>("/api/v1/Backups",request);
|
|
|
|
}
|
|
|
|
public async Task<EnumerateBackupResponse> EnumerateBackupDataAsync(long backupId)
|
|
{
|
|
EnumerateBackupRequest request=new EnumerateBackupRequest();
|
|
request.BackupId= backupId;
|
|
request.Key = LoginResponse.Key;
|
|
return await clt.MakeJsonPostRequestAsync<EnumerateBackupResponse>("/api/v1/Backup",request);
|
|
}
|
|
public async Task<EnumerateDeviceResponse> GetDevicesAsync()
|
|
{
|
|
EnumerateDeviceRequest request = new EnumerateDeviceRequest();
|
|
request.Key = LoginResponse.Key;
|
|
|
|
return await clt.MakeJsonPostRequestAsync<EnumerateDeviceResponse>("/api/v1/Devices",request);
|
|
}
|
|
|
|
public async Task<GetDeviceResponse> SetDeviceAsync(string deviceName)
|
|
{
|
|
GetDeviceRequest request=new GetDeviceRequest();
|
|
request.Key = LoginResponse.Key;
|
|
request.Name = deviceName;
|
|
var resp= await clt.MakeJsonPostRequestAsync<GetDeviceResponse>("/api/v1/Device",request);
|
|
DeviceId=resp.DeviceId;
|
|
return resp;
|
|
}
|
|
public async Task RestoreFileAsync(string hash,long myDeviceId,Stream strm)
|
|
{
|
|
var fstrm=await clt.Client.GetStreamAsync($"/api/v1/File?key={LoginResponse.Key}&device={myDeviceId}&hash={hash}");
|
|
await fstrm.CopyToAsync(strm);
|
|
}
|
|
public async Task RestoreFileAsync(string hash,Stream strm)
|
|
{
|
|
await RestoreFileAsync(hash,DeviceId,strm);
|
|
}
|
|
public async Task<BackupContext> PrepareBackupAsync(IVirtualFilesystem fs)
|
|
{
|
|
|
|
Func<List<BackupFileEntry>,UnixPath,Task> enumerateFiles=null;
|
|
enumerateFiles=async(ent,p)=>{
|
|
foreach(var dir in fs.EnumerateDirectories(p))
|
|
{
|
|
BackupFileEntry entry=new BackupFileEntry();
|
|
entry.IsFile=false;
|
|
entry.Created = await fs.GetCreationTimeAsync(dir);
|
|
entry.Modified = await fs.GetLastWriteTimeAsync(dir);
|
|
entry.Length = 0;
|
|
entry.Hash ="";
|
|
entry.Name = dir.Name;
|
|
|
|
await enumerateFiles(entry.SubEntries,dir);
|
|
ent.Add(entry);
|
|
}
|
|
foreach(var file in fs.EnumerateFiles(p))
|
|
{
|
|
BackupFileEntry entry=new BackupFileEntry();
|
|
|
|
entry.IsFile=true;
|
|
entry.Created = await fs.GetCreationTimeAsync(file);
|
|
entry.Modified = await fs.GetLastWriteTimeAsync(file);
|
|
using(var f = await fs.OpenAsync(file,System.IO.FileMode.Open,System.IO.FileAccess.Read,System.IO.FileShare.Read))
|
|
{
|
|
entry.Length = f.Length;
|
|
|
|
using (var bufferedStream = new BufferedStream(f, 1024 * 32))
|
|
{
|
|
using(var sha = new SHA256Managed())
|
|
{
|
|
byte[] hashBytes=sha.ComputeHash(bufferedStream);
|
|
entry.Hash = BitConverter.ToString(hashBytes).Replace("-","");
|
|
}
|
|
}
|
|
}
|
|
entry.Name = file.Name;
|
|
|
|
ent.Add(entry);
|
|
}
|
|
};
|
|
CreateBackupRequest request = new CreateBackupRequest();
|
|
await enumerateFiles(request.BackupData,Special.Root);
|
|
request.DeviceId = DeviceId;
|
|
request.Key = LoginResponse.Key;
|
|
|
|
var response=await clt.MakeJsonPostRequestAsync<CreateBackupResponse>("/api/v1/CreateBackup",request);
|
|
return await Task.Run<BackupContext>(()=>{
|
|
return new BackupContext(LoginResponse.Key,clt.Client,fs,response,request.DeviceId);
|
|
});
|
|
}
|
|
public async Task<BackupContext> PrepareBackupAsync(IVirtualFilesystem fs,UnixPath path)
|
|
{
|
|
return await PrepareBackupAsync(fs.GetSubdirFilesystem(path));
|
|
}
|
|
}
|
|
} |