/* 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 . */ 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 LogoutAsync() { LogoutRequest request = new LogoutRequest(); request.Key = LoginResponse.Key; return await clt.MakeJsonPostRequestAsync("/api/v1/Logout",request); } public async Task EnumerateBackupsAsync() { EnumerateBackupsRequest request=new EnumerateBackupsRequest(); request.DeviceId = DeviceId; request.Key = LoginResponse.Key; return await clt.MakeJsonPostRequestAsync("/api/v1/Backups",request); } public async Task EnumerateBackupDataAsync(long backupId) { EnumerateBackupRequest request=new EnumerateBackupRequest(); request.BackupId= backupId; request.Key = LoginResponse.Key; return await clt.MakeJsonPostRequestAsync("/api/v1/Backup",request); } public async Task GetDevicesAsync() { EnumerateDeviceRequest request = new EnumerateDeviceRequest(); request.Key = LoginResponse.Key; return await clt.MakeJsonPostRequestAsync("/api/v1/Devices",request); } public async Task SetDeviceAsync(string deviceName) { GetDeviceRequest request=new GetDeviceRequest(); request.Key = LoginResponse.Key; request.Name = deviceName; var resp= await clt.MakeJsonPostRequestAsync("/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 PrepareBackupAsync(IVirtualFilesystem fs) { Func,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("/api/v1/CreateBackup",request); return await Task.Run(()=>{ return new BackupContext(LoginResponse.Key,clt.Client,fs,response,request.DeviceId); }); } public async Task PrepareBackupAsync(IVirtualFilesystem fs,UnixPath path) { return await PrepareBackupAsync(fs.GetSubdirFilesystem(path)); } } }