using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
using System.Net.Mail;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Common.Extensions;
namespace System
{
///
/// String extensions.
///
public static class StringExtensions
{
///
/// Converts a hex string into a byte array.
///
/// The hex encoded string.
/// A delimiter between the bytes (e.g. for MAC address).
/// The bytes.
public static IEnumerable HexToBytes(this string hexString, string delimiter = "")
{
if (string.IsNullOrWhiteSpace(hexString))
yield break;
string str = string.IsNullOrEmpty(delimiter) ? hexString : hexString.Replace(delimiter, "");
if (str.Length % 2 == 1)
yield break;
if (Regex.IsMatch(str, "[^0-9a-fA-F]"))
yield break;
for (int i = 0; i < str.Length; i += 2)
yield return Convert.ToByte(str.Substring(i, 2), 16);
}
///
/// Converts a byte collection into a hex string.
///
/// The bytes.
/// A delimiter to set between the bytes (e.g. for MAC address).
/// The hex encoded string.
public static string BytesToHex(this IEnumerable bytes, string delimiter = "")
{
if (bytes?.Any() != true)
return null;
return string.Join(delimiter, bytes.Select(b => b.ToString("x2")));
}
///
/// Encodes a string to the hexadecimal system (base 16).
///
/// The string to encode hexadecimal.
/// The text encoding to use (default: )
///
public static string HexEncode(this string str, Encoding encoding = null)
{
if (string.IsNullOrEmpty(str))
return str;
return (encoding ?? Encoding.Default).GetBytes(str).BytesToHex();
}
///
/// Decodes a string from the hexadecimal system (base 16).
///
/// The hexadecimal encoded string to decode.
/// The text encoding to use (default: )
///
public static string HexDecode(this string str, Encoding encoding = null)
{
if (string.IsNullOrEmpty(str))
return str;
return (encoding ?? Encoding.Default).GetString(str.HexToBytes().ToArray());
}
///
/// Encodes a string to base64.
///
/// The string to encode with base64.
/// The text encoding to use (default: )
///
public static string Base64Encode(this string str, Encoding encoding = null)
=> Convert.ToBase64String((encoding ?? Encoding.Default).GetBytes(str));
///
/// Decodes a string from base64.
///
/// The base64 encoded string to decode.
/// The text encoding to use (default: )
///
public static string Base64Decode(this string str, Encoding encoding = null)
=> (encoding ?? Encoding.Default).GetString(Convert.FromBase64String(str));
///
/// Replaces the search substring with the replacement when it was found at the beginning of the string.
///
/// The string.
/// The searched substring.
/// The replacement.
///
public static string ReplaceStart(this string str, string search, string replacement)
{
if (str.StartsWith(search))
return replacement + str.Substring(search.Length);
return str;
}
///
/// Replaces the search substring with the replacement when it was found at the end of the string.
///
/// The string.
/// The searched substring.
/// The replacement.
///
public static string ReplaceEnd(this string str, string search, string replacement)
{
if (str.EndsWith(search))
return str.Substring(0, str.Length - search.Length) + replacement;
return str;
}
///
/// Parses a to a using culture "de" or invariant.
///
/// The string to parse.
///
public static decimal ParseDecimal(this string decString)
{
int dotIndex = decString.LastIndexOf('.');
int commaIndex = decString.LastIndexOf(',');
var culture = dotIndex < commaIndex ? new CultureInfo("de-DE") : CultureInfo.InvariantCulture;
return decimal.Parse(decString, culture);
}
///
/// Checks whether the given is a valid .
///
///
/// You can enhance the check by requesting the MX record of the domain.
///
/// The email address as string to validate.
/// A value indicating whether to resolve a MX record (Google DNS is used).
/// true when the email address is valid, other wise false.
public static bool IsValidEmailAddress(this string email, bool checkForDnsRecord = false)
=> email.IsValidEmailAddress(checkForDnsRecord ? new[] { new IPEndPoint(IPAddress.Parse("8.8.8.8"), 53) } : null);
///
/// Checks whether the given is a valid .
///
///
/// The check is enhanced by a request for MX records on the defined .
///
/// The DNS resolution is only used when the DNS NuGet package is available.
/// See: https://www.nuget.org/packages/DNS/7.0.0
///
/// The email address as string to validate.
/// A list of s of nameservers.
/// true when the email address is valid, other wise false.
public static bool IsValidEmailAddress(this string emailAddress, IEnumerable nameservers)
{
try
{
var mailAddress = new MailAddress(emailAddress);
bool isValid = mailAddress.Address == emailAddress;
if (isValid && nameservers?.Any() == true)
{
var dnsClientType = Type.GetType("DNS.Client.DnsClient, DNS") ?? throw new DllNotFoundException("The DNS NuGet package is required: https://www.nuget.org/packages/DNS/7.0.0");
var recordTypeType = Type.GetType("DNS.Protocol.RecordType, DNS");
var resolveMethodInfo = dnsClientType.GetMethod("Resolve", new[] { typeof(string), recordTypeType, typeof(CancellationToken) });
bool exists = false;
foreach (var nameserver in nameservers)
{
object dnsClient = Activator.CreateInstance(dnsClientType, new object[] { nameserver });
var waitTask = Task.Run(async () => await resolveMethodInfo.InvokeAsync