#region Usings using System; using System.Drawing; using System.Windows.Forms; using System.Diagnostics; using System.Security.Cryptography; using System.Text; using System.IO; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Net; #if !BASICLAUNCHER using NLog; #endif using System.Text.RegularExpressions; using System.Drawing.Imaging; using System.Runtime.InteropServices; using System.Management; #if !BASICLAUNCHER using Mono.Nat; #endif #endregion namespace Novetus.Core { #region Utils public static class Util { #region Extensions //This code was brought to you by: //https://stackoverflow.com/questions/1926264/color-different-parts-of-a-richtextbox-string //https://stackoverflow.com/questions/262280/how-can-i-know-if-a-process-is-running //https://stackoverflow.com/questions/444798/case-insensitive-containsstring //https://stackoverflow.com/questions/6084940/how-do-i-search-a-multi-dimensional-array //https://www.dotnetperls.com/between-before-after //https://stackoverflow.com/questions/12422619/can-i-disable-the-close-button-of-a-form-using-c //https://stackoverflow.com/questions/9031537/really-simple-encryption-with-c-sharp-and-symmetricalgorithm #region Rich Text Box Extensions public static void AppendText(this RichTextBox box, string text, Color color) { box.SelectionStart = box.TextLength; box.SelectionLength = 0; box.SelectionColor = color; box.AppendText(text); //box.SelectionColor = box.ForeColor; } #endregion #region Process Extensions public static bool IsRunning(this Process process) { try { Process.GetProcessById(process.Id); } catch (InvalidOperationException) { return false; } catch (ArgumentException) { return false; } return true; } #endregion #region String Extensions public static bool Contains(this string source, string toCheck, StringComparison comp) { if (source == null) return false; return source.IndexOf(toCheck, comp) >= 0; } #endregion #region Substring Extensions /// /// Get string value between [first] a and [last] b. /// public static string Between(this string value, string a, string b) { int posA = value.IndexOf(a); int posB = value.LastIndexOf(b); if (posA == -1) { return ""; } if (posB == -1) { return ""; } int adjustedPosA = posA + a.Length; if (adjustedPosA >= posB) { return ""; } return value.Substring(adjustedPosA, posB - adjustedPosA); } /// /// Get string value after [first] a. /// public static string Before(this string value, string a) { int posA = value.IndexOf(a); if (posA == -1) { return ""; } return value.Substring(0, posA); } /// /// Get string value after [last] a. /// public static string After(this string value, string a) { int posA = value.LastIndexOf(a); if (posA == -1) { return ""; } int adjustedPosA = posA + a.Length; if (adjustedPosA >= value.Length) { return ""; } return value.Substring(adjustedPosA); } #endregion #region String Utilities private static byte[] key = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; private static byte[] iv = new byte[8] { 1, 2, 3, 4, 5, 6, 7, 8 }; public static string Crypt(this string text) { SymmetricAlgorithm algorithm = DES.Create(); ICryptoTransform transform = algorithm.CreateEncryptor(key, iv); byte[] inputbuffer = Encoding.Unicode.GetBytes(text); byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length); return Convert.ToBase64String(outputBuffer); } public static string Decrypt(this string text) { SymmetricAlgorithm algorithm = DES.Create(); ICryptoTransform transform = algorithm.CreateDecryptor(key, iv); byte[] inputbuffer = Convert.FromBase64String(text); byte[] outputBuffer = transform.TransformFinalBlock(inputbuffer, 0, inputbuffer.Length); return Encoding.Unicode.GetString(outputBuffer); } #endregion #region Exception Helpers //https://github.com/AlexMelw/EasySharp/blob/master/NHelpers/ExceptionsDealing/Extensions/ExceptionExtensions.cs /// /// Gets the entire stack trace consisting of exception's footprints (File, Method, LineNumber) /// /// Source /// /// that represents the entire stack trace consisting of exception's footprints (File, /// Method, LineNumber) /// public static string GetExceptionFootprints(this Exception exception) { StackTrace stackTrace = new StackTrace(exception, true); StackFrame[] frames = stackTrace.GetFrames(); if (ReferenceEquals(frames, null)) { return string.Empty; } var traceStringBuilder = new StringBuilder(); for (var i = 0; i < frames.Length; i++) { StackFrame frame = frames[i]; if (frame.GetFileLineNumber() < 1) continue; traceStringBuilder.AppendLine($"File: {frame.GetFileName()}"); traceStringBuilder.AppendLine($"Method: {frame.GetMethod().Name}"); traceStringBuilder.AppendLine($"LineNumber: {frame.GetFileLineNumber()}"); if (i == frames.Length - 1) break; traceStringBuilder.AppendLine(" ---> "); } string stackTraceFootprints = traceStringBuilder.ToString(); if (string.IsNullOrWhiteSpace(stackTraceFootprints)) return "NO DETECTED FOOTPRINTS"; return stackTraceFootprints; } #endregion #region DirectoryInfo Extensions public static IEnumerable GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions) { if (extensions == null) throw new ArgumentNullException("extensions"); IEnumerable files = dir.EnumerateFiles(); return files.Where(f => extensions.Contains(f.Extension)); } #endregion #region DateTime Extensions //https://stackoverflow.com/questions/5672862/check-if-datetime-instance-falls-in-between-other-two-datetime-objects public static bool IsBetweenTwoDates(this DateTime dt, DateTime start, DateTime end) { return dt >= start && dt <= end; } #endregion #region Form Extensions [DllImport("user32")] public static extern IntPtr GetSystemMenu(IntPtr hWnd, bool bRevert); [DllImport("user32")] public static extern bool EnableMenuItem(IntPtr hMenu, uint itemId, uint uEnable); public static void DisableCloseButton(this Form form) { // The 1 parameter means to gray out. 0xF060 is SC_CLOSE. EnableMenuItem(GetSystemMenu(form.Handle, false), 0xF060, 1); } public static void EnableCloseButton(this Form form) { // The zero parameter means to enable. 0xF060 is SC_CLOSE. EnableMenuItem(GetSystemMenu(form.Handle, false), 0xF060, 0); } #endregion #endregion #region Utility Functions private static DialogResult ShowOverrideWarning(string dest) { DialogResult box = MessageBox.Show("A file with a similar name was detected in the directory as '" + dest + "'.\n\nWould you like to override it?", "Novetus - Override Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Warning); return box; } public static void FixedFileCopy(string src, string dest, bool overwrite, bool overwritewarning = false) { if (File.Exists(dest)) { if (overwrite && overwritewarning) { if (ShowOverrideWarning(dest) == DialogResult.No) { return; } } File.SetAttributes(dest, FileAttributes.Normal); } File.Copy(src, dest, overwrite); File.SetAttributes(dest, FileAttributes.Normal); } public static void FixedFileDelete(string src) { if (File.Exists(src)) { File.SetAttributes(src, FileAttributes.Normal); File.Delete(src); } } public static void FixedFileMove(string src, string dest, bool overwrite, bool overwritewarning = false) { if (src.Equals(dest)) return; if (!File.Exists(dest)) { File.SetAttributes(src, FileAttributes.Normal); File.Move(src, dest); } else { if (overwrite) { if (overwritewarning) { if (ShowOverrideWarning(dest) == DialogResult.No) { return; } } FixedFileDelete(dest); File.SetAttributes(src, FileAttributes.Normal); File.Move(src, dest); } else { throw new IOException("Cannot create a file when that file already exists. FixedFileMove cannot override files with overwrite disabled."); } } } //modified from the following: //https://stackoverflow.com/questions/28887314/performance-of-image-loading //https://stackoverflow.com/questions/2479771/c-why-am-i-getting-the-process-cannot-access-the-file-because-it-is-being-u public static Image LoadImage(string fileFullName, string fallbackFileFullName = "") { if (string.IsNullOrWhiteSpace(fileFullName)) return null; Image image = null; try { using (MemoryStream ms = new MemoryStream(File.ReadAllBytes(fileFullName))) { image = Image.FromStream(ms); } // PropertyItems seem to get lost when fileStream is closed to quickly (?); perhaps // this is the reason Microsoft didn't want to close it in the first place. PropertyItem[] items = image.PropertyItems; foreach (PropertyItem item in items) { image.SetPropertyItem(item); } } #if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { LogExceptions(ex); #else catch (Exception) { #endif if (!string.IsNullOrWhiteSpace(fallbackFileFullName)) image = LoadImage(fallbackFileFullName); } return image; } //https://social.msdn.microsoft.com/Forums/vstudio/en-US/b0c31115-f6f0-4de5-a62d-d766a855d4d1/directorygetfiles-with-searchpattern-to-get-all-dll-and-exe-files-in-one-call?forum=netfxbcl public static string[] GetFiles(string path, string searchPattern, SearchOption searchOption) { string[] searchPatterns = searchPattern.Split('|'); List files = new List(); foreach (string sp in searchPatterns) files.AddRange(System.IO.Directory.GetFiles(path, sp, searchOption)); files.Sort(); return files.ToArray(); } // Credit to Carrot for the original code. Rewote it to be smaller. public static string CryptStringWithByte(string word) { byte[] bytes = Encoding.ASCII.GetBytes(word); string result = ""; for (int i = 0; i < bytes.Length; i++) { result += Convert.ToChar(0x55 ^ bytes[i]); } return result; } //https://stackoverflow.com/questions/1879395/how-do-i-generate-a-stream-from-a-string public static Stream GenerateStreamFromString(string s) { var stream = new MemoryStream(); var writer = new StreamWriter(stream); writer.Write(s); writer.Flush(); stream.Position = 0; return stream; } //https://stackoverflow.com/questions/14488796/does-net-provide-an-easy-way-convert-bytes-to-kb-mb-gb-etc private static readonly string[] SizeSuffixes = { "bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" }; public static string SizeSuffix(Int64 value, int decimalPlaces = 1) { if (decimalPlaces < 0) { throw new ArgumentOutOfRangeException("decimalPlaces"); } if (value < 0) { return "-" + SizeSuffix(-value, decimalPlaces); } if (value == 0) { return string.Format("{0:n" + decimalPlaces + "} bytes", 0); } // mag is 0 for bytes, 1 for KB, 2, for MB, etc. int mag = (int)Math.Log(value, 1024); // 1L << (mag * 10) == 2 ^ (10 * mag) // [i.e. the number of bytes in the unit corresponding to mag] decimal adjustedSize = (decimal)value / (1L << (mag * 10)); // make adjustment when the value is large enough that // it would round up to 1000 or more if (Math.Round(adjustedSize, decimalPlaces) >= 1000) { mag += 1; adjustedSize /= 1024; } return string.Format("{0:n" + decimalPlaces + "} {1}", adjustedSize, SizeSuffixes[mag]); } //https://stackoverflow.com/questions/11927116/getting-files-recursively-skip-files-directories-that-cannot-be-read public static string[] FindAllFiles(string rootDir) { var pathsToSearch = new Queue(); var foundFiles = new List(); pathsToSearch.Enqueue(rootDir); while (pathsToSearch.Count > 0) { var dir = pathsToSearch.Dequeue(); try { var files = Directory.GetFiles(dir); foreach (var file in Directory.GetFiles(dir)) { foundFiles.Add(file); } foreach (var subDir in Directory.GetDirectories(dir)) { pathsToSearch.Enqueue(subDir); } } #if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { LogExceptions(ex); #else catch (Exception) { #endif } } return foundFiles.ToArray(); } //https://stackoverflow.com/questions/66667263/i-want-to-remove-special-characters-from-file-name-without-affecting-extension-i //https://stackoverflow.com/questions/3218910/rename-a-file-in-c-sharp public static bool FileHasInvalidChars(string path) { string fileName = Path.GetFileName(path); if (Regex.Match(fileName, @"[^\w-.'_!()& ]") != Match.Empty) { return true; } return false; } public static void RenameFileWithInvalidChars(string path) { try { if (!FileHasInvalidChars(path)) return; string pathWithoutFilename = Path.GetDirectoryName(path); string fileName = Path.GetFileName(path); fileName = Regex.Replace(fileName, @"[^\w-.'_!()& ]", ""); string finalPath = pathWithoutFilename + "\\" + fileName; FixedFileMove(path, finalPath, File.Exists(finalPath)); } #if URI || LAUNCHER || BASICLAUNCHER catch (Exception ex) { LogExceptions(ex); #else catch (Exception) { #endif } } public static void LogPrint(string text, int type = 1) { //TODO, remove nlog support for bootstrapper completely. this is a temp fix. #if !BASICLAUNCHER Logger log = LogManager.GetCurrentClassLogger(); switch (type) { case 2: log.Error(text); break; case 3: log.Warn(text); break; default: log.Info(text); break; } #endif } public static void LogExceptions(Exception ex) { string message = (ex.Message != null ? ex.Message.ToString() : "N/A"); ConsolePrint(ex.Source + " Exception: " + message, 2, true); #if LAUNCHER || URI || BASICLAUNCHER LogPrint("EXCEPTION|MESSAGE: " + message, 2); LogPrint("EXCEPTION|STACK TRACE: " + (!string.IsNullOrWhiteSpace(ex.StackTrace) ? ex.StackTrace : "N/A"), 2); LogPrint("EXCEPTION|ADDITIONAL INFO: " + (ex != null ? ex.ToString() : "N/A"), 2); #endif } //https://stackoverflow.com/questions/27108264/how-to-properly-make-a-http-web-get-request private static string HttpGetInternal(string uri) { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri); request.AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) { using (Stream stream = response.GetResponseStream()) { using (StreamReader reader = new StreamReader(stream)) { return reader.ReadToEnd(); } } } } public static string HttpGet(string uri) { int tries = 0; int triesMax = 5; string exceptionMessage = ""; while (tries < triesMax) { tries++; try { return HttpGetInternal(uri); } catch (Exception ex) { exceptionMessage = ex.Message; continue; } } return "ERROR: " + exceptionMessage; } public static void DrawBorderSimple(Graphics graphics, Rectangle bounds, Color color, ButtonBorderStyle style, int width) { //AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ControlPaint.DrawBorder(graphics, bounds, color, width, style, color, width, style, color, width, style, color, width, style); } public static bool IsIPValid(string IP) { IPAddress address; if (IPAddress.TryParse(IP, out address)) { switch (address.AddressFamily) { case System.Net.Sockets.AddressFamily.InterNetwork: return true; case System.Net.Sockets.AddressFamily.InterNetworkV6: default: break; } } return false; } //converted from https://facreationz.wordpress.com/2014/12/11/c-know-if-running-under-wine/ public static bool IsWineRunning() { string processName = "winlogon"; var p = Process.GetProcessesByName(processName).Count(); return (p <= 0); } public static void ConsolePrint(string text, int type = 1, bool noLog = false, bool scrollDown = true) { switch (type) { case 0: ConsoleText(text, ConsoleColor.Black, true); break; case 2: ConsoleText(text, ConsoleColor.Red, true); if (!noLog) LogPrint(text, 2); break; case 3: ConsoleText(text, ConsoleColor.Green, true); if (!noLog) LogPrint(text); break; case 4: ConsoleText(text, ConsoleColor.Cyan, true); if (!noLog) LogPrint(text); break; case 5: ConsoleText(text, ConsoleColor.Yellow, true); if (!noLog) LogPrint(text, 3); break; case 1: default: ConsoleText(text, ConsoleColor.White, true); if (!noLog) LogPrint(text); break; } #if LAUNCHER if (GlobalVars.consoleForm != null) { if (GlobalVars.consoleForm.InvokeRequired) return; FormPrint(text, type, GlobalVars.consoleForm.ConsoleBox, scrollDown); } #endif } public static void ConsolePrintMultiLine(string text, int type = 1, bool noLog = false) { try { string[] NewlineChars = { Environment.NewLine, "\n" }; string[] lines = text.Split(NewlineChars, StringSplitOptions.None); ConsolePrintMultiLine(lines, type, noLog); } catch (Exception e) { #if URI || LAUNCHER || BASICLAUNCHER LogExceptions(e); #endif } } public static void ConsolePrintMultiLine(ICollection textColection, int type = 1, bool noLog = false) { if (!textColection.Any()) return; if (textColection.Count == 1) { ConsolePrint(textColection.First(), type, noLog); return; } foreach (string text in textColection) { ConsolePrint(text, type, noLog); } } private static void FormPrint(string text, int type, RichTextBox box, bool scrollDown = true) { if (box == null) return; foreach (string line in box.Lines) { Regex.Replace(line, @"^\s+$[\r\n]*", "", RegexOptions.Multiline); } box.AppendText("\r\n", Color.White); switch (type) { case 1: box.AppendText(text, Color.White); break; case 2: box.AppendText(text, Color.Red); break; case 3: box.AppendText(text, Color.Lime); break; case 4: box.AppendText(text, Color.Aqua); break; case 5: box.AppendText(text, Color.Yellow); break; case 0: default: box.AppendText(text, Color.Black); break; } if (scrollDown) { box.SelectionStart = box.Text.Length; box.ScrollToCaret(); } } private static void ConsoleText(string text, ConsoleColor color, bool newLine = false) { Console.ForegroundColor = color; if (newLine) { Console.WriteLine(text); } else { Console.Write(text); } } public static void ReadTextFileWithColor(string path, bool scrollDown = true) { var lines = File.ReadLines(path); foreach (var line in lines) { try { string[] vals = line.Split('|'); ConsolePrint(vals[0], Convert.ToInt32(vals[1]), true, scrollDown); } catch (Exception) { ConsolePrint(line, 1, true, scrollDown); } } } #if LAUNCHER //https://stackoverflow.com/questions/30687987/unable-to-decompress-bz2-file-has-orginal-file-using-dotnetzip-library public static string Compress(string sourceFile, bool forceOverwrite) { var outFname = sourceFile + ".bz2"; if (File.Exists(outFname)) { if (forceOverwrite) File.Delete(outFname); else return null; } long rowCount = 0; var output = File.Create(outFname); try { using (StreamReader reader = new StreamReader(sourceFile)) { using (var compressor = new Ionic.BZip2.ParallelBZip2OutputStream(output)) { StreamWriter writer = new StreamWriter(compressor, Encoding.UTF8); string line = ""; while ((line = reader.ReadLine()) != null) { writer.WriteLine(line); rowCount++; } writer.Close(); compressor.Close(); } } } catch (Exception) { throw; } finally { if (output != null) output = null; } // Pump(fs, compressor); return outFname; } public static string Decompress(string sourceFile, bool forceOverwrite) { var outFname = sourceFile.Replace(".bz2", ""); if (File.Exists(outFname)) { if (forceOverwrite) File.Delete(outFname); else return null; } using (Stream fs = File.OpenRead(sourceFile), output = File.Create(outFname), decompressor = new Ionic.BZip2.BZip2InputStream(fs)) Pump(decompressor, output); return outFname; } private static void Pump(Stream src, Stream dest) { byte[] buffer = new byte[2048]; int n; while ((n = src.Read(buffer, 0, buffer.Length)) > 0) dest.Write(buffer, 0, n); } #endif //these methods were made so we dont have to do shit like false.ToString() or 0.ToString(). //will still use ToString for converting variables, but converting values didn't feel right. public static string BoolValue(bool value) { return value.ToString(); } public static string IntValue(int value) { return value.ToString(); } #endregion } #endregion }