Skip to content

Commit 1cdd57d

Browse files
committed
Feature: HostsFileEditor add/edit
1 parent 903b444 commit 1cdd57d

File tree

12 files changed

+454
-49
lines changed

12 files changed

+454
-49
lines changed

Source/NETworkManager.Localization/Resources/Strings.Designer.cs

Lines changed: 30 additions & 12 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Source/NETworkManager.Localization/Resources/Strings.resx

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -679,7 +679,7 @@
679679
<value>Apply</value>
680680
</data>
681681
<data name="ApplyWindowsKeyCombinationsLikeAltTab" xml:space="preserve">
682-
<value>Apply Windows key combinations (e.g. ALT+TAB):</value>
682+
<value>Apply Windows key combinations (e.g., ALT+TAB):</value>
683683
</data>
684684
<data name="Auth" xml:space="preserve">
685685
<value>Auth</value>
@@ -1367,16 +1367,16 @@ Profile files are not affected!</value>
13671367
<value>Enter a valid IPv4 address!</value>
13681368
</data>
13691369
<data name="EnterValidMACAddress" xml:space="preserve">
1370-
<value>Enter a valid MAC address (like 00:F1:23:AB:F2:35)!</value>
1370+
<value>Enter a valid MAC address (e.g., 00:F1:23:AB:F2:35)!</value>
13711371
</data>
13721372
<data name="EnterValidPort" xml:space="preserve">
13731373
<value>Enter a valid port (1 - 65535)!</value>
13741374
</data>
13751375
<data name="EnterValidSubnetmask" xml:space="preserve">
1376-
<value>Enter a valid subnetmask (like 255.255.255.0)!</value>
1376+
<value>Enter a valid subnetmask (e.g., 255.255.255.0)!</value>
13771377
</data>
13781378
<data name="EnterValidSubnetmaskOrCIDR" xml:space="preserve">
1379-
<value>Enter a valid subnetmask or CIDR (like 255.255.255.0 or /24)!</value>
1379+
<value>Enter a valid subnetmask or CIDR (e.g., 255.255.255.0 or /24)!</value>
13801380
</data>
13811381
<data name="FieldCannotBeEmpty" xml:space="preserve">
13821382
<value>Field cannot be empty!</value>
@@ -1448,10 +1448,10 @@ Profile files are not affected!</value>
14481448
<value>Enter a valid port and/or port range (1 - 65535)!</value>
14491449
</data>
14501450
<data name="EnterValidSubnet" xml:space="preserve">
1451-
<value>Enter a valid subnet (like 192.168.178.133/26)!</value>
1451+
<value>Enter a valid subnet (e.g., 192.168.178.133/26)!</value>
14521452
</data>
14531453
<data name="EnterValidWebsiteUri" xml:space="preserve">
1454-
<value>Enter a valid website (like https://example.com/index.html)</value>
1454+
<value>Enter a valid website (e.g., https://example.com/index.html)</value>
14551455
</data>
14561456
<data name="Green" xml:space="preserve">
14571457
<value>Green</value>
@@ -1742,7 +1742,7 @@ Profile files are not affected!</value>
17421742
<value>Add a tab to query whois...</value>
17431743
</data>
17441744
<data name="EnterValidDomain" xml:space="preserve">
1745-
<value>Enter a valid domain (like "example.com")!</value>
1745+
<value>Enter a valid domain (e.g., "example.com")!</value>
17461746
</data>
17471747
<data name="WhoisServerNotFoundForTheDomain" xml:space="preserve">
17481748
<value>Whois server not found for the domain: "{0}"</value>
@@ -2032,7 +2032,7 @@ is disabled!</value>
20322032
<value>Use custom IPv4 address API</value>
20332033
</data>
20342034
<data name="HelpMessage_CustomPublicIPv4AddressAPI" xml:space="preserve">
2035-
<value>URL to a web service that can be reached via http or https and returns an IPv4 address like "xx.xx.xx.xx" as response.</value>
2035+
<value>URL to a web service that can be reached via http or https and returns an IPv4 address e.g., "xx.xx.xx.xx" as response.</value>
20362036
</data>
20372037
<data name="CouldNotParsePublicIPAddressFromXXXMessage" xml:space="preserve">
20382038
<value>Could not parse public ip address from "{0}"! Try another service or use the default... </value>
@@ -3192,7 +3192,7 @@ If the option is disabled again, the values are no longer modified. However, the
31923192
<value>SNTP server(s)</value>
31933193
</data>
31943194
<data name="HelpMessage_CustomPublicIPv6AddressAPI" xml:space="preserve">
3195-
<value>URL to a web service that can be reached via http or https and returns an IPv6 address like "xxxx:xx:xxx::xx" as response.</value>
3195+
<value>URL to a web service that can be reached via http or https and returns an IPv6 address e.g., "xxxx:xx:xxx::xx" as response.</value>
31963196
</data>
31973197
<data name="IPEndPoint" xml:space="preserve">
31983198
<value>IP endpoint</value>
@@ -3234,7 +3234,7 @@ If the option is disabled again, the values are no longer modified. However, the
32343234
<value>An SNTP server with this name already exists!</value>
32353235
</data>
32363236
<data name="EnterValidHostnameOrIPAddress" xml:space="preserve">
3237-
<value>Enter a valid hostname (like "server-01" or "example.com") or a valid IP address (like 192.168.178.1)!</value>
3237+
<value>Enter a valid hostname (e.g., "server-01" or "example.com") or a valid IP address (e.g., 192.168.178.1)!</value>
32383238
</data>
32393239
<data name="Servers" xml:space="preserve">
32403240
<value>Server(s)</value>
@@ -3528,10 +3528,10 @@ Changes to this value will take effect after the application is restarted. Wheth
35283528
<value>The settings on this page contain errors. Correct them to be able to save.</value>
35293529
</data>
35303530
<data name="HelpMessage_PuTTYHostkey" xml:space="preserve">
3531-
<value>SSH hostkey to use for the connection (like "71:b8:f2:6e..."). Only available if the mode is "SSH".</value>
3531+
<value>SSH hostkey to use for the connection (e.g., "71:b8:f2:6e..."). Only available if the mode is "SSH".</value>
35323532
</data>
35333533
<data name="HelpMessage_PuTTYPrivateKeyFile" xml:space="preserve">
3534-
<value>Full path to the private key file (like "C:\Users\BornToBeRoot\SSH\private_key.ppk"). Only available if the mode is "SSH".</value>
3534+
<value>Full path to the private key file (e.g., "C:\Users\BornToBeRoot\SSH\private_key.ppk"). Only available if the mode is "SSH".</value>
35353535
</data>
35363536
<data name="HelpMessage_PuTTYUsername" xml:space="preserve">
35373537
<value>Username that will be passed into the PuTTY session. Only available if the mode is "SSH", "Telnet" or "Rlogin".</value>
@@ -3938,4 +3938,10 @@ Right-click for more options.</value>
39383938

39393939
{0} {1} {2}</value>
39403940
</data>
3941+
<data name="ExampleHostsFileEntryComment" xml:space="preserve">
3942+
<value>Primary DNS server</value>
3943+
</data>
3944+
<data name="EnterValidHostsFileEntryHostname" xml:space="preserve">
3945+
<value>Enter a valid hostname (e.g., "server-01" or "example.com")! Multiple hostnames can be separated with a space.</value>
3946+
</data>
39413947
</root>

Source/NETworkManager.Utilities/RegexHelper.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,17 +26,14 @@ public static class RegexHelper
2626
public const string IPv4AddressRangeRegex = $"^{IPv4AddressValues}-{IPv4AddressValues}$";
2727

2828
// Match a MAC-Address 000000000000 00:00:00:00:00:00, 00-00-00-00-00-00-00 or 0000.0000.0000
29-
3029
public const string MACAddressRegex =
3130
@"^^[A-Fa-f0-9]{12}$|^[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}$|^[A-Fa-f0-9]{4}.[A-Fa-f0-9]{4}.[A-Fa-f0-9]{4}$$";
3231

3332
// Match the first 3 bytes of a MAC-Address 000000, 00:00:00, 00-00-00
34-
3533
public const string MACAddressFirst3BytesRegex =
3634
@"^[A-Fa-f0-9]{6}$|^[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}(:|-){1}[A-Fa-f0-9]{2}$|^[A-Fa-f0-9]{4}.[A-Fa-f0-9]{2}$";
3735

3836
// Private subnetmask / cidr values
39-
4037
private const string SubnetmaskValues =
4138
@"(((255\.){3}(255|254|252|248|240|224|192|128|0+))|((255\.){2}(255|254|252|248|240|224|192|128|0+)\.0)|((255\.)(255|254|252|248|240|224|192|128|0+)(\.0+){2})|((255|254|252|248|240|224|192|128|0+)(\.0+){3}))";
4239

@@ -111,7 +108,7 @@ public static class RegexHelper
111108

112109
// Match an SNMP OID (like 1.3.6.1 or .1.3.6.2)
113110
public const string SnmpOidRegex = @"^\.?[012]\.(?:[0-9]|[1-3][0-9])(\.\d+)*$";
114-
111+
115112
// Match a hosts file entry with optional comments, supporting IPv4, IPv6, and hostnames
116113
// ^* : Matches the beginning of the line
117114
// (#)? : Optionally matches a comment (#) at the start of the line
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
using NETworkManager.Localization.Resources;
2+
using NETworkManager.Utilities;
3+
using System.Diagnostics;
4+
using System.Globalization;
5+
using System.Text.RegularExpressions;
6+
using System.Windows.Controls;
7+
8+
namespace NETworkManager.Validators;
9+
10+
public class HostsFileEntryHostnameValidator : ValidationRule
11+
{
12+
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
13+
{
14+
var input = (value as string);
15+
16+
var isValid = true;
17+
18+
Debug.WriteLine(input);
19+
20+
foreach (var hostname in input.Split(' '))
21+
{
22+
if (Regex.IsMatch(hostname, RegexHelper.HostnameOrDomainRegex) == false)
23+
{
24+
isValid = false;
25+
break;
26+
}
27+
}
28+
29+
if (isValid)
30+
return ValidationResult.ValidResult;
31+
32+
return new ValidationResult(false, Strings.EnterValidHostsFileEntryHostname);
33+
}
34+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
using NETworkManager.Localization.Resources;
2+
using System.Globalization;
3+
using System.Net.Sockets;
4+
using System.Windows.Controls;
5+
6+
namespace NETworkManager.Validators;
7+
8+
public class IPAddressValidator : ValidationRule
9+
{
10+
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
11+
{
12+
var input = (value as string);
13+
14+
if (System.Net.IPAddress.TryParse(input, out var address) && (address.AddressFamily == AddressFamily.InterNetwork || address.AddressFamily == AddressFamily.InterNetworkV6))
15+
return ValidationResult.ValidResult;
16+
17+
return new ValidationResult(false, Strings.EnterValidIPv6Address);
18+
}
19+
}
Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,19 @@
1-
using System.Globalization;
2-
using System.Text.RegularExpressions;
1+
using NETworkManager.Localization.Resources;
2+
using System.Globalization;
3+
using System.Net.Sockets;
34
using System.Windows.Controls;
4-
using NETworkManager.Localization.Resources;
5-
using NETworkManager.Utilities;
65

76
namespace NETworkManager.Validators;
87

98
public class IPv6AddressValidator : ValidationRule
109
{
1110
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
1211
{
13-
var ipAddress = (value as string)?.Trim();
12+
var input = (value as string);
1413

15-
if (string.IsNullOrEmpty(ipAddress))
16-
return new ValidationResult(false, Strings.EnterValidIPv6Address);
14+
if (System.Net.IPAddress.TryParse(input, out var address) && address.AddressFamily == AddressFamily.InterNetworkV6)
15+
return ValidationResult.ValidResult;
1716

18-
return Regex.IsMatch(ipAddress, RegexHelper.IPv6AddressRegex)
19-
? ValidationResult.ValidResult
20-
: new ValidationResult(false, Strings.EnterValidIPv6Address);
17+
return new ValidationResult(false, Strings.EnterValidIPv6Address);
2118
}
2219
}

0 commit comments

Comments
 (0)