Kit.Core/LibExternal/Minio/Helper/BuilderUtil.cs

137 lines
4.7 KiB
C#

/*
* MinIO .NET Library for Amazon S3 Compatible Cloud Storage, (C) 2020 MinIO, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
using System.Globalization;
using System.Net;
namespace Minio.Helper;
public static class BuilderUtil
{
public static bool IsAwsDualStackEndpoint(string endpoint)
{
if (string.IsNullOrEmpty(endpoint))
throw new ArgumentException($"'{nameof(endpoint)}' cannot be null or empty.", nameof(endpoint));
return endpoint.Contains(".dualstack.", StringComparison.OrdinalIgnoreCase);
}
public static bool IsAwsAccelerateEndpoint(string endpoint)
{
if (string.IsNullOrEmpty(endpoint))
throw new ArgumentException($"'{nameof(endpoint)}' cannot be null or empty.", nameof(endpoint));
return endpoint.StartsWith("s3-accelerate.", StringComparison.OrdinalIgnoreCase);
}
public static bool IsAwsEndpoint(string endpoint)
{
if (string.IsNullOrEmpty(endpoint))
throw new ArgumentException($"'{nameof(endpoint)}' cannot be null or empty.", nameof(endpoint));
return (endpoint.StartsWith("s3.", StringComparison.OrdinalIgnoreCase) ||
IsAwsAccelerateEndpoint(endpoint)) &&
(endpoint.EndsWith(".amazonaws.com", StringComparison.OrdinalIgnoreCase) ||
endpoint.EndsWith(".amazonaws.com.cn", StringComparison.OrdinalIgnoreCase));
}
public static bool IsChineseDomain(string host)
{
if (string.IsNullOrEmpty(host))
throw new ArgumentException($"'{nameof(host)}' cannot be null or empty.", nameof(host));
return host.EndsWith(".cn", StringComparison.OrdinalIgnoreCase);
}
public static string ExtractRegion(string endpoint)
{
if (string.IsNullOrEmpty(endpoint))
throw new ArgumentException($"'{nameof(endpoint)}' cannot be null or empty.", nameof(endpoint));
var tokens = endpoint.Split('.');
if (tokens.Length < 2)
return null;
var token = tokens[1];
// If token is "dualstack", then region might be in next token.
if (token.Equals("dualstack", StringComparison.OrdinalIgnoreCase) && tokens.Length >= 3)
token = tokens[2];
// If token is equal to "amazonaws", region is not passed in the endpoint.
if (token.Equals("amazonaws", StringComparison.OrdinalIgnoreCase))
return null;
// Return token as region.
return token;
}
private static bool IsValidSmallInt(string val)
{
return byte.TryParse(val, out _);
}
private static bool IsValidOctetVal(string val)
{
const byte uLimit = 255;
return byte.Parse(val, NumberStyles.Integer, CultureInfo.InvariantCulture) <= uLimit;
}
private static bool IsValidIPv4(string ip)
{
var posColon = ip.LastIndexOf(':');
if (posColon != -1) ip = ip[..posColon];
var octetsStr = ip.Split('.');
if (octetsStr.Length != 4) return false;
var isValidSmallInt = Array.TrueForAll(octetsStr, IsValidSmallInt);
if (!isValidSmallInt) return false;
return Array.TrueForAll(octetsStr, IsValidOctetVal);
}
private static bool IsValidIP(string host)
{
return IPAddress.TryParse(host, out _);
}
public static bool IsValidHostnameOrIPAddress(string host)
{
// Let's do IP address check first.
if (string.IsNullOrWhiteSpace(host)) return false;
// IPv4 first
if (IsValidIPv4(host)) return true;
// IPv6 or other IP address format
if (IsValidIP(host)) return true;
// Remove any port in endpoint, in such a case.
var posColon = host.LastIndexOf(':');
if (posColon != -1)
{
try
{
var port = int.Parse(host.Substring(posColon + 1, host.Length - posColon - 1),
CultureInfo.InvariantCulture);
}
catch (FormatException)
{
return false;
}
host = host[..posColon];
}
// Check host if it is a hostname.
return Uri.CheckHostName(host).ToString().Equals("dns", StringComparison.OrdinalIgnoreCase);
}
}