diff --git a/.gitignore b/.gitignore index 274c3f1..b3cd828 100644 --- a/.gitignore +++ b/.gitignore @@ -355,3 +355,4 @@ MigrationBackup/ /NuGet/Extensions.cs.3.4.600.nupkg /Extensions.csproj.old /Extensions.New +/Extensions.String.csproj diff --git a/Classes/Extensions.Configuration.cs b/Classes/Extensions.Configuration.cs deleted file mode 100644 index 2f1188b..0000000 --- a/Classes/Extensions.Configuration.cs +++ /dev/null @@ -1,150 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; -using System.Collections.Generic; -using System.IO; -using System.Text.Json; -using static Extensions.Core; - -namespace Extensions -{ - /// - /// Class that carries the configuration for a given tenant. - /// - [Serializable] - public partial class Configuration - { - /// - /// Settings contains the dictionary of all settings. - /// - public Dictionary Settings { get; set; } - = new Dictionary(); - /// - /// Labels contains the Azure Information Protection labels for the tenant. - /// - public Dictionary Labels { get; set; } - = new Dictionary(); - - /// - /// Empty constructor. - /// - public Configuration() - { - } - - /// - /// Method to generate the configuration JSON filename based on the - /// given tenantString. - /// - /// The name of the tenant e.g. for - /// contoso.sharepoint.us it would be 'contoso'. - /// The filename of the configuration JSON file. - internal static string GetConfigFileName(string tenantString) - { - return $"UniversalConfig.{tenantString}.json"; - } - - /// - /// Method to generate the labels JSON filename based on the - /// given tenantString. - /// - /// The name of the tenant e.g. for - /// contoso.sharepoint.us it would be 'contoso'. - /// The filename of the label JSON file. - internal static string GetLabelsFileName(string tenantString) - { - return $"Labels.{tenantString}.json"; - } - - /// - /// Method to load the configuration JSON files. - /// - /// The name of the tenant e.g. for - /// contoso.sharepoint.us it would be 'contoso'. - internal void LoadConfig(string tenantString) - { - Inf("Loading config from [" + - $"{Core.GetRunFolder()}\\{GetConfigFileName(tenantString)}]"); - Settings = LoadJSON($"{Core.GetRunFolder()}" + - $"\\{GetConfigFileName(tenantString)}"); - Labels = LoadJSON($"{Core.GetRunFolder()}" + - $"\\{GetLabelsFileName(tenantString)}"); - Inf($"[{Settings.Count}] settings and [{Labels.Count}] labels loaded."); - } - - /// - /// Method to load a JSON file with dictionary values. - /// - /// The name of the file to load. - /// A dictionary of strings from the JSON file. - internal static Dictionary LoadJSON(string filePath) - { - var result = new Dictionary(); - using (StreamReader reader = new StreamReader(filePath)) - { - result = JsonSerializer.Deserialize< - Dictionary>(reader.ReadToEnd()); - } - return result; - } - - /// - /// Method to initialize a given tenant for further operations. - /// - /// The name of the tenant e.g. for - /// contoso.sharepoint.us it would be 'contoso'. - /// The TenantConfig object fully initialized and authorized - /// with HttpClient and GraphServiceClient objects ready for use. - public TenantConfig InitializeTenant(string tenantString) - { - try - { - Inf($"Initializing tenant [{tenantString}] settings"); - if (Tenants.ContainsKey(tenantString)) - { - ActiveTenant = Tenants[tenantString]; - return ActiveTenant; - } - var tenant = new TenantConfig(tenantString); - LoadConfig(tenantString); - tenant.AzureEnvironment = GetAzureEnvironment( - GetEnv("AzureEnvironment")); - tenant.TenantDirectoryId = GetEnv("TenantDirectoryId"); - tenant.ApplicationClientId = GetEnv("ApplicationClientId"); - tenant.CertStoreLocation = GetEnv("CertStoreLocation"); - tenant.CertThumbprint = GetEnv("CertThumbprint"); - tenant.DebugEnabled = - GetEnv("DebugEnabled") == "" ? - true : - Convert.ToBoolean(GetEnv("DebugEnabled")); - tenant.MultiThreaded = - GetEnv("MultiThreaded") == "" ? - true : - Convert.ToBoolean(GetEnv("MultiThreaded")); - tenant.LogitSiteBaseUrl = GetEnv("LogitSiteBaseUrl"); - tenant.LogitSiteId = GetEnv("LogitSiteId"); - tenant.LogitDefaultListGuid = GetEnv("LogitDefaultListGuid"); - if (GetEnv("DefaultBlobContainer") == "") - { - SetEnv("DefaultBlobContainer", "provisioning-blob"); - } - if (GetEnv("EmailSendingAccount") == "") - { - SetEnv("DefaultBlobContainer", "C@contoso.com"); - } - CoreBase.Initialize(tenantString); - return tenant; - } - catch (Exception ex) - { - Err(ex.ToString()); - throw; - } - } - } -} diff --git a/Classes/Extensions.Constants.cs b/Classes/Extensions.Constants.cs deleted file mode 100644 index 075b8aa..0000000 --- a/Classes/Extensions.Constants.cs +++ /dev/null @@ -1,774 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; -using System.Collections.Generic; - -namespace Extensions -{ - /// - /// Constants used in the Extensions methods. - /// - [Serializable] - public static partial class Constants - { - #region Binary Constants - - /// - /// Enum of the binary number types. - /// - public enum NumberType - { - - Bytes, - KB, - MB, - GB, - TB, - PB, - EB, - ZB, - YB, - BB, - GpB, - SB, - PaB, - AB, - PlB, - BrB, - SoB, - QB, - KaB, - RB, - DB, - HB, - MrB, - DdB, - RtB, - ShB, - CB, - KkB - } - - /// - /// Number of bits per byte. - /// - public const double BitsPerByte = 8; - - /// - /// Number of bytes in a Kilobyte. - /// - public const double KB = 1024; - - /// - /// Number of bytes in a Megabyte. - /// - public const double MB = KB * 1024; - - /// - /// Number of bytes in a Gigabyte. - /// - public const double GB = MB * 1024; - - /// - /// Number of bytes in a Terabyte. - /// - public const double TB = GB * 1024; - - /// - /// Number of bytes in a Petabyte. - /// - public const double PB = TB * 1024; - - /// - /// Number of bytes in a Exabyte. - /// - public const double EB = PB * 1024; - - /// - /// Number of bytes in a Zettabyte. - /// - public const double ZB = EB * 1024; - - /// - /// Number of bytes in a Yottabyte. - /// - public const double YB = ZB * 1024; - - /// - /// Number of bytes in a Brontobyte. - /// - public const double BB = YB * 1024; - - /// - /// Number of bytes in a Geopbyte. - /// - public const double GpB = BB * 1024; - - /// - /// Number of bytes in a Saganbyte. - /// - public const double SB = GpB * 1024; - - /// - /// Number of bytes in a Pijabyte. - /// - public const double PaB = SB * 1024; - - /// - /// Number of bytes in a Alphabyte. - /// - public const double AB = PaB * 1024; - - /// - /// Number of bytes in a Pectrolbyte. - /// - public const double PlB = AB * 1024; - - /// - /// Number of bytes in a Bolgerbyte. - /// - public const double BrB = PlB * 1024; - - /// - /// Number of bytes in a Sambobyte. - /// - public const double SoB = BrB * 1024; - - /// - /// Number of bytes in a Quesabyte. - /// - public const double QB = SoB * 1024; - - /// - /// Number of bytes in a Kinsabyte. - /// - public const double KaB = QB * 1024; - - /// - /// Number of bytes in a Rutherbyte. - /// - public const double RB = KaB * 1024; - - /// - /// Number of bytes in a Dubnibyte. - /// - public const double DB = RB * 1024; - - /// - /// Number of bytes in a Hassiubyte. - /// - public const double HB = DB * 1024; - - /// - /// Number of bytes in a Meitnerbyte. - /// - public const double MrB = HB * 1024; - - /// - /// Number of bytes in a Darmstadbyte. - /// - public const double DdB = MrB * 1024; - - /// - /// Number of bytes in a Roentbyte. - /// - public const double RtB = DdB * 1024; - - /// - /// Number of bytes in a Sophobyte. - /// - public const double ShB = RtB * 1024; - - /// - /// Number of bytes in a Coperbyte. - /// - public const double CB = ShB * 1024; - - /// - /// Number of bytes in a Koentekbyte. *1024^81 - /// - public const double KkB = CB * 1024; - - /// - /// Number of bytes in a CornelionByte. *1024^100000000 - /// Cornelion = "1 x 10 ^ 100,000,000"; - /// - public const string CornelionByte = "1 x 10 ^ 100,000,000"; - #endregion Binary Constants - - #region CompoundFrequency - /// - /// Enum of possible frequency in which interest compounding is done. - /// - public enum CompoundFrequency - { - Monthly, - Yearly - }; - #endregion CompoundFrequency - - #region Cryptography - /// - /// List of encryption providers to use. - /// - public enum EncryptionProvider - { - AES, - DES, - DSA, - MD5, - RNG, - RSA, - SHA1, - SHA256, - SHA384, - SHA512, - TrippleDES - } - #endregion Cryptography - - #region EnumerationType - /// - /// Enum of possible enumerable types. - /// - public enum EnumerableType - { - Dictionary, - NameValueCollection - }; - #endregion EnumerationType - - #region ErrorType - /// - /// Enum of error types to validate. - /// - public enum ErrorType - { - Null, - IntNonNegative - }; - - /// - /// Array holding all error types for easier passing. - /// - public static ErrorType[] ErrorTypeAll = - { - ErrorType.Null, - ErrorType.IntNonNegative - }; - #endregion ErrorType - - #region DuplicateGroupReturnType - /// - /// The types of data that can be returned after the duplication of - /// an M365 Group i.e. the GUID ID of the Group or the Group itself. - /// - public enum DuplicateGroupReturnType - { - Group, - Id - } - #endregion DuplicateGroupReturnType - - #region Graph Constants - /// - /// The types of Graph user info to retrieve. The id, mail and - /// userProfileName values use camel case to allow their .ToString() - /// values to be used in the query constructor. - /// - public enum UserInfoType - { - All, - id, - mail, - userProfileName - } - - /// - /// The type of Group membership users to retrieve i.e. Owners of the - /// Group, Members of the Group or both. - /// - public enum GroupUserMembershipType - { - All, - Members, - Owners - } - - /// - /// The type of string being passed to the .UpdateGroup() method i.e. - /// the display name of the Group or the Group's GUID ID value. - /// - public enum GroupUpdateType - { - DisplayName, - Guid - } - #endregion Graph Constants - - #region Help - /// - /// String array of args that will trigger help text. - /// - public readonly static string[] HelpStrings = - { - "/?", - "?", - "/help", - "help", - "-help", - "/huh", - "huh", - "-huh" - }; - #endregion Help - - #region Hexadecimal - /// - /// Character array of all hexadecimal lower case characters. - /// - public readonly static char[] HexChars = - { - '0', - '1', - '2', - '3', - '4', - '5', - '6', - '7', - '8', - '9', - 'a', - 'b', - 'c', - 'd', - 'e', - 'f' - }; - #endregion Hexadecimal - - #region LoremIpsum - /// - /// String array of lorem ipsum text. - /// - public readonly static string[] LoremIpsum = - { - "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer aliquam arcu rhoncus erat consectetur, quis rutrum augue tincidunt. Suspendisse elit ipsum, lobortis lobortis tellus eu, vulputate fringilla lorem. Cras molestie nibh sed turpis dapibus sollicitudin ut a nulla. Suspendisse blandit suscipit egestas. Nunc et ante mattis nulla vehicula rhoncus. Vivamus commodo nunc id ultricies accumsan. Mauris vitae ante ut justo venenatis tempus.", - "Nunc posuere, nisi eu convallis convallis, quam urna sagittis ipsum, et tempor ante libero ac ex. Aenean lacus mi, blandit non eros luctus, ultrices consectetur nunc. Vivamus suscipit justo odio, a porta massa posuere ac. Aenean varius leo non ipsum porttitor eleifend. Phasellus accumsan ultrices massa et finibus. Nunc vestibulum augue ut bibendum facilisis. Donec est massa, lobortis quis molestie at, placerat a neque. Donec quis bibendum leo. Pellentesque ultricies ac odio id pharetra. Nulla enim massa, lacinia nec nunc nec, egestas pulvinar odio. Sed pulvinar molestie justo, eu hendrerit nunc blandit eu. Suspendisse et sapien quis ipsum scelerisque rutrum.", - "Mauris eget convallis lorem, rutrum venenatis risus. Cras turpis risus, convallis nec lectus id, blandit varius ante. Morbi id turpis vel neque gravida consequat in elementum tellus. Fusce venenatis ex eget quam tincidunt varius. Mauris non mauris est. Vestibulum eget pharetra risus, sit amet accumsan elit. Etiam rhoncus tristique mauris. Ut convallis dignissim dictum. Vivamus dolor augue, vulputate a consequat ut, euismod finibus mi. Morbi sit amet pellentesque lectus.", - "Nullam mattis cursus lorem ut venenatis. Praesent et sapien at tellus feugiat varius non eget orci. Maecenas sodales orci vitae rhoncus posuere. Aliquam erat volutpat. Nullam nulla sapien, faucibus sit amet porttitor vitae, fermentum ut orci. Etiam accumsan lacus quis tortor posuere, vitae tristique urna porta. Proin urna velit, lobortis ut gravida sit amet, iaculis vitae tellus. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Etiam porttitor metus eu finibus malesuada. Vivamus lobortis mauris id erat condimentum, ac laoreet mauris tristique. Fusce sit amet arcu purus. Donec quam enim, ultrices luctus nisi eget, vestibulum porta enim. Fusce sed iaculis metus, nec fermentum nisl. Pellentesque in condimentum risus, a fringilla turpis.", - "In in interdum lectus. Quisque aliquet sem ac ante tincidunt, at sodales libero mollis. In suscipit felis vitae mauris ultricies, at commodo magna hendrerit. Pellentesque convallis, justo a fermentum dapibus, augue quam tempor lectus, ac dignissim magna tellus luctus odio. Morbi sed vestibulum diam. Proin sodales urna vitae ex cursus volutpat. Cras dapibus quam velit, eu ultrices est rhoncus id. Sed sit amet ligula eget nisl tempus iaculis. Donec et lacus a tellus volutpat suscipit sed in nisi. Vivamus placerat semper ex et pellentesque.", - "Sed pulvinar felis ut ipsum feugiat sollicitudin. Mauris ut nisi vel nibh vestibulum pellentesque. Sed dignissim rhoncus mattis. Duis in placerat magna. Duis interdum lorem sed consequat molestie. Proin maximus dolor sit amet placerat pellentesque. Proin porttitor magna at ante vestibulum, sed egestas tortor maximus. Vestibulum nec tristique neque, eget euismod mauris. Aliquam non enim metus. Curabitur iaculis tellus dui, id tempor metus fringilla id. Phasellus ante tellus, egestas eu risus in, lacinia molestie purus. Fusce ultricies vehicula massa a vehicula. Proin at magna quis nunc faucibus ultricies eget eu orci. Aenean cursus lorem eros, in tempor magna mattis sed. Donec ac bibendum risus. Phasellus urna ante, sodales at leo eu, lobortis faucibus risus.", - "Cras aliquam metus vel purus suscipit vehicula. Curabitur dignissim velit eget ante mollis sollicitudin. Sed id lorem nec mi varius aliquet at nec lorem. Nullam vel lorem libero. Mauris rhoncus dolor non facilisis feugiat. Suspendisse cursus vel elit non porta. Duis sodales vel nisl non pharetra.", - "Integer mi libero, tincidunt id erat ut, sollicitudin laoreet est. Aliquam non lectus luctus, placerat ligula semper, vestibulum arcu. Fusce ut lobortis quam. Nunc et mollis lectus. Curabitur condimentum ac nisi quis congue. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nam porttitor elit eget elit finibus, sed sagittis tortor aliquet. Sed et accumsan dui, lobortis luctus eros. Cras a dolor turpis. Aenean mollis, nulla sit amet eleifend cursus, arcu erat dignissim neque, non egestas ligula metus at purus. Etiam hendrerit magna ut vehicula sodales. Duis dictum lorem in magna bibendum eleifend. Cras sed diam ut sem pretium vestibulum sed non nibh. Morbi finibus enim nec lacus aliquet, id convallis sapien vulputate.", - "In hac habitasse platea dictumst. Vivamus sit amet ornare magna. Curabitur sollicitudin viverra nibh, sit amet tempor nisl dictum nec. Integer in auctor sem. Phasellus accumsan ante mollis dui feugiat, non semper augue posuere. Cras ac faucibus nulla, id elementum ante. Nulla ipsum felis, semper id eleifend in, placerat nec ipsum. Nunc ut leo tincidunt, facilisis leo egestas, sollicitudin lacus. Curabitur at ex eget libero convallis volutpat.", - "Nulla facilisi. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque eu tristique lacus, sed porta nisl. Orci varius natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Vestibulum libero neque, faucibus sed condimentum sed, aliquet vitae massa. Sed dignissim a velit tempus feugiat. Etiam sollicitudin, neque sit amet posuere semper, enim enim facilisis quam, ac sollicitudin lectus purus ut urna. Vivamus interdum odio nec felis interdum mollis. Praesent et massa quis augue accumsan laoreet. Nullam ultrices, dui ac condimentum cursus, lectus elit molestie velit, vitae consequat elit arcu sed massa. Praesent at lacinia ante, varius lacinia urna. Donec pretium gravida nunc, sed congue mi tincidunt eu. Aenean ut diam eget orci dignissim placerat. Pellentesque fermentum aliquet velit et fermentum. Etiam ut risus dapibus, dictum augue ac, ornare metus." - }; - #endregion LoremIpsum - - #region Mersenne - /// - /// Enum of possible comparison types in the Mersenne type. - /// - public enum MersenneComparisonType - { - Greater, - Less - }; - #endregion Mersenne - - #region Morse - /// - /// Dictionary of alphabetic to Morse code translation values. - /// - public readonly static Dictionary MorseCode = new Dictionary() - { - {'a', ".-"}, - {'b', "-..."}, - {'c', "-.-."}, - {'d', "-.."}, - {'e', "."}, - {'f', "..-."}, - {'g', "--."}, - {'h', "...."}, - {'i', ".."}, - {'j', ".---"}, - {'k', "-.-"}, - {'l', ".-.."}, - {'m', "--"}, - {'n', "-."}, - {'o', "---"}, - {'p', ".--."}, - {'q', "--.-"}, - {'r', ".-."}, - {'s', "..."}, - {'t', "-"}, - {'u', "..-"}, - {'v', "...-"}, - {'w', ".--"}, - {'x', "-..-"}, - {'y', "-.--"}, - {'z', "--.."}, - {'0', "-----"}, - {'1', ".----"}, - {'2', "..---"}, - {'3', "...--"}, - {'4', "....-"}, - {'5', "....."}, - {'6', "-...."}, - {'7', "--..."}, - {'8', "---.."}, - {'9', "----."}, - {'.',".-.-.-"}, - {',',"--.--"}, - {'?',"..--.."}, - {' ',"-...-"} - }; - #endregion Morse - - #region Quote - /// - /// Enum of possible quote types. - /// - public enum QuoteType - { - Single, - Double - }; - #endregion Quote - - #region Substring - /// - /// List of processing options for .Substring() method. - /// - public enum SubstringType - { - FromHead, - FromTail, - LeftOfIndex, - RigthOfIndex, - IndexValue - }; - #endregion Substring - - #region TimeSpan - /// - /// Enum for the timespan type returned from .Sum() - /// - public enum TimeSpanSumType - { - Seconds, - Minutes, - Hours, - Days, - Weeks, - Years, - Decades, - Centuries, - Mellinnia - }; - #endregion TimeSpan - - #region TimeZone - /// - /// Enum of possible time zones. - /// - public enum TimeZone - { - AfghanistanStandardTime, - AlaskanStandardTime, - AleutianStandardTime, - AltaiStandardTime, - ArabStandardTime, - ArabianStandardTime, - ArabicStandardTime, - ArgentinaStandardTime, - AstrakhanStandardTime, - AtlanticStandardTime, - AUSCentralStandardTime, - AusCentralWStandardTime, - AUSEasternStandardTime, - AzerbaijanStandardTime, - AzoresStandardTime, - BahiaStandardTime, - BangladeshStandardTime, - BelarusStandardTime, - BougainvilleStandardTime, - CanadaCentralStandardTime, - CapeVerdeStandardTime, - CaucasusStandardTime, - CenAustraliaStandardTime, - CentralAmericaStandardTime, - CentralAsiaStandardTime, - CentralBrazilianStandardTime, - CentralEuropeStandardTime, - CentralEuropeanStandardTime, - CentralPacificStandardTime, - CentralStandardTime, - CentralStandardTimeMexico, - ChathamIslandsStandardTime, - ChinaStandardTime, - CubaStandardTime, - DatelineStandardTime, - EAfricaStandardTime, - EAustraliaStandardTime, - EEuropeStandardTime, - ESouthAmericaStandardTime, - EasterIslandStandardTime, - EasternStandardTime, - EasternStandardTimeMexico, - EgyptStandardTime, - EkaterinburgStandardTime, - FijiStandardTime, - FLEStandardTime, - GeorgianStandardTime, - GMTStandardTime, - GreenlandStandardTime, - GreenwichStandardTime, - GTBStandardTime, - HaitiStandardTime, - HawaiianStandardTime, - IndiaStandardTime, - IranStandardTime, - IsraelStandardTime, - JordanStandardTime, - KaliningradStandardTime, - KamchatkaStandardTime, - KoreaStandardTime, - LibyaStandardTime, - LineIslandsStandardTime, - LordHoweStandardTime, - MagadanStandardTime, - MagallanesStandardTime, - MarquesasStandardTime, - MauritiusStandardTime, - MidAtlanticStandardTime, - MiddleEastStandardTime, - MontevideoStandardTime, - MoroccoStandardTime, - MountainStandardTime, - MountainStandardTimeMexico, - MyanmarStandardTime, - NCentralAsiaStandardTime, - NamibiaStandardTime, - NepalStandardTime, - NewZealandStandardTime, - NewfoundlandStandardTime, - NorfolkStandardTime, - NorthAsiaEastStandardTime, - NorthAsiaStandardTime, - NorthKoreaStandardTime, - OmskStandardTime, - PacificSAStandardTime, - PacificStandardTime, - PacificStandardTimeMexico, - PakistanStandardTime, - ParaguayStandardTime, - QyzylordaStandardTime, - RomanceStandardTime, - RussiaTimeZone10, - RussiaTimeZone11, - RussiaTimeZone3, - RussianStandardTime, - SAEasternStandardTime, - SAPacificStandardTime, - SAWesternStandardTime, - SaintPierreStandardTime, - SakhalinStandardTime, - SamoaStandardTime, - SaoTomeStandardTime, - SaratovStandardTime, - SEAsiaStandardTime, - SingaporeStandardTime, - SouthAfricaStandardTime, - SriLankaStandardTime, - SudanStandardTime, - SyriaStandardTime, - TaipeiStandardTime, - TasmaniaStandardTime, - TocantinsStandardTime, - TokyoStandardTime, - TomskStandardTime, - TongaStandardTime, - TransbaikalStandardTime, - TurkeyStandardTime, - TurksAndCaicosStandardTime, - UlaanbaatarStandardTime, - USEasternStandardTime, - USMountainStandardTime, - UTC, - UTCPlus12, - UTCPlus13, - UTCMinus02, - UTCMinus08, - UTCMinus09, - UTCMinus11, - VenezuelaStandardTime, - VladivostokStandardTime, - VolgogradStandardTime, - WAustraliaStandardTime, - WCentralAfricaStandardTime, - WEuropeStandardTime, - WMongoliaStandardTime, - WestAsiaStandardTime, - WestBankStandardTime, - WestPacificStandardTime, - YakutskStandardTime, - YukonStandardTime - }; - - /// - /// Dictionary of time zones and their TimeZoneInfo registry strings. - /// - public readonly static Dictionary TimeZones = new Dictionary() - { - { TimeZone.AfghanistanStandardTime, "Afghanistan Standard Time" }, - { TimeZone.AlaskanStandardTime, "Alaskan Standard Time" }, - { TimeZone.AleutianStandardTime, "Aleutian Standard Time" }, - { TimeZone.AltaiStandardTime, "Altai Standard Time" }, - { TimeZone.ArabStandardTime, "Arab Standard Time" }, - { TimeZone.ArabianStandardTime, "Arabian Standard Time" }, - { TimeZone.ArabicStandardTime, "Arabic Standard Time" }, - { TimeZone.ArgentinaStandardTime, "Argentina Standard Time" }, - { TimeZone.AstrakhanStandardTime, "Astrakhan Standard Time" }, - { TimeZone.AtlanticStandardTime, "Atlantic Standard Time" }, - { TimeZone.AUSCentralStandardTime, "AUS Central Standard Time" }, - { TimeZone.AusCentralWStandardTime, "Aus Central W. Standard Time" }, - { TimeZone.AUSEasternStandardTime, "AUS Eastern Standard Time" }, - { TimeZone.AzerbaijanStandardTime, "Azerbaijan Standard Time" }, - { TimeZone.AzoresStandardTime, "Azores Standard Time" }, - { TimeZone.BahiaStandardTime, "Bahia Standard Time" }, - { TimeZone.BangladeshStandardTime, "Bangladesh Standard Time" }, - { TimeZone.BelarusStandardTime, "Belarus Standard Time" }, - { TimeZone.BougainvilleStandardTime, "Bougainville Standard Time" }, - { TimeZone.CanadaCentralStandardTime, "Canada Central Standard Time" }, - { TimeZone.CapeVerdeStandardTime, "Cape Verde Standard Time" }, - { TimeZone.CaucasusStandardTime, "Caucasus Standard Time" }, - { TimeZone.CenAustraliaStandardTime, "Cen. Australia Standard Time" }, - { TimeZone.CentralAmericaStandardTime, "Central America Standard Time" }, - { TimeZone.CentralAsiaStandardTime, "Central Asia Standard Time" }, - { TimeZone.CentralBrazilianStandardTime, "Central Brazilian Standard Time" }, - { TimeZone.CentralEuropeStandardTime, "Central Europe Standard Time" }, - { TimeZone.CentralEuropeanStandardTime, "Central European Standard Time" }, - { TimeZone.CentralPacificStandardTime, "Central Pacific Standard Time" }, - { TimeZone.CentralStandardTime, "Central Standard Time" }, - { TimeZone.CentralStandardTimeMexico, "Central Standard Time (Mexico)" }, - { TimeZone.ChathamIslandsStandardTime, "Chatham Islands Standard Time" }, - { TimeZone.ChinaStandardTime, "China Standard Time" }, - { TimeZone.CubaStandardTime, "Cuba Standard Time" }, - { TimeZone.DatelineStandardTime, "Dateline Standard Time" }, - { TimeZone.EAfricaStandardTime, "E. Africa Standard Time" }, - { TimeZone.EAustraliaStandardTime, "E. Australia Standard Time" }, - { TimeZone.EEuropeStandardTime, "E. Europe Standard Time" }, - { TimeZone.ESouthAmericaStandardTime, "E. South America Standard Time" }, - { TimeZone.EasterIslandStandardTime, "Easter Island Standard Time" }, - { TimeZone.EasternStandardTime, "Eastern Standard Time" }, - { TimeZone.EasternStandardTimeMexico, "Eastern Standard Time (Mexico)" }, - { TimeZone.EgyptStandardTime, "Egypt Standard Time" }, - { TimeZone.EkaterinburgStandardTime, "Ekaterinburg Standard Time" }, - { TimeZone.FijiStandardTime, "Fiji Standard Time" }, - { TimeZone.FLEStandardTime, "FLE Standard Time" }, - { TimeZone.GeorgianStandardTime, "Georgian Standard Time" }, - { TimeZone.GMTStandardTime, "GMT Standard Time" }, - { TimeZone.GreenlandStandardTime, "Greenland Standard Time" }, - { TimeZone.GreenwichStandardTime, "Greenwich Standard Time" }, - { TimeZone.GTBStandardTime, "GTB Standard Time" }, - { TimeZone.HaitiStandardTime, "Haiti Standard Time" }, - { TimeZone.HawaiianStandardTime, "Hawaiian Standard Time" }, - { TimeZone.IndiaStandardTime, "India Standard Time" }, - { TimeZone.IranStandardTime, "Iran Standard Time" }, - { TimeZone.IsraelStandardTime, "Israel Standard Time" }, - { TimeZone.JordanStandardTime, "Jordan Standard Time" }, - { TimeZone.KaliningradStandardTime, "Kaliningrad Standard Time" }, - { TimeZone.KamchatkaStandardTime, "Kamchatka Standard Time" }, - { TimeZone.KoreaStandardTime, "Korea Standard Time" }, - { TimeZone.LibyaStandardTime, "Libya Standard Time" }, - { TimeZone.LineIslandsStandardTime, "Line Islands Standard Time" }, - { TimeZone.LordHoweStandardTime, "Lord Howe Standard Time" }, - { TimeZone.MagadanStandardTime, "Magadan Standard Time" }, - { TimeZone.MagallanesStandardTime, "Magallanes Standard Time" }, - { TimeZone.MarquesasStandardTime, "Marquesas Standard Time" }, - { TimeZone.MauritiusStandardTime, "Mauritius Standard Time" }, - { TimeZone.MidAtlanticStandardTime, "Mid-Atlantic Standard Time" }, - { TimeZone.MiddleEastStandardTime, "Middle East Standard Time" }, - { TimeZone.MontevideoStandardTime, "Montevideo Standard Time" }, - { TimeZone.MoroccoStandardTime, "Morocco Standard Time" }, - { TimeZone.MountainStandardTime, "Mountain Standard Time" }, - { TimeZone.MountainStandardTimeMexico, "Mountain Standard Time (Mexico)" }, - { TimeZone.MyanmarStandardTime, "Myanmar Standard Time" }, - { TimeZone.NCentralAsiaStandardTime, "N. Central Asia Standard Time" }, - { TimeZone.NamibiaStandardTime, "Namibia Standard Time" }, - { TimeZone.NepalStandardTime, "Nepal Standard Time" }, - { TimeZone.NewZealandStandardTime, "New Zealand Standard Time" }, - { TimeZone.NewfoundlandStandardTime, "Newfoundland Standard Time" }, - { TimeZone.NorfolkStandardTime, "Norfolk Standard Time" }, - { TimeZone.NorthAsiaEastStandardTime, "North Asia East Standard Time" }, - { TimeZone.NorthAsiaStandardTime, "North Asia Standard Time" }, - { TimeZone.NorthKoreaStandardTime, "North Korea Standard Time" }, - { TimeZone.OmskStandardTime, "Omsk Standard Time" }, - { TimeZone.PacificSAStandardTime, "Pacific SA Standard Time" }, - { TimeZone.PacificStandardTime, "Pacific Standard Time" }, - { TimeZone.PacificStandardTimeMexico, "Pacific Standard Time (Mexico)" }, - { TimeZone.PakistanStandardTime, "Pakistan Standard Time" }, - { TimeZone.ParaguayStandardTime, "Paraguay Standard Time" }, - { TimeZone.QyzylordaStandardTime, "Qyzylorda Standard Time" }, - { TimeZone.RomanceStandardTime, "Romance Standard Time" }, - { TimeZone.RussiaTimeZone10, "Russia Time Zone 10" }, - { TimeZone.RussiaTimeZone11, "Russia Time Zone 11" }, - { TimeZone.RussiaTimeZone3, "Russia Time Zone 3" }, - { TimeZone.RussianStandardTime, "Russian Standard Time" }, - { TimeZone.SAEasternStandardTime, "SA Eastern Standard Time" }, - { TimeZone.SAPacificStandardTime, "SA Pacific Standard Time" }, - { TimeZone.SAWesternStandardTime, "SA Western Standard Time" }, - { TimeZone.SaintPierreStandardTime, "Saint Pierre Standard Time" }, - { TimeZone.SakhalinStandardTime, "Sakhalin Standard Time" }, - { TimeZone.SamoaStandardTime, "Samoa Standard Time" }, - { TimeZone.SaoTomeStandardTime, "Sao Tome Standard Time" }, - { TimeZone.SaratovStandardTime, "Saratov Standard Time" }, - { TimeZone.SEAsiaStandardTime, "SE Asia Standard Time" }, - { TimeZone.SingaporeStandardTime, "Singapore Standard Time" }, - { TimeZone.SouthAfricaStandardTime, "South Africa Standard Time" }, - { TimeZone.SriLankaStandardTime, "Sri Lanka Standard Time" }, - { TimeZone.SudanStandardTime, "Sudan Standard Time" }, - { TimeZone.SyriaStandardTime, "Syria Standard Time" }, - { TimeZone.TaipeiStandardTime, "Taipei Standard Time" }, - { TimeZone.TasmaniaStandardTime, "Tasmania Standard Time" }, - { TimeZone.TocantinsStandardTime, "Tocantins Standard Time" }, - { TimeZone.TokyoStandardTime, "Tokyo Standard Time" }, - { TimeZone.TomskStandardTime, "Tomsk Standard Time" }, - { TimeZone.TongaStandardTime, "Tonga Standard Time" }, - { TimeZone.TransbaikalStandardTime, "Transbaikal Standard Time" }, - { TimeZone.TurkeyStandardTime, "Turkey Standard Time" }, - { TimeZone.TurksAndCaicosStandardTime, "Turks And Caicos Standard Time" }, - { TimeZone.UlaanbaatarStandardTime, "Ulaanbaatar Standard Time" }, - { TimeZone.USEasternStandardTime, "US Eastern Standard Time" }, - { TimeZone.USMountainStandardTime, "US Mountain Standard Time" }, - { TimeZone.UTC, "UTC" }, - { TimeZone.UTCPlus12, "UTC+12" }, - { TimeZone.UTCPlus13, "UTC+13" }, - { TimeZone.UTCMinus02, "UTC-02" }, - { TimeZone.UTCMinus08, "UTC-08" }, - { TimeZone.UTCMinus09, "UTC-09" }, - { TimeZone.UTCMinus11, "UTC-11" }, - { TimeZone.VenezuelaStandardTime, "Venezuela Standard Time" }, - { TimeZone.VladivostokStandardTime, "Vladivostok Standard Time" }, - { TimeZone.VolgogradStandardTime, "Volgograd Standard Time" }, - { TimeZone.WAustraliaStandardTime, "W. Australia Standard Time" }, - { TimeZone.WCentralAfricaStandardTime, "W. Central Africa Standard Time" }, - { TimeZone.WEuropeStandardTime, "W. Europe Standard Time" }, - { TimeZone.WMongoliaStandardTime, "W. Mongolia Standard Time" }, - { TimeZone.WestAsiaStandardTime, "West Asia Standard Time" }, - { TimeZone.WestBankStandardTime, "West Bank Standard Time" }, - { TimeZone.WestPacificStandardTime, "West Pacific Standard Time" }, - { TimeZone.YakutskStandardTime, "Yakutsk Standard Time" }, - { TimeZone.YukonStandardTime, "Yukon Standard Time" } - }; - #endregion TimeZone - } -} diff --git a/Classes/Extensions.Core.cs b/Classes/Extensions.Core.cs deleted file mode 100644 index 81c8781..0000000 --- a/Classes/Extensions.Core.cs +++ /dev/null @@ -1,1289 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using Microsoft.Graph; -using Microsoft.Graph.Models; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.Http; -using System.Text.Json; -using System.Text.Json.Nodes; -using Extensions.Identity; -using Extensions.Tenant; -using static Extensions.Identity.AuthMan; - -namespace Extensions -{ - /// - /// Core class for constants, enums and helper methods. - /// - [Serializable] - public static partial class Core - { - #region Enums - /// - /// The list of valid AzureEnvironments used. - /// - public enum AzureEnvironment - { - /// - /// China - /// - China, - /// - /// Default - /// - Commercial, - /// - /// Germany - /// - Germany, - /// - /// GCC/DoD - /// - USGovGCC, - /// - /// GCCHigh - /// - USGovGCCHigh - } - #endregion Enums - - #region Properties - /// - /// A dictionary of configurations for different tenants. - /// - public static Dictionary Tenants { get; private set; } - = new Dictionary(); - - /// - /// The currently active tenant configuration in use. - /// - public static TenantConfig ActiveTenant { get; set; } = null; - - /// - /// The currently active Auth object from the stack. - /// - public static Auth ActiveAuth { get; private set; } = new Auth(); - //= GetAuth(GetEnv("TenantDirectoryId"), - // GetEnv("ApplicationClientId"), - // GetEnv("CertificateThumbprint"), - // GetEnv("TenantString")); - - /// - /// TODO - /// - public static Configuration Config { get; set; } = new Configuration(); - - ///// - ///// The tenant name e.g. for contoso.sharepoint.us it would be "contoso". - ///// - //public static string TenantUrl { get; } - // = $"{ActiveTenant.TenantString}.sharepoint.us"; - - ///// - ///// The URI of the tenant. - ///// - //public static Uri TenantUri { get; } - // = new Uri("https://" + TenantUrl); - - ///// - ///// Method to get the valid Authority URL given the AzureEnvironment. - ///// - //public static string Authority - //{ - // get - // { - // switch (GetAzureEnvironment(ActiveTenant.AzureEnvironment)) - // { - // case AzureEnvironment.USGovGCCHigh: - // return $"https://login.microsoftonline.us/{TenantUrl}"; - // break; - // case AzureEnvironment.Commercial: - // return $"https://login.microsoftonline.com/{TenantUrl}"; - // break; - // default: - // throw new NotImplementedException("Only GCCHigh and Commercial available."); - // break; - // } - // } - //} - - /// - /// Method to get the valid Graph endpoint URL given the AzureEnvironment. - /// - public static string GraphEndPointUrl - { - get - { - switch (ActiveTenant.AzureEnvironment) - { - case AzureEnvironment.USGovGCCHigh: - return $"https://graph.microsoft.us/v1.0"; - break; - case AzureEnvironment.Commercial: - return $"https://graph.microsoft.com/v1.0"; - default: - throw new NotImplementedException("Only GCCHigh and Commercial available."); - break; - } - } - } - - /// - /// Method to return the users endpoint for the given Graph context. - /// - public static string GraphUserEndPointUrl - { - get - { - return $"{GraphEndPointUrl}/users"; - } - } - - /// - /// The assembly used on out calls. - /// - private static System.Reflection.Assembly assembly; - - /// - /// The private object used to manage locks on file I/O. - /// - private static readonly object LockManager = new object(); - #endregion Properties - - #region Auth - /// - /// Method to get a matching Auth object from the stack or if it - /// doesn't exist on the stack, generate the new Auth object and - /// push it to the stack. - /// - /// The scope type of the Auth. Default value - /// is Graph. - /// Boolean to trigger a clearing of the - /// Auth stack. Default value is false. - /// A valid Auth object from the stack. - public static Auth GetAuth( - ScopeType scopeType = ScopeType.Graph, - bool authStackReset = false) - { - return AuthMan.GetAuth( - ActiveTenant.TenantDirectoryId, - ActiveTenant.ApplicationClientId, - ActiveTenant.CertThumbprint, - ActiveTenant.TenantString, - scopeType, - authStackReset); - } - - /// - /// A method to set the current ActiveAuth. - /// - /// The key to use against the AuthStack. - /// True if ActiveAuth was successfully set, else False. - public static bool SetActiveAuth(string key) - { - if (AuthStack.ContainsKey(key)) - { - ActiveAuth = AuthStack[key]; - return true; - } - return false; - } - #endregion Auth - - #region InitializeTenant - /// - /// Initialization method for tenant configuration. - /// - /// The name of the tenant to initialize. - public static void InitializeTenant(string tenantString) - { - try - { - Inf($"Initializing Tenant [{tenantString}]"); - //Only initialize the tenant if it hasn't already been done. - if ((!Tenants.ContainsKey(tenantString)) || - (Tenants[tenantString].Settings == null)) - { - CoreBase.TenantString = tenantString; - LoadConfig(tenantString); - string[] sp = Scopes.SharePoint; - sp[0] = sp[0].Replace("Contoso", CoreBase.TenantString); - Scopes.SharePoint = sp; - AuthMan.GetAuth(GetEnv("TenantDirectoryId"), - GetEnv("ApplicationClientId"), - GetEnv("CertThumbprint"), - tenantString); - } - else - { - Inf($"Tenant [{tenantString}] is already in the pool. " + - $"Using pool instance."); - LoadConfig(tenantString); - GetAuth(); - } - ActiveTenant = Tenants[tenantString]; - Inf($"Initializing Tenant [{tenantString}] complete."); - } - catch (Exception ex) - { - Err(ex.ToString()); - throw; - } - } - - /// - /// Internal method to add an Environment Variable (usually from the - /// settings of an Azure Function) to the active config. - /// - /// The name of the EV to add to config. - internal static void AddEnvSetting(string key) - { - Config.Settings.Add(key, GetEnv(key)); - } - - /// - /// Internal method to add multiple Environment Variables (usually from - /// the settings of an Azure Function) to the active config. - /// - /// A string array containing the EVs to add to - /// the active config. - internal static void AddEnvSetting(string[] keys) - { - foreach (string key in keys) - { - try - { - Config.Settings.Add(key, GetEnv(key)); - } - catch (Exception ex) - { - Err(ex.ToString()); - throw new Exception($"The key [{key}] does not exist as an" + - $"environment variable.\n\n" + ex.ToString()); - } - } - } - - - /// - /// An internal method for loading environment variables from JSON - /// config files when interactively debugging. - /// - /// The name of the target tenant. - internal static void LoadConfig(string tenantString) - { - Config.Settings = new Dictionary(); - Config.Settings.Add("TenantString", tenantString); - if (Environment.UserInteractive) - { - Inf($"Loading config from [" + - $"{GetRunFolder()}]\\{GetConfigFileName(tenantString)}]."); - Config.Settings = LoadJSON( - $"{GetRunFolder()}" + - $"\\{GetConfigFileName(tenantString)}"); - Inf($"Loading sensitivity labels from [" + - $"{GetRunFolder()}]\\{GetLabelsFileName(tenantString)}]."); - Config.Labels = LoadJSON( - $"{GetRunFolder()}" + - $"\\{GetLabelsFileName(tenantString)}"); - Inf("Config and Labels loaded."); - } - else - { - //AddEnvSetting( - // "TenantDirectoryId," + - // "ApplicationClientId," + - // "AzureEnvironment," + - // "ConnectionString," + - // "DefaultBlobContainer," + - // "EmailSendingAccount," + - // "CertStoreLocation," + - // "CertThumbprint," + - // "DebugEnabled," + - // "MultiThreaded," + - // "LogitSiteBaseUrl," + - // "LogitSiteId," + - // "LogitDefaultListGuid," + - // "HomeSiteBaseUrl".Split( - // ',', - // StringSplitOptions..TrimEntries | - // StringSplitOptions.RemoveEmptyEntries)); - } - } - - /// - /// Internal method to get the name of the universal config file - /// based on the tenant name. - /// - /// The name of the Tenant e.g. for the - /// contoso.sharepoint.us tenant the value would be "contoso". - /// The name of a JSON file for the current Tenant. - internal static string GetConfigFileName(string tenantString) - { - return $"UniversalConfig.{tenantString}.json"; - } - - /// - /// Internal method to get the name of the sensitivity labels file - /// based on the tenant name. - /// - /// The name of the Tenant e.g. for the - /// contoso.sharepoint.us tenant the value would be "contoso". - /// The name of a JSON file for the current Tenant. - internal static string GetLabelsFileName(string tenantString) - { - return $"Labels.{tenantString}.json"; - } - - /// - /// An internal method that loads a given file and attempts to - /// deserialize it to a Dictionary of string,string object for return. - /// - /// The full path and file name of the target - /// file to load. - /// A Dictionary of string,string values or an empty - /// Dictionary if an error occus. - internal static Dictionary LoadJSON(string filePath) - { - var result = new Dictionary(); - try - { - using (StreamReader sr = new StreamReader(filePath)) - { - result = JsonSerializer.Deserialize< - Dictionary>(sr.ReadToEnd()); - } - } - catch (Exception ex) - { - //If something goes wrong while reading the file, we simply - //return a blank dictionary by swallowing the error and logging - //the exception. - Err(ex.ToString()); - } - return result; - } - - /// - /// A public method to allow settings values to be retrieved. - /// - /// The name of the setting value to retrieve. - /// If the requested setting exist in the config, its value is - /// returned else a blank string is returned. - public static string GetSetting(string key) - { - if (Config.Settings.ContainsKey(key)) - { - return Config.Settings[key]; - } - return ""; - } - #endregion InitializeTenant - - #region Logit - /// - /// Called to write "Information" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - /// Return value from Log() method. - public static void Inf( - string message, - int eventId = 0, - Logit.Instance instance = null) - { - Logit.Inf(message, eventId, instance); - } - - /// - /// Called to write "Warning" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - /// Return value from Log() method. - public static void Wrn( - string message, - int eventId = 0, - Logit.Instance instance = null) - { - Logit.Wrn(message, eventId, instance); - } - - /// - /// Called to write "Error" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - /// Return value from Log() method. - public static void Err( - string message, - int eventId = 0, - Logit.Instance instance = null) - { - Logit.Err(message, eventId, instance); - } - - /// - /// Called to write "Verbose" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - /// Return value from Log() method. - public static void Vrb( - string message, - int eventId = 0, - Logit.Instance instance = null) - { - Logit.Vrb(message, eventId, instance); - } - #endregion Logit - - #region GetCVersion() - /// - /// Method to get the CVersion. - /// - /// Path to the json file containing the - /// version. - /// The CVersion. - public static string GetCVersion(string filePath = null) - { - try - { - if (filePath == null) - { - filePath = "version.json"; - } - string json = ""; - using (FileStream fs = new FileStream(filePath, - FileMode.Open, - FileAccess.Read)) - { - using (StreamReader sr = new StreamReader(fs)) - { - json = sr.ReadToEnd().ToString(); - } - } - JsonNode node = JsonNode.Parse(json); - return "CVersion-" + node["cversion"].ToString(); - } - catch (Exception ex) - { - Err(ex.ToString()); - return ex.ToString(); - } - finally - { - } - } - - /// - /// Method to get the CVersion from IConfiguration. - /// - /// Instance of IConfiguration. - /// The CVersion. - public static string GetCVersion( - Microsoft.Extensions.Configuration.IConfiguration config) - { - try - { - return "CVersion-" + config.GetSection( - "AzureFunctionsJobHost:cversion").Value; - } - catch (Exception ex) - { - Wrn(ex.ToString()); - return GetCVersion(); - } - finally - { - } - } - #endregion - - #region GetExecutingAssembly() - /// - /// Gets the current assembly through reflection. - /// - /// The current Entry or Executing assembly. - public static System.Reflection.Assembly GetExecutingAssembly() - { - return System.Reflection.Assembly.GetEntryAssembly() == null ? - System.Reflection.Assembly.GetExecutingAssembly() : - System.Reflection.Assembly.GetEntryAssembly(); - } - - /// - /// Gets the name of the current assembly. - /// - /// Out parm to hold the assembly. - /// Should the value be escaped? - /// Returns the name of the current assembly, optionally - /// escaped. - private static string GetExecutingAssemblyName( - out System.Reflection.Assembly asm, - bool escaped = false) - { - asm = GetExecutingAssembly(); - string result = asm.ManifestModule.Name; - if (escaped) - { - return System.Uri.EscapeDataString(result); - } - return result; - } - - /// - /// Gets the name of the current assembly. - /// - /// Should the value be escaped? - /// Returns the name of the current assembly, optionally - /// escaped. - public static string GetExecutingAssemblyName(bool escaped = false) - { - return GetExecutingAssemblyName(out assembly, escaped); - } - - /// - /// Gets the folder path of the current assembly. - /// - /// Out parm to hold the assembly. - /// Should the value be escaped? - /// Returns the folder path of the current assembly, - /// optionally escaped. - private static string GetExecutingAssemblyFolder( - out System.Reflection.Assembly asm, - bool escaped = false) - { - asm = GetExecutingAssembly(); - string result = System.IO.Path.GetDirectoryName(asm.Location) - .TrimEnd('\\'); - if (escaped) - { - return System.Uri.EscapeDataString(result); - } - return result; - } - - /// - /// Gets the folder path of the current assembly. - /// - /// Should the value be escaped? - /// Returns the folder path of the current assembly, - /// optionally escaped. - public static string GetExecutingAssemblyFolder(bool escaped = false) - { - return GetExecutingAssemblyFolder(out assembly, escaped); - } - - /// - /// Get the location where the assembly stack started executing. - /// - /// The folder path. - public static string GetRunFolder() - { - return System.IO.Path.GetDirectoryName( - System.Reflection.Assembly.GetEntryAssembly() - .Location.TrimEnd('\\')); //Ensure no trailing slash. - } - - /// - /// A public method to retrieve the Tenant ID. - /// - /// The Tenant name e.g. for - /// "contoso.sharepoint.us" it would be "contoso". - /// The Tenant ID. - public static string GetTenantId(string tenantString) - { - var az = GetAuthorityDomain(GetAzureEnvironment("GCCHigh")); - var http = new HttpClient(); - var res = http.GetAsync( - $"https://login.microsoftonline{az}/{tenantString}" + - $".onmicrosoft{az}/v2.0/.well-known" + - $"/openid-configuration").GetAwaiter().GetResult(); - var raw = res.Content.ReadAsStringAsync().Result; - var json = JsonSerializer.Deserialize(raw); - return json.authorization_endpoint.ToLower() - .Replace($"https://login.microsoftonline{az}/", "") - .Replace("/oauth2/v2.0/authorize", ""); - } - - /// - /// Gets the full path and file name of the current assembly. - /// - /// Should the value be escaped? - /// Returns the full path and file name of the current - /// assembly, optionally escaped. - public static string GetExecutingAssemblyFullPath(bool escaped = false) - { - string result = GetExecutingAssemblyFolder(out assembly) + "\\" + - assembly.ManifestModule.Name; - if (escaped) - { - return System.Uri.EscapeDataString(result); - } - return result; - } - #endregion GetExecutingAssembly() - - #region GetFQDN() - /// - /// Returns the current computer Fully Qualified Domain Name. - /// - /// Returns the current computer Fully Qualified Domain Name. - public static string GetFQDN() - { - string domainName = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName; - string hostName = System.Net.Dns.GetHostName(); - if (domainName == "") - { - return hostName; - } - domainName = "." + domainName; - if (!hostName.EndsWith(domainName)) - { - hostName = domainName; - } - return hostName; - } - #endregion GetFQDN() - - #region Null - /// - /// Method to ensure a given object is not null. - /// - /// The object to check. - /// The string value of the object. - public static string NoNull(object str) - { - if (str == null) - { - return ""; - } - return str.ToString(); - } - - /// - /// Method to ensure a value in a dictionary is not null. - /// - /// The dictionary containing the variable. - /// The name of the variable to check. - /// - public static string NoNull(IDictionary dict, - string fieldName) - { - try - { - if (dict.ContainsKey(fieldName)) - { - return dict[fieldName].ToString(); - } - else - { - return ""; - } - } - catch (Exception ex) - { - return ""; - } - finally - { - } - } - - /// - /// Extension method for object array to validate all object are not - /// null. - /// - /// The array of objects to check. - /// True if any object in the array is null, else false. - public static bool AnyNull(this object[] objects) - { - foreach (object obj in objects) - { - if (obj == null) - { - return true; - } - } - return false; - } - #endregion Null - - #region printf() - /// - /// Simple printf method for console output with color control. Both - /// text color and background color is returned to previous state - /// after the string has been written to console. - /// - /// String to print to console. - /// Overrideable text color, default to white. - /// Overrideable background color, default to - /// black. - public static void Printf(object msg, - ConsoleColor foreground = ConsoleColor.White, - ConsoleColor background = ConsoleColor.Black) - { - ConsoleColor fore = Console.ForegroundColor; - ConsoleColor back = Console.BackgroundColor; - if (foreground != fore) - { - Console.ForegroundColor = foreground; - } - if (background != back) - { - Console.BackgroundColor = background; - } - Console.WriteLine(Convert.ToString(msg)); - if (foreground != fore) - { - Console.ForegroundColor = fore; - } - if (background != back) - { - Console.BackgroundColor = back; - } - } - #endregion printf() - - #region TimeStamp() - /// - /// Returns the current local date time stamp as a string in either - /// "YYYY-MM-DD" or "YYYY-MM-DD@hh.mm.ss.nnn" format. - /// - /// If true, return the current local date - /// time stamp as "YYYY-MM-DD" else return it as - /// "YYYY-MM-DD@hh.mm.ss.nnn" - /// Returns the current local date time stamp as a string in - /// either "YYYY-MM-DD" or "YYYY-MM-DD@hh.mm.ss.nnn" format. - public static string TimeStamp(bool DateOnly = false) - { - System.DateTime now = System.DateTime.Now; - if (DateOnly) - { - return now.Year.ToString() + "-" + - now.Month.ToString("d2") + "-" + - now.Day.ToString("d2"); - } - else - { - return now.Year.ToString() + "-" + - now.Month.ToString("d2") + "-" + - now.Day.ToString("d2") + "@" + - now.Hour.ToString("d2") + "." + - now.Minute.ToString("d2") + "." + - now.Second.ToString("d2") + "." + - now.Millisecond.ToString("d3"); - } - } - #endregion TimeStamp - - #region Validate() - /// - /// Makes quick work of null validating all parameters you pass to it. - /// This method takes a variable number of parameters and validates that - /// all parameters are not null. If a parameter is found to be null, a - /// ArgumentNullException is thrown. - /// For example: - /// void MyMethod(string str, double dbl, MyClass cls) - /// { - /// Universal.ValidateNoNulls(str, dbl, cls); - /// ...Your code here... - /// } - /// You do not have to pass all parameters, but can instead do this: - /// void MyMethod(string str, double dbl, MyClass cls) - /// { - /// Universal.ValidateNoNulls(str, cls); - /// ...Your code here... - /// } - /// where we chose NOT to validate the double dbl in this case. - /// - /// The variable set of parameters. - public static bool ValidateNoNulls(params object[] parms) - { - for (int C = 0; C < parms.Length; C++) - { - if (parms[C] == null) - { - throw new ArgumentNullException("Parameter #" + C); - } - } - return true; - } - - /// - /// Makes quick work of validating all parameters you pass to it. - /// This method takes a variable number of parameters and validates - /// all parameters based on ErrorType and object type. Null validation - /// is seamless. If a parameter is found to be null, a - /// ArgumentNullException is thrown which notes the number of the - /// parameter since parmeters are treated as objects and thus the - /// parameter names are inaccessible. - /// For example: - /// void MyMethod(string str, double dbl, MyClass cls) - /// { - /// Universal.Validate(ErrorType.Null, str, dbl, cls); - /// ...Your code here... - /// } - /// You do not have to pass all parameters, but can instead do this: - /// void MyMethod(string str, double dbl, MyClass cls) - /// { - /// Universal.Validate(ErrorType.Null, str, cls); - /// ...Your code here... - /// } - /// where we chose NOT to validate the double dbl in this case. - /// Alternatively, you can validate that dbl is a non-negative - /// number by doing this: - /// void MyMethod(string str, double dbl, MyClass cls) - /// { - /// Universal.Validate( - /// {ErrorType.Null, ErrorType.NonNegative}, - /// str, cls); - /// ...Your code here... - /// } - /// - /// The array of error types to validate. - /// The variable set of parameters. - public static bool Validate(Constants.ErrorType[] errors, - params object[] parms) - { - foreach (Constants.ErrorType error in errors) - { - for (int C = 0; C < parms.Length; C++) - { - switch (error) - { - case Constants.ErrorType.Null: - if (parms[C] == null) - { - throw new ArgumentNullException("Parameter #" + C); - } - break; - case Constants.ErrorType.IntNonNegative: - if (parms[C].GetType() == typeof(int)) - { - if ((int)parms[C] < 0) - { - throw new ArgumentOutOfRangeException( - "Parameter #" + C, - "Value must be >= 0"); - } - } - break; - } - } - } - return true; - } - #endregion Validate() - - #region EnvironmentVariables - /// - /// A method to get an EnvironmentVariable value. - /// - /// The target variable name. - /// The value of the EnvironmentVariable or. - public static string GetEnv(string key) - { - if (Environment.GetEnvironmentVariable(key) != null) - { - return Environment.GetEnvironmentVariable(key); - } - return GetSetting(key); - } - - /// - /// A method to set an EnvironmentVariable value. - /// - /// The variable to set. - /// The value to which to set the variable. - public static void SetEnv(string target, string value) - { - Environment.SetEnvironmentVariable(target, value); - } - #endregion EnvironmentVariables - - #region GetAzureEnvironment - /// - /// Method to return the AzureEnvironment based on the given string. - /// - /// The environment to get. - /// The enum value of the environment. - public static AzureEnvironment GetAzureEnvironment(string env) - { - if (env.ToLower().Contains("gcchigh")) - { - return AzureEnvironment.USGovGCCHigh; - } - if (env.ToLower().Contains("china")) - { - return AzureEnvironment.China; - } - if (env.ToLower().Contains("germany")) - { - return AzureEnvironment.Germany; - } - if (env.ToLower().Contains("gcc")) - { - return AzureEnvironment.USGovGCC; - } - if (env.ToLower().Contains("dod")) - { - return AzureEnvironment.USGovGCC; - } - return AzureEnvironment.Commercial; - } - #endregion GetAzureEnvironment - - #region Group - /// - /// A private method to get a group of list of groups where the - /// displayName matches the given group name. - /// - /// The displayName of the target group. - /// A List of Group or null if none found. - private static List GetGroupByName(string groupName) - { - if (NoNull(groupName) != "") - { - return ActiveAuth.GraphClient.Groups.GetAsync((C) => - { - C.QueryParameters.Filter = $"displayName eq '{groupName}'"; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult().Value; - } - return new List(); - } - - /// - /// A private method to retrieve all the Members of a Group. - /// - /// The displayName of the target Group. - /// A List of DirectoryObject values that represens all the - /// members of the Group. - private static List GetGroupMembers(string groupName) - { - List members = new List(); - var groups = GetGroupByName(groupName); - if (groups.Count > 0) - { - var page = ActiveAuth.GraphClient.Groups[groups[0].Id].Members - .GetAsync().GetAwaiter().GetResult(); - var pageIterator = - PageIterator - .CreatePageIterator( - ActiveAuth.GraphClient, - page, - (member) => - { - members.Add(member); - return true; - }); - pageIterator.IterateAsync().GetAwaiter().GetResult(); - } - return members; - } - - /// - /// A private method to retrieve all the Owners of a Group. - /// - /// The displayName of the target Group. - /// A List of DirectoryObject values that represens all the - /// owners of the Group. - private static List GetGroupOwners(string groupName) - { - List owners = new List(); - var groups = GetGroupByName(groupName); - if (groups.Count > 0) - { - var page = ActiveAuth.GraphClient.Groups[groups[0].Id].Owners - .GetAsync().GetAwaiter().GetResult(); - var pageIterator = - PageIterator - .CreatePageIterator( - ActiveAuth.GraphClient, - page, - (owner) => - { - owners.Add(owner); - return true; - }); - pageIterator.IterateAsync().GetAwaiter().GetResult(); - } - return owners; - } - #endregion Group - - #region GetUser - /// - /// Method to get the user given a user lookup id from SharePoint. - /// - /// The SharePoint list id of the user. - /// A reference to the list of users. - /// The user associated with the id or null. - public static Microsoft.Graph.Models.ListItem GetUserFromLookupId( - string id, - ref List siteUsers) - { - foreach (var item in siteUsers) - { - if (item.Id == id) - { - return item; - } - } - return null; - } - - /// - /// Method to get a user's EMail or UserName. Particulary useful for - /// translating SharePoint UserLookupIds like LastModified or Author - /// from a numeric value to the UPN string. - /// - /// A ListItem instance from the site's - /// UserInformation list. - /// The EMail or UserName value from a ListItem instance - /// from the UserInformation list. - /// - public static string GetUserEmailUpn( - Microsoft.Graph.Models.ListItem listItem) - { - if (listItem.Fields.AdditionalData.ContainsKey("EMail") && - listItem.Fields.AdditionalData["EMail"] != null) - { - return listItem.Fields.AdditionalData["EMail"].ToString(); - } - if (listItem.Fields.AdditionalData.ContainsKey("EMail") && - listItem.Fields.AdditionalData["EMail"] != null) - { - return listItem.Fields.AdditionalData["UserName"].ToString(); - } - return ""; - } - - public static string GetUserEmailUpn( - string id, - GraphServiceClient client) - { - try - { - if ((id == null) || - (id == "")) - { - return ""; - } - var userListItems = GetListItems( - "User Information List", - GetEnv("HomeSiteBaseUrl"), - id); - if ((userListItems != null) && - (userListItems.Count > 0) && - (userListItems[0].Fields.AdditionalData.ContainsKey("EMail")) && - (userListItems[0].Fields.AdditionalData["EMail"] != null)) - { - return userListItems[0].Fields.AdditionalData["EMail"].ToString(); - } - return userListItems[0].Fields.AdditionalData["UserName"].ToString(); - } - catch (Exception ex) - { - Err(ex.ToString()); - return ""; - } - finally - { - } - } - - /// - /// Method to get the user's UPN given a SharePoint lookup id. - /// Particulary useful for translating SharePoint UserLookupIds like - /// LastModified or Author from a numeric value to the UPN string. - /// - /// The lookup id of the user. - /// A reference to the list of users. - /// The EMail or UserName value from a ListItem instance - /// from the UserInformation list. - public static string GetUserEmailUpn( - string id, - ref List siteUsers) - { - var item = GetUserFromLookupId(id, ref siteUsers); - if (item == null) - { - return ""; - } - try - { - if ((item.Fields.AdditionalData.ContainsKey("EMail")) && - (item.Fields.AdditionalData["EMail"] != null)) - { - return item.Fields.AdditionalData["EMail"].ToString(); - } - return item.Fields.AdditionalData["UserName"].ToString(); - } - catch (Exception ex) - { - Err(ex.ToString()); - return item.Fields.AdditionalData["UserName"].ToString(); - } - finally - { - } - } - #endregion GetUser - - #region TryAdd - /// - /// Extension method for Dictionary to add an item if it doesn't - /// already exist in the dictionary. - /// - /// The dictionary to which the instance should be - /// added. - /// The key to use for the instance. - /// The value to add to the dictionary. - /// True if add successful, false if not. - public static bool TryAdd( - this Dictionary dic, - object key, - object val) - { - try - { - if (!dic.ContainsValue(val)) - { - dic.Add(key, val); - return true; - } - return false; - } - catch (Exception ex) - { - return false; - } - } - - /// - /// Extension method for List to add a string item if it doesn't - /// already exist in the list. - /// - /// The list to which the object should be added. - /// The string to add to the list. - /// True if add successful, false if not. - public static bool TryAdd( - this List lst, - string obj) - { - try - { - if (!lst.Contains(obj)) - { - lst.Add(obj); - return true; - } - return false; - } - catch (Exception ex) - { - return false; - } - } - - /// - /// Extension method for List to add an int item if it doesn't - /// already exist in the list. - /// - /// The list to which the object should be added. - /// The int to add to the list. - /// True if add successful, false if not. - public static bool TryAdd( - this List lst, - int obj) - { - try - { - if (!lst.Contains(obj)) - { - lst.Add(obj); - return true; - } - return false; - } - catch (Exception ex) - { - return false; - } - } - #endregion TryAdd - - /// - /// Method to write out all setting values in both the ActiveAuth's - /// tenant configuration as well as the Core configuration values. - /// - public static void DumpSettings() - { - Inf("Dumping ActiveAuth settings..."); - foreach (var setting in ActiveAuth.TenantCfg.Settings) - { - Inf($"[{setting.Key}] = [{setting.Value}]"); - } - Inf("Dumping Core settings..."); - foreach (var setting in Core.Config.Settings) - { - Inf($"[{setting.Key}] = [{setting.Value}]"); - } - } - - /// - /// Method to get a Graph List object given the list name and the path - /// of the containing site." - /// - /// The name of the target List. - /// The relative path of the site containing - /// the target list e.g. "/sites/Extensions". - /// A Graph List object - public static Microsoft.Graph.Models.List GetList( - string listName, - string sitePath) - { - return ActiveAuth.GraphClient.Sites[Graph.GetSiteId(sitePath)] - .Lists[Graph.GetListId(listName, sitePath)] - .GetAsync().GetAwaiter().GetResult(); - } - - /// - /// A method to get all list items given a list name, the path of the - /// containing site and optionally a filter or ID. If an ID value is - /// provided, a list containing a single item is returned. - /// - /// The name of the target list. - /// The path to the site containing said target - /// list e.g. "/sites/Extensions". - /// An optional ID of a specific item in the - /// list. - /// An optional filter to be used during selection - /// of the resulting data set e.g. "name = 'Extensions'". - /// A list of items for the target list and containing site. - /// If no filter or ID is provided, all items in the list is returned. - /// If a filter is provided, the items conforming to the filter is - /// returned. If an ID is provided, the target item is returned. - /// - public static List GetListItems( - string listName, - string sitePath, - string id = null, - string filter = null) - { - return Graph.GetListItems(listName, sitePath, id, filter); - } - } -} diff --git a/Classes/Extensions.CoreBase.cs b/Classes/Extensions.CoreBase.cs deleted file mode 100644 index ac2a3e9..0000000 --- a/Classes/Extensions.CoreBase.cs +++ /dev/null @@ -1,22 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; - -namespace Extensions -{ - [Serializable] - public static partial class CoreBase - { - public static string TenantString { get; set; } = "Contoso"; - - public static void Initialize(string tenantString) - { - TenantString = tenantString; - } - } -} diff --git a/Classes/Extensions.Graph.cs b/Classes/Extensions.Graph.cs deleted file mode 100644 index 15900da..0000000 --- a/Classes/Extensions.Graph.cs +++ /dev/null @@ -1,2058 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using Microsoft.Graph; -using static Microsoft.Graph.Groups.GroupsRequestBuilder; -using static Microsoft.Graph.Users.UsersRequestBuilder; -using Microsoft.Graph.Models; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using static Extensions.Core; -using static Microsoft.Graph.Users.Item.Drives.DrivesRequestBuilder; -using Extensions.Identity; -using System.IO; -using static Microsoft.Graph.Drives.Item.Items.Item.Children.ChildrenRequestBuilder; - -namespace Extensions -{ - /// - /// An extension class for working with batch requests in Microsoft.Graph. - /// - [Serializable] - public partial class BatchGroup - { - /// - /// A collection of batch requests. - /// - public BatchRequestContentCollection Batch { get; set;} - /// - /// A list of string IDs for requests contained in the batch. - /// - public List Ids { get; set;} - } - - /// - /// An extension class that makes working with Microsoft.Graph in GCCHigh - /// environments easy. - /// - [Serializable] - public static partial class Graph - { - public static Drive GetDrive(User user) - { - var drives = GetDrives($"id eq '{user.Id}'", ""); - return drives.FirstOrDefault(); - } - - public static Drive GetDrive(string userId) - { - var drives = GetDrives($"id eq '{userId}'", ""); - return drives.FirstOrDefault(); - } - - public static List GetDrives() - { - return GetDrives("", "", null); - } - - public static List GetDrives(string[] select = null) - { - return GetDrives("", "", select); - } - - public static List GetDrives(string userFilter = "", - string[] select = null) - { - return GetDrives(userFilter, "", select); - } - - public static List GetDrives(string userFilter = "", - string filter = "", - string[] select = null) - { - var drives = new List(); - var users = GetUsers(userFilter); - Parallel.ForEach(users, user => - { - GetDrives(ref drives, user, filter, select); - }); - return drives; - } - - /// - /// A method to retrieve a list containing all the - /// Microsoft.Graph.Models.Drive child items for the given user and - /// filter. Optionally, additional Drive metadata can be requested - /// through the select string array parameter. The method will add - /// all discovered Drive items to the referenced drives List. - /// - /// A reference to the aggregation container. - /// The Graph User for which drives are retrieved. - /// An optional OData filter string to apply. - /// An optional string array of additional Drive metadata - /// field names to retrieve. - internal static void GetDrives(ref List drives, - User user, - string filter = "", - string[] select = null) - { - //Get the first page of drives. - DriveCollectionResponse drivesPage = null; - DrivesRequestBuilderGetQueryParameters queryParameters = null; - if (filter != "") - { - queryParameters = new DrivesRequestBuilderGetQueryParameters(); - queryParameters.Filter = filter; - } - if (select != null) - { - if (queryParameters == null) - { - queryParameters = new DrivesRequestBuilderGetQueryParameters(); - } - queryParameters.Select = select; - } - try - { - if (queryParameters == null) - { - //Get all Drives. - drivesPage = ActiveAuth.GraphClient.Users[user.Id] - .Drives - .GetAsync((C) => - { - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - } - else - { - //Apply the specified filter to the Drives request. - drivesPage = ActiveAuth.GraphClient.Users[user.Id] - .Drives - .GetAsync((C) => - { - C.QueryParameters = queryParameters; - //At present, Graph does not support filtering with NOT - //without using setting Count being equal to true. - //It throws a 400 exception with an HResult of -214623388. - //The message states "Operator 'not' is not supported - //because the required parameters might be missing. - //Try adding $count=true query parameter and - //ConsistencyLevel:eventual header. - //Refer to https://aka.ms/graph-docs/advanced-queries for - //more information." - C.QueryParameters.Count = true; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - } - GetDrivesPages(ref drives, ref drivesPage); - } - catch (Exception ex) - { - //Ignore exceptions when the user's OneDrive is not configured. - if ((!ex.Message.Contains("Unable to retrieve user's mysite URL.")) && - (!ex.Message.Contains("User's mysite not found."))) - { - throw; - } - } - } - - /// - /// A method to iterate a page collection reference and add retrieved - /// items to an aggregation container reference. - /// - /// A reference to the aggregation container. - /// A reference to the first page to iterate. - internal static void GetDrivesPages( - ref List drives, - ref DriveCollectionResponse drivesPage) - { - while (drivesPage.Value != null) - { - lock (drives) - { - drives.AddRange(drivesPage.Value); - } - if (!string.IsNullOrEmpty(drivesPage.OdataNextLink)) - { - drivesPage = ActiveAuth.GraphClient.Drives - .WithUrl(drivesPage.OdataNextLink) - .GetAsync((C) => - { - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult() ; - } - else - { - drivesPage.Value = null; - } - } - } - - /// - /// A method to get the size of a OneDrive in bytes. - /// - /// The target Drive to calculate. - /// An optional list of Auth objects that can - /// be passed to be used during multi-threaded operations e.g. if the - /// environment is huge, 429 throttling can occur on the AppId being - /// used. By spreading the load across multiple AppIds, their auth - /// tokens can be generated before hand and then passed to be used. - /// A boolean switch to control if - /// BlackCheetah is used in the operation. Defaults to false. - /// A long value of the number of bytes of the Drive. - public static long GetDriveContentSize(this Drive drive, - List authStack = null, - bool blackCheetah = false) - { - long result = 0; - if (drive == null) - { - return result; - } -#if BlackCheetah - if (blackCheetah) - { - if (authStack == null) - { - authStack = new List(); - authStack.Add(ActiveAuth); - } - List graphClients = - new List(); - foreach (var auth in authStack) - { - graphClients.Add(auth.GraphClient); - } - foreach (var driveItem in BlackCheetah.Graph.GetDriveItems( - drive, - graphClients)) - { - result += (long)driveItem.Size; - } - return result; - } -#endif - List driveItems = GetDriveItems( - drive, - "", - null, - authStack, - blackCheetah); - foreach (var driveItem in GetDriveItems(drive)) - { - result += (long)driveItem.Size; - } - return result; - } - - /// - /// A method to get a specific DriveItem. - /// - /// The containing Drive ID. - /// The target item ID. - /// The DriveItem if found, else null. - public static DriveItem GetDriveItem(string driveId, - string itemId) - { - DriveItem driveItem = - ActiveAuth.GraphClient.Drives[driveId] - .Items[itemId] - .GetAsync((C) => - { - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - if (driveItem != null) - { - return driveItem; - } - return null; - } - - /// - /// A method to retrieve a list containing all the - /// Microsoft.Graph.Models.DriveItem child items for the given user. - /// - /// The ID of the target user to iterate. - /// An OData filter string to apply. - /// An optional string array of additional metadata - /// field names to retrieve. - /// An optional list of Auth objects that can - /// be passed to be used during multi-threaded operations e.g. if the - /// environment is huge, 429 throttling can occur on the AppId being - /// used. By spreading the load across multiple AppIds, their auth - /// tokens can be generated before hand and then passed to be used. - /// A boolean switch to control if - /// BlackCheetah is used in the operation. Defaults to false. - /// A list containing all the Microsoft.Graph.Models.DriveItem - /// child items for the given user. - public static List GetDriveItems( - string userGuid, - List authStack = null, - string filter = null, - string[] select = null, - bool blackCheetah = false) - { - var driveItems = new List(); - if (userGuid == null) - { - return driveItems; - } - if (authStack == null) - { - authStack = new List(); - authStack.Add(ActiveAuth); - } - var user = ActiveAuth.GraphClient.Users[userGuid] - .GetAsync().GetAwaiter().GetResult(); - var drive = ActiveAuth.GraphClient.Drives[user.Id] - .GetAsync().GetAwaiter().GetResult(); -#if BlackCheetah - if (blackCheetah) - { - if (authStack == null) - { - authStack = new List(); - authStack.Add(ActiveAuth); - } - List graphClients = - new List(); - foreach (var auth in authStack) - { - graphClients.Add(auth.GraphClient); - } - List results = - new List(); - results = BlackCheetah.Graph.GetDriveItems(drive, - graphClients, - filter); - foreach (var result in results) - { - driveItems.Add(BlackCheetah.Graph.ToGraphDriveItem(result)); - } - return driveItems; - } -#endif - return GetDriveItems(drive, filter, select, authStack); - } - - /// - /// A method to retrieve a list containing all the - /// Microsoft.Graph.Models.DriveItem child items for the given Drive. - /// - /// The target Drive to iterate. - /// An OData filter string to apply. - /// An optional string array of additional metadata - /// field names to retrieve. - /// An optional list of Auth objects that can - /// be passed to be used during multi-threaded operations e.g. if the - /// environment is huge, 429 throttling can occur on the AppId being - /// used. By spreading the load across multiple AppIds, their auth - /// tokens can be generated before hand and then passed to be used. - /// A boolean switch to control if - /// BlackCheetah is used in the operation. Defaults to false. - /// A list containing all the Microsoft.Graph.Models.DriveItem - /// child items for the given Drive. - public static List GetDriveItems( - Drive drive, - string filter = null, - string[] select = null, - List authStack = null, - bool blackCheetah = false) - { - //Create result container. - var allDriveItems = new List(); - //If we don't have a valid Drive, return empty container. - if (drive == null) - { - return allDriveItems; - } - //Get the DriveItem of the Drive root. - var driveItemRoot = ActiveAuth.GraphClient.Drives[drive.Id] - .Root.GetAsync().GetAwaiter().GetResult(); - GetDriveItems(ref allDriveItems, - driveItemRoot, - filter, - select, - authStack, - blackCheetah); - return allDriveItems; - } - - /// - /// A method to retrieve a list containing all the - /// Microsoft.Graph.Models.DriveItem child items for the given DriveItem - /// and filter. Optionally, additional DriveItem metadata can be - /// requested through the select string array parameter. The method - /// will add all discovered DriveItems to the referenced DriveItems List. - /// - /// A reference to the aggregation container. - /// The target DriveItem to iterate. - /// An optional OData filter string to apply. - /// An optional string array of additional metadata - /// field names to retrieve. - /// A boolean switch to control if - /// BlackCheetah is used in the operation. Defaults to false. - /// An optional list of Auth objects that can - /// be passed to be used during multi-threaded operations e.g. if the - /// environment is huge, 429 throttling can occur on the AppId being - /// used. By spreading the load across multiple AppIds, their auth - /// tokens can be generated before hand and then passed to be used. - internal static void GetDriveItems(ref List driveItems, - DriveItem item, - string filter = "", - string[] select = null, - List authStack = null, - bool blackCheetah = false) - { -#if BlackCheetah - if (blackCheetah) - { - List clientStack = new List(); - if (authStack == null) - { - authStack.Add(ActiveAuth); - } - foreach (var auth in authStack) - { - clientStack.Add(auth.GraphClient); - } - var bcItems = BlackCheetah.Graph.GetDriveItems( - item, - item.ParentReference.DriveId, - filter, - select, - clientStack); - if ((bcItems != null) && - (bcItems.Count > 0) && - (bcItems.ContainsKey("driveItems")) && - (bcItems["driveItems"].Count > 0)) - { - lock (driveItems) - { - foreach (var bcDriveItem in bcItems["driveItems"]) - { - driveItems.Add(BlackCheetah.Graph.ToGraphDriveItem(bcDriveItem)); - } - } - } - return; - } -#endif - //Get the first page of drive items. - DriveItemCollectionResponse driveItemsPage = null; - ChildrenRequestBuilderGetQueryParameters queryParameters = null; - if (filter != "") - { - queryParameters = new ChildrenRequestBuilderGetQueryParameters(); - queryParameters.Filter = filter; - } - if (select != null) - { - if (queryParameters == null) - { - queryParameters = new ChildrenRequestBuilderGetQueryParameters(); - } - queryParameters.Select = select; - } - if (queryParameters == null) - { - //There no filter, so get all items. - driveItemsPage = ActiveAuth.GraphClient.Drives[item.ParentReference.DriveId] - .Items[item.Id] - .Children.GetAsync((C) => - { - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - } - else - { - //Apply the specified filter to the request. - driveItemsPage = ActiveAuth.GraphClient.Drives[item.ParentReference.DriveId] - .Items[item.Id] - .Children.GetAsync((C) => - { - C.QueryParameters = queryParameters; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - } - GetDriveItemsPages(ref driveItems, - ref driveItemsPage, - item.ParentReference.DriveId); - } - - /// - /// A method to iterate a page collection reference and add retrieved - /// items to an aggregation container reference. - /// - /// A reference to the aggregation container. - /// A reference to the first page to iterate. - /// The ID of the containing Drive. - internal static void GetDriveItemsPages( - ref List driveItems, - ref DriveItemCollectionResponse driveItemsPage, - string driveId) - { - //Was anything returned. - while (driveItemsPage.Value != null) - { - //If so, lock the container and add found items. - lock (driveItems) - { - driveItems.AddRange(driveItemsPage.Value); - } - //Are the more pages of items? - if (!string.IsNullOrEmpty(driveItemsPage.OdataNextLink)) - { - //If so, get the next page of items. - driveItemsPage = ActiveAuth.GraphClient.Drives[driveId] - .Items - .WithUrl(driveItemsPage.OdataNextLink) - .GetAsync((C) => - { - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - } - else - { - //No more result pages remain. - break; - } - } - } - - /// - /// A method to get a Group by name. - /// - /// The name of the Group to get. - /// An optional string array of fields to retrieve - /// for the target Group. - /// The Group object if found, else null. - public static Group GetGroup(string name, string[] fields = null) - { - var queryParameters = new GroupsRequestBuilderGetQueryParameters(); - queryParameters.Filter = $"displayName eq '{name}'"; - if (fields != null) - { - queryParameters.Select = fields; - } - var groups = ActiveAuth.GraphClient.Groups.GetAsync((C) => - { - C.QueryParameters = queryParameters; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult().Value; - //There should only be 1 group. If so, return it. - if ((groups != null) && (groups.Count == 1)) - { - return groups[0]; - } - return null; - } - - /// - /// A method to retrieve a list containing all the Microsoft.Graph.Group - /// values in the tenant that match the specified filter value. - /// - /// An OData filter string to apply. - /// A list containing all the Microsoft.Graph.Group values in - /// the tenant matching the given OData filter. - public static List GetGroups(string filter) - { - var groups = new List(); - GetGroups(ref groups, filter); - return groups; - } - - /// - /// A method to retrieve a list containing all the Microsoft.Graph.Group - /// values in the tenant. - /// - /// A reference to the aggregation container. - /// An OData filter string to apply. - /// A list containing all the Microsoft.Graph.Group values in - /// the tenant matching the given OData filter. - internal static void GetGroups(ref List groups, string filter = "") - { - //Get the first page of groups. - GroupCollectionResponse groupsPage = null; - if (filter == "") - { - //There's no filter, so get all Groups. - groupsPage = ActiveAuth.GraphClient.Groups - .GetAsync().GetAwaiter().GetResult(); - } - else - { - //Apply the specified filter to the Groups request. - groupsPage = ActiveAuth.GraphClient.Groups - .GetAsync((C) => - { - C.QueryParameters.Filter = filter; - //C.QueryParameters.Select = new string[] { "id", "displayName" }; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - } - GetGroupsPages(ref groups, ref groupsPage); - } - - /// - /// A method to iterate a page collection reference and add retrieved - /// items to an aggregation container reference. - /// - /// A reference to the aggregation container. - /// A reference to the first page to iterate. - internal static void GetGroupsPages( - ref List groups, - ref GroupCollectionResponse groupsPage) - { - while (groupsPage.Value != null) - { - foreach (var group in groupsPage.Value) - { - lock (groups) - { - groups.Add(group); - } - } - if (!string.IsNullOrEmpty(groupsPage.OdataNextLink)) - { - groupsPage = ActiveAuth.GraphClient.Groups - .WithUrl(groupsPage.OdataNextLink) - .GetAsync().GetAwaiter().GetResult(); - } - WriteCount(groups.Count); - } - } - - ///// - ///// A method to retrieve a list containing all the Microsoft.Graph.Group - ///// values in the tenant that match the specified filter value. - ///// - ///// An OData filter string to apply. - ///// An array of field names to return. - ///// A list containing all the Microsoft.Graph.Group values in - ///// the tenant matching the given OData filter. - //public static List GetGroups( - // string filter, - // string[] fields = null) - //{ - // var groups = new List(); - // GetGroups(ref groups, filter, fields); - // return groups; - //} - - ///// - ///// A method to retrieve a list containing all the Microsoft.Graph.Group - ///// values in the tenant. - ///// - ///// A reference to the aggregation container. - ///// An OData filter string to apply e.g. - ///// "displayName eq 'Extensions'. - ///// A string array of fields to retrieve. - ///// If null, no specific fields are targeted. - ///// A list containing all the Microsoft.Graph.Group values in - ///// the tenant matching the given OData filter. - //internal static void GetGroups( - // ref List groups, - // string filter = "", - // string[] fields = null) - //{ - // try - // { - // GroupCollectionResponse groupCollectionResponse = null; - // List ids = new List(); - // //ids = (List)(object)ids.Load>(@"GroupIds.bin"); - // List result = new List(); - // List batchGroups = new List(); - // //using var ps = PowerShell.Create(); - // //ps.AddCommand("Set-ExecutionPolicy") - // // .AddParameter("ExecutionPolicy", "RemoteSigned") - // // .AddParameter("Scope", "CurrentUser") - // // .AddParameter("Force", ""); - // //ps.AddCommand("Install-Module") - // // .AddParameter("Name", "ExchangeOnlineManagement") - // // .AddParameter("AllowClobber", "True") - // // .AddParameter("Confirm", "True"); - // //ps.AddCommand("Import-Module") - // // .AddParameter("Name", "ExchangeOnlineManagement"); - // //ps.AddCommand("Connect-ExchangeOnlineManagement") - // // .AddParameter("ExchangeEnvironmentName", "O365USGovGCCHigh") - // // .AddParameter("AccessToken", ActiveAuth.AuthResult.AccessToken); - // //ps.AddScript("$groups = GetUnifiedGroup; " + - // // "foreach ($group in $groups)" + - // // "{" + - // // " write-information $group;" + - // // "}"); - // //PSDataCollection output = new PSDataCollection(); - // //output.DataAdded += (s, e) => - // //{ - // // PSObject newRecord = ((PSDataCollection)s)[e.Index]; - // // Inf(newRecord.ToString()); - // //}; - // //var proc = ps.BeginInvoke(null, output); - // //proc.AsyncWaitHandle.WaitOne(); - // Inf(DateTime.Now.ToString()); - // int count = 0; - // while (count < ids.Count) - // { - // var idBatch = ids.Take(20).ToList(); - // count += 20; - // BatchGroup bg = new BatchGroup(); - // bg.batch = new BatchRequestContentCollection(ActiveAuth.GraphClient); - // foreach (var id in idBatch) - // { - // var groupRequest = ActiveAuth.GraphClient.Groups[id] - // .ToGetRequestInformation((C) => - // { - // C.Headers.Add("ConsistencyLevel", "eventual"); - // C.QueryParameters.Select = fields; - // }); - // bg.ids.Add(bg.batch.AddBatchRequestStepAsync( - // groupRequest).GetAwaiter().GetResult()); - // } - // batchGroups.Add(bg); - // Console.Write(count.ToString()); - // Console.CursorLeft = 0; - // } - // Console.WriteLine("\n\r"); - // foreach (var batchChunk in batchGroups.Chunk(200)) - // { - // Parallel.ForEach(batchChunk.ToList(), batchGroup => - // { - // var ret = ActiveAuth.GraphClient.Batch.PostAsync( - // batchGroup.batch).GetAwaiter().GetResult(); - // foreach (var id in batchGroup.ids) - // { - // try - // { - // lock (result) - // { - // result.Add( - // ret.GetResponseByIdAsync(id) - // .GetAwaiter().GetResult()); - // } - // } - // catch (HttpRequestException http) - // { - // } - // catch (Exception ex) - // { - // } - // } - // Console.Write(result.Count); - // Console.CursorLeft = 0; - // }); - // } - // Inf(DateTime.Now.ToString()); - - // Parallel.ForEach(ids, id => - // { - // try - // { - // var group = ActiveAuth.GraphClient.Groups[id] - // .GetAsync(C => - // { - // C.Headers.Add("ConsistencyLevel", "eventual"); - // C.QueryParameters.Select = fields; - // }).GetAwaiter().GetResult(); - // lock (result) - // { - // result.Add(group); - // } - // } - // catch (Exception ex) - // { - // } - // }); - // //var res = (object)result.Save("Groups.bin"); - - // //Setup query configuration and get the first page. - // Microsoft.Kiota.Abstractions.RequestConfiguration cfg = - // new Microsoft.Kiota.Abstractions.RequestConfiguration(); - // groupCollectionResponse = ActiveAuth.GraphClient.Groups - // .GetAsync((C) => - // { - // Configure(ref C, filter, fields); - // }).GetAwaiter().GetResult(); - // //Check if more than one page of results exist. - // if (groupCollectionResponse.OdataNextLink != null) - // { - // //If it does, create a PageIterator to get all pages. - // var pageIterator = PageIterator - // .CreatePageIterator( - // ActiveAuth.GraphClient, - // groupCollectionResponse, - // (group) => - // { - // result.Add(group); - // return true; - // }, - // (req) => - // { - // req.Headers.Add("ConsistencyLevel", "eventual"); - // Inf(result.Count.ToString()); - // return req; - // }); - // //Now let the iterator get everything. - // pageIterator.IterateAsync().GetAwaiter().GetResult(); - // } - // else - // { - // //Only one page of results, so add it to the list. - // result.AddRange(groupCollectionResponse.Value); - // } - // Inf(DateTime.Now.ToString()); - // } - // catch (Exception ex) - // { - // Err(ex.ToString()); - // } - //} - - //static void Configure( - // ref Microsoft.Kiota.Abstractions.RequestConfiguration cfg, - // string filter = "", - // string[] fields = null) - //{ - // //Add default query parameters. - // cfg.Headers.Add("ConsistencyLevel", "eventual"); - // cfg.QueryParameters.Top = 999; - // //If a filter is specified, add it. - // if ((filter != null) && - // (filter.Length > 0)) - // { - // cfg.QueryParameters.Filter = filter; - // } - // //If fields are specified, add them. - // if ((fields != null) && - // (fields.Length > 0)) - // { - // cfg.QueryParameters.Select = new string[] { "id", "displayName" }; - // //cfg.QueryParameters.Expand = fields; - // } - //} - - /////// - /////// A method to iterate a page collection reference and add retrieved - /////// items to an aggregation container reference. - /////// - /////// A reference to the aggregation container. - /////// A reference to the first page to iterate. - ////internal static void GetGroupsPages( - //// ref List groups, - //// ref IGraphServiceGroupsCollectionPage page) - ////{ - //// //Add items to the temporary list. - //// groups.AddRange(page.CurrentPage.OfType()); - //// //Recurively iterate until all items are found. - //// while (page.NextPageRequest != null) - //// { - //// page = page.NextPageRequest - //// .GetAsync().GetAwaiter().GetResult(); - //// groups.AddRange(page.CurrentPage.OfType()); - //// //Add visual feedback for command line usage. - //// WriteCount(groups.Count); - //// } - ////} - - /// - /// A method to aggregate all Groups in the tenant across 36 threads, - /// returning the cumulative list of Groups. - /// - /// A list of all Groups in the tenant. - public static List GetGroups() - { - var groups = new List(); - List starters = new List() - { - "a","b","c","d","e","f","g","h","i","j","k","l","m","n","o", - "p","q","r","s","t","u","v","w","x","y","z","1","2","3","4", - "5","6","7","8","9","0" - }; - foreach (var starter in starters) - { - GetGroups( - ref groups, - $"startswith(displayName, '{starter}')"); - } - //Parallel.ForEach(starters, starter => - //{ - // GetGroups(ref groups, $"startswith(displayName, '{starter}')"); - //}); - Inf(groups.Count.ToString()); - return groups; - } - - /// - /// A method to get a User by email or ID. - /// - /// The email or ID of the user to get. - /// Optional string array of fields to retrieve - /// for the target User. - /// The User object if found, else null. - public static User GetUser(string key, string[] fields = null) - { - var queryParameters = new UsersRequestBuilderGetQueryParameters(); - if (System.Guid.TryParse(key, out var id)) - { - queryParameters.Filter = $"id eq '{key}'"; - } - else - { - queryParameters.Filter = $"mail eq '{key}'"; - } - if (fields != null) - { - queryParameters.Select = fields; - } - var users = ActiveAuth.GraphClient.Users.GetAsync((C) => - { - C.QueryParameters = queryParameters; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult().Value; - //There should only be 1 user. If so, return it. - if ((users != null) && (users.Count == 1)) - { - return users[0]; - } - return null; - } - - /// - /// A method to return a list of all users using the given filter. - /// - /// The OData filter to apply. - /// A list of Microsoft.Graph.Models.User for the given - /// filter or all users if the filter is blank. - public static List GetUsers(string filter = "") - { - var users = new List(); - GetUsers(ref users, filter); - return users; - } - - /// - /// A method to populate a given reference list of Users using the - /// given filter. - /// - /// The aggregation container to use. - /// The OData filter to apply to the request. - internal static void GetUsers(ref List users, - string filter = "") - { - //Get the first page of Users. - UserCollectionResponse usersPage = null; - if (filter == "") - { - //There's no filter, so get all Users. - usersPage = ActiveAuth.GraphClient.Users - .GetAsync((C) => - { - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - } - else - { - //Apply the specified filter to the Users request. - usersPage = ActiveAuth.GraphClient.Users - .GetAsync((C) => - { - C.QueryParameters.Filter = filter; - //At present, Graph does not support filtering with NOT - //without using setting Count = true. - //It throws a 400 exception with an HResult of -2146233088. - //The mssage states "Operator 'not' is not supported - //because the required parameters might be missing. - //Try adding $count=true query parameter and - //ConsistencyLevel:eventual header. - //Refer to https://aka.ms/graph-docs/advanced-queries - //for more information. - C.QueryParameters.Count = true; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - } - GetUsersPages(ref users, ref usersPage); - } - - /// - /// A method to iterate all the result pages and aggregate the values - /// in the given reference list of Users. - /// - /// The aggregation container to use. - /// The first page of the response. - internal static void GetUsersPages( - ref List users, - ref UserCollectionResponse usersPage) - { - while (usersPage.Value != null) - { - foreach (var user in usersPage.Value) - { - lock (users) - { - users.Add(user); - } - } - if (!string.IsNullOrEmpty(usersPage.OdataNextLink)) - { - usersPage = ActiveAuth.GraphClient.Users - .WithUrl(usersPage.OdataNextLink) - .GetAsync((C) => - { - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - } - else - { - usersPage.Value = null; - } - } - } - - /// - /// A method to duplicate an existing M365 group. - /// - /// The name of the group to duplicate. - /// The name to use for the new group. - /// The type of data to return after - /// duplicating the Group i.e. the GUID ID of the Group or the actual - /// Group itself. - /// The GUID string ID of the Group if returnType = Id and - /// the Group object if returnType = Group. - public static object DuplicateGroup( - string groupName, - string newName, - Constants.DuplicateGroupReturnType returnType = - Constants.DuplicateGroupReturnType.Id) - { - //Find the source group. - Group group = GetGroup(groupName); - //If the group is not found, return null. - if (group == null) - { - return null; - } - Dictionary sourceFields = new Dictionary(); - Group newGroupInfo = new Group(); - System.Reflection.FieldInfo fieldInfo; - object fieldValue; - foreach (System.Reflection.FieldInfo sourceFieldInfo in typeof(Group).GetFields()) - { - fieldInfo = typeof(Group).GetField(sourceFieldInfo.Name); - fieldValue = fieldInfo.GetValue(group); - fieldInfo.SetValue(newGroupInfo, fieldValue); - } - //Create the new group. - var newGroup = ActiveAuth.GraphClient.Groups - .PostAsync(newGroupInfo) - .GetAwaiter().GetResult(); - //Determine what to return. - if (returnType == Constants.DuplicateGroupReturnType.Id) - { - //Return the ID of the new group. - return newGroup.Id; - } - return newGroup; - } - - /// - /// Create a new Group given a set of fields and values. If values - /// in the dictionary are invalid for whatever reason, the exception - /// is allowed to bubble up. - /// - /// The dictionary containing the fields - /// and values to use for Group creation. - /// The Group after creation. - public static Group NewGroup( - Dictionary groupFields) - { - var newGroupInfo = new Group(); - System.Reflection.FieldInfo fieldInfo; - foreach (KeyValuePair kvp in groupFields) - { - fieldInfo = typeof(Group).GetField(kvp.Key); - fieldInfo.SetValue(newGroupInfo, kvp.Value); - } - //Create the new group. - var newGroup = ActiveAuth.GraphClient.Groups - .PostAsync(newGroupInfo) - .GetAwaiter().GetResult(); - return newGroup; - } - - /// - /// Updates a given Group given its name and a set of fields and - /// values. If values in the dictionary are invalid for whatever - /// reason, the exception is allowed to bubble up. - /// - /// The name of the Group to update. - /// The dictionary containing the fields - /// and values to use for Group update. - /// The type of value being passed in - /// the groupName parameter i.e. DisplayName or Guid. Default is - /// DisplayName. - /// The Group after update. - public static Group UpdateGroup( - string groupName, - Dictionary groupFields, - Constants.GroupUpdateType groupUpdateType = - Constants.GroupUpdateType.DisplayName) - { - string id = ""; - if (groupUpdateType == Constants.GroupUpdateType.DisplayName) - { - var groupToUpdate = GetGroup(groupName); - id = groupToUpdate.Id; - } - var updatedGroupInfo = ConstructGroupObject(groupFields); - //Create the new group. - var updatedGroup = ActiveAuth.GraphClient.Groups[id] - .PatchAsync(updatedGroupInfo) - .GetAwaiter().GetResult(); - return updatedGroup; - } - - /// - /// Constructs a new in memory Group object given a set of fields - /// and values. If values in the dictionary are invalid for - /// whatever reason, the exception is allowed to bubble up. - /// - /// The dictionary containing the fields - /// and values to use for Group creation. - /// The Group object after construction. - public static Group ConstructGroupObject( - Dictionary groupFields) - { - var newGroupInfo = new Group(); - System.Reflection.FieldInfo fieldInfo; - foreach (KeyValuePair kvp in groupFields) - { - fieldInfo = typeof(Group).GetField(kvp.Key); - fieldInfo.SetValue(newGroupInfo, kvp.Value); - } - return newGroupInfo; - } - /// - /// Updates a given Group given its name and a the ID of the target - /// sensitivity label. Exceptions are allowed to bubble up. - /// - /// The name of the Group to update. - /// The GUID string of the target - /// sensitivity label's ID value. - /// The type of value being passed in - /// the groupName parameter i.e. DisplayName or Guid. Default is - /// DisplayName. - /// The Group after update. - public static Group SetGroupSensitivity( - string groupName, - string sensitivityGuid, - Constants.GroupUpdateType groupUpdateType = - Constants.GroupUpdateType.DisplayName) - { - Dictionary dic = new Dictionary(); - dic.Add("AssignedLabels", new List() - { - new AssignedLabel() - { - LabelId = sensitivityGuid - } - }); - return UpdateGroup(groupName, dic, groupUpdateType); - } - - /// - /// A method to retrieve a list of ID values (GUID) for all members - /// of a specified Group. - /// - /// The ID (GUID) of the target group. - /// The type of user info to return - /// i.e. "id", "mail" or "userProfileName". Default is "id". - /// A list of strings representing the IDs of member - /// users. - public static List GetMembers( - string groupId, - Constants.UserInfoType userInfoType = Constants.UserInfoType.id) - { - //Create the aggregation container. - List members = new List(); - List users = new List(); - //Get the first page of members. - var usersPage = ActiveAuth.GraphClient.Groups[groupId] - .Members.GraphUser.GetAsync(C => - { - C.QueryParameters.Select = new string[] - { - userInfoType.ToString() - }; - }).GetAwaiter().GetResult(); - if (usersPage.Value.Count == 0) - { - return members; - } - var pageIterator = PageIterator - .CreatePageIterator( - ActiveAuth.GraphClient, - usersPage, - (user) => - { - switch (userInfoType) - { - case Constants.UserInfoType.id: - if (user.Id != null && - user.Id.Trim().Length > 0) - { - members.Add(user.Id.Trim()); - } - break; - case Constants.UserInfoType.mail: - if (user.Mail != null && - user.Mail.Trim().Length > 0) - { - members.Add(user.Mail.Trim()); - } - break; - case Constants.UserInfoType.userProfileName: - if (user.UserPrincipalName != null && - user.UserPrincipalName.Trim().Length > 0) - { - members.Add(user.UserPrincipalName.Trim()); - } - break; - } - return true; - }); - pageIterator.IterateAsync().GetAwaiter().GetResult(); - Inf(members.Count.ToString()); - return members; - } - - /// - /// A method to retrieve a list of ID values (GUID) for all owners - /// of a specified Group. - /// - /// The ID (GUID) of the target group. - /// The type of user info to return - /// i.e. "id", "mail" or "userProfileName". Default is "id". - /// A list of objects representing the information about the - /// Owners users depending on the userInfoType specified i.e. - /// - For Constants.UserInfoType.id a list of strings containing user ID - /// values is returned. - /// - For Constants.UserInfoType.mail a list of strings containing user - /// email address values is returned. - /// - For Constants.UserInfoType.userPrincipalName a list of strings - /// containing user UPN values is returned. - /// - For Constants.UserInfoType.all a list of Microsoft.Graph.Models.User - /// objects is returned. - public static List GetOwners( - string groupId, - Constants.UserInfoType userInfoType = Constants.UserInfoType.id) - { - //Create the aggregation container. - List owners = new List(); - List users = new List(); - //Get the first page of owners. - var usersPage = ActiveAuth.GraphClient.Groups[groupId] - .Owners.GraphUser.GetAsync(C => - { - C.QueryParameters.Select = new string[] - { - (userInfoType == Constants.UserInfoType.All ? "" : - userInfoType.ToString()) - }; - }).GetAwaiter().GetResult(); - if (usersPage.Value.Count == 0) - { - return owners; - } - var pageIterator = PageIterator - .CreatePageIterator( - ActiveAuth.GraphClient, - usersPage, - (user) => - { - switch (userInfoType) - { - case Constants.UserInfoType.id: - if (user.Id != null && - user.Id.Trim().Length > 0) - { - owners.Add(user.Id.Trim()); - } - break; - case Constants.UserInfoType.mail: - if (user.Mail != null && - user.Mail.Trim().Length > 0) - { - owners.Add(user.Mail.Trim()); - } - break; - case Constants.UserInfoType.userProfileName: - if (user.UserPrincipalName != null && - user.UserPrincipalName.Trim().Length > 0) - { - owners.Add(user.UserPrincipalName.Trim()); - } - break; - case Constants.UserInfoType.All: - owners.Add(user); - break; - } - return true; - }); - pageIterator.IterateAsync().GetAwaiter().GetResult(); - Inf(owners.Count.ToString()); - return owners; - } - - /// - /// A method to retrieve a list of ID values (GUID) for all owners - /// of a specified Group. - /// - /// The ID (GUID) of the target group. - /// The type of user info to return - /// i.e. "id", "mail" or "userProfileName". Default is "id". - /// The type of Group membership - /// users to retrieve i.e. Owners of the Group, Members of the Group - /// or both. - /// A list of objects representing the information about the - /// Owners users depending on the userInfoType specified i.e. - /// - For Constants.UserInfoType.id a list of strings containing user ID - /// values is returned. - /// - For Constants.UserInfoType.mail a list of strings containing user - /// email address values is returned. - /// - For Constants.UserInfoType.userPrincipalName a list of strings - /// containing user UPN values is returned. - /// - For Constants.UserInfoType.all a list of Microsoft.Graph.Models.User - /// objects is returned. - public static List GetGroupUsers( - string groupId, - Constants.UserInfoType userInfoType = Constants.UserInfoType.id, - Constants.GroupUserMembershipType groupUserMembershipType - = Constants.GroupUserMembershipType.All) - { - //Create the aggregation container. - List users = new List(); - //Get the first page of users. - UserCollectionResponse usersPage = - //If groupUserMembershipType is All or Owners, get the Owners first page. - ((groupUserMembershipType == Constants.GroupUserMembershipType.All || - groupUserMembershipType == Constants.GroupUserMembershipType.Owners) ? - ActiveAuth.GraphClient.Groups[groupId] - .Owners.GraphUser.GetAsync(C => - { - C.QueryParameters.Select = new string[] - { - //Check if the userInfoType is All and if so, - //do NOT specify any .Select parameters. - (userInfoType == Constants.UserInfoType.All ? "" : - userInfoType.ToString()) - }; - C.Headers.Add("ConsistencyLevel", "eventual"); - }) : - //If its not All or Owners, its Members so get the Members first page. - ActiveAuth.GraphClient.Groups[groupId] - .Members.GraphUser.GetAsync(C => - { - C.QueryParameters.Select = new string[] - { - (userInfoType == Constants.UserInfoType.All ? "" : - userInfoType.ToString()) - }; - C.Headers.Add("ConsistencyLevel", "eventual"); - }) - ).GetAwaiter().GetResult(); - //If groupUserMembershipType is not All and there are no items, return list. - //If groupUserMembershipType is All, and there are no items in the Owners - //page then we still need to get the Members. - if ((groupUserMembershipType != Constants.GroupUserMembershipType.All) && - (usersPage.Value.Count == 0)) - { - return users; - } - //There are items so create a PageIterator. - var pageIterator = PageIterator - .CreatePageIterator( - ActiveAuth.GraphClient, - usersPage, - (user) => - { - //Aggregate the list based on the userInfoType requested. - switch (userInfoType) - { - //Get User ID GUID values. - case Constants.UserInfoType.id: - if (user.Id != null && - user.Id.Trim().Length > 0) - { - users.Add(user.Id.Trim()); - } - break; - //Get User email address values. - case Constants.UserInfoType.mail: - if (user.Mail != null && - user.Mail.Trim().Length > 0) - { - users.Add(user.Mail.Trim()); - } - break; - //Get User UPN values, usually the same as email - //but can be different. - case Constants.UserInfoType.userProfileName: - if (user.UserPrincipalName != null && - user.UserPrincipalName.Trim().Length > 0) - { - users.Add(user.UserPrincipalName.Trim()); - } - break; - //Get the entire User object. - case Constants.UserInfoType.All: - users.Add(user); - break; - } - return true; - }); - pageIterator.IterateAsync().GetAwaiter().GetResult(); - //Before returning our list check if All was requested. - if (groupUserMembershipType == Constants.GroupUserMembershipType.All) - { - //If All was requested, the list contains Owners info. - //Now get the Member info as well. - usersPage = ActiveAuth.GraphClient.Groups[groupId] - .Members.GraphUser.GetAsync(C => - { - C.QueryParameters.Select = new string[] - { - //Check if the userInfoType is All and if so, - //do NOT specify any .Select parameters. - (userInfoType == Constants.UserInfoType.All ? "" : - userInfoType.ToString()) - }; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - //If there are no Members, return the aggregated list. - if (usersPage.Value.Count == 0) - { - return users; - } - //If however there are Members, assign the first page to the - //PageIterator for processing. - pageIterator = PageIterator - .CreatePageIterator( - ActiveAuth.GraphClient, - usersPage, - (user) => - { - //Aggregate the list based on the userInfoType requested. - switch (userInfoType) - { - //Get User ID GUID values. - case Constants.UserInfoType.id: - if (user.Id != null && - user.Id.Trim().Length > 0) - { - users.Add(user.Id.Trim()); - } - break; - //Get User email address values. - case Constants.UserInfoType.mail: - if (user.Mail != null && - user.Mail.Trim().Length > 0) - { - users.Add(user.Mail.Trim()); - } - break; - //Get User UPN values, usually the same as email - //but can be different. - case Constants.UserInfoType.userProfileName: - if (user.UserPrincipalName != null && - user.UserPrincipalName.Trim().Length > 0) - { - users.Add(user.UserPrincipalName.Trim()); - } - break; - //Get the entire User object. - case Constants.UserInfoType.All: - users.Add(user); - break; - } - return true; - }); - pageIterator.IterateAsync().GetAwaiter().GetResult(); - } - //Write out the user count for debug. - Inf(users.Count.ToString()); - //Return the aggregated list. - return users; - } - - /// - /// Method to add one or more users to a group. - /// - /// The ID of the target group. - /// A list of IDs (GUIDs) of users to add to - /// the target group. - public static async void CreateMembers(string groupId, List userIds) - { - //During bulk operations, this method may be called many times. - //Yield to prevent UI lockup. - System.Threading.Thread.Yield(); - //Add the Graph location prefix. - //NOTE: The use of .com for both Commercial and GCCHigh tenants. - for (int C = 0; C < userIds.Count; C++) - { - userIds[C] = $"https://graph.microsoft.us/v1.0/directoryObjects/{userIds[C]}"; - } - var group = new Group - { - AdditionalData = new Dictionary() - { - {"members@odata.bind", (object)userIds} - } - }; - } - - /// - /// Get the site ID (GUID) of the specified site. - /// - /// The path to the site - /// e.g. "/sites/Research" - /// A GUID value representing the ID of the site. - public static string GetSiteId(string sitePath) - { - return (ActiveAuth.GraphClient.Sites[$"root:{sitePath}"] - .GetAsync().GetAwaiter().GetResult()).Id; - } - - /// - /// Get a list of all sites in SharePoint. - /// - /// A list of all sites in SharePoint. - public static List GetSites() - { - //Create the aggregation container. - var sites = new List(); - //Get the first page of sites. - var sitesPage = ActiveAuth.GraphClient.Sites - .GetAsync().GetAwaiter().GetResult(); - var pageIterator = PageIterator - .CreatePageIterator( - ActiveAuth.GraphClient, - sitesPage, - (site) => - { - sites.Add(site); - return true; - }); - Inf(sites.Count.ToString()); - return sites; - } - - /// - /// Get the list ID (GUID) of the specified list. - /// - /// The name of the list e.g. "Documents" - /// The path to the site - /// e.g. "/sites/Research" - /// A GUID value representing the ID of the list. - public static string GetListId( - string listName, - string sitePath) - { - return ActiveAuth.GraphClient.Sites[GetSiteId(sitePath)] - .Lists.GetAsync((C) => - { - C.QueryParameters.Filter = $"displayName eq '{listName}'"; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult().Value[0].Id; - } - - /// - /// Get a specific item in a specified list. - /// - /// The name of the list e.g. "Documents" - /// The path to the site - /// e.g. "/sites/Research" - /// The ID value of the item e.g. "3" - /// A list of ListItem containing the single item. - public static List GetListItem( - string listName, - string sitePath, - string id) - { - return GetListItems(listName, sitePath, id); - } - - /// - /// Method to get a field value from a ListItem object. - /// - /// The item to get data from. - /// The field to target. - /// The value of the field in the item. - public static string GetFld(this ListItem item, string field) - { - return item.Fields.AdditionalData[field].ToString(); - } - - /// - /// Get all or just one item(s) in a specified list. - /// - /// The name of the list e.g. "Documents" - /// The path to the site - /// e.g. "/sites/Research" - /// The ID value of the item e.g. "3". This value - /// defaults to null and in such case, will result in all items being - /// returned. - /// The filter syntax to use. - /// A list of ListItem containing the item(s). - public static List GetListItems( - string listName, - string sitePath, - string id = null, - string filter = null) - { - //Create the aggregation container. - List listItems = new List(); - //Check if a specific item was requested. - if (id != null) - { - try - { - //Get the specified item. - var listItem = ActiveAuth.GraphClient.Sites[GetSiteId(sitePath)] - .Lists[GetListId(listName, sitePath)] - .Items[id] - .GetAsync((C) => - { - C.QueryParameters.Expand = new string[] { "fields" }; - C.Headers.Add("ConsistencyLevel", "eventual"); - }).GetAwaiter().GetResult(); - //Check if the item was found. - if (listItem != null) - { - listItems.Add(listItem); - } - } - catch (Exception ex) - { - Err(ex.ToString()); - } - } - else - { - try - { - var listItemCollectionResponse = - ActiveAuth.GraphClient.Sites[GetSiteId(sitePath)] - .Lists[GetListId(listName, sitePath)] - .Items.GetAsync((C) => - { - if (filter != null) - { - C.QueryParameters.Filter = filter; - C.Headers.Add("ConsistencyLevel", "eventual"); - } - C.QueryParameters.Expand = new string[] { "fields" }; - }).GetAwaiter().GetResult(); - if (listItemCollectionResponse == null) - { - return listItems; - } - var pageIterator = PageIterator - .CreatePageIterator( - ActiveAuth.GraphClient, - listItemCollectionResponse, - (listItem) => - { - listItems.Add(listItem); - return true; - }); - pageIterator.IterateAsync().GetAwaiter().GetResult(); - } - catch (Exception ex) - { - if (ex.Message.Contains("Requested site could not be found")) - { - Err(ex.ToString()); - } - throw; - } - } - //Return the aggregated list. - Inf(listItems.Count.ToString()); - return listItems; - } - - /// - /// Get all items in a given list updated since a given datetime and - /// with a pending status. - /// - /// The name of the list from which to get - /// items e.g. "Documents". - /// The site path of the site containing the - /// list e.g. "/sites/MySite" - /// The date/time string to use to narrow - /// down the returned result set e.g. "2017-07-04". If not specified - /// and the default value of null is found, this field will default - /// to the current date/time minus one day. - /// A list of ListItem containing the item(s). - public static List GetPendingListItemsUpdatedSince( - string listName, - string sitePath, - string dateTime = null) - { - Inf(Core.GetEnv("NewItemsStatusFilter")); - Inf($"Scope [{ActiveAuth.Scopes[0]}]"); - Inf($"GetPendingListItemsUpdatedSince(" + - $"{listName}, {sitePath}, {dateTime}"); - if (dateTime == null) - { - dateTime = DateTime.Now.AddDays(-1).ToString(); - } - var items = GetListItems( - listName, - sitePath, - null, - $"fields/Modified gt '{dateTime}'"); - Inf($"Pre-filtered items:[{items.Count}]"); - string filter = "pending"; - filter = Core.GetEnv("NewItemsStatusFilter").ToLower(); - for (int C = items.Count - 1; C >= 0; C--) - { - if (items[C].GetJsonString("Status").ToLower() != "filter") - { - items.RemoveAt(C); - } - } - Inf($"Post-filtered items:[{items.Count}]"); - return items; - } - - /// - /// Gets the Team associated with the current Group. - /// - /// The Group for which to get the Team. - /// The Team if it exist, else null. - public static Team GetTeam( - this Microsoft.Graph.Models.Group group) - { - if (group.HasTeam()) - { - return GetTeam(group.Id); - } - return null; - } - - /// - /// Gets the Team associated with the current Group. - /// - /// The ID of the Group for which to get - /// the Team. - /// The Team if it exist, else null. - public static Team GetTeam( - string groupId) - { - Team team = null; - try - { - team = ActiveAuth.GraphClient.Groups[groupId].Team - .GetAsync().GetAwaiter().GetResult(); - return team; - } - catch (Exception ex) - { - Err(ex.ToString()); - return null; - } - } - - /// - /// Checks if the Group has an associated Team. - /// - /// The Group being checked. - /// True if the Group has an associated Team, else false. - public static bool HasTeam( - this Group group) - { - var groups = GetGroups("((id eq '" + group.Id + - "') and (resourceProvisioningOptions/Any(x:x eq 'Team')))"); - return groups.Count > 0; - } - - /// - /// Add a Team to the current group. - /// - /// The target Group for Team addition. - /// Optional Team options to use when - /// creating the new Team. - /// The Team after creation. If the Team already exist, the - /// existing Team is returned. If creation fails it'll retry for 30 - /// seconds before returning null. - public static Team Teamify( - this Group group, - Team newTeamInfo = null) - { - return Teamify(group.Id, newTeamInfo); - } - - /// - /// Add a Team to the current group. - /// - /// The ID of the target Group for Team - /// addition. - /// Optional Team options to use when - /// creating the new Team. - /// The Team after creation. If the Team already exist, the - /// existing Team is returned. If creation fails it'll retry for 30 - /// seconds before returning null. - public static Team Teamify( - string groupId, - Team newTeamInfo = null) - { - Team team = null; - bool done = false; - int count = 0; - while (!done) - { - count++; - try - { - team = GetTeam(groupId); - if (team != null) - { - done = true; - return team; - } - else - { - if (newTeamInfo == null) - { - newTeamInfo = new Team - { - MemberSettings = new TeamMemberSettings - { - AllowCreatePrivateChannels = true, - AllowCreateUpdateChannels = true - }, - MessagingSettings = new TeamMessagingSettings - { - AllowUserDeleteMessages = true, - AllowUserEditMessages = true - }, - FunSettings = new TeamFunSettings - { - AllowGiphy = true, - GiphyContentRating = GiphyRatingType.Strict - } - }; - } - team = ActiveAuth.GraphClient.Groups[groupId].Team - .PutAsync(newTeamInfo) - .GetAwaiter().GetResult(); - if (team != null) - { - done = true; - return team; - } - } - } - catch (Exception ex) - { - //Azure async processes may not yet have created the Team. - //Wait for a second before retrying. - Thread.Sleep(1000); - } - if (count > 30) - { - done = true; - return null; - } - } - return team; - } - - /// - /// Update a specified list item with specified values. - /// - /// The site ID (GUID) value. - /// The list ID (GUID) value. - /// The ID value of the item e.g. "3" - /// A dictionary of objects representing the - /// field names and values to update. - public static void UpdateListItemFields( - string siteGuid, - string listGuid, - string listItemId, - Dictionary newFields) - { - ActiveAuth.GraphClient.Sites[siteGuid] - .Lists[listGuid] - .Items[listItemId] - .Fields - .PatchAsync(CreateFieldValueSet(newFields)) - .GetAwaiter().GetResult(); - } - - /// - /// Create a new list item with specified values. - /// - /// The site ID (GUID) value. - /// The list ID (GUID) value. - /// A dictionary of objects representing the - /// field names and values to update. - public static void CreateListItem( - string siteGuid, - string listGuid, - Dictionary newFields) - { - ActiveAuth.GraphClient.Sites[siteGuid] - .Lists[listGuid] - .Items - .PostAsync(CreateListItemJSON(newFields)) - .GetAwaiter().GetResult(); - } - - /// - /// Method to create a new list item. - /// - /// The target site ID. - /// The target list ID. - /// The ListItem to add to the target. - public static void CreateListItem( - string siteGuid, - string listGuid, - ListItem listItem) - { - ActiveAuth.GraphClient.Sites[siteGuid] - .Lists[listGuid] - .Items - .PostAsync(listItem) - .GetAwaiter().GetResult(); - } - - /// - /// Create a new FieldValueSet JSON object. - /// - /// A dictionary of objects representing the - /// field names and values to use. - /// A FieldValueSet object populated with the values from - /// the dictionary. - internal static FieldValueSet CreateFieldValueSet( - Dictionary newFields) - { - return new FieldValueSet - { - AdditionalData = newFields - }; - } - - /// - /// Create a new ListItem JSON object. - /// - /// A dictionary of objects representing the - /// field names and values to use. - /// A ListItem object populated with the values from the - /// dictionary. - internal static ListItem CreateListItemJSON( - Dictionary newFields) - { - return new ListItem - { - Fields = CreateFieldValueSet(newFields) - }; - } - - /// - /// A method to force Azure to provision the back end SharePoint site - /// for a given Group or Team. When new Teams are created via code, - /// Azure will not spin up the SharePoint site until a user clicks on - /// the Files link. Problem is that when the user does that they get - /// an error message telling them to try again later. This is a - /// terrible user experience so the .SharePointify() method can be - /// used to force the process to take place so the user never sees - /// that error. - /// - /// The GUID ID of the Group associated with the - /// Team. - /// A reference to the Drive object if successful. The process - /// will retry every second for 30 seconds afterwhich it will timeout - /// and simply return null. This seldom happens. - public static Drive SharePointify( - string groupId) - { - Drive drive = null; - bool done = false; - int count = 0; - while (!done) - { - count++; - try - { - drive = ActiveAuth.GraphClient.Groups[groupId].Drive - .GetAsync().GetAwaiter().GetResult(); - if (drive != null) - { - done = true; - return drive; - } - } - catch (Exception ex) - { - //Azure async processes may not yet have created the Group. - //Wait for a second before retrying. - Thread.Sleep(1000); - } - if (count > 30) - { - done = true; - } - } - return drive; - } - - /// - /// A method to force Azure to provision the back end SharePoint site - /// for a given Group or Team. When new Teams are created via code, - /// Azure will not spin up the SharePoint site until a user clicks on - /// the Files link. Problem is that when the user does that they get - /// an error message telling them to try again later. This is a - /// terrible user experience so the .SharePointify() method can be - /// used to force the process to take place so the user never sees - /// that error. - /// - /// The Group associated with the Team. - /// A reference to the Drive object if successful. The process - /// will retry every second for 30 seconds afterwhich it will timeout - /// and simply return null. This seldom happens. - public static Drive SharePointify( - this Microsoft.Graph.Models.Group group) - { - return SharePointify(group.Id); - } - - /// - /// Write visible feedback to console for command line usage. The - /// feedback is written in a fixed location providing a counter like - /// experience without screen scroll. - /// - /// The count to write. - internal static void WriteCount(int count) - { - //Capture the current cursor location. - var left = Console.CursorLeft; - var top = Console.CursorTop; - //Write output. - Console.Write(count); - //Reset the cursor location. - Console.CursorLeft = left; - Console.CursorTop = top; - } - } -} diff --git a/Classes/Extensions.Identity.App.cs b/Classes/Extensions.Identity.App.cs deleted file mode 100644 index 597ca9b..0000000 --- a/Classes/Extensions.Identity.App.cs +++ /dev/null @@ -1,200 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using Microsoft.Identity.Client; -using System; -using System.Linq; -using System.Security.Cryptography.X509Certificates; - -namespace Extensions.Identity -{ - /// - /// A class for managing ConfidentialClientApplications in Azure. - /// - [Serializable] - public static partial class App - { - /// - /// An enum for the type of Azure environment. - /// - public enum EnvironmentName - { - /// - /// China national cloud. - /// - O365China, - /// - /// Default commercial cloud. - /// - O365Default, //Commercial tenant - /// - /// Germany national cloud. - /// - O365GermanyCloud, - /// - /// US Government Department of Defense cloud. - /// - O365USGovDoD, - /// - /// US Government High Security cloud. - /// - O365USGovGCCHigh //GCCHigh tenant - } - - /// - /// Get a valid IConfidentialClientApplication. - /// - /// The GUID for the App/Client ID. - /// The thumbprint of the associated - /// certificate. - /// The tenant string e.g. for - /// 'contoso.sharepoint.com' the value would be 'contoso'. - /// The environment name enum value. - /// Defaults to O365USGovGCCHigh. - /// An IConfidentialClientApplication object. - public static IConfidentialClientApplication GetApp( - string appId, - string thumbPrint, - string tenantString, - EnvironmentName environmentName = EnvironmentName.O365USGovGCCHigh) - { - //Get the target cert. - var cert = Cert.GetCertByThumbPrint(thumbPrint); - //Using the cert, get the app. - return GetApp(appId, cert, tenantString, environmentName); - } - - /// - /// Get a valid IConfidentialClientApplication. - /// - /// The GUID for the App/Client ID. - /// The associated certificate. - /// The tenant string e.g. for - /// 'contoso.sharepoint.com' the value would be 'contoso'. - /// The environment name enum value. - /// Defaults to O365USGovGCCHigh. - /// An IConfidentialClientApplication object. - public static IConfidentialClientApplication GetApp( - string appId, - X509Certificate2 cert, - string tenantString, - EnvironmentName environmentName = EnvironmentName.O365USGovGCCHigh) - { - //Get the authority URL for the given environment. - string authority = GetAuthority(environmentName, tenantString); - //Create the app using appId, cert and authority. - return ConfidentialClientApplicationBuilder.Create(appId) - .WithCertificate(cert) - .WithAuthority(new Uri(authority)) - .Build(); - } - - /// - /// Get a valid IPublicClientApplication. - /// - /// The GUID for the App/Client ID. - /// The tenant string e.g. for - /// 'contoso.sharepoint.com' the value would be 'contoso'. - /// The environment name enum value. - /// Defaults to O365USGovGCCHigh. - /// An IPublicClientApplication object. - public static IPublicClientApplication GetApp( - string appId, - string tenantString, - EnvironmentName environmentName = EnvironmentName.O365USGovGCCHigh) - { - //Get the authority URL for the given environment. - string authority = GetAuthority(environmentName, tenantString); - //Create the app using appId, cert and authority. - return PublicClientApplicationBuilder.Create(appId) - .WithAuthority(new Uri(authority)) - .WithDefaultRedirectUri() - .Build(); - } - - /// - /// The different types of authentication efforts to use. - /// - internal enum PublicAppAuthResultType - { - Silent, - Interactive, - Prompt - } - - /// - /// Get an IPublicClientApplication AuthenticationResult based on - /// different authentication methods from least to most intrusive. - /// - /// A reference to the IPublicClientApplication - /// that is being authenticated. - /// A reference to the accounts associated - /// with the given IPublicClientApplication. - /// The type of authentication to use. Values - /// range from least to most intrusive to the end user. - /// A valid AuthenticationResult or null. - internal static AuthenticationResult GetPublicAppAuthResult( - ref IPublicClientApplication app, - ref System.Collections.Generic.IEnumerable accounts, - PublicAppAuthResultType authType) - { - switch (authType) - { - case PublicAppAuthResultType.Silent: - return app.AcquireTokenSilent( - Scopes.Graph, - accounts.FirstOrDefault()) - .ExecuteAsync().GetAwaiter().GetResult(); - break; - case PublicAppAuthResultType.Interactive: - return app.AcquireTokenInteractive(Scopes.Graph) - .ExecuteAsync().GetAwaiter().GetResult(); - break; - case PublicAppAuthResultType.Prompt: - return app.AcquireTokenInteractive(Scopes.Graph) - .WithAccount(accounts.FirstOrDefault()) - .WithPrompt(Prompt.SelectAccount) - .ExecuteAsync().GetAwaiter().GetResult(); - break; - } - return null; - } - - /// - /// Get the authentication authority URL for the given environment. - /// - /// The specified environment. - /// Defaults to GCCHigh. - /// The specified tenant string. - /// The URL of the authentication authority. - /// Unimplemented clouds. - public static string GetAuthority(EnvironmentName environmentName, - string tenantString) - { - string result = "https://login.microsoftonline"; - switch (environmentName) - { - case EnvironmentName.O365China: - throw new Exception("O365China is not presently supported."); - break; - case EnvironmentName.O365Default: - result += $".com/{tenantString}.sharepoint.com"; - break; - case EnvironmentName.O365GermanyCloud: - throw new Exception("O365GermanyCloud is not presently supported."); - break; - case EnvironmentName.O365USGovDoD: - throw new Exception("O365USGovDoD is not presently supported."); - break; - case EnvironmentName.O365USGovGCCHigh: - result += $".us/{tenantString}.sharepoint.us"; - break; - } - return result; - } - } -} diff --git a/Classes/Extensions.Identity.Auth.ClientApplicationType.cs b/Classes/Extensions.Identity.Auth.ClientApplicationType.cs deleted file mode 100644 index 4c078d9..0000000 --- a/Classes/Extensions.Identity.Auth.ClientApplicationType.cs +++ /dev/null @@ -1,30 +0,0 @@ -using System; -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// -namespace Extensions.Identity -{ - /// - /// Auth class for holding authentication objects. - /// - public partial class Auth - { - /// - /// The type of ClientApplication to use. - /// - public enum ClientApplicationType - { - /// - /// Confidential - /// - Confidential, - /// - /// Public - /// - Public - } - } -} diff --git a/Classes/Extensions.Identity.Auth.cs b/Classes/Extensions.Identity.Auth.cs deleted file mode 100644 index 6fc6386..0000000 --- a/Classes/Extensions.Identity.Auth.cs +++ /dev/null @@ -1,283 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using Microsoft.Graph; -using Microsoft.Identity.Client; -using System; -using System.Net.Http; -using System.Security.Cryptography.X509Certificates; -using System.Threading; -using static Extensions.Identity.AuthMan; -using static System.Logit; - -namespace Extensions.Identity -{ - /// - /// Auth class for holding authentication objects. - /// - [Serializable] - public partial class Auth - { - /// - /// The ID of the auth object in format {TenantID}=={AppId}=={ThumbPrint}" - /// - public string Id { get; private set; } - - /// - /// The container to maintain the current Auth object scope type. - /// - ScopeType AuthScopeType { get; set; } - - /// - /// The container for this Auth object's associated tenant configuration. - /// - public TenantConfig TenantCfg { get; private set; } - = new TenantConfig(CoreBase.TenantString); - - /// - ///The type of ClientApplication the current Auth object is using. - /// - public ClientApplicationType AppType { get; private set; } - - /// - /// The certificate of the current Auth object. - /// - public X509Certificate2 Cert { get; private set; } = null; - - /// - /// The current IConfidentialClientApplication of the current Auth object. - /// - public object App { get; private set; } - - /// - /// The current AuthenticationResult of the current Auth object. - /// - public AuthenticationResult AuthResult { get; set; } - - /// - /// The current scopes with with the current Auth object. - /// Defaults to Graph. - /// - public string[] Scopes { get; set; } - = Identity.Scopes.Graph; - - /// - /// The current authenticated GraphClient of the current Auth object. - /// - public GraphServiceClient GraphClient { get; set; } - - /// - /// The current authenticated GraphClient of the current Auth object - /// for the Beta endpoint. - /// - public GraphServiceClient GraphBetaClient { get; set; } - - /// - /// The current authenticated HttpClient of the current Auth object. - /// - public HttpClient HttpClient { get; set; } - - /// - /// The authentication refresh timer of the current Auth object. - /// - public System.Threading.Timer Timer { get; private set; } - - /// - /// Empty constructor for Auth. - /// - public Auth() - { - } - - /// - /// The constructor that populates all the member variables of this - /// instance of the Auth object. - /// - /// The Tenant/Directory ID of the target. - /// The Application/Client ID of the target. - /// The thumbprint of the certificate to - /// use. - /// The base tenant string used with the - /// current Auth object e.g. for "contoso.sharepoint.com" it would - /// be "contoso". - /// The type of ClientApplication to use. - /// The scope type used by this auth. - public Auth( - string tenantId, - string appId, - string thumbprint, - string tenantString, - ClientApplicationType appType = ClientApplicationType.Confidential, - ScopeType scopeType = ScopeType.Graph) - { - Inf($"Auth.Auth({tenantId}, {appId}, {thumbprint}, {tenantString}, {appType.ToString()}, {scopeType.ToString()});"); - //Generate the unique ID. - Id = AuthMan.GetKey(tenantId, appId, thumbprint, scopeType.ToString()); - AuthScopeType = scopeType; - //Save the parms. - AppType = appType; - //Save the tenant configuration values. - TenantCfg.TenantDirectoryId = tenantId; - TenantCfg.ApplicationClientId = appId; - TenantCfg.CertThumbprint = thumbprint; - TenantCfg.TenantString = tenantString; - //Get the certificate. - Cert = Identity.Cert.GetCertByThumbPrint(thumbprint); - //Get the application. - App = Identity.App.GetApp(appId, thumbprint, tenantString); - //Set the scopes for this Auth object. - Scopes = Identity.Scopes.GetScopes(scopeType); - TenantCfg.Settings = Core.Config.Settings; - TenantCfg.Labels = Core.Config.Labels; - if (!Core.Tenants.ContainsKey(tenantString)) - { - Core.Tenants.Add(tenantString, TenantCfg); - } - Core.ActiveTenant = Core.Tenants[tenantString]; - //Call refresh method to populate the rest. - RefreshAuth(null); - } - - /// - /// The constructor that populates all the member variables of this - /// instance of the Auth object. - /// - /// The Tenant/Directory ID of the target. - /// The Application/Client ID of the target. - /// The certificate to use. - /// The base tenant string used with the - /// current Auth object e.g. for "contoso.sharepoint.com" it would - /// be "contoso". - /// The type of ClientApplication to use. - /// The scope type to use. - public Auth( - string tenantId, - string appId, - X509Certificate2 cert, - string tenantString, - ClientApplicationType appType = ClientApplicationType.Confidential, - ScopeType scopeType = ScopeType.Graph) - { - Cert = cert; - //Generate the unique ID. - Id = AuthMan.GetKey(tenantId, appId, Cert.Thumbprint, scopeType.ToString()); - AuthScopeType = scopeType; - //Save the parms. - AppType = appType; - TenantCfg.TenantDirectoryId = tenantId; - TenantCfg.ApplicationClientId = appId; - TenantCfg.CertThumbprint = Cert.Thumbprint; - TenantCfg.TenantString = tenantString; - //Get the application. - App = Identity.App.GetApp(appId, Cert.Thumbprint, tenantString); - //Set the scopes for this Auth object. - Scopes = Identity.Scopes.GetScopes(scopeType); - TenantCfg.Settings = Core.Config.Settings; - TenantCfg.Labels = Core.Config.Labels; - if (!Core.Tenants.ContainsKey(tenantString)) - { - Core.Tenants.Add(tenantString, TenantCfg); - } - Core.ActiveTenant = Core.Tenants[tenantString]; - - //Call refresh method to populate the rest. - RefreshAuth(null); - } - - /// - /// The constructor that populates all the member variables of this - /// instance of the Auth object. - /// - /// The Tenant/Directory ID of the target. - /// The Application/Client ID of the target. - /// The base tenant string used with the - /// current Auth object e.g. for "contoso.sharepoint.com" it would - /// be "contoso". - /// The type of ClientApplication to use. - public Auth( - string tenantId, - string appId, - string tenantString, - ClientApplicationType appType = ClientApplicationType.Public) - { - //Generate the unique ID. - Id = AuthMan.GetKey(tenantId, appId, "PublicClientApplication", ""); - //Save the parms. - AppType = appType; - TenantCfg.TenantDirectoryId = tenantId; - TenantCfg.ApplicationClientId = appId; - TenantCfg.TenantString = tenantString; - //Get the application. - App = Identity.App.GetApp(appId, tenantString); - if (!Core.Tenants.ContainsKey(tenantString)) - { - Core.Tenants.Add(tenantString, TenantCfg); - } - Core.ActiveTenant = Core.Tenants[tenantString]; - //Call refresh method to populate the rest. - RefreshAuth(null); - } - - /// - /// The method that refreshes the current Auth object's related - /// authentication members. - /// - /// Needed for the timer method. - public void RefreshAuth(Object obj) - { - //Build the application. - switch (AppType) - { - case ClientApplicationType.Confidential: - App = Identity.App.GetApp(TenantCfg.ApplicationClientId, - Cert, - TenantCfg.TenantString); - break; - case ClientApplicationType.Public: - App = Identity.App.GetApp(TenantCfg.ApplicationClientId, - TenantCfg.TenantString); - break; - } - //Get a valid AuthenticationResult for the app. - AuthResult = GetAuthResult( - App, - TenantCfg.TenantDirectoryId, - AppType, - Scopes); - //Build the GraphServiceClient object using the AuthenticatedResult - //from the previous step. - HttpClient = GetHttpClient(AuthResult); - GraphClient = GetGraphServiceClient(HttpClient); - GraphBetaClient = GetGraphBetaServiceClient(HttpClient); - //Check if the current Auth object is in the stack. - if (AuthStack.ContainsKey(Id)) - { - //It is, so update it. - lock (AuthStack) - { - AuthStack[Id] = this; - } - } - else - { - //It is not, so push it to the stack. - lock(AuthStack) - { - AuthStack.Add(Id, this); - } - } - //Define the refresh timer that will fire 5 minutes before the - //expiration of the AuthenticationResult. - Timer = new System.Threading.Timer( - RefreshAuth, - null, - (AuthResult.ExpiresOn - DateTime.UtcNow).Subtract( - TimeSpan.FromMinutes(5)), - Timeout.InfiniteTimeSpan); - } - } -} diff --git a/Classes/Extensions.Identity.AuthMan.cs b/Classes/Extensions.Identity.AuthMan.cs deleted file mode 100644 index 4e094cd..0000000 --- a/Classes/Extensions.Identity.AuthMan.cs +++ /dev/null @@ -1,607 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using Microsoft.Graph; -using Microsoft.Identity.Client; -using Microsoft.SharePoint.Client; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Http; -using System.Net.Http.Headers; -using System.Security.Cryptography.X509Certificates; -using System.Text.Json; -using System.Threading; -using static Extensions.Core; -using static Extensions.Identity.App; -using static Extensions.Identity.Auth; - -namespace Extensions.Identity -{ - /// - /// Authentication Manager class for working with M365 and GCCHigh. - /// - [Serializable] - public static partial class AuthMan - { - /// - /// The stack of current Auth objects. - /// - public static Dictionary AuthStack { get; set; } - = new Dictionary(); - - /// - /// Constructor method. - /// - static AuthMan() - { - //Intentionally left empty. - } - - /// - /// Method to get the AuthenticationResult of current ActiveAuth. - /// - /// The scopes to use for auth. - /// The active AuthenticationResult. - public static AuthenticationResult GetAuthenticationResult( - string[] scopes = null) - { - if ((ActiveAuth.AuthResult == null) || - ((scopes != null) && - (ActiveAuth.Scopes != scopes))) - { - GetAuth(scopes); - } - return ActiveAuth.AuthResult; - } - - /// - /// Method to get a matching Auth object from the stack or if it - /// doesn't exist on the stack, generate the new Auth object and - /// push it to the stack. - /// - /// An array of scope strings. - /// Boolean to trigger a clearing of the - /// Auth stack. Default value is false. - /// A valid Auth object from the stack. - public static Auth GetAuth( - string[] scopes, - bool authStackReset = false) - { - ScopeType scopeType = Scopes.GetScopeType(scopes); - return GetAuth(scopeType, authStackReset); - } - - /// - /// Method to get a matching Auth object from the stack or if it - /// doesn't exist on the stack, generate the new Auth object and - /// push it to the stack. - /// - /// The scope type of the Auth. Default value - /// is Graph. - /// Boolean to trigger a clearing of the - /// Auth stack. Default value is false. - /// A valid Auth object from the stack. - public static Auth GetAuth( - ScopeType scopeType = ScopeType.Graph, - bool authStackReset = false) - { - return GetAuth( - ActiveTenant.TenantDirectoryId, - ActiveTenant.ApplicationClientId, - ActiveTenant.CertThumbprint, - ActiveTenant.TenantString, - scopeType, - authStackReset); - } - - /// - /// Method to get a matching Auth object from the stack or if it - /// doesn't exist on the stack, generate the new Auth object and - /// push it to the stack. - /// - /// The Tenant/Directory ID to use for the - /// Auth object. - /// The Application/Client ID to use for the - /// Auth object. - /// The certificate thumbprint to use for - /// the Auth object. - /// The base tenant string to use for - /// the Auth object e.g. for "contoso.sharepoint.com" it would - /// be "contoso". - /// The scope type of the Auth. - /// Boolean to trigger a clearing of the - /// Auth stack. - /// A valid Auth object from the stack. - public static Auth GetAuth( - string tenantId, - string appId, - string thumbPrint, - string tenantString, - ScopeType scopeType = ScopeType.Graph, - bool authStackReset = false) - { - //If logging location is static, don't write this output. - if (!Logit.ActiveLogitInstance.StaticConsoleLocation) - { - //Check if there's an active auth that can be used to log to - //SharePoint and if logging to SharePoint is enabled. - if ((ActiveAuth.AuthResult == null) && - (Logit.ActiveLogitInstance.LogToSPList)) - { - //There isn't so don't log to list an active Logit instance. - Logit.ActiveLogitInstance.LogToSPList = false; - //Inf($"AuthMan.GetAuth({tenantId}, {appId}, {thumbPrint}, " + - // $"{tenantString}, {scopeType.ToString()}, " + - // $"{authStackReset.ToString()}"); - Logit.ActiveLogitInstance.LogToSPList = true; - } - else - { - //Inf($"AuthMan.GetAuth({tenantId}, {appId}, {thumbPrint}, " + - // $"{tenantString}, {scopeType.ToString()}, " + - // $"{authStackReset.ToString()}"); - } - } - //If a reset is requested, clear the stack. - if (authStackReset) - { - AuthStack.Clear(); - } - //Generate the key from the parms. - string key = GetKey(tenantId, appId, thumbPrint, scopeType.ToString()); - //Check if the key is on the stack. - if (AuthStack.ContainsKey(key)) - { - //If it is, set the current ActiveAuth to that stack instance. - SetActiveAuth(key); - } - else - { - //If it is not, generate a new Auth object. - var auth = new Auth( - tenantId, - appId, - thumbPrint, - tenantString, - Auth.ClientApplicationType.Confidential, - scopeType); - //Set the current ActiveAuth to the new stack instance - //that was pushed to the stack by its ctor. - SetActiveAuth(key); - } - //Return the ActiveAuth object. - return ActiveAuth; - } - - /// - /// Method to get a matching Auth object from the stack or if it - /// doesn't exist on the stack, generate the new Auth object and - /// push it to the stack. - /// - /// The Tenant/Directory ID to use for the - /// Auth object. - /// The Application/Client ID to use for the - /// Auth object. - /// The certificate to use for the Auth - /// object. - /// The base tenant string to use for - /// the Auth object e.g. for "contoso.sharepoint.com" it would - /// be "contoso". - /// The scope type of the Auth. - /// Boolean to trigger a clearing of the - /// Auth stack. - /// A valid Auth object from the stack. - public static Auth GetAuth( - string tenantId, - string appId, - X509Certificate2 cert, - string tenantString, - ScopeType scopeType = ScopeType.Graph, - bool authStackReset = false) - { - return GetAuth( - tenantId, - appId, - cert.Thumbprint, - tenantString, - scopeType, - authStackReset); - } - - #region GetAuthorityDomain - /// - /// A public method to get the domain extension. - /// - /// The name of the Azure environment - /// type. - /// ".us" if the environment is USGovGCCHigh otherwise it - /// will return ".com". - public static string GetAuthorityDomain( - AzureEnvironment azureEnvironment = AzureEnvironment.USGovGCCHigh) - { - if (azureEnvironment == AzureEnvironment.USGovGCCHigh) - { - return ".us"; - } - return ".com"; - } - #endregion GetAuthorityDomain - - /// - /// Method to get a matching Auth object from the stack or if it - /// doesn't exist on the stack, generate the new Auth object and - /// push it to the stack. - /// - /// The Tenant/Directory ID to use for the - /// Auth object. - /// The Application/Client ID to use for the - /// Auth object. - /// The base tenant string to use for - /// the Auth object e.g. for "contoso.sharepoint.com" it would - /// be "contoso". - /// A valid Auth object from the stack. - public static Auth GetPublicAuth(string tenantId, - string appId, - string tenantString) - { - //Generate the key from the parms. - string key = GetKey(tenantId, appId, "PublicClientApplication", ""); - //Check if the key is on the stack. - if (AuthStack.ContainsKey(key)) - { - //If it is, set the current ActiveAuth to that stack instance. - SetActiveAuth(key); - } - else - { - //If it is not, generate a new Auth object. - var auth = new Auth(tenantId, appId, tenantString); - //Push it to the stack. - AuthStack.Add(auth.Id, auth); - //Set the current ActiveAuth to the new stack instance. - SetActiveAuth(auth.Id); - } - //Return the ActiveAuth object. - return ActiveAuth; - } - - /// - /// Internal method to generate a consistent key for the Auth object. - /// - /// The Tenant/Directory ID to use for the - /// Auth object. - /// The Application/Client ID to use for the - /// Auth object. - /// The certificate thumbprint to use for - /// the Auth object. - /// The scope type to use. - /// A string consisting of the lower case version of the - /// specified parameters in the format of - /// {TenantID}=={AppId}=={ThumbPrint}" - internal static string GetKey( - string tenantId, - string appId, - string thumbPrint, - string scopeType) - { - return NoNull(tenantId.ToLower()) + "==" + - NoNull(appId.ToLower()) + "==" + - NoNull(thumbPrint.ToLower()) + "==" + - NoNull(scopeType.ToLower()); - } - - /// - /// Method to convert a string type to ClientApplicationType. - /// - /// The string to convert. - /// A ClientApplicationType. - /// Default is Confidential. - public static ClientApplicationType GetClientApplicationType - (string clientApplicationType) - { - switch (clientApplicationType.ToLower()) - { - case "public": - return ClientApplicationType.Public; - break; - } - return ClientApplicationType.Confidential; - } - - /// - /// Get the currently active TenantString. - /// - /// A string if the stack is not empty, otherwise it will - /// return null. - public static string GetTenantString() - { - if (ActiveAuth != null) - { - return ActiveAuth.TenantCfg.TenantString; - } - else - { - try - { - string env = GetEnv("TenantString"); - if (env != null) - { - return env; - } - else - { - try - { - //Load config from file. - using (StreamReader sr = new StreamReader( - GetRunFolder() + "\\" + $"TenantConfig.json")) - { - var tenantConfig = - JsonSerializer.Deserialize(sr.ReadToEnd()); - sr.Close(); - return tenantConfig.TenantString; - } - } - catch (Exception ex2) - { - //Err(ex2.ToString()); - throw; - } - } - } - catch (Exception ex) - { - //Err(ex.ToString()); - throw; - } - } - } - - /// - /// A method to return the current execution folder. - /// - /// A string containing the execution folder path. - public static string GetRunFolder() - { - return Path.GetDirectoryName( - System.Reflection.Assembly.GetEntryAssembly() - .Location.TrimEnd('\\')); //Ensure no double trailing slash. - } - - /// - /// A method to return a valid HttpClient for the given - /// AuthenticationResult. - /// - /// The AuthenticationResult to use during - /// HttpClient construction. - /// A valid HttpClient using the given - /// AuthenticationResult. If authResult is null, it will return - /// the HttpClient from the ActiveAuth. - public static HttpClient GetHttpClient( - AuthenticationResult authResult = null) - { - if (authResult == null) - { - return ActiveAuth.HttpClient; - } -#if NET5_0_OR_GREATER - var socketsHandler = new SocketsHttpHandler - { - MaxConnectionsPerServer = 1000, - PooledConnectionIdleTimeout = TimeSpan.FromMinutes(55), - PooledConnectionLifetime = TimeSpan.FromMinutes(60) - }; - //Build the HttpClient object using the AuthenticationResult - //from the previous step. - HttpClient httpClient = new HttpClient(socketsHandler); -#endif -#if NETFRAMEWORK || NETSTANDARD - HttpClient httpClient = new HttpClient(); -#endif - httpClient.Timeout = TimeSpan.FromMinutes(1) + - TimeSpan.FromSeconds(40); - ServicePointManager.DefaultConnectionLimit = int.MaxValue; - ThreadPool.SetMaxThreads(32767, 1000); - ProductInfoHeaderValue productInfoHeaderValue = - new ProductInfoHeaderValue("User-Agent", $"NONISV|Extensions"); - httpClient.DefaultRequestHeaders.UserAgent.Add( - productInfoHeaderValue); - httpClient.DefaultRequestHeaders.Authorization = - new AuthenticationHeaderValue("Bearer", authResult.AccessToken); - httpClient.DefaultRequestHeaders.Accept.Add( - new MediaTypeWithQualityHeaderValue("application/json")); - return httpClient; - } - - /// - /// A method to return a valid GraphServiceClient for the given - /// HttpClient. - /// - /// The HttpClient to use during construction - /// of the GraphServiceClient. - /// A valid GraphServiceClient for the given - /// HttpClient. - public static GraphServiceClient GetGraphServiceClient( - HttpClient httpClient = null) - { - if (httpClient == null) - { - return ActiveAuth.GraphClient; - } - return new GraphServiceClient( - httpClient, - null, - $"https://graph.microsoft{GetAuthorityDomain(ActiveTenant.AzureEnvironment)}/v1.0"); - } - - /// - /// A method to return a valid Beta endpoint GraphServiceClient for - /// the given HttpClient. - /// - /// The HttpClient to use during construction - /// of the GraphServiceClient. - /// A valid Beta endpoint GraphServiceClient for the given - /// HttpClient. - public static GraphServiceClient GetGraphBetaServiceClient( - HttpClient httpClient = null) - { - if (httpClient == null) - { - return ActiveAuth.GraphBetaClient; - } - return new GraphServiceClient( - httpClient, - null, - $"https://graph.microsoft{GetAuthorityDomain(ActiveTenant.AzureEnvironment)}/beta"); - } - - /// - /// Get a CSOM ClientContent for the given URL. - /// - /// The URL for which to get the Context. - /// The token to use for the bearer. - /// Should errors be suppressed? Default - /// is false. - /// A valid ClientContext for the site or null if an exception - /// occurred. - public static ClientContext GetClientContext( - string url, - string accessToken, - bool suppressErrors = false) - { - try - { - var clientContext = new ClientContext(url); - clientContext.ExecutingWebRequest += (sender, args) => - { - args.WebRequestExecutor.RequestHeaders["Authorization"] = - "Bearer " + accessToken; - }; - return clientContext; - } - catch (Exception ex) - { - if (!suppressErrors) - { - Err($"ERROR getting context for [{url}].\n\r" + - $"Message: [{ex.Message}]\n\r" + - $"Stack Trace: [{ex.StackTrace}]"); - } - return null; - } - } - - /// - /// Method to get a valid AuthenticationResult for the current - /// application, tenant and scopes. - /// - /// The application previously generated. - /// The Tenant/Directory ID of the target - /// tenant. - /// The type of ClientApplication to use. - /// The authentication scopes to target. - /// The AuthenticationResult containing the AccessToken - /// to use for requests. - public static AuthenticationResult GetAuthResult( - object app, - string tenantId, - ClientApplicationType appType = ClientApplicationType.Confidential, - string[] scopes = null) - { - //Inf("AuthMan.GetAuthResult()"); - //If no scopes are specified, default to the current Scopes. - if (scopes == null) - { - if (ActiveAuth == null) - { - scopes = Scopes.Graph; - } - else - { - scopes = ActiveAuth.Scopes; - } - } - else - { - ActiveAuth.Scopes = scopes; - } - //Reset the auth result. - AuthenticationResult authResult = null; - //Configure retries. - int retries = 0; - - //Generate the result. - switch (appType) - { - case ClientApplicationType.Confidential: - var appC = app as IConfidentialClientApplication; - while (retries < 3) - { - try - { - authResult = appC.AcquireTokenForClient(scopes) - .WithTenantId(tenantId) - .ExecuteAsync().GetAwaiter().GetResult(); - break; - } - catch (MsalServiceException msalex) - { - if (!msalex.IsRetryable) - { - throw; - } - retries++; - } - } - break; - case ClientApplicationType.Public: - var appP = app as IPublicClientApplication; - var accounts = appP.GetAccountsAsync() - .GetAwaiter().GetResult(); - while (retries < 3) - { - try - { - authResult = GetPublicAppAuthResult( - ref appP, - ref accounts, - PublicAppAuthResultType.Silent); - break; - if (authResult == null) - { - authResult = GetPublicAppAuthResult( - ref appP, - ref accounts, - PublicAppAuthResultType.Interactive); - break; - if (authResult == null) - { - authResult = GetPublicAppAuthResult( - ref appP, - ref accounts, - PublicAppAuthResultType.Prompt); - break; - } - } - } - catch (MsalClientException msalex) - { - if (!msalex.IsRetryable) - { - throw; - } - retries++; - } - } - break; - } - return authResult; - } - } -} diff --git a/Classes/Extensions.Identity.Cert.cs b/Classes/Extensions.Identity.Cert.cs deleted file mode 100644 index 66a4708..0000000 --- a/Classes/Extensions.Identity.Cert.cs +++ /dev/null @@ -1,91 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; -using System.Security.Cryptography.X509Certificates; - -namespace Extensions.Identity -{ - /// - /// Class for working with certificates. - /// - [Serializable] - public static partial class Cert - { - /// - /// Get a certificate from the CurrentUser store based on thumbprint. - /// If the certificate is not found, the LocalMachine store is searched - /// for the matching certificate. - /// - /// The thumbprint of the target - /// certificate. - /// The certificate if found, else null. - public static X509Certificate2 GetCertByThumbPrint(string thumbPrint) - { - //Check if the cert is in the CurrentUser store. - var cert = GetCertByThumbPrint(thumbPrint, - StoreName.My, - StoreLocation.CurrentUser); - //If it is not in the CurrentUser store, attempt to locate the - //cert in the LocalMachine store. - return cert == null ? - GetCertByThumbPrint(thumbPrint, - StoreName.My, - StoreLocation.LocalMachine) : cert; - } - - /// - /// Get a certificate from the specified StoreName and StoreLocation. - /// - /// The thumbprint of the target - /// certificate. - /// The name of the certificate store to - /// search e.g. My. - /// The location of the certificate - /// store to search e.g. CurrentUser, LocalMachine etc. - /// The certificate if found, else null. - public static X509Certificate2 GetCertByThumbPrint( - string thumbPrint, - StoreName storeName, - StoreLocation storeLocation) - { - //Define the store with the specified StoreName and StoreLocation. - X509Store store = new X509Store(storeName, storeLocation); - X509Certificate2 result = null; - try - { - //Attempt to open the store in read mode. - store.Open(OpenFlags.ReadOnly); - //Get the collection of certificates in the store. - X509Certificate2Collection certCollection = store.Certificates; - //Filter the collection of certificates by matching thumbprints. - //Only return valid certificates. Should only return 1 cert. - certCollection = certCollection.Find(X509FindType.FindByThumbprint, - thumbPrint, - false); //For self signed cert. - //If a valid cert was found, return it, otherwise return null. - result = certCollection.Count == 0 ? null : certCollection[0]; - } - catch (Exception ex) - { - //Err(ex.ToString()); - } - finally - { - //Close the store before returning. - store.Close(); - } - //Throw exception if we fail to load the cert. - if ((storeLocation == StoreLocation.LocalMachine) && - (result == null)) - { - throw new Exception($"Unable to load certificate [{thumbPrint}]"); - } - return result; - } - } -} diff --git a/Classes/Extensions.Identity.Scopes.cs b/Classes/Extensions.Identity.Scopes.cs deleted file mode 100644 index 81ab310..0000000 --- a/Classes/Extensions.Identity.Scopes.cs +++ /dev/null @@ -1,192 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; - -namespace Extensions.Identity -{ - /// - /// The types of scopes Identity could use. - /// - [Serializable] - public enum ScopeType - { - /// - /// Exchange scope. - /// - Exchange, - /// - /// Graph scope. - /// - Graph, - /// - /// Management scope. - /// - Management, - /// - /// PowerBI scope. - /// - PowerBI, - /// - /// SharePoint scope. - /// - SharePoint, - /// - /// SharePoint Admin scope. - /// - SharePointAdmin - } - - /// - /// A class containing the various scope string arrays. - /// - [Serializable] - public static partial class Scopes - { - /// - /// Universal definition for the offline access scope string. - /// - internal static string Offline = "offline_access"; - - /// - /// Default access scope set to Graph. - /// - public static string[] Default = Graph; - - /// - /// Access scope for Exchange. - /// - public static string[] Exchange = new string[] - { - "https://outlook.office365.us/.default" - }; - - /// - /// Access scope for Graph. - /// - public static string[] Graph = new string[] - { - "https://graph.microsoft.us/.default", - Offline - }; - - /// - /// Access scope for M365 Management. - /// - public static string[] Management = new string[] - { - "https://manage.office365.us/.default", - Offline - }; - - /// - /// Access scope for PowerBI. - /// - public static string[] PowerBI = new string[] - { - "https://high.analysis.usgovcloudapi.net/powerbi/api/.default", - Offline - }; - //"https://analysis.windows.net/powerbi/api/.default" - - /// - /// Access scope for SharePoint. - /// - public static string[] SharePoint = new string[] - { - $"https://{AuthMan.GetTenantString().TrimEnd('/')}.sharepoint.us/.default", - Offline - }; - - /// - /// Access scope for SharePoint Admin portal. - /// - public static string[] SharePointAdmin = new string[] - { - $"https://{Extensions.CoreBase.TenantString}-admin.sharepoint.us/.default", - Offline - }; - - /// - /// Return the scopes array based on the type of scope being - /// requested. - /// - /// The type of scope. - /// A string array of scopes. - public static string[] GetScopes(ScopeType scopeType) - { - switch (scopeType) - { - case ScopeType.Graph: - return Scopes.Graph; - break; - //For performance reasons SharePoint is listed second as its - //the second most common scope type in use after Graph. This - //eliminates needless checks on common queries. - case ScopeType.SharePoint: - return Scopes.SharePoint; - break; - case ScopeType.Management: - return Scopes.Management; - break; - case ScopeType.PowerBI: - return Scopes.PowerBI; - break; - case ScopeType.Exchange: - return Scopes.Exchange; - break; - case ScopeType.SharePointAdmin: - return Scopes.SharePointAdmin; - break; - default: - return Scopes.Graph; - break; - } - } - - /// - /// Method to convert a string array of scopes back to a ScopeType object. - /// - /// The string array of scopes. - /// The associated ScopeType object. - /// Thrown if conversion fails. - public static ScopeType GetScopeType(string[] scopes) - { - switch (scopes[0].ToLower()) - { - case "https://graph.microsoft.us/.default": - return ScopeType.Graph; - break; - case "https://outlook.office365.us/.default": - return ScopeType.Exchange; - break; - case "https://analysis.windows.net/powerbi/api/.default": - return ScopeType.PowerBI; - break; - default: - if (scopes[0].ToLower() == - $"https://{AuthMan.GetTenantString().ToLower().TrimEnd('/')}.sharepoint.us/.default") - { - return ScopeType.SharePoint; - } - if (scopes[0].ToLower() == - $"https://{AuthMan.GetTenantString().ToLower().TrimEnd('/')}-admin.sharepoint.us/.default") - { - return ScopeType.SharePointAdmin; - } - break; - } - string msg = ""; - for (int C = 0; C < scopes.Length; C++) - { - msg += scopes[C]; - } - msg = $"ERROR! Scopes [{msg} is invalid.]"; - throw new Exception(msg); - } - } -} diff --git a/Classes/Extensions.InstanceExceptionInfo.cs b/Classes/Extensions.InstanceExceptionInfo.cs new file mode 100644 index 0000000..589ec06 --- /dev/null +++ b/Classes/Extensions.InstanceExceptionInfo.cs @@ -0,0 +1,94 @@ +/// +/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk +/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the +/// author and contributors. Please see: +/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE +/// + +using System; +using System.Collections.Generic; + +namespace Extensions +{ + /// + /// A class for exception capture and return during bulk operations. + /// + [Serializable] + public partial class InstanceExceptionInfo + { + /// + /// The string key of this instance. + /// + public string Key { get; set; } + + /// + /// A list of Exceptions to be captured. + /// + public List Exceptions { get; set; } + + /// + /// A dictionary of any string metadata to be captured. + /// + public Dictionary MetaData { get; set; } + + /// + /// A dictionary of any binary data to be captured. + /// + public Dictionary BinaryData { get; set; } + + /// + /// A boolean value indicating if the exception occurred while the + /// app was configured for multi-threading. + /// + public bool MultiThreaded { get; set; } + + /// + /// Empty constructor. + /// + public InstanceExceptionInfo() { } + + /// + /// Inline constructor. + /// + /// The object key. + /// A list of Exception values to capture. + /// A dictionary of metadata to capture. + /// A dictionary of any binary data to capture. + /// Boolean switch indicating if the operation was + /// multi-threaded or single-threaded at the time. + public InstanceExceptionInfo(string key, + List exceptions, + Dictionary metaData, + Dictionary binaryData, + bool multiThreaded) + { + Key = key; + Exceptions = exceptions; + MetaData = metaData; + BinaryData = binaryData; + MultiThreaded = multiThreaded; + } + + /// + /// Inline constructor. + /// + /// The object key. + /// An Exception value to capture. + /// A string of metadata to capture. + /// An object of any binary data to capture. + /// Boolean switch indicating if the operation was + /// multi-threaded or single-threaded at the time. + public InstanceExceptionInfo(string key, + Exception exception, + string metaData, + object binaryData, + bool multiThreaded) + { + Key = key; + Exceptions.Add(exception); + MetaData.Add(key, metaData); + BinaryData.Add(key, binaryData); + MultiThreaded = multiThreaded; + } + } +} diff --git a/Classes/Extensions.Telemetry.cs b/Classes/Extensions.Telemetry.cs index 6856a88..576456e 100644 --- a/Classes/Extensions.Telemetry.cs +++ b/Classes/Extensions.Telemetry.cs @@ -21,15 +21,15 @@ public class TelemetryInstance /// /// The stopwatch of the instance. /// - public Stopwatch timer { get; set; } = new Stopwatch(); + public Stopwatch Timer { get; set; } = new Stopwatch(); /// /// The number of threads used by the instance. /// - public List threads { get; set; } = new List(); + public List Threads { get; set; } = new List(); /// /// The counter of the instance. /// - public int counter { get; set; } = 0; + public int Counter { get; set; } = 0; } /// @@ -41,20 +41,20 @@ public static class Telemetry /// /// The stack of telemetry measuring instances. /// - public static Dictionary timers { get; private set; } = + public static Dictionary Timers { get; private set; } = new Dictionary(); /// /// The name of the active telemetry instance. /// - public static string activeTimer { get; set; } = "default"; + public static string ActiveTimer { get; set; } = "default"; /// /// The delegate method for stopping telemetry on the instance. /// - public static Action stopTelemetryMethod { get; set; } + public static Action StopTelemetryMethod { get; set; } /// /// The delegate method for starting telemetry on the instance. /// - public static Action startTelemetryMethod { get; set; } + public static Action StartTelemetryMethod { get; set; } /// /// Method to add a new instance to the stack. @@ -70,9 +70,9 @@ public static void AddTimer( try { //If timer doesn't already exist, add it. - if (!timers.ContainsKey(timerName)) + if (!Timers.ContainsKey(timerName)) { - timers.Add(timerName, new TelemetryInstance()); + Timers.Add(timerName, new TelemetryInstance()); } } catch (Exception ex) @@ -87,7 +87,7 @@ public static void AddTimer( //Set the activeTimer to the new timer if requested. if (setAsActive) { - activeTimer = timerName; + ActiveTimer = timerName; } //Start the new timer if requested. if (startImmediately) @@ -101,7 +101,7 @@ public static void AddTimer( /// public static void ClearEverything() { - timers.Clear(); + Timers.Clear(); } /// @@ -111,7 +111,7 @@ public static void ClearEverything() public static int Count() { Initialize(); - return timers[activeTimer].counter; + return Timers[ActiveTimer].Counter; } /// @@ -122,7 +122,7 @@ public static int Count() public static int Count(string timerName) { Initialize(); - return timers[timerName].counter; + return Timers[timerName].Counter; } /// @@ -131,7 +131,7 @@ public static int Count(string timerName) /// The activeTimer.threads.Count value. public static int ThreadCount() { - return ThreadCount(activeTimer); + return ThreadCount(ActiveTimer); } /// @@ -142,7 +142,7 @@ public static int ThreadCount() public static int ThreadCount(string timerName) { Initialize(); - return timers[timerName].threads.Count; + return Timers[timerName].Threads.Count; } /// @@ -153,7 +153,7 @@ public static int ThreadCount(string timerName) /// the current CPU used. public static string TelemetryStatus() { - return TelemetryStatus(activeTimer); + return TelemetryStatus(ActiveTimer); } /// @@ -173,9 +173,13 @@ public static string TelemetryStatus(string timerName) ThreadCount(timerName) + $"] thread(s), [" + RAM() + - $"] RAM, [" + + $"] RAM" + +#if NETFRAMEWORK + $", [" + CPU() + - $"] CPU."; + $"] CPU" + +#endif + $"."; } /// @@ -184,7 +188,7 @@ public static string TelemetryStatus(string timerName) /// The activeTimer.timer.Elapsed value. public static TimeSpan Elapsed() { - return Elapsed(activeTimer); + return Elapsed(ActiveTimer); } /// @@ -195,7 +199,7 @@ public static TimeSpan Elapsed() public static TimeSpan Elapsed(string timerName) { Initialize(timerName); - return timers[timerName].timer.Elapsed; + return Timers[timerName].Timer.Elapsed; } /// @@ -205,7 +209,7 @@ public static TimeSpan Elapsed(string timerName) /// The activeTimer.timer.ElapsedMilliseconds value. public static long ElapsedMilliseconds() { - return ElapsedMilliseconds(activeTimer); + return ElapsedMilliseconds(ActiveTimer); } /// @@ -218,7 +222,7 @@ public static long ElapsedMilliseconds() public static long ElapsedMilliseconds(string timerName) { Initialize(timerName); - return timers[timerName].timer.ElapsedMilliseconds; + return Timers[timerName].Timer.ElapsedMilliseconds; } /// @@ -227,7 +231,7 @@ public static long ElapsedMilliseconds(string timerName) /// The activeTimer.timer.ElapsedTicks value. public static long ElapsedTicks() { - return ElapsedTicks(activeTimer); + return ElapsedTicks(ActiveTimer); } /// @@ -238,7 +242,7 @@ public static long ElapsedTicks() public static long ElapsedTicks(string timerName) { Initialize(timerName); - return timers[timerName].timer.ElapsedTicks; + return Timers[timerName].Timer.ElapsedTicks; } /// @@ -247,7 +251,7 @@ public static long ElapsedTicks(string timerName) /// The name of the timer to use. public static void Initialize(string timerName = "default") { - if (!timers.ContainsKey(timerName)) + if (!Timers.ContainsKey(timerName)) { AddTimer(timerName); } @@ -259,7 +263,7 @@ public static void Initialize(string timerName = "default") /// The value of activeTimer.timer.IsRunning public static bool IsRunning() { - return IsRunning(activeTimer); + return IsRunning(ActiveTimer); } /// @@ -270,7 +274,7 @@ public static bool IsRunning() public static bool IsRunning(string timerName) { Initialize(timerName); - return timers[timerName].timer.IsRunning; + return Timers[timerName].Timer.IsRunning; } /// @@ -280,7 +284,7 @@ public static void Load() { try { - timers = (Dictionary) + Timers = (Dictionary) State.LoadStateList( "Telemetry", typeof(Dictionary), @@ -290,7 +294,7 @@ public static void Load() catch (Exception ex) { //If timers fail to load, initialize a new set. - timers = new Dictionary(); + Timers = new Dictionary(); } } @@ -302,7 +306,7 @@ public static void Load(Dictionary savedTimers) { if (savedTimers != null) { - timers = savedTimers; + Timers = savedTimers; } } @@ -311,7 +315,7 @@ public static void Load(Dictionary savedTimers) /// public static void Reset() { - Reset(activeTimer); + Reset(ActiveTimer); } /// @@ -321,7 +325,7 @@ public static void Reset() public static void Reset(string timerName) { Initialize(timerName); - timers[timerName].timer.Reset(); + Timers[timerName].Timer.Reset(); } /// @@ -329,7 +333,7 @@ public static void Reset(string timerName) /// public static void Restart() { - Restart(activeTimer); + Restart(ActiveTimer); } /// @@ -339,7 +343,7 @@ public static void Restart() public static void Restart(string timerName) { Initialize(timerName); - timers[timerName].timer.Restart(); + Timers[timerName].Timer.Restart(); } /// @@ -348,7 +352,7 @@ public static void Restart(string timerName) public static void Save() { StopAllTimers(); - State.SaveStateList("Telemetry", timers); + State.SaveStateList("Telemetry", Timers); } /// @@ -365,7 +369,7 @@ public static void Start() /// Not used. public static void Start(bool active = true) { - Start(activeTimer); + Start(ActiveTimer); } /// @@ -375,7 +379,7 @@ public static void Start(bool active = true) public static void Start(string timerName) { Initialize(timerName); - timers[timerName].timer.Start(); + Timers[timerName].Timer.Start(); } /// @@ -392,7 +396,7 @@ public static void Stop() /// Not used. public static void Stop(bool active = true) { - Stop(activeTimer); + Stop(ActiveTimer); } /// @@ -402,7 +406,7 @@ public static void Stop(bool active = true) public static void Stop(string timerName) { Initialize(timerName); - timers[timerName].timer.Stop(); + Timers[timerName].Timer.Stop(); } /// @@ -410,11 +414,11 @@ public static void Stop(string timerName) /// public static void StopAllTimers() { - foreach (var timer in timers.Values) + foreach (var timer in Timers.Values) { if (timer != null) { - timer.timer.Stop(); + timer.Timer.Stop(); } } } @@ -425,7 +429,7 @@ public static void StopAllTimers() /// public static void StopTelemetry(object parms) { - stopTelemetryMethod(parms); + StopTelemetryMethod(parms); } /// @@ -437,6 +441,7 @@ public static string RAM() return $"{(Process.GetCurrentProcess().PrivateMemorySize64 / 1024 / 1024)} MB"; } +#if NETFRAMEWORK /// /// Method to calculate the current CPU consumption. /// @@ -457,5 +462,6 @@ public static string CPU() return ""; } } +#endif } } diff --git a/Classes/Extensions.Tenant.OpenId.cs b/Classes/Extensions.Tenant.OpenId.cs deleted file mode 100644 index c0015b2..0000000 --- a/Classes/Extensions.Tenant.OpenId.cs +++ /dev/null @@ -1,41 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; -using System.Collections.Generic; - -namespace Extensions.Tenant -{ - [Serializable] - public partial class OpenId - { - public string token_endpoint { get; set; } - public List token_endpoint_auth_methods_supported { get; set; } - public string jwks_uri { get; set; } - public List response_modes_supported { get; set; } - public List subject_types_supported { get; set; } - public List id_token_signing_alg_values_supported { get; set; } - public List response_types_supported { get; set; } - public List scopes_supported { get; set; } - public string issuer { get; set; } - public bool request_uri_parameter_supported { get; set; } - public string userinfo_endpoint { get; set; } - public string authorization_endpoint { get; set; } - public string device_authorization_endpoint { get; set; } - public bool http_logout_supported { get; set; } - public bool frontchannel_logout_supported { get; set; } - public string end_session_endpoint { get; set; } - public List claims_supported { get; set; } - public string kerberos_endpoint { get; set; } - public string tenant_region_scope { get; set; } - public string tenant_region_sub_scope { get; set; } - public string cloud_instance_name { get; set; } - public string cloud_graph_host_name { get; set; } - public string msgraph_host { get; set; } - public string rbac_url { get; set; } - } -} diff --git a/Classes/Extensions.TenantConfig.cs b/Classes/Extensions.TenantConfig.cs deleted file mode 100644 index 0f58c28..0000000 --- a/Classes/Extensions.TenantConfig.cs +++ /dev/null @@ -1,216 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; -using System.Collections.Generic; -using static Extensions.Core; - -namespace Extensions -{ - /// - /// Class that contains tenant configuration settings. - /// - [Serializable] - public partial class TenantConfig - { - /// - /// The name of the tenant e.g. "contoso.sharepoint.us" would - /// be "contoso". Default is "Contoso". - /// - public string TenantString { get; set; } = "Contoso"; - - /// - /// Dictionary containing settings for the given tenant. - /// - public Dictionary Settings { get; set; } - - /// - /// Dictionary containing the AIP labels for a given tenant. - /// - public Dictionary Labels { get; set; } - - /// - /// String containing the URL for the given tenant. - /// - public string TenantUrl { get; private set; } - - /// - /// URI for the given tenant. - /// - public Uri TenantUri { get; private set; } - - /// - /// String containing the Authority for the given tenant. - /// - public string Authority { get; private set; } - - /// - /// String containing the URL of the endpoint for the Graph User API. - /// - public string GraphUserEndPointUrl { get; private set; } - - /// - /// The Azure environment e.g. Commercial or USGovGCCHigh etc. Default - /// value is "USGovGCCHigh". - /// - public Core.AzureEnvironment AzureEnvironment { get; set; } - = Core.AzureEnvironment.USGovGCCHigh; - - /// - /// The Tenant or Directory ID to use for this instance. Default is - /// all zeros. - /// - public string TenantDirectoryId { get; set; } - = "00000000-0000-0000-0000-000000000000"; - - /// - /// The Application or Client ID to use for this instance. Default is - /// all zeros. - /// - public string ApplicationClientId { get; set; } - = "00000000-0000-0000-0000-000000000000"; - - /// - /// The certificate store location to use where the certificate - /// associated with the instance's CertThumbprint is installed. - /// Default value is "CurrentUser" with "LocalMachine" as the - /// other alternative. - /// - public string CertStoreLocation { get; set; } = "CurrentUser"; - - /// - /// The thumbprint of the certificate associated with the - /// ApplicationClientId of this instance. Default is a blank string. - /// - public string CertThumbprint { get; set; } = ""; - - /// - /// Switch to enable or disable debuging for this instance. Default - /// is true. - /// - public bool DebugEnabled { get; set; } = true; - - /// - /// Switch to enable or disable multi-threading for this instance. - /// Default is true. - /// - public bool MultiThreaded { get; set; } = true; - - /// - /// The base URL of the site that Extensions.Logit should use for debug - /// logging. Default is "Logit". - /// - public string LogitSiteBaseUrl { get; set; } = "Logit"; - - /// - /// The ID of the site that Extensions.Logit should use for debug - /// logging. Default is all zeros. - /// - public string LogitSiteId { get; set; } - = "00000000-0000-0000-0000-000000000000"; - - /// - /// The ID of the list that Extensions.Logit should use for debug - /// logging. Default is all zeros. - /// - public string LogitDefaultListGuid { get; set; } - = "00000000-0000-0000-0000-000000000000"; - - /// - /// Empty constructor. - /// - public TenantConfig() - { - Init(null); - } - - /// - /// Constructor for a given tenant. - /// - /// The name of the tenant e.g. for - /// contoso.sharepoint.us it would be 'contoso'. - public TenantConfig(string tenantString) - { - Init(tenantString); - } - - /// - /// Parameterized constructor for the class. - /// - /// The name of the tenant e.g. - /// "contoso.sharepoint.us" would be "contoso". Default is - /// "Contoso". - /// The Azure environment e.g. - /// Commercial or USGovGCCHigh etc. Default value is - /// "USGovGCCHigh". - /// The Tenant or Directory ID to use - /// for this instance. - /// The Application or Client ID to - /// use for this instance. - /// The certificate store location to - /// use where the certificate associated with the instance's - /// CertThumbprint is installed. Default value is "CurrentUser" with - /// "LocalMachine" as the other alternative. - /// The thumbprint of the certificate - /// associated with the ApplicationClientId of this instance. - /// Switch to enable or disable debuging - /// for this instance. - /// The ID of the site that - /// Extensions.Logit should use for debug logging. - /// The ID of the site that Extensions.Logit - /// should use for debug logging. - /// The ID of the list that - /// Extensions.Logit should use for debug logging. - public TenantConfig(string tenantString, - Core.AzureEnvironment azureEnvironment, - string tenantDirectoryId, - string applicationClientId, - string certStoreLocation, - string certThumbprint, - bool debugEnabled, - bool multiThreaded, - string logitSiteId, - string logitDefaultListGuid) - { - TenantString = tenantString; - AzureEnvironment = azureEnvironment; - Init(tenantString); - TenantDirectoryId = tenantDirectoryId; - ApplicationClientId = applicationClientId; - CertStoreLocation = certStoreLocation; - CertThumbprint = certThumbprint; - DebugEnabled = debugEnabled; - MultiThreaded = multiThreaded; - LogitSiteId = logitSiteId; - LogitDefaultListGuid = logitDefaultListGuid; - foreach (var prop in this.GetType().GetProperties()) - { - Inf($"[{prop.Name}] = [{prop.GetValue(this)}]"); - } - } - - /// - /// Method to initialize base values. - /// - /// The name of the tenant e.g. for - /// contoso.sharepoint.us it would be 'contoso'. - public void Init(string tenantString) - { - if (tenantString != null) - { - string authority = Identity.AuthMan.GetAuthorityDomain(AzureEnvironment); - TenantString = tenantString.Trim(); - TenantUrl = TenantString + ".sharepoint" + authority; - TenantUri = new Uri("https://" + TenantUrl); - Authority = - $"https://login.microsoftonline{authority}/{TenantUrl}/"; - GraphUserEndPointUrl = - $"https://graph.microsoft{authority}/v1.0/users"; - } - } - } -} diff --git a/Classes/Extensions.UniversalConfig.cs b/Classes/Extensions.UniversalConfig.cs deleted file mode 100644 index ed64bd2..0000000 --- a/Classes/Extensions.UniversalConfig.cs +++ /dev/null @@ -1,53 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; -using System.IO; -using System.Text.Json; -using static Extensions.Core; //NuGet Extensions.cs - -namespace Extensions -{ - [Serializable] - public static partial class UniversalConfig - { - public static void InitializeTenant(string tenantString) - { - try - { - string target = - $"{GetRunFolder()}\\UniversalConfig.{tenantString}.json"; - Inf($"Initializing tenant [{tenantString}]"); - if (!Tenants.ContainsKey(tenantString)) - { - Inf($"Loading config from [{target}]"); - using (StreamReader sr = new StreamReader(target)) - { - Tenants.Add( - tenantString, - JsonSerializer.Deserialize( - sr.ReadToEnd())); - ActiveTenant = Tenants[tenantString]; - Inf($"Added tenant [{tenantString}] to the pool now " + - $"containing [{Tenants.Count}] configs."); - } - } - else - { - Inf($"Tenant [{tenantString}] is already in the pool. " + - $"Using pool instance."); - ActiveTenant = Tenants[tenantString]; - } - Inf($"Done initializing tenant [{tenantString}]"); - } - catch (Exception ex) - { - throw; - } - } - } -} diff --git a/Classes/Microsoft.Graph.ListItem.cs b/Classes/Microsoft.Graph.ListItem.cs deleted file mode 100644 index 41ccb06..0000000 --- a/Classes/Microsoft.Graph.ListItem.cs +++ /dev/null @@ -1,76 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using Microsoft.Graph.Models; -using System; -using static Extensions.Core; - -namespace Extensions -{ - /// - /// An extension class to simplify getting data from ListItems. - /// - [Serializable] - public static partial class ListItemExtensions - { - /// - /// Method to get a boolean field from ListItem. - /// - /// The item in question. - /// The field name to get. - /// - public static bool GetJsonBool( - this ListItem item, - string fieldName) - { - var result = false; - - try - { - result = Convert.ToBoolean( - item.Fields.AdditionalData[fieldName]); - } - catch (Exception ex) - { - Err(ex.ToString()); - result = false; - } - finally - { - } - return result; - } - - /// - /// Method to get a string field from ListItem. - /// - /// The item in question. - /// The field name to get. - /// - public static string GetJsonString( - this ListItem item, - string fieldName) - { - var result = ""; - - try - { - result = Convert.ToString( - item.Fields.AdditionalData[fieldName]); - } - catch (Exception ex) - { - Err(ex.ToString()); - result = ""; - } - finally - { - } - return result; - } - } -} diff --git a/Classes/System.Collections.Generic.List.cs b/Classes/System.Collections.Generic.List.cs index 225a2e4..cc67e2a 100644 --- a/Classes/System.Collections.Generic.List.cs +++ b/Classes/System.Collections.Generic.List.cs @@ -8,7 +8,8 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Threading.Tasks; +using System.Threading.Tasks; +using static Extensions.Constants; namespace Extensions { diff --git a/Classes/System.Guid.cs b/Classes/System.Guid.cs index b37961b..0762a4e 100644 --- a/Classes/System.Guid.cs +++ b/Classes/System.Guid.cs @@ -30,8 +30,8 @@ public static System.Guid NewCustomGuid(string StartWith = "") "GUID values can only contain hexadecimal characters."); } System.Guid result = System.Guid.NewGuid(); - return new System.Guid((StartWith.ToLower() + - result.ToString().ToLower().Substring(StartWith.Length))); + return new System.Guid(StartWith.ToLower() + + result.ToString().ToLower().Substring(StartWith.Length)); } } } diff --git a/Classes/System.Logit.cs b/Classes/System.Logit.cs deleted file mode 100644 index 3e3d522..0000000 --- a/Classes/System.Logit.cs +++ /dev/null @@ -1,1053 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System.Collections.Generic; -using System.IO; -using System.Threading; -using Extensions; -using Microsoft.Extensions.Logging; -using Microsoft.Graph; - -namespace System -{ - /// - /// Logging class with options for targeting screen, file, Event Log, - /// SharePoint list, ILogger and database. - /// - [Serializable] - public static partial class Logit - { - /// - /// Class containing the instance of the Logit engine. - /// - [Serializable] - public partial class Instance - { - #region Globals - /// - /// The delegate method to call in order to determine if debug - /// logging should take place. - /// - public Func IsDebugMethod { get; private set; } - /// - /// The file to which logging will be done if the logToFile - /// switch is set to true. - /// - public string LogFile { get; private set; } = - GetExecutingAssemblyFileName() + TimeStamp() + ".log"; - /// - /// The default message type if none is specified. - /// - public MessageType DefaultLogMessageType { get; private set; } - = MessageType.Information; - /// - /// The ILogger instance to use for logging. - /// - public ILogger ILogger { get; private set; } = null; - /// - /// A Graph client for logging to SharePoint. - /// - public GraphServiceClient GraphClient { get; private set; } = null; - /// - /// The base URL of the SharePoint site housing the target list. - /// Specify only the base URL of the site e.g. for the site - /// "contoso.sharepoint.us/sites/LogData" the value supplied would - /// be just "LogData". - /// - public string LogSiteUrl { get; private set; } = null; - /// - /// The list name for the target list when logging to SharePoint. - /// - public string LogListName { get; private set; } = null; - #endregion Globals - - #region Switches - /// - /// When set to true, will output logging content to the console. - /// Default = true; - /// - public bool LogToConsole { get; set; } = true; - /// - /// When set to true, will output logging content to the log file. - /// Default = false; - /// - public bool LogToFile { get; set; } = false; - /// - /// When set to true, will output logging content to the Event Log. - /// Default = false; - /// - public bool LogToEventLog { get; set; } = false; - /// - /// When set to true, will output logging content to a provided - /// ILogger client. - /// - public bool LogToILogger { get; set; } = false; - /// - /// When set to true, will output logging content to a SharePoint list. - /// Default = false; - /// - public bool LogToSPList { get; set; } = false; - /// - /// When set to true, will output logging content to a database. - /// Default = false; - /// - public bool LogToDB { get; set; } = false; - /// - /// Define if timestamps should be prepended to messages. - /// Default = true; - /// - public bool IncludeTimeStamp { get; set; } = true; - /// - /// Define if console output should be in a static location thus - /// constantly overwriting the previous output. This is useful in - /// status updates like % complete etc. - /// Default = false; - /// - public bool StaticConsoleLocation { get; set; } = false; - #endregion Switches - - #region Constructors - /// - /// Default constructor that logs only to the console. - /// - /// A delegate method called to determine - /// if debug logging should happen. - /// The default message type to - /// use in logging if type isn't specified. - /// Bool determining if logging is done to - /// the console. - /// Bool determining if logging is done to - /// a file. - /// Bool determining if logging is done to - /// the Event Log. - /// Bool determining if logging is done to - /// the provided ILogger. - /// The ILogger instance to use for logging. - public Instance( - Func isDebugMethod, - MessageType defaultLogMessageType = MessageType.Information, - bool logToConsole = true, - bool logToFile = false, - bool logToEventLog = false, - bool logToILogger = false, - ILogger iLogger = null) - { - //Capture the delegate method. - IsDebugMethod = isDebugMethod; - //Configure if logging should take place to the console. - LogToConsole = logToConsole; - //Configure if logging should take place to file. - LogToFile = logToFile; - //Configure the default log file for this session. - LogFile = GetExecutingAssemblyFileName() + TimeStamp() + ".log"; - //Configure if logging should take place to the Event Log. - LogToEventLog = logToEventLog; - //Configure the default log message type for this session. - DefaultLogMessageType = defaultLogMessageType; - //Configure if logging should take place to ILogger. - LogToILogger = logToILogger; - //Configure the default ILogger instance for this session. - ILogger = iLogger; - //Update default instance to this. - ActiveLogitInstance = this; - } - - /// - /// Default constructor that logs only to the console. - /// - /// A delegate method called to determine - /// if debug logging should happen. - /// The GraphServiceClient to use for - /// writing SharePoint list entries. - /// The base URL of the SharePoint site - /// that houses the target list. - /// The GUID of the target SharePoint list - /// to which logging will be done. - /// The default message type to - /// use in logging if type isn't specified. - /// Bool determining if logging is done to - /// the console. - /// Bool determining if logging is done to - /// a file. - /// Bool determining if logging is done to - /// the Event Log. - /// Bool determining if logging is done to - /// a SharePoint list. - /// Bool determining if logging is done to - /// a database. - /// Bool determining if logging is done to - /// the provided ILogger. - /// The ILogger instance to use for logging. - public Instance( - Func isDebugMethod, - GraphServiceClient graphClient, - string spSiteUrl, - string spListName, - MessageType defaultLogMessageType = - MessageType.Information, - bool logToConsole = true, - bool logToFile = false, - bool logToEventLog = false, - bool logToSPList = false, - bool logToDatabase = false, - bool logToILogger = false, - ILogger iLogger = null) - { - //Capture the delegate method. - IsDebugMethod = isDebugMethod; - //Configure if logging should take place to the console. - LogToConsole = logToConsole; - //Configure if logging should take place to file. - LogToFile = logToFile; - //Configure the default log file for this session. - LogFile = GetExecutingAssemblyFileName() + TimeStamp() + ".log"; - //Configure if logging should take place to the Event Log. - LogToEventLog = logToEventLog; - //Configure if logging should take place to ILogger. - LogToILogger = logToILogger; - //Configure the default ILogger instance for this session. - ILogger = iLogger; - //Configure if logging should take place to a SharePoint list. - LogToSPList = logToSPList; - //Configure the default GraphServiceClient to use for logging. - GraphClient = graphClient; - //Configure the default SharePoint site for this session. - LogSiteUrl = spSiteUrl; - //Configure the default SharePoint list for this session. - LogListName = spListName; - //Configure if logging should take place to a database. - LogToDB = logToDatabase; - //Configure the default log message type for this session. - DefaultLogMessageType = defaultLogMessageType; - //Update default instance to this. - ActiveLogitInstance = this; - } - #endregion Constructors - - #region Worker Methods - /// - /// Called to write "Information" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - public void Inf( - string message, - int eventId = 0) - { - System.Logit.Inf(message, eventId, this); - } - - /// - /// Called to write "Warning" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - public void Wrn( - string message, - int eventId = 0) - { - System.Logit.Wrn(message, eventId, this); - } - - /// - /// Called to write "Error" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - public void Err( - string message, - int eventId = 0) - { - System.Logit.Err(message, eventId, this); - } - - /// - /// Called to write "Verbose" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - public void Vrb( - string message, - int eventId = 0) - { - System.Logit.Vrb(message, eventId, this); - } - #endregion Worker Methods - } - - #region Globals - /// - /// The lock object to prevent file I/O clashes. - /// - private static readonly ReaderWriterLockSlim _lock = new ReaderWriterLockSlim(); - /// - /// Lock object for marshalling static console location output. - /// - private static readonly object _lockStaticConsoleLocation = new object(); - /// - /// Define the type of messages that can be written. - /// - public enum MessageType - { - /// - /// Error message type that writes red output to console. - /// - Error, - /// - /// Warning message type that writes yellow output to console. - /// - Warning, - /// - /// Information message type that writes gray output to console. - /// - Information, - /// - /// Verbose message type that writes cyan output to console. - /// - Verbose - } - /// - /// Define the types of logs that can be written. - /// - public enum LogType - { - /// - /// Write to console. - /// - Console, - /// - /// Write to a logging file. - /// - File, - /// - /// Write to the Event Log. - /// - EventLog, - /// - /// Write to a SharePoint list. - /// - SPList, - /// - /// Write to a given ILogger. - /// - ILogger, - /// - /// Write to database. - /// - Database - } - /// - /// The currently active Logit engine instance that will handle - /// requests. - /// - public static Instance ActiveLogitInstance { get; set; } - = new Instance(IsDebug); - #endregion Globals - - #region Debug Switch - /// - /// Default delegate method to enable logging. - /// - /// Always true when no delegate is provided. - public static bool IsDebug() - { - return true; - } - - /// - /// Intended method for calling delegate debug switch determinors. - /// - /// The delegate method to call. - /// The return value of the delegate method. - public static bool IsDebug(Func func) - { - return func(); - } - #endregion Debug Switch - - #region Utility Methods - /// - /// This method will save the current console foreground color - /// and then write the parameter passed message to the console - /// output in different colors based on the MessageType before - /// restoring the console foreground to the original color it had - /// before the method was called. Colors are red for Error, yellow - /// for Warning, gray for Information and cyan for Verbose. - /// - /// Output to write. - /// The name of the delegate method - /// to call to determine if debug logging should happen. - /// The type of message to write. Default - /// value is MessageType.Information. - private static void WriteConsoleMessage( - string message, - Func isDebugValidationMethod = null, - MessageType messageType = MessageType.Information) - { - //Save the current console foreground color. - var foreground = Console.ForegroundColor; - //Save the current console background color. - var background = Console.BackgroundColor; - try - { - //Check if a debug validation method was specified. - if (isDebugValidationMethod != null) - { - //Check if debug is on. If not, no logging takes place. - if (IsDebug(isDebugValidationMethod)) - { - //Set console output to: - //red for error, - //yellow for warning, - //gray for information, - //cyan for verbose. - switch (messageType) - { - case MessageType.Error: - Console.ForegroundColor = ConsoleColor.Red; - break; - case MessageType.Warning: - Console.ForegroundColor = ConsoleColor.Yellow; - break; - case MessageType.Information: - Console.ForegroundColor = ConsoleColor.Gray; - break; - case MessageType.Verbose: - Console.ForegroundColor = ConsoleColor.Cyan; - break; - } - //Default the background to black. - Console.BackgroundColor = ConsoleColor.Black; - //Write the error. - Console.WriteLine(message); - //Reset the console colors. - Console.ForegroundColor = foreground; - Console.BackgroundColor = background; - } - } - } - catch (Exception ex) - { - //Logging code may NEVER terminate its parent through exceptions. - try - { - //Write the error in red to the console. - Console.ForegroundColor = ConsoleColor.Red; - Console.WriteLine(ex.ToString()); - Console.ForegroundColor = foreground; - Console.BackgroundColor = background; - } - catch - { - //Just reset the console colors. - Console.ForegroundColor = foreground; - Console.BackgroundColor = background; - } - } - } - - /// - /// This method will save the current console foreground color - /// and then write the parameter passed message to the console - /// output in different colors based on the MessageType before - /// restoring the console foreground to the original color it had - /// before the method was called. Colors are red for Error, yellow - /// for Warning, gray for Information and cyan for Verbose. - /// - /// Output to write. - /// The name of the delegate method - /// to call to determine if debug logging should happen. - public static void WriteConsoleError( - string message, - Func isDebugValidationMethod = null) - { - WriteConsoleMessage(message, isDebugValidationMethod, MessageType.Error); - } - - /// - /// Turn the currently running assembly name into a pathed file name - /// string that can be used as a log file name. - /// This method can also be called with a (false) parameter to simply - /// return the fully qualified path to the current executing assembly - /// file name. - /// - /// If true, spaces are replaced - /// with underscores. - /// Unique string representing the fully qualified path to - /// the executing assembly with spaces in the file name portion of - /// the string replaced by underscores e.g. - /// C:\Users\CvD\My Documents\App Name.exe - /// becomes - /// C:\Users\CvD\My_Documents\App_Name.exe - public static string GetExecutingAssemblyFileName( - bool noSpacesinFileName = true) - { - //Logging code may NEVER terminate its parent through exceptions. - try - { - if (noSpacesinFileName) - { - return Path.GetDirectoryName( - Reflection.Assembly.GetEntryAssembly().Location) - .TrimEnd('\\') + "\\" + //Ensure no double trailing slash. - Uri.EscapeDataString( - Reflection.Assembly.GetEntryAssembly() - .ManifestModule.Name.Replace(" ", "_")); - } - else - { - return Path.GetDirectoryName( - Reflection.Assembly.GetEntryAssembly().Location) - .TrimEnd('\\') + "\\" + //Ensure no double trailing slash. - Uri.EscapeDataString( - Reflection.Assembly.GetEntryAssembly() - .ManifestModule.Name); - } - } - catch (Exception ex) - { - //Write exception info to the console in default red. - WriteConsoleError(ex.ToString()); - //Return empty string instead of null as null could cause an - //exception to be thrown by the calling code. - return ""; - } - } - - /// - /// Strip "http://" and "https://" headers from URLs and replace - /// forward slashes (/) with underscored (_) and spaces with - /// dashes (-). - /// This is useful for turning a web URL into a log file name or - /// part thereof. - /// - /// The URL to transform. - /// The transformed URL value. - public static string HtmlStrip(string url) - { - //Logging code may NEVER terminate its parent through exceptions. - try - { - return url.ToLower().Replace("https://", "") - .Replace("http://", "") - .Replace("/", "_") - .Replace(" ", "-"); - } - catch (Exception ex) - { - //Write exception info to the console in default red. - WriteConsoleError(ex.ToString()); - //Return empty string instead of null as null could cause an - //exception to be thrown by the calling code. - return ""; - } - } - - /// - /// This method returns the current Zulu (GMT) date/time value as a - /// string stamp in the format yyyy-MM-dd@hh.mm.ss.ttt - /// e.g. 2017-07-04@09.03.01.567Z - /// - /// String stamp in the format yyyy-MM-dd@hh.mm.ss.ttt - /// e.g. 2017-07-04@09.03.01.567Z - public static string TimeStampZulu() - { - //Logging code may NEVER terminate its parent through exceptions. - try - { - var time = DateTime.UtcNow; - return time.Year.ToString() + "-" + - time.Month.ToString("d2") + "-" + - time.Day.ToString("d2") + "@" + - time.Hour.ToString("d2") + "." + - time.Minute.ToString("d2") + "." + - time.Second.ToString("d2") + "." + - time.Millisecond.ToString("d3"); - } - catch (Exception ex) - { - //Write exception info to the console in default red. - WriteConsoleError(ex.ToString()); - //Return empty string instead of null as null could cause an - //exception to be thrown by the calling code. - return ""; - } - } - - /// - /// This method returns the current local date/time value as a - /// string stamp in the format yyyy-MM-dd@hh.mm.ss.ttt - /// e.g. 2017-07-04@09.03.01.567Z - /// - /// String stamp in the format yyyy-MM-dd@hh.mm.ss.ttt - /// e.g. 2017-07-04@09.03.01.567Z - public static string TimeStamp() - { - //Logging code may NEVER terminate its parent through exceptions. - try - { - var time = DateTime.UtcNow; - return time.Year.ToString() + "-" + - time.Month.ToString("d2") + "-" + - time.Day.ToString("d2") + "@" + - time.Hour.ToString("d2") + "." + - time.Minute.ToString("d2") + "." + - time.Second.ToString("d2") + "." + - time.Millisecond.ToString("d3"); - } - catch (Exception ex) - { - //Write exception info to the console in default red. - WriteConsoleError(ex.ToString()); - //Return empty string instead of null as null could cause an - //exception to be thrown by the calling code. - return ""; - } - } - - /// - /// This method returns the executing computer's Fully Qualified - /// Domain Name. - /// - /// FQDN - public static string GetFQDN() - { - //Logging code may NEVER terminate its parent through exceptions. - try - { - string domainName = - System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().DomainName; - string hostName = System.Net.Dns.GetHostName(); - domainName = "." + domainName; - if (!hostName.EndsWith(domainName)) - { - hostName += domainName; - } - return hostName; - } - catch (Exception ex) - { - //Write exception info to the console in default red. - WriteConsoleError(ex.ToString()); - //Return empty string instead of null as null could cause an - //exception to be thrown by the calling code. - return ""; - } - } - - /// - /// Used to build output text with the date/time stamp - /// depending on the value of the includeTimeStamp switch. - /// - /// The message to stamp if needed. - /// - /// - public static string PrependTimeStamp( - string message, - bool includeTimeStamp = false) - { - //Logging code may NEVER terminate its parent through exceptions. - try - { - if (!includeTimeStamp) - { - //No timestamp needed. Simply return the message. - return message; - } - //The inclusion of a comma (,) between the timestamp and the - //message is intentional. This allows for importing of log - //file output into a spreadsheet via comma separated value - //(CSV) format while splitting timestamps and messages for - //sorting and filtering purposes. - return TimeStamp() + " >>> ," + message; - } - catch (Exception ex) - { - //Write exception info to the console in default red. - WriteConsoleError(ex.ToString()); - return ex.ToString(); - } - } - #endregion Utility Methods - - #region Worker Methods - /// - /// Method to write a log to console. - /// - /// The message to write. - /// the foreground color of the console - /// for the message. - /// The background color of the console - /// for the message. Defaults to black. - public static void Log( - string message, - ConsoleColor foreground, - ConsoleColor background = ConsoleColor.Black) - { - Log(message, - 0, - MessageType.Information, - null, - ActiveLogitInstance.IsDebugMethod, - foreground, - background); - } - - /// - /// Log the message to the log file, provided the logging was - /// initialized. - /// - /// The message being logged. - /// An event ID to use if logging to the - /// system Event Log. - /// The message type to use. - /// The Logit instance to use. If null, - /// the default instance is used. - /// A delegate method provided - /// which when called, will determine if the caller wants debug logging - /// to take place or not. - /// The foreground color to use when - /// logging to console. Defaults to gray. - /// The background color to use when - /// logging to console. Defaults to black. - public static void Log( - string message, - int eventId = 0, - MessageType messageType = MessageType.Information, - Instance instance = null, - Func isDebugValidationMethod = null, - ConsoleColor foreground = ConsoleColor.Gray, - ConsoleColor background = ConsoleColor.Black) - { - //Logging code may NEVER terminate its parent through exceptions. - try - { - //Check if a debug func was specified. - if (isDebugValidationMethod != null) - { - //Check if debug is enabled. - if (!IsDebug(isDebugValidationMethod)) - { - return; - } - } - //Check if a Logit instance was passed. - if (instance == null) - { - instance = ActiveLogitInstance; - } - //Check if we should log to Console. - if (instance.LogToConsole) - { - //Save the current console colors. - var foreColor = Console.ForegroundColor; - var backColor = Console.BackgroundColor; - //Set console output to: - //red for error, - //yellow for warning, - //gray for information, - //cyan for verbose. - switch (messageType) - { - case MessageType.Information: - Console.ForegroundColor = ConsoleColor.Gray; - break; - case MessageType.Warning: - Console.ForegroundColor = ConsoleColor.Yellow; - break; - case MessageType.Error: - Console.ForegroundColor = ConsoleColor.Red; - break; - case MessageType.Verbose: - Console.ForegroundColor = ConsoleColor.Cyan; - break; - } - //Check if an override foreground color was specified. - if (foreColor != foreground) - { - Console.ForegroundColor = foreground; - } - //Check if an override background color was specified. - if (backColor != background) - { - Console.BackgroundColor = background; - } - //Are we keeping output in a static location? - if (instance.StaticConsoleLocation) - { - //Leverage the lock to ensure multiple threads - //don't try to write to console concurrently. - lock (_lockStaticConsoleLocation) - { - //Grab the current cursor position. - var cursorTop = Console.CursorTop; - var cursorLeft = Console.CursorLeft; - //Output the message with a large trailing - //blank to clear previous output from the static - //console line. - Console.WriteLine( - PrependTimeStamp(message) - .PadRight(120, ' ')); - //Reset the cursor after output. - Console.CursorTop = cursorTop; - Console.CursorLeft = cursorLeft; - } - } - //No static output location is required. - else - { - //Simply write the message to the console. - Console.WriteLine(PrependTimeStamp(message)); - } - //Reset console colors. - Console.ForegroundColor = foreColor; - Console.BackgroundColor = backColor; - } - //Check if should log to EventLog - if (instance.LogToEventLog) - { - //Set the default EventLog type. - System.Diagnostics.EventLogEntryType targetType = - System.Diagnostics.EventLogEntryType.Error; - //Change the default to match the message type. - switch (messageType) - { - case MessageType.Warning: - targetType = - System.Diagnostics.EventLogEntryType.Warning; - break; - case MessageType.Information: - targetType = - System.Diagnostics.EventLogEntryType.Information; - break; - case MessageType.Verbose: - targetType = - System.Diagnostics.EventLogEntryType.Information; - break; - } - //Check if an event ID was specified. - if (eventId != 0) - { - //Event ID specified so include it in the write. - System.Diagnostics.EventLog.WriteEntry( - "Application", - message, - targetType); - } - else - { - //No event ID so write without it. - System.Diagnostics.EventLog.WriteEntry( - "Application", - message, - targetType); - } - } - //Check if we should log to file. - if (instance.LogToFile) - { - //Extra try/catch/finally to handle file locking. - try - { - //Obtain a lock, waiting up to 10 seconds to do so. - if (_lock.TryEnterWriteLock(10000)) - { - //Write to the configured log file. - System.IO.File.AppendAllText( - instance.LogFile, - messageType.ToString() + - ", " + - PrependTimeStamp(message) + "\n"); - } - } - catch (Exception ex) - { - //Write exception info to the console in default red. - WriteConsoleError(ex.ToString()); - System.Diagnostics.EventLog.WriteEntry( - "Application", - ex.ToString(), - System.Diagnostics.EventLogEntryType.Error); - } - finally - { - _lock.ExitWriteLock(); - } - } - //Check if logging should be done to a SharePoint list. - if (instance.LogToSPList) - { - var client = instance.GraphClient; - if (client != null) - { - try - { - var dic = new Dictionary(); - var msg = message.Split("|||".ToCharArray()); - if (msg.Length == 2) - { - dic.Add("Title", msg[0]); - dic.Add("Message", msg[1]); - } - else - { - dic.Add("Title", message); - } - var listItem = new Microsoft.Graph.Models.ListItem - { - Fields = new Microsoft.Graph.Models.FieldValueSet - { - AdditionalData = dic - } - }; - var result = client.Sites[Graph.GetSiteId( - $"/sites/{instance.LogSiteUrl}")] - .Lists[Graph.GetListId( - instance.LogListName, - instance.LogSiteUrl)] - .Items - .PostAsync(listItem) - .GetAwaiter().GetResult(); - } - catch (Exception ex) - { - System.Diagnostics.EventLog.WriteEntry( - "Application", - ex.ToString()); - } - } - } - //Check if message should be logged to ILogger. - if (instance.LogToILogger) - { - switch (messageType) - { - case MessageType.Information: - instance.ILogger.LogInformation(message); - break; - case MessageType.Warning: - instance.ILogger.LogWarning(message); - break; - case MessageType.Error: - instance.ILogger.LogError(message); - break; - case MessageType.Verbose: - instance.ILogger.LogInformation(message); - break; - } - } - //Check if message should be logged to database. - if (instance.LogToDB) - { - throw new NotImplementedException("DB logging coming soon!"); - } - } - //Something went wrong. - catch (Exception ex) - { - //Logging code may NEVER terminate its parent through exceptions. - try - { - if (instance == null) - { - instance = ActiveLogitInstance; - } - //Log exception to console and event log! - var fore = Console.ForegroundColor; - var back = Console.BackgroundColor; - Console.ForegroundColor = ConsoleColor.Red; - //Write console output, stamped if needed. - Console.WriteLine(PrependTimeStamp(ex.ToString())); - //Reset the console foreground color. - Console.ForegroundColor = fore; - Console.BackgroundColor = back; - System.Diagnostics.EventLog.WriteEntry( - "Application", - ex.ToString(), - System.Diagnostics.EventLogEntryType.Error); - } - catch - { - //Swallow the error. - } - } - } - - /// - /// Called to write "Information" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - /// Return value from Log() method. - public static void Inf( - string message, - int eventId = 0, - Instance instance = null) - { - if (instance == null) - { - instance = ActiveLogitInstance; - } - Log(message, eventId, MessageType.Information, instance); - } - - /// - /// Called to write "Warning" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - /// Return value from Log() method. - public static void Wrn( - string message, - int eventId = 0, - Instance instance = null) - { - if (instance == null) - { - instance = ActiveLogitInstance; - } - Log(message, eventId, MessageType.Warning, instance); - } - - /// - /// Called to write "Error" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - /// Return value from Log() method. - public static void Err( - string message, - int eventId = 0, - Instance instance = null) - { - if (instance == null) - { - instance = ActiveLogitInstance; - } - Log(message, eventId, MessageType.Error, instance); - } - - /// - /// Called to write "Verbose" entries. - /// - /// The string message to log. - /// The Event Log event ID to use. - /// Return value from Log() method. - public static void Vrb( - string message, - int eventId = 0, - Instance instance = null) - { - if (instance == null) - { - instance = ActiveLogitInstance; - } - Log(message, eventId, MessageType.Verbose, instance); - } - #endregion Worker Methods - } -} diff --git a/Classes/System.String.cs b/Classes/System.String.cs deleted file mode 100644 index ec758e1..0000000 --- a/Classes/System.String.cs +++ /dev/null @@ -1,2861 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text.Json.Serialization; -using System.Text.Json; -using static Extensions.Constants; -using static Extensions.Core; -using System.Text; -using System.Globalization; - -namespace Extensions -{ - /// - /// Extension methods for the System.String and System.Text.StringBuilder - /// classes. - /// - [Serializable] - public static partial class StringExtensions - { - #region BeginsWith() - /// - /// Checks if the current string begins with the given target string. - /// - /// - /// - /// - /// - public static bool BeginsWith(this System.String str, - string target, - bool ignorecase = true) - { - ValidateNoNulls(str, target); - if (target.Length <= str.Length) - { - if (ignorecase) - { - if (str.ToLower().Substring(0, target.Length) == target.ToLower()) - { - return true; - } - } - else - { - if (str.Substring(0, target.Length) == target) - { - return true; - } - } - } - return false; - } - #endregion BeginsWith() - - #region ContainsAny() - /// - /// Checks if the given string contains any of the strings provided in - /// the IEnumerable. - /// - /// The given string to check. - /// The character array to validate against. - /// True if the given string contains any characters provided - /// in the character array, otherwise False. - public static bool ContainsAny(this System.String str, - char[] chars) - { - ValidateNoNulls(str, chars); - foreach (char C in chars) - { - if (str.Contains(C)) - { - return true; - } - } - return false; - } - - /// - /// Checks if the given string contains any of the strings provided in - /// the IEnumerable. - /// - /// The given string to check. - /// The IEnumerable i.e. List of strings or - /// string array to validate against. - /// True if the given string contains any of the strings - /// provided in the IEnumerable, otherwise False. - public static bool ContainsAny(this System.String str, - IEnumerable strings) - { - ValidateNoNulls(str, strings); - foreach (string C in strings) - { - if (str.Contains(C)) - { - return true; - } - } - return false; - } - - /// - /// Checks if the given string contains any of the strings provided in - /// the IEnumerable. - /// - /// The given string to check. - /// The character array to validate against. - /// True if the given string contains any characters provided - /// in the character array, otherwise False. - public static bool ContainsAny(this System.Text.StringBuilder str, - char[] chars) - { - ValidateNoNulls(str, chars); - return ContainsAny(str.ToString(), chars); - } - - /// - /// Checks if the given string contains any of the strings provided in - /// the IEnumerable. - /// - /// The given string to check. - /// The IEnumerable i.e. List of strings or - /// string array to validate against. - /// True if the given string contains any of the strings - /// provided in the IEnumerable, otherwise False. - public static bool ContainsAny(this System.Text.StringBuilder str, - IEnumerable strings) - { - ValidateNoNulls(str, strings); - return ContainsAny(str.ToString(), strings); - } - #endregion ContainsAny() - - #region ContainsOnly() - /// - /// Checks if the given string contains only the characters provided in - /// the IEnumerable. - /// - /// The given string to check. - /// The character array to validate against. - /// True if the given string only contains characters provided - /// in the IEnumerable, otherwise False. - public static bool ContainsOnly(this System.String str, - char[] chars) - { - ValidateNoNulls(str, chars); - string remain = str; - foreach (char C in chars) - { - remain = remain.Replace(C.ToString(), ""); - } - remain = remain.Trim(); - if (remain == "") - { - return true; - } - return false; - } - - /// - /// Checks if the given string contains only the strings provided in - /// the IEnumerable. - /// - /// The given string to check. - /// The IEnumerable i.e. List of strings or - /// string array to validate against. - /// True if the given string only contains strings provided - /// in the IEnumerable, otherwise False. - public static bool ContainsOnly(this System.String str, - IEnumerable strings) - { - ValidateNoNulls(str, strings); - string remain = str; - foreach (string C in strings) - { - remain = remain.Replace(C, ""); - } - remain = remain.Trim(); - if (remain == "") - { - return true; - } - return false; - } - - /// - /// Checks if the given string contains only the characters provided in - /// the IEnumerable. - /// - /// The given string to check. - /// The character array to validate against. - /// True if the given string only contains characters provided - /// in the IEnumerable, otherwise False. - public static bool ContainsOnly(this System.Text.StringBuilder str, - char[] chars) - { - ValidateNoNulls(str, chars); - return ContainsOnly(str.ToString(), chars); - } - - /// - /// Checks if the given string contains only the strings provided in - /// the IEnumerable. - /// - /// The given string to check. - /// The IEnumerable i.e. List of strings or - /// string array to validate against. - /// True if the given string only contains strings provided - /// in the IEnumerable, otherwise False. - public static bool ContainsOnly(this System.Text.StringBuilder str, - IEnumerable strings) - { - ValidateNoNulls(str, strings); - return ContainsOnly(str.ToString(), strings); - } - #endregion ContainsOnly() - - #region DoubleQuote() - /// - /// Return the given string encased in double quotes. - /// - /// The given string to be quoted. - /// The given string encased in double quotes. - public static string DoubleQuote(this System.String str) - { - ValidateNoNulls(str); - return ('"' + str + '"'); - } - - /// - /// Return the given string encased in double quotes. - /// - /// The given string to be quoted. - /// The given string encased in double quotes. - public static string DoubleQuote(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return DoubleQuote(str.ToString()); - } - #endregion DoubleQuote() - - #region EncodeAsXml() - /// - /// Encode a given string as XML. - /// - /// The target string to encode. - /// The target string with ampersand, apostrophe, - /// greater than, less than and double quote XML converted. - public static string EncodeAsXml(this string str) - { - return str.Replace("&", "&") - .Replace("'", "'") - .Replace(">", ">") - .Replace("<", "<") - .Replace("\"", """); - } - #endregion EncodeAsXml() - - #region Encrypt() - - //public static string Encrypt(this System.String str, - // string password, - // Constants.EncryptionProvider provider = - // Constants.EncryptionProvider.SHA512) - //{ - // System.Security.Cryptography.SHA512CryptoServiceProvider cryptoServiceProvider = - // new System.Security.Cryptography.SHA512CryptoServiceProvider(); - // System.Text.Encoding encoding = System.Text.Encoding.UTF8; - // System.Security.Cryptography.Rfc2898DeriveBytes key = - // new System.Security.Cryptography.Rfc2898DeriveBytes(password, salt); - // byte[] raw = encoding.GetBytes(password); - // byte[] hashKey = cryptoServiceProvider.ComputeHash(raw); - // byte[] hashIV = hashKey.CopyTo(16); - // byte[] encrypted; - // using (System.Security.Cryptography.RijndaelManaged managed = - // new System.Security.Cryptography.RijndaelManaged()) - // { - // managed.Key = hashKey; - // managed.IV = hashIV; - // System.Security.Cryptography.ICryptoTransform encryptor = - // managed.CreateEncryptor(managed.Key, managed.IV); - // using (System.IO.MemoryStream memoryStream = - // new System.IO.MemoryStream()) - // { - // using (System.Security.Cryptography.CryptoStream cryptoStream = - // new System.Security.Cryptography.CryptoStream(memoryStream, - // encryptor, - // System.Security.Cryptography.CryptoStreamMode.Write)) - // { - // using (System.IO.StreamWriter streamWriter = - // new System.IO.StreamWriter(cryptoStream)) - // { - // streamWriter.Write(str); - // } - // encrypted = memoryStream.ToArray(); - // } - // } - // } - // return Convert.ToBase64String(encrypted); - //} - - //public static string Decrypt(this System.String str, - // string password, - // Constants.EncryptionProvider provider = - // Constants.EncryptionProvider.SHA512) - //{ - // System.Security.Cryptography.SHA512CryptoServiceProvider cryptoServiceProvider = - // new System.Security.Cryptography.SHA512CryptoServiceProvider(); - // System.Text.Encoding encoding = System.Text.Encoding.UTF8; - // byte[] raw = encoding.GetBytes(password); - // byte[] hashKey = cryptoServiceProvider.ComputeHash(raw); - // byte[] hashIV = hashKey.CopyTo(16); - // byte[] encrypted = Convert.FromBase64String(str); - // string decrypted = null; - // using (System.Security.Cryptography.RijndaelManaged managed = - // new System.Security.Cryptography.RijndaelManaged()) - // { - // managed.Key = hashKey; - // managed.IV = hashIV; - // System.Security.Cryptography.ICryptoTransform decryptor = - // managed.CreateDecryptor(managed.Key, managed.IV); - // using (System.IO.MemoryStream memoryStream = - // new System.IO.MemoryStream(encrypted)) - // { - // using (System.Security.Cryptography.CryptoStream cryptoStream = - // new System.Security.Cryptography.CryptoStream(memoryStream, - // decryptor, - // System.Security.Cryptography.CryptoStreamMode.Read)) - // { - // using (System.IO.StreamReader streamReader = - // new System.IO.StreamReader(cryptoStream)) - // { - // decrypted = streamReader.ReadToEnd(); - // } - // } - // } - // } - // return decrypted; - //} - - #endregion Encrypt() - - #region ExceedsLength() - /// - /// Checks if a referenced offset exceeds the length of the string. - /// - /// The current string to check against. - /// The referenced offset value. - /// Should the offset be incremented before - /// the length comparison takes place. - /// - public static bool ExceedsLength(this System.String str, - ref int offset, - bool increment = true) - { - if (increment) - { - offset++; - } - if (offset >= str.Length) - { - return true; - } - return false; - } - - /// - /// Checks if a referenced offset exceeds the length of the string. - /// - /// The current string to check against. - /// The referenced offset value. - /// Should the offset be incremented before - /// the length comparison takes place. - /// - public static bool ExceedsLength(this System.Text.StringBuilder str, - ref int offset, - bool increment = true) - { - return ExceedsLength(str.ToString(), ref offset, increment); - } - #endregion ExceedsLength() - - #region GetSiteUrl() - /// - /// Get the tenant root for the given string object containing a URL. - /// For example: - /// "https://blog.cjvandyk.com/sites/Approval".GetTenantUrl() - /// will return "https://blog.cjvandyk.com". - /// - /// The System.String object containing the URL - /// from which the tenant root is to be extracted. - /// The tenant root of the URL given the URL string. - public static string GetSiteUrl(this System.String url) - { - return url.Substring(-1, "/", SubstringType.LeftOfIndex, 5); - } - #endregion GetSiteUrl() - - #region GetTenantUrl() - /// - /// Get the tenant root for the given string object containing a URL. - /// For example: - /// "https://blog.cjvandyk.com/sites/Approval".GetTenantUrl() - /// will return "https://blog.cjvandyk.com". - /// - /// The System.String object containing the URL - /// from which the tenant root is to be extracted. - /// The tenant root of the URL given the URL string. - public static string GetTenantUrl(this System.String url) - { - return GetUrlRoot(url); - } - #endregion GetTenantUrl() - - #region GetUrlRoot() - /// - /// Get the URL root for the given string object containing a URL. - /// For example: - /// "https://blog.cjvandyk.com".GetUrlRoot() - /// will return "https://blog.cjvandyk.com" whereas - /// "https://blog.cjvandyk.com/sites/Approval".GetUrlRoot() - /// will also return "https://blog.cjvandyk.com". - /// - /// The System.String object containing the URL - /// from which the root is to be extracted. - /// The root of the URL given the URL string. - public static string GetUrlRoot(this System.String url) - { - ValidateNoNulls(url); - string root = url.ToLower().Replace("https://", ""); - return ("https://" + root.Substring(0, root.IndexOf('/'))); - } - - /// - /// Get the URL root for the given string builder object containing a - /// URL. For example: - /// "https://blog.cjvandyk.com".GetUrlRoot() - /// will return "https://blog.cjvandyk.com" whereas - /// "https://blog.cjvandyk.com/sites/Approval".GetUrlRoot() - /// will also return "https://blog.cjvandyk.com". - /// - /// The System.Text.StringBuilder object containing - /// the URL from which the root is to be extracted. - /// The root of the URL given the URL string. - public static string GetUrlRoot(this System.Text.StringBuilder url) - { - ValidateNoNulls(url); - return GetUrlRoot(url.ToString()); - } - #endregion GetUrlRoot() - - #region HasLower() - /// - /// Check if given System.String object contains lower case. - /// - /// The string object to check. - /// Remove spaces before checking? - /// True if the object contains any lower case, else False. - public static bool HasLower(this System.String str, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, ignoreSpaces); - return (ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .Select(C => (int)C) - .Any(C => C >= 97 && C <= 122); - } - - /// - /// Check if given System.Text.StringBuilder object contains lower case. - /// - /// The string object to check. - /// True if the string contains any lower case, else False. - public static bool HasLower(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return HasLower(str.ToString()); - } - #endregion HasLower() - - #region HasNumeric() - /// - /// Checks if the given string contains any numeric characters. - /// - /// The given string object to check. - /// Remove spaces before compare? - /// True if any characters in the given string are numeric, - /// else False. - public static bool HasNumeric(this System.String str, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, ignoreSpaces); - return (ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .Any(Char.IsDigit); - } - - /// - /// Checks if the given string contains any numeric characters. - /// - /// The given string builder object to check. - /// Remove spaces before compare? - /// True if any characters in the given string are numeric, - /// else False. - public static bool HasNumeric(this System.Text.StringBuilder str, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, ignoreSpaces); - return HasNumeric(str.ToString(), - ignoreSpaces); - } - #endregion HasNumeric() - - #region HasSymbol() - /// - /// Checks if the given System.String object contains symbols or - /// special characters. - /// - /// The given string object to check. - /// Remove spaces before compare? - /// True if any characters in the given string are - /// symbols or special characters, else False. - public static bool HasSymbol(this System.String str, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, ignoreSpaces); - return (!(ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .All(Char.IsLetterOrDigit)); - } - - /// - /// Checks if the given System.Text.StringBuilder object contains - /// symbols or special characters. - /// - /// The given string object to check. - /// Use non-RegEx method. - /// Remove spaces before compare? - /// True if all characters in the given string contains - /// any symbols or special characters, else False. - public static bool HasSymbol(this System.Text.StringBuilder str, - bool Classic = false, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, Classic, ignoreSpaces); - return HasSymbol(str.ToString(), - ignoreSpaces); - } - #endregion HasSymbol() - - #region HasUpper() - /// - /// Check if given System.String object contains upper case. - /// - /// The string object to check. - /// Remove spaces before checking? - /// True if the string contains any upper case, else False. - public static bool HasUpper(this System.String str, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, ignoreSpaces); - return (ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .Select(C => (int)C) - .Any(C => C >= 65 && C <= 90); - } - - /// - /// Check if given System.Text.StringBuilder object contains upper case. - /// - /// The string object to check. - /// True if the string contains any upper case, else False. - public static bool HasUpper(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return HasUpper(str.ToString()); - } - #endregion HasUpper() - - #region HtmlDecode() - /// - /// Decode the HTML escaped components in a given string. - /// - /// The given source string to decode. - /// The given source string without HTML escaped components. - public static string HtmlDecode(this System.String str) - { - ValidateNoNulls(str); -#if NET5_0_OR_GREATER - return System.Web.HttpUtility.HtmlDecode(str); -#else - return System.Net.WebUtility.HtmlDecode(str); -#endif - } - - /// - /// Decode the HTML escaped components in a given string. - /// - /// The given source string to decode. - /// The given source string without HTML escaped components. - public static string HtmlDecode(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return HtmlDecode(str.ToString()); - } - #endregion HtmlDecode() - - #region HtmlEncode() - /// - /// Encode the given string to be HTML safe. - /// - /// The given source string to encode. - /// The given source string in HTML safe format. - public static string HtmlEncode(this System.String str) - { - ValidateNoNulls(str); -#if NET5_0_OR_GREATER - return System.Web.HttpUtility.HtmlEncode(str); -#else - return System.Net.WebUtility.HtmlEncode(str); -#endif - } - - /// - /// Encode the given string to be HTML safe. - /// - /// The given source string to encode. - /// The given source string in HTML safe format. - public static string HtmlEncode(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return HtmlEncode(str.ToString()); - } - #endregion HtmlEncode() - - #region IsAlphabetic() - /// - /// Checks if the given string contains all alphabetic characters. - /// - /// The given string object to check. - /// Switch to force RegEx comparison instead of - /// Linq. - /// Remove spaces before compare? - /// True if all characters in the given string are alphabetic, - /// else False. - public static bool IsAlphabetic(this System.String str, - bool Classic = false, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, Classic, ignoreSpaces); - if (Classic) //No LINQ available e.g. .NET 2.0 - { - return System.Text.RegularExpressions.Regex.IsMatch( - (ignoreSpaces ? str.Replace(" ", "") : str), - @"^[a-zA-Z]+$"); - } - else //This method is on average 670% faster than RegEx method. - { - return (ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .All(Char.IsLetter); - } - } - - /// - /// Checks if the given string contains all alphabetic characters. - /// - /// The given string builder object to check. - /// Switch to force RegEx comparison instead - /// of Linq. - /// Remove spaces before compare? - /// True if all characters in the given string are alphabetic, - /// else False. - public static bool IsAlphabetic(this System.Text.StringBuilder str, - bool Classic = false, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, Classic, ignoreSpaces); - return IsAlphabetic(str.ToString(), - Classic, - ignoreSpaces); - } - #endregion IsAlphabetic() - - #region IsAlphaNumeric() - /// - /// Checks if the given string contains only alphabetic and numeric - /// characters. - /// - /// The given string object to check. - /// Switch to force RegEx comparison instead of - /// Linq. - /// Remove spaces before compare? - /// True if all characters in the given string are either - /// alphabetic or numeric, else False. - public static bool IsAlphaNumeric(this System.String str, - bool Classic = false, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, Classic, ignoreSpaces); - if (Classic) //No LINQ available e.g. .NET 2.0 - { - return System.Text.RegularExpressions.Regex.IsMatch( - (ignoreSpaces ? str.Replace(" ", "") : str), - @"^[a-zA-Z0-9]+$"); - } - else //This method is on average 670% faster than RegEx method. - { - return (ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .All(Char.IsLetterOrDigit); - } - } - - /// - /// Checks if the given string contains only alphabetic and numeric - /// characters. - /// - /// The given string builder object to check. - /// Switch to force RegEx comparison instead of - /// Linq. - /// Remove spaces before compare? - /// True if all characters in the given string are either - /// alphabetic or numeric, else False. - public static bool IsAlphaNumeric(this System.Text.StringBuilder str, - bool Classic = false, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, Classic, ignoreSpaces); - return IsAlphaNumeric(str.ToString(), - Classic, - ignoreSpaces); - } - #endregion IsAlphaNumeric() - - #region IsChar() - /// - /// Check if the given string contains only the characters in the - /// Chars array being passed. - /// - /// The given string object to check. - /// The array of valid characters that are checked - /// in the string. - /// Switch to force RegEx comparison instead of - /// Linq. - /// True if the given string contains only characters in the - /// Chars array, else False. - public static bool IsChar(this System.String str, - char[] Chars, - bool Classic = false) - { - ValidateNoNulls(str, Chars, Classic); - if (Classic) //No LINQ available e.g. .NET 2.0 - { - string comparor = @"^["; - foreach (char c in Chars) - { - comparor += c; - } - comparor += "]+$"; - return System.Text.RegularExpressions.Regex.IsMatch(str, - comparor); - } - else - { - foreach (char c in Chars) - { - if (!str.Contains(c)) - { - return false; - } - } - return true; - } - } - - /// - /// Check if the given string contains only the characters in the - /// Chars array being passed. - /// - /// The given string builder object to check. - /// The array of valid characters that are checked - /// in the string. - /// Switch to force RegEx comparison instead of - /// Linq. - /// True if the given string contains only characters in the - /// Chars array, else False. - public static bool IsChar(this System.Text.StringBuilder str, - char[] Chars, - bool Classic = false) - { - ValidateNoNulls(str, Chars, Classic); - return IsChar(str.ToString(), Chars, Classic); - } - #endregion IsChar() - - #region IsDateTime() - /// - /// Checks if a given string is a valid date/time given the format. - /// - /// The given string to check. - /// The string format of the date/time to - /// use in the object convertion e.g. "dd/MM/yyyy HH:mm:ss" If - /// none is specified it defaults to "dd/MM/yyyy HH:mm:ss" - /// True if the given string is a valid date/time in the - /// given format, else False. - public static bool IsDateTime(this string str, - string inFormat = "dd/MM/yyyy HH:mm:ss") - { - try - { - DateTime dateTime = DateTime.ParseExact( - str, inFormat, CultureInfo.InvariantCulture); - return true; - } - catch - { - return false; - } - } - - /// - /// Checks if a given StringBuilder is a valid date/time given the - /// format. - /// - /// The given StringBuilder to check. - /// The string format of the date/time to - /// use in the object convertion e.g. "dd/MM/yyyy HH:mm:ss" If - /// none is specified it defaults to "dd/MM/yyyy HH:mm:ss" - /// True if the given StringBuilder is a valid date/time in - /// the given format, else False. - public static bool IsDateTime(this StringBuilder sb, - string inFormat = "dd/MM/yyyy HH:mm:ss") - { - return IsDateTime(sb.ToString(), inFormat); - } - #endregion IsDateTime() - - #region IsEmail() - /// - /// Checks if a given System.String object is an email address. - /// - /// The System.String to validate as email. - /// True if email, false if not. - public static bool IsEmail(this System.String str) - { - ValidateNoNulls(str); - try - { - var email = new System.Net.Mail.MailAddress(str); - return true; - } - catch - { - return false; - } - } - - /// - /// Checks if a given System.Text.StringBuilder object is an email - /// address. - /// - /// The System.Text.StringBuilder to validate as - /// email. - /// True if email, false if not. - public static bool IsEmail(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return IsEmail(str.ToString()); - } - #endregion IsEmail() - - #region IsHex() - /// - /// Checks if the given string contains all hex characters. - /// - /// The given string object to check. - /// Switch to force RegEx comparison instead - /// of Linq. - /// Remove spaces before compare? - /// True if all characters in the given string are hex, - /// else False. - public static bool IsHex(this System.String str, - bool Classic = false, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, Classic, ignoreSpaces); - if (Classic) //No LINQ available e.g. .NET 2.0 - { - return System.Text.RegularExpressions.Regex.IsMatch( - (ignoreSpaces ? str.Replace(" ", "") : str), - @"\A\b[0-9a-fA-F]+\b\Z"); - } - else //This method is on average 670% faster than RegEx method. - { - return (ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .All(C => (C >= 0 && C <= 9) || - (C >= 'a' && C <= 'f') || - (C >= 'A' && C <= 'F')); - } - } - - /// - /// Checks if the given string contains all hex characters. - /// - /// The given string builder object to check. - /// Switch to force RegEx comparison instead of - /// Linq. - /// Remove spaces before compare? - /// True if all characters in the given string are hex, - /// else False. - public static bool IsHex(this System.Text.StringBuilder str, - bool Classic = false, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, Classic, ignoreSpaces); - return IsHex(str.ToString(), - Classic, - ignoreSpaces); - } - #endregion IsHex() - - #region IsLower() - /// - /// Check if given System.String object is all lower case. - /// - /// The string object to check. - /// Remove spaces before checking? - /// True if the object is all lower case, else False. - public static bool IsLower(this System.String str, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, ignoreSpaces); - return (ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .Select(C => (int)C) - .All(C => C >= 97 && C <= 122); - } - - /// - /// Check if given System.Text.StringBuilder object is all lower case. - /// - /// The string object to check. - /// True if the entire string is lower case, else False. - public static bool IsLower(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return IsLower(str.ToString()); - } - #endregion IsLower() - - #region IsNumeric() - /// - /// Checks if the given string contains all numeric characters. - /// - /// The given string object to check. - /// Switch to force RegEx comparison instead - /// of Linq. - /// Remove spaces before compare? - /// True if all characters in the given string are numeric, - /// else False. - public static bool IsNumeric(this System.String str, - bool Classic = false, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, Classic, ignoreSpaces); - if (Classic) //No LINQ available e.g. .NET 2.0 - { - return System.Text.RegularExpressions.Regex.IsMatch( - (ignoreSpaces ? str.Replace(" ", "") : str), - @"^[0-9]+$"); - } - else //This method is on average 670% faster than RegEx method. - { - return (ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .All(Char.IsDigit); - } - } - - /// - /// Checks if the given string contains all numeric characters. - /// - /// The given string builder object to check. - /// Switch to force RegEx comparison instead of - /// Linq. - /// Remove spaces before compare? - /// True if all characters in the given string are numeric, - /// else False. - public static bool IsNumeric(this System.Text.StringBuilder str, - bool Classic = false, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, Classic, ignoreSpaces); - return IsNumeric(str.ToString(), - Classic, - ignoreSpaces); - } - #endregion IsNumeric() - - #region IsStrong() - /// - /// Checks if the given System.String object is a strong password - /// string. - /// - /// The given string to check. - /// The number of strong criteria - /// that are required to be checked for. - /// Are upper case characters required? - /// Default is Yes. - /// Are lower case characters required? - /// Default is Yes. - /// Are numbers required? - /// Default is Yes. - /// Are symbols or special characters - /// required? Default is Yes. - /// True if string matches all require... criteria, - /// else False. - public static bool IsStrong(this System.String str, - int numberCriteriaRequired = 4, - bool requireUpper = true, - bool requireLower = true, - bool requireNumeric = true, - bool requireSymbol = true) - { - ValidateNoNulls(str, numberCriteriaRequired, - requireUpper, requireLower, - requireNumeric, requireSymbol); - if ((numberCriteriaRequired < 1) || - (numberCriteriaRequired > 4)) - { - return false; - } - int criteria = numberCriteriaRequired; - int required = 0; - if (requireUpper) required++; - if (requireLower) required++; - if (requireNumeric) required++; - if (requireSymbol) required++; - - if (str.HasUpper()) - { - criteria -= 1; - if (criteria == 0) - { - if (requireUpper) required--; - if (required == 0) - { - return true; - } - } - else - { - if (requireUpper) required--; - } - } - else - { - if (requireUpper) - { - return false; - } - } - - if (str.HasLower()) - { - criteria -= 1; - if (criteria == 0) - { - if (requireLower) required--; - if (required == 0) - { - return true; - } - } - else - { - if (requireLower) required--; - } - } - else - { - if (requireLower) - { - return false; - } - } - - if (str.HasNumeric()) - { - criteria -= 1; - if (criteria == 0) - { - if (requireNumeric) required--; - if (required == 0) - { - return true; - } - } - else - { - if (requireNumeric) required--; - } - } - else - { - if (requireNumeric) - { - return false; - } - } - - if (str.HasSymbol()) - { - criteria -= 1; - if (criteria == 0) - { - if (requireSymbol) required--; - if (required == 0) - { - return true; - } - } - else - { - if (requireSymbol) required--; - } - } - else - { - if (requireSymbol) - { - return false; - } - } - return false; - } - - /// - /// Checks if the given System.Test.StringBuilder object is a strong - /// password string. - /// - /// The given string to check. - /// The number of strong criteria - /// that are required to be checked for. - /// Are upper case characters required? - /// Default is Yes. - /// Are lower case characters required? - /// Default is Yes. - /// Are numbers required? - /// Default is Yes. - /// Are symbols or special characters - /// required? Default is Yes. - /// True if string matches all require... criteria, - /// else False. - public static bool IsStrong(this System.Text.StringBuilder str, - int numberCriteriaRequired = 4, - bool requireUpper = true, - bool requireLower = true, - bool requireNumeric = true, - bool requireSymbol = true) - { - ValidateNoNulls(str, numberCriteriaRequired, - requireUpper, requireLower, - requireNumeric, requireSymbol); - return IsStrong(str, - numberCriteriaRequired, - requireUpper, - requireLower, - requireNumeric, - requireSymbol); - } - #endregion IsStrong() - - #region IsUpper() - /// - /// Check if given System.String object is all upper case. - /// - /// The string object to check. - /// Remove spaces before checking? - /// True if the entire string is upper case, else False. - public static bool IsUpper(this System.String str, - bool ignoreSpaces = true) - { - ValidateNoNulls(str, ignoreSpaces); - return (ignoreSpaces ? str.Replace(" ", "") : str) - .ToCharArray() - .Select(C => (int)C) - .All(C => C >= 65 && C <= 90); - } - - /// - /// Check if given System.Text.StringBuilder object is all upper case. - /// - /// The string object to check. - /// True if the entire string is upper case, else False. - public static bool IsUpper(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return IsUpper(str.ToString()); - } - #endregion IsUpper() - - #region IsUrlRoot() - /// - /// Check if the given string object containing a URL, is that of the - /// URL root only. Returns True if so, False if not. For example: - /// "https://blog.cjvandyk.com".IsUrlRootOnly() - /// will return True whereas - /// "https://blog.cjvandyk.com/sites/Approval".IsUrlRootOnly() - /// will return False. - /// - /// The System.String object containing the URL to - /// be checked. - /// True if the URL is a root, False if not. - public static bool IsUrlRoot(this System.String url) - { - ValidateNoNulls(url); - if (url.ToLower() - .TrimEnd('/') - .Replace("https://", "") - .Replace("http://", "") - .IndexOf('/') == -1) - { - return true; - } - return false; - } - - /// - /// Check if the given string builder object containing a URL, is that - /// of the URL root only. Returns True if so, False if not. - /// For example: - /// "https://blog.cjvandyk.com".IsUrlRootOnly() - /// will return True whereas - /// "https://blog.cjvandyk.com/sites/Approval".IsUrlRootOnly() - /// will return False. - /// - /// The System.Text.StringBuilder object containing - /// the URL to be checked. - /// True if the URL is a root, False if not. - public static bool IsUrlRoot(this System.Text.StringBuilder url) - { - ValidateNoNulls(url); - return IsUrlRoot(url.ToString()); - } - #endregion IsUrlRoot() - - #region IsVowel() - /// - /// Checks if the given System.Char is an English vowel. - /// - /// The char to check. - /// True if it's a vowel, else False. - public static bool IsVowel(this System.Char C) - { - ValidateNoNulls(C); - switch (C) - { - case 'a': - case 'e': - case 'i': - case 'o': - case 'u': - case 'y': - return true; - default: - return false; - } - } - - /// - /// Checks if the given System.String is an English vowel. - /// This allows the developer the ability to check a string without - /// having to first convert to a char e.g. as a substring return. - /// - /// The string to check. - /// True if it's a vowel, else False. - public static bool IsVowel(this System.String str) - { - ValidateNoNulls(str); - return IsVowel(Convert.ToChar(str)); - } - - /// - /// Checks if the given System.Test.StringBuilder is an English vowel. - /// This allows the developer the ability to check a string without - /// having to first convert to a char e.g. as a substring return. - /// - /// The string to check. - /// True if it's a vowel, else False. - public static bool IsVowel(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return IsVowel(Convert.ToChar(str.ToString())); - } - #endregion IsVowel() - - #region IsZipCode() - /// - /// Checks if the given System.String object is in the valid format - /// of a United States zip code i.e. nnnnn-nnnn or just nnnnn. - /// - /// The given string object to check. - /// True if in valid format, else False. - public static bool IsZipCode(this System.String str) - { - ValidateNoNulls(str); - string[] parts = str.Split('-'); - if (parts.Length == 1) - { - return IsZipCode5Digits(str); - } - else - { - if (parts.Length == 2) - { - return (str.Length == 10 && - IsZipCode5Digits(parts[0]) && - parts[1].Length == 4 && - int.TryParse(parts[1], out _)); - } - } - return false; - } - - /// - /// Checks if the given System.Text.StringBuilder object is in the - /// valid format of a United States zip code i.e. nnnnn-nnnn or - /// just nnnnn. - /// - /// The given string object to check. - /// True if in valid format, else False. - public static bool IsZipCode(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return IsZipCode(str.ToString()); - } - - /// - /// Checks if the given System.String is 5 digits long and numeric. - /// - /// The given string object to check. - /// True if a 5 digit numeric, else False. - private static bool IsZipCode5Digits(this System.String str) - { - ValidateNoNulls(str); - return (str.Length == 5 && - int.TryParse(str, out _)); - } - #endregion IsZipCode() - - #region Left() - /// - /// Returns text to the left of the index string. Use negative values - /// for occurrence if the occurrence count should start from the end - /// instead of its default from the beginning of the string. - /// - /// A System.Text.StringBuilder object being - /// searched. - /// The System.String value used as the target - /// of the search. - /// The number of matches to find. - /// Returns text to the left of the index string. Use - /// negative values for occurrence if the occurrence count should - /// start from the end instead of its default from the beginning of - /// the string. - public static string Left(this System.String str, - string index, - int occurrence = 1) - { - ValidateNoNulls(str, index, occurrence); - if (str.IndexOf(index) > 0) - { - if (occurrence == 1) - { - return str.Substring(0, str.IndexOf(index)); - } - if (occurrence == -1) - { - return str.Substring(0, str.LastIndexOf(index)); - } - if (occurrence > 1) - { - string remainder = str; - for (int C = 0; C < occurrence; C++) - { - if (remainder.IndexOf(index) == -1) - { - return ""; - } - try - { - remainder = remainder.Substring(remainder.IndexOf(index) + index.Length); - } - catch (Exception ex) - { - return ""; - } - } - return str.Substring(0, str.Length - (remainder.Length + index.Length)); - } - if (occurrence < -1) - { - string remainder = str; - for (int C = 0; C > occurrence; C--) - { - if (remainder.LastIndexOf(index) == -1) - { - return ""; - } - try - { - remainder = remainder.Substring(0, remainder.LastIndexOf(index)); - } - catch (Exception ex) - { - return ""; - } - } - return remainder; - } - } - return ""; - } - - /// - /// Returns text to the left of the index string. Use negative values - /// for occurrence if the occurrence count should start from the end - /// instead of its default from the beginning of the string. - /// - /// A System.Text.StringBuilder object being - /// searched. - /// The System.String value used as the target - /// of the search. - /// The number of matches to find. - /// Returns text to the left of the index string. Use - /// negative values for occurrence if the occurrence count should - /// start from the end instead of its default from the beginning of - /// the string. - public static string Left(this System.Text.StringBuilder str, - string index, - int occurrence = 1) - { - ValidateNoNulls(str, index, occurrence); - return Left(str.ToString(), index, occurrence); - } - #endregion Left() - - #region Lines() - /// - /// Returns the number of sentences in the given string object. - /// - /// A System.String object. - /// The number of sentences in the given object. - public static int Lines(this System.String str) - { - ValidateNoNulls(str); - return str.Split(new char[] { '\n' }, - StringSplitOptions.RemoveEmptyEntries) - .Length; - } - - /// - /// Returns the number of sentences in the given string builder object. - /// - /// A System.Text.StringBuilder object. - /// The number of sentences in the given object. - public static int Lines(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return Lines(str.ToString()); - } - #endregion Lines() - - #region LoremIpsum() - /// - /// Returns a string containing 1 - 10 paragraphs of dummy text - /// in lorem ipsum style. - /// - /// The System.String object to be populated with - /// the dummy text. - /// An integer with the number of paragraphs - /// to be returned. Presently supports 1-10 - /// The string containing the generated dummy text. - public static string LoremIpsum(this System.String str, - int Paragraphs) - { - Validate(ErrorTypeAll, str, Paragraphs); - str = null; - for (int C = 0; C < (Paragraphs > 10 ? 10 : Paragraphs); C++) - { - str += Extensions.Constants.LoremIpsum[C] + '\n' + '\n'; - } - return str; - } - - /// - /// Returns a string containing 1 - 10 paragraphs of dummy text - /// in lorem ipsum style. - /// - /// The System.String object to be populated with - /// the dummy text. - /// An integer with the number of paragraphs - /// to be returned. Presently supports 1-10 - /// The string containing the generated dummy text. - public static string LoremIpsum(this System.Text.StringBuilder str, - int Paragraphs) - { - return LoremIpsum(str.ToString(), Paragraphs); - } - #endregion LoremIpsum() - - #region Match() - /// - /// Checks if the current string matches a given search mask. - /// It ignores duplicate '*' in the mask. '*' is matched against - /// 0 or more characters. Duplicate '?' is treated as requiring - /// the number of characters. '?' is matched against 1 or more - /// characters. - /// For example: - /// "abcdefgh".Match("***a?c*") - /// will return True while - /// "abcdefgh".Match("***ac*") - /// will return False but - /// "abcdefgh".Match("?a?c*") - /// will also return False because the first '?' requires a character - /// before 'a'. - /// - /// The current string being matched. - /// The search mask being used for the match. - /// Switch to ignore case sensitivity. - /// True if the current string matches the given search mask. - public static bool Match(this System.String str, - string mask, - bool ignoreCase = true) - { - ValidateNoNulls(str, mask); - if (mask == "*") - { - return true; - } - if (ignoreCase) - { - str = str.ToLower(); - mask = mask.ToLower(); - } - mask = mask.Singularize('*'); - int strOffset = 0; - int maskOffset = 0; - bool found = false; - while (maskOffset < mask.Length) - { - switch (mask[maskOffset]) - { - case '*': - maskOffset++; - if (maskOffset >= mask.Length) - { - return true; - } - found = false; - while (strOffset < str.Length) - { - if (str[strOffset] != mask[maskOffset]) - { - strOffset++; - } - else - { - found = true; - break; - } - } - if (!found) - { - return false; - } - break; - case '?': - if (str.ExceedsLength(ref strOffset)) - { - return true; - } - maskOffset++; - break; - default: - found = false; - while (strOffset < str.Length) - { - if (str[strOffset] != mask[maskOffset]) - { - strOffset++; - } - else - { - found = true; - break; - } - } - if (found) - { - maskOffset++; - strOffset++; - } - else - { - return false; - } - if (strOffset >= str.Length) - { - return true; - } - break; - } - } - return true; - } - - /// - /// Checks if the current string matches a given search mask. - /// It ignores duplicate '*' in the mask. '*' is matched against - /// 0 or more characters. Duplicate '?' is treated as requiring - /// the number of characters. '?' is matched against 1 or more - /// characters. - /// For example: - /// "abcdefgh".Match("***a?c*") - /// will return True while - /// "abcdefgh".Match("***ac*") - /// will return False but - /// "abcdefgh".Match("?a?c*") - /// will also return False because the first '?' requires a character - /// before 'a'. - /// - /// The current string being matched. - /// The search mask being used for the match. - /// Switch to ignore case sensitivity. - /// True if the current string matches the given search mask. - public static bool Match(this System.Text.StringBuilder str, - string mask, - bool ignoreCase = true) - { - return Match(str.ToString(), mask, ignoreCase); - } - #endregion Match() - - #region MorseCodeBeep() - /// - /// Takes a given System.String representing Morse code and audiblize - /// it according to standards. - /// https://www.infoplease.com/encyclopedia/science/engineering/electrical/morse-code - /// Assumes the input value to be in Morse code format already. - /// Use .ToMorseCode() to pre-convert text if needed. - /// - /// The System.String text in Morse code format. - /// The beep frequency. - /// The duration of a dot beep in ms. - public static void MorseCodeBeep(this System.String str, - int frequency = 999, - int duration = 100) - { - Validate(ErrorTypeAll, str, frequency, duration); - foreach (char c in str) - { - switch (c) - { - case '.': - Console.Beep(frequency, duration); - break; - - case '-': - Console.Beep(frequency, duration * 3); - break; - - case ' ': - Console.Beep(frequency, duration * 6); - break; - } - System.Threading.Thread.Sleep(duration * 3); - } - } - - /// - /// Takes a given System.Text.StringBuilder representing Morse code - /// and audiblize it according to standards. - /// https://www.infoplease.com/encyclopedia/science/engineering/electrical/morse-code - /// Assumes the input value to be in Morse code format already. - /// Use .ToMorseCode() to pre-convert text if needed. - /// - /// The System.Text.StringBuilder text in Morse - /// code format. - /// The beep frequency. - /// The duration of a dot beep in ms. - public static void MorseCodeBeep(this System.Text.StringBuilder str, - int frequency = 999, - int duration = 100) - { - ValidateNoNulls(str, frequency, duration); - MorseCodeBeep(str.ToString(), frequency, duration); - } - #endregion MorseCodeBeep() - - #region Quote() - /// - /// Return the given string encased in requested quotes. - /// Default is Constants.QuoteType.Double. - /// - /// The given string to be quoted. - /// The type of quote to use. Defaults to double. - /// The given string encased in requested quotes. - public static string Quote(this System.String str, - Constants.QuoteType type = - Constants.QuoteType.Double) - { - ValidateNoNulls(str, type); - if (type == Constants.QuoteType.Double) - { - return DoubleQuote(str); - } - return SingleQuote(str); - } - - /// - /// Return the given string encased in requested quotes. - /// Default is Constants.QuoteType.Double. - /// - /// The given string to be quoted. - /// The type of quote to use. Defaults to double. - /// The given string encased in requested quotes. - public static string Quote(this System.Text.StringBuilder str, - Constants.QuoteType type = - Constants.QuoteType.Double) - { - ValidateNoNulls(str, type); - return Quote(str, type); - } - #endregion Quote() - - #region ReplaceTokens() - /// - /// Takes a given string and replaces 1 to n tokens in the string - /// with replacement tokens as defined in the given Dictionary - /// of strings. - /// - /// The System.String object upon which token - /// replacement is to be done. - /// A Dictionary of tokens and replacement - /// strings to be used for replacement. - /// A System.String value with tokens replaced. - public static string ReplaceTokens(this System.String str, - Dictionary tokens) - { - ValidateNoNulls(str, tokens); - string returnValue = str; - foreach (string key in tokens.Keys) - { - returnValue = returnValue.Replace(key, tokens[key]); - } - return returnValue; - } - - /// - /// Takes a given string and replaces 1 to n tokens in the string - /// with replacement tokens as defined in the given Dictionary - /// of strings. - /// - /// The System.Text.StringBuilder upon which - /// token replacement is to be one. - /// A Dictionary of tokens and replacement - /// strings to be used for replacement. - /// A System.Text.StringBuilder value with tokens replaced. - public static string ReplaceTokens(this System.Text.StringBuilder str, - Dictionary tokens) - { - ValidateNoNulls(str, tokens); - return ReplaceTokens(str.ToString(), tokens); - } - #endregion ReplaceTokens() - - #region RemoveExtraSpace() - /// - /// Trims leading and trailing white space and then removes all extra - /// white space in the given System.String object returning a single - /// spaced result. - /// - /// The given System.String object from which - /// extra spaces needs to be removed. - /// The given string object with leading and strailing white - /// space removed and all other spaces reduced to single space. - public static string RemoveExtraSpace(this System.String str) - { - ValidateNoNulls(str); - return System.Text.RegularExpressions.Regex.Replace(str.Trim(), - "\\s+", - " "); - } - - /// - /// Trims leading and trailing white space and then removes all extra - /// white space in the given System.Text.StringBuilder returning a - /// single spaced result. - /// - /// The given System.Text.StringBuilder object from - /// which extra spaces needs to be removed. - /// The given string object with leading and strailing white - /// space removed and all other spaces reduced to single space. - public static string RemoveExtraSpace(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return RemoveExtraSpace(str.ToString()); - } - #endregion RemoveExtraSpace() - - #region Right() - /// - /// Returns text to the right of the index string. Use negative values - /// for occurrence if the occurrence count should start from the end - /// instead of its default from the beginning of the string. - /// - /// A System.String object being searched. - /// The System.String value used as the target - /// of the search. - /// The number of matches to find. - /// Returns text to the right of the index string. Use - /// negative values for occurrence if the occurrence count should - /// start from the end instead of its default from the beginning of - /// the string. - public static string Right( - this System.String str, - string index, - int occurrence = 1) - { - ValidateNoNulls(str, index, occurrence); - if (str.IndexOf(index) >= 0) - { - if (occurrence == 1) - { - return str.Substring(str.IndexOf(index) + index.Length); - } - if (occurrence == -1) - { - return str.Substring(str.LastIndexOf(index) + index.Length); - } - if (occurrence > 1) - { - string remainder = str; - for (int C = 0; C < occurrence; C++) - { - if (remainder.IndexOf(index) == -1) - { - return ""; - } - try - { - remainder = remainder.Substring(remainder.IndexOf(index) + index.Length); - } - catch (Exception ex) - { - return ""; - } - } - return remainder; - } - if (occurrence < -1) - { - string remainder = str; - for (int C = 0; C > occurrence; C--) - { - if (remainder.LastIndexOf(index) == -1) - { - return ""; - } - try - { - remainder = remainder.Substring(0, remainder.LastIndexOf(index)); - } - catch (Exception ex) - { - return ""; - } - } - return str.Substring(remainder.Length + index.Length); - } - } - return ""; - } - - /// - /// Returns text to the right of the index string. Use negative values - /// for occurrence if the occurrence count should start from the end - /// instead of its default from the beginning of the string. - /// - /// A System.String object being searched. - /// The System.String value used as the target - /// of the search. - /// The number of matches to find. - /// Returns text to the right of the index string. Use - /// negative values for occurrence if the occurrence count should - /// start from the end instead of its default from the beginning of - /// the string. - public static string Right( - this System.Text.StringBuilder str, - string index, - int occurrence = 1) - { - ValidateNoNulls(str, index, occurrence); - return Right(str.ToString(), index, occurrence); - } - #endregion Right() - - #region SingleQuote() - /// - /// Return the given string encased in single quotes. - /// - /// The given string to be quoted. - /// The given string encased in single quotes. - public static string SingleQuote(this System.String str) - { - ValidateNoNulls(str); - return ("'" + str + "'"); - } - - /// - /// Return the given string encased in single quotes. - /// - /// The given string to be quoted. - /// The given string encased in single quotes. - public static string SingleQuote(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return SingleQuote(str.ToString()); - } - #endregion SingleQuote() - - #region Singularize() - /// - /// Parses the given string removing multiples of a given character. - /// - /// The string to parse. - /// The character to de-duplicate. - /// Switch to ignore case during comparrison. - /// The given string with multiples of the given character - /// removed. - public static System.String Singularize(this System.String str, - char target, - bool ignoreCase = true) - { - ValidateNoNulls(str, target); - if (str.Length == 1) - { - return str; - } - string result = str[0].ToString(); - if (ignoreCase) - { - for (int C = 1; C < str.Length; C++) - { - if (str[C].ToString().ToLower() - != str[C - 1].ToString().ToLower()) - { - result += str[C]; - } - } - } - else - { - for (int C = 1; C < str.Length; C++) - { - if (str[C]!= str[C - 1]) - { - result += str[C]; - } - } - } - return result; - } - - /// - /// Parses the given string removing multiples of a given character. - /// - /// The string to parse. - /// The character to de-duplicate. - /// Switch to ignore case during comparrison. - /// The given string with multiples of the given character - /// removed. - public static System.String Singularize(this System.Text.StringBuilder str, - char target, - bool ignoreCase = true) - { - ValidateNoNulls(str, target); - return Singularize(str.ToString(), target, ignoreCase); - } - #endregion Singularize() - - #region Substring() - /// - /// Extension method to handle FromHead and FromTail types - /// which allows the caller to return the requested length - /// of characters from the head or the tail of the given - /// string. - /// - /// The given string that is being searched. - /// The requested length of characters to return. - /// Use -1 for max. - /// The type of return string requested. - /// FromHead returns the "length" of characters from the head - /// of the given string. - /// FromTail returns the "length" of characters from the tail of the - /// given string. - public static string Substring(this System.String str, - int length, - Constants.SubstringType type = - Constants.SubstringType.FromHead) - { - Validate(ErrorTypeAll, str, length, type); - if (length == -1) - { - length = int.MaxValue; - } - switch (type) - { - case Constants.SubstringType.FromHead: - if (str.Length < length) - { - return str; - } - else - { - return str.Substring(0, length); - } - break; - case Constants.SubstringType.FromTail: - if (str.Length < length) - { - return str; - } - else - { - return str.Substring(str.Length - length, length); - } - break; - } - return null; - } - - /// - /// Extension method to handle LeftOfIndex and RightOfIndex types - /// which allows the caller to locate a given number of occurrences - /// of a given search string and then return the requested length - /// of characters to either the left or the rigth of the located - /// search index. - /// - /// The given string that is being searched. - /// The requested length of characters to return. - /// Use -1 for max. - /// The string to search for. - /// The type of return string requested. - /// The number of occurrences to match. - /// LeftOfIndex returns the "length" of characters to the LEFT - /// of the located index representing the "occurence"th match of the - /// "index" string. - /// RightOfIndex returns the "length" of characters to the RIGHT - /// of the located index representing the "occurence"th match of the - /// "index" string. - public static string Substring(this System.String str, - int length, - string index, - Constants.SubstringType type = - Constants.SubstringType.LeftOfIndex, - int occurrence = 1) - { - Validate(ErrorTypeAll, str, length, index, type, occurrence); - int offset; - string temp = str; - if (length == -1) - { - length = int.MaxValue; - } - switch (type) - { - case Constants.SubstringType.LeftOfIndex: - if (occurrence <= 0) - { - return null; - } - if (str.IndexOf(index) == -1) - { - return null; - } - for (int C = 0; C < occurrence; C++) - { - temp = temp.Substring(temp.IndexOf(index) + index.Length); - } - offset = str.IndexOf(temp); - temp = str.Substring(0, offset - index.Length); - if (temp.Length <= length) - { - return str.Substring(0, offset - index.Length); - } - else - { - return temp.Substring(temp.Length - length); - } - case Constants.SubstringType.RigthOfIndex: - if (occurrence <= 0) - { - return null; - } - if (str.IndexOf(index) == -1) - { - return null; - } - for (int C = 0; C < occurrence; C++) - { - temp = temp.Substring(temp.IndexOf(index) + index.Length); - } - if (temp.Length <= length) - { - return temp; - } - else - { - return temp.Substring(0, length); - } - break; - } - return null; - } - - /// - /// Extension method to handle FromHead and FromTail types - /// which allows the caller to return the requested length - /// of characters from the head of the given string. - /// - /// The given string that is being searched. - /// The requested length of characters to return. - /// Use -1 for max. - /// The type of return string requested. - /// FromHead returns the "length" of characters from the head - /// of the given string. - /// FromTail returns the "length" of characters from the tail of the - /// given string. - public static string Substring(this System.Text.StringBuilder str, - int length, - Constants.SubstringType type = - Constants.SubstringType.FromHead) - { - Validate(ErrorTypeAll, str, length, type); - return Substring(str.ToString(), - length, - type); - } - - /// - /// Extension method to handle LeftOfIndex and RightOfIndex types - /// which allows the caller to locate a given number of occurrences - /// of a given search string and then return the requested length - /// of characters to either the left or the rigth of the located - /// search index. - /// - /// The given string that is being searched. - /// The requested length of characters to return. - /// Use -1 for max. - /// The string to search for. - /// The type of return string requested. - /// The number of occurrences to match. - /// LeftOfIndex returns the "length" of characters to the LEFT - /// of the located index representing the "occurence"th match of the - /// "index" string. - /// RightOfIndex returns the "length" of characters to the RIGHT - /// of the located index representing the "occurence"th match of the - /// "index" string. - public static string Substring(this System.Text.StringBuilder str, - int length, - string index, - Constants.SubstringType type = - Constants.SubstringType.LeftOfIndex, - int occurrence = 1) - { - Validate(ErrorTypeAll, str, length, index, type, occurrence); - return Substring(str.ToString(), - length, - index, - type, - occurrence); - } - - /// - /// Retrieves a substring from this instance. The substring starts - /// at a specified character position and continues to the end of the - /// string. - /// - /// The StringBuilder source instance. - /// The starting position of the substring - /// selection. - /// A string that is equivalent to the substring that begins - /// at startIndex in this instance, or System.String.Empty if - /// startIndex is equal to the length of this instance. - public static string Substring(this System.Text.StringBuilder str, - int startIndex) - { - Validate(ErrorTypeAll, str, startIndex); - return str.ToString().Substring(startIndex); - } - - /// - /// Retrieves a substring from this instance. The substring starts at - /// a specified character position and has a specified length. - /// - /// The StringBuilder source instance. - /// The starting position of the substring - /// selection. - /// The length of the substring to be selected. - /// A string that is equivalent to the substring of length - /// length that begins at startIndex in this instance, or - /// System.String.Empty if startIndex is equal to the length of this - /// instance and length is zero. - public static string Substring(this System.Text.StringBuilder str, - int startIndex, - int length) - { - Validate(ErrorTypeAll, str, startIndex, length); - return str.ToString().Substring(startIndex, length); - } - #endregion Substring() - - #region TailString() - /// - /// Method to return the tail end of a string following a given string - /// index location e.g. - /// TailString( - /// "https://contoso.sharepoint.us/sites/HomeSite/lists/MyList", - /// "/", - /// 3) - /// would return "sites/HomeSite/lists/MyList". - /// TailString( - /// "https://contoso.sharepoint.us/sites/HomeSite/lists/MyList", - /// "/", - /// 6) - /// would return "MyList" etc. - /// - /// The string to inspect. - /// The substring to locate. - /// The number of times the method needs to - /// locate the index in str. - /// Returns the tail end of a string following a given string - /// index location - public static string TailString(this System.String str, - string index, - int occurrence = 1) - { - Validate(ErrorTypeAll, str, index, occurrence); - int offset; - if (occurrence > 1) - { - string baseStr = str; - while (occurrence > 0) - { - offset = baseStr.IndexOf(index); - if (offset > 0) - { - baseStr = baseStr.Substring(offset + index.Length); - occurrence--; - } - else - { - baseStr = baseStr.Substring(offset + index.Length); - return baseStr; - } - } - } - offset = str.LastIndexOf(index); - if (offset > 0) - { - return str.Substring(offset + index.Length); - } - else - { - return str; - } - } - #endregion - - #region ToBinary() - /// - /// Returns the binary representation of a given string object. - /// - /// The System.String object to convert to binary. - /// - public static string ToBinary(this System.String str) - { - ValidateNoNulls(str); - System.Text.StringBuilder sb = new System.Text.StringBuilder(); - foreach (byte b in System.Text.ASCIIEncoding.UTF8.GetBytes( - str.ToCharArray())) - { - sb.Append(Convert.ToString(b, 2) + " "); - } - return sb.ToString(); - } - - /// - /// Returns the binary representation of a given StringBuilder object. - /// - /// The System.Text.StringBuilder object to convert - /// to binary. - /// - public static string ToBinary(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return ToBinary(str.ToString()); - } - #endregion ToBinary() - - #region ToEnum() - /// - /// Convert a System.String to its Enum value. - /// - /// The enum type. - /// The string to match to an enum. - /// The enum value. - public static T ToEnum(this System.String str) - { - ValidateNoNulls(str); - return (T)Enum.Parse(typeof(T), str); - } - - /// - /// Convert a System.String to its Enum value. - /// - /// The enum type. - /// The string to match to an enum. - /// The enum value. - public static T ToEnum(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return (str.ToString().ToEnum()); - } - #endregion ToEnum() - - #region ToEnumerable() - /// - /// Converts the given querystring to a Dictionary. - /// - /// The given querystring to convert. - /// Defaults to ampersand per W3C standards. - /// Defaults to = per W3C standards. - /// The parsed dictionary containing querystring values. - public static Dictionary QueryStringToDictionary( - this System.String str, - char separator = '&', - char assigner = '=') - { - ValidateNoNulls(str, separator, assigner); - Dictionary result = new Dictionary(); - string query = str.Substring(str.IndexOf('?') + 1); - string[] parts = query.Split(separator); - foreach (string part in parts) - { - string[] pair = part.Split(assigner); - result.Add(pair[0], pair[1]); - } - return result; - } - - /// - /// Converts the given querystring to a Dictionary. - /// - /// The given querystring to convert. - /// Defaults to ampersand per W3C standards. - /// Defaults to = per W3C standards. - /// The parsed dictionary containing querystring values. - public static Dictionary QueryStringToDictionary( - this System.Text.StringBuilder str, - char separator = '&', - char assigner = '=') - { - ValidateNoNulls(str, separator, assigner); - return QueryStringToDictionary(str.ToString(), separator, assigner); - } - - /// - /// Converts the given querystring to a NameValueCollection. - /// - /// The given querystring to convert. - /// Defaults to ampersand per W3C standards. - /// Defaults to = per W3C standards. - /// The parsed NameValueCollection containing querystring - /// values. - public static System.Collections.Specialized.NameValueCollection QueryStringToNameValueCollection( - this System.String str, - char separator = '&', - char assigner = '=') - { - ValidateNoNulls(str, separator, assigner); - System.Collections.Specialized.NameValueCollection nvc = - new System.Collections.Specialized.NameValueCollection(); - foreach (KeyValuePair kvp in QueryStringToDictionary(str)) - { - nvc.Add(kvp.Key, kvp.Value); - } - return nvc; - } - - /// - /// Converts the given querystring to a NameValueCollection. - /// - /// The given querystring to convert. - /// Defaults to ampersand per W3C standards. - /// Defaults to = per W3C standards. - /// The parsed NameValueCollection containing querystring - /// values. - public static System.Collections.Specialized.NameValueCollection QueryStringToNameValueCollection( - this System.Text.StringBuilder str, - char separator = '&', - char assigner = '=') - { - ValidateNoNulls(str, separator, assigner); - return QueryStringToNameValueCollection(str.ToString(), - separator, - assigner); - } - #endregion ToEnumerable() - - #region ToJson() - /// - /// Convert an object to a JSON string. - /// - /// The object type being converted. - /// The object being converted. - /// Options to use for - /// serialization. If none is specified defaults are used. - /// A JSON string representing the given object. - public static string ToJson(this T obj, - JsonSerializerOptions jsonSerializerOptions = null) - { - if (obj == null) - { - return "{}"; - } - if (jsonSerializerOptions == null) - { - jsonSerializerOptions = new JsonSerializerOptions - { - WriteIndented = true, - DefaultIgnoreCondition = JsonIgnoreCondition.Never, - ReferenceHandler = ReferenceHandler.Preserve - }; - } - return JsonSerializer.Serialize(obj, jsonSerializerOptions); - } - #endregion ToJson() - - #region ToMorseCode() - /// - /// Convert given System.String to its Morse code representation. - /// Undefined characters will return in the format: - /// Undefined:char - /// For example: - /// "sos@".ToMorseCode() - /// will return - /// "...---...Undefined:@" - /// - /// The given string to convert to Morse code. - /// Are spaces included in translation. - /// The Morse code represenation of the given string. - public static string ToMorseCode(this System.String str, - bool includeSpaces = true) - { - ValidateNoNulls(str, includeSpaces); - System.Text.StringBuilder returnValue = - new System.Text.StringBuilder(); - foreach (char c in str.ToLower()) - { - if (Constants.MorseCode.TryGetValue(c, out string tempStr)) - { - returnValue.Append(c != ' ' ? tempStr : - (includeSpaces ? tempStr : "")); - } - else - { - returnValue.Append(""); - } - } - return returnValue.ToString(); - } - - /// - /// Convert given System.Text.Stringbuilder object to its Morse code - /// representation. - /// Undefined characters will return in the format: - /// Undefined:char> - /// For example: - /// "sos@".ToMorseCode() - /// will return - /// "...---...Undefined:@" - /// - /// The given string to convert to Morse code. - /// Are spaces included in translation. - /// The Morse code represenation of the given string. - public static string ToMorseCode(this System.Text.StringBuilder str, - bool includeSpaces = true) - { - ValidateNoNulls(str, includeSpaces); - return (str.ToString()); - } - #endregion ToMorseCode() - - #region ToEnglishAlphaChars() - /// - /// Convert all non-English characters in a given string to their - /// English equivalent characters. - /// - /// The target string to convert. - /// Converted English equivalent string. - public static string ToEnglishAlphaChars(this string str) - { - StringBuilder sb = new StringBuilder(str); - return sb.ToEnglishAlphaChars().ToString(); - } - - /// - /// Convert all non-English characters in a given StringBuilder to - /// their English equivalent characters. - /// - /// The target StringBuilder to convert. - /// Converted English equivalent StringBuilder. - public static StringBuilder ToEnglishAlphaChars(this StringBuilder sb) - { - sb = sb.Replace('Á', 'A'); - sb = sb.Replace('Ă', 'A'); - sb = sb.Replace('Â', 'A'); - sb = sb.Replace('Ä', 'A'); - sb = sb.Replace('À', 'A'); - sb = sb.Replace('Ā', 'A'); - sb = sb.Replace('Ą', 'A'); - sb = sb.Replace('Å', 'A'); - sb = sb.Replace('Ã', 'A'); - sb = sb.Replace('Æ', 'A'); - sb = sb.Replace('Ć', 'C'); - sb = sb.Replace('Č', 'C'); - sb = sb.Replace('Ç', 'C'); - sb = sb.Replace('Ĉ', 'C'); - sb = sb.Replace('Ċ', 'C'); - sb = sb.Replace('Ď', 'D'); - sb = sb.Replace('Đ', 'D'); - sb = sb.Replace('É', 'E'); - sb = sb.Replace('Ĕ', 'E'); - sb = sb.Replace('Ě', 'E'); - sb = sb.Replace('Ê', 'E'); - sb = sb.Replace('Ë', 'E'); - sb = sb.Replace('Ė', 'E'); - sb = sb.Replace('È', 'E'); - sb = sb.Replace('Ē', 'E'); - sb = sb.Replace('Ę', 'E'); - sb = sb.Replace('Ŋ', 'N'); - sb = sb.Replace('Ð', 'E'); - sb = sb.Replace('Ğ', 'G'); - sb = sb.Replace('Ģ', 'G'); - sb = sb.Replace('Ĝ', 'G'); - sb = sb.Replace('Ġ', 'G'); - sb = sb.Replace('Ĥ', 'H'); - sb = sb.Replace('Ħ', 'H'); - sb = sb.Replace('Í', 'I'); - sb = sb.Replace('Ĭ', 'I'); - sb = sb.Replace('Î', 'I'); - sb = sb.Replace('Ï', 'I'); - sb = sb.Replace('İ', 'I'); - sb = sb.Replace('Ì', 'I'); - sb = sb.Replace('Ī', 'I'); - sb = sb.Replace('Į', 'I'); - sb = sb.Replace('Ĩ', 'I'); - sb = sb.Replace('Ĵ', 'J'); - sb = sb.Replace('Ķ', 'K'); - sb = sb.Replace('Ĺ', 'L'); - sb = sb.Replace('Ľ', 'L'); - sb = sb.Replace('Ļ', 'L'); - sb = sb.Replace('Ŀ', 'L'); - sb = sb.Replace('Ł', 'L'); - sb = sb.Replace('IJ', 'I'); - sb = sb.Replace('Œ', 'O'); - sb = sb.Replace('Ń', 'N'); - sb = sb.Replace('Ň', 'N'); - sb = sb.Replace('Ņ', 'N'); - sb = sb.Replace('Ñ', 'N'); - sb = sb.Replace('Ó', 'O'); - sb = sb.Replace('Ŏ', 'O'); - sb = sb.Replace('Ô', 'O'); - sb = sb.Replace('Ö', 'O'); - sb = sb.Replace('Ò', 'O'); - sb = sb.Replace('Ō', 'O'); - sb = sb.Replace('Ø', 'O'); - sb = sb.Replace('Õ', 'O'); - sb = sb.Replace('Ő', 'O'); - sb = sb.Replace('Ŕ', 'R'); - sb = sb.Replace('Ř', 'R'); - sb = sb.Replace('Ŗ', 'R'); - sb = sb.Replace('Ś', 'S'); - sb = sb.Replace('Š', 'S'); - sb = sb.Replace('Ş', 'S'); - sb = sb.Replace('Ŝ', 'S'); - sb = sb.Replace('Ť', 'T'); - sb = sb.Replace('Ţ', 'T'); - sb = sb.Replace('Ŧ', 'T'); - sb = sb.Replace('Þ', 'P'); - sb = sb.Replace('Ů', 'U'); - sb = sb.Replace('Ú', 'U'); - sb = sb.Replace('Ŭ', 'U'); - sb = sb.Replace('Û', 'U'); - sb = sb.Replace('Ü', 'U'); - sb = sb.Replace('Ű', 'U'); - sb = sb.Replace('Ù', 'U'); - sb = sb.Replace('Ū', 'U'); - sb = sb.Replace('Ų', 'U'); - sb = sb.Replace('Ũ', 'U'); - sb = sb.Replace('Ŵ', 'W'); - sb = sb.Replace('Ý', 'Y'); - sb = sb.Replace('Ŷ', 'Y'); - sb = sb.Replace('Ÿ', 'Y'); - sb = sb.Replace('Ź', 'Z'); - sb = sb.Replace('Ž', 'Z'); - sb = sb.Replace('Ż', 'Z'); - sb = sb.Replace('á', 'a'); - sb = sb.Replace('ă', 'a'); - sb = sb.Replace('â', 'a'); - sb = sb.Replace('ä', 'a'); - sb = sb.Replace('à', 'a'); - sb = sb.Replace('ā', 'a'); - sb = sb.Replace('ą', 'a'); - sb = sb.Replace('å', 'a'); - sb = sb.Replace('ã', 'a'); - sb = sb.Replace('æ', 'a'); - sb = sb.Replace('ć', 'c'); - sb = sb.Replace('č', 'c'); - sb = sb.Replace('ç', 'c'); - sb = sb.Replace('ĉ', 'c'); - sb = sb.Replace('ċ', 'c'); - sb = sb.Replace('ď', 'd'); - sb = sb.Replace('đ', 'd'); - sb = sb.Replace('ı', 'i'); - sb = sb.Replace('é', 'e'); - sb = sb.Replace('ĕ', 'e'); - sb = sb.Replace('ě', 'e'); - sb = sb.Replace('ê', 'e'); - sb = sb.Replace('ë', 'e'); - sb = sb.Replace('ė', 'e'); - sb = sb.Replace('è', 'e'); - sb = sb.Replace('ē', 'e'); - sb = sb.Replace('ę', 'e'); - sb = sb.Replace('ŋ', 'n'); - sb = sb.Replace('ð', 'e'); - sb = sb.Replace('ğ', 'g'); - sb = sb.Replace('ģ', 'g'); - sb = sb.Replace('ĝ', 'g'); - sb = sb.Replace('ġ', 'g'); - sb = sb.Replace('ĥ', 'h'); - sb = sb.Replace('ħ', 'h'); - sb = sb.Replace('í', 'i'); - sb = sb.Replace('ĭ', 'i'); - sb = sb.Replace('î', 'i'); - sb = sb.Replace('ï', 'i'); - sb = sb.Replace('ì', 'i'); - sb = sb.Replace('ī', 'i'); - sb = sb.Replace('į', 'i'); - sb = sb.Replace('ĩ', 'i'); - sb = sb.Replace('ĵ', 'j'); - sb = sb.Replace('ķ', 'k'); - sb = sb.Replace('ĸ', 'k'); - sb = sb.Replace('ĺ', 'l'); - sb = sb.Replace('ľ', 'l'); - sb = sb.Replace('ļ', 'l'); - sb = sb.Replace('ŀ', 'l'); - sb = sb.Replace('ł', 'l'); - sb = sb.Replace('ij', 'i'); - sb = sb.Replace('œ', 'o'); - sb = sb.Replace('ſ', 's'); - sb = sb.Replace('ń', 'n'); - sb = sb.Replace('ň', 'n'); - sb = sb.Replace('ņ', 'n'); - sb = sb.Replace('ʼn', 'n'); - sb = sb.Replace('ñ', 'n'); - sb = sb.Replace('ó', 'o'); - sb = sb.Replace('ŏ', 'o'); - sb = sb.Replace('ô', 'o'); - sb = sb.Replace('ö', 'o'); - sb = sb.Replace('ò', 'o'); - sb = sb.Replace('ō', 'o'); - sb = sb.Replace('ø', 'o'); - sb = sb.Replace('õ', 'o'); - sb = sb.Replace('ő', 'o'); - sb = sb.Replace('ŕ', 'r'); - sb = sb.Replace('ř', 'r'); - sb = sb.Replace('ŗ', 'r'); - sb = sb.Replace('ś', 's'); - sb = sb.Replace('š', 's'); - sb = sb.Replace('ş', 's'); - sb = sb.Replace('ŝ', 's'); - sb = sb.Replace('ß', 's'); - sb = sb.Replace('ť', 't'); - sb = sb.Replace('ţ', 't'); - sb = sb.Replace('ŧ', 't'); - sb = sb.Replace('þ', 'p'); - sb = sb.Replace('ů', 'u'); - sb = sb.Replace('ú', 'u'); - sb = sb.Replace('ŭ', 'u'); - sb = sb.Replace('û', 'u'); - sb = sb.Replace('ü', 'u'); - sb = sb.Replace('ű', 'u'); - sb = sb.Replace('ù', 'u'); - sb = sb.Replace('ū', 'u'); - sb = sb.Replace('ų', 'u'); - sb = sb.Replace('ũ', 'u'); - sb = sb.Replace('ŵ', 'w'); - sb = sb.Replace('ý', 'y'); - sb = sb.Replace('ŷ', 'y'); - sb = sb.Replace('ÿ', 'y'); - sb = sb.Replace('ź', 'z'); - sb = sb.Replace('ž', 'z'); - sb = sb.Replace('ż', 'z'); - return sb; - } - #endregion ToEnglishAlphaChars() - - #region TrimLength() - /// - /// Returns part of the given System.String object tuncated to - /// the requested length minus the length of the suffix. - /// If the string is null or empty, it returns said value. - /// If the string is shorter than the requested length, it returns - /// the whole string. - /// - /// The given System.String object. - /// The requested length of the return string. - /// The string appended to the end of the - /// returned string. Default value is "..." - /// Returns part of the given System.String object tuncated - /// to the requested length minus the length of the suffix. - public static string TrimLength(this System.String str, - int length, - string suffix = "...") - { - ValidateNoNulls(str, length, suffix); - return (string.IsNullOrEmpty(str) || str.Length < length ? str : - (str.Substring(0, length - suffix.Length) + suffix)); - } - - /// - /// Returns part of the given System.Text.StringBuilder object - /// tuncated to the requested length minus the length of the - /// suffix. - /// If the string is null or empty, it returns said value. - /// If the string is shorter than the requested length, it returns - /// the whole string. - /// - /// The given System.Text.StringBuilder object. - /// The requested length of the return string. - /// The string appended to the end of the - /// returned string. Default value is "..." - /// Returns part of the given System.String object tuncated - /// to the requested length minus the length of the suffix. - public static string TrimLength(this System.Text.StringBuilder str, - int length, - string suffix = "...") - { - ValidateNoNulls(str, length, suffix); - return TrimLength(str.ToString(), length, suffix); - } - #endregion TrimLength() - - #region TrimStart() - /// - /// Trims the starting target string from the current string. - /// - /// The current string to be trimmed. - /// The target string to trim off the current - /// string. - /// The current string minus the target string IF the current - /// string begins with the target string, else it returns the current - /// string. - public static string TrimStart(this System.String str, - string target) - { - ValidateNoNulls(str, target); - if (str.BeginsWith(target)) - { - return str.Substring(target.Length); - } - return str; - } - #endregion TrimStart() - - #region Words() - /// - /// Returns the number of words in the given string object. - /// - /// A System.String object for which to count - /// words. - /// The number of words in the given object. - public static int Words(this System.String str) - { - ValidateNoNulls(str); - return str.Split(new char[] { ' ', - '.', - '?', - '!', - ';' }, - StringSplitOptions.RemoveEmptyEntries) - .Length; - } - - /// - /// Returns the number of words in the given string builder object. - /// - /// A System.Text.StringBuilder object for which - /// to count words. - /// The number of words in the given object. - public static int Words(this System.Text.StringBuilder str) - { - ValidateNoNulls(str); - return Words(str.ToString()); - } - #endregion Words() - - //public static bool ToEmailSafeTextFile(this System.String filePath) - //{ - // if (System.IO.File.Exists(filePath)) - // { - // System.IO.File.WriteAllText( - // filePath + ".txt", - // Convert.ToBase64String( - // System.IO.File.ReadAllBytes(filePath))); - // return true; - // } - // return false; - //} - - //public static bool FromEmailSafeTextFile(this System.String filePath) - //{ - // if (System.IO.File.Exists(filePath)) - // { - // System.IO.File.WriteAllBytes( - // filePath.ToLower() - // .TrimEnd(new char[] { - // '.', - // 't', - // 'x', - // 't'}), - // Convert.FromBase64String( - // System.IO.File.ReadAllText(filePath))); - // return true; - // } - // return false; - //} - } -} diff --git a/Classes/System.Text.StringBuilder.cs b/Classes/System.Text.StringBuilder.cs deleted file mode 100644 index 5985d54..0000000 --- a/Classes/System.Text.StringBuilder.cs +++ /dev/null @@ -1,81 +0,0 @@ -/// -/// Author: Cornelius J. van Dyk blog.cjvandyk.com @cjvandyk -/// This code is provided under GNU GPL 3.0 and is a copyrighted work of the -/// author and contributors. Please see: -/// https://github.com/cjvandyk/Extensions/blob/main/LICENSE -/// - -using System; -using static Extensions.Core; - -namespace Extensions -{ - /// - /// Extension methods for the System.Text.StringBuilder - /// classes. - /// - [Serializable] - public static partial class StringBuilderExtensions - { - #region IndexOf() - /// - /// Returns the offset location of the index value. - /// - /// - /// - /// - /// - /// The integer offset of the index string in the source - /// StringBuilder object. - public static int IndexOf(this System.Text.StringBuilder str, - string index, - int startindex = 0, - bool ignorecase = true) - { - ValidateNoNulls(str, index); - int counter; - int targetlength = index.Length; - if (ignorecase) - { - for (int C = startindex; C < ((str.Length - targetlength) + 1); C++) - { - if (Char.ToLower(str[C]) == Char.ToLower(index[0])) - { - counter = 1; - while ((counter < targetlength) && - (Char.ToLower(str[C + counter]) == Char.ToLower(index[counter]))) - { - counter++; - } - if (counter == targetlength) - { - return C; - } - } - } - return -1; - } - else - { - for (int C = startindex; C < ((str.Length - targetlength) + 1); C++) - { - if (str[C] == index[0]) - { - counter = 1; - while ((counter < targetlength) && (str[C + counter] == index[counter])) - { - counter++; - } - if (counter == targetlength) - { - return C; - } - } - } - } - return -1; - } - #endregion IndexOf() - - } -} diff --git a/Directory.Build.props b/Directory.Build.props index de2c5a9..92b4b0c 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,6 +1,6 @@ - 5.6.800 + 6.0.800 latest Cornelius J. van Dyk Copyright © 2020-2024 diff --git a/Extensions.csproj b/Extensions.csproj index 63f3f5a..ec3c9e3 100644 --- a/Extensions.csproj +++ b/Extensions.csproj @@ -75,6 +75,7 @@ + @@ -90,6 +91,7 @@ + @@ -105,6 +107,7 @@ + @@ -140,27 +143,12 @@ - - - - - - - - - + + PreserveNewest - - - - - - 7.4.0 - - \ No newline at end of file diff --git a/Extensions.sln b/Extensions.sln index 783d5de..9ec3257 100644 --- a/Extensions.sln +++ b/Extensions.sln @@ -19,6 +19,20 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BuildBump", "BuildBump\Buil {331A7C3B-45DC-4E04-85BF-DE1934C6B3FA} = {331A7C3B-45DC-4E04-85BF-DE1934C6B3FA} EndProjectSection EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "BlackCheetah", "..\BlackCheetah\BlackCheetah.csproj", "{47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TESTING", "TESTING\TESTING.csproj", "{653D447D-2324-4A7E-8E13-BAA50606C0C8}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Extensions.Graph", "Extensions.Graph\Extensions.Graph.csproj", "{0FA42816-F785-4AD6-8E67-98FAE854CE21}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Extensions.Core", "Extensions.Core\Extensions.Core.csproj", "{1097ADA1-5FA3-4E13-92AF-57104015DE8C}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Extensions.Constants", "Extensions.Constants\Extensions.Constants.csproj", "{6A69FE24-D534-42D4-99D4-7C95091AE703}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Extensions.Identity", "Extensions.Identity\Extensions.Identity.csproj", "{CF697F0A-97EE-4C75-B0B3-CBDC421A3476}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Extensions.String", "Extensions.String\Extensions.String.csproj", "{526043BC-A852-4377-A894-4928BE7C68A3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -77,6 +91,90 @@ Global {F6C0B61D-81B4-48EB-ABD4-E8680A9F9992}.Release|arm64.Build.0 = Release|Any CPU {F6C0B61D-81B4-48EB-ABD4-E8680A9F9992}.Release|x86.ActiveCfg = Release|Any CPU {F6C0B61D-81B4-48EB-ABD4-E8680A9F9992}.Release|x86.Build.0 = Release|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Debug|arm64.ActiveCfg = Debug|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Debug|arm64.Build.0 = Debug|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Debug|x86.ActiveCfg = Debug|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Debug|x86.Build.0 = Debug|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Release|Any CPU.Build.0 = Release|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Release|arm64.ActiveCfg = Release|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Release|arm64.Build.0 = Release|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Release|x86.ActiveCfg = Release|Any CPU + {47E65AE4-8DC4-46F3-A4CA-A23F42C869C3}.Release|x86.Build.0 = Release|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Debug|Any CPU.Build.0 = Debug|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Debug|arm64.ActiveCfg = Debug|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Debug|arm64.Build.0 = Debug|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Debug|x86.ActiveCfg = Debug|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Debug|x86.Build.0 = Debug|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Release|Any CPU.ActiveCfg = Release|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Release|Any CPU.Build.0 = Release|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Release|arm64.ActiveCfg = Release|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Release|arm64.Build.0 = Release|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Release|x86.ActiveCfg = Release|Any CPU + {653D447D-2324-4A7E-8E13-BAA50606C0C8}.Release|x86.Build.0 = Release|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Debug|arm64.ActiveCfg = Debug|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Debug|arm64.Build.0 = Debug|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Debug|x86.ActiveCfg = Debug|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Debug|x86.Build.0 = Debug|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Release|Any CPU.Build.0 = Release|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Release|arm64.ActiveCfg = Release|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Release|arm64.Build.0 = Release|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Release|x86.ActiveCfg = Release|Any CPU + {0FA42816-F785-4AD6-8E67-98FAE854CE21}.Release|x86.Build.0 = Release|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Debug|arm64.ActiveCfg = Debug|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Debug|arm64.Build.0 = Debug|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Debug|x86.ActiveCfg = Debug|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Debug|x86.Build.0 = Debug|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Release|Any CPU.Build.0 = Release|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Release|arm64.ActiveCfg = Release|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Release|arm64.Build.0 = Release|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Release|x86.ActiveCfg = Release|Any CPU + {1097ADA1-5FA3-4E13-92AF-57104015DE8C}.Release|x86.Build.0 = Release|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Debug|arm64.ActiveCfg = Debug|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Debug|arm64.Build.0 = Debug|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Debug|x86.ActiveCfg = Debug|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Debug|x86.Build.0 = Debug|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Release|Any CPU.Build.0 = Release|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Release|arm64.ActiveCfg = Release|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Release|arm64.Build.0 = Release|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Release|x86.ActiveCfg = Release|Any CPU + {6A69FE24-D534-42D4-99D4-7C95091AE703}.Release|x86.Build.0 = Release|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Debug|Any CPU.Build.0 = Debug|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Debug|arm64.ActiveCfg = Debug|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Debug|arm64.Build.0 = Debug|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Debug|x86.ActiveCfg = Debug|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Debug|x86.Build.0 = Debug|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Release|Any CPU.ActiveCfg = Release|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Release|Any CPU.Build.0 = Release|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Release|arm64.ActiveCfg = Release|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Release|arm64.Build.0 = Release|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Release|x86.ActiveCfg = Release|Any CPU + {CF697F0A-97EE-4C75-B0B3-CBDC421A3476}.Release|x86.Build.0 = Release|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Debug|arm64.ActiveCfg = Debug|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Debug|arm64.Build.0 = Debug|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Debug|x86.ActiveCfg = Debug|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Debug|x86.Build.0 = Debug|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Release|Any CPU.Build.0 = Release|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Release|arm64.ActiveCfg = Release|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Release|arm64.Build.0 = Release|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Release|x86.ActiveCfg = Release|Any CPU + {526043BC-A852-4377-A894-4928BE7C68A3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/GlobalSuppressions.cs b/GlobalSuppressions.cs index e2059c9..79c6d21 100644 --- a/GlobalSuppressions.cs +++ b/GlobalSuppressions.cs @@ -16,9 +16,11 @@ [assembly: SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "CvD")] [assembly: SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "CvD")] [assembly: SuppressMessage("Maintainability", "CA1507:Use nameof to express symbol names", Justification = "CvD")] +[assembly: SuppressMessage("Performance", "CA1845:Use span-based 'string.Concat'", Justification = "CvD")] [assembly: SuppressMessage("Style", "IDE0017:Simplify object initialization", Justification = "CvD")] [assembly: SuppressMessage("Style", "IDE0031:Use null propagation", Justification = "CvD")] [assembly: SuppressMessage("Style", "IDE0035:Unreachable code detected", Justification = "CvD")] +[assembly: SuppressMessage("Style", "IDE0057:Use range operator", Justification = "CvD")] [assembly: SuppressMessage("Style", "IDE0059:Unnecessary assignment of a value", Justification = "CvD")] [assembly: SuppressMessage("Style", "IDE0071:Simplify interpolation", Justification = "CvD")] [assembly: SuppressMessage("Style", "IDE0074:Use compound assignment", Justification = "CvD")] diff --git a/NuGet/Extensions.Constants.6.0.800.nupkg b/NuGet/Extensions.Constants.6.0.800.nupkg index 39b5f7e..3905552 100644 Binary files a/NuGet/Extensions.Constants.6.0.800.nupkg and b/NuGet/Extensions.Constants.6.0.800.nupkg differ diff --git a/NuGet/Extensions.Constants.6.0.800.snupkg b/NuGet/Extensions.Constants.6.0.800.snupkg index 9915490..1e2e981 100644 Binary files a/NuGet/Extensions.Constants.6.0.800.snupkg and b/NuGet/Extensions.Constants.6.0.800.snupkg differ diff --git a/NuGet/Extensions.Core.6.0.800.nupkg b/NuGet/Extensions.Core.6.0.800.nupkg deleted file mode 100644 index 7a618a1..0000000 Binary files a/NuGet/Extensions.Core.6.0.800.nupkg and /dev/null differ diff --git a/NuGet/Extensions.Core.6.0.800.snupkg b/NuGet/Extensions.Core.6.0.800.snupkg deleted file mode 100644 index 92b96ef..0000000 Binary files a/NuGet/Extensions.Core.6.0.800.snupkg and /dev/null differ diff --git a/NuGet/Extensions.Core.cs.6.0.800.nupkg b/NuGet/Extensions.Core.cs.6.0.800.nupkg index 59eb342..dd84e4e 100644 Binary files a/NuGet/Extensions.Core.cs.6.0.800.nupkg and b/NuGet/Extensions.Core.cs.6.0.800.nupkg differ diff --git a/NuGet/Extensions.Core.cs.6.0.800.snupkg b/NuGet/Extensions.Core.cs.6.0.800.snupkg index fe538e8..ab8d9b1 100644 Binary files a/NuGet/Extensions.Core.cs.6.0.800.snupkg and b/NuGet/Extensions.Core.cs.6.0.800.snupkg differ diff --git a/NuGet/Extensions.Graph.6.0.800.nupkg b/NuGet/Extensions.Graph.6.0.800.nupkg index dee3ccb..0e97055 100644 Binary files a/NuGet/Extensions.Graph.6.0.800.nupkg and b/NuGet/Extensions.Graph.6.0.800.nupkg differ diff --git a/NuGet/Extensions.Graph.6.0.800.snupkg b/NuGet/Extensions.Graph.6.0.800.snupkg index 33062f9..d0afa55 100644 Binary files a/NuGet/Extensions.Graph.6.0.800.snupkg and b/NuGet/Extensions.Graph.6.0.800.snupkg differ diff --git a/NuGet/Extensions.Identity.6.0.800.nupkg b/NuGet/Extensions.Identity.6.0.800.nupkg index 9318866..cc1d36b 100644 Binary files a/NuGet/Extensions.Identity.6.0.800.nupkg and b/NuGet/Extensions.Identity.6.0.800.nupkg differ diff --git a/NuGet/Extensions.Identity.6.0.800.snupkg b/NuGet/Extensions.Identity.6.0.800.snupkg index 3f60060..01dc778 100644 Binary files a/NuGet/Extensions.Identity.6.0.800.snupkg and b/NuGet/Extensions.Identity.6.0.800.snupkg differ diff --git a/NuGet/Extensions.String.6.0.800.nupkg b/NuGet/Extensions.String.6.0.800.nupkg deleted file mode 100644 index 331f3f0..0000000 Binary files a/NuGet/Extensions.String.6.0.800.nupkg and /dev/null differ diff --git a/NuGet/Extensions.String.6.0.800.snupkg b/NuGet/Extensions.String.6.0.800.snupkg deleted file mode 100644 index 6d54514..0000000 Binary files a/NuGet/Extensions.String.6.0.800.snupkg and /dev/null differ diff --git a/NuGet/Extensions.String.cs.6.0.800.nupkg b/NuGet/Extensions.String.cs.6.0.800.nupkg index 99d5c3c..24afcb2 100644 Binary files a/NuGet/Extensions.String.cs.6.0.800.nupkg and b/NuGet/Extensions.String.cs.6.0.800.nupkg differ diff --git a/NuGet/Extensions.String.cs.6.0.800.snupkg b/NuGet/Extensions.String.cs.6.0.800.snupkg index 6f94958..2e5d785 100644 Binary files a/NuGet/Extensions.String.cs.6.0.800.snupkg and b/NuGet/Extensions.String.cs.6.0.800.snupkg differ diff --git a/NuGet/Extensions.cs.6.0.800.nupkg b/NuGet/Extensions.cs.6.0.800.nupkg new file mode 100644 index 0000000..e6f6451 Binary files /dev/null and b/NuGet/Extensions.cs.6.0.800.nupkg differ diff --git a/NuGet/Extensions.cs.6.0.800.snupkg b/NuGet/Extensions.cs.6.0.800.snupkg new file mode 100644 index 0000000..7632ce0 Binary files /dev/null and b/NuGet/Extensions.cs.6.0.800.snupkg differ diff --git a/TESTING/Program.cs b/TESTING/Program.cs index fab630c..4f93b06 100644 --- a/TESTING/Program.cs +++ b/TESTING/Program.cs @@ -6,14 +6,15 @@ /// author and contributors. Please see: /// https://github.com/cjvandyk/Extensions/blob/main/LICENSE /// +using Microsoft.Extensions.Logging; using System; using System.Collections.Generic; using System.Linq; -using Extensions; -using Microsoft.Graph; -using static Extensions.Core; -using static System.Logit; +//using Extensions; +//using Microsoft.Graph; +//using static Extensions.Core; +//using static System.Logit; namespace TESTING { @@ -29,163 +30,165 @@ class Program static void Main(string[] args) { - Inf("Testing"); - - //Call the imported function with the cursor's current position - uint X = (uint)System.Windows.Forms.Cursor.Position.X; - uint Y = (uint)System.Windows.Forms.Cursor.Position.Y; - Random random = new Random(27); - for (int C = 0; C < 10000; C++) - { - System.Threading.Thread.Sleep(random.Next(2000, 5000)); - mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 80, 50, 0, 0); - } - - var auth = Extensions.Identity.AuthMan.GetAuth("tenantid", "appid", "thumbprint", "tenantstring"); - //bool[] b1 = new bool[] { true, false, false, true }; - //bool[] b2 = new bool[] { true, false, false, true }; - //Mersenne64.GreaterThan(ref b1, ref b2); - //Mersenne64 m = new Mersenne64(new bool[] { true, false, true, false, true }); - //bool[] result = m.Mod(new bool[] { true, true, true }); - ////If a number n is not a prime, it can be factored into two factors a and b: - ////n = a * b - ////Now a and b can't be both greater than the square root of n, since then the - ////product a * b would be greater than sqrt(n) * sqrt(n) = n. So in any factorization - ////of n, at least one of the factors must be smaller than the square root of n, and if - ////we can't find any factors less than or equal to the square root, n must be a prime. - ////System.Numerics.BigInteger big = 0; - ////UInt64 big = (UInt64)Math.Pow(2, 82589933); - ////for (long C = 0; C < 82589933; C++) - ////{ - //// big = big * 2; - ////} - //long l = 2; - ////Console.WriteLine($"{l} {l.IsEven()}"); - ////Console.WriteLine($"{l} {l.IsOdd()}"); - ////l = 6; - ////Console.WriteLine($"{l} {l.IsEven()}"); - ////Console.WriteLine($"{l} {l.IsOdd()}"); - //////553:17 vs 17:10 - - //System.Numerics.BigInteger bint = new System.Numerics.BigInteger(); - //for (System.Numerics.BigInteger C = 11; C < 1000000000; C++) - //{ - // bint = C * C; - // if (((int)(bint.ToString().Length /2) + 0) < C.ToString().Length) - // { - // Console.WriteLine($"C:[{C.ToString().Length}] Value:[{bint.ToString().Length}]"); - // } - //} + Console.WriteLine("."); - ////System.Numerics.BigInteger big = new System.Numerics.BigInteger(); - //int big = 1234567890; - //Console.WriteLine(Convert.ToString(big, 2)); - //Console.WriteLine(Mersenne32.BaseConverter.ToBinary(big)); - //Console.WriteLine(Mersenne32.BaseConverter.Sqrt(big)); + //Inf("Testing"); - //System.DateTime startBitArray = System.DateTime.Now; - //bool[] bits = new bool[25000000]; - //for (int C = 0; C < 25000000; C++) + ////Call the imported function with the cursor's current position + //uint X = (uint)System.Windows.Forms.Cursor.Position.X; + //uint Y = (uint)System.Windows.Forms.Cursor.Position.Y; + //Random random = new Random(27); + //for (int C = 0; C < 10000; C++) //{ - // bits[C] = true; + // System.Threading.Thread.Sleep(random.Next(2000, 5000)); + // mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, 80, 50, 0, 0); //} - //System.DateTime stopBitArray = System.DateTime.Now; - //System.Numerics.BigInteger bigInteger;// = System.Numerics.BigInteger.Parse("1234567890"); - //System.Numerics.BigInteger bigSquare; - //System.Text.StringBuilder bigString = new System.Text.StringBuilder(); - //System.DateTime startString = System.DateTime.Now; - //for (int C = 1; C <= 1000000; C++) - //{ - // bigString.Append("1234567890"); - // //string s = String.Format("{0:n0}", bigString.Length) - // //Console.WriteLine($"{System.String.Format("{0:n0}", bigString.Length)} digits"); - //} - //System.DateTime stopString = System.DateTime.Now; - //bigInteger = System.Numerics.BigInteger.Parse(bigString.ToString()); - //System.DateTime stopInt = System.DateTime.Now; - //bigSquare = Mersenne32.BaseConverter.Sqrt(bigInteger); - //System.DateTime stopSquare = System.DateTime.Now; - //Console.WriteLine($"Build string:{(stopString - startString)}"); - //Console.WriteLine($"Create int:{(stopInt - stopString)}"); - //Console.WriteLine($"Calc sqrt:{(stopSquare - stopInt)}"); - //Console.WriteLine($"[{bigString.Length}][{bigSquare.ToString().Length}]"); - - //for (int C = 1; C <= 1000; C++) - //{ - // for (int repeat = 0; repeat < C; repeat++) - // { - // //bigString += "1234567890"; - // } - // //bigInteger = System.Numerics.BigInteger.Parse(bigString); - // //bigSquare = Mersenne32.BaseConverter.Sqrt(bigInteger); - // Console.WriteLine($"[{bigString.Length}][{bigSquare.ToString().Length}]"); - //} + //var auth = Extensions.Identity.AuthMan.GetAuth("tenantid", "appid", "thumbprint", "tenantstring"); + ////bool[] b1 = new bool[] { true, false, false, true }; + ////bool[] b2 = new bool[] { true, false, false, true }; + ////Mersenne64.GreaterThan(ref b1, ref b2); + ////Mersenne64 m = new Mersenne64(new bool[] { true, false, true, false, true }); + ////bool[] result = m.Mod(new bool[] { true, true, true }); + //////If a number n is not a prime, it can be factored into two factors a and b: + //////n = a * b + //////Now a and b can't be both greater than the square root of n, since then the + //////product a * b would be greater than sqrt(n) * sqrt(n) = n. So in any factorization + //////of n, at least one of the factors must be smaller than the square root of n, and if + //////we can't find any factors less than or equal to the square root, n must be a prime. + //////System.Numerics.BigInteger big = 0; + //////UInt64 big = (UInt64)Math.Pow(2, 82589933); + //////for (long C = 0; C < 82589933; C++) + //////{ + ////// big = big * 2; + //////} + ////long l = 2; + //////Console.WriteLine($"{l} {l.IsEven()}"); + //////Console.WriteLine($"{l} {l.IsOdd()}"); + //////l = 6; + //////Console.WriteLine($"{l} {l.IsEven()}"); + //////Console.WriteLine($"{l} {l.IsOdd()}"); + ////////553:17 vs 17:10 - //Mersenne32.BaseConverter.Convert(10, 2, "16"); + ////System.Numerics.BigInteger bint = new System.Numerics.BigInteger(); + ////for (System.Numerics.BigInteger C = 11; C < 1000000000; C++) + ////{ + //// bint = C * C; + //// if (((int)(bint.ToString().Length /2) + 0) < C.ToString().Length) + //// { + //// Console.WriteLine($"C:[{C.ToString().Length}] Value:[{bint.ToString().Length}]"); + //// } + ////} - //bool prime = false; - //System.UInt64 bi = 2; - //long evenPrime = 0; - //long oddPrime = 0; - //for (System.UInt64 C = 1; C < 1000; C++) - //{ - // prime = (bi - 1).IsPrime(); - // if (prime) - // { - // if ((C % 2) == 0) - // { - // evenPrime++; - // } - // else - // { - // oddPrime++; - // } - // } - // Console.WriteLine($"{C}:{(bi - 1)}: {prime} (Even:{evenPrime} Odd:{oddPrime}"); - // if (C == 60) - // { - // Console.WriteLine("Here"); - // } - // bi = bi * 2; - //} - //((System.Numerics.BigInteger)99).IsPrime(); - //l.GetNthPrimeAsync(4227946); - //TimeSpan ts; - //System.DateTime start; - //start = System.DateTime.Now; - //Console.WriteLine(start); - //Console.WriteLine(l.GetNthPrimeAsync(10000)); - //ts = System.DateTime.Now - start; - //Console.WriteLine(ts.TotalSeconds); - //start = System.DateTime.Now; - //Console.WriteLine(start); - //Console.WriteLine(l.GetNthPrime(10000)); - //ts = System.DateTime.Now - start; - //Console.WriteLine(ts.TotalSeconds); - //start = System.DateTime.Now; - //Console.WriteLine(start); - //Console.WriteLine(l.GetNthPrimeAsync(100000)); - //ts = System.DateTime.Now - start; - //Console.WriteLine(ts.TotalSeconds); - //start = System.DateTime.Now; - //Console.WriteLine(start); - //Console.WriteLine(l.GetNthPrime(100000)); - //ts = System.DateTime.Now - start; - //Console.WriteLine(ts.TotalSeconds); - ////Console.WriteLine("================================"); - ////Array.Test(); - ////DateTime.Test(); - ////Dictionary.Test(); - ////Double.Test(); - ////Object.Test(); - ////Process.Test(); - ////String.Test(); - ////TimeZoneInfo.Test(); - ////PrimeNumbers.Test(); - //WebException.Test(); - - //Test System.String.Left() + //////System.Numerics.BigInteger big = new System.Numerics.BigInteger(); + ////int big = 1234567890; + ////Console.WriteLine(Convert.ToString(big, 2)); + ////Console.WriteLine(Mersenne32.BaseConverter.ToBinary(big)); + ////Console.WriteLine(Mersenne32.BaseConverter.Sqrt(big)); + + ////System.DateTime startBitArray = System.DateTime.Now; + ////bool[] bits = new bool[25000000]; + ////for (int C = 0; C < 25000000; C++) + ////{ + //// bits[C] = true; + ////} + ////System.DateTime stopBitArray = System.DateTime.Now; + + ////System.Numerics.BigInteger bigInteger;// = System.Numerics.BigInteger.Parse("1234567890"); + ////System.Numerics.BigInteger bigSquare; + ////System.Text.StringBuilder bigString = new System.Text.StringBuilder(); + ////System.DateTime startString = System.DateTime.Now; + ////for (int C = 1; C <= 1000000; C++) + ////{ + //// bigString.Append("1234567890"); + //// //string s = String.Format("{0:n0}", bigString.Length) + //// //Console.WriteLine($"{System.String.Format("{0:n0}", bigString.Length)} digits"); + ////} + ////System.DateTime stopString = System.DateTime.Now; + ////bigInteger = System.Numerics.BigInteger.Parse(bigString.ToString()); + ////System.DateTime stopInt = System.DateTime.Now; + ////bigSquare = Mersenne32.BaseConverter.Sqrt(bigInteger); + ////System.DateTime stopSquare = System.DateTime.Now; + ////Console.WriteLine($"Build string:{(stopString - startString)}"); + ////Console.WriteLine($"Create int:{(stopInt - stopString)}"); + ////Console.WriteLine($"Calc sqrt:{(stopSquare - stopInt)}"); + ////Console.WriteLine($"[{bigString.Length}][{bigSquare.ToString().Length}]"); + + ////for (int C = 1; C <= 1000; C++) + ////{ + //// for (int repeat = 0; repeat < C; repeat++) + //// { + //// //bigString += "1234567890"; + //// } + //// //bigInteger = System.Numerics.BigInteger.Parse(bigString); + //// //bigSquare = Mersenne32.BaseConverter.Sqrt(bigInteger); + //// Console.WriteLine($"[{bigString.Length}][{bigSquare.ToString().Length}]"); + ////} + + ////Mersenne32.BaseConverter.Convert(10, 2, "16"); + + ////bool prime = false; + ////System.UInt64 bi = 2; + ////long evenPrime = 0; + ////long oddPrime = 0; + ////for (System.UInt64 C = 1; C < 1000; C++) + ////{ + //// prime = (bi - 1).IsPrime(); + //// if (prime) + //// { + //// if ((C % 2) == 0) + //// { + //// evenPrime++; + //// } + //// else + //// { + //// oddPrime++; + //// } + //// } + //// Console.WriteLine($"{C}:{(bi - 1)}: {prime} (Even:{evenPrime} Odd:{oddPrime}"); + //// if (C == 60) + //// { + //// Console.WriteLine("Here"); + //// } + //// bi = bi * 2; + ////} + ////((System.Numerics.BigInteger)99).IsPrime(); + ////l.GetNthPrimeAsync(4227946); + ////TimeSpan ts; + ////System.DateTime start; + ////start = System.DateTime.Now; + ////Console.WriteLine(start); + ////Console.WriteLine(l.GetNthPrimeAsync(10000)); + ////ts = System.DateTime.Now - start; + ////Console.WriteLine(ts.TotalSeconds); + ////start = System.DateTime.Now; + ////Console.WriteLine(start); + ////Console.WriteLine(l.GetNthPrime(10000)); + ////ts = System.DateTime.Now - start; + ////Console.WriteLine(ts.TotalSeconds); + ////start = System.DateTime.Now; + ////Console.WriteLine(start); + ////Console.WriteLine(l.GetNthPrimeAsync(100000)); + ////ts = System.DateTime.Now - start; + ////Console.WriteLine(ts.TotalSeconds); + ////start = System.DateTime.Now; + ////Console.WriteLine(start); + ////Console.WriteLine(l.GetNthPrime(100000)); + ////ts = System.DateTime.Now - start; + ////Console.WriteLine(ts.TotalSeconds); + //////Console.WriteLine("================================"); + //////Array.Test(); + //////DateTime.Test(); + //////Dictionary.Test(); + //////Double.Test(); + //////Object.Test(); + //////Process.Test(); + //////String.Test(); + //////TimeZoneInfo.Test(); + //////PrimeNumbers.Test(); + ////WebException.Test(); + + ////Test System.String.Left() } } diff --git a/TESTING/TESTING.csproj b/TESTING/TESTING.csproj index 0428b7b..6900f1e 100644 --- a/TESTING/TESTING.csproj +++ b/TESTING/TESTING.csproj @@ -55,26 +55,12 @@ - - - - - - - - - - - - - {331a7c3b-45dc-4e04-85bf-de1934c6b3fa} - EXTENSIONS - + \ No newline at end of file diff --git a/VersionHistory.md b/VersionHistory.md index 91f3414..a2387de 100644 --- a/VersionHistory.md +++ b/VersionHistory.md @@ -386,3 +386,6 @@ - Removed Logit dependencies.
- Updated Microsoft.Graph dependency to 5.42.0.
- Updated Microsoft.Identity.Client dependency to 4.59.0.
+ +### **6.0.800 (2024-02-22)**
+ - Rearchitected and Optimized.