mirror of
https://github.com/alexhopeoconnor/dnsmasq-webui.git
synced 2026-10-03 22:12:00 +10:00
- OptionSemantics: metadata only (no validator delegates); OptionValidationKind + PathPolicy - IOptionSemanticHandler: handler-first validation; handlers registered via IApplicationMultiSingleton - OptionSemanticValidator: single engine, handler dispatch then generic kind-based validation - Shared syntax: DnsmasqScopedDomainSyntax, DnsmasqDhcpRangeValueParser, DnsmasqDhcpOptionSyntax, DnsmasqRelaySyntax, DnsmasqDhcpTagSyntax, DnsmasqIpPrefixSyntax for reuse across handlers - New handlers: Server, Local, RevServer, Address, Alias, Ipset, Nftset, DhcpRange, DhcpHost, DhcpOption, DhcpRelay, DhcpProxy, IgnoreAddress, ConnmarkAllowlist, DhcpMatch, DhcpMac, PxeService, TrustAnchor, RebindDomainOk, BogusNxdomain, DhcpIgnoreNames, DhcpBoot, Slaac, BridgeInterface, SharedNetwork, DhcpOptionPxe, DhcpNameMatch, DhcpIgnore, DhcpVendorclass, DhcpUserclass, TagIf - Registry and pre-save validation use engine only; placeholders via DnsmasqOptionPlaceholders - DnsmasqConfigSetService uses DnsmasqDhcpRangeValueParser; DhcpRangeValueParserTests added
38 lines
1.4 KiB
C#
38 lines
1.4 KiB
C#
using DnsmasqWebUI.Infrastructure.Helpers.Config;
|
|
|
|
namespace DnsmasqWebUI.Infrastructure.Services.EffectiveConfig.Validation;
|
|
|
|
/// <summary>
|
|
/// Specialized semantic behavior for <c>ipset</c> values.
|
|
/// Validates scoped domain syntax followed by one or more ipset names.
|
|
/// </summary>
|
|
public sealed class IpsetSemanticHandler : IOptionSemanticHandler
|
|
{
|
|
public bool CanHandle(string optionName) =>
|
|
optionName == DnsmasqConfKeys.Ipset;
|
|
|
|
public string? ValidateSingle(object? value) => null;
|
|
|
|
public string? ValidateMultiItem(string? value)
|
|
{
|
|
var s = value?.Trim() ?? "";
|
|
if (s.Length == 0)
|
|
return "Value cannot be empty.";
|
|
|
|
if (!DnsmasqScopedDomainSyntax.TrySplitScopedValue(s, out var domains, out var setList, out var error))
|
|
return error == "Value must start with '/'."
|
|
? "ipset must start with '/'."
|
|
: "ipset must use /domain[/domain...]/set[,set...] syntax.";
|
|
|
|
error = DnsmasqScopedDomainSyntax.ValidateDomainPatterns(domains);
|
|
if (error is not null)
|
|
return error.Replace("Value", "ipset", StringComparison.Ordinal);
|
|
|
|
var sets = setList.Split(',').Select(t => t.Trim()).ToArray();
|
|
if (sets.Length == 0 || sets.Any(string.IsNullOrWhiteSpace))
|
|
return "ipset must include at least one non-empty set name.";
|
|
|
|
return null;
|
|
}
|
|
}
|