// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.IO; using System.Linq; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text.Json; using System.Text.Json.Nodes; using EpicGames.Core; using EpicGames.Horde.Storage.Bundles; using Microsoft.Win32; namespace EpicGames.Horde { using JsonObject = System.Text.Json.Nodes.JsonObject; /// /// Options for configuring the Horde connection /// public class HordeOptions { /// /// Address of the Horde server /// public Uri? ServerUrl { get; set; } /// /// Access token to use for connecting to the server /// public string? AccessToken { get; set; } /// /// Whether to allow opening a browser window to prompt for authentication /// public bool AllowAuthPrompt { get; set; } = true; /// /// Options for creating new bundles /// public BundleOptions Bundle { get; } = new BundleOptions(); /// /// Options for caching bundles /// public BundleCacheOptions BundleCache { get; } = new BundleCacheOptions(); /// /// Options for the storage backend cache /// public StorageBackendCacheOptions BackendCache { get; } = new StorageBackendCacheOptions(); /// /// Gets the configured server URL, or the default value /// public Uri? GetServerUrlOrDefault() => ServerUrl ?? GetServerUrlFromEnvironment() ?? GetDefaultServerUrl(); /// /// Reads the server URL from the environment /// public static Uri? GetServerUrlFromEnvironment() { string? hordeUrlEnvVar = Environment.GetEnvironmentVariable(HordeHttpClient.HordeUrlEnvVarName); if (String.IsNullOrEmpty(hordeUrlEnvVar)) { return null; } return new Uri(hordeUrlEnvVar); } /// /// Gets the default server URL for the current user /// /// Default URL public static Uri? GetDefaultServerUrl() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { string? url = (Registry.GetValue(@"HKEY_CURRENT_USER\SOFTWARE\Epic Games\Horde", "Url", null) as string) ?? (Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Epic Games\Horde", "Url", null) as string); if (!String.IsNullOrEmpty(url)) { try { return new Uri(url); } catch (UriFormatException) { } } } else { FileReference? configFile = GetConfigFile(); if (configFile != null && FileReference.Exists(configFile)) { byte[] data = FileReference.ReadAllBytes(configFile); JsonObject? root = JsonNode.Parse(data, new JsonNodeOptions { PropertyNameCaseInsensitive = true }, new JsonDocumentOptions { AllowTrailingCommas = true }) as JsonObject; root ??= new JsonObject(); JsonNode? value; if (root.TryGetPropertyValue("server", out value)) { string? stringValue = (string?)value; if (stringValue != null) { try { return new Uri(stringValue); } catch (UriFormatException) { } } } } } return null; } /// /// Sets the default server url for the current user /// /// Horde server URL to use public static void SetDefaultServerUrl(Uri serverUrl) { if (!serverUrl.OriginalString.EndsWith("/", StringComparison.Ordinal)) { serverUrl = new Uri(serverUrl.OriginalString + "/"); } if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { string? newServerUrl = serverUrl.ToString(); string? defaultServerUrl = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Epic Games\Horde", "Url", null) as string; if (String.Equals(newServerUrl, defaultServerUrl, StringComparison.Ordinal)) { using RegistryKey key = Registry.CurrentUser.CreateSubKey("SOFTWARE\\Epic Games\\Horde"); DeleteRegistryKey(key, "Url"); } else { Registry.SetValue(@"HKEY_CURRENT_USER\SOFTWARE\Epic Games\Horde", "Url", serverUrl.ToString()); } } else { FileReference? configFile = GetConfigFile(); if (configFile != null) { JsonObject? root = null; if (FileReference.Exists(configFile)) { byte[] data = FileReference.ReadAllBytes(configFile); root = JsonNode.Parse(data, new JsonNodeOptions { PropertyNameCaseInsensitive = true }, new JsonDocumentOptions { AllowTrailingCommas = true }) as JsonObject; } root ??= new JsonObject(); root["server"] = serverUrl.ToString(); using (FileStream stream = FileReference.Open(configFile, FileMode.Create, FileAccess.ReadWrite, FileShare.Read)) { using Utf8JsonWriter writer = new Utf8JsonWriter(stream, new JsonWriterOptions { Indented = true }); root.WriteTo(writer); } } } } static FileReference? GetConfigFile() { DirectoryReference? userFolder = DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.UserProfile); userFolder ??= DirectoryReference.GetSpecialFolder(Environment.SpecialFolder.LocalApplicationData); userFolder ??= DirectoryReference.GetCurrentDirectory(); return FileReference.Combine(userFolder, ".horde.json"); } [SupportedOSPlatform("windows")] static void DeleteRegistryKey(RegistryKey key, string name) { string[] valueNames = key.GetValueNames(); if (valueNames.Any(x => String.Equals(x, name, StringComparison.OrdinalIgnoreCase))) { try { key.DeleteValue(name); } catch { } } } } /// /// Options for the storage backend cache /// public class StorageBackendCacheOptions { /// /// Directory to store cached data /// public string? CacheDir { get; set; } /// /// Maximum size of the cache, in bytes /// public long MaxSize { get; set; } } }