#nullable enable
|
|
using IPA.AntiMalware;
|
|
using IPA.Config;
|
|
using IPA.Utilities;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using static IPA.Logging.Logger;
|
|
#if NET3
|
|
using Net3_Proxy;
|
|
using Path = Net3_Proxy.Path;
|
|
using File = Net3_Proxy.File;
|
|
using Directory = Net3_Proxy.Directory;
|
|
using Array = Net3_Proxy.Array;
|
|
#endif
|
|
|
|
namespace IPA.Injector
|
|
{
|
|
internal static class Updates
|
|
{
|
|
private const string DeleteFileName = "$$delete";
|
|
|
|
public static void InstallPendingUpdates()
|
|
{
|
|
InstallPendingSelfUpdates();
|
|
InstallPendingModUpdates();
|
|
}
|
|
|
|
private static void InstallPendingSelfUpdates()
|
|
{
|
|
var path = Path.Combine(UnityGame.InstallPath, "IPA.exe");
|
|
if (!File.Exists(path)) return;
|
|
|
|
var scanResult = AntiMalwareEngine.Engine.ScanFile(new FileInfo(path));
|
|
if (scanResult == ScanResult.Detected)
|
|
{
|
|
updater.Error("Scan of BSIPA installer found malware; not updating");
|
|
return;
|
|
}
|
|
if (!SelfConfig.AntiMalware_.RunPartialThreatCode_ && scanResult is not ScanResult.KnownSafe and not ScanResult.NotDetected)
|
|
{
|
|
updater.Error("Scan of BSIPA installer returned partial threat; not updating. To allow this, enable AntiMalware.RunPartialThreatCode in the config.");
|
|
return;
|
|
}
|
|
|
|
var ipaVersion = new Version(FileVersionInfo.GetVersionInfo(path).FileVersion);
|
|
var selfVersion = Assembly.GetExecutingAssembly().GetName().Version;
|
|
|
|
if (ipaVersion > selfVersion)
|
|
{
|
|
_ = Process.Start(new ProcessStartInfo
|
|
{
|
|
FileName = path,
|
|
Arguments = $"\"-nw={Process.GetCurrentProcess().Id},s={string.Join(" ", Environment.GetCommandLineArgs().Skip(1).StrJP()).Replace("\\", "\\\\").Replace(",", "\\,")}\"",
|
|
UseShellExecute = false
|
|
});
|
|
|
|
updater.Info("Updating BSIPA...");
|
|
Environment.Exit(0);
|
|
}
|
|
}
|
|
|
|
private static void InstallPendingModUpdates()
|
|
{
|
|
var pendingDir = Path.Combine(UnityGame.InstallPath, "IPA", "Pending");
|
|
if (!Directory.Exists(pendingDir)) return;
|
|
|
|
// there are pending updates, install
|
|
updater.Info("Installing pending updates");
|
|
|
|
var toDelete = Array.Empty<string>();
|
|
var delFn = Path.Combine(pendingDir, DeleteFileName);
|
|
if (File.Exists(delFn))
|
|
{
|
|
toDelete = File.ReadAllLines(delFn);
|
|
File.Delete(delFn);
|
|
}
|
|
|
|
foreach (var file in toDelete)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(Path.Combine(UnityGame.InstallPath, file));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
updater.Error("While trying to install pending updates: Error deleting file marked for deletion");
|
|
updater.Error(e);
|
|
}
|
|
}
|
|
|
|
#region Self Protection
|
|
|
|
string path;
|
|
if (Directory.Exists(path = Path.Combine(pendingDir, "IPA")))
|
|
{
|
|
var dirs = new Stack<string>(20);
|
|
|
|
dirs.Push(path);
|
|
|
|
while (dirs.Count > 0)
|
|
{
|
|
var currentDir = dirs.Pop();
|
|
string[] subDirs;
|
|
string[] files;
|
|
try
|
|
{
|
|
subDirs = Directory.GetDirectories(currentDir);
|
|
files = Directory.GetFiles(currentDir);
|
|
}
|
|
catch (UnauthorizedAccessException e)
|
|
{
|
|
updater.Error(e);
|
|
continue;
|
|
}
|
|
catch (DirectoryNotFoundException e)
|
|
{
|
|
updater.Error(e);
|
|
continue;
|
|
}
|
|
|
|
foreach (var file in files)
|
|
{
|
|
try
|
|
{
|
|
if (!Utils.GetRelativePath(file, path).Split(Path.PathSeparator).Contains("Pending"))
|
|
File.Delete(file);
|
|
}
|
|
catch (FileNotFoundException e)
|
|
{
|
|
updater.Error(e);
|
|
}
|
|
}
|
|
|
|
foreach (var str in subDirs)
|
|
dirs.Push(str);
|
|
}
|
|
}
|
|
if (File.Exists(path = Path.Combine(pendingDir, "IPA.exe")))
|
|
{
|
|
File.Delete(path);
|
|
if (File.Exists(path = Path.Combine(pendingDir, "Mono.Cecil.dll")))
|
|
File.Delete(path);
|
|
}
|
|
|
|
#endregion
|
|
|
|
try
|
|
{
|
|
Utils.CopyAll(new DirectoryInfo(pendingDir), new DirectoryInfo(UnityGame.InstallPath), onCopyException: (e, f) =>
|
|
{
|
|
updater.Error($"Error copying file {Utils.GetRelativePath(f.FullName, pendingDir)} from Pending:");
|
|
updater.Error(e);
|
|
return true;
|
|
});
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
updater.Error("While trying to install pending updates: Error copying files in");
|
|
updater.Error(e);
|
|
}
|
|
|
|
try
|
|
{
|
|
Directory.Delete(pendingDir, true);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
updater.Error("Something went wrong performing an operation that should never fail!");
|
|
updater.Error(e);
|
|
}
|
|
}
|
|
}
|
|
}
|