// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.IO.Compression; using System.Text.Json; #nullable disable namespace HordeServer.Utilities { static class AgentUtilities { /// /// Reads the version number from an archive /// /// The archive data /// public static string ReadVersion(byte[] data) { MemoryStream inputStream = new MemoryStream(data); using (ZipArchive inputArchive = new ZipArchive(inputStream, ZipArchiveMode.Read, true)) { foreach (ZipArchiveEntry inputEntry in inputArchive.Entries) { if (inputEntry.FullName.Equals("HordeAgent.dll", StringComparison.OrdinalIgnoreCase)) { string tempFile = Path.GetTempFileName(); try { inputEntry.ExtractToFile(tempFile, true); return FileVersionInfo.GetVersionInfo(tempFile).ProductVersion; } finally { File.Delete(tempFile); } } } } throw new Exception("Unable to find HordeAgent.dll in archive"); } /// /// Updates the agent app settings within the archive data /// /// Data for the zip archive /// The settings to update /// New agent app data public static byte[] UpdateAppSettings(byte[] data, Dictionary settings) { bool writtenClientId = false; MemoryStream outputStream = new MemoryStream(); using (ZipArchive outputArchive = new ZipArchive(outputStream, ZipArchiveMode.Create, true)) { MemoryStream inputStream = new MemoryStream(data); using (ZipArchive inputArchive = new ZipArchive(inputStream, ZipArchiveMode.Read, true)) { foreach (ZipArchiveEntry inputEntry in inputArchive.Entries) { ZipArchiveEntry outputEntry = outputArchive.CreateEntry(inputEntry.FullName); using System.IO.Stream inputEntryStream = inputEntry.Open(); using System.IO.Stream outputEntryStream = outputEntry.Open(); if (inputEntry.FullName.Equals("appsettings.json", StringComparison.OrdinalIgnoreCase)) { using MemoryStream memoryStream = new MemoryStream(); inputEntryStream.CopyTo(memoryStream); Dictionary> document = JsonSerializer.Deserialize>>(memoryStream.ToArray()); foreach (KeyValuePair pair in settings) { document["Horde"][pair.Key] = pair.Value; } using Utf8JsonWriter writer = new Utf8JsonWriter(outputEntryStream, new JsonWriterOptions { Indented = true }); JsonSerializer.Serialize>>(writer, document, new JsonSerializerOptions { WriteIndented = true }); writtenClientId = true; } else { inputEntryStream.CopyTo(outputEntryStream); } } } } if (!writtenClientId) { throw new InvalidDataException("Missing appsettings.json file from zip archive"); } return outputStream.ToArray(); } } }