UP
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace StellaOps.Feedser.Source.Distro.Debian.Internal;
|
||||
|
||||
internal static class DebianListParser
|
||||
{
|
||||
private static readonly Regex HeaderRegex = new("^\\[(?<date>[^\\]]+)\\]\\s+(?<id>DSA-\\d{4,}-\\d+)\\s+(?<title>.+)$", RegexOptions.Compiled);
|
||||
private static readonly Regex CveRegex = new("CVE-\\d{4}-\\d{3,7}", RegexOptions.IgnoreCase | RegexOptions.Compiled);
|
||||
|
||||
public static IReadOnlyList<DebianListEntry> Parse(string? content)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(content))
|
||||
{
|
||||
return Array.Empty<DebianListEntry>();
|
||||
}
|
||||
|
||||
var entries = new List<DebianListEntry>();
|
||||
var currentCves = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
|
||||
DateTimeOffset currentDate = default;
|
||||
string? currentId = null;
|
||||
string? currentTitle = null;
|
||||
string? currentPackage = null;
|
||||
|
||||
foreach (var rawLine in content.Split('\n'))
|
||||
{
|
||||
var line = rawLine.TrimEnd('\r');
|
||||
if (string.IsNullOrWhiteSpace(line))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line[0] == '[')
|
||||
{
|
||||
if (currentId is not null && currentTitle is not null && currentPackage is not null)
|
||||
{
|
||||
entries.Add(new DebianListEntry(
|
||||
currentId,
|
||||
currentDate,
|
||||
currentTitle,
|
||||
currentPackage,
|
||||
currentCves.Count == 0 ? Array.Empty<string>() : new List<string>(currentCves)));
|
||||
}
|
||||
|
||||
currentCves.Clear();
|
||||
currentId = null;
|
||||
currentTitle = null;
|
||||
currentPackage = null;
|
||||
|
||||
var match = HeaderRegex.Match(line);
|
||||
if (!match.Success)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!DateTimeOffset.TryParseExact(
|
||||
match.Groups["date"].Value,
|
||||
new[] { "dd MMM yyyy", "d MMM yyyy" },
|
||||
CultureInfo.InvariantCulture,
|
||||
DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal,
|
||||
out currentDate))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
currentId = match.Groups["id"].Value.Trim();
|
||||
currentTitle = match.Groups["title"].Value.Trim();
|
||||
|
||||
var separatorIndex = currentTitle.IndexOf(" - ", StringComparison.Ordinal);
|
||||
currentPackage = separatorIndex > 0
|
||||
? currentTitle[..separatorIndex].Trim()
|
||||
: currentTitle.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries).FirstOrDefault();
|
||||
if (string.IsNullOrWhiteSpace(currentPackage))
|
||||
{
|
||||
currentPackage = currentId;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line[0] == '{')
|
||||
{
|
||||
foreach (Match match in CveRegex.Matches(line))
|
||||
{
|
||||
if (match.Success && !string.IsNullOrWhiteSpace(match.Value))
|
||||
{
|
||||
currentCves.Add(match.Value.ToUpperInvariant());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (currentId is not null && currentTitle is not null && currentPackage is not null)
|
||||
{
|
||||
entries.Add(new DebianListEntry(
|
||||
currentId,
|
||||
currentDate,
|
||||
currentTitle,
|
||||
currentPackage,
|
||||
currentCves.Count == 0 ? Array.Empty<string>() : new List<string>(currentCves)));
|
||||
}
|
||||
|
||||
return entries;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user