diff --git a/.gitignore b/.gitignore
index ea85d98..1c6098b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,3 @@
-/bin/**/**
-/obj/**/**
-/App_Data/**/**
+/bin/**/**
+/obj/**/**
+/App_Data/**/**
diff --git a/ExtensionsEx.cs b/ExtensionsEx.cs
index d986691..d8c2fe7 100644
--- a/ExtensionsEx.cs
+++ b/ExtensionsEx.cs
@@ -1,49 +1,49 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 27-08-2016
-//
-// Last Modified By : Frede H.
-// Last Modified On : 02-24-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the Affero GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// Affero GNU General Public License for more details.
-//
-// You should have received a copy of the Affero GNU General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
-//
-//
-// ***********************************************************************
-
-using System;
-using System.Collections.Generic;
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Class ExtensionsEx.
- ///
- public static class ExtensionsEx
- {
- ///
- /// ForEach loop
- ///
- ///
- /// The items.
- /// The action.
- public static void ForEach(this IEnumerable items, Action action)
- {
- foreach (var item in items)
- action(item);
- }
- }
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 27-08-2016
+//
+// Last Modified By : Frede H.
+// Last Modified On : 02-24-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the Affero GNU General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// Affero GNU General Public License for more details.
+//
+// You should have received a copy of the Affero GNU General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
+//
+//
+// ***********************************************************************
+
+using System;
+using System.Collections.Generic;
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Class ExtensionsEx.
+ ///
+ public static class ExtensionsEx
+ {
+ ///
+ /// ForEach loop
+ ///
+ ///
+ /// The items.
+ /// The action.
+ public static void ForEach(this IEnumerable items, Action action)
+ {
+ foreach (var item in items)
+ action(item);
+ }
+ }
}
\ No newline at end of file
diff --git a/FCS.Lib.Utility.csproj b/FCS.Lib.Utility.csproj
index 960a025..b5c2bb4 100644
--- a/FCS.Lib.Utility.csproj
+++ b/FCS.Lib.Utility.csproj
@@ -1,92 +1,92 @@
-
-
-
-
- 10.0
-
-
- Debug
- AnyCPU
- {1F1FECFD-E07E-4B5C-A7F9-67FB89EE94A3}
- Library
- Properties
- FCS.Lib.Utility
- FCS.Lib.Utility
- v4.8
- 512
- true
-
-
- true
- full
- false
- bin\Debug\
- DEBUG;TRACE
- prompt
- 4
- bin\Debug\FCS.Lib.Utility.xml
-
-
- pdbonly
- true
- bin\Release\
- TRACE
- prompt
- 4
-
-
- false
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- True
- True
- AssemblyInfo.tt
-
-
-
-
-
-
-
-
-
-
-
-
-
- TextTemplatingFileGenerator
- AssemblyInfo.cs
-
-
-
-
-
-
-
-
- "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\TextTransform.exe" -out "$(ProjectDir)Properties\AssemblyInfo.cs" "$(ProjectDir)Properties\AssemblyInfo.tt"
-
+
+
+
+
+ 10.0
+
+
+ Debug
+ AnyCPU
+ {1F1FECFD-E07E-4B5C-A7F9-67FB89EE94A3}
+ Library
+ Properties
+ FCS.Lib.Utility
+ FCS.Lib.Utility
+ v4.8
+ 512
+ true
+
+
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+ bin\Debug\FCS.Lib.Utility.xml
+
+
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ True
+ True
+ AssemblyInfo.tt
+
+
+
+
+
+
+
+
+
+
+
+
+
+ TextTemplatingFileGenerator
+ AssemblyInfo.cs
+
+
+
+
+
+
+
+
+ "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\TextTransform.exe" -out "$(ProjectDir)Properties\AssemblyInfo.cs" "$(ProjectDir)Properties\AssemblyInfo.tt"
+
\ No newline at end of file
diff --git a/FCS.Lib.Utility.csproj.user b/FCS.Lib.Utility.csproj.user
index c10e84b..1dec02f 100644
--- a/FCS.Lib.Utility.csproj.user
+++ b/FCS.Lib.Utility.csproj.user
@@ -1,6 +1,6 @@
-
-
-
- ProjectFiles
-
+
+
+
+ ProjectFiles
+
\ No newline at end of file
diff --git a/Generators.cs b/Generators.cs
index 23b986f..74e2588 100644
--- a/Generators.cs
+++ b/Generators.cs
@@ -1,323 +1,323 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 2020-07-01
-//
-// Last Modified By : FH
-// Last Modified On : 02-24-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the Affero GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// Affero GNU General Public License for more details.
-//
-// You should have received a copy of the Affero GNU General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
-//
-//
-// ***********************************************************************
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Security.Cryptography;
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Generators
- ///
- public static class Generators
- {
- ///
- /// Generate 6 character shortUrl
- ///
- /// of 6 characters
- public static string ShortUrlGenerator()
- {
- return ShortUrlGenerator(6);
- }
-
- ///
- /// Generate shortUrl with length
- ///
- /// The length.
- ///
- /// derived from https://sourceforge.net/projects/shorturl-dotnet/
- public static string ShortUrlGenerator(int length)
- {
- const string charsLower = "abcdefghijkmnopqrstuvwxyz";
- const string charsUpper = "ABCDFEGHJKLMNPQRSTUVWXYZ-";
- const string charsNumeric = "1234567890";
-
- // Create a local array containing supported short-url characters
- // grouped by types.
- var charGroups = new[]
- {
- charsLower.ToCharArray(),
- charsUpper.ToCharArray(),
- charsNumeric.ToCharArray()
- };
-
- // Use this array to track the number of unused characters in each
- // character group.
- var charsLeftInGroup = new int[charGroups.Length];
-
- // Initially, all characters in each group are not used.
- for (var i = 0; i < charsLeftInGroup.Length; i++)
- charsLeftInGroup[i] = charGroups[i].Length;
-
- // Use this array to track (iterate through) unused character groups.
- var leftGroupsOrder = new int[charGroups.Length];
-
- // Initially, all character groups are not used.
- for (var i = 0; i < leftGroupsOrder.Length; i++)
- leftGroupsOrder[i] = i;
-
- // Using our private randomizer
- var random = RandomSeed();
-
- // This array will hold short-url characters.
- // Allocate appropriate memory for the short-url.
- var shortUrl = new char[random.Next(length, length)];
-
- // Index of the last non-processed group.
- var lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
-
- // Generate short-url characters one at a time.
- for (var i = 0; i < shortUrl.Length; i++)
- {
- // If only one character group remained unprocessed, process it;
- // otherwise, pick a random character group from the unprocessed
- // group list. To allow a special character to appear in the
- // first position, increment the second parameter of the Next
- // function call by one, i.e. lastLeftGroupsOrderIdx + 1.
- int nextLeftGroupsOrderIdx;
- if (lastLeftGroupsOrderIdx == 0)
- nextLeftGroupsOrderIdx = 0;
- else
- nextLeftGroupsOrderIdx = random.Next(0,
- lastLeftGroupsOrderIdx);
-
- // Get the actual index of the character group, from which we will
- // pick the next character.
- var nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
-
- // Get the index of the last unprocessed characters in this group.
- var lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
-
- // If only one unprocessed character is left, pick it; otherwise,
- // get a random character from the unused character list.
- var nextCharIdx = lastCharIdx == 0 ? 0 : random.Next(0, lastCharIdx + 1);
-
- // Add this character to the short-url.
- shortUrl[i] = charGroups[nextGroupIdx][nextCharIdx];
-
- // If we processed the last character in this group, start over.
- if (lastCharIdx == 0)
- {
- charsLeftInGroup[nextGroupIdx] =
- charGroups[nextGroupIdx].Length;
- }
- // There are more unprocessed characters left.
- else
- {
- // Swap processed character with the last unprocessed character
- // so that we don't pick it until we process all characters in
- // this group.
- if (lastCharIdx != nextCharIdx)
- {
- (charGroups[nextGroupIdx][lastCharIdx], charGroups[nextGroupIdx][nextCharIdx]) = (charGroups[nextGroupIdx][nextCharIdx], charGroups[nextGroupIdx][lastCharIdx]);
- }
-
- // Decrement the number of unprocessed characters in
- // this group.
- charsLeftInGroup[nextGroupIdx]--;
- }
-
- // If we processed the last group, start all over.
- if (lastLeftGroupsOrderIdx == 0)
- {
- lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
- }
- // There are more unprocessed groups left.
- else
- {
- // Swap processed group with the last unprocessed group
- // so that we don't pick it until we process all groups.
- if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
- {
- (leftGroupsOrder[lastLeftGroupsOrderIdx], leftGroupsOrder[nextLeftGroupsOrderIdx]) = (leftGroupsOrder[nextLeftGroupsOrderIdx], leftGroupsOrder[lastLeftGroupsOrderIdx]);
- }
-
- // Decrement the number of unprocessed groups.
- lastLeftGroupsOrderIdx--;
- }
- }
-
- // Convert password characters into a string and return the result.
- return new string(shortUrl);
- }
-
- ///
- /// Username generator
- ///
- /// The options.
- ///
- ///
- public static string GenerateUsername(StringOptions options = null)
- {
- options ??= new StringOptions
- {
- RequiredLength = 10,
- RequireDigit = true,
- RequireLowercase = true,
- RequireUppercase = true,
- RequiredUniqueChars = 4,
- RequireNonLetterOrDigit = false,
- RequireNonAlphanumeric = false
- };
- return GenerateRandomString(options);
- }
-
- ///
- /// Password generator
- ///
- /// The options.
- ///
- ///
- public static string GeneratePassword(StringOptions options = null)
- {
- options ??= new StringOptions
- {
- RequiredLength = 10,
- RequireDigit = true,
- RequireLowercase = true,
- RequireUppercase = true,
- RequiredUniqueChars = 4,
- RequireNonLetterOrDigit = true,
- RequireNonAlphanumeric = true
- };
- return GenerateRandomString(options);
- }
-
- ///
- /// Random string generator with length
- ///
- /// The length.
- ///
- public static string GenerateRandomText(int length)
- {
- const string consonants = "bcdfghjklmnprstvxzBDFGHJKLMNPRSTVXZ";
- const string vowels = "aeiouyAEIOUY";
-
- var rndString = "";
- var randomNum = RandomSeed();
-
- while (rndString.Length < length)
- {
- rndString += consonants[randomNum.Next(consonants.Length)];
- if (rndString.Length < length)
- rndString += vowels[randomNum.Next(vowels.Length)];
- }
-
- return rndString;
- }
-
- ///
- /// Random string generator - string options
- ///
- /// The options.
- ///
- public static string GenerateRandomString(StringOptions options = null)
- {
- options ??= new StringOptions
- {
- RequiredLength = 10,
- RequireDigit = true,
- RequireLowercase = true,
- RequireUppercase = true,
- RequiredUniqueChars = 4,
- RequireNonLetterOrDigit = true,
- RequireNonAlphanumeric = true
- };
-
- var randomChars = new[]
- {
- "ABCDEFGHJKLMNOPQRSTUVWXYZ", // uppercase
- "abcdefghijkmnopqrstuvwxyz", // lowercase
- "0123456789", // digits
- "!@$?_-" // non-alphanumeric
- };
-
- // Using our private randomizer
- var rand = RandomSeed();
-
- var chars = new List();
-
- 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)]);
-
- var rcs = randomChars[rand.Next(0, randomChars.Length)];
- for (var i = chars.Count;
- i < options.RequiredLength
- || chars.Distinct().Count() < options.RequiredUniqueChars;
- i++)
- chars.Insert(rand.Next(0, chars.Count),
- rcs[rand.Next(0, rcs.Length)]);
-
- return new string(chars.ToArray());
- }
-
- ///
- /// Randomize random using RNGCrypto
- ///
- ///
- /// derived from https://sourceforge.net/projects/shorturl-dotnet/
- ///
- public static Random RandomSeed()
- {
- // As the default Random is based on the current time
- // so it produces the same "random" number within a second
- // Use a crypto service to create the seed value
-
- // 4-byte array to fill with random bytes
- var randomBytes = new byte[4];
-
- // Generate 4 random bytes.
- using (var rng = new RNGCryptoServiceProvider())
- {
- rng.GetBytes(randomBytes);
- }
-
- // Convert 4 bytes into a 32-bit integer value.
- var seed = ((randomBytes[0] & 0x7f) << 24) |
- (randomBytes[1] << 16) |
- (randomBytes[2] << 8) |
- randomBytes[3];
-
- // Return a truly randomized random generator
- return new Random(seed);
- }
- }
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 2020-07-01
+//
+// Last Modified By : FH
+// Last Modified On : 02-24-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the Affero GNU General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// Affero GNU General Public License for more details.
+//
+// You should have received a copy of the Affero GNU General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
+//
+//
+// ***********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Security.Cryptography;
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Generators
+ ///
+ public static class Generators
+ {
+ ///
+ /// Generate 6 character shortUrl
+ ///
+ /// of 6 characters
+ public static string ShortUrlGenerator()
+ {
+ return ShortUrlGenerator(6);
+ }
+
+ ///
+ /// Generate shortUrl with length
+ ///
+ /// The length.
+ ///
+ /// derived from https://sourceforge.net/projects/shorturl-dotnet/
+ public static string ShortUrlGenerator(int length)
+ {
+ const string charsLower = "abcdefghijkmnopqrstuvwxyz";
+ const string charsUpper = "ABCDFEGHJKLMNPQRSTUVWXYZ-";
+ const string charsNumeric = "1234567890";
+
+ // Create a local array containing supported short-url characters
+ // grouped by types.
+ var charGroups = new[]
+ {
+ charsLower.ToCharArray(),
+ charsUpper.ToCharArray(),
+ charsNumeric.ToCharArray()
+ };
+
+ // Use this array to track the number of unused characters in each
+ // character group.
+ var charsLeftInGroup = new int[charGroups.Length];
+
+ // Initially, all characters in each group are not used.
+ for (var i = 0; i < charsLeftInGroup.Length; i++)
+ charsLeftInGroup[i] = charGroups[i].Length;
+
+ // Use this array to track (iterate through) unused character groups.
+ var leftGroupsOrder = new int[charGroups.Length];
+
+ // Initially, all character groups are not used.
+ for (var i = 0; i < leftGroupsOrder.Length; i++)
+ leftGroupsOrder[i] = i;
+
+ // Using our private randomizer
+ var random = RandomSeed();
+
+ // This array will hold short-url characters.
+ // Allocate appropriate memory for the short-url.
+ var shortUrl = new char[random.Next(length, length)];
+
+ // Index of the last non-processed group.
+ var lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
+
+ // Generate short-url characters one at a time.
+ for (var i = 0; i < shortUrl.Length; i++)
+ {
+ // If only one character group remained unprocessed, process it;
+ // otherwise, pick a random character group from the unprocessed
+ // group list. To allow a special character to appear in the
+ // first position, increment the second parameter of the Next
+ // function call by one, i.e. lastLeftGroupsOrderIdx + 1.
+ int nextLeftGroupsOrderIdx;
+ if (lastLeftGroupsOrderIdx == 0)
+ nextLeftGroupsOrderIdx = 0;
+ else
+ nextLeftGroupsOrderIdx = random.Next(0,
+ lastLeftGroupsOrderIdx);
+
+ // Get the actual index of the character group, from which we will
+ // pick the next character.
+ var nextGroupIdx = leftGroupsOrder[nextLeftGroupsOrderIdx];
+
+ // Get the index of the last unprocessed characters in this group.
+ var lastCharIdx = charsLeftInGroup[nextGroupIdx] - 1;
+
+ // If only one unprocessed character is left, pick it; otherwise,
+ // get a random character from the unused character list.
+ var nextCharIdx = lastCharIdx == 0 ? 0 : random.Next(0, lastCharIdx + 1);
+
+ // Add this character to the short-url.
+ shortUrl[i] = charGroups[nextGroupIdx][nextCharIdx];
+
+ // If we processed the last character in this group, start over.
+ if (lastCharIdx == 0)
+ {
+ charsLeftInGroup[nextGroupIdx] =
+ charGroups[nextGroupIdx].Length;
+ }
+ // There are more unprocessed characters left.
+ else
+ {
+ // Swap processed character with the last unprocessed character
+ // so that we don't pick it until we process all characters in
+ // this group.
+ if (lastCharIdx != nextCharIdx)
+ {
+ (charGroups[nextGroupIdx][lastCharIdx], charGroups[nextGroupIdx][nextCharIdx]) = (charGroups[nextGroupIdx][nextCharIdx], charGroups[nextGroupIdx][lastCharIdx]);
+ }
+
+ // Decrement the number of unprocessed characters in
+ // this group.
+ charsLeftInGroup[nextGroupIdx]--;
+ }
+
+ // If we processed the last group, start all over.
+ if (lastLeftGroupsOrderIdx == 0)
+ {
+ lastLeftGroupsOrderIdx = leftGroupsOrder.Length - 1;
+ }
+ // There are more unprocessed groups left.
+ else
+ {
+ // Swap processed group with the last unprocessed group
+ // so that we don't pick it until we process all groups.
+ if (lastLeftGroupsOrderIdx != nextLeftGroupsOrderIdx)
+ {
+ (leftGroupsOrder[lastLeftGroupsOrderIdx], leftGroupsOrder[nextLeftGroupsOrderIdx]) = (leftGroupsOrder[nextLeftGroupsOrderIdx], leftGroupsOrder[lastLeftGroupsOrderIdx]);
+ }
+
+ // Decrement the number of unprocessed groups.
+ lastLeftGroupsOrderIdx--;
+ }
+ }
+
+ // Convert password characters into a string and return the result.
+ return new string(shortUrl);
+ }
+
+ ///
+ /// Username generator
+ ///
+ /// The options.
+ ///
+ ///
+ public static string GenerateUsername(StringOptions options = null)
+ {
+ options ??= new StringOptions
+ {
+ RequiredLength = 10,
+ RequireDigit = true,
+ RequireLowercase = true,
+ RequireUppercase = true,
+ RequiredUniqueChars = 4,
+ RequireNonLetterOrDigit = false,
+ RequireNonAlphanumeric = false
+ };
+ return GenerateRandomString(options);
+ }
+
+ ///
+ /// Password generator
+ ///
+ /// The options.
+ ///
+ ///
+ public static string GeneratePassword(StringOptions options = null)
+ {
+ options ??= new StringOptions
+ {
+ RequiredLength = 10,
+ RequireDigit = true,
+ RequireLowercase = true,
+ RequireUppercase = true,
+ RequiredUniqueChars = 4,
+ RequireNonLetterOrDigit = true,
+ RequireNonAlphanumeric = true
+ };
+ return GenerateRandomString(options);
+ }
+
+ ///
+ /// Random string generator with length
+ ///
+ /// The length.
+ ///
+ public static string GenerateRandomText(int length)
+ {
+ const string consonants = "bcdfghjklmnprstvxzBDFGHJKLMNPRSTVXZ";
+ const string vowels = "aeiouyAEIOUY";
+
+ var rndString = "";
+ var randomNum = RandomSeed();
+
+ while (rndString.Length < length)
+ {
+ rndString += consonants[randomNum.Next(consonants.Length)];
+ if (rndString.Length < length)
+ rndString += vowels[randomNum.Next(vowels.Length)];
+ }
+
+ return rndString;
+ }
+
+ ///
+ /// Random string generator - string options
+ ///
+ /// The options.
+ ///
+ public static string GenerateRandomString(StringOptions options = null)
+ {
+ options ??= new StringOptions
+ {
+ RequiredLength = 10,
+ RequireDigit = true,
+ RequireLowercase = true,
+ RequireUppercase = true,
+ RequiredUniqueChars = 4,
+ RequireNonLetterOrDigit = true,
+ RequireNonAlphanumeric = true
+ };
+
+ var randomChars = new[]
+ {
+ "ABCDEFGHJKLMNOPQRSTUVWXYZ", // uppercase
+ "abcdefghijkmnopqrstuvwxyz", // lowercase
+ "0123456789", // digits
+ "!@$?_-" // non-alphanumeric
+ };
+
+ // Using our private randomizer
+ var rand = RandomSeed();
+
+ var chars = new List();
+
+ 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)]);
+
+ var rcs = randomChars[rand.Next(0, randomChars.Length)];
+ for (var i = chars.Count;
+ i < options.RequiredLength
+ || chars.Distinct().Count() < options.RequiredUniqueChars;
+ i++)
+ chars.Insert(rand.Next(0, chars.Count),
+ rcs[rand.Next(0, rcs.Length)]);
+
+ return new string(chars.ToArray());
+ }
+
+ ///
+ /// Randomize random using RNGCrypto
+ ///
+ ///
+ /// derived from https://sourceforge.net/projects/shorturl-dotnet/
+ ///
+ public static Random RandomSeed()
+ {
+ // As the default Random is based on the current time
+ // so it produces the same "random" number within a second
+ // Use a crypto service to create the seed value
+
+ // 4-byte array to fill with random bytes
+ var randomBytes = new byte[4];
+
+ // Generate 4 random bytes.
+ using (var rng = new RNGCryptoServiceProvider())
+ {
+ rng.GetBytes(randomBytes);
+ }
+
+ // Convert 4 bytes into a 32-bit integer value.
+ var seed = ((randomBytes[0] & 0x7f) << 24) |
+ (randomBytes[1] << 16) |
+ (randomBytes[2] << 8) |
+ randomBytes[3];
+
+ // Return a truly randomized random generator
+ return new Random(seed);
+ }
+ }
}
\ No newline at end of file
diff --git a/GuidGenerator.cs b/GuidGenerator.cs
index 85a7bbf..6808e8f 100644
--- a/GuidGenerator.cs
+++ b/GuidGenerator.cs
@@ -1,251 +1,251 @@
-using System;
-using System.Text;
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Used for generating UUID based on RFC 4122.
- ///
- /// RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace
- public static class GuidGenerator
- {
-
- ///
- /// number of bytes in guid
- ///
- public const int ByteArraySize = 16;
-
- ///
- /// multiplex variant info - variant byte
- ///
- public const int VariantByte = 8;
-
- ///
- /// multiplex variant info - variant byte mask
- ///
- public const int VariantByteMask = 0x3f;
-
- ///
- /// multiplex variant info - variant byte shift
- ///
- public const int VariantByteShift = 0x80;
-
- ///
- /// multiplex version info - version byte
- ///
- public const int VersionByte = 7;
-
- ///
- /// multiplex version info - version byte mask
- ///
- public const int VersionByteMask = 0x0f;
-
- ///
- /// multiplex version info version byte shift
- ///
- public const int VersionByteShift = 4;
-
- // indexes within the uuid array for certain boundaries
- private const byte TimestampByte = 0;
- private const byte GuidClockSequenceByte = 8;
- private const byte NodeByte = 10;
-
- // offset to move from 1/1/0001, which is 0-time for .NET, to gregorian 0-time of 10/15/1582
- private static readonly DateTimeOffset GregorianCalendarStart = new(1582, 10, 15, 0, 0, 0, TimeSpan.Zero);
-
-
- ///
- /// Default clock sequence
- ///
- public static byte[] DefaultClockSequence { get; set; }
- ///
- /// Default node
- ///
- public static byte[] DefaultNode { get; set; }
-
- static GuidGenerator()
- {
- DefaultClockSequence = new byte[2];
- DefaultNode = new byte[6];
-
- var random = new Random();
- random.NextBytes(DefaultClockSequence);
- random.NextBytes(DefaultNode);
- }
-
- ///
- /// Set default node
- ///
- ///
- public static void SetDefaultNode(string nodeName)
- {
- var x = nodeName.GetHashCode();
- var node = $"{x:X}";
- DefaultNode = Encoding.UTF8.GetBytes(node.ToCharArray(), 0, 6);
- }
-
- ///
- /// Get version
- ///
- ///
- ///
- public static GuidVersion GetVersion(this Guid guid)
- {
- var bytes = guid.ToByteArray();
- return (GuidVersion)((bytes[VersionByte] & 0xFF) >> VersionByteShift);
- }
-
- ///
- /// Get date time offset from guid
- ///
- ///
- ///
- public static DateTimeOffset GetDateTimeOffset(Guid guid)
- {
- var bytes = guid.ToByteArray();
-
- // reverse the version
- bytes[VersionByte] &= VersionByteMask;
- bytes[VersionByte] |= (byte)GuidVersion.TimeBased >> VersionByteShift;
-
- var timestampBytes = new byte[8];
- Array.Copy(bytes, TimestampByte, timestampBytes, 0, 8);
-
- var timestamp = BitConverter.ToInt64(timestampBytes, 0);
- var ticks = timestamp + GregorianCalendarStart.Ticks;
-
- return new DateTimeOffset(ticks, TimeSpan.Zero);
- }
-
- ///
- /// get date time from guid
- ///
- ///
- ///
- public static DateTime GetDateTime(Guid guid)
- {
- return GetDateTimeOffset(guid).DateTime;
- }
-
- ///
- /// get local date time from guid
- ///
- ///
- ///
- public static DateTime GetLocalDateTime(Guid guid)
- {
- return GetDateTimeOffset(guid).LocalDateTime;
- }
-
- ///
- /// get utc date time from guid
- ///
- ///
- ///
- public static DateTime GetUtcDateTime(Guid guid)
- {
- return GetDateTimeOffset(guid).UtcDateTime;
- }
-
- ///
- /// Generate time based guid
- ///
- ///
- public static Guid GenerateTimeBasedGuid()
- {
- return GenerateTimeBasedGuid(DateTimeOffset.UtcNow, DefaultClockSequence, DefaultNode);
- }
-
- ///
- /// Generate time based guid providing a NodeName string
- ///
- ///
- ///
- public static Guid GenerateTimeBasedGuid(string nodeName)
- {
- var x = nodeName.GetHashCode();
- var node = $"{x:X}";
- var defaultNode = Encoding.UTF8.GetBytes(node.ToCharArray(), 0, 6);
- return GenerateTimeBasedGuid(DateTimeOffset.UtcNow, DefaultClockSequence, defaultNode);
- }
-
- ///
- /// Generate time based guid providing a valid DateTime object
- ///
- ///
- ///
- public static Guid GenerateTimeBasedGuid(DateTime dateTime)
- {
- return GenerateTimeBasedGuid(dateTime, DefaultClockSequence, DefaultNode);
- }
-
- ///
- /// Generate time base guid providing a valid DateTimeOffset object
- ///
- ///
- ///
- public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime)
- {
- return GenerateTimeBasedGuid(dateTime, DefaultClockSequence, DefaultNode);
- }
-
- ///
- /// Generate time based guid providing a date time, byte array for clock sequence and node
- ///
- ///
- ///
- ///
- ///
- public static Guid GenerateTimeBasedGuid(DateTime dateTime, byte[] clockSequence, byte[] node)
- {
- return GenerateTimeBasedGuid(new DateTimeOffset(dateTime), clockSequence, node);
- }
-
- ///
- /// Generate time based guid providing a valid DateTimeOffset Object and byte arrays for clock sequence and node
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime, byte[] clockSequence, byte[] node)
- {
- if (clockSequence == null)
- throw new ArgumentNullException(nameof(clockSequence));
-
- if (node == null)
- throw new ArgumentNullException(nameof(node));
-
- if (clockSequence.Length != 2)
- throw new ArgumentOutOfRangeException(nameof(clockSequence), "The clockSequence must be 2 bytes.");
-
- if (node.Length != 6)
- throw new ArgumentOutOfRangeException(nameof(node), "The node must be 6 bytes.");
-
- var ticks = (dateTime - GregorianCalendarStart).Ticks;
- var guid = new byte[ByteArraySize];
- var timestamp = BitConverter.GetBytes(ticks);
-
- // copy node
- Array.Copy(node, 0, guid, NodeByte, Math.Min(6, node.Length));
-
- // copy clock sequence
- Array.Copy(clockSequence, 0, guid, GuidClockSequenceByte, Math.Min(2, clockSequence.Length));
-
- // copy timestamp
- Array.Copy(timestamp, 0, guid, TimestampByte, Math.Min(8, timestamp.Length));
-
- // set the variant
- guid[VariantByte] &= VariantByteMask;
- guid[VariantByte] |= VariantByteShift;
-
- // set the version
- guid[VersionByte] &= VersionByteMask;
- guid[VersionByte] |= (byte)GuidVersion.TimeBased << VersionByteShift;
-
- return new Guid(guid);
- }
- }
-}
+using System;
+using System.Text;
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Used for generating UUID based on RFC 4122.
+ ///
+ /// RFC 4122 - A Universally Unique IDentifier (UUID) URN Namespace
+ public static class GuidGenerator
+ {
+
+ ///
+ /// number of bytes in guid
+ ///
+ public const int ByteArraySize = 16;
+
+ ///
+ /// multiplex variant info - variant byte
+ ///
+ public const int VariantByte = 8;
+
+ ///
+ /// multiplex variant info - variant byte mask
+ ///
+ public const int VariantByteMask = 0x3f;
+
+ ///
+ /// multiplex variant info - variant byte shift
+ ///
+ public const int VariantByteShift = 0x80;
+
+ ///
+ /// multiplex version info - version byte
+ ///
+ public const int VersionByte = 7;
+
+ ///
+ /// multiplex version info - version byte mask
+ ///
+ public const int VersionByteMask = 0x0f;
+
+ ///
+ /// multiplex version info version byte shift
+ ///
+ public const int VersionByteShift = 4;
+
+ // indexes within the uuid array for certain boundaries
+ private const byte TimestampByte = 0;
+ private const byte GuidClockSequenceByte = 8;
+ private const byte NodeByte = 10;
+
+ // offset to move from 1/1/0001, which is 0-time for .NET, to gregorian 0-time of 10/15/1582
+ private static readonly DateTimeOffset GregorianCalendarStart = new(1582, 10, 15, 0, 0, 0, TimeSpan.Zero);
+
+
+ ///
+ /// Default clock sequence
+ ///
+ public static byte[] DefaultClockSequence { get; set; }
+ ///
+ /// Default node
+ ///
+ public static byte[] DefaultNode { get; set; }
+
+ static GuidGenerator()
+ {
+ DefaultClockSequence = new byte[2];
+ DefaultNode = new byte[6];
+
+ var random = new Random();
+ random.NextBytes(DefaultClockSequence);
+ random.NextBytes(DefaultNode);
+ }
+
+ ///
+ /// Set default node
+ ///
+ ///
+ public static void SetDefaultNode(string nodeName)
+ {
+ var x = nodeName.GetHashCode();
+ var node = $"{x:X}";
+ DefaultNode = Encoding.UTF8.GetBytes(node.ToCharArray(), 0, 6);
+ }
+
+ ///
+ /// Get version
+ ///
+ ///
+ ///
+ public static GuidVersion GetVersion(this Guid guid)
+ {
+ var bytes = guid.ToByteArray();
+ return (GuidVersion)((bytes[VersionByte] & 0xFF) >> VersionByteShift);
+ }
+
+ ///
+ /// Get date time offset from guid
+ ///
+ ///
+ ///
+ public static DateTimeOffset GetDateTimeOffset(Guid guid)
+ {
+ var bytes = guid.ToByteArray();
+
+ // reverse the version
+ bytes[VersionByte] &= VersionByteMask;
+ bytes[VersionByte] |= (byte)GuidVersion.TimeBased >> VersionByteShift;
+
+ var timestampBytes = new byte[8];
+ Array.Copy(bytes, TimestampByte, timestampBytes, 0, 8);
+
+ var timestamp = BitConverter.ToInt64(timestampBytes, 0);
+ var ticks = timestamp + GregorianCalendarStart.Ticks;
+
+ return new DateTimeOffset(ticks, TimeSpan.Zero);
+ }
+
+ ///
+ /// get date time from guid
+ ///
+ ///
+ ///
+ public static DateTime GetDateTime(Guid guid)
+ {
+ return GetDateTimeOffset(guid).DateTime;
+ }
+
+ ///
+ /// get local date time from guid
+ ///
+ ///
+ ///
+ public static DateTime GetLocalDateTime(Guid guid)
+ {
+ return GetDateTimeOffset(guid).LocalDateTime;
+ }
+
+ ///
+ /// get utc date time from guid
+ ///
+ ///
+ ///
+ public static DateTime GetUtcDateTime(Guid guid)
+ {
+ return GetDateTimeOffset(guid).UtcDateTime;
+ }
+
+ ///
+ /// Generate time based guid
+ ///
+ ///
+ public static Guid GenerateTimeBasedGuid()
+ {
+ return GenerateTimeBasedGuid(DateTimeOffset.UtcNow, DefaultClockSequence, DefaultNode);
+ }
+
+ ///
+ /// Generate time based guid providing a NodeName string
+ ///
+ ///
+ ///
+ public static Guid GenerateTimeBasedGuid(string nodeName)
+ {
+ var x = nodeName.GetHashCode();
+ var node = $"{x:X}";
+ var defaultNode = Encoding.UTF8.GetBytes(node.ToCharArray(), 0, 6);
+ return GenerateTimeBasedGuid(DateTimeOffset.UtcNow, DefaultClockSequence, defaultNode);
+ }
+
+ ///
+ /// Generate time based guid providing a valid DateTime object
+ ///
+ ///
+ ///
+ public static Guid GenerateTimeBasedGuid(DateTime dateTime)
+ {
+ return GenerateTimeBasedGuid(dateTime, DefaultClockSequence, DefaultNode);
+ }
+
+ ///
+ /// Generate time base guid providing a valid DateTimeOffset object
+ ///
+ ///
+ ///
+ public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime)
+ {
+ return GenerateTimeBasedGuid(dateTime, DefaultClockSequence, DefaultNode);
+ }
+
+ ///
+ /// Generate time based guid providing a date time, byte array for clock sequence and node
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Guid GenerateTimeBasedGuid(DateTime dateTime, byte[] clockSequence, byte[] node)
+ {
+ return GenerateTimeBasedGuid(new DateTimeOffset(dateTime), clockSequence, node);
+ }
+
+ ///
+ /// Generate time based guid providing a valid DateTimeOffset Object and byte arrays for clock sequence and node
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static Guid GenerateTimeBasedGuid(DateTimeOffset dateTime, byte[] clockSequence, byte[] node)
+ {
+ if (clockSequence == null)
+ throw new ArgumentNullException(nameof(clockSequence));
+
+ if (node == null)
+ throw new ArgumentNullException(nameof(node));
+
+ if (clockSequence.Length != 2)
+ throw new ArgumentOutOfRangeException(nameof(clockSequence), "The clockSequence must be 2 bytes.");
+
+ if (node.Length != 6)
+ throw new ArgumentOutOfRangeException(nameof(node), "The node must be 6 bytes.");
+
+ var ticks = (dateTime - GregorianCalendarStart).Ticks;
+ var guid = new byte[ByteArraySize];
+ var timestamp = BitConverter.GetBytes(ticks);
+
+ // copy node
+ Array.Copy(node, 0, guid, NodeByte, Math.Min(6, node.Length));
+
+ // copy clock sequence
+ Array.Copy(clockSequence, 0, guid, GuidClockSequenceByte, Math.Min(2, clockSequence.Length));
+
+ // copy timestamp
+ Array.Copy(timestamp, 0, guid, TimestampByte, Math.Min(8, timestamp.Length));
+
+ // set the variant
+ guid[VariantByte] &= VariantByteMask;
+ guid[VariantByte] |= VariantByteShift;
+
+ // set the version
+ guid[VersionByte] &= VersionByteMask;
+ guid[VersionByte] |= (byte)GuidVersion.TimeBased << VersionByteShift;
+
+ return new Guid(guid);
+ }
+ }
+}
diff --git a/GuidVersion.cs b/GuidVersion.cs
index b08869e..f9212ab 100644
--- a/GuidVersion.cs
+++ b/GuidVersion.cs
@@ -1,25 +1,25 @@
-namespace FCS.Lib.Utility
-{
- ///
- /// Guid Version Enum
- ///
- public enum GuidVersion
- {
- ///
- /// Time
- ///
- TimeBased = 0x01,
- ///
- /// Reserved
- ///
- Reserved = 0x02,
- ///
- /// Name
- ///
- NameBased = 0x03,
- ///
- /// Random
- ///
- Random = 0x04
- }
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Guid Version Enum
+ ///
+ public enum GuidVersion
+ {
+ ///
+ /// Time
+ ///
+ TimeBased = 0x01,
+ ///
+ /// Reserved
+ ///
+ Reserved = 0x02,
+ ///
+ /// Name
+ ///
+ NameBased = 0x03,
+ ///
+ /// Random
+ ///
+ Random = 0x04
+ }
}
\ No newline at end of file
diff --git a/IAsyncReadonlyRepo.cs b/IAsyncReadonlyRepo.cs
index ad34652..9b7b177 100644
--- a/IAsyncReadonlyRepo.cs
+++ b/IAsyncReadonlyRepo.cs
@@ -1,96 +1,96 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 03-10-2015
-//
-// Last Modified By : FH
-// Last Modified On : 02-24-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the Affero GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// Affero GNU General Public License for more details.
-//
-// You should have received a copy of the Affero GNU General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
-//
-//
-// ***********************************************************************
-
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Linq.Expressions;
-using System.Threading.Tasks;
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Interface IRepositoryAsync
- ///
- /// The type of the t entity.
- public interface IAsyncReadonlyRepo where TEntity : class
- {
- ///
- /// Alls this instance.
- ///
- /// IQueryable<TEntity>.
- IQueryable All();
-
- ///
- /// Alls the asynchronous.
- ///
- /// The predicate.
- /// Task<IList<TEntity>>.
- Task> AllAsync(Expression> predicate);
-
- ///
- /// Anies the asynchronous.
- ///
- /// The predicate.
- /// Task<System.Boolean>.
- Task AnyAsync(Expression> predicate);
-
- ///
- /// Finds the asynchronous.
- ///
- /// The predicate.
- /// Task<TEntity>.
- Task FindAsync(Expression> predicate);
-
- ///
- /// Firsts the asynchronous.
- ///
- /// The predicate.
- /// Task<TEntity>.
- Task FirstAsync(Expression> predicate);
-
- ///
- /// Firsts the or default asynchronous.
- ///
- /// The predicate.
- /// Task<TEntity>.
- Task FirstOrDefaultAsync(Expression> predicate);
-
- ///
- /// Anies the specified predicate.
- ///
- /// The predicate.
- /// true if XXXX, false otherwise.
- bool Any(Expression> predicate);
-
- ///
- /// Gets the by identifier.
- ///
- /// The identifier.
- /// TEntity.
- TEntity GetById(string id);
- }
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 03-10-2015
+//
+// Last Modified By : FH
+// Last Modified On : 02-24-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the Affero GNU General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// Affero GNU General Public License for more details.
+//
+// You should have received a copy of the Affero GNU General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
+//
+//
+// ***********************************************************************
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Interface IRepositoryAsync
+ ///
+ /// The type of the t entity.
+ public interface IAsyncReadonlyRepo where TEntity : class
+ {
+ ///
+ /// Alls this instance.
+ ///
+ /// IQueryable<TEntity>.
+ IQueryable All();
+
+ ///
+ /// Alls the asynchronous.
+ ///
+ /// The predicate.
+ /// Task<IList<TEntity>>.
+ Task> AllAsync(Expression> predicate);
+
+ ///
+ /// Anies the asynchronous.
+ ///
+ /// The predicate.
+ /// Task<System.Boolean>.
+ Task AnyAsync(Expression> predicate);
+
+ ///
+ /// Finds the asynchronous.
+ ///
+ /// The predicate.
+ /// Task<TEntity>.
+ Task FindAsync(Expression> predicate);
+
+ ///
+ /// Firsts the asynchronous.
+ ///
+ /// The predicate.
+ /// Task<TEntity>.
+ Task FirstAsync(Expression> predicate);
+
+ ///
+ /// Firsts the or default asynchronous.
+ ///
+ /// The predicate.
+ /// Task<TEntity>.
+ Task FirstOrDefaultAsync(Expression> predicate);
+
+ ///
+ /// Anies the specified predicate.
+ ///
+ /// The predicate.
+ /// true if XXXX, false otherwise.
+ bool Any(Expression> predicate);
+
+ ///
+ /// Gets the by identifier.
+ ///
+ /// The identifier.
+ /// TEntity.
+ TEntity GetById(string id);
+ }
}
\ No newline at end of file
diff --git a/IRepository.cs b/IRepository.cs
index 1f73c0c..275c4cb 100644
--- a/IRepository.cs
+++ b/IRepository.cs
@@ -1,61 +1,61 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 05-13-2020
-//
-// Last Modified By : FH
-// Last Modified On : 02-24-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the Affero GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// Affero GNU General Public License for more details.
-//
-// You should have received a copy of the Affero GNU General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
-//
-//
-// ***********************************************************************
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Interface IRepository
- ///
- ///
- /// The type of the TKey.
- public interface IRepository where T : class
- {
- ///
- /// Gets the specified identifier.
- ///
- /// The identifier.
- /// T.
- T GetById(TKey id);
-
- ///
- /// Creates the specified entity.
- ///
- /// The entity.
- void Create(T entity);
-
- ///
- /// Updates the specified entity.
- ///
- /// The entity.
- void Update(T entity);
-
- ///
- /// Deletes the specified identifier.
- ///
- /// The identifier.
- void Delete(TKey id);
- }
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 05-13-2020
+//
+// Last Modified By : FH
+// Last Modified On : 02-24-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the Affero GNU General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// Affero GNU General Public License for more details.
+//
+// You should have received a copy of the Affero GNU General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
+//
+//
+// ***********************************************************************
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Interface IRepository
+ ///
+ ///
+ /// The type of the TKey.
+ public interface IRepository where T : class
+ {
+ ///
+ /// Gets the specified identifier.
+ ///
+ /// The identifier.
+ /// T.
+ T GetById(TKey id);
+
+ ///
+ /// Creates the specified entity.
+ ///
+ /// The entity.
+ void Create(T entity);
+
+ ///
+ /// Updates the specified entity.
+ ///
+ /// The entity.
+ void Update(T entity);
+
+ ///
+ /// Deletes the specified identifier.
+ ///
+ /// The identifier.
+ void Delete(TKey id);
+ }
}
\ No newline at end of file
diff --git a/IRepositoryEx.cs b/IRepositoryEx.cs
index 7a6ad06..e310e5b 100644
--- a/IRepositoryEx.cs
+++ b/IRepositoryEx.cs
@@ -1,127 +1,127 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 03-10-2015
-//
-// Last Modified By : FH
-// Last Modified On : 02-24-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the Affero GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// Affero GNU General Public License for more details.
-//
-// You should have received a copy of the Affero GNU General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
-//
-//
-// ***********************************************************************
-
-using System;
-using System.Linq;
-using System.Linq.Expressions;
-using System.Threading.Tasks;
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Interface IRepositoryEx
- ///
- /// The type of the t entity
- public interface IRepositoryEx where TEntity : class
- {
- ///
- /// Get all entities synchronous
- ///
- /// Predicate
- /// Task<System.Boolean>
- Task AnyAsync(Expression> predicate);
-
- ///
- /// Find matching entity asynchronous
- ///
- /// Predicate
- /// Task<TEntity>
- Task FindAsync(Expression> predicate);
-
- ///
- /// Find first matching entity asynchronous
- ///
- /// Predicate
- /// Task<TEntity>
- Task FirstAsync(Expression> predicate);
-
- ///
- /// Get first entity matching query or default entity asynchronous
- ///
- /// Predicate
- /// Task<TEntity>
- Task FirstOrDefaultAsync(Expression> predicate);
-
- ///
- /// Add an entity
- ///
- /// The entity.
- void Add(TEntity entity);
-
- ///
- /// Attach the entity
- ///
- /// The entity.
- void Attach(TEntity entity);
-
- ///
- /// Delete the entity
- ///
- /// The entity.
- void Delete(TEntity entity);
-
- ///
- /// Anies the specified predicate.
- ///
- /// The predicate.
- /// true if XXXX, false otherwise.
- bool Any(Expression> predicate);
-
- ///
- /// Get entity by id
- ///
- /// The identifier.
- /// TEntity
- TEntity GetById(string id);
-
- ///
- /// Find first entity matching query
- ///
- /// Predicate
- /// TEntity
- TEntity First(Expression> predicate);
-
- ///
- /// Find first matching entity or default entity
- ///
- /// Predicate
- /// TEntity
- TEntity FirstOrDefault(Expression> predicate);
-
- ///
- /// Find all matching entities matching query
- ///
- /// Predicate
- /// IQueryable<TEntity>
- IQueryable Find(Expression> predicate);
-
- ///
- /// Get all entities
- ///
- /// IQueryable<TEntity>
- IQueryable All();
- }
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 03-10-2015
+//
+// Last Modified By : FH
+// Last Modified On : 02-24-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the Affero GNU General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// Affero GNU General Public License for more details.
+//
+// You should have received a copy of the Affero GNU General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
+//
+//
+// ***********************************************************************
+
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Threading.Tasks;
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Interface IRepositoryEx
+ ///
+ /// The type of the t entity
+ public interface IRepositoryEx where TEntity : class
+ {
+ ///
+ /// Get all entities synchronous
+ ///
+ /// Predicate
+ /// Task<System.Boolean>
+ Task AnyAsync(Expression> predicate);
+
+ ///
+ /// Find matching entity asynchronous
+ ///
+ /// Predicate
+ /// Task<TEntity>
+ Task FindAsync(Expression> predicate);
+
+ ///
+ /// Find first matching entity asynchronous
+ ///
+ /// Predicate
+ /// Task<TEntity>
+ Task FirstAsync(Expression> predicate);
+
+ ///
+ /// Get first entity matching query or default entity asynchronous
+ ///
+ /// Predicate
+ /// Task<TEntity>
+ Task FirstOrDefaultAsync(Expression> predicate);
+
+ ///
+ /// Add an entity
+ ///
+ /// The entity.
+ void Add(TEntity entity);
+
+ ///
+ /// Attach the entity
+ ///
+ /// The entity.
+ void Attach(TEntity entity);
+
+ ///
+ /// Delete the entity
+ ///
+ /// The entity.
+ void Delete(TEntity entity);
+
+ ///
+ /// Anies the specified predicate.
+ ///
+ /// The predicate.
+ /// true if XXXX, false otherwise.
+ bool Any(Expression> predicate);
+
+ ///
+ /// Get entity by id
+ ///
+ /// The identifier.
+ /// TEntity
+ TEntity GetById(string id);
+
+ ///
+ /// Find first entity matching query
+ ///
+ /// Predicate
+ /// TEntity
+ TEntity First(Expression> predicate);
+
+ ///
+ /// Find first matching entity or default entity
+ ///
+ /// Predicate
+ /// TEntity
+ TEntity FirstOrDefault(Expression> predicate);
+
+ ///
+ /// Find all matching entities matching query
+ ///
+ /// Predicate
+ /// IQueryable<TEntity>
+ IQueryable Find(Expression> predicate);
+
+ ///
+ /// Get all entities
+ ///
+ /// IQueryable<TEntity>
+ IQueryable All();
+ }
}
\ No newline at end of file
diff --git a/LICENSE b/LICENSE
index 2e22840..f51b3dd 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,660 +1,660 @@
-### Affero GNU GENERAL PUBLIC LICENSE
-
-Version 3, 19 November 2007
-
-Copyright (C) 2007 Free Software Foundation, Inc.
-
-
-Everyone is permitted to copy and distribute verbatim copies of this
-license document, but changing it is not allowed.
-
-### Preamble
-
-The Affero GNU General Public License is a free, copyleft license for
-software and other kinds of works, specifically designed to ensure
-cooperation with the community in the case of network server software.
-
-The licenses for most software and other practical works are designed
-to take away your freedom to share and change the works. By contrast,
-our General Public Licenses are intended to guarantee your freedom to
-share and change all versions of a program--to make sure it remains
-free software for all its users.
-
-When we speak of free software, we are referring to freedom, not
-price. Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-them if you wish), that you receive source code or can get it if you
-want it, that you can change the software or use pieces of it in new
-free programs, and that you know you can do these things.
-
-Developers that use our General Public Licenses protect your rights
-with two steps: (1) assert copyright on the software, and (2) offer
-you this License which gives you legal permission to copy, distribute
-and/or modify the software.
-
-A secondary benefit of defending all users' freedom is that
-improvements made in alternate versions of the program, if they
-receive widespread use, become available for other developers to
-incorporate. Many developers of free software are heartened and
-encouraged by the resulting cooperation. However, in the case of
-software used on network servers, this result may fail to come about.
-The GNU General Public License permits making a modified version and
-letting the public access it on a server without ever releasing its
-source code to the public.
-
-The Affero GNU General Public License is designed specifically to
-ensure that, in such cases, the modified source code becomes available
-to the community. It requires the operator of a network server to
-provide the source code of the modified version running there to the
-users of that server. Therefore, public use of a modified version, on
-a publicly accessible server, gives the public access to the source
-code of the modified version.
-
-An older license, called the Affero General Public License and
-published by Affero, was designed to accomplish similar goals. This is
-a different license, not a version of the Affero GPL, but Affero has
-released a new version of the Affero GPL which permits relicensing
-under this license.
-
-The precise terms and conditions for copying, distribution and
-modification follow.
-
-### TERMS AND CONDITIONS
-
-#### 0. Definitions.
-
-"This License" refers to version 3 of the Affero GNU General Public
-License.
-
-"Copyright" also means copyright-like laws that apply to other kinds
-of works, such as semiconductor masks.
-
-"The Program" refers to any copyrightable work licensed under this
-License. Each licensee is addressed as "you". "Licensees" and
-"recipients" may be individuals or organizations.
-
-To "modify" a work means to copy from or adapt all or part of the work
-in a fashion requiring copyright permission, other than the making of
-an exact copy. The resulting work is called a "modified version" of
-the earlier work or a work "based on" the earlier work.
-
-A "covered work" means either the unmodified Program or a work based
-on the Program.
-
-To "propagate" a work means to do anything with it that, without
-permission, would make you directly or secondarily liable for
-infringement under applicable copyright law, except executing it on a
-computer or modifying a private copy. Propagation includes copying,
-distribution (with or without modification), making available to the
-public, and in some countries other activities as well.
-
-To "convey" a work means any kind of propagation that enables other
-parties to make or receive copies. Mere interaction with a user
-through a computer network, with no transfer of a copy, is not
-conveying.
-
-An interactive user interface displays "Appropriate Legal Notices" to
-the extent that it includes a convenient and prominently visible
-feature that (1) displays an appropriate copyright notice, and (2)
-tells the user that there is no warranty for the work (except to the
-extent that warranties are provided), that licensees may convey the
-work under this License, and how to view a copy of this License. If
-the interface presents a list of user commands or options, such as a
-menu, a prominent item in the list meets this criterion.
-
-#### 1. Source Code.
-
-The "source code" for a work means the preferred form of the work for
-making modifications to it. "Object code" means any non-source form of
-a work.
-
-A "Standard Interface" means an interface that either is an official
-standard defined by a recognized standards body, or, in the case of
-interfaces specified for a particular programming language, one that
-is widely used among developers working in that language.
-
-The "System Libraries" of an executable work include anything, other
-than the work as a whole, that (a) is included in the normal form of
-packaging a Major Component, but which is not part of that Major
-Component, and (b) serves only to enable use of the work with that
-Major Component, or to implement a Standard Interface for which an
-implementation is available to the public in source code form. A
-"Major Component", in this context, means a major essential component
-(kernel, window system, and so on) of the specific operating system
-(if any) on which the executable work runs, or a compiler used to
-produce the work, or an object code interpreter used to run it.
-
-The "Corresponding Source" for a work in object code form means all
-the source code needed to generate, install, and (for an executable
-work) run the object code and to modify the work, including scripts to
-control those activities. However, it does not include the work's
-System Libraries, or general-purpose tools or generally available free
-programs which are used unmodified in performing those activities but
-which are not part of the work. For example, Corresponding Source
-includes interface definition files associated with source files for
-the work, and the source code for shared libraries and dynamically
-linked subprograms that the work is specifically designed to require,
-such as by intimate data communication or control flow between those
-subprograms and other parts of the work.
-
-The Corresponding Source need not include anything that users can
-regenerate automatically from other parts of the Corresponding Source.
-
-The Corresponding Source for a work in source code form is that same
-work.
-
-#### 2. Basic Permissions.
-
-All rights granted under this License are granted for the term of
-copyright on the Program, and are irrevocable provided the stated
-conditions are met. This License explicitly affirms your unlimited
-permission to run the unmodified Program. The output from running a
-covered work is covered by this License only if the output, given its
-content, constitutes a covered work. This License acknowledges your
-rights of fair use or other equivalent, as provided by copyright law.
-
-You may make, run and propagate covered works that you do not convey,
-without conditions so long as your license otherwise remains in force.
-You may convey covered works to others for the sole purpose of having
-them make modifications exclusively for you, or provide you with
-facilities for running those works, provided that you comply with the
-terms of this License in conveying all material for which you do not
-control copyright. Those thus making or running the covered works for
-you must do so exclusively on your behalf, under your direction and
-control, on terms that prohibit them from making any copies of your
-copyrighted material outside their relationship with you.
-
-Conveying under any other circumstances is permitted solely under the
-conditions stated below. Sublicensing is not allowed; section 10 makes
-it unnecessary.
-
-#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
-
-No covered work shall be deemed part of an effective technological
-measure under any applicable law fulfilling obligations under article
-11 of the WIPO copyright treaty adopted on 20 December 1996, or
-similar laws prohibiting or restricting circumvention of such
-measures.
-
-When you convey a covered work, you waive any legal power to forbid
-circumvention of technological measures to the extent such
-circumvention is effected by exercising rights under this License with
-respect to the covered work, and you disclaim any intention to limit
-operation or modification of the work as a means of enforcing, against
-the work's users, your or third parties' legal rights to forbid
-circumvention of technological measures.
-
-#### 4. Conveying Verbatim Copies.
-
-You may convey verbatim copies of the Program's source code as you
-receive it, in any medium, provided that you conspicuously and
-appropriately publish on each copy an appropriate copyright notice;
-keep intact all notices stating that this License and any
-non-permissive terms added in accord with section 7 apply to the code;
-keep intact all notices of the absence of any warranty; and give all
-recipients a copy of this License along with the Program.
-
-You may charge any price or no price for each copy that you convey,
-and you may offer support or warranty protection for a fee.
-
-#### 5. Conveying Modified Source Versions.
-
-You may convey a work based on the Program, or the modifications to
-produce it from the Program, in the form of source code under the
-terms of section 4, provided that you also meet all of these
-conditions:
-
-- a) The work must carry prominent notices stating that you modified
- it, and giving a relevant date.
-- b) The work must carry prominent notices stating that it is
- released under this License and any conditions added under
- section 7. This requirement modifies the requirement in section 4
- to "keep intact all notices".
-- c) You must license the entire work, as a whole, under this
- License to anyone who comes into possession of a copy. This
- License will therefore apply, along with any applicable section 7
- additional terms, to the whole of the work, and all its parts,
- regardless of how they are packaged. This License gives no
- permission to license the work in any other way, but it does not
- invalidate such permission if you have separately received it.
-- d) If the work has interactive user interfaces, each must display
- Appropriate Legal Notices; however, if the Program has interactive
- interfaces that do not display Appropriate Legal Notices, your
- work need not make them do so.
-
-A compilation of a covered work with other separate and independent
-works, which are not by their nature extensions of the covered work,
-and which are not combined with it such as to form a larger program,
-in or on a volume of a storage or distribution medium, is called an
-"aggregate" if the compilation and its resulting copyright are not
-used to limit the access or legal rights of the compilation's users
-beyond what the individual works permit. Inclusion of a covered work
-in an aggregate does not cause this License to apply to the other
-parts of the aggregate.
-
-#### 6. Conveying Non-Source Forms.
-
-You may convey a covered work in object code form under the terms of
-sections 4 and 5, provided that you also convey the machine-readable
-Corresponding Source under the terms of this License, in one of these
-ways:
-
-- a) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by the
- Corresponding Source fixed on a durable physical medium
- customarily used for software interchange.
-- b) Convey the object code in, or embodied in, a physical product
- (including a physical distribution medium), accompanied by a
- written offer, valid for at least three years and valid for as
- long as you offer spare parts or customer support for that product
- model, to give anyone who possesses the object code either (1) a
- copy of the Corresponding Source for all the software in the
- product that is covered by this License, on a durable physical
- medium customarily used for software interchange, for a price no
- more than your reasonable cost of physically performing this
- conveying of source, or (2) access to copy the Corresponding
- Source from a network server at no charge.
-- c) Convey individual copies of the object code with a copy of the
- written offer to provide the Corresponding Source. This
- alternative is allowed only occasionally and noncommercially, and
- only if you received the object code with such an offer, in accord
- with subsection 6b.
-- d) Convey the object code by offering access from a designated
- place (gratis or for a charge), and offer equivalent access to the
- Corresponding Source in the same way through the same place at no
- further charge. You need not require recipients to copy the
- Corresponding Source along with the object code. If the place to
- copy the object code is a network server, the Corresponding Source
- may be on a different server (operated by you or a third party)
- that supports equivalent copying facilities, provided you maintain
- clear directions next to the object code saying where to find the
- Corresponding Source. Regardless of what server hosts the
- Corresponding Source, you remain obligated to ensure that it is
- available for as long as needed to satisfy these requirements.
-- e) Convey the object code using peer-to-peer transmission,
- provided you inform other peers where the object code and
- Corresponding Source of the work are being offered to the general
- public at no charge under subsection 6d.
-
-A separable portion of the object code, whose source code is excluded
-from the Corresponding Source as a System Library, need not be
-included in conveying the object code work.
-
-A "User Product" is either (1) a "consumer product", which means any
-tangible personal property which is normally used for personal,
-family, or household purposes, or (2) anything designed or sold for
-incorporation into a dwelling. In determining whether a product is a
-consumer product, doubtful cases shall be resolved in favor of
-coverage. For a particular product received by a particular user,
-"normally used" refers to a typical or common use of that class of
-product, regardless of the status of the particular user or of the way
-in which the particular user actually uses, or expects or is expected
-to use, the product. A product is a consumer product regardless of
-whether the product has substantial commercial, industrial or
-non-consumer uses, unless such uses represent the only significant
-mode of use of the product.
-
-"Installation Information" for a User Product means any methods,
-procedures, authorization keys, or other information required to
-install and execute modified versions of a covered work in that User
-Product from a modified version of its Corresponding Source. The
-information must suffice to ensure that the continued functioning of
-the modified object code is in no case prevented or interfered with
-solely because modification has been made.
-
-If you convey an object code work under this section in, or with, or
-specifically for use in, a User Product, and the conveying occurs as
-part of a transaction in which the right of possession and use of the
-User Product is transferred to the recipient in perpetuity or for a
-fixed term (regardless of how the transaction is characterized), the
-Corresponding Source conveyed under this section must be accompanied
-by the Installation Information. But this requirement does not apply
-if neither you nor any third party retains the ability to install
-modified object code on the User Product (for example, the work has
-been installed in ROM).
-
-The requirement to provide Installation Information does not include a
-requirement to continue to provide support service, warranty, or
-updates for a work that has been modified or installed by the
-recipient, or for the User Product in which it has been modified or
-installed. Access to a network may be denied when the modification
-itself materially and adversely affects the operation of the network
-or violates the rules and protocols for communication across the
-network.
-
-Corresponding Source conveyed, and Installation Information provided,
-in accord with this section must be in a format that is publicly
-documented (and with an implementation available to the public in
-source code form), and must require no special password or key for
-unpacking, reading or copying.
-
-#### 7. Additional Terms.
-
-"Additional permissions" are terms that supplement the terms of this
-License by making exceptions from one or more of its conditions.
-Additional permissions that are applicable to the entire Program shall
-be treated as though they were included in this License, to the extent
-that they are valid under applicable law. If additional permissions
-apply only to part of the Program, that part may be used separately
-under those permissions, but the entire Program remains governed by
-this License without regard to the additional permissions.
-
-When you convey a copy of a covered work, you may at your option
-remove any additional permissions from that copy, or from any part of
-it. (Additional permissions may be written to require their own
-removal in certain cases when you modify the work.) You may place
-additional permissions on material, added by you to a covered work,
-for which you have or can give appropriate copyright permission.
-
-Notwithstanding any other provision of this License, for material you
-add to a covered work, you may (if authorized by the copyright holders
-of that material) supplement the terms of this License with terms:
-
-- a) Disclaiming warranty or limiting liability differently from the
- terms of sections 15 and 16 of this License; or
-- b) Requiring preservation of specified reasonable legal notices or
- author attributions in that material or in the Appropriate Legal
- Notices displayed by works containing it; or
-- c) Prohibiting misrepresentation of the origin of that material,
- or requiring that modified versions of such material be marked in
- reasonable ways as different from the original version; or
-- d) Limiting the use for publicity purposes of names of licensors
- or authors of the material; or
-- e) Declining to grant rights under trademark law for use of some
- trade names, trademarks, or service marks; or
-- f) Requiring indemnification of licensors and authors of that
- material by anyone who conveys the material (or modified versions
- of it) with contractual assumptions of liability to the recipient,
- for any liability that these contractual assumptions directly
- impose on those licensors and authors.
-
-All other non-permissive additional terms are considered "further
-restrictions" within the meaning of section 10. If the Program as you
-received it, or any part of it, contains a notice stating that it is
-governed by this License along with a term that is a further
-restriction, you may remove that term. If a license document contains
-a further restriction but permits relicensing or conveying under this
-License, you may add to a covered work material governed by the terms
-of that license document, provided that the further restriction does
-not survive such relicensing or conveying.
-
-If you add terms to a covered work in accord with this section, you
-must place, in the relevant source files, a statement of the
-additional terms that apply to those files, or a notice indicating
-where to find the applicable terms.
-
-Additional terms, permissive or non-permissive, may be stated in the
-form of a separately written license, or stated as exceptions; the
-above requirements apply either way.
-
-#### 8. Termination.
-
-You may not propagate or modify a covered work except as expressly
-provided under this License. Any attempt otherwise to propagate or
-modify it is void, and will automatically terminate your rights under
-this License (including any patent licenses granted under the third
-paragraph of section 11).
-
-However, if you cease all violation of this License, then your license
-from a particular copyright holder is reinstated (a) provisionally,
-unless and until the copyright holder explicitly and finally
-terminates your license, and (b) permanently, if the copyright holder
-fails to notify you of the violation by some reasonable means prior to
-60 days after the cessation.
-
-Moreover, your license from a particular copyright holder is
-reinstated permanently if the copyright holder notifies you of the
-violation by some reasonable means, this is the first time you have
-received notice of violation of this License (for any work) from that
-copyright holder, and you cure the violation prior to 30 days after
-your receipt of the notice.
-
-Termination of your rights under this section does not terminate the
-licenses of parties who have received copies or rights from you under
-this License. If your rights have been terminated and not permanently
-reinstated, you do not qualify to receive new licenses for the same
-material under section 10.
-
-#### 9. Acceptance Not Required for Having Copies.
-
-You are not required to accept this License in order to receive or run
-a copy of the Program. Ancillary propagation of a covered work
-occurring solely as a consequence of using peer-to-peer transmission
-to receive a copy likewise does not require acceptance. However,
-nothing other than this License grants you permission to propagate or
-modify any covered work. These actions infringe copyright if you do
-not accept this License. Therefore, by modifying or propagating a
-covered work, you indicate your acceptance of this License to do so.
-
-#### 10. Automatic Licensing of Downstream Recipients.
-
-Each time you convey a covered work, the recipient automatically
-receives a license from the original licensors, to run, modify and
-propagate that work, subject to this License. You are not responsible
-for enforcing compliance by third parties with this License.
-
-An "entity transaction" is a transaction transferring control of an
-organization, or substantially all assets of one, or subdividing an
-organization, or merging organizations. If propagation of a covered
-work results from an entity transaction, each party to that
-transaction who receives a copy of the work also receives whatever
-licenses to the work the party's predecessor in interest had or could
-give under the previous paragraph, plus a right to possession of the
-Corresponding Source of the work from the predecessor in interest, if
-the predecessor has it or can get it with reasonable efforts.
-
-You may not impose any further restrictions on the exercise of the
-rights granted or affirmed under this License. For example, you may
-not impose a license fee, royalty, or other charge for exercise of
-rights granted under this License, and you may not initiate litigation
-(including a cross-claim or counterclaim in a lawsuit) alleging that
-any patent claim is infringed by making, using, selling, offering for
-sale, or importing the Program or any portion of it.
-
-#### 11. Patents.
-
-A "contributor" is a copyright holder who authorizes use under this
-License of the Program or a work on which the Program is based. The
-work thus licensed is called the contributor's "contributor version".
-
-A contributor's "essential patent claims" are all patent claims owned
-or controlled by the contributor, whether already acquired or
-hereafter acquired, that would be infringed by some manner, permitted
-by this License, of making, using, or selling its contributor version,
-but do not include claims that would be infringed only as a
-consequence of further modification of the contributor version. For
-purposes of this definition, "control" includes the right to grant
-patent sublicenses in a manner consistent with the requirements of
-this License.
-
-Each contributor grants you a non-exclusive, worldwide, royalty-free
-patent license under the contributor's essential patent claims, to
-make, use, sell, offer for sale, import and otherwise run, modify and
-propagate the contents of its contributor version.
-
-In the following three paragraphs, a "patent license" is any express
-agreement or commitment, however denominated, not to enforce a patent
-(such as an express permission to practice a patent or covenant not to
-sue for patent infringement). To "grant" such a patent license to a
-party means to make such an agreement or commitment not to enforce a
-patent against the party.
-
-If you convey a covered work, knowingly relying on a patent license,
-and the Corresponding Source of the work is not available for anyone
-to copy, free of charge and under the terms of this License, through a
-publicly available network server or other readily accessible means,
-then you must either (1) cause the Corresponding Source to be so
-available, or (2) arrange to deprive yourself of the benefit of the
-patent license for this particular work, or (3) arrange, in a manner
-consistent with the requirements of this License, to extend the patent
-license to downstream recipients. "Knowingly relying" means you have
-actual knowledge that, but for the patent license, your conveying the
-covered work in a country, or your recipient's use of the covered work
-in a country, would infringe one or more identifiable patents in that
-country that you have reason to believe are valid.
-
-If, pursuant to or in connection with a single transaction or
-arrangement, you convey, or propagate by procuring conveyance of, a
-covered work, and grant a patent license to some of the parties
-receiving the covered work authorizing them to use, propagate, modify
-or convey a specific copy of the covered work, then the patent license
-you grant is automatically extended to all recipients of the covered
-work and works based on it.
-
-A patent license is "discriminatory" if it does not include within the
-scope of its coverage, prohibits the exercise of, or is conditioned on
-the non-exercise of one or more of the rights that are specifically
-granted under this License. You may not convey a covered work if you
-are a party to an arrangement with a third party that is in the
-business of distributing software, under which you make payment to the
-third party based on the extent of your activity of conveying the
-work, and under which the third party grants, to any of the parties
-who would receive the covered work from you, a discriminatory patent
-license (a) in connection with copies of the covered work conveyed by
-you (or copies made from those copies), or (b) primarily for and in
-connection with specific products or compilations that contain the
-covered work, unless you entered into that arrangement, or that patent
-license was granted, prior to 28 March 2007.
-
-Nothing in this License shall be construed as excluding or limiting
-any implied license or other defenses to infringement that may
-otherwise be available to you under applicable patent law.
-
-#### 12. No Surrender of Others' Freedom.
-
-If conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License. If you cannot convey a
-covered work so as to satisfy simultaneously your obligations under
-this License and any other pertinent obligations, then as a
-consequence you may not convey it at all. For example, if you agree to
-terms that obligate you to collect a royalty for further conveying
-from those to whom you convey the Program, the only way you could
-satisfy both those terms and this License would be to refrain entirely
-from conveying the Program.
-
-#### 13. Remote Network Interaction; Use with the GNU General Public License.
-
-Notwithstanding any other provision of this License, if you modify the
-Program, your modified version must prominently offer all users
-interacting with it remotely through a computer network (if your
-version supports such interaction) an opportunity to receive the
-Corresponding Source of your version by providing access to the
-Corresponding Source from a network server at no charge, through some
-standard or customary means of facilitating copying of software. This
-Corresponding Source shall include the Corresponding Source for any
-work covered by version 3 of the GNU General Public License that is
-incorporated pursuant to the following paragraph.
-
-Notwithstanding any other provision of this License, you have
-permission to link or combine any covered work with a work licensed
-under version 3 of the GNU General Public License into a single
-combined work, and to convey the resulting work. The terms of this
-License will continue to apply to the part which is the covered work,
-but the work with which it is combined will remain governed by version
-3 of the GNU General Public License.
-
-#### 14. Revised Versions of this License.
-
-The Free Software Foundation may publish revised and/or new versions
-of the Affero GNU General Public License from time to time. Such new
-versions will be similar in spirit to the present version, but may
-differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number. If the Program
-specifies that a certain numbered version of the Affero GNU General
-Public License "or any later version" applies to it, you have the
-option of following the terms and conditions either of that numbered
-version or of any later version published by the Free Software
-Foundation. If the Program does not specify a version number of the
-Affero GNU General Public License, you may choose any version ever
-published by the Free Software Foundation.
-
-If the Program specifies that a proxy can decide which future versions
-of the Affero GNU General Public License can be used, that proxy's
-public statement of acceptance of a version permanently authorizes you
-to choose that version for the Program.
-
-Later license versions may give you additional or different
-permissions. However, no additional obligations are imposed on any
-author or copyright holder as a result of your choosing to follow a
-later version.
-
-#### 15. Disclaimer of Warranty.
-
-THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
-APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
-HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
-WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
-PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
-DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
-CORRECTION.
-
-#### 16. Limitation of Liability.
-
-IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
-WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
-CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
-INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
-ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
-NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
-LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
-TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
-PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-
-#### 17. Interpretation of Sections 15 and 16.
-
-If the disclaimer of warranty and limitation of liability provided
-above cannot be given local legal effect according to their terms,
-reviewing courts shall apply local law that most closely approximates
-an absolute waiver of all civil liability in connection with the
-Program, unless a warranty or assumption of liability accompanies a
-copy of the Program in return for a fee.
-
-END OF TERMS AND CONDITIONS
-
-### How to Apply These Terms to Your New Programs
-
-If you develop a new program, and you want it to be of the greatest
-possible use to the public, the best way to achieve this is to make it
-free software which everyone can redistribute and change under these
-terms.
-
-To do so, attach the following notices to the program. It is safest to
-attach them to the start of each source file to most effectively state
-the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-
- Copyright (C)
-
- This program is free software: you can redistribute it and/or modify
- it under the terms of the Affero GNU General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- Affero GNU General Public License for more details.
-
- You should have received a copy of the Affero GNU General Public License
- along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html].
-
-Also add information on how to contact you by electronic and paper
-mail.
-
-If your software can interact with users remotely through a computer
-network, you should also make sure that it provides a way for users to
-get its source. For example, if your program is a web application, its
-interface could display a "Source" link that leads users to an archive
-of the code. There are many ways you could offer source, and different
-solutions will be better for different programs; see section 13 for
-the specific requirements.
-
-You should also get your employer (if you work as a programmer) or
-school, if any, to sign a "copyright disclaimer" for the program, if
-necessary. For more information on this, and how to apply and follow
-the GNU AGPL, see [https://www.gnu.org/licenses/agpl-3.0.en.html].
+### Affero GNU GENERAL PUBLIC LICENSE
+
+Version 3, 19 November 2007
+
+Copyright (C) 2007 Free Software Foundation, Inc.
+
+
+Everyone is permitted to copy and distribute verbatim copies of this
+license document, but changing it is not allowed.
+
+### Preamble
+
+The Affero GNU General Public License is a free, copyleft license for
+software and other kinds of works, specifically designed to ensure
+cooperation with the community in the case of network server software.
+
+The licenses for most software and other practical works are designed
+to take away your freedom to share and change the works. By contrast,
+our General Public Licenses are intended to guarantee your freedom to
+share and change all versions of a program--to make sure it remains
+free software for all its users.
+
+When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+them if you wish), that you receive source code or can get it if you
+want it, that you can change the software or use pieces of it in new
+free programs, and that you know you can do these things.
+
+Developers that use our General Public Licenses protect your rights
+with two steps: (1) assert copyright on the software, and (2) offer
+you this License which gives you legal permission to copy, distribute
+and/or modify the software.
+
+A secondary benefit of defending all users' freedom is that
+improvements made in alternate versions of the program, if they
+receive widespread use, become available for other developers to
+incorporate. Many developers of free software are heartened and
+encouraged by the resulting cooperation. However, in the case of
+software used on network servers, this result may fail to come about.
+The GNU General Public License permits making a modified version and
+letting the public access it on a server without ever releasing its
+source code to the public.
+
+The Affero GNU General Public License is designed specifically to
+ensure that, in such cases, the modified source code becomes available
+to the community. It requires the operator of a network server to
+provide the source code of the modified version running there to the
+users of that server. Therefore, public use of a modified version, on
+a publicly accessible server, gives the public access to the source
+code of the modified version.
+
+An older license, called the Affero General Public License and
+published by Affero, was designed to accomplish similar goals. This is
+a different license, not a version of the Affero GPL, but Affero has
+released a new version of the Affero GPL which permits relicensing
+under this license.
+
+The precise terms and conditions for copying, distribution and
+modification follow.
+
+### TERMS AND CONDITIONS
+
+#### 0. Definitions.
+
+"This License" refers to version 3 of the Affero GNU General Public
+License.
+
+"Copyright" also means copyright-like laws that apply to other kinds
+of works, such as semiconductor masks.
+
+"The Program" refers to any copyrightable work licensed under this
+License. Each licensee is addressed as "you". "Licensees" and
+"recipients" may be individuals or organizations.
+
+To "modify" a work means to copy from or adapt all or part of the work
+in a fashion requiring copyright permission, other than the making of
+an exact copy. The resulting work is called a "modified version" of
+the earlier work or a work "based on" the earlier work.
+
+A "covered work" means either the unmodified Program or a work based
+on the Program.
+
+To "propagate" a work means to do anything with it that, without
+permission, would make you directly or secondarily liable for
+infringement under applicable copyright law, except executing it on a
+computer or modifying a private copy. Propagation includes copying,
+distribution (with or without modification), making available to the
+public, and in some countries other activities as well.
+
+To "convey" a work means any kind of propagation that enables other
+parties to make or receive copies. Mere interaction with a user
+through a computer network, with no transfer of a copy, is not
+conveying.
+
+An interactive user interface displays "Appropriate Legal Notices" to
+the extent that it includes a convenient and prominently visible
+feature that (1) displays an appropriate copyright notice, and (2)
+tells the user that there is no warranty for the work (except to the
+extent that warranties are provided), that licensees may convey the
+work under this License, and how to view a copy of this License. If
+the interface presents a list of user commands or options, such as a
+menu, a prominent item in the list meets this criterion.
+
+#### 1. Source Code.
+
+The "source code" for a work means the preferred form of the work for
+making modifications to it. "Object code" means any non-source form of
+a work.
+
+A "Standard Interface" means an interface that either is an official
+standard defined by a recognized standards body, or, in the case of
+interfaces specified for a particular programming language, one that
+is widely used among developers working in that language.
+
+The "System Libraries" of an executable work include anything, other
+than the work as a whole, that (a) is included in the normal form of
+packaging a Major Component, but which is not part of that Major
+Component, and (b) serves only to enable use of the work with that
+Major Component, or to implement a Standard Interface for which an
+implementation is available to the public in source code form. A
+"Major Component", in this context, means a major essential component
+(kernel, window system, and so on) of the specific operating system
+(if any) on which the executable work runs, or a compiler used to
+produce the work, or an object code interpreter used to run it.
+
+The "Corresponding Source" for a work in object code form means all
+the source code needed to generate, install, and (for an executable
+work) run the object code and to modify the work, including scripts to
+control those activities. However, it does not include the work's
+System Libraries, or general-purpose tools or generally available free
+programs which are used unmodified in performing those activities but
+which are not part of the work. For example, Corresponding Source
+includes interface definition files associated with source files for
+the work, and the source code for shared libraries and dynamically
+linked subprograms that the work is specifically designed to require,
+such as by intimate data communication or control flow between those
+subprograms and other parts of the work.
+
+The Corresponding Source need not include anything that users can
+regenerate automatically from other parts of the Corresponding Source.
+
+The Corresponding Source for a work in source code form is that same
+work.
+
+#### 2. Basic Permissions.
+
+All rights granted under this License are granted for the term of
+copyright on the Program, and are irrevocable provided the stated
+conditions are met. This License explicitly affirms your unlimited
+permission to run the unmodified Program. The output from running a
+covered work is covered by this License only if the output, given its
+content, constitutes a covered work. This License acknowledges your
+rights of fair use or other equivalent, as provided by copyright law.
+
+You may make, run and propagate covered works that you do not convey,
+without conditions so long as your license otherwise remains in force.
+You may convey covered works to others for the sole purpose of having
+them make modifications exclusively for you, or provide you with
+facilities for running those works, provided that you comply with the
+terms of this License in conveying all material for which you do not
+control copyright. Those thus making or running the covered works for
+you must do so exclusively on your behalf, under your direction and
+control, on terms that prohibit them from making any copies of your
+copyrighted material outside their relationship with you.
+
+Conveying under any other circumstances is permitted solely under the
+conditions stated below. Sublicensing is not allowed; section 10 makes
+it unnecessary.
+
+#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law.
+
+No covered work shall be deemed part of an effective technological
+measure under any applicable law fulfilling obligations under article
+11 of the WIPO copyright treaty adopted on 20 December 1996, or
+similar laws prohibiting or restricting circumvention of such
+measures.
+
+When you convey a covered work, you waive any legal power to forbid
+circumvention of technological measures to the extent such
+circumvention is effected by exercising rights under this License with
+respect to the covered work, and you disclaim any intention to limit
+operation or modification of the work as a means of enforcing, against
+the work's users, your or third parties' legal rights to forbid
+circumvention of technological measures.
+
+#### 4. Conveying Verbatim Copies.
+
+You may convey verbatim copies of the Program's source code as you
+receive it, in any medium, provided that you conspicuously and
+appropriately publish on each copy an appropriate copyright notice;
+keep intact all notices stating that this License and any
+non-permissive terms added in accord with section 7 apply to the code;
+keep intact all notices of the absence of any warranty; and give all
+recipients a copy of this License along with the Program.
+
+You may charge any price or no price for each copy that you convey,
+and you may offer support or warranty protection for a fee.
+
+#### 5. Conveying Modified Source Versions.
+
+You may convey a work based on the Program, or the modifications to
+produce it from the Program, in the form of source code under the
+terms of section 4, provided that you also meet all of these
+conditions:
+
+- a) The work must carry prominent notices stating that you modified
+ it, and giving a relevant date.
+- b) The work must carry prominent notices stating that it is
+ released under this License and any conditions added under
+ section 7. This requirement modifies the requirement in section 4
+ to "keep intact all notices".
+- c) You must license the entire work, as a whole, under this
+ License to anyone who comes into possession of a copy. This
+ License will therefore apply, along with any applicable section 7
+ additional terms, to the whole of the work, and all its parts,
+ regardless of how they are packaged. This License gives no
+ permission to license the work in any other way, but it does not
+ invalidate such permission if you have separately received it.
+- d) If the work has interactive user interfaces, each must display
+ Appropriate Legal Notices; however, if the Program has interactive
+ interfaces that do not display Appropriate Legal Notices, your
+ work need not make them do so.
+
+A compilation of a covered work with other separate and independent
+works, which are not by their nature extensions of the covered work,
+and which are not combined with it such as to form a larger program,
+in or on a volume of a storage or distribution medium, is called an
+"aggregate" if the compilation and its resulting copyright are not
+used to limit the access or legal rights of the compilation's users
+beyond what the individual works permit. Inclusion of a covered work
+in an aggregate does not cause this License to apply to the other
+parts of the aggregate.
+
+#### 6. Conveying Non-Source Forms.
+
+You may convey a covered work in object code form under the terms of
+sections 4 and 5, provided that you also convey the machine-readable
+Corresponding Source under the terms of this License, in one of these
+ways:
+
+- a) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by the
+ Corresponding Source fixed on a durable physical medium
+ customarily used for software interchange.
+- b) Convey the object code in, or embodied in, a physical product
+ (including a physical distribution medium), accompanied by a
+ written offer, valid for at least three years and valid for as
+ long as you offer spare parts or customer support for that product
+ model, to give anyone who possesses the object code either (1) a
+ copy of the Corresponding Source for all the software in the
+ product that is covered by this License, on a durable physical
+ medium customarily used for software interchange, for a price no
+ more than your reasonable cost of physically performing this
+ conveying of source, or (2) access to copy the Corresponding
+ Source from a network server at no charge.
+- c) Convey individual copies of the object code with a copy of the
+ written offer to provide the Corresponding Source. This
+ alternative is allowed only occasionally and noncommercially, and
+ only if you received the object code with such an offer, in accord
+ with subsection 6b.
+- d) Convey the object code by offering access from a designated
+ place (gratis or for a charge), and offer equivalent access to the
+ Corresponding Source in the same way through the same place at no
+ further charge. You need not require recipients to copy the
+ Corresponding Source along with the object code. If the place to
+ copy the object code is a network server, the Corresponding Source
+ may be on a different server (operated by you or a third party)
+ that supports equivalent copying facilities, provided you maintain
+ clear directions next to the object code saying where to find the
+ Corresponding Source. Regardless of what server hosts the
+ Corresponding Source, you remain obligated to ensure that it is
+ available for as long as needed to satisfy these requirements.
+- e) Convey the object code using peer-to-peer transmission,
+ provided you inform other peers where the object code and
+ Corresponding Source of the work are being offered to the general
+ public at no charge under subsection 6d.
+
+A separable portion of the object code, whose source code is excluded
+from the Corresponding Source as a System Library, need not be
+included in conveying the object code work.
+
+A "User Product" is either (1) a "consumer product", which means any
+tangible personal property which is normally used for personal,
+family, or household purposes, or (2) anything designed or sold for
+incorporation into a dwelling. In determining whether a product is a
+consumer product, doubtful cases shall be resolved in favor of
+coverage. For a particular product received by a particular user,
+"normally used" refers to a typical or common use of that class of
+product, regardless of the status of the particular user or of the way
+in which the particular user actually uses, or expects or is expected
+to use, the product. A product is a consumer product regardless of
+whether the product has substantial commercial, industrial or
+non-consumer uses, unless such uses represent the only significant
+mode of use of the product.
+
+"Installation Information" for a User Product means any methods,
+procedures, authorization keys, or other information required to
+install and execute modified versions of a covered work in that User
+Product from a modified version of its Corresponding Source. The
+information must suffice to ensure that the continued functioning of
+the modified object code is in no case prevented or interfered with
+solely because modification has been made.
+
+If you convey an object code work under this section in, or with, or
+specifically for use in, a User Product, and the conveying occurs as
+part of a transaction in which the right of possession and use of the
+User Product is transferred to the recipient in perpetuity or for a
+fixed term (regardless of how the transaction is characterized), the
+Corresponding Source conveyed under this section must be accompanied
+by the Installation Information. But this requirement does not apply
+if neither you nor any third party retains the ability to install
+modified object code on the User Product (for example, the work has
+been installed in ROM).
+
+The requirement to provide Installation Information does not include a
+requirement to continue to provide support service, warranty, or
+updates for a work that has been modified or installed by the
+recipient, or for the User Product in which it has been modified or
+installed. Access to a network may be denied when the modification
+itself materially and adversely affects the operation of the network
+or violates the rules and protocols for communication across the
+network.
+
+Corresponding Source conveyed, and Installation Information provided,
+in accord with this section must be in a format that is publicly
+documented (and with an implementation available to the public in
+source code form), and must require no special password or key for
+unpacking, reading or copying.
+
+#### 7. Additional Terms.
+
+"Additional permissions" are terms that supplement the terms of this
+License by making exceptions from one or more of its conditions.
+Additional permissions that are applicable to the entire Program shall
+be treated as though they were included in this License, to the extent
+that they are valid under applicable law. If additional permissions
+apply only to part of the Program, that part may be used separately
+under those permissions, but the entire Program remains governed by
+this License without regard to the additional permissions.
+
+When you convey a copy of a covered work, you may at your option
+remove any additional permissions from that copy, or from any part of
+it. (Additional permissions may be written to require their own
+removal in certain cases when you modify the work.) You may place
+additional permissions on material, added by you to a covered work,
+for which you have or can give appropriate copyright permission.
+
+Notwithstanding any other provision of this License, for material you
+add to a covered work, you may (if authorized by the copyright holders
+of that material) supplement the terms of this License with terms:
+
+- a) Disclaiming warranty or limiting liability differently from the
+ terms of sections 15 and 16 of this License; or
+- b) Requiring preservation of specified reasonable legal notices or
+ author attributions in that material or in the Appropriate Legal
+ Notices displayed by works containing it; or
+- c) Prohibiting misrepresentation of the origin of that material,
+ or requiring that modified versions of such material be marked in
+ reasonable ways as different from the original version; or
+- d) Limiting the use for publicity purposes of names of licensors
+ or authors of the material; or
+- e) Declining to grant rights under trademark law for use of some
+ trade names, trademarks, or service marks; or
+- f) Requiring indemnification of licensors and authors of that
+ material by anyone who conveys the material (or modified versions
+ of it) with contractual assumptions of liability to the recipient,
+ for any liability that these contractual assumptions directly
+ impose on those licensors and authors.
+
+All other non-permissive additional terms are considered "further
+restrictions" within the meaning of section 10. If the Program as you
+received it, or any part of it, contains a notice stating that it is
+governed by this License along with a term that is a further
+restriction, you may remove that term. If a license document contains
+a further restriction but permits relicensing or conveying under this
+License, you may add to a covered work material governed by the terms
+of that license document, provided that the further restriction does
+not survive such relicensing or conveying.
+
+If you add terms to a covered work in accord with this section, you
+must place, in the relevant source files, a statement of the
+additional terms that apply to those files, or a notice indicating
+where to find the applicable terms.
+
+Additional terms, permissive or non-permissive, may be stated in the
+form of a separately written license, or stated as exceptions; the
+above requirements apply either way.
+
+#### 8. Termination.
+
+You may not propagate or modify a covered work except as expressly
+provided under this License. Any attempt otherwise to propagate or
+modify it is void, and will automatically terminate your rights under
+this License (including any patent licenses granted under the third
+paragraph of section 11).
+
+However, if you cease all violation of this License, then your license
+from a particular copyright holder is reinstated (a) provisionally,
+unless and until the copyright holder explicitly and finally
+terminates your license, and (b) permanently, if the copyright holder
+fails to notify you of the violation by some reasonable means prior to
+60 days after the cessation.
+
+Moreover, your license from a particular copyright holder is
+reinstated permanently if the copyright holder notifies you of the
+violation by some reasonable means, this is the first time you have
+received notice of violation of this License (for any work) from that
+copyright holder, and you cure the violation prior to 30 days after
+your receipt of the notice.
+
+Termination of your rights under this section does not terminate the
+licenses of parties who have received copies or rights from you under
+this License. If your rights have been terminated and not permanently
+reinstated, you do not qualify to receive new licenses for the same
+material under section 10.
+
+#### 9. Acceptance Not Required for Having Copies.
+
+You are not required to accept this License in order to receive or run
+a copy of the Program. Ancillary propagation of a covered work
+occurring solely as a consequence of using peer-to-peer transmission
+to receive a copy likewise does not require acceptance. However,
+nothing other than this License grants you permission to propagate or
+modify any covered work. These actions infringe copyright if you do
+not accept this License. Therefore, by modifying or propagating a
+covered work, you indicate your acceptance of this License to do so.
+
+#### 10. Automatic Licensing of Downstream Recipients.
+
+Each time you convey a covered work, the recipient automatically
+receives a license from the original licensors, to run, modify and
+propagate that work, subject to this License. You are not responsible
+for enforcing compliance by third parties with this License.
+
+An "entity transaction" is a transaction transferring control of an
+organization, or substantially all assets of one, or subdividing an
+organization, or merging organizations. If propagation of a covered
+work results from an entity transaction, each party to that
+transaction who receives a copy of the work also receives whatever
+licenses to the work the party's predecessor in interest had or could
+give under the previous paragraph, plus a right to possession of the
+Corresponding Source of the work from the predecessor in interest, if
+the predecessor has it or can get it with reasonable efforts.
+
+You may not impose any further restrictions on the exercise of the
+rights granted or affirmed under this License. For example, you may
+not impose a license fee, royalty, or other charge for exercise of
+rights granted under this License, and you may not initiate litigation
+(including a cross-claim or counterclaim in a lawsuit) alleging that
+any patent claim is infringed by making, using, selling, offering for
+sale, or importing the Program or any portion of it.
+
+#### 11. Patents.
+
+A "contributor" is a copyright holder who authorizes use under this
+License of the Program or a work on which the Program is based. The
+work thus licensed is called the contributor's "contributor version".
+
+A contributor's "essential patent claims" are all patent claims owned
+or controlled by the contributor, whether already acquired or
+hereafter acquired, that would be infringed by some manner, permitted
+by this License, of making, using, or selling its contributor version,
+but do not include claims that would be infringed only as a
+consequence of further modification of the contributor version. For
+purposes of this definition, "control" includes the right to grant
+patent sublicenses in a manner consistent with the requirements of
+this License.
+
+Each contributor grants you a non-exclusive, worldwide, royalty-free
+patent license under the contributor's essential patent claims, to
+make, use, sell, offer for sale, import and otherwise run, modify and
+propagate the contents of its contributor version.
+
+In the following three paragraphs, a "patent license" is any express
+agreement or commitment, however denominated, not to enforce a patent
+(such as an express permission to practice a patent or covenant not to
+sue for patent infringement). To "grant" such a patent license to a
+party means to make such an agreement or commitment not to enforce a
+patent against the party.
+
+If you convey a covered work, knowingly relying on a patent license,
+and the Corresponding Source of the work is not available for anyone
+to copy, free of charge and under the terms of this License, through a
+publicly available network server or other readily accessible means,
+then you must either (1) cause the Corresponding Source to be so
+available, or (2) arrange to deprive yourself of the benefit of the
+patent license for this particular work, or (3) arrange, in a manner
+consistent with the requirements of this License, to extend the patent
+license to downstream recipients. "Knowingly relying" means you have
+actual knowledge that, but for the patent license, your conveying the
+covered work in a country, or your recipient's use of the covered work
+in a country, would infringe one or more identifiable patents in that
+country that you have reason to believe are valid.
+
+If, pursuant to or in connection with a single transaction or
+arrangement, you convey, or propagate by procuring conveyance of, a
+covered work, and grant a patent license to some of the parties
+receiving the covered work authorizing them to use, propagate, modify
+or convey a specific copy of the covered work, then the patent license
+you grant is automatically extended to all recipients of the covered
+work and works based on it.
+
+A patent license is "discriminatory" if it does not include within the
+scope of its coverage, prohibits the exercise of, or is conditioned on
+the non-exercise of one or more of the rights that are specifically
+granted under this License. You may not convey a covered work if you
+are a party to an arrangement with a third party that is in the
+business of distributing software, under which you make payment to the
+third party based on the extent of your activity of conveying the
+work, and under which the third party grants, to any of the parties
+who would receive the covered work from you, a discriminatory patent
+license (a) in connection with copies of the covered work conveyed by
+you (or copies made from those copies), or (b) primarily for and in
+connection with specific products or compilations that contain the
+covered work, unless you entered into that arrangement, or that patent
+license was granted, prior to 28 March 2007.
+
+Nothing in this License shall be construed as excluding or limiting
+any implied license or other defenses to infringement that may
+otherwise be available to you under applicable patent law.
+
+#### 12. No Surrender of Others' Freedom.
+
+If conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot convey a
+covered work so as to satisfy simultaneously your obligations under
+this License and any other pertinent obligations, then as a
+consequence you may not convey it at all. For example, if you agree to
+terms that obligate you to collect a royalty for further conveying
+from those to whom you convey the Program, the only way you could
+satisfy both those terms and this License would be to refrain entirely
+from conveying the Program.
+
+#### 13. Remote Network Interaction; Use with the GNU General Public License.
+
+Notwithstanding any other provision of this License, if you modify the
+Program, your modified version must prominently offer all users
+interacting with it remotely through a computer network (if your
+version supports such interaction) an opportunity to receive the
+Corresponding Source of your version by providing access to the
+Corresponding Source from a network server at no charge, through some
+standard or customary means of facilitating copying of software. This
+Corresponding Source shall include the Corresponding Source for any
+work covered by version 3 of the GNU General Public License that is
+incorporated pursuant to the following paragraph.
+
+Notwithstanding any other provision of this License, you have
+permission to link or combine any covered work with a work licensed
+under version 3 of the GNU General Public License into a single
+combined work, and to convey the resulting work. The terms of this
+License will continue to apply to the part which is the covered work,
+but the work with which it is combined will remain governed by version
+3 of the GNU General Public License.
+
+#### 14. Revised Versions of this License.
+
+The Free Software Foundation may publish revised and/or new versions
+of the Affero GNU General Public License from time to time. Such new
+versions will be similar in spirit to the present version, but may
+differ in detail to address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies that a certain numbered version of the Affero GNU General
+Public License "or any later version" applies to it, you have the
+option of following the terms and conditions either of that numbered
+version or of any later version published by the Free Software
+Foundation. If the Program does not specify a version number of the
+Affero GNU General Public License, you may choose any version ever
+published by the Free Software Foundation.
+
+If the Program specifies that a proxy can decide which future versions
+of the Affero GNU General Public License can be used, that proxy's
+public statement of acceptance of a version permanently authorizes you
+to choose that version for the Program.
+
+Later license versions may give you additional or different
+permissions. However, no additional obligations are imposed on any
+author or copyright holder as a result of your choosing to follow a
+later version.
+
+#### 15. Disclaimer of Warranty.
+
+THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
+APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
+HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
+WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE
+DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
+CORRECTION.
+
+#### 16. Limitation of Liability.
+
+IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR
+CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
+ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT
+NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR
+LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM
+TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
+PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
+
+#### 17. Interpretation of Sections 15 and 16.
+
+If the disclaimer of warranty and limitation of liability provided
+above cannot be given local legal effect according to their terms,
+reviewing courts shall apply local law that most closely approximates
+an absolute waiver of all civil liability in connection with the
+Program, unless a warranty or assumption of liability accompanies a
+copy of the Program in return for a fee.
+
+END OF TERMS AND CONDITIONS
+
+### How to Apply These Terms to Your New Programs
+
+If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these
+terms.
+
+To do so, attach the following notices to the program. It is safest to
+attach them to the start of each source file to most effectively state
+the exclusion of warranty; and each file should have at least the
+"copyright" line and a pointer to where the full notice is found.
+
+
+ Copyright (C)
+
+ This program is free software: you can redistribute it and/or modify
+ it under the terms of the Affero GNU General Public License as
+ published by the Free Software Foundation, either version 3 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ Affero GNU General Public License for more details.
+
+ You should have received a copy of the Affero GNU General Public License
+ along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html].
+
+Also add information on how to contact you by electronic and paper
+mail.
+
+If your software can interact with users remotely through a computer
+network, you should also make sure that it provides a way for users to
+get its source. For example, if your program is a web application, its
+interface could display a "Source" link that leads users to an archive
+of the code. There are many ways you could offer source, and different
+solutions will be better for different programs; see section 13 for
+the specific requirements.
+
+You should also get your employer (if you work as a programmer) or
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. For more information on this, and how to apply and follow
+the GNU AGPL, see [https://www.gnu.org/licenses/agpl-3.0.en.html].
diff --git a/Mogrify.cs b/Mogrify.cs
index d08a613..b8fc422 100644
--- a/Mogrify.cs
+++ b/Mogrify.cs
@@ -1,478 +1,478 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 27-08-2016
-//
-// Last Modified By : Frede H.
-// Last Modified On : 02-24-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the Affero GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// Affero GNU General Public License for more details.
-//
-// You should have received a copy of the Affero GNU General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
-//
-//
-// ***********************************************************************
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Globalization;
-using System.IO;
-using System.Linq;
-using System.Text;
-using System.Text.RegularExpressions;
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Mogrify between units
- ///
- public static class Mogrify
- {
- ///
- /// Get month from timestamp
- ///
- ///
- /// integer
- public static int MonthFromTimestamp(long timeStamp)
- {
- return TimeStampToDateTime(timeStamp).Month;
- }
-
- ///
- /// validate if timestamp occurs in month
- ///
- ///
- ///
- /// boolean
- public static bool TimestampInMonth(long timestamp, int month)
- {
- return TimeStampToDateTime(timestamp).Month == month;
- }
-
- ///
- /// return iso8601 string from timestamp
- ///
- ///
- ///
- public static string TimestampToIso8601(long timestamp)
- {
- return DateTimeIso8601(TimeStampToDateTime(timestamp));
- }
- ///
- /// return date as ISO
- ///
- ///
- ///
- public static string DateTimeIso8601(DateTime date)
- {
- return date.ToString("o",CultureInfo.InvariantCulture);
- }
-
- ///
- /// Get timestamp range for given datetime
- ///
- ///
- /// dictionary
- public static Dictionary DateToTimestampRange(DateTime dateTime)
- {
- var dt1 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day,0,0,0);
- var dt2 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59);
- return new Dictionary{
- { "lower", DateTimeToTimeStamp(dt1) },
- { "upper", DateTimeToTimeStamp(dt2) }
- };
- }
-
- ///
- /// ISO date to timestamp
- ///
- ///
- /// long
- public static long IsoDateToTimestamp(string isoDateString)
- {
- var result = DateTime.TryParse(isoDateString, out var test);
- if (!result)
- return 0;
- return $"{test:yyyy-MM-dd}" == isoDateString ? DateTimeToTimeStamp(test) : 0;
- }
-
- ///
- /// ISO date from timestamp
- ///
- ///
- /// string yyyy-MM-dd
- public static string TimestampToIsoDate(long timestamp)
- {
- return $"{TimeStampToDateTime(timestamp):yyyy-MM-dd}";
- }
-
- ///
- /// get timestamp from current date time
- ///
- ///
- public static long CurrentDateTimeToTimeStamp()
- {
- return Convert.ToUInt32(DateTimeToTimeStamp(DateTime.Now));
- }
-
- ///
- /// get timestamp from date time
- ///
- ///
- ///
- public static long DateTimeToTimeStamp(DateTime dateTime)
- {
- var bigDate = new DateTime(2038, 1, 19, 0, 0, 0, 0);
- var nixDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
-
- if (dateTime >= bigDate)
- return Convert.ToInt64((bigDate - nixDate).TotalSeconds) +
- Convert.ToInt64((dateTime - bigDate).TotalSeconds);
-
- return Convert.ToInt64((dateTime - nixDate).TotalSeconds);
- }
-
- ///
- /// get date time from timestamp
- ///
- ///
- ///
- public static DateTime TimeStampToDateTime(long timeStamp)
- {
- var nixDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
- return nixDate.AddSeconds(timeStamp);
- }
-
- ///
- /// get seconds from timespan
- ///
- ///
- ///
- public static long TimeSpanToSeconds(TimeSpan timespan)
- {
- return Convert.ToUInt32(timespan.Ticks / 10000000L);
- }
-
- ///
- /// get timespan from seconds
- ///
- ///
- ///
- public static TimeSpan SecondsToTimeSpan(long seconds)
- {
- return TimeSpan.FromTicks(10000000L * seconds);
- }
-
- ///
- /// get minutes from timespan
- ///
- ///
- ///
- public static long TimespanToMinutes(TimeSpan timespan)
- {
- return Convert.ToUInt32(timespan.Ticks / 10000000L) / 60;
- }
-
- ///
- /// reverse boolean
- ///
- ///
- /// bool
- public static bool BoolReverse(bool value)
- {
- return !value;
- }
-
- ///
- /// number from bool
- ///
- ///
- /// integer
- public static int BoolToInt(bool value)
- {
- return value ? 1 : 0;
- }
-
- ///
- /// string from bool
- ///
- ///
- /// string true/false
- public static string BoolToString(bool value)
- {
- return value ? "true" : "false";
- }
-
- ///
- /// get bool from integer
- ///
- ///
- ///
- public static bool IntToBool(int value)
- {
- return value is > 0 or < 0;
- }
-
- ///
- /// get the number value from enum
- ///
- ///
- /// int
- public static int EnumToInt(object enumeration)
- {
- return Convert.ToInt32(enumeration, CultureInfo.InvariantCulture);
- }
-
- ///
- /// get string from enum
- ///
- ///
- /// string - name of the enum
- public static string EnumToString(Enum value)
- {
- return value == null ? string.Empty : value.ToString();
- }
-
- ///
- /// get list of enum of type T
- ///
- ///
- /// list of enum
- public static IEnumerable GetEnumList()
- {
- return (T[])Enum.GetValues(typeof(T));
- }
-
-
- ///
- /// get enum from integer of type T
- ///
- ///
- ///
- ///
- public static T IntToEnum(int value)
- {
- return (T) Enum.ToObject(typeof(T), value);
- }
-
- ///
- /// get string from list using semicolon separator
- ///
- ///
- ///
- ///
- public static string ListToString(List list)
- {
- return ListToString(list, ";");
- }
-
- ///
- /// get string from list using delimiter
- ///
- ///
- ///
- ///
- ///
- public static string ListToString(List list, string delimiter)
- {
- var empty = string.Empty;
- if (list == null) return empty;
- var enumerator = (IEnumerator) list.GetType().GetMethod("GetEnumerator")?.Invoke(list, null);
- while (enumerator != null && enumerator.MoveNext())
- if (enumerator.Current != null)
- empty = string.Concat(empty, enumerator.Current.ToString(), delimiter);
-
- return empty;
- }
-
- ///
- /// get lowercase dash separated string from Pascal case
- ///
- ///
- ///
- public static string PascalToLower(string value)
- {
- var result = string.Join("-", Regex.Split(value, @"(?
- /// get bool from string
- ///
- ///
- ///
- public static bool StringToBool(string value)
- {
- if (string.IsNullOrEmpty(value))
- return false;
-
- var flag = false;
- var upper = value.ToUpperInvariant();
- if (string.Compare(upper, "true", StringComparison.OrdinalIgnoreCase) == 0)
- {
- flag = true;
- }
- else if (string.CompareOrdinal(upper, "false") == 0)
- {
- }
- else if (string.CompareOrdinal(upper, "1") == 0)
- {
- flag = true;
- }
-
- return flag;
- }
- ///
- /// get decimal from string
- ///
- ///
- ///
- public static decimal? StringToDecimal(string inString)
- {
- if (string.IsNullOrEmpty(inString)) return 0;
- return
- !decimal.TryParse(inString.Replace(",", "").Replace(".", ""), NumberStyles.Number,
- CultureInfo.InvariantCulture, out var num)
- ? (decimal?) null
- : decimal.Divide(num, new decimal((long) 100));
- }
-
- ///
- /// get enum of type T from string
- ///
- ///
- ///
- ///
- public static T StringToEnum(string value)
- {
- return (T)Enum.Parse(typeof(T), value, true);
- }
-
- ///
- /// get list from string using semicolon
- ///
- ///
- ///
- ///
- public static List StringToList(string value)
- {
- return StringToList(value, ";");
- }
-
- ///
- /// get list from string using delimiter
- ///
- ///
- ///
- ///
- ///
- ///
- public static List StringToList(string value, string delimiter)
- {
- if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value));
- if (string.IsNullOrEmpty(delimiter)) throw new ArgumentNullException(nameof(delimiter));
-
- var ts = new List();
- var strArrays = value.Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
- foreach (var str in strArrays)
- {
- var o = typeof(T).FullName;
- if (o == null) continue;
- var upperInvariant = o.ToUpperInvariant();
- if (string.CompareOrdinal(upperInvariant, "system.string") == 0)
- {
- ts.Add((T) Convert.ChangeType(str, typeof(T), CultureInfo.InvariantCulture));
- }
- else if (string.CompareOrdinal(upperInvariant, "system.int32") == 0)
- {
- ts.Add((T) Convert.ChangeType(str, typeof(T), CultureInfo.InvariantCulture));
- }
- else if (string.CompareOrdinal(upperInvariant, "system.guid") == 0)
- {
- var guid = new Guid(str);
- ts.Add((T) Convert.ChangeType(guid, typeof(T), CultureInfo.InvariantCulture));
- }
- }
-
- return ts;
- }
-
- ///
- /// get string from stream (default encoding)
- ///
- ///
- ///
- public static Stream StringToStream(string value)
- {
- return StringToStream(value, Encoding.Default);
- }
-
- ///
- /// get stream from string (using encoding)
- ///
- ///
- ///
- ///
- public static Stream StringToStream(string value, Encoding encoding)
- {
- return encoding == null ? null : new MemoryStream(encoding.GetBytes(value ?? ""));
- }
-
-
- /////
- ///// get string from date time
- /////
- /////
- //public static string CurrentDateTimeToAlpha()
- //{
- // var dt = DateTime.UtcNow.ToString("yy MM dd HH MM ss");
- // var sb = new StringBuilder();
- // var dts = dt.Split(' ');
- // sb.Append((char) int.Parse(dts[0]) + 65);
- // sb.Append((char) int.Parse(dts[1]) + 65);
- // sb.Append((char) int.Parse(dts[2]) + 97);
- // sb.Append((char) int.Parse(dts[3]) + 65);
- // sb.Append((char) int.Parse(dts[4]) + 97);
- // sb.Append((char) int.Parse(dts[5]) + 97);
- // return sb.ToString();
- //}
-
- /////
- ///// integer to letter
- /////
- /////
- ///// string
- //public static string IntToLetter(int value)
- //{
- // var empty = string.Empty;
- // var num = 97;
- // var str = "";
- // var num1 = 0;
- // var num2 = 97;
- // for (var i = 0; i <= value; i++)
- // {
- // num1++;
- // empty = string.Concat(str, Convert.ToString(Convert.ToChar(num), CultureInfo.InvariantCulture));
- // num++;
- // if (num1 != 26) continue;
- // num1 = 0;
- // str = Convert.ToChar(num2).ToString(CultureInfo.InvariantCulture);
- // num2++;
- // num = 97;
- // }
- // return empty;
- //}
- }
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 27-08-2016
+//
+// Last Modified By : Frede H.
+// Last Modified On : 02-24-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the Affero GNU General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// Affero GNU General Public License for more details.
+//
+// You should have received a copy of the Affero GNU General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
+//
+//
+// ***********************************************************************
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Linq;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Mogrify between units
+ ///
+ public static class Mogrify
+ {
+ ///
+ /// Get month from timestamp
+ ///
+ ///
+ /// integer
+ public static int MonthFromTimestamp(long timeStamp)
+ {
+ return TimeStampToDateTime(timeStamp).Month;
+ }
+
+ ///
+ /// validate if timestamp occurs in month
+ ///
+ ///
+ ///
+ /// boolean
+ public static bool TimestampInMonth(long timestamp, int month)
+ {
+ return TimeStampToDateTime(timestamp).Month == month;
+ }
+
+ ///
+ /// return iso8601 string from timestamp
+ ///
+ ///
+ ///
+ public static string TimestampToIso8601(long timestamp)
+ {
+ return DateTimeIso8601(TimeStampToDateTime(timestamp));
+ }
+ ///
+ /// return date as ISO
+ ///
+ ///
+ ///
+ public static string DateTimeIso8601(DateTime date)
+ {
+ return date.ToString("o",CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// Get timestamp range for given datetime
+ ///
+ ///
+ /// dictionary
+ public static Dictionary DateToTimestampRange(DateTime dateTime)
+ {
+ var dt1 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day,0,0,0);
+ var dt2 = new DateTime(dateTime.Year, dateTime.Month, dateTime.Day, 23, 59, 59);
+ return new Dictionary{
+ { "lower", DateTimeToTimeStamp(dt1) },
+ { "upper", DateTimeToTimeStamp(dt2) }
+ };
+ }
+
+ ///
+ /// ISO date to timestamp
+ ///
+ ///
+ /// long
+ public static long IsoDateToTimestamp(string isoDateString)
+ {
+ var result = DateTime.TryParse(isoDateString, out var test);
+ if (!result)
+ return 0;
+ return $"{test:yyyy-MM-dd}" == isoDateString ? DateTimeToTimeStamp(test) : 0;
+ }
+
+ ///
+ /// ISO date from timestamp
+ ///
+ ///
+ /// string yyyy-MM-dd
+ public static string TimestampToIsoDate(long timestamp)
+ {
+ return $"{TimeStampToDateTime(timestamp):yyyy-MM-dd}";
+ }
+
+ ///
+ /// get timestamp from current date time
+ ///
+ ///
+ public static long CurrentDateTimeToTimeStamp()
+ {
+ return Convert.ToUInt32(DateTimeToTimeStamp(DateTime.Now));
+ }
+
+ ///
+ /// get timestamp from date time
+ ///
+ ///
+ ///
+ public static long DateTimeToTimeStamp(DateTime dateTime)
+ {
+ var bigDate = new DateTime(2038, 1, 19, 0, 0, 0, 0);
+ var nixDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
+
+ if (dateTime >= bigDate)
+ return Convert.ToInt64((bigDate - nixDate).TotalSeconds) +
+ Convert.ToInt64((dateTime - bigDate).TotalSeconds);
+
+ return Convert.ToInt64((dateTime - nixDate).TotalSeconds);
+ }
+
+ ///
+ /// get date time from timestamp
+ ///
+ ///
+ ///
+ public static DateTime TimeStampToDateTime(long timeStamp)
+ {
+ var nixDate = new DateTime(1970, 1, 1, 0, 0, 0, 0);
+ return nixDate.AddSeconds(timeStamp);
+ }
+
+ ///
+ /// get seconds from timespan
+ ///
+ ///
+ ///
+ public static long TimeSpanToSeconds(TimeSpan timespan)
+ {
+ return Convert.ToUInt32(timespan.Ticks / 10000000L);
+ }
+
+ ///
+ /// get timespan from seconds
+ ///
+ ///
+ ///
+ public static TimeSpan SecondsToTimeSpan(long seconds)
+ {
+ return TimeSpan.FromTicks(10000000L * seconds);
+ }
+
+ ///
+ /// get minutes from timespan
+ ///
+ ///
+ ///
+ public static long TimespanToMinutes(TimeSpan timespan)
+ {
+ return Convert.ToUInt32(timespan.Ticks / 10000000L) / 60;
+ }
+
+ ///
+ /// reverse boolean
+ ///
+ ///
+ /// bool
+ public static bool BoolReverse(bool value)
+ {
+ return !value;
+ }
+
+ ///
+ /// number from bool
+ ///
+ ///
+ /// integer
+ public static int BoolToInt(bool value)
+ {
+ return value ? 1 : 0;
+ }
+
+ ///
+ /// string from bool
+ ///
+ ///
+ /// string true/false
+ public static string BoolToString(bool value)
+ {
+ return value ? "true" : "false";
+ }
+
+ ///
+ /// get bool from integer
+ ///
+ ///
+ ///
+ public static bool IntToBool(int value)
+ {
+ return value is > 0 or < 0;
+ }
+
+ ///
+ /// get the number value from enum
+ ///
+ ///
+ /// int
+ public static int EnumToInt(object enumeration)
+ {
+ return Convert.ToInt32(enumeration, CultureInfo.InvariantCulture);
+ }
+
+ ///
+ /// get string from enum
+ ///
+ ///
+ /// string - name of the enum
+ public static string EnumToString(Enum value)
+ {
+ return value == null ? string.Empty : value.ToString();
+ }
+
+ ///
+ /// get list of enum of type T
+ ///
+ ///
+ /// list of enum
+ public static IEnumerable GetEnumList()
+ {
+ return (T[])Enum.GetValues(typeof(T));
+ }
+
+
+ ///
+ /// get enum from integer of type T
+ ///
+ ///
+ ///
+ ///
+ public static T IntToEnum(int value)
+ {
+ return (T) Enum.ToObject(typeof(T), value);
+ }
+
+ ///
+ /// get string from list using semicolon separator
+ ///
+ ///
+ ///
+ ///
+ public static string ListToString(List list)
+ {
+ return ListToString(list, ";");
+ }
+
+ ///
+ /// get string from list using delimiter
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static string ListToString(List list, string delimiter)
+ {
+ var empty = string.Empty;
+ if (list == null) return empty;
+ var enumerator = (IEnumerator) list.GetType().GetMethod("GetEnumerator")?.Invoke(list, null);
+ while (enumerator != null && enumerator.MoveNext())
+ if (enumerator.Current != null)
+ empty = string.Concat(empty, enumerator.Current.ToString(), delimiter);
+
+ return empty;
+ }
+
+ ///
+ /// get lowercase dash separated string from Pascal case
+ ///
+ ///
+ ///
+ public static string PascalToLower(string value)
+ {
+ var result = string.Join("-", Regex.Split(value, @"(?
+ /// get bool from string
+ ///
+ ///
+ ///
+ public static bool StringToBool(string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ return false;
+
+ var flag = false;
+ var upper = value.ToUpperInvariant();
+ if (string.Compare(upper, "true", StringComparison.OrdinalIgnoreCase) == 0)
+ {
+ flag = true;
+ }
+ else if (string.CompareOrdinal(upper, "false") == 0)
+ {
+ }
+ else if (string.CompareOrdinal(upper, "1") == 0)
+ {
+ flag = true;
+ }
+
+ return flag;
+ }
+ ///
+ /// get decimal from string
+ ///
+ ///
+ ///
+ public static decimal? StringToDecimal(string inString)
+ {
+ if (string.IsNullOrEmpty(inString)) return 0;
+ return
+ !decimal.TryParse(inString.Replace(",", "").Replace(".", ""), NumberStyles.Number,
+ CultureInfo.InvariantCulture, out var num)
+ ? (decimal?) null
+ : decimal.Divide(num, new decimal((long) 100));
+ }
+
+ ///
+ /// get enum of type T from string
+ ///
+ ///
+ ///
+ ///
+ public static T StringToEnum(string value)
+ {
+ return (T)Enum.Parse(typeof(T), value, true);
+ }
+
+ ///
+ /// get list from string using semicolon
+ ///
+ ///
+ ///
+ ///
+ public static List StringToList(string value)
+ {
+ return StringToList(value, ";");
+ }
+
+ ///
+ /// get list from string using delimiter
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static List StringToList(string value, string delimiter)
+ {
+ if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value));
+ if (string.IsNullOrEmpty(delimiter)) throw new ArgumentNullException(nameof(delimiter));
+
+ var ts = new List();
+ var strArrays = value.Split(delimiter.ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
+ foreach (var str in strArrays)
+ {
+ var o = typeof(T).FullName;
+ if (o == null) continue;
+ var upperInvariant = o.ToUpperInvariant();
+ if (string.CompareOrdinal(upperInvariant, "system.string") == 0)
+ {
+ ts.Add((T) Convert.ChangeType(str, typeof(T), CultureInfo.InvariantCulture));
+ }
+ else if (string.CompareOrdinal(upperInvariant, "system.int32") == 0)
+ {
+ ts.Add((T) Convert.ChangeType(str, typeof(T), CultureInfo.InvariantCulture));
+ }
+ else if (string.CompareOrdinal(upperInvariant, "system.guid") == 0)
+ {
+ var guid = new Guid(str);
+ ts.Add((T) Convert.ChangeType(guid, typeof(T), CultureInfo.InvariantCulture));
+ }
+ }
+
+ return ts;
+ }
+
+ ///
+ /// get string from stream (default encoding)
+ ///
+ ///
+ ///
+ public static Stream StringToStream(string value)
+ {
+ return StringToStream(value, Encoding.Default);
+ }
+
+ ///
+ /// get stream from string (using encoding)
+ ///
+ ///
+ ///
+ ///
+ public static Stream StringToStream(string value, Encoding encoding)
+ {
+ return encoding == null ? null : new MemoryStream(encoding.GetBytes(value ?? ""));
+ }
+
+
+ /////
+ ///// get string from date time
+ /////
+ /////
+ //public static string CurrentDateTimeToAlpha()
+ //{
+ // var dt = DateTime.UtcNow.ToString("yy MM dd HH MM ss");
+ // var sb = new StringBuilder();
+ // var dts = dt.Split(' ');
+ // sb.Append((char) int.Parse(dts[0]) + 65);
+ // sb.Append((char) int.Parse(dts[1]) + 65);
+ // sb.Append((char) int.Parse(dts[2]) + 97);
+ // sb.Append((char) int.Parse(dts[3]) + 65);
+ // sb.Append((char) int.Parse(dts[4]) + 97);
+ // sb.Append((char) int.Parse(dts[5]) + 97);
+ // return sb.ToString();
+ //}
+
+ /////
+ ///// integer to letter
+ /////
+ /////
+ ///// string
+ //public static string IntToLetter(int value)
+ //{
+ // var empty = string.Empty;
+ // var num = 97;
+ // var str = "";
+ // var num1 = 0;
+ // var num2 = 97;
+ // for (var i = 0; i <= value; i++)
+ // {
+ // num1++;
+ // empty = string.Concat(str, Convert.ToString(Convert.ToChar(num), CultureInfo.InvariantCulture));
+ // num++;
+ // if (num1 != 26) continue;
+ // num1 = 0;
+ // str = Convert.ToChar(num2).ToString(CultureInfo.InvariantCulture);
+ // num2++;
+ // num = 97;
+ // }
+ // return empty;
+ //}
+ }
}
\ No newline at end of file
diff --git a/Properties/AssemblyInfo.cs b/Properties/AssemblyInfo.cs
index 6996bbd..5d1fa51 100644
--- a/Properties/AssemblyInfo.cs
+++ b/Properties/AssemblyInfo.cs
@@ -1,21 +1,21 @@
-// This code was generated by a tool. Any changes made manually will be lost
-// the next time this code is regenerated.
-
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("FCS.Lib.Utility")]
-[assembly: AssemblyDescription("FCS.Lib.Utility")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("FCS")]
-[assembly: AssemblyProduct("FCS.Lib.Utility")]
-[assembly: AssemblyCopyright("AGPL-3.0-or-later Copyright © FCS 2015-2022")]
-[assembly: AssemblyTrademark("© FCS")]
-[assembly: AssemblyCulture("")]
-
-
-[assembly: ComVisible(false)]
-[assembly: Guid("8D850197-78DB-4D16-A91F-E5BB6E8880A7")]
-
-[assembly: AssemblyVersion("1.0.1.0")]
-[assembly: AssemblyFileVersion("1.0.1.0")]
\ No newline at end of file
+// This code was generated by a tool. Any changes made manually will be lost
+// the next time this code is regenerated.
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("FCS.Lib.Utility")]
+[assembly: AssemblyDescription("FCS.Lib.Utility")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("FCS")]
+[assembly: AssemblyProduct("FCS.Lib.Utility")]
+[assembly: AssemblyCopyright("AGPL-3.0-or-later Copyright © FCS 2015-2022")]
+[assembly: AssemblyTrademark("© FCS")]
+[assembly: AssemblyCulture("")]
+
+
+[assembly: ComVisible(false)]
+[assembly: Guid("8D850197-78DB-4D16-A91F-E5BB6E8880A7")]
+
+[assembly: AssemblyVersion("1.0.22346.0710")]
+[assembly: AssemblyFileVersion("1.0.22346.0710")]
\ No newline at end of file
diff --git a/Properties/AssemblyInfo.tt b/Properties/AssemblyInfo.tt
index 5ebbad0..8d17bfb 100644
--- a/Properties/AssemblyInfo.tt
+++ b/Properties/AssemblyInfo.tt
@@ -1,42 +1,39 @@
-<#@ template debug="true" hostspecific="false" language="C#" #>
-<#@ output extension=".cs" #>
-<#
- int major = 1;
- int minor = 0; // Official == even, Preview == odd
- int build = 1;
- int revision = 0;
-
- string version = String.Format("{0}.{1}.{2}.{3}", major, minor, build, revision);
-
- if (minor % 2 == 1) // Preview build
- {
- // Auto-generate the build and revision
-
- DateTime buildTime = DateTime.Now;
-
- build = (1000 * (buildTime.Year % 100)) + buildTime.DayOfYear;
- revision = (100 * buildTime.Hour) + buildTime.Minute;
- version = String.Format("{0}.{1}.{2:00000}.{3:0000}", major, minor, build, revision);
- }
- #>
-// This code was generated by a tool. Any changes made manually will be lost
-// the next time this code is regenerated.
-
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-[assembly: AssemblyTitle("FCS.Lib.Utility")]
-[assembly: AssemblyDescription("FCS.Lib.Utility")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("FCS")]
-[assembly: AssemblyProduct("FCS.Lib.Utility")]
-[assembly: AssemblyCopyright("AGPL-3.0-or-later Copyright © FCS 2015-2022")]
-[assembly: AssemblyTrademark("© FCS")]
-[assembly: AssemblyCulture("")]
-
-
-[assembly: ComVisible(false)]
-[assembly: Guid("8D850197-78DB-4D16-A91F-E5BB6E8880A7")]
-
-[assembly: AssemblyVersion("<#= version #>")]
+<#@ template debug="true" hostspecific="false" language="C#" #>
+<#@ output extension=".cs" #>
+<#
+ int major = 1;
+ int minor = 0; // Official == even, Preview == odd
+ int build = 1;
+ int revision = 0;
+
+ // string version = String.Format("{0}.{1}.{2}.{3}", major, minor, build, revision);
+
+ // Auto-generate the build and revision
+
+ DateTime buildTime = DateTime.Now;
+
+ build = (1000 * (buildTime.Year % 100)) + buildTime.DayOfYear;
+ revision = (100 * buildTime.Hour) + buildTime.Minute;
+ string version = String.Format("{0}.{1}.{2:00000}.{3:0000}", major, minor, build, revision);
+ #>
+// This code was generated by a tool. Any changes made manually will be lost
+// the next time this code is regenerated.
+
+using System.Reflection;
+using System.Runtime.InteropServices;
+
+[assembly: AssemblyTitle("FCS.Lib.Utility")]
+[assembly: AssemblyDescription("FCS.Lib.Utility")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("FCS")]
+[assembly: AssemblyProduct("FCS.Lib.Utility")]
+[assembly: AssemblyCopyright("AGPL-3.0-or-later Copyright © FCS 2015-2022")]
+[assembly: AssemblyTrademark("© FCS")]
+[assembly: AssemblyCulture("")]
+
+
+[assembly: ComVisible(false)]
+[assembly: Guid("8D850197-78DB-4D16-A91F-E5BB6E8880A7")]
+
+[assembly: AssemblyVersion("<#= version #>")]
[assembly: AssemblyFileVersion("<#= version #>")]
\ No newline at end of file
diff --git a/QueryHelper.cs b/QueryHelper.cs
index d47362a..eb522fd 100644
--- a/QueryHelper.cs
+++ b/QueryHelper.cs
@@ -1,98 +1,98 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 01-01-2022
-//
-// Last Modified By : FH
-// Last Modified On : 02-24-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the Affero GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// Affero GNU General Public License for more details.
-//
-// You should have received a copy of the Affero GNU General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
-//
-//
-// ***********************************************************************
-
-using System;
-using System.Linq;
-using System.Linq.Expressions;
-using System.Reflection;
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Class QueryHelper.
- ///
- public static class QueryHelper
- {
- // https://stackoverflow.com/a/45761590
-
- ///
- /// OrderBy
- ///
- ///
- ///
- ///
- ///
- ///
- public static IQueryable OrderBy (this IQueryable q, string name, bool desc)
- {
- var entityType = typeof(TModel);
- var p = entityType.GetProperty(name);
- var m = typeof(QueryHelper)
- .GetMethod("OrderByProperty")
- ?.MakeGenericMethod(entityType, p.PropertyType);
-
- return(IQueryable) m.Invoke(null, new object[] { q, p , desc });
- }
-
- ///
- /// ThenBy
- ///
- ///
- ///
- ///
- ///
- ///
- public static IQueryable ThenBy (this IQueryable q, string name, bool desc)
- {
- var entityType = typeof(TModel);
- var p = entityType.GetProperty(name);
- var m = typeof(QueryHelper)
- .GetMethod("OrderByProperty")
- ?.MakeGenericMethod(entityType, p.PropertyType);
-
- return(IQueryable) m.Invoke(null, new object[] { q, p , desc });
- }
-
-
- ///
- /// OrderByProperty
- ///
- ///
- ///
- ///
- ///
- ///
- ///
- public static IQueryable OrderByProperty(IQueryable q, PropertyInfo p, bool desc)
- {
- var pe = Expression.Parameter(typeof(TModel));
- Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object));
- var exp = Expression.Lambda>(se, pe);
-
- return desc ? q.OrderByDescending(exp) : q.OrderBy(exp);
- }
-
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 01-01-2022
+//
+// Last Modified By : FH
+// Last Modified On : 02-24-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the Affero GNU General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// Affero GNU General Public License for more details.
+//
+// You should have received a copy of the Affero GNU General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
+//
+//
+// ***********************************************************************
+
+using System;
+using System.Linq;
+using System.Linq.Expressions;
+using System.Reflection;
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Class QueryHelper.
+ ///
+ public static class QueryHelper
+ {
+ // https://stackoverflow.com/a/45761590
+
+ ///
+ /// OrderBy
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IQueryable OrderBy (this IQueryable q, string name, bool desc)
+ {
+ var entityType = typeof(TModel);
+ var p = entityType.GetProperty(name);
+ var m = typeof(QueryHelper)
+ .GetMethod("OrderByProperty")
+ ?.MakeGenericMethod(entityType, p.PropertyType);
+
+ return(IQueryable) m.Invoke(null, new object[] { q, p , desc });
+ }
+
+ ///
+ /// ThenBy
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IQueryable ThenBy (this IQueryable q, string name, bool desc)
+ {
+ var entityType = typeof(TModel);
+ var p = entityType.GetProperty(name);
+ var m = typeof(QueryHelper)
+ .GetMethod("OrderByProperty")
+ ?.MakeGenericMethod(entityType, p.PropertyType);
+
+ return(IQueryable) m.Invoke(null, new object[] { q, p , desc });
+ }
+
+
+ ///
+ /// OrderByProperty
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public static IQueryable OrderByProperty(IQueryable q, PropertyInfo p, bool desc)
+ {
+ var pe = Expression.Parameter(typeof(TModel));
+ Expression se = Expression.Convert(Expression.Property(pe, p), typeof(object));
+ var exp = Expression.Lambda>(se, pe);
+
+ return desc ? q.OrderByDescending(exp) : q.OrderBy(exp);
+ }
+
}}
\ No newline at end of file
diff --git a/README.md b/README.md
index a0577fa..76cd048 100644
--- a/README.md
+++ b/README.md
@@ -1 +1 @@
-# fcs-utils
+# fcs-utils
diff --git a/Squid.cs b/Squid.cs
index 1e3933a..cee9c57 100644
--- a/Squid.cs
+++ b/Squid.cs
@@ -1,395 +1,395 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 2020-07-01
-//
-// Last Modified By : FH
-// Last Modified On : 02-24-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the Affero GNU General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// Affero GNU General Public License for more details.
-//
-// You should have received a copy of the Affero GNU General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
-//
-// Derived from https:github.com/csharpvitamins/CSharpVitamins.ShortGuid
-// ***********************************************************************
-
-using System;
-using System.Diagnostics;
-
-namespace FCS.Lib.Utility
-{
- ///
- /// A wrapper for handling URL-safe Base64 encoded globally unique identifiers (GUID).
- ///
- /// Special characters are replaced (/, +) or removed (==).
- /// Derived from https:github.com/csharpvitamins/CSharpVitamins.ShortGuid
- [DebuggerDisplay("{" + nameof(Value) + "}")]
- public readonly struct Squid : IEquatable
- {
- ///
- /// A read-only object of the Squid struct.
- /// Value is guaranteed to be all zeroes.
- /// Equivalent to .
- ///
- public static readonly Squid Empty = new(Guid.Empty);
-
- ///
- /// Creates a new Squid from a Squid encoded string.
- ///
- /// A valid Squid encodd string.
- public Squid(string value)
- {
- Value = value;
- Guid = DecodeSquid(value);
- }
-
- ///
- /// Creates a new Squid with the given .
- ///
- /// A valid System.Guid object.
- public Squid(Guid obj)
- {
- Value = EncodeGuid(obj);
- Guid = obj;
- }
-
- ///
- /// Gets the underlying for the encoded Squid.
- ///
- /// The unique identifier.
-#pragma warning disable CA1720 // Identifier contains type name
- public Guid Guid { get; }
-#pragma warning restore CA1720 // Identifier contains type name
-
- ///
- /// The encoded string value of the
- /// as an URL-safe Base64 string.
- ///
- /// The value.
- public string Value { get; }
-
- ///
- /// Returns the encoded URL-safe Base64 string.
- ///
- /// A that represents this instance.
- public override string ToString()
- {
- return Value;
- }
-
- ///
- /// Returns a value indicating whether this object and a specified object represent the same type and value.
- /// Compares for equality against other string, Guid and Squid types.
- ///
- /// A Systerm.String, System.Guid or Squid object
- /// true if the specified is equal to this instance; otherwise, false.
- public override bool Equals(object obj)
- {
- return obj is Squid other && Equals(other);
- }
-
- ///
- /// Equality comparison
- ///
- /// A valid Squid object
- /// A boolean indicating equality.
- public bool Equals(Squid obj)
- {
- return Guid.Equals(obj.Guid) && Value == obj.Value;
- }
-
- ///
- /// Returns the hash code for the underlying .
- ///
- /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
- public override int GetHashCode()
- {
- unchecked
- {
- return (Guid.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
- }
- }
-
- ///
- /// Initialises a new object of the Squid using .
- ///
- /// New Squid object
- public static Squid NewGuid()
- {
- return new(Guid.NewGuid());
- }
-
- ///
- /// Encode string as a new Squid encoded string.
- /// The encoding is similar to Base64 with
- /// non-URL safe characters replaced, and padding removed.
- ///
- /// A valid .Tostring().
- /// A 22 character URL-safe Base64 string.
- public static string EncodeString(string value)
- {
- var guid = new Guid(value);
- return EncodeGuid(guid);
- }
-
- ///
- /// Encode a object to Squid.
- /// The encoding is similar to Base64 with
- /// non-URL safe characters replaced, and padding removed.
- ///
- /// A valid object.
- /// A 22 character URL-safe Base64 string.
- public static string EncodeGuid(Guid obj)
- {
- var encoded = Convert.ToBase64String(obj.ToByteArray());
- encoded = encoded
- .Replace("/", "_")
- .Replace("+", "-");
- return encoded.Substring(0, 22);
- }
-
- ///
- /// Decode Squid string to a .
- /// See also or
- /// .
- ///
- /// A valid Squid encoded string.
- /// A new object from the parsed string.
- public static Guid DecodeSquid(string value)
- {
- if (value == null) return Empty;
- value = value
- .Replace("_", "/")
- .Replace("-", "+");
-
- var blob = Convert.FromBase64String(value + "==");
- return new Guid(blob);
- }
-
- ///
- /// Squid to Guid.
- ///
- /// A valid Squid object.
- /// System.Guid object.
- public static Guid FromSquid(Squid obj)
- {
- return obj.Guid;
- }
-
- ///
- /// String to Squid.
- ///
- /// String value to convert
- /// A Squid object.
- public static Squid FromString(string value)
- {
- if (string.IsNullOrEmpty(value))
- return Empty;
- return TryParse(value, out Squid obj) ? obj : Empty;
- }
-
- ///
- /// Decodes the given value to a .
- ///
- /// The Squid encoded string to decode.
- /// A new object from the parsed string.
- /// A boolean indicating if the decode was successful.
- public static bool TryDecode(string value, out Guid obj)
- {
- try
- {
- // Decode as Squid
- obj = DecodeSquid(value);
- return true;
- }
-#pragma warning disable CA1031 // Do not catch general exception types
- catch (Exception)
-#pragma warning restore CA1031 // Do not catch general exception types
- {
- // Return empty Guid
- obj = Guid.Empty;
- return false;
- }
- }
-
- ///
- /// Tries to parse the given string value and
- /// outputs the object.
- ///
- /// The Squid encoded string or string representation of a Guid.
- /// A new object from the parsed string.
- /// A boolean indicating if the parse was successful.
- public static bool TryParse(string value, out Squid obj)
- {
- // Parse as Squid string.
- if (TryDecode(value, out var oGuid))
- {
- obj = oGuid;
- return true;
- }
-
- // Parse as Guid string.
- if (Guid.TryParse(value, out oGuid))
- {
- obj = oGuid;
- return true;
- }
-
- obj = Empty;
- return false;
- }
-
- ///
- /// Tries to parse the string value and
- /// outputs the underlying object.
- ///
- /// The Squid encoded string or string representation of a Guid.
- /// A new object from the parsed string.
- /// A boolean indicating if the parse was successful.
- public static bool TryParse(string value, out Guid obj)
- {
- // Try a Squid string.
- if (TryDecode(value, out obj))
- return true;
-
- // Try a Guid string.
- if (Guid.TryParse(value, out obj))
- return true;
-
- obj = Guid.Empty;
- return false;
- }
-
- #region Operators
-
- ///
- /// Determines if both Squid objects have the same
- /// underlying value.
- ///
- /// The x.
- /// The y.
- /// The result of the operator.
- public static bool operator ==(Squid x, Squid y)
- {
- return x.Guid == y.Guid;
- }
-
- ///
- /// Determines if both objects have the same
- /// underlying value.
- ///
- /// The x.
- /// The y.
- /// The result of the operator.
- public static bool operator ==(Squid x, Guid y)
- {
- return x.Guid == y;
- }
-
- ///
- /// Determines if both objects have the same
- /// underlying value.
- ///
- /// The x.
- /// The y.
- /// The result of the operator.
- public static bool operator ==(Guid x, Squid y)
- {
- return y == x; // NB: order of arguments
- }
-
- ///
- /// Determines if both Squid objects do not have the same
- /// underlying value.
- ///
- /// The x.
- /// The y.
- /// The result of the operator.
- public static bool operator !=(Squid x, Squid y)
- {
- return !(x == y);
- }
-
- ///
- /// Determines if both objects do not have the same
- /// underlying value.
- ///
- /// The x.
- /// The y.
- /// The result of the operator.
- public static bool operator !=(Squid x, Guid y)
- {
- return !(x == y);
- }
-
- ///
- /// Determines if both objects do not have the same
- /// underlying value.
- ///
- /// The x.
- /// The y.
- /// The result of the operator.
- public static bool operator !=(Guid x, Squid y)
- {
- return !(x == y);
- }
-
- ///
- /// Implicitly converts the Squid to
- /// its string equivalent.
- ///
- /// The o squid.
- /// The result of the conversion.
- public static implicit operator string(Squid oSquid)
- {
- return oSquid.Value;
- }
-
- ///
- /// Implicitly converts the Squid to
- /// its equivalent.
- ///
- /// The o squid.
- /// The result of the conversion.
- public static implicit operator Guid(Squid oSquid)
- {
- return oSquid.Guid;
- }
-
- ///
- /// Implicitly converts the string to a Squid.
- ///
- /// The value.
- /// The result of the conversion.
- public static implicit operator Squid(string value)
- {
- if (string.IsNullOrEmpty(value))
- return Empty;
-
- return TryParse(value, out Squid oSquid) ? oSquid : Empty;
- }
-
- ///
- /// Implicitly converts the to a Squid.
- ///
- /// The o unique identifier.
- /// The result of the conversion.
- public static implicit operator Squid(Guid oGuid)
- {
- return oGuid == Guid.Empty ? Empty : new Squid(oGuid);
- }
-
- #endregion
- }
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 2020-07-01
+//
+// Last Modified By : FH
+// Last Modified On : 02-24-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the Affero GNU General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// Affero GNU General Public License for more details.
+//
+// You should have received a copy of the Affero GNU General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses/agpl-3.0.en.html]
+//
+// Derived from https:github.com/csharpvitamins/CSharpVitamins.ShortGuid
+// ***********************************************************************
+
+using System;
+using System.Diagnostics;
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// A wrapper for handling URL-safe Base64 encoded globally unique identifiers (GUID).
+ ///
+ /// Special characters are replaced (/, +) or removed (==).
+ /// Derived from https:github.com/csharpvitamins/CSharpVitamins.ShortGuid
+ [DebuggerDisplay("{" + nameof(Value) + "}")]
+ public readonly struct Squid : IEquatable
+ {
+ ///
+ /// A read-only object of the Squid struct.
+ /// Value is guaranteed to be all zeroes.
+ /// Equivalent to .
+ ///
+ public static readonly Squid Empty = new(Guid.Empty);
+
+ ///
+ /// Creates a new Squid from a Squid encoded string.
+ ///
+ /// A valid Squid encodd string.
+ public Squid(string value)
+ {
+ Value = value;
+ Guid = DecodeSquid(value);
+ }
+
+ ///
+ /// Creates a new Squid with the given .
+ ///
+ /// A valid System.Guid object.
+ public Squid(Guid obj)
+ {
+ Value = EncodeGuid(obj);
+ Guid = obj;
+ }
+
+ ///
+ /// Gets the underlying for the encoded Squid.
+ ///
+ /// The unique identifier.
+#pragma warning disable CA1720 // Identifier contains type name
+ public Guid Guid { get; }
+#pragma warning restore CA1720 // Identifier contains type name
+
+ ///
+ /// The encoded string value of the
+ /// as an URL-safe Base64 string.
+ ///
+ /// The value.
+ public string Value { get; }
+
+ ///
+ /// Returns the encoded URL-safe Base64 string.
+ ///
+ /// A that represents this instance.
+ public override string ToString()
+ {
+ return Value;
+ }
+
+ ///
+ /// Returns a value indicating whether this object and a specified object represent the same type and value.
+ /// Compares for equality against other string, Guid and Squid types.
+ ///
+ /// A Systerm.String, System.Guid or Squid object
+ /// true if the specified is equal to this instance; otherwise, false.
+ public override bool Equals(object obj)
+ {
+ return obj is Squid other && Equals(other);
+ }
+
+ ///
+ /// Equality comparison
+ ///
+ /// A valid Squid object
+ /// A boolean indicating equality.
+ public bool Equals(Squid obj)
+ {
+ return Guid.Equals(obj.Guid) && Value == obj.Value;
+ }
+
+ ///
+ /// Returns the hash code for the underlying .
+ ///
+ /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
+ public override int GetHashCode()
+ {
+ unchecked
+ {
+ return (Guid.GetHashCode() * 397) ^ (Value != null ? Value.GetHashCode() : 0);
+ }
+ }
+
+ ///
+ /// Initialises a new object of the Squid using .
+ ///
+ /// New Squid object
+ public static Squid NewGuid()
+ {
+ return new(Guid.NewGuid());
+ }
+
+ ///
+ /// Encode string as a new Squid encoded string.
+ /// The encoding is similar to Base64 with
+ /// non-URL safe characters replaced, and padding removed.
+ ///
+ /// A valid .Tostring().
+ /// A 22 character URL-safe Base64 string.
+ public static string EncodeString(string value)
+ {
+ var guid = new Guid(value);
+ return EncodeGuid(guid);
+ }
+
+ ///
+ /// Encode a object to Squid.
+ /// The encoding is similar to Base64 with
+ /// non-URL safe characters replaced, and padding removed.
+ ///
+ /// A valid object.
+ /// A 22 character URL-safe Base64 string.
+ public static string EncodeGuid(Guid obj)
+ {
+ var encoded = Convert.ToBase64String(obj.ToByteArray());
+ encoded = encoded
+ .Replace("/", "_")
+ .Replace("+", "-");
+ return encoded.Substring(0, 22);
+ }
+
+ ///
+ /// Decode Squid string to a .
+ /// See also or
+ /// .
+ ///
+ /// A valid Squid encoded string.
+ /// A new object from the parsed string.
+ public static Guid DecodeSquid(string value)
+ {
+ if (value == null) return Empty;
+ value = value
+ .Replace("_", "/")
+ .Replace("-", "+");
+
+ var blob = Convert.FromBase64String(value + "==");
+ return new Guid(blob);
+ }
+
+ ///
+ /// Squid to Guid.
+ ///
+ /// A valid Squid object.
+ /// System.Guid object.
+ public static Guid FromSquid(Squid obj)
+ {
+ return obj.Guid;
+ }
+
+ ///
+ /// String to Squid.
+ ///
+ /// String value to convert
+ /// A Squid object.
+ public static Squid FromString(string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ return Empty;
+ return TryParse(value, out Squid obj) ? obj : Empty;
+ }
+
+ ///
+ /// Decodes the given value to a .
+ ///
+ /// The Squid encoded string to decode.
+ /// A new object from the parsed string.
+ /// A boolean indicating if the decode was successful.
+ public static bool TryDecode(string value, out Guid obj)
+ {
+ try
+ {
+ // Decode as Squid
+ obj = DecodeSquid(value);
+ return true;
+ }
+#pragma warning disable CA1031 // Do not catch general exception types
+ catch (Exception)
+#pragma warning restore CA1031 // Do not catch general exception types
+ {
+ // Return empty Guid
+ obj = Guid.Empty;
+ return false;
+ }
+ }
+
+ ///
+ /// Tries to parse the given string value and
+ /// outputs the object.
+ ///
+ /// The Squid encoded string or string representation of a Guid.
+ /// A new object from the parsed string.
+ /// A boolean indicating if the parse was successful.
+ public static bool TryParse(string value, out Squid obj)
+ {
+ // Parse as Squid string.
+ if (TryDecode(value, out var oGuid))
+ {
+ obj = oGuid;
+ return true;
+ }
+
+ // Parse as Guid string.
+ if (Guid.TryParse(value, out oGuid))
+ {
+ obj = oGuid;
+ return true;
+ }
+
+ obj = Empty;
+ return false;
+ }
+
+ ///
+ /// Tries to parse the string value and
+ /// outputs the underlying object.
+ ///
+ /// The Squid encoded string or string representation of a Guid.
+ /// A new object from the parsed string.
+ /// A boolean indicating if the parse was successful.
+ public static bool TryParse(string value, out Guid obj)
+ {
+ // Try a Squid string.
+ if (TryDecode(value, out obj))
+ return true;
+
+ // Try a Guid string.
+ if (Guid.TryParse(value, out obj))
+ return true;
+
+ obj = Guid.Empty;
+ return false;
+ }
+
+ #region Operators
+
+ ///
+ /// Determines if both Squid objects have the same
+ /// underlying value.
+ ///
+ /// The x.
+ /// The y.
+ /// The result of the operator.
+ public static bool operator ==(Squid x, Squid y)
+ {
+ return x.Guid == y.Guid;
+ }
+
+ ///
+ /// Determines if both objects have the same
+ /// underlying value.
+ ///
+ /// The x.
+ /// The y.
+ /// The result of the operator.
+ public static bool operator ==(Squid x, Guid y)
+ {
+ return x.Guid == y;
+ }
+
+ ///
+ /// Determines if both objects have the same
+ /// underlying value.
+ ///
+ /// The x.
+ /// The y.
+ /// The result of the operator.
+ public static bool operator ==(Guid x, Squid y)
+ {
+ return y == x; // NB: order of arguments
+ }
+
+ ///
+ /// Determines if both Squid objects do not have the same
+ /// underlying value.
+ ///
+ /// The x.
+ /// The y.
+ /// The result of the operator.
+ public static bool operator !=(Squid x, Squid y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines if both objects do not have the same
+ /// underlying value.
+ ///
+ /// The x.
+ /// The y.
+ /// The result of the operator.
+ public static bool operator !=(Squid x, Guid y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Determines if both objects do not have the same
+ /// underlying value.
+ ///
+ /// The x.
+ /// The y.
+ /// The result of the operator.
+ public static bool operator !=(Guid x, Squid y)
+ {
+ return !(x == y);
+ }
+
+ ///
+ /// Implicitly converts the Squid to
+ /// its string equivalent.
+ ///
+ /// The o squid.
+ /// The result of the conversion.
+ public static implicit operator string(Squid oSquid)
+ {
+ return oSquid.Value;
+ }
+
+ ///
+ /// Implicitly converts the Squid to
+ /// its equivalent.
+ ///
+ /// The o squid.
+ /// The result of the conversion.
+ public static implicit operator Guid(Squid oSquid)
+ {
+ return oSquid.Guid;
+ }
+
+ ///
+ /// Implicitly converts the string to a Squid.
+ ///
+ /// The value.
+ /// The result of the conversion.
+ public static implicit operator Squid(string value)
+ {
+ if (string.IsNullOrEmpty(value))
+ return Empty;
+
+ return TryParse(value, out Squid oSquid) ? oSquid : Empty;
+ }
+
+ ///
+ /// Implicitly converts the to a Squid.
+ ///
+ /// The o unique identifier.
+ /// The result of the conversion.
+ public static implicit operator Squid(Guid oGuid)
+ {
+ return oGuid == Guid.Empty ? Empty : new Squid(oGuid);
+ }
+
+ #endregion
+ }
}
\ No newline at end of file
diff --git a/StringOptions.cs b/StringOptions.cs
index 15fb09f..8131aed 100644
--- a/StringOptions.cs
+++ b/StringOptions.cs
@@ -1,76 +1,76 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 2020-09-09
-//
-// Last Modified By : FH
-// Last Modified On : 03-14-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses]
-//
-//
-// ***********************************************************************
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Class StringOptions.
- ///
- public class StringOptions
- {
- ///
- /// Gets or sets the required length of a string
- ///
- /// The length of the required.
- public int RequiredLength { get; set; }
-
- ///
- /// Gets or sets a value indicating whether to [require non letter or digit].
- ///
- /// true if [require non letter or digit]; otherwise, false.
- public bool RequireNonLetterOrDigit { get; set; }
-
- ///
- /// Gets or sets a value indicating whether to [require digit].
- ///
- /// true if [require digit]; otherwise, false.
- public bool RequireDigit { get; set; }
-
- ///
- /// Gets or sets a value indicating whether to [require lowercase].
- ///
- /// true if [require lowercase]; otherwise, false.
- public bool RequireLowercase { get; set; }
-
- ///
- /// Gets or sets a value indicating whether to [require uppercase].
- ///
- /// true if [require uppercase]; otherwise, false.
- public bool RequireUppercase { get; set; }
-
- ///
- /// Gets or sets the required unique chars.
- ///
- /// The required unique chars.
- public int RequiredUniqueChars { get; set; }
-
- ///
- /// Gets or sets a value indicating whether to [require non alphanumeric].
- ///
- /// true if [require non alphanumeric]; otherwise, false.
- public bool RequireNonAlphanumeric { get; set; }
- }
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 2020-09-09
+//
+// Last Modified By : FH
+// Last Modified On : 03-14-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses]
+//
+//
+// ***********************************************************************
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Class StringOptions.
+ ///
+ public class StringOptions
+ {
+ ///
+ /// Gets or sets the required length of a string
+ ///
+ /// The length of the required.
+ public int RequiredLength { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to [require non letter or digit].
+ ///
+ /// true if [require non letter or digit]; otherwise, false.
+ public bool RequireNonLetterOrDigit { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to [require digit].
+ ///
+ /// true if [require digit]; otherwise, false.
+ public bool RequireDigit { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to [require lowercase].
+ ///
+ /// true if [require lowercase]; otherwise, false.
+ public bool RequireLowercase { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to [require uppercase].
+ ///
+ /// true if [require uppercase]; otherwise, false.
+ public bool RequireUppercase { get; set; }
+
+ ///
+ /// Gets or sets the required unique chars.
+ ///
+ /// The required unique chars.
+ public int RequiredUniqueChars { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to [require non alphanumeric].
+ ///
+ /// true if [require non alphanumeric]; otherwise, false.
+ public bool RequireNonAlphanumeric { get; set; }
+ }
}
\ No newline at end of file
diff --git a/VatFormatValidator.cs b/VatFormatValidator.cs
index 7222edf..7088404 100644
--- a/VatFormatValidator.cs
+++ b/VatFormatValidator.cs
@@ -1,233 +1,233 @@
-// ***********************************************************************
-// Assembly : FCS.Lib.Utility
-// Author : FH
-// Created : 03-30-2022
-//
-// Last Modified By : FH
-// Last Modified On : 04-19-2022
-// ***********************************************************************
-//
-// Copyright (C) 2022 FCS Frede's Computer Services.
-// This program is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Affero General Public License as
-// published by the Free Software Foundation, either version 3 of the
-// License, or (at your option) any later version.
-//
-// This program is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Affero General Public License for more details.
-//
-// You should have received a copy of the GNU Affero General Public License
-// along with this program. If not, see [https://www.gnu.org/licenses]
-//
-//
-// ***********************************************************************
-using System.Linq;
-
-namespace FCS.Lib.Utility
-{
- ///
- /// Vat format validator
- ///
- public static class VatFormatValidator
- {
- // https://ec.europa.eu/taxation_customs/vies/faqvies.do#item_11
- // https://ec.europa.eu/taxation_customs/vies/
-
- ///
- /// Check vat number format
- ///
- ///
- ///
- /// bool indicating if the vat number conform to country specification
- public static bool CheckVat(string countryCode, string vatNumber)
- {
- return countryCode.ToUpperInvariant() switch
- {
- "DK" => ValidateFormatDk(vatNumber),
- "NO" => ValidateFormatNo(vatNumber),
- "SE" => ValidateFormatSe(vatNumber),
- _ => false
- };
- }
-
- ///
- /// sanitize vat number
- ///
- ///
- /// sanitized string
- public static string SanitizeVatNumber(string vatNumber)
- {
- vatNumber = vatNumber.ToUpperInvariant();
- return vatNumber
- .Replace(" ", "")
- .Replace("-", "")
- .Replace("_", "")
- .Replace("DK", "")
- .Replace("NO", "")
- .Replace("SE","")
- .Replace("MVA", "");
- }
-
- private static bool ValidateFormatDk(string vatNumber)
- {
- // https://wiki.scn.sap.com/wiki/display/CRM/Denmark
- // 8 digits 0 to 9
- // C1..C7
- // C8 check-digit MOD11
- // C1 > 0
- // R = (2*C1 + 7*C2 + 6*C3 + 5*C4 + 4*C5 + 3*C6 + 2*C7 + C8)
- if(vatNumber.Length == 8 && long.TryParse(vatNumber, out _))
- return ValidateMod11(vatNumber);
- return false;
- }
-
- private static bool ValidateFormatNo(string vatNumber)
- {
- // https://wiki.scn.sap.com/wiki/display/CRM/Norway
- // 12 digits
- // C1..C8 random 0 to 9
- // C9 check-digit MOD11
- // C10 C11 C12 chars == MVA
- try
- {
- if (vatNumber.Length == 9 && long.TryParse(vatNumber, out _))
- return ValidateMod11(vatNumber);
- return false;
- }
- catch
- {
- return false;
- }
- }
-
- private static bool ValidateFormatSe(string vatNumber)
- {
- // https://wiki.scn.sap.com/wiki/display/CRM/Sweden
- // 12 digits 0 to 9
- // C10 = (10 – (18 + 5 + 1 + 8 + 4)MOD10 10) MOD10
- // R = S1 + S3 + S5 + S7 + S9
- // Si = int(Ci/5) + (Ci*2)MOD10)
- // https://www.skatteverket.se/skatter/mervardesskattmoms/momsregistreringsnummer.4.18e1b10334ebe8bc80002649.html
- // C11 C12 == 01 (De två sista siffrorna är alltid 01)
-
- if (vatNumber.Length != 12 || vatNumber.Substring(10) != "01" || !long.TryParse(vatNumber, out _))
- return false;
-
- var r = new[] { 0, 2, 4, 6, 8 }
- .Sum(m => (int)char.GetNumericValue(vatNumber[m]) / 5 +
- (int)char.GetNumericValue(vatNumber[m]) * 2 % 10);
- var c1 = new[] { 1, 3, 5, 7 }.Sum(m => (int)char.GetNumericValue(vatNumber[m]));
- var c10 = (10 - (r + c1) % 10) % 10;
- return $"{vatNumber.Substring(0, 9)}{c10}01" == vatNumber;
- }
-
- private static bool ValidateMod11(string number)
- {
- try
- {
- if (long.Parse(number) == 0)
- return false;
- var sum = 0;
- for (int i = number.Length - 1, multiplier = 1; i >= 0; i--)
- {
- // Console.WriteLine($"char: {number[i]} multiplier: {multiplier}");
- sum += (int)char.GetNumericValue(number[i]) * multiplier;
- if (++multiplier > 7) multiplier = 2;
- }
-
- return sum % 11 == 0;
- }
- catch
- {
- return false;
- }
-
- }
-
- //private static bool ValidateMod10(string number)
- //{
- // if (long.Parse(number) == 0)
- // return false;
-
- // var nDigits = number.Length;
- // var nSum = 0;
- // var isSecond = false;
- // for (var i = nDigits - 1; i >= 0; i--)
- // {
- // var d = (int)char.GetNumericValue(number[i]) - '0';
- // if (isSecond)
- // d *= 2;
- // nSum += d / 10;
- // nSum += d % 10;
- // isSecond = !isSecond;
- // }
- // return nSum % 10 == 0;
- //}
-
- //private static string GetMod10CheckDigit(string number)
- //{
- // var sum = 0;
- // var alt = true;
- // var digits = number.ToCharArray();
- // for (var i = digits.Length - 1; i >= 0; i--)
- // {
- // var curDigit = digits[i] - 48;
- // if (alt)
- // {
- // curDigit *= 2;
- // if (curDigit > 9)
- // curDigit -= 9;
- // }
-
- // sum += curDigit;
- // alt = !alt;
- // }
- // return sum % 10 == 0 ? "0" : (10 - sum % 10).ToString();
- //}
-
- //private string AddMod11CheckDigit(string number)
- //{
- // return number + GetMod11CheckDigit(number);
- //}
-
- //private static string GetMod11CheckDigit(string number)
- //{
- // var sum = 0;
- // for (int i = number.Length - 1, multiplier = 2; i >= 0; i--)
- // {
- // sum += (int)char.GetNumericValue(number[i]) * multiplier;
- // if (++multiplier > 7) multiplier = 2;
- // }
-
- // var modulo = sum % 11;
- // return modulo is 0 or 1 ? "0" : (11 - modulo).ToString();
- //}
-
- //private static bool CheckLuhn(string vatNumber)
- //{
- // // https://www.geeksforgeeks.org/luhn-algorithm/
-
- // var nDigits = vatNumber.Length;
- // var nSum = 0;
- // var isSecond = false;
- // for (var i = nDigits - 1; i >= 0; i--)
- // {
- // var d = (int)char.GetNumericValue(vatNumber[i]) - '0';
- // if (isSecond)
- // d *= 2;
- // // We add two digits to handle
- // // cases that make two digits
- // // after doubling
- // nSum += d / 10;
- // nSum += d % 10;
-
- // isSecond = !isSecond;
- // }
-
- // return nSum % 10 == 0;
- //}
-
- }
+// ***********************************************************************
+// Assembly : FCS.Lib.Utility
+// Author : FH
+// Created : 03-30-2022
+//
+// Last Modified By : FH
+// Last Modified On : 04-19-2022
+// ***********************************************************************
+//
+// Copyright (C) 2022 FCS Frede's Computer Services.
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as
+// published by the Free Software Foundation, either version 3 of the
+// License, or (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with this program. If not, see [https://www.gnu.org/licenses]
+//
+//
+// ***********************************************************************
+using System.Linq;
+
+namespace FCS.Lib.Utility
+{
+ ///
+ /// Vat format validator
+ ///
+ public static class VatFormatValidator
+ {
+ // https://ec.europa.eu/taxation_customs/vies/faqvies.do#item_11
+ // https://ec.europa.eu/taxation_customs/vies/
+
+ ///
+ /// Check vat number format
+ ///
+ ///
+ ///
+ /// bool indicating if the vat number conform to country specification
+ public static bool CheckVat(string countryCode, string vatNumber)
+ {
+ return countryCode.ToUpperInvariant() switch
+ {
+ "DK" => ValidateFormatDk(vatNumber),
+ "NO" => ValidateFormatNo(vatNumber),
+ "SE" => ValidateFormatSe(vatNumber),
+ _ => false
+ };
+ }
+
+ ///
+ /// sanitize vat number
+ ///
+ ///
+ /// sanitized string
+ public static string SanitizeVatNumber(string vatNumber)
+ {
+ vatNumber = vatNumber.ToUpperInvariant();
+ return vatNumber
+ .Replace(" ", "")
+ .Replace("-", "")
+ .Replace("_", "")
+ .Replace("DK", "")
+ .Replace("NO", "")
+ .Replace("SE","")
+ .Replace("MVA", "");
+ }
+
+ private static bool ValidateFormatDk(string vatNumber)
+ {
+ // https://wiki.scn.sap.com/wiki/display/CRM/Denmark
+ // 8 digits 0 to 9
+ // C1..C7
+ // C8 check-digit MOD11
+ // C1 > 0
+ // R = (2*C1 + 7*C2 + 6*C3 + 5*C4 + 4*C5 + 3*C6 + 2*C7 + C8)
+ if(vatNumber.Length == 8 && long.TryParse(vatNumber, out _))
+ return ValidateMod11(vatNumber);
+ return false;
+ }
+
+ private static bool ValidateFormatNo(string vatNumber)
+ {
+ // https://wiki.scn.sap.com/wiki/display/CRM/Norway
+ // 12 digits
+ // C1..C8 random 0 to 9
+ // C9 check-digit MOD11
+ // C10 C11 C12 chars == MVA
+ try
+ {
+ if (vatNumber.Length == 9 && long.TryParse(vatNumber, out _))
+ return ValidateMod11(vatNumber);
+ return false;
+ }
+ catch
+ {
+ return false;
+ }
+ }
+
+ private static bool ValidateFormatSe(string vatNumber)
+ {
+ // https://wiki.scn.sap.com/wiki/display/CRM/Sweden
+ // 12 digits 0 to 9
+ // C10 = (10 – (18 + 5 + 1 + 8 + 4)MOD10 10) MOD10
+ // R = S1 + S3 + S5 + S7 + S9
+ // Si = int(Ci/5) + (Ci*2)MOD10)
+ // https://www.skatteverket.se/skatter/mervardesskattmoms/momsregistreringsnummer.4.18e1b10334ebe8bc80002649.html
+ // C11 C12 == 01 (De två sista siffrorna är alltid 01)
+
+ if (vatNumber.Length != 12 || vatNumber.Substring(10) != "01" || !long.TryParse(vatNumber, out _))
+ return false;
+
+ var r = new[] { 0, 2, 4, 6, 8 }
+ .Sum(m => (int)char.GetNumericValue(vatNumber[m]) / 5 +
+ (int)char.GetNumericValue(vatNumber[m]) * 2 % 10);
+ var c1 = new[] { 1, 3, 5, 7 }.Sum(m => (int)char.GetNumericValue(vatNumber[m]));
+ var c10 = (10 - (r + c1) % 10) % 10;
+ return $"{vatNumber.Substring(0, 9)}{c10}01" == vatNumber;
+ }
+
+ private static bool ValidateMod11(string number)
+ {
+ try
+ {
+ if (long.Parse(number) == 0)
+ return false;
+ var sum = 0;
+ for (int i = number.Length - 1, multiplier = 1; i >= 0; i--)
+ {
+ // Console.WriteLine($"char: {number[i]} multiplier: {multiplier}");
+ sum += (int)char.GetNumericValue(number[i]) * multiplier;
+ if (++multiplier > 7) multiplier = 2;
+ }
+
+ return sum % 11 == 0;
+ }
+ catch
+ {
+ return false;
+ }
+
+ }
+
+ //private static bool ValidateMod10(string number)
+ //{
+ // if (long.Parse(number) == 0)
+ // return false;
+
+ // var nDigits = number.Length;
+ // var nSum = 0;
+ // var isSecond = false;
+ // for (var i = nDigits - 1; i >= 0; i--)
+ // {
+ // var d = (int)char.GetNumericValue(number[i]) - '0';
+ // if (isSecond)
+ // d *= 2;
+ // nSum += d / 10;
+ // nSum += d % 10;
+ // isSecond = !isSecond;
+ // }
+ // return nSum % 10 == 0;
+ //}
+
+ //private static string GetMod10CheckDigit(string number)
+ //{
+ // var sum = 0;
+ // var alt = true;
+ // var digits = number.ToCharArray();
+ // for (var i = digits.Length - 1; i >= 0; i--)
+ // {
+ // var curDigit = digits[i] - 48;
+ // if (alt)
+ // {
+ // curDigit *= 2;
+ // if (curDigit > 9)
+ // curDigit -= 9;
+ // }
+
+ // sum += curDigit;
+ // alt = !alt;
+ // }
+ // return sum % 10 == 0 ? "0" : (10 - sum % 10).ToString();
+ //}
+
+ //private string AddMod11CheckDigit(string number)
+ //{
+ // return number + GetMod11CheckDigit(number);
+ //}
+
+ //private static string GetMod11CheckDigit(string number)
+ //{
+ // var sum = 0;
+ // for (int i = number.Length - 1, multiplier = 2; i >= 0; i--)
+ // {
+ // sum += (int)char.GetNumericValue(number[i]) * multiplier;
+ // if (++multiplier > 7) multiplier = 2;
+ // }
+
+ // var modulo = sum % 11;
+ // return modulo is 0 or 1 ? "0" : (11 - modulo).ToString();
+ //}
+
+ //private static bool CheckLuhn(string vatNumber)
+ //{
+ // // https://www.geeksforgeeks.org/luhn-algorithm/
+
+ // var nDigits = vatNumber.Length;
+ // var nSum = 0;
+ // var isSecond = false;
+ // for (var i = nDigits - 1; i >= 0; i--)
+ // {
+ // var d = (int)char.GetNumericValue(vatNumber[i]) - '0';
+ // if (isSecond)
+ // d *= 2;
+ // // We add two digits to handle
+ // // cases that make two digits
+ // // after doubling
+ // nSum += d / 10;
+ // nSum += d % 10;
+
+ // isSecond = !isSecond;
+ // }
+
+ // return nSum % 10 == 0;
+ //}
+
+ }
}
\ No newline at end of file