Files
git.stella-ops.org/src/StellaOps.Feedser.Source.Ru.Bdu/Internal/RuBduXmlParser.cs
master 0f1b203fde
Some checks failed
Build Test Deploy / build-test (push) Has been cancelled
Build Test Deploy / authority-container (push) Has been cancelled
Build Test Deploy / docs (push) Has been cancelled
Build Test Deploy / deploy (push) Has been cancelled
tam
2025-10-12 20:42:07 +00:00

197 lines
6.4 KiB
C#

using System.Collections.Immutable;
using System.Linq;
using System.Globalization;
using System.Xml.Linq;
namespace StellaOps.Feedser.Source.Ru.Bdu.Internal;
internal static class RuBduXmlParser
{
public static RuBduVulnerabilityDto? TryParse(XElement element)
{
ArgumentNullException.ThrowIfNull(element);
var identifier = element.Element("identifier")?.Value?.Trim();
if (string.IsNullOrWhiteSpace(identifier))
{
return null;
}
var name = Normalize(element.Element("name")?.Value);
var description = Normalize(element.Element("description")?.Value);
var solution = Normalize(element.Element("solution")?.Value);
var severity = Normalize(element.Element("severity")?.Value);
var exploitStatus = Normalize(element.Element("exploit_status")?.Value);
var fixStatus = Normalize(element.Element("fix_status")?.Value);
var vulStatus = Normalize(element.Element("vul_status")?.Value);
var vulClass = Normalize(element.Element("vul_class")?.Value);
var vulState = Normalize(element.Element("vul_state")?.Value);
var other = Normalize(element.Element("other")?.Value);
var incidentCount = ParseInt(element.Element("vul_incident")?.Value);
var identifyDate = ParseDate(element.Element("identify_date")?.Value);
var cvssVectorElement = element.Element("cvss")?.Element("vector");
var cvssVector = Normalize(cvssVectorElement?.Value);
var cvssScore = ParseDouble(cvssVectorElement?.Attribute("score")?.Value);
var cvss3VectorElement = element.Element("cvss3")?.Element("vector");
var cvss3Vector = Normalize(cvss3VectorElement?.Value);
var cvss3Score = ParseDouble(cvss3VectorElement?.Attribute("score")?.Value);
var software = ParseSoftware(element.Element("vulnerable_software"));
var environment = ParseEnvironment(element.Element("environment"));
var cwes = ParseCwes(element.Element("cwes"));
return new RuBduVulnerabilityDto(
identifier.Trim(),
name,
description,
solution,
identifyDate,
severity,
cvssVector,
cvssScore,
cvss3Vector,
cvss3Score,
exploitStatus,
incidentCount,
fixStatus,
vulStatus,
vulClass,
vulState,
other,
software,
environment,
cwes);
}
private static ImmutableArray<RuBduSoftwareDto> ParseSoftware(XElement? root)
{
if (root is null)
{
return ImmutableArray<RuBduSoftwareDto>.Empty;
}
var builder = ImmutableArray.CreateBuilder<RuBduSoftwareDto>();
foreach (var soft in root.Elements("soft"))
{
var vendor = Normalize(soft.Element("vendor")?.Value);
var name = Normalize(soft.Element("name")?.Value);
var version = Normalize(soft.Element("version")?.Value);
var platform = Normalize(soft.Element("platform")?.Value);
var types = soft.Element("types") is { } typesElement
? typesElement.Elements("type").Select(static x => Normalize(x.Value)).Where(static value => !string.IsNullOrWhiteSpace(value)).Cast<string>().ToImmutableArray()
: ImmutableArray<string>.Empty;
builder.Add(new RuBduSoftwareDto(vendor, name, version, platform, types));
}
return builder.ToImmutable();
}
private static ImmutableArray<RuBduEnvironmentDto> ParseEnvironment(XElement? root)
{
if (root is null)
{
return ImmutableArray<RuBduEnvironmentDto>.Empty;
}
var builder = ImmutableArray.CreateBuilder<RuBduEnvironmentDto>();
foreach (var os in root.Elements())
{
var vendor = Normalize(os.Element("vendor")?.Value);
var name = Normalize(os.Element("name")?.Value);
var version = Normalize(os.Element("version")?.Value);
var platform = Normalize(os.Element("platform")?.Value);
builder.Add(new RuBduEnvironmentDto(vendor, name, version, platform));
}
return builder.ToImmutable();
}
private static ImmutableArray<RuBduCweDto> ParseCwes(XElement? root)
{
if (root is null)
{
return ImmutableArray<RuBduCweDto>.Empty;
}
var builder = ImmutableArray.CreateBuilder<RuBduCweDto>();
foreach (var cwe in root.Elements("cwe"))
{
var identifier = Normalize(cwe.Element("identifier")?.Value);
if (string.IsNullOrWhiteSpace(identifier))
{
continue;
}
var name = Normalize(cwe.Element("name")?.Value);
builder.Add(new RuBduCweDto(identifier, name));
}
return builder.ToImmutable();
}
private static DateTimeOffset? ParseDate(string? value)
{
if (string.IsNullOrWhiteSpace(value))
{
return null;
}
var trimmed = value.Trim();
if (DateTimeOffset.TryParse(trimmed, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal, out var isoDate))
{
return isoDate;
}
if (DateTimeOffset.TryParseExact(trimmed, new[] { "dd.MM.yyyy", "dd.MM.yyyy HH:mm:ss" }, CultureInfo.GetCultureInfo("ru-RU"), DateTimeStyles.AssumeUniversal, out var ruDate))
{
return ruDate;
}
return null;
}
private static double? ParseDouble(string? value)
{
if (string.IsNullOrWhiteSpace(value))
{
return null;
}
if (double.TryParse(value.Trim(), NumberStyles.Any, CultureInfo.InvariantCulture, out var parsed))
{
return parsed;
}
return null;
}
private static int? ParseInt(string? value)
{
if (string.IsNullOrWhiteSpace(value))
{
return null;
}
if (int.TryParse(value.Trim(), NumberStyles.Integer, CultureInfo.InvariantCulture, out var parsed))
{
return parsed;
}
return null;
}
private static string? Normalize(string? value)
{
if (string.IsNullOrWhiteSpace(value))
{
return null;
}
return value.Replace('\r', ' ').Replace('\n', ' ').Trim();
}
}