Improve BizTalk endpoint address detection

This commit is contained in:
2026-08-06 18:20:38 +02:00
parent ac51714a88
commit 26e6ea5aac
6 changed files with 116 additions and 21 deletions
@@ -48,7 +48,16 @@ namespace BizTalkCheckmkPulse
return Unresolved("Aktive statische Transportadresse ist leer.");
}
if (LooksLikeEmailRecipients(address) || Contains(candidate.AdapterName, "SMTP"))
if (Contains(candidate.AdapterName, "SMTP"))
{
return Expected("SMTP-Empfaenger beziehungsweise Adapteradresse enthaelt nicht den SMTP-Server.");
}
// SFTP-/FTP-Adressen duerfen Benutzerinformationen enthalten (user@host).
// Deshalb erst nach der adapterspezifischen Aufloesung als Empfaengerliste einstufen.
if (LooksLikeEmailRecipients(address)
&& !Contains(candidate.AdapterName, "SFTP")
&& !Contains(candidate.AdapterName, "FTP"))
{
return Expected("SMTP-Empfaenger beziehungsweise Adapteradresse enthaelt nicht den SMTP-Server.");
}
@@ -144,7 +153,9 @@ namespace BizTalkCheckmkPulse
return true;
}
if (LooksLikeEmailRecipients(address))
if (LooksLikeEmailRecipients(address)
&& !Contains(adapterName, "SFTP")
&& !Contains(adapterName, "FTP"))
{
reason = "SMTP-Empfaengerliste ist kein pruefbarer Netzwerk-Endpunkt.";
return false;
@@ -171,6 +182,28 @@ namespace BizTalkCheckmkPulse
return Validate(host, port, out reason);
}
// Host:Port muss vor Uri.TryCreate ausgewertet werden: .NET interpretiert
// beispielsweise "server:2222/path" sonst als URI mit dem Schema "server".
var match = HostPortPattern.Match(address);
if (match.Success)
{
host = match.Groups["host"].Value.Trim('[', ']');
if (!int.TryParse(match.Groups["port"].Value, out port))
{
port = 0;
}
return Validate(host, port, out reason);
}
// BizTalk-FTP-/SFTP-Konfigurationen kommen auch ohne Schema vor. Durch
// die temporaere URI-Normalisierung werden user@host, IPv6 und Ports
// sauber getrennt; Benutzername und Pfad gelangen nicht in den Katalog.
if (TryResolveAdapterUri(address, adapterName, out host, out port))
{
return Validate(host, port, out reason);
}
Uri uri;
if (Uri.TryCreate(address, UriKind.Absolute, out uri)
&& !string.IsNullOrWhiteSpace(uri.Scheme))
@@ -184,7 +217,7 @@ namespace BizTalkCheckmkPulse
return false;
}
host = uri.Host;
host = NormalizeHost(uri.Host);
port = 445;
return Validate(host, port, out reason);
}
@@ -195,7 +228,7 @@ namespace BizTalkCheckmkPulse
return false;
}
host = uri.Host;
host = NormalizeHost(uri.Host);
protocol = scheme == "udp" ? "UDP" : "TCP";
port = ResolvePort(uri, scheme);
if (port <= 0 && HasExplicitPort(address))
@@ -212,18 +245,6 @@ namespace BizTalkCheckmkPulse
return Validate(host, port, out reason);
}
var match = HostPortPattern.Match(address);
if (match.Success)
{
host = match.Groups["host"].Value.Trim('[', ']');
if (!int.TryParse(match.Groups["port"].Value, out port))
{
port = 0;
}
return Validate(host, port, out reason);
}
if (Contains(adapterName, "SFTP"))
{
host = ExtractBareAdapterHost(address);
@@ -318,6 +339,33 @@ namespace BizTalkCheckmkPulse
return separator < 0 ? value : value.Substring(0, separator);
}
private static bool TryResolveAdapterUri(string address, string adapterName, out string host, out int port)
{
host = string.Empty;
port = 0;
var scheme = Contains(adapterName, "SFTP")
? "sftp"
: Contains(adapterName, "FTP") ? "ftp" : string.Empty;
if (scheme.Length == 0 || address.IndexOf("://", StringComparison.Ordinal) >= 0)
{
return false;
}
Uri uri;
var normalized = scheme + "://" + address.TrimStart('/');
if (!Uri.TryCreate(normalized, UriKind.Absolute, out uri)
|| string.IsNullOrWhiteSpace(uri.Host))
{
return false;
}
host = NormalizeHost(uri.Host);
port = uri.IsDefaultPort || uri.Port <= 0
? scheme == "sftp" ? 22 : 21
: uri.Port;
return true;
}
/// <summary>
/// Erkennt Adapter, deren relative Receive-Adresse eine lokale Listenerbindung statt eines Remoteziels beschreibt.
/// </summary>
@@ -385,10 +433,16 @@ namespace BizTalkCheckmkPulse
&& value.IndexOf(fragment, StringComparison.OrdinalIgnoreCase) >= 0;
}
private static string NormalizeHost(string host)
{
return (host ?? string.Empty).Trim().Trim('[', ']');
}
private static bool Validate(string host, int port, out string reason)
{
host = (host ?? string.Empty).Trim();
if (host.Length == 0 || host.IndexOfAny(new[] { ' ', '\t', '\r', '\n', '*', '%' }) >= 0)
host = NormalizeHost(host);
if (host.Length == 0
|| host.IndexOfAny(new[] { ' ', '\t', '\r', '\n', '*', '%', '/', '\\', '@', ';', '?', '#' }) >= 0)
{
reason = "Host ist leer oder enthaelt nicht aufgeloeste Platzhalter.";
return false;