コード例 #1
0
        private void ExtractPluginAsync(MemoryStream stream, DependencyObject item, ApiEndpoint.Mod.PlatformFile fileInfo)
        { // (3.3)
            Logger.updater.Debug($"Extracting ZIP file for {item.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 targetDir = Path.Combine(BeatSaber.InstallPath, "IPA", Path.GetRandomFileName() + "_Pending");

            Directory.CreateDirectory(targetDir);

            var eventualOutput = Path.Combine(BeatSaber.InstallPath, "IPA", "Pending");

            if (!Directory.Exists(eventualOutput))
            {
                Directory.CreateDirectory(eventualOutput);
            }

            try
            {
                bool shouldDeleteOldFile = !(item.LocalPluginMeta?.Plugin is SelfPlugin);

                using (var zipFile = ZipFile.Read(stream))
                {
                    Logger.updater.Debug("Streams opened");
                    foreach (var entry in zipFile)
                    {
                        if (entry.IsDirectory)
                        {
                            Logger.updater.Debug($"Creating directory {entry.FileName}");
                            Directory.CreateDirectory(Path.Combine(targetDir, 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);

                                try
                                {
                                    if (!LoneFunctions.UnsafeCompare(fileHash, fileInfo.FileHashes[entry.FileName]))
                                    {
                                        throw new Exception("The hash for the file doesn't match what is defined");
                                    }
                                }
                                catch (KeyNotFoundException)
                                {
                                    throw new ModsaberInterceptException("ModSaber did not send the hashes for the zip's content!");
                                }

                                ostream.Seek(0, SeekOrigin.Begin);
                                FileInfo targetFile = new FileInfo(Path.Combine(targetDir, entry.FileName));
                                Directory.CreateDirectory(targetFile.DirectoryName ?? throw new InvalidOperationException());

                                if (LoneFunctions.GetRelativePath(targetFile.FullName, targetDir) == LoneFunctions.GetRelativePath(item.LocalPluginMeta?.Filename, BeatSaber.InstallPath))
                                {
                                    shouldDeleteOldFile = false; // overwriting old file, no need to delete
                                }

                                /*if (targetFile.Exists)
                                 *  backup.Add(targetFile);
                                 * else
                                 *  newFiles.Add(targetFile);*/

                                Logger.updater.Debug($"Extracting file {targetFile.FullName}");

                                targetFile.Delete();
                                using (var fstream = targetFile.Create())
                                    ostream.CopyTo(fstream);
                            }
                        }
                    }
                }

                if (shouldDeleteOldFile && item.LocalPluginMeta != null)
                {
                    File.AppendAllLines(Path.Combine(targetDir, SpecialDeletionsFile), new[] { LoneFunctions.GetRelativePath(item.LocalPluginMeta.Filename, BeatSaber.InstallPath) });
                }
            }
            catch (Exception)
            {                                      // something failed; restore
                /*foreach (var file in newFiles)
                 *  file.Delete();
                 * backup.Restore();
                 * backup.Delete();*/
                Directory.Delete(targetDir, true); // delete extraction site

                throw;
            }

            if (item.LocalPluginMeta?.Plugin is SelfPlugin)
            { // currently updating self, so copy to working dir and update
                LoneFunctions.CopyAll(new DirectoryInfo(targetDir), new DirectoryInfo(BeatSaber.InstallPath));
                if (File.Exists(Path.Combine(BeatSaber.InstallPath, SpecialDeletionsFile)))
                {
                    File.Delete(Path.Combine(BeatSaber.InstallPath, SpecialDeletionsFile));
                }
                Process.Start(new ProcessStartInfo
                {
                    FileName        = item.LocalPluginMeta.Filename,
                    Arguments       = $"-nw={Process.GetCurrentProcess().Id}",
                    UseShellExecute = false
                });
            }
            else
            {
                LoneFunctions.CopyAll(new DirectoryInfo(targetDir), new DirectoryInfo(eventualOutput), SpecialDeletionsFile);
            }
            Directory.Delete(targetDir, true); // delete extraction site

            Logger.updater.Debug("Extractor exited");
        }
コード例 #2
0
        public static void InstallPendingUpdates()
        {
            var pendingDir = Path.Combine(BeatSaber.InstallPath, "IPA", "Pending");

            if (!Directory.Exists(pendingDir))
            {
                return;
            }

            // there are pending updates, install
            updater.Info("Installing pending updates");

            var toDelete = new string[0];
            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(BeatSaber.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
            if (Directory.Exists(Path.Combine(pendingDir, "IPA")))
            {
                Directory.Delete(Path.Combine(pendingDir, "IPA"), true);
            }
            if (File.Exists(Path.Combine(pendingDir, "IPA.exe")))
            {
                File.Delete(Path.Combine(pendingDir, "IPA.exe"));
                if (File.Exists(Path.Combine(pendingDir, "Mono.Cecil.dll")))
                {
                    File.Delete(Path.Combine(pendingDir, "Mono.Cecil.dll"));
                }
            }

            #endregion

            try
            {
                LoneFunctions.CopyAll(new DirectoryInfo(pendingDir), new DirectoryInfo(BeatSaber.InstallPath));
            }
            catch (Exception e)
            {
                updater.Error("While trying to install pending updates: Error copying files in");
                updater.Error(e);
            }

            Directory.Delete(pendingDir, true);
        }