diff --git a/anbs_cp/Classes/FileExtensions.cs b/anbs_cp/Classes/FileExtensions.cs index 478586f..2988845 100644 --- a/anbs_cp/Classes/FileExtensions.cs +++ b/anbs_cp/Classes/FileExtensions.cs @@ -1,8 +1,4 @@ -using System.Security.Cryptography; - -using Microsoft.AspNetCore.Http; - -namespace anbs_cp.Classes; +namespace anbs_cp.Classes; /// /// Класс -- расширение для класса File @@ -17,14 +13,6 @@ public static class FileExtension public static string MIMEType (string filename) => MimeTypes.GetMimeType(filename); - /// - /// Получает MIME-тип файла - /// - /// Загружаемый файл - /// MIME-тип файла - public static string MIMEType (IFormFile file) => - file.ContentType; - /// /// Размер файла в байтах /// diff --git a/anbs_cp/Classes/FileHash.cs b/anbs_cp/Classes/FileHash.cs index 73ca448..72b09da 100644 --- a/anbs_cp/Classes/FileHash.cs +++ b/anbs_cp/Classes/FileHash.cs @@ -1,8 +1,6 @@ using System.Security.Cryptography; using System.Text; -using Microsoft.AspNetCore.Http; - namespace anbs_cp.Classes; /// @@ -23,19 +21,6 @@ public sealed class FileHash Hash = md5.ComputeHash(stream); } - /// - /// Получение md5-хэша загружаемого файла. - /// Взято с https://stackoverflow.com/a/67081012/16469671 - /// - /// Загружаемый файл - /// Массив хэша - public FileHash (IFormFile file) - { - using MD5 md5 = MD5.Create(); - using StreamReader streamReader = new(file.OpenReadStream()); - Hash = md5.ComputeHash(streamReader.BaseStream); - } - /// /// Простой конструктор /// diff --git a/anbs_cp/Classes/PasswordOptions.cs b/anbs_cp/Classes/PasswordOptions.cs new file mode 100644 index 0000000..519f5de --- /dev/null +++ b/anbs_cp/Classes/PasswordOptions.cs @@ -0,0 +1,50 @@ +namespace anbs_cp.Classes; + +/// +/// Параметры пароля +/// +public sealed class PasswordOptions +{ + /// + /// Конструктор + /// + public PasswordOptions () + { + RequiredLength = 8; + RequireLowercase = true; + RequireUppercase = true; + RequireDigit = true; + RequireNonAlphanumeric = false; + RequiredUniqueChars = 6; + } + + /// + /// Требуемая длина пароля + /// + public byte RequiredLength { get; set; } + + /// + /// Требовать строчные буквы в пароле + /// + public bool RequireLowercase { get; set; } + + /// + /// Требовать прописные буквы в пароле + /// + public bool RequireUppercase { get; set; } + + /// + /// Требовать цифры в пароле + /// + public bool RequireDigit { get; set; } + + /// + /// Требовать символы + /// + public bool RequireNonAlphanumeric { get; set; } + + /// + /// Уникальных символов + /// + public byte RequiredUniqueChars { get; set; } +} \ No newline at end of file diff --git a/anbs_cp/Classes/TextFormatter.cs b/anbs_cp/Classes/TextFormatter.cs new file mode 100644 index 0000000..4d9e1c7 --- /dev/null +++ b/anbs_cp/Classes/TextFormatter.cs @@ -0,0 +1,111 @@ +using System.Net.Mail; + +namespace anbs_cp.Classes; + +/// +/// Форматирование текста +/// +public static class TextFormatter +{ + /// + /// Заменяет %МАРКЕРЫ% на их значения + /// + /// Текст сообщения + /// Словарь замен + /// Отформатированное сообщение + public static string FormatMessage (string message, Dictionary replaceDictionary) => + replaceDictionary.Aggregate(message, + static (current, item) => current.Replace($"%{item.Key}%", item.Value)); + + /// + /// Обрезает строку до указанных в параметре символов + /// + /// Текст, который нужно обрезать + /// Максимальное количество символов в тексте + /// Чем завершать обрезанный текст, если он был обрезан. Внимание расходует ! + /// Обрезанный текст + public static string GetShortText (string text, int maxLength, string endDots = "") => + text.Length < maxLength ? text : $"{text[..(maxLength - endDots.Length)]}{endDots}"; + + /// + /// Генерирует случайный пароль, удовлетворяющий параметрам . + /// Автор метода: Darkseal (https://stackoverflow.com/users/1233379/darkseal) + /// URL: https://stackoverflow.com/a/46229180/16469671 + /// + /// Объект допустимых параметров пароля, содержащий требования к надежности пароля. + /// Случайный пароль + public static string GenerateRandomPassword (PasswordOptions? options) + { + //Проверка options и установка по-умолчанию + options ??= new(); + + //Получаю массив символов + string[] randomChars = { + "ABCDEFGHJKLMNOPQRSTUVWXYZ", // прописные буквы + "abcdefghijkmnopqrstuvwxyz", // строчные буквы + "0123456789", // цифры + "~!@#$%^&*+-/.,{}[]();:|?<>='`" // символы + }; + + //Создаю объект Random + Random rand = new(Environment.TickCount); + + //Массив результатов + List chars = new(); + + //Вставляю прописные буквы + if (options.RequireUppercase) + chars.Insert(rand.Next(0, chars.Count), + randomChars[0][rand.Next(0, randomChars[0].Length)]); + + //Вставляю строчные буквы + if (options.RequireLowercase) + chars.Insert(rand.Next(0, chars.Count), + randomChars[1][rand.Next(0, randomChars[1].Length)]); + + //Вставляю цифры + if (options.RequireDigit) + chars.Insert(rand.Next(0, chars.Count), + randomChars[2][rand.Next(0, randomChars[2].Length)]); + + //Вставляю символы + if (options.RequireNonAlphanumeric) + chars.Insert(rand.Next(0, chars.Count), + randomChars[3][rand.Next(0, randomChars[3].Length)]); + + //Делаю выборку + for (int i = chars.Count; i < options.RequiredLength || chars.Distinct().Count() < options.RequiredUniqueChars; i++) + { + string rcs = randomChars[rand.Next(0, randomChars.Length)]; + chars.Insert(rand.Next(0, chars.Count), + rcs[rand.Next(0, rcs.Length)]); + } + + //Вывожу результат + return new(chars.ToArray()); + } + + /// + /// Проверяет на соответствие критерию электронной почты + /// Взято с: https://stackoverflow.com/a/1374644/16469671 + /// + /// Проверяемая строка + /// Является ли адресом электронной почты + public static bool IsValidEmail (string email) + { + string trimmedEmail = email.Trim(); + + if (trimmedEmail.EndsWith(".", StringComparison.Ordinal)) + return false; + + try + { + MailAddress addr = new(email); + return addr.Address == trimmedEmail; + } + catch + { + return false; + } + } +} \ No newline at end of file diff --git a/anbs_cp/Classes/TypeConverter.cs b/anbs_cp/Classes/TypeConverter.cs index 6139a0f..1760edb 100644 --- a/anbs_cp/Classes/TypeConverter.cs +++ b/anbs_cp/Classes/TypeConverter.cs @@ -1,7 +1,4 @@ -using System.Text.Encodings.Web; -using Microsoft.AspNetCore.Html; - -namespace anbs_cp.Classes; +namespace anbs_cp.Classes; /// /// Конвертер типов на манер Delphi @@ -13,37 +10,37 @@ public static class TypeConverter /// /// Преобразование int в string /// - /// Число + /// Число /// Строка - public static string IntToStr(int AInt) => AInt.ToString(); + public static string IntToStr (int aInt) => aInt.ToString(); /// /// Преобразование uint в string /// - /// Число + /// Число /// Строка - public static string IntToStr(uint AInt) => AInt.ToString(); + public static string IntToStr (uint aInt) => aInt.ToString(); /// /// Преобразование long в string /// - /// Число + /// Число /// Строка - public static string IntToStr(long AInt) => AInt.ToString(); + public static string IntToStr (long aInt) => aInt.ToString(); /// /// Преобразование ulong в string /// - /// Число + /// Число /// Строка - public static string IntToStr(ulong AInt) => AInt.ToString(); + public static string IntToStr (ulong aInt) => aInt.ToString(); /// /// Преобразование byte в string /// - /// Число + /// Число /// Строка - public static string IntToStr(byte AInt) => AInt.ToString(); + public static string IntToStr (byte aInt) => aInt.ToString(); #endregion @@ -52,86 +49,67 @@ public static class TypeConverter /// /// Преобразование строки в число /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) + /// Строка + /// Значение по умолчанию (по умолчанию, 0) /// Число - public static int StrToInt(string AStr, int ADefault = 0) + public static int StrToInt (string aStr, int aDefault = 0) { - if (!int.TryParse(AStr, out int result)) result = ADefault; + if (!int.TryParse(aStr, out int result)) + result = aDefault; return result; } /// /// Преобразование строки в число /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) + /// Строка + /// Значение по умолчанию (по умолчанию, 0) /// Число - public static uint StrToUInt(string AStr, uint ADefault = 0) + public static uint StrToUInt (string aStr, uint aDefault = 0) { - if (!uint.TryParse(AStr, out uint result)) result = ADefault; + if (!uint.TryParse(aStr, out uint result)) + result = aDefault; return result; } /// /// Преобразование строки в число /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) + /// Строка + /// Значение по умолчанию (по умолчанию, 0) /// Число - public static long StrToInt64(string AStr, long ADefault = 0) + public static long StrToInt64 (string aStr, long aDefault = 0) { - if (!long.TryParse(AStr, out long result)) result = ADefault; + if (!long.TryParse(aStr, out long result)) + result = aDefault; return result; } /// /// Преобразование строки в число /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) + /// Строка + /// Значение по умолчанию (по умолчанию, 0) /// Число - public static ulong StrToUInt64(string AStr, ulong ADefault = 0) + public static ulong StrToUInt64 (string aStr, ulong aDefault = 0) { - if (!ulong.TryParse(AStr, out ulong result)) result = ADefault; + if (!ulong.TryParse(aStr, out ulong result)) + result = aDefault; return result; } /// /// Преобразование строки в число /// - /// Строка - /// Значение по умолчанию (по умолчанию, 0) + /// Строка + /// Значение по умолчанию (по умолчанию, 0) /// Число - public static byte StrToByte(string AStr, byte ADefault = 0) + public static byte StrToByte (string aStr, byte aDefault = 0) { - if (!byte.TryParse(AStr, out byte result)) result = ADefault; + if (!byte.TryParse(aStr, out byte result)) + result = aDefault; return result; } #endregion - - #region Конвернтация IHtmlContent - /// - /// Преобразует тип в строку . - /// - /// Значение, которое нужно преобразовать. - /// - public static string HtmlContentToString(IHtmlContent content) - { - //Создаём writer - using StringWriter writer = new(); - //Конвертируем IHtmlContent в string - content.WriteTo(writer, HtmlEncoder.Default); - //Возвращаем результат - return writer.ToString(); - } - - /// - /// Преобразует строку в тип . - /// - /// Значение, которое нужно преобразовать. - /// - public static IHtmlContent StringToHtmlContent(string content) => new HtmlContentBuilder().AppendHtml(content); - #endregion } \ No newline at end of file diff --git a/anbs_cp/anbs_cp.csproj b/anbs_cp/anbs_cp.csproj index 758d1b5..21ced65 100644 --- a/anbs_cp/anbs_cp.csproj +++ b/anbs_cp/anbs_cp.csproj @@ -2,11 +2,11 @@ net7.0 - 2023.409.2 - Alexander Babaev - ANB Software Components Pack - Library of some useful functions in C# language. - Alexander Babaev + 2023.0514.2 + Александр Бабаев + Набор компонентов ANB Software + Библиотека полезных методов языка C# + Александр Бабаев anbs_cp anbs_cp enable @@ -38,10 +38,8 @@ - - - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/anbs_cpfn/Classes/NetFileExtension.cs b/anbs_cpfn/Classes/NetFileExtension.cs new file mode 100644 index 0000000..bef0227 --- /dev/null +++ b/anbs_cpfn/Classes/NetFileExtension.cs @@ -0,0 +1,17 @@ +using Microsoft.AspNetCore.Http; + +namespace anbs_cp.ForNet.Classes; + +/// +/// Класс -- расширение для класса File +/// +public class NetFileExtension +{ + /// + /// Получает MIME-тип файла + /// + /// Загружаемый файл + /// MIME-тип файла + public static string MIMEType (IFormFile file) => + file.ContentType; +} \ No newline at end of file diff --git a/anbs_cpfn/Classes/NetFileHash.cs b/anbs_cpfn/Classes/NetFileHash.cs new file mode 100644 index 0000000..fc2e50c --- /dev/null +++ b/anbs_cpfn/Classes/NetFileHash.cs @@ -0,0 +1,38 @@ +using System.Security.Cryptography; + +using anbs_cp.Classes; + +using Microsoft.AspNetCore.Http; + +namespace anbs_cp.ForNet.Classes; + +public static class NetFileHash +{ + /// + /// Получение md5-хэша загружаемого файла. + /// Взято с https://stackoverflow.com/a/67081012/16469671 + /// + /// Загружаемый файл + /// Массив хэша + public static FileHash GetFileHash (IFormFile file) + { + //Создаю md5 + using MD5 md5 = MD5.Create(); + + //Создаю поток для чтения + using StreamReader streamReader = new(file.OpenReadStream()); + + //Получаю строковый хэш + string hash = BitConverter.ToString(md5.ComputeHash(streamReader.BaseStream)).Replace("-", "") + .ToLowerInvariant(); + + //Создаю результат + FileHash fileHash = new(); + + //Вношу в него данные + fileHash.FromString(hash); + + //Возвращаю результат + return fileHash; + } +} \ No newline at end of file diff --git a/anbs_cpfn/Classes/NetTypeConverter.cs b/anbs_cpfn/Classes/NetTypeConverter.cs new file mode 100644 index 0000000..5aceca8 --- /dev/null +++ b/anbs_cpfn/Classes/NetTypeConverter.cs @@ -0,0 +1,35 @@ +using System.Text.Encodings.Web; + +using Microsoft.AspNetCore.Html; + +namespace anbs_cp.ForNet.Classes; + +/// +/// Расширение конвертера типов на манер Delphi +/// +public static class NetTypeConverter +{ + #region Конвернтация IHtmlContent + /// + /// Преобразует тип в строку . + /// + /// Значение, которое нужно преобразовать. + /// + public static string HtmlContentToString(IHtmlContent content) + { + //Создаём writer + using StringWriter writer = new(); + //Конвертируем IHtmlContent в string + content.WriteTo(writer, HtmlEncoder.Default); + //Возвращаем результат + return writer.ToString(); + } + + /// + /// Преобразует строку в тип . + /// + /// Значение, которое нужно преобразовать. + /// + public static IHtmlContent StringToHtmlContent(string content) => new HtmlContentBuilder().AppendHtml(content); + #endregion +} \ No newline at end of file diff --git a/anbs_cpfn/Extensions/UrlHelperExtension.cs b/anbs_cpfn/Extensions/UrlHelperExtension.cs new file mode 100644 index 0000000..a793f56 --- /dev/null +++ b/anbs_cpfn/Extensions/UrlHelperExtension.cs @@ -0,0 +1,110 @@ +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Http.Extensions; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.WebUtilities; +using Microsoft.Extensions.Primitives; + +namespace anbs_cp.ForNet.Extensions; + +/// +/// Расширение URLHelper +/// +public static class UrlHelperExtension +{ + /// + /// Очищает URL, удаляя ненужные QueryString + /// + /// + /// + /// + /// + /// + /// + /// Ссылка, которую нужно почистить + /// Массив ключей, которые нужно удалить + /// Возвращать только локальную ссылку + /// + public static string ParseURLQuery(this IUrlHelper helper, HttpContext context, string? url, + string[] clearQueryString, bool getLocalURL = true) + { + //Получаю returnURL + url ??= "/"; + + //Если адрес локальный, то преобразую в полный + if (helper.IsLocalUrl(url)) + url = LocalToFullURL(helper, context, url); + + //Создаю uri по адресу + Uri uri = new(url ?? ""); + + //Формат + const UriFormat format = UriFormat.UriEscaped; + + //Формирую Uri-адрес сайта + string baseUri = + uri.GetComponents(UriComponents.Scheme | UriComponents.Host | UriComponents.Port, + format); + + //Формирую локальную ссылку + string localUri = uri.GetComponents(UriComponents.Path, format); + + //Создаю словарь запроса + Dictionary query = QueryHelpers.ParseQuery(uri.Query); + + //Если он содержит параметр для очистки, то удаляю его + foreach (KeyValuePair queryItem in query.Where(queryItem => + clearQueryString.Contains(queryItem.Key))) + query.Remove(queryItem.Key); + + //Создаю список запроса, пригодный для QueryBuilder + List> queryList = query.Select(static queryItem => + new KeyValuePair(queryItem.Key, queryItem.Value.ToString())).ToList(); + + //Запускаю построение новых параметров + QueryBuilder qBuilder = new(queryList); + + //Создаю переменную-результат + string result = ""; + + //Если нужно получить полную ссылку + if (!getLocalURL) + result = baseUri; + + //формирую переменную-результат + result = $"{result}/{localUri}{qBuilder.ToQueryString()}"; + + //Вывожу результат + return result; + } + + /// + /// Получает локальный url-адрес + /// + /// + /// url-адрес + /// Локальный url-адрес + public static string ToLocalURL (this IUrlHelper helper, string url) + { + //Создаю uri из url + Uri uri = new(url); + + //Вывожу результат + return helper.IsLocalUrl(url) ? url : uri.PathAndQuery; + } + + /// + /// Преобразует локальную ссылку в полную + /// + /// + /// + /// + /// + /// + /// + /// Ссылка + /// + /// + /// + public static string? LocalToFullURL (this IUrlHelper helper, HttpContext context, string? url) => + helper.IsLocalUrl(url) ? $"{context.Request.Scheme}://{context.Request.Host}{url}" : url; +} \ No newline at end of file diff --git a/anbs_cpfn/anbs_cpfn.csproj b/anbs_cpfn/anbs_cpfn.csproj new file mode 100644 index 0000000..70928cc --- /dev/null +++ b/anbs_cpfn/anbs_cpfn.csproj @@ -0,0 +1,38 @@ + + + + net7.0 + enable + enable + True + ANBSoftware.ComponentsPackForNet + 2023.05.14.1 + Александр Бабаев + Набор компонентов ANB Software для ASP.NET Core + Библиотека полезных методов языка C# для ASP.NET Core + Александр Бабаев + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + https://git.babaev-an.ru/babaev-an/anbsoftware_componentspack + git + MIT + anbs_cp.ForNet + anbs_cp_fn + + + + + + + + + + + + + + + + + + + diff --git a/anbsoftware.componentspack.sln b/anbsoftware.componentspack.sln index adc732b..1443384 100644 --- a/anbsoftware.componentspack.sln +++ b/anbsoftware.componentspack.sln @@ -5,7 +5,12 @@ VisualStudioVersion = 17.0.31903.59 MinimumVisualStudioVersion = 10.0.40219.1 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "anbs_cp", "anbs_cp\anbs_cp.csproj", "{442A56CC-1061-4EB5-8B67-3E3D997976D7}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "demo", "demo\demo.csproj", "{3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "demo", "demo\demo.csproj", "{3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}" + ProjectSection(ProjectDependencies) = postProject + {442A56CC-1061-4EB5-8B67-3E3D997976D7} = {442A56CC-1061-4EB5-8B67-3E3D997976D7} + EndProjectSection +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "anbs_cpfn", "anbs_cpfn\anbs_cpfn.csproj", "{EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}" ProjectSection(ProjectDependencies) = postProject {442A56CC-1061-4EB5-8B67-3E3D997976D7} = {442A56CC-1061-4EB5-8B67-3E3D997976D7} EndProjectSection @@ -23,6 +28,10 @@ Global {3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}.Debug|Any CPU.ActiveCfg = Release|Any CPU {3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}.Debug|Any CPU.Build.0 = Release|Any CPU {3BB0778D-3C34-4DD8-A54E-CB476BEF2F7B}.Release|Any CPU.ActiveCfg = Debug.CNF|Any CPU + {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EDED871B-8A96-4A2F-83CF-AD40FF66F6E2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/anbsoftware.componentspack.sln.DotSettings b/anbsoftware.componentspack.sln.DotSettings index 08f8a10..8425d97 100644 --- a/anbsoftware.componentspack.sln.DotSettings +++ b/anbsoftware.componentspack.sln.DotSettings @@ -4,7 +4,10 @@ HDD RA RAM + True + True True + True True True True