Files
BeWoPlaner/SharedLauncher/Logic/FileController.cs

265 lines
8.8 KiB
C#

using BS.SharedLauncher.DataContract;
using BS.SharedLauncher.Enums;
using BS.SharedLauncher.Extensions;
using BS.SharedLauncher.Information;
using BS.SharedLauncher.Update;
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace BS.SharedLauncher.Logic
{
public static class FileController
{
private static string ZipFormatName => BeWoPathFileConfig.ZipFormatName;
private static string DotBeWoInfo => BeWoPathFileConfig.DotBeWoInfo;
public static string GetDZipPath(string root, int number) => Path.Combine(root, string.Format(ZipFormatName, getFileNumberCountString(number)));
public static string GetDZipInfoPath(string root, int number) => GetDZipPath(root, number) + DotBeWoInfo;
public static void ApplyDZip(Dictionary<string, List<string>> zip2keepfiles, string destinationfolder, Action<int, object> apply)
{
foreach (var pair in zip2keepfiles)
{
ApplyDZip(pair.Key, destinationfolder, pair.Value.Contains, apply);
}
}
public static void ApplyDZip(string zipfilepath, string destinationfolder, Action<int, object> apply)
=> ApplyDZip(zipfilepath, destinationfolder, (s) => true, apply);
private static void ApplyDZip(string zipfilepath, string destinationfolder, Func<string, bool> isValidFunc, Action<int, object> apply)
{
using (ZipArchive archive = ZipFile.OpenRead(zipfilepath))
{
foreach (ZipArchiveEntry entry in archive.Entries)
{
if (isValidFunc(entry.FullName))
{
var path = destinationfolder.Combine(entry.FullName);
Directory.CreateDirectory(Path.GetDirectoryName(path));
entry.ExtractToFile(path, true);
apply((int)LauncherProgress.ApplyUpdate, new ApplyFileEventArgs(entry.FullName, path));
Thread.Sleep(100);
}
}
}
}
public static void RemoveUnsuedFiles(PlanerPackageInfoDC latestApplicationInfo, string applyFolder, Action<int, object> status)
{
foreach (var file in GetPlanerFiles(applyFolder))
{
file.LoadHash();
if (latestApplicationInfo.Files.Any(late => late.EqualsFile(file)))
continue;
if (file.IgnoreToRemove())
continue;
File.Delete(file.AbsolutePath);
status((int)LauncherProgress.DeleteUpdate, file);
}
}
public static List<string> GetValidDZipPaths(string path)
{
var res = new List<string>();
var dir = new DirectoryInfo(path);
var files = dir.GetFiles("*.zip");
foreach (var file in files)
{
if (file.FullName.IsDZipValid())
res.Add(file.FullName);
}
return res;
}
public static string GetNewZipPath(string root)
{
int i = 0;
string temp = string.Empty;
do
{
temp = GetDZipPath(root, i++);
} while (temp.IsDZipValidAndDeleteIfNot());
return temp;
}
public static void SaveDZipStream(string path, Stream filebytestream, long length, Action<int, DownloadProgressEventArgs> download)
{
long startlength = 0;
FileInfo finfo = new FileInfo(path);
if (finfo.Exists)
startlength = finfo.Length; // If File exists,
// we need to send the Start length to the server
using (FileStream writeStream =
new System.IO.FileStream(path, FileMode.OpenOrCreate, FileAccess.Write))
{
int chunkSize = 2048;
byte[] buffer = new byte[chunkSize];
do
{
int bytesRead = filebytestream.Read(buffer, 0, chunkSize);
if (bytesRead == 0) break;
writeStream.Write(buffer, 0, bytesRead);
download(11, new DownloadProgressEventArgs(writeStream.Position * 100 / length));
}
while (true);
writeStream.Close();
}
filebytestream.Dispose();
}
public static void SaveDZip(string path, byte[] data)
{
File.WriteAllBytes(path, data);
}
public static void SaveInfo<T>(string path, T t)
where T : class
{
File.WriteAllText(path.WithInfoExtension(), XmlConverter.Serialize<T>(t));
}
public static void DeleteInfo(string path)
{
File.Delete(path.WithInfoExtension());
}
public static PlanerPackageInfoDC LoadInfo(string filepath)
{
filepath = filepath.WithInfoExtension();
var xml = File.ReadAllText(filepath);
var obj = XmlConverter.Deserialize<PlanerPackageInfoDC>(xml);
return obj;
}
public static bool TryGetPackageInfo(string filepath, out PlanerPackageInfoDC planerPackageInfoDC)
{
planerPackageInfoDC = null;
try
{
planerPackageInfoDC = LoadInfo(filepath);
}
catch (Exception)
{
return false;
}
return true;
}
public static Dictionary<string, PlanerPackageInfoDC> LoadInfos(string rootfolder)
{
var allDZips = GetValidDZipPaths(rootfolder);
if (allDZips is null || !allDZips.Any())
return null;
return allDZips.ToDictionary(dzip => dzip, dzip => LoadInfo(dzip));
// Detailed Debug Section
//var res = new Dictionary<string, PlanerPackageInfoDC>();
//foreach (var dzip in allDZips)
//{
// res.Add(dzip, GetPackageInfo(dzip));
//}
//return res;
}
public static List<PlanerFileInfo> GetPlanerFiles(string path)
{
var res = new List<PlanerFileInfo>();
// Sollte der Path ohne / enden, wird der unterordner mit angegeben
// Deshalb manuell hinzufügen, falls nicht vorhanden
if (!path.EndsWith(Path.DirectorySeparatorChar.ToString()))
path += Path.DirectorySeparatorChar;
getPlanerFilesRecursive(new DirectoryInfo(path), path, ref res);
return res;
}
public static bool IsDZipValidAndDeleteIfNot(this string path)
{
if (path.IsDZipValid())
return true;
new FileInfo(path).Delete();
new FileInfo(path + BeWoPathFileConfig.DotBeWoInfo).Delete();
return false;
}
public static bool IsDZipValid(this string path)
{
return path.Exists() && (path + BeWoPathFileConfig.DotBeWoInfo).Exists();
}
public static string WithInfoExtension(this string path)
{
if (path.EndsWith(DotBeWoInfo))
return path;
return path + DotBeWoInfo;
}
private static void getPlanerFilesRecursive(DirectoryInfo directoryInfo, string relativeTo, ref List<PlanerFileInfo> files)
{
foreach (var item in directoryInfo.GetDirectories())
{
getPlanerFilesRecursive(item, relativeTo, ref files);
}
foreach (var item in directoryInfo.GetFiles())
{
var file = new PlanerFileInfo(item, relativeTo);
files.Add(file);
}
}
private static string getFileNumberCountString(int i)
{
if (i == 0)
return string.Empty;
return $"({i})";
}
public static bool IsDirectoryWritable(string dirPath, bool throwIfFails = false)
{
try
{
Directory.CreateDirectory(dirPath);
using (FileStream fs = File.Create(
Path.Combine(
dirPath,
BeWoPathFileConfig.TestForPermissionFile
),
1,
FileOptions.DeleteOnClose)
)
{ }
return true;
}
catch
{
if (throwIfFails)
throw;
else
return false;
}
}
}
}