Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
118 changes: 0 additions & 118 deletions src/c#/GeneralUpdate.Core/Configuration/ConfiginfoBuilder-Example.cs

This file was deleted.

30 changes: 5 additions & 25 deletions src/c#/GeneralUpdate.Core/Configuration/Environments.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@
using System.IO;
using System.Security.Cryptography;
using System.Text;
using GeneralUpdate.Core.Ipc;

namespace GeneralUpdate.Core.Configuration;

/// <summary>
/// Secure IPC environment variable provider.
/// AES-encrypted temp files in a dedicated subdirectory, auto-deleted after read.
/// Encryption is delegated to <see cref="IpcEncryption"/>.
/// </summary>
public static class Environments
{
// Fixed key/IV derived from a constant — not crypto-grade, but sufficient for
// ephemeral IPC where the file lives < 1 second and is in a per-user directory.
private static readonly byte[] _aesKey = SHA256.Create()
.ComputeHash(Encoding.UTF8.GetBytes("GeneralUpdate.IPC.EnvironmentProvider.v1"));
private static readonly byte[] _aesIV = new byte[16] { 0x47, 0x55, 0x50, 0x44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
Expand All @@ -31,33 +31,13 @@ public static void SetEnvironmentVariable(string key, string value)
{
var filePath = Path.Combine(IpcDir, $"{key}.enc");
var plainBytes = Encoding.UTF8.GetBytes(value);
using var aes = Aes.Create();
aes.Key = _aesKey;
aes.IV = _aesIV;
using var encryptor = aes.CreateEncryptor();
var encrypted = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
File.WriteAllBytes(filePath, encrypted);
IpcEncryption.EncryptToFile(plainBytes, filePath, _aesKey, _aesIV);
}

public static string GetEnvironmentVariable(string key)
{
var filePath = Path.Combine(Path.GetTempPath(), "GeneralUpdate", "ipc", $"{key}.enc");
if (!File.Exists(filePath))
return string.Empty;

try
{
var encrypted = File.ReadAllBytes(filePath);
using var aes = Aes.Create();
aes.Key = _aesKey;
aes.IV = _aesIV;
using var decryptor = aes.CreateDecryptor();
var plainBytes = decryptor.TransformFinalBlock(encrypted, 0, encrypted.Length);
return Encoding.UTF8.GetString(plainBytes);
}
finally
{
try { File.Delete(filePath); } catch { /* best-effort cleanup */ }
}
var plainBytes = IpcEncryption.DecryptFromFile(filePath, _aesKey, _aesIV);
return plainBytes != null ? Encoding.UTF8.GetString(plainBytes) : string.Empty;
}
}
2 changes: 1 addition & 1 deletion src/c#/GeneralUpdate.Core/FileSystem/BlackListDefaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace GeneralUpdate.Core.FileSystem;

/// <summary>Built-in default blacklist items — previously hardcoded in BlackListManager.</summary>
/// <summary>Built-in default blacklist items.</summary>
public static class BlackListDefaults
{
/// <summary>Default blacklisted files (system DLLs that ship with the runtime).</summary>
Expand Down
88 changes: 0 additions & 88 deletions src/c#/GeneralUpdate.Core/FileSystem/BlackListManager.cs

This file was deleted.

11 changes: 11 additions & 0 deletions src/c#/GeneralUpdate.Core/FileSystem/IBlackListMatcher.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System.Collections.Generic;

namespace GeneralUpdate.Core.FileSystem;

/// <summary>Matches files/directories against a blacklist configuration.</summary>
public interface IBlackListMatcher
{
bool IsBlacklisted(string relativeFilePath);
bool IsBlacklistedFormat(string extension);
bool ShouldSkipDirectory(string directoryName);
}
10 changes: 3 additions & 7 deletions src/c#/GeneralUpdate.Core/FileSystem/StorageManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
private long _fileCount = 0;
public const string DirectoryName = "app-";

/// <summary>Optional blacklist matcher. When set, takes precedence over BlackListManager.</summary>
/// <summary>Optional blacklist matcher. Must be set before any file operation.</summary>
public static IBlackListMatcher? BlackListMatcher { get; set; }

private ComparisonResult ComparisonResult { get; set; }
Expand Down Expand Up @@ -255,7 +255,7 @@
/// <summary>
/// Recursively read all files in the folder path.
/// </summary>
private IEnumerable<FileNode> ReadFileNode(string path, string rootPath = null)

Check warning on line 258 in src/c#/GeneralUpdate.Core/FileSystem/StorageManager.cs

View workflow job for this annotation

GitHub Actions / build-and-test (ubuntu-latest)

Cannot convert null literal to non-nullable reference type.

Check warning on line 258 in src/c#/GeneralUpdate.Core/FileSystem/StorageManager.cs

View workflow job for this annotation

GitHub Actions / aot-verify

Cannot convert null literal to non-nullable reference type.
{
var resultFiles = new List<FileNode>();
rootPath ??= path;
Expand All @@ -267,9 +267,7 @@

foreach (var subPath in Directory.EnumerateFiles(path))
{
#pragma warning disable CS0618 // Obsolete fallback
if ((BlackListMatcher ?? BlackListManager.Instance).IsBlacklisted(subPath)) continue;
#pragma warning restore CS0618
if (BlackListMatcher != null && BlackListMatcher.IsBlacklisted(subPath)) continue;

var hashAlgorithm = new Sha256HashAlgorithm();
var hash = hashAlgorithm.ComputeHash(subPath);
Expand All @@ -288,9 +286,7 @@

foreach (var subPath in Directory.EnumerateDirectories(path))
{
#pragma warning disable CS0618 // Obsolete fallback
if ((BlackListMatcher ?? BlackListManager.Instance).ShouldSkipDirectory(subPath)) continue;
#pragma warning restore CS0618
if (BlackListMatcher != null && BlackListMatcher.ShouldSkipDirectory(subPath)) continue;
resultFiles.AddRange(ReadFileNode(subPath, rootPath));
}

Expand Down
3 changes: 2 additions & 1 deletion src/c#/GeneralUpdate.Core/GeneralUpdate.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<Nullable>enable</Nullable>
<Title>GeneralUpdate.Core</Title>
<Authors>JusterZhu</Authors>
<Description>GeneralUpdate unified core client and upgrade bootstrap, download, pipeline, strategies, utilities.</Description>
<Description>GeneralUpdate unified core �?client and upgrade bootstrap, download, pipeline, strategies, utilities.</Description>
<Copyright>Copyright 2020-2026 JusterZhu</Copyright>
<PackageProjectUrl>https://github.com/GeneralLibrary/GeneralUpdate</PackageProjectUrl>
<RepositoryUrl>https://github.com/GeneralLibrary/GeneralUpdate</RepositoryUrl>
Expand All @@ -30,6 +30,7 @@
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="8.0.0" />
</ItemGroup>

<!-- net10.0: IHttpClientFactory built-in; add Http package for ServiceCollection -->
<ItemGroup Condition="'$(TargetFramework)' == 'net10.0'">
<PackageReference Include="Microsoft.AspNetCore.SignalR.Client" Version="10.0.1" />
</ItemGroup>
Expand Down
23 changes: 6 additions & 17 deletions src/c#/GeneralUpdate.Core/Ipc/IProcessInfoProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ public interface IProcessInfoProvider
/// <summary>
/// AES-encrypted temporary file IPC — simplest, most reliable cross-platform approach.
/// File lives in %TEMP%/GeneralUpdate/ipc/ with a random name, auto-deleted after read.
/// Encryption is delegated to <see cref="IpcEncryption"/>.
/// </summary>
public class EncryptedFileProcessInfoProvider : IProcessInfoProvider
{
Expand Down Expand Up @@ -47,11 +48,7 @@ public void Send(ProcessInfo info)
{
var json = JsonSerializer.Serialize(info, ProcessInfoJsonContext.Default.ProcessInfo);
var plainBytes = Encoding.UTF8.GetBytes(json);
using var aes = Aes.Create();
aes.Key = Key; aes.IV = IV;
using var enc = aes.CreateEncryptor();
var cipher = enc.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
File.WriteAllBytes(_filePath, cipher);
IpcEncryption.EncryptToFile(plainBytes, _filePath, Key, IV);
}

public Task<ProcessInfo?> ReceiveAsync(CancellationToken token = default)
Expand All @@ -60,17 +57,9 @@ public void Send(ProcessInfo info)
/// <summary>Synchronous receive — reads and deletes the encrypted file.</summary>
public ProcessInfo? Receive()
{
if (!File.Exists(_filePath)) return null;
try
{
var cipher = File.ReadAllBytes(_filePath);
using var aes = Aes.Create();
aes.Key = Key; aes.IV = IV;
using var dec = aes.CreateDecryptor();
var plain = dec.TransformFinalBlock(cipher, 0, cipher.Length);
var json = Encoding.UTF8.GetString(plain);
return JsonSerializer.Deserialize(json, ProcessInfoJsonContext.Default.ProcessInfo);
}
finally { try { File.Delete(_filePath); } catch { } }
var plain = IpcEncryption.DecryptFromFile(_filePath, Key, IV);
if (plain == null) return null;
var json = Encoding.UTF8.GetString(plain);
return JsonSerializer.Deserialize(json, ProcessInfoJsonContext.Default.ProcessInfo);
}
}
Loading
Loading