#define PROD_ // also change in LicenseFile.cs too, prevents compilation of the licensekey making bits /* * Created by SharpDevelop. * User: D Macintosh * Date: 10/25/2022 * Time: 9:32 PM * * To change this template use Tools | Options | Coding | Edit Standard Headers. */ using System; using System.Collections.Generic; using System.Net; using System.IO; using System.Text; using Newtonsoft.Json.Linq; using System.Threading; using System.Reflection; namespace cdrtool { class cdrtool { public static string product = "CDR-Tool"; public static string version = "1.6.7"; public static int debug = 1; public static int mode = 1; public static int major_errs = 0; public static int MAX_RETRY = 3; public static int MIN_INT = 10; // minimum interval for timer in minutes public static int MAX_INT = 360; // maximum interval for timer public static int webMaxWait = 20; //max wait time in minutes for webaccess public static bool logappend = true; public static string logname = "logfile.txt"; public static string licfile = "license.txt"; public static StreamWriter outfile; public static string username; public static string password; public static string company; public static bool licensed; public static string dirpath = ""; public static string token = ""; public static int begin = 8; public static int end = 20; public static int interval = 0; public static bool checkPrevMonth = true; public static int prevMonOffset = 1; public static string mfa = ""; // 6-digit MFA code public static int mfa_delay = 120; // wait time for email to arrive in seconds public static string ssh_user; public static string ssh_pass; public static string ssh_host; public static string ssh_path = "." + Path.DirectorySeparatorChar ; public static int ssh_port = 22; public static bool sftp = false; public static StringBuilder adminLog = new StringBuilder(); public static StringBuilder auditLog = new StringBuilder(); public static int adlvl = 2; /* see https://denhamcoder.net/2018/08/25/embedding-net-assemblies-inside-net-assemblies/ */ // still needs external copy during compilation! // Loads NewtonsoftJson lib into memory as .dll public static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { string name = new AssemblyName(args.Name).Name; string embname = "other"; if (name == "BouncyCastle.Cryptography") { embname = "CDRTool.Embedded.BouncyCastle.Cryptography.dll"; } else if (name == "Google.Apis") { embname = "CDRTool.Embedded.Google.Apis.dll"; } else if (name == "Google.Apis.Auth") { embname = "CDRTool.Embedded.Google.Apis.Auth.dll"; } else if (name == "Google.Apis.Core") { embname = "CDRTool.Embedded.Google.Apis.Core.dll"; } else if (name == "Google.Apis.Gmail.v1") { embname = "CDRTool.Embedded.Google.Apis.Gmail.v1.dll"; } else if (name == "Microsoft.Bcl.AsyncInterfaces") { embname = "CDRTool.Embedded.Microsoft.Bcl.AsyncInterfaces.dll"; } else if (name == "Microsoft.Extensions.DependencyInjection.Abstractions") { embname = "CDRTool.Embedded.Microsoft.Extensions.DependencyInjection.Abstractions.dll"; } else if (name == "Microsoft.Extensions.Logging.Abstractions") { embname = "CDRTool.Embedded.Microsoft.Extensions.Logging.Abstractions.dll"; } else if (name == "Newtonsoft.Json") { embname = "CDRTool.Embedded.Newtonsoft.Json.dll"; } else if (name == "Renci.SshNet") { embname = "CDRTool.Embedded.Renci.SshNet.dll"; } else if (name == "System.Buffers") { embname = "CDRTool.Embedded.System.Buffers.dll"; } else if (name == "System.CodeDom") { embname = "CDRTool.Embedded.System.CodeDom.dll"; } else if (name == "System.Diagnostics.DiagnosticSource") { embname = "CDRTool.Embedded.System.Diagnostics.DiagnosticSource.dll"; } else if (name == "System.Formats.Asn1") { embname = "CDRTool.Embedded.System.Formats.Asn1.dll"; } else if (name == "System.Memory") { embname = "CDRTool.Embedded.System.Memory.dll"; } else if (name == "System.Numerics.Vectors") { embname = "CDRTool.Embedded.System.Numerics.Vectors.dll"; } else if (name == "System.Runtime.CompilerServices.Unsafe") { embname = "CDRTool.Embedded.System.Runtime.CompilerServices.Unsafe.dll"; } else if (name == "System.Threading.Tasks.Extensions") { embname = "CDRTool.Embedded.System.Threading.Tasks.Extensions.dll"; } else if (name == "System.ValueTuple") { embname = "CDRTool.Embedded.System.ValueTuple.dll"; } else { embname = "something_bad"; } //Console.WriteLine("returning assy: " + name); using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(embname)) { var assemblyData = new Byte[stream.Length]; stream.Read(assemblyData, 0, assemblyData.Length); return Assembly.Load(assemblyData); } } public static void Main(string[] args) { // Load Embedded Resources AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve; //foreach (var resource in Assembly.GetExecutingAssembly().GetManifestResourceNames()) Console.WriteLine("Resource: " + resource); Main2(args); } public static async void Main2(string[] args) { #if !PROD_ // LicenseFile.makeLicenseFile(licfile, "Support", 5, false); LicenseFile.makeLicenseFile("license.txt", "Support", 1, true); Console.WriteLine(LicenseFile.validate("license.txt")); return; #endif // Clears 'async' compiler error await System.Threading.Tasks.Task.CompletedTask; // Enforce TLS1.2 Sep2017 ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072 | (SecurityProtocolType)768 | (SecurityProtocolType)192; // Logging file outfile = new StreamWriter(@""+logname,logappend); outfile.AutoFlush = true; string ban2 = product+" v"+version+" (c) 2022-2026 Sommet Consulting Inc."; ban2 = "\u2551 " + ban2 + " \u2551"; string ban1 = "\u2554"; for ( int i = 2; i < ban2.Length; i++) { ban1 += "\u2550"; } ban1 += "\u2557"; string ban3 = "\u255a"; for ( int i = 2; i < ban2.Length; i++) { ban3 += "\u2550"; } ban3 += "\u255d"; Logger.Log(ban1); Logger.Log(ban2); Logger.Log(ban3); //Logger.Log("--- UNLICENSED, FOR EVALUATION USE ONLY ---"); dynamic license; Arguments myargs = new Arguments(args); CookieContainer cookiejar = new CookieContainer(); if ( (myargs.Count < 1 ) || myargs.Exists("help") || myargs.Exists("h") ) { Logger.Log(" usage: " + System.Diagnostics.Process.GetCurrentProcess().ProcessName + " [-options]"); //Console.WriteLine("retry: -retries n"); //Logger.Log("--- UNLICENSED, FOR EVALUATION USE ONLY ---"); Logger.Log(" login: -u user -p passwd"); Logger.Log(" time: -begin 8 -end 20 -interval 60"); Logger.Log(" path: -path " + ( Path.DirectorySeparatorChar.ToString()=="\\" ? "C:" : "") + "/directory/subdir"); Logger.Log(" sftp: -sh sftp.server -su user -sp passwd -sport 22 -spath CustomPath"); //Logger.Log(" debug: -debug n"); //Console.WriteLine("-fiddler"); // not needed with Fiddler v5.x return; } WebProxy proxyObject = null; #if !PROD_ { //cdrtool Creds if (myargs.Exists("dm")) { username = "Doug.Macintosh@rci.rogers.com"; password = "Rogers1!"; //clientInfo = "logging in as Doug Macintosh"; } if (myargs.IsTrue("fiddler")) { Logger.Log("Enabling Fiddler Proxy"); proxyObject = new WebProxy("http://127.0.0.1:8888/"); // Fiddler proxy //System.Net.WebRequest.DefaultWebProxy = new System.Net.WebProxy("127.0.0.1", 8888); } //} #endif if (myargs.Exists("debug")) { debug = int.Parse(myargs.Single("debug")); Logger.Log(5, "Setting debug level to {0}", debug); } //} if (myargs.Exists("path")) { dirpath = myargs.Single("path"); } else { dirpath = "." + Path.DirectorySeparatorChar.ToString(); } if (dirpath.EndsWith(Path.DirectorySeparatorChar.ToString())) { } else { dirpath += Path.DirectorySeparatorChar.ToString();} Logger.Log(0,"Setting filestore path to {0}", dirpath); int b = begin; int e = end; if (myargs.Exists("begin")) { b = int.Parse(myargs.Single("begin")); } if (myargs.Exists("end")) { e = int.Parse(myargs.Single("end")); } if ( ( e > b) && ( ( e > 0) && ( e <= 24 )) ) { end = e; } else { Logger.Log(0,"Invalid parameter for end hour. Must be 0-24h and greater than begin hour."); return; } if ( ( b < e ) && ( ( b >= 0 ) && ( b < 24 ) ) ) { begin = b; } else { Logger.Log(0,"Invalid parameter for start hour. Must be 0-24h and less than end hour."); return; } if (myargs.Exists("interval")) { int i = int.Parse(myargs.Single("interval")); if ( ( i >= MIN_INT ) && ( i <= MAX_INT ) ) { interval = i; } else { Logger.Log(0,"Invalid parameter for interval in minutes. Must be 10-360min"); return; } } if (interval > 0) { Logger.Log(0,"Setting Timer Period {0}h to {1}h, {2}min interval", begin, end, interval); } else { Logger.Log(0,"Single Shot Mode. (set time: parameters to enable repetition)."); } if (myargs.Exists("offset")) { prevMonOffset = int.Parse(myargs.Single("offset")); Logger.Log(0, "Setting History File offset to -{0}", prevMonOffset); } if ((myargs.Exists("sh")) && (myargs.Exists("su")) && (myargs.Exists("sp")) ) { ssh_host = myargs.Single("sh"); ssh_user = myargs.Single("su"); ssh_pass = myargs.Single("sp"); if (myargs.Exists("sport")) { ssh_port = int.Parse(myargs.Single("sport")); } if (myargs.Exists("spath")) { ssh_path = (myargs.Single("spath")); } sftp = true; Logger.Log(0, "Uploading files as {3} to server: {0}:{1}{4}{2}", ssh_host, ssh_port, ssh_path, ssh_user, Path.DirectorySeparatorChar); } if ((myargs.Exists("u")) && (myargs.Exists("p"))) { username = myargs.Single("u"); password = myargs.Single("p"); Logger.Log(0, "Setting authorized account to: {0}", username); } #if !PROD_ else if (myargs.Exists("dm")) { //already done } #endif else { Logger.Log(0,"No valid login credentials found. Exiting."); return; } // ***MAIN //sftp.Upload_file("./CURRENT.csv", "10.0.0.3", 2222, "doug", "D4t4Guru"); //return; do { var now = DateTime.Now; var start = new DateTime(now.Year, now.Month, now.Day, begin, 0, 0, now.Kind); // Logger.Log(5," day of week: {0}", now.DayOfWeek); TimeSpan span = now - start; // - TimeSpan.FromSeconds(1); int m = (interval>0) ? interval - ((( span.Hours * 60 ) + span.Minutes ) % interval) : 0; //minutes to next logical interval var nextTrigger = now + TimeSpan.FromMinutes(m>0 ? m:interval) - TimeSpan.FromSeconds(span.Seconds); // sync to next logical interval Logger.Log(5," next event at: {0}",nextTrigger); if( ( interval == 0 ) || ( now.Hour >= begin && now.Hour <= end)) { // Work loop bool LoggedIn = false; int tries = 1; //Login do { Logger.Log(0,"Initiating connection..."); tries++; try { LoggedIn = WebRoutines.Login( username, password, ref token, ref cookiejar, proxyObject ); if (!LoggedIn) { Logger.Log(1," retrying {0}",tries); } } catch (Exception) { Logger.Log("Error attempting to login to SIP Portal website"); if (!LoggedIn) { Logger.Log(1," retrying {0}",tries); } } } while (!LoggedIn && (tries <= MAX_RETRY) ); if ( !LoggedIn ) { Logger.Log("Aborting due to inability to login to SIP Portal website"); break; // DWMM Jan26 } else { try { #if !PROD_ LicenseFile.makeLicenseFile(licfile, "Support", 5, false); #endif license = JObject.Parse(LicenseFile.validate(licfile)); } catch (Exception ex) { Logger.Log("ERROR: Invalid License File!"); Logger.Log(5,ex.Message); Logger.Log("Exiting."); return; } string validity = ( ((bool)license.Perpetual ? "Perpetual License: " : "License: ") + product + " has " + ((DateTime.Now <= (DateTime)license.ValidTo) ? (license.Type + " valid through " + license.ValidTo) : ((bool)license.Perpetual ? "Right to Use only." : "Expired on " + license.ValidTo))); if (checkPrevMonth) Logger.Log(validity); licensed = !validity.Contains("Expire"); if (licensed && checkPrevMonth) Logger.Log("For assistance please contact support@sommetconsulting.ca"); } // Get Parameters string wfr_guid = ""; string ch_guid = ""; string act_guid = ""; string co_guid = ""; string did_guid = ""; string year = ""; string mtd = ""; bool gotParams = false; tries = 1; do { try { if (licensed) { Logger.Log("Setting up..."); gotParams = WebRoutines.GetGUIDs(token, ref wfr_guid, ref ch_guid, ref act_guid, ref co_guid, ref did_guid, ref year, ref mtd, ref cookiejar, proxyObject); } } catch (Exception ex) { Logger.Log("Error navigating SIP Portal"); Logger.Log(5, ex.Message); if (!gotParams) { tries++; Logger.Log(0, " retrying {0}", tries); } } } while (!gotParams && (tries < MAX_RETRY)); if (!gotParams) { Logger.Log("Aborting due to inability to navigate SIP Portal."); break; //return; } // Get files string filename = "CURRENT.csv"; //filename = ""; // use system filename bool gotMTDFile = false; tries = 1; do { try { if (licensed) { gotMTDFile = WebRoutines.GetMTDFile(dirpath, filename, token, ref act_guid, ref co_guid, ref did_guid, ref year, ref mtd, ref cookiejar, proxyObject); } } catch (Exception ex) { Logger.Log("Error attempting to download MTD File."); Logger.Log(5, ex.Message); if (!gotMTDFile) { tries++; Logger.Log(0, " retrying {0}", tries); } } } while (!gotMTDFile && (tries < MAX_RETRY)); if (!gotMTDFile) { Logger.Log("Exiting due to inability to download Month-to-Date file."); break; // return; } bool gotCDRHistoryFile = false; tries = 1; do { try { if (checkPrevMonth && licensed) { filename = ""; // use system filename gotCDRHistoryFile = WebRoutines.GetCDRHistoryFile(dirpath, filename, prevMonOffset, token, ref act_guid, ref co_guid, ref did_guid, ref year, ref mtd, ref cookiejar, proxyObject); } else { gotCDRHistoryFile = true; } } catch (Exception ex) { Logger.Log("Error attempting to download History File."); Logger.Log(5, ex.Message); if (!gotCDRHistoryFile) { tries++; Logger.Log(0, " retrying {0}", tries); } } } while (!gotCDRHistoryFile && (tries < MAX_RETRY)); if (!gotCDRHistoryFile) { Logger.Log("Aborting due to inability to download CDR Monthly History file."); break; // return; } checkPrevMonth = false; Logger.Log(3,"Trigger hour {0} Now hour {1}", nextTrigger.Hour, now.Hour); //if (( interval > 0) && ( nextTrigger.Hour <= ( now.Hour + 1)) ) // NEED TO HANDLE MIDNIGHT ROLLOVER STILL if ( (interval > 0) ) // NEED TO HANDLE MIDNIGHT ROLLOVER STILL { Logger.Log(0,"Completed CDR processing. Next event at {0:00}h{1:00}", nextTrigger.Hour, nextTrigger.Minute); } else { Logger.Log(0,"Completed CDR processing."); } // LOG OUT bool LoggedOut = WebRoutines.Logout(token, ref cookiejar, ref proxyObject); //break; // exit while() loop we are using as in 'IF' } //END OF WORK LOOP now = DateTime.Now; // reset and clean up in case we started just before the next cycle was to start // Moved stuff span = now - start; // - TimeSpan.FromSeconds(1); m = (interval > 0) ? interval - (((span.Hours * 60) + span.Minutes) % interval) : 0; //minutes to next logical interval nextTrigger = now + TimeSpan.FromMinutes(m > 0 ? m : interval) - TimeSpan.FromSeconds(span.Seconds); // sync to next logical interval //Logger.Log(0, " span {0} m:{1} next trigger {2})", span, m, nextTrigger); if ( ( now.Hour < begin || now.Hour > end || nextTrigger.Hour < begin || nextTrigger.Hour > end) && ( interval > 0 ) ) { nextTrigger = new DateTime(now.Year, now.Month, now.Day, now.Hour, 0, 0, now.Kind) ; nextTrigger += TimeSpan.FromHours( (24 - now.Hour + begin) % 24 ); Logger.Log(0,"Going to sleep until {0:00}h{1:00}", nextTrigger.Hour, nextTrigger.Minute); // begin is always less than end in any given 24h cycle checkPrevMonth = true; } if (interval > 0) { //now = DateTime.Now; // if ((nextTrigger - now) < TimeSpan.FromSeconds(1)) now -= TimeSpan.FromSeconds(1); //nextTrigger += TimeSpan.FromMinutes(interval); //Logger.Log(3,"values adjusted: trig:{0} now:{1}", nextTrigger, now); //Logger.Log(3, " thread sleeping {0}", (nextTrigger - now)); Logger.Log(5, " thread sleeping {0} ({1} - {2})", (nextTrigger - now), (nextTrigger), (now.ToString("HH:mm:ss.fff"))); token = ""; // reset auth token for session Thread.Sleep(nextTrigger - now + TimeSpan.FromSeconds(0.5)); } } while ( ( licensed || checkPrevMonth) && (interval > 0)); } // end of MAIN() } // cdrtool class public static class IDictionaryExtensions { public static TKey FindKeyByValue(this IDictionary dictionary, TValue value) { if (dictionary == null) throw new ArgumentNullException("dictionary"); foreach (KeyValuePair pair in dictionary) if (value.Equals(pair.Value)) return pair.Key; throw new Exception("the value is not found in the dictionary"); } } }