public static void CopyAll(DirectoryInfo source, DirectoryInfo target, bool aggressive, BackupUnit backup, Func <FileInfo, FileInfo, IEnumerable <FileInfo> > interceptor = null) { if (interceptor == null) { interceptor = PassThroughInterceptor; } // Copy each file into the new directory. foreach (FileInfo fi in source.GetFiles()) { foreach (var targetFile in interceptor(fi, new FileInfo(Path.Combine(target.FullName, fi.Name)))) { if (!targetFile.Exists || targetFile.LastWriteTimeUtc < fi.LastWriteTimeUtc || aggressive) { targetFile.Directory.Create(); Console.WriteLine(@"Copying {0}", targetFile.FullName); backup.Add(targetFile); fi.CopyTo(targetFile.FullName, true); } } } // Copy each subdirectory using recursion. foreach (DirectoryInfo diSourceSubDir in source.GetDirectories()) { DirectoryInfo nextTargetSubDir = new DirectoryInfo(Path.Combine(target.FullName, diSourceSubDir.Name)); CopyAll(diSourceSubDir, nextTargetSubDir, aggressive, backup, interceptor); } }
public static void CopyAll(DirectoryInfo source, DirectoryInfo target, bool aggressive, BackupUnit backup, Func <FileInfo, FileInfo, IEnumerable <FileInfo> > interceptor = null, bool recurse = true) { if (interceptor == null) { interceptor = PassThroughInterceptor; } // Copy each file into the new directory. foreach (var fi in source.GetFiles()) { foreach (var targetFile in interceptor(fi, new FileInfo(Path.Combine(target.FullName, fi.Name)))) { if (targetFile.Exists && targetFile.LastWriteTimeUtc >= fi.LastWriteTimeUtc && !aggressive) { continue; } Debug.Assert(targetFile.Directory != null, "targetFile.Directory != null"); targetFile.Directory?.Create(); LineBack(); ClearLine(); Console.WriteLine(@"Copying {0}", targetFile.FullName); backup.Add(targetFile); fi.CopyTo(targetFile.FullName, true); } } // Copy each subdirectory using recursion. if (!recurse) { return; } foreach (var diSourceSubDir in source.GetDirectories()) { var nextTargetSubDir = new DirectoryInfo(Path.Combine(target.FullName, diSourceSubDir.Name)); CopyAll(diSourceSubDir, nextTargetSubDir, aggressive, backup, interceptor); } }
private static void Install(PatchContext context) { try { var backup = new BackupUnit(context); // Copying Console.WriteLine("Updating files... "); var nativePluginFolder = Path.Combine(context.DataPathDst, "Plugins"); bool isFlat = Directory.Exists(nativePluginFolder) && Directory.GetFiles(nativePluginFolder).Any(f => f.EndsWith(".dll")); bool force = !BackupManager.HasBackup(context) || context.Args.Contains("-f") || context.Args.Contains("--force"); var architecture = DetectArchitecture(context.Executable); Console.WriteLine("Architecture: {0}", architecture); CopyAll(new DirectoryInfo(context.DataPathSrc), new DirectoryInfo(context.DataPathDst), force, backup, (from, to) => NativePluginInterceptor(from, to, new DirectoryInfo(nativePluginFolder), isFlat, architecture)); Console.WriteLine("Successfully updated files!"); if (!Directory.Exists(context.PluginsFolder)) { Console.WriteLine("Creating plugins folder... "); Directory.CreateDirectory(context.PluginsFolder); } // Deobfuscating /*var options = new Deobfuscator.Options(); * options.OneFileAtATime = false; * var searchDir = new Deobfuscator.SearchDir() { InputDirectory = context.ManagedPath, OutputDirectory = Path.Combine(context.ManagedPath, "decompiled/"), SkipUnknownObfuscators = false }; * options.SearchDirs = new List<Deobfuscator.SearchDir>() { searchDir }; * new Deobfuscator(options).DoIt();*/ // Patching var patchedModule = PatchedModule.Load(context.EngineFile); if (!patchedModule.IsPatched) { Console.Write("Patching UnityEngine.dll... "); backup.Add(context.EngineFile); patchedModule.Patch(); Console.WriteLine("Done!"); } // Virtualizing if (File.Exists(context.AssemblyFile)) { var virtualizedModule = VirtualizedModule.Load(context.AssemblyFile); if (!virtualizedModule.IsVirtualized) { Console.Write("Virtualizing Assembly-Csharp.dll... "); backup.Add(context.AssemblyFile); virtualizedModule.Virtualize(); Console.WriteLine("Done!"); } } // Creating shortcut if (!File.Exists(context.ShortcutPath)) { Console.Write("Creating shortcut to IPA ({0})... ", context.IPA); try { Shortcut.Create( fileName: context.ShortcutPath, targetPath: context.IPA, arguments: Args(context.Executable, "--launch"), workingDirectory: context.ProjectRoot, description: "Launches the game and makes sure it's in a patched state", hotkey: "", iconPath: context.Executable ); Console.WriteLine("Created"); } catch (Exception e) { Console.Error.WriteLine("Failed to create shortcut, but game was patched!"); } } } catch (Exception e) { Fail("Oops! This should not have happened.\n\n" + e); } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Finished!"); Console.ResetColor(); }
private static void Install(PatchContext context) { try { var backup = new BackupUnit(context); // Copying Console.WriteLine("Updating files... "); var nativePluginFolder = Path.Combine(context.DataPathDst, "Plugins"); bool isFlat = Directory.Exists(nativePluginFolder) && Directory.GetFiles(nativePluginFolder).Any(f => f.EndsWith(".dll")); bool force = !BackupManager.HasBackup(context) || context.Args.Contains("-f") || context.Args.Contains("--force"); var architecture = DetectArchitecture(context.Executable); Console.WriteLine("Architecture: {0}", architecture); CopyAll(new DirectoryInfo(context.DataPathSrc), new DirectoryInfo(context.DataPathDst), force, backup, (from, to) => NativePluginInterceptor(from, to, new DirectoryInfo(nativePluginFolder), isFlat, architecture)); Console.WriteLine("Successfully updated files!"); if (!Directory.Exists(context.PluginsFolder)) { Console.WriteLine("Creating plugins folder... "); Directory.CreateDirectory(context.PluginsFolder); } if (!Directory.Exists(context.LogsFolder)) { Console.WriteLine("Creating logs folder... "); Directory.CreateDirectory(context.LogsFolder); } // Patching var patchedModule = PatchedModule.Load(context.EngineFile); if (!patchedModule.IsPatched) { Console.Write("Patching UnityEngine.dll... "); backup.Add(context.EngineFile); patchedModule.Patch(); Console.WriteLine("Done!"); } // Virtualizing if (File.Exists(context.AssemblyFile)) { var virtualizedModule = VirtualizedModule.Load(context.AssemblyFile); if (!virtualizedModule.IsVirtualized) { Console.Write("Virtualizing Assembly-Csharp.dll... "); backup.Add(context.AssemblyFile); virtualizedModule.Virtualize(); Console.WriteLine("Done!"); } } } catch (Exception e) { Fail("Oops! This should not have happened.\n\n" + e); } Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Finished!"); Console.ResetColor(); }
private static void Install(PatchContext context) { try { var backup = new BackupUnit(context); if (ArgDestructive) { #region Patch Version Check var patchedModule = PatchedModule.Load(context.EngineFile); #if DEBUG var isCurrentNewer = Version.CompareTo(patchedModule.Data.Version) >= 0; #else var isCurrentNewer = Version.CompareTo(patchedModule.Data.Version) > 0; #endif Console.WriteLine($"Current: {Version} Patched: {patchedModule.Data.Version}"); if (isCurrentNewer) { Console.ForegroundColor = ConsoleColor.White; Console.WriteLine( $"Preparing for update, {(patchedModule.Data.Version == null ? "UnPatched" : patchedModule.Data.Version.ToString())} => {Version}"); Console.WriteLine("--- Starting ---"); Revert(context); Console.ResetColor(); #region File Copying Console.ForegroundColor = ConsoleColor.Magenta; Console.WriteLine("Updating files... "); var nativePluginFolder = Path.Combine(context.DataPathDst, "Plugins"); bool isFlat = Directory.Exists(nativePluginFolder) && Directory.GetFiles(nativePluginFolder).Any(f => f.EndsWith(".dll")); bool force = !BackupManager.HasBackup(context) || ArgForce; var architecture = DetectArchitecture(context.Executable); Console.WriteLine("Architecture: {0}", architecture); CopyAll(new DirectoryInfo(context.DataPathSrc), new DirectoryInfo(context.DataPathDst), force, backup, (from, to) => NativePluginInterceptor(from, to, new DirectoryInfo(nativePluginFolder), isFlat, architecture)); CopyAll(new DirectoryInfo(context.LibsPathSrc), new DirectoryInfo(context.LibsPathDst), force, backup, (from, to) => NativePluginInterceptor(from, to, new DirectoryInfo(nativePluginFolder), isFlat, architecture)); Console.WriteLine("Successfully updated files!"); #endregion } else { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine($"Files up to date @ Version {Version}!"); Console.ResetColor(); } #endregion #region Patching if (!patchedModule.Data.IsPatched || isCurrentNewer) { Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"Patching UnityEngine.dll with Version {Application.ProductVersion}... "); backup.Add(context.EngineFile); patchedModule.Patch(Version); Console.WriteLine("Done!"); Console.ResetColor(); } #endregion #region Creating shortcut if (!File.Exists(context.ShortcutPath)) { Console.ForegroundColor = ConsoleColor.DarkGreen; Console.WriteLine("Creating shortcut to IPA ({0})... ", context.IPA); try { Shortcut.Create( fileName: context.ShortcutPath, targetPath: context.IPA, arguments: Args(context.Executable, "-ln"), workingDirectory: context.ProjectRoot, description: "Launches the game and makes sure it's in a patched state", hotkey: "", iconPath: context.Executable ); } catch (Exception) { Console.ForegroundColor = ConsoleColor.Red; Console.Error.WriteLine("Failed to create shortcut, but game was patched!"); } Console.ResetColor(); } #endregion } else { Console.ForegroundColor = ConsoleColor.Cyan; Console.WriteLine("Restoring old version... "); if (BackupManager.HasBackup(context)) { BackupManager.Restore(context); } var nativePluginFolder = Path.Combine(context.DataPathDst, "Plugins"); bool isFlat = Directory.Exists(nativePluginFolder) && Directory.GetFiles(nativePluginFolder).Any(f => f.EndsWith(".dll")); bool force = !BackupManager.HasBackup(context) || ArgForce; var architecture = DetectArchitecture(context.Executable); Console.ForegroundColor = ConsoleColor.DarkCyan; Console.WriteLine("Installing files... "); CopyAll(new DirectoryInfo(context.DataPathSrc), new DirectoryInfo(context.DataPathDst), force, backup, (from, to) => NativePluginInterceptor(from, to, new DirectoryInfo(nativePluginFolder), isFlat, architecture)); CopyAll(new DirectoryInfo(context.LibsPathSrc), new DirectoryInfo(context.LibsPathDst), force, backup, (from, to) => NativePluginInterceptor(from, to, new DirectoryInfo(nativePluginFolder), isFlat, architecture)); CopyAll(new DirectoryInfo(context.IPARoot), new DirectoryInfo(context.ProjectRoot), force, backup, null, false); //backup.Add(context.AssemblyFile); //backup.Add(context.EngineFile); } #region Create Plugin Folder if (!Directory.Exists(context.PluginsFolder)) { Console.ForegroundColor = ConsoleColor.DarkYellow; Console.WriteLine("Creating plugins folder... "); Directory.CreateDirectory(context.PluginsFolder); Console.ResetColor(); } #endregion #region Virtualizing if (ArgDestructive && File.Exists(context.AssemblyFile)) { var virtualizedModule = VirtualizedModule.Load(context.AssemblyFile); if (!virtualizedModule.IsVirtualized) { Console.ForegroundColor = ConsoleColor.Green; Console.WriteLine("Virtualizing Assembly-Csharp.dll... "); backup.Add(context.AssemblyFile); virtualizedModule.Virtualize(); Console.WriteLine("Done!"); Console.ResetColor(); } } #endregion } catch (Exception e) { Console.ForegroundColor = ConsoleColor.Red; Fail("Oops! This should not have happened.\n\n" + e); } Console.ResetColor(); }
private void ExtractPluginAsync(MemoryStream stream, UpdateStruct item, ApiEndpoint.Mod.PlatformFile fileInfo, string tempDirectory) { Logger.log.Debug($"Extracting ZIP file for {item.plugin.Plugin.Name}"); var data = stream.GetBuffer(); SHA1 sha = new SHA1CryptoServiceProvider(); var hash = sha.ComputeHash(data); if (!LoneFunctions.UnsafeCompare(hash, fileInfo.Hash)) { throw new Exception("The hash for the file doesn't match what is defined"); } var newFiles = new List <FileInfo>(); var backup = new BackupUnit(tempDirectory, $"backup-{item.plugin.ModsaberInfo.InternalName}"); try { bool shouldDeleteOldFile = true; using (var zipFile = ZipFile.Read(stream)) { Logger.log.Debug("Streams opened"); foreach (var entry in zipFile) { if (entry.IsDirectory) { Logger.log.Debug($"Creating directory {entry.FileName}"); Directory.CreateDirectory(Path.Combine(Environment.CurrentDirectory, entry.FileName)); } else { using (var ostream = new MemoryStream((int)entry.UncompressedSize)) { entry.Extract(ostream); ostream.Seek(0, SeekOrigin.Begin); sha = new SHA1CryptoServiceProvider(); var fileHash = sha.ComputeHash(ostream); if (!LoneFunctions.UnsafeCompare(fileHash, fileInfo.FileHashes[entry.FileName])) { throw new Exception("The hash for the file doesn't match what is defined"); } ostream.Seek(0, SeekOrigin.Begin); FileInfo targetFile = new FileInfo(Path.Combine(Environment.CurrentDirectory, entry.FileName)); Directory.CreateDirectory(targetFile.DirectoryName); if (targetFile.FullName == item.plugin.Filename) { shouldDeleteOldFile = false; // overwriting old file, no need to delete } if (targetFile.Exists) { backup.Add(targetFile); } else { newFiles.Add(targetFile); } Logger.log.Debug($"Extracting file {targetFile.FullName}"); var fstream = targetFile.Create(); ostream.CopyTo(fstream); } } } } if (item.plugin.Plugin is SelfPlugin) { // currently updating self Process.Start(new ProcessStartInfo { FileName = item.plugin.Filename, Arguments = $"--waitfor={Process.GetCurrentProcess().Id} --nowait", UseShellExecute = false }); } else if (shouldDeleteOldFile) { File.Delete(item.plugin.Filename); } } catch (Exception) { // something failed; restore foreach (var file in newFiles) { file.Delete(); } backup.Restore(); backup.Delete(); throw; } backup.Delete(); Logger.log.Debug("Downloader exited"); }