Rename Feedser to Concelier

This commit is contained in:
2025-10-18 20:04:15 +03:00
parent 7e1b10d3b2
commit 0137856fdb
1208 changed files with 4370 additions and 4370 deletions

View File

@@ -0,0 +1,166 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Text.RegularExpressions;
namespace StellaOps.Concelier.Models;
public static class AliasSchemeRegistry
{
private sealed record AliasScheme(
string Name,
Func<string?, bool> Predicate,
Func<string?, string> Normalizer);
private static readonly AliasScheme[] SchemeDefinitions =
{
BuildScheme(AliasSchemes.Cve, alias => alias is not null && Matches(CvERegex, alias), alias => alias is null ? string.Empty : NormalizePrefix(alias, "CVE")),
BuildScheme(AliasSchemes.Ghsa, alias => alias is not null && Matches(GhsaRegex, alias), alias => alias is null ? string.Empty : NormalizePrefix(alias, "GHSA")),
BuildScheme(AliasSchemes.OsV, alias => alias is not null && Matches(OsVRegex, alias), alias => alias is null ? string.Empty : NormalizePrefix(alias, "OSV")),
BuildScheme(AliasSchemes.Jvn, alias => alias is not null && Matches(JvnRegex, alias), alias => alias is null ? string.Empty : NormalizePrefix(alias, "JVN")),
BuildScheme(AliasSchemes.Jvndb, alias => alias is not null && Matches(JvndbRegex, alias), alias => alias is null ? string.Empty : NormalizePrefix(alias, "JVNDB")),
BuildScheme(AliasSchemes.Bdu, alias => alias is not null && Matches(BduRegex, alias), alias => alias is null ? string.Empty : NormalizePrefix(alias, "BDU")),
BuildScheme(AliasSchemes.Vu, alias => alias is not null && alias.StartsWith("VU#", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "VU", preserveSeparator: '#')),
BuildScheme(AliasSchemes.Msrc, alias => alias is not null && alias.StartsWith("MSRC-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "MSRC")),
BuildScheme(AliasSchemes.CiscoSa, alias => alias is not null && alias.StartsWith("CISCO-SA-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "CISCO-SA")),
BuildScheme(AliasSchemes.OracleCpu, alias => alias is not null && alias.StartsWith("ORACLE-CPU", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "ORACLE-CPU")),
BuildScheme(AliasSchemes.Apsb, alias => alias is not null && alias.StartsWith("APSB-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "APSB")),
BuildScheme(AliasSchemes.Apa, alias => alias is not null && alias.StartsWith("APA-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "APA")),
BuildScheme(AliasSchemes.AppleHt, alias => alias is not null && alias.StartsWith("APPLE-HT", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "APPLE-HT")),
BuildScheme(AliasSchemes.ChromiumPost, alias => alias is not null && (alias.StartsWith("CHROMIUM-POST", StringComparison.OrdinalIgnoreCase) || alias.StartsWith("CHROMIUM:", StringComparison.OrdinalIgnoreCase)), NormalizeChromium),
BuildScheme(AliasSchemes.Vmsa, alias => alias is not null && alias.StartsWith("VMSA-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "VMSA")),
BuildScheme(AliasSchemes.Rhsa, alias => alias is not null && alias.StartsWith("RHSA-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "RHSA")),
BuildScheme(AliasSchemes.Usn, alias => alias is not null && alias.StartsWith("USN-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "USN")),
BuildScheme(AliasSchemes.Dsa, alias => alias is not null && alias.StartsWith("DSA-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "DSA")),
BuildScheme(AliasSchemes.SuseSu, alias => alias is not null && alias.StartsWith("SUSE-SU-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "SUSE-SU")),
BuildScheme(AliasSchemes.Icsa, alias => alias is not null && alias.StartsWith("ICSA-", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "ICSA")),
BuildScheme(AliasSchemes.Cwe, alias => alias is not null && Matches(CweRegex, alias), alias => alias is null ? string.Empty : NormalizePrefix(alias, "CWE")),
BuildScheme(AliasSchemes.Cpe, alias => alias is not null && alias.StartsWith("cpe:", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "cpe", uppercase:false)),
BuildScheme(AliasSchemes.Purl, alias => alias is not null && alias.StartsWith("pkg:", StringComparison.OrdinalIgnoreCase), alias => NormalizePrefix(alias, "pkg", uppercase:false)),
};
private static AliasScheme BuildScheme(string name, Func<string?, bool> predicate, Func<string?, string> normalizer)
=> new(
name,
predicate,
alias => normalizer(alias));
private static readonly ImmutableHashSet<string> SchemeNames = SchemeDefinitions
.Select(static scheme => scheme.Name)
.ToImmutableHashSet(StringComparer.OrdinalIgnoreCase);
private static readonly Regex CvERegex = new("^CVE-\\d{4}-\\d{4,}$", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
private static readonly Regex GhsaRegex = new("^GHSA-[0-9a-z]{4}-[0-9a-z]{4}-[0-9a-z]{4}$", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
private static readonly Regex OsVRegex = new("^OSV-\\d{4}-\\d+$", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
private static readonly Regex JvnRegex = new("^JVN-\\d{4}-\\d{6}$", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
private static readonly Regex JvndbRegex = new("^JVNDB-\\d{4}-\\d{6}$", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
private static readonly Regex BduRegex = new("^BDU-\\d{4}-\\d+$", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
private static readonly Regex CweRegex = new("^CWE-\\d+$", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
public static IReadOnlyCollection<string> KnownSchemes => SchemeNames;
public static bool IsKnownScheme(string? scheme)
=> !string.IsNullOrWhiteSpace(scheme) && SchemeNames.Contains(scheme);
public static bool TryGetScheme(string? alias, out string scheme)
{
if (string.IsNullOrWhiteSpace(alias))
{
scheme = string.Empty;
return false;
}
var candidate = alias.Trim();
foreach (var entry in SchemeDefinitions)
{
if (entry.Predicate(candidate))
{
scheme = entry.Name;
return true;
}
}
scheme = string.Empty;
return false;
}
public static bool TryNormalize(string? alias, out string normalized, out string scheme)
{
normalized = string.Empty;
scheme = string.Empty;
if (string.IsNullOrWhiteSpace(alias))
{
return false;
}
var candidate = alias.Trim();
foreach (var entry in SchemeDefinitions)
{
if (entry.Predicate(candidate))
{
scheme = entry.Name;
normalized = entry.Normalizer(candidate);
return true;
}
}
normalized = candidate;
return false;
}
private static string NormalizePrefix(string? alias, string prefix, bool uppercase = true, char? preserveSeparator = null)
{
if (string.IsNullOrWhiteSpace(alias))
{
return string.Empty;
}
var comparison = StringComparison.OrdinalIgnoreCase;
if (!alias.StartsWith(prefix, comparison))
{
return uppercase ? alias : alias.ToLowerInvariant();
}
var remainder = alias[prefix.Length..];
if (preserveSeparator is { } separator && remainder.Length > 0 && remainder[0] != separator)
{
// Edge case: alias is expected to use a specific separator but does not return unchanged.
return uppercase ? prefix.ToUpperInvariant() + remainder : prefix + remainder;
}
var normalizedPrefix = uppercase ? prefix.ToUpperInvariant() : prefix.ToLowerInvariant();
return normalizedPrefix + remainder;
}
private static string NormalizeChromium(string? alias)
{
if (string.IsNullOrWhiteSpace(alias))
{
return string.Empty;
}
if (alias.StartsWith("CHROMIUM-POST", StringComparison.OrdinalIgnoreCase))
{
return NormalizePrefix(alias, "CHROMIUM-POST");
}
if (alias.StartsWith("CHROMIUM:", StringComparison.OrdinalIgnoreCase))
{
var remainder = alias["CHROMIUM".Length..];
return "CHROMIUM" + remainder;
}
return alias;
}
private static bool Matches(Regex? regex, string? candidate)
{
if (regex is null || string.IsNullOrWhiteSpace(candidate))
{
return false;
}
return regex.IsMatch(candidate);
}
}