//----------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Generates the key with the temporal and computer specific attributes /// </summary> protected StringBuilder GenerateKey() { //-----a----- Start building the encrypted string StringBuilder tokenToEncrypt = new StringBuilder(); tokenToEncrypt.Append(MGLEncryption.GetSalt(1)); //-----b----- Double check that the anonID cookie has been set and set it again if not... (this should never not have happened as it is called first OnInit in the MGLBasePage) SetAnonIDCookie(); //-----c----- The AnonID is a GUID - always 36 characters string tempValue = DefaultAnonID; if (Request.Cookies["AnonID"] != null) { tempValue = Request.Cookies["AnonID"].Value; } tokenToEncrypt.Append(tempValue); //-----d----- Add some padding tokenToEncrypt.Append(MGLEncryption.GetSalt(1)); //-----e----- The date time will be of the form yyyy-mm-dd hh:mm:ss - and will always be dd and mm (not d and m for e.g. 01) tokenToEncrypt.Append(DateTimeInformation.FormatDatabaseDate(DateTime.Now, true, true)); tokenToEncrypt.Append(MGLEncryption.GetSalt(1)); //-----f----- Do the encryption itself StringBuilder authKey = MGLEncryption.Encrypt(tokenToEncrypt); //-----g----- And lastly, lets make this key HTML secure ... authKey = MGLEncryption.HTMLifyString(authKey); return(authKey); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Generates a series of simple one pattern range searches which is useful for more specific testing /// 1=PrimaryKey, 2=Integer, 3=Long, 4=Double, 5=String, 6=DateTime (7=Bool -- Warning this one is sloooow) /// </summary> public static void GenerateRandomSingleSearchPatterns(int parameterToSearchWith) { // Lets generate some random integers ... PatternsToSearchFor = new List <List <DatabaseSearchPattern> >(); for (int i = 0; i < TestParameters.NumSearchPatterns; i++) { DatabaseSearchPattern rsp = null; if (parameterToSearchWith == 1) // Primary key search { rsp = GenerateSearchPatternPrimaryKey(0, NumIterations); } else if (parameterToSearchWith == 2) // Integer search { rsp = GenerateSearchPatternInteger(1, TestParameters.MaxIntegerInRange, 1); } else if (parameterToSearchWith == 3) // Long search { rsp = GenerateSearchPatternLong(TestParameters.MinLongInRange, TestParameters.MaxLongInRange, 1); } else if (parameterToSearchWith == 4) // Double search { rsp = GenerateSearchPatternDouble(TestParameters.MinDoubleInRange, TestParameters.MaxDoubleInRange, 1); } else if (parameterToSearchWith == 5) // String search { rsp = GenerateSearchPatternString(); } else if (parameterToSearchWith == 6) // DateTime search { rsp = GenerateSearchPatternDateTime(TestParameters.DateMin, TestParameters.DateMax, 1); } else if (parameterToSearchWith == 7) // Bool search { Logger.LogWarning("TestParameters.GenerateRandomIntegerRangePatterns - Boolean searches are SLOOOW and deprecated - be careful."); TestParameters.PatternsToSearchFor.Add(new List <DatabaseSearchPattern>() { new DatabaseSearchPattern("TestBool", MGLEncryption.GenerateRandomBool()) }); } else { Logger.LogWarning("TestParameters.GenerateRandomIntegerRangePatterns - Unknown search parameter requested - " + parameterToSearchWith); } // And finally - lets add our search pattern ... TestParameters.PatternsToSearchFor.Add(new List <DatabaseSearchPattern>() { rsp }); } }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- public static DatabaseSearchPattern GenerateSearchPatternLong(long min, long max, int numTestsInGroup) { DatabaseSearchPattern rsp = null; //-----a----- Get the expression type (==, <=, >= or between) int randomET = GenerateExpressionType(numTestsInGroup); //-----b----- The range is 20m by default long range = ((max - min) * TestParameters.SearchRangeSize / TestParameters.MaxIntegerInRange); //-----c----- So we want to generalise for multiple tests --- so if numTests > 0, then increase the range ..... if (numTestsInGroup > 1) { // increase the range by a factor of 10 ... range = range * 10; // For >= or <= lets also tweak the min and max to ensure the range is larger if (randomET == 2) { min = min + range; max = max - range; } } //-----d----- Generate the random value long randomVal = MGLEncryption.GenerateRandomLong(min, max); //-----e----- Generate the search expression if (randomET == 1) //_____ == _____ { rsp = new DatabaseSearchPattern("TestLong", randomVal); } else if (randomET == 2) //_____ >= or <= range search _____ // Work out if this is a <= or >= query { bool randomBool = MGLEncryption.GenerateRandomBool(); if (randomBool == true) { rsp = new DatabaseSearchPattern("TestLong", MGLEncryption.GenerateRandomLong(max - range, max), randomBool); } else { rsp = new DatabaseSearchPattern("TestLong", MGLEncryption.GenerateRandomLong(min, min + range), randomBool); } } else //_____ Between _____ { rsp = new DatabaseSearchPattern("TestLong", randomVal, randomVal + range); } return(rsp); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- public static DatabaseSearchPattern GenerateSearchPatternDouble(double min, double max, int numTestsInGroup) { DatabaseSearchPattern rsp = null; //-----a----- Get the expression type (==, <=, >= or between) int randomET = GenerateExpressionType(numTestsInGroup); //-----b----- Generate the default range size double range = (double)TestParameters.SearchRangeSize / (double)TestParameters.MaxIntegerInRange; //----c----- so we want to generalise for multiple tests --- so if numTests > 0, then increase the range and bring in the min and max to ensure a larger range ..... if (numTestsInGroup > 1) { range = range * 4; // For >= or <= lets also tweak the min and max to ensure the range is larger if (randomET == 2) { min = min + range; max = max - range; } } //-----d----- Generate the random value double randomVal = MGLEncryption.GenerateRandomDouble(min, max); //-----e----- Generate the search pattern if (randomET == 1) //_____ == _____ { rsp = new DatabaseSearchPattern("TestDouble", randomVal); } else if (randomET == 2) //_____ >= or <= range search _____ // Work out if this is a <= or >= query { bool randomBool = MGLEncryption.GenerateRandomBool(); if (randomBool == true) { rsp = new DatabaseSearchPattern("TestDouble", MGLEncryption.GenerateRandomDouble(max - range, max), randomBool); } else { rsp = new DatabaseSearchPattern("TestDouble", MGLEncryption.GenerateRandomDouble(min, min + range), randomBool); } } else //_____ Between _____ { rsp = new DatabaseSearchPattern("TestDouble", randomVal, randomVal + range); } return(rsp); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- public static DatabaseSearchPattern GenerateSearchPatternInteger(int min, int max, int numTestsInGroup) { DatabaseSearchPattern rsp = null; //-----a----- Get the expression type (==, <=, >= or between) int randomET = GenerateExpressionType(numTestsInGroup); //-----b----- Generate the range int range = TestParameters.SearchRangeSize; // 50,000 //-----c----- We want to generalise for multiple tests --- so if numTests > 0, then increase the range and bring in the min and max to ensure a larger range ..... if (numTestsInGroup > 1) { range = range * 10; // For >= or <= lets also tweak the min and max to ensure the range is larger if (randomET == 2) { min = min + range; max = max - range; } } //-----d----- Generate the random value int randomVal = MGLEncryption.GenerateRandomInt(min, max); //-----e----- Now generate the search pattern if (randomET == 1) //_____ == _____ { rsp = new DatabaseSearchPattern("TestInt", randomVal); } else if (randomET == 2) //_____ >= or <= range search _____ { bool randomBool = MGLEncryption.GenerateRandomBool(); if (randomBool == true) { rsp = new DatabaseSearchPattern("TestInt", MGLEncryption.GenerateRandomInt(max - range, max), randomBool); } else { rsp = new DatabaseSearchPattern("TestInt", MGLEncryption.GenerateRandomInt(min, min + range), randomBool); } } else //_____ Between _____ { rsp = new DatabaseSearchPattern("TestInt", randomVal, randomVal + range); } return(rsp); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Generates a series of simple integer range searches... useful for more specific testing /// </summary> public static void TestSorting() { List <DatabaseIndexInfo> riis = rw.IndexFindAll(new TestObj()); int randomVal = MGLEncryption.GenerateRandomInt(1, 1000000); long randomVal2 = MGLEncryption.GenerateRandomLong(8000000000, 12000000000); double randomVal3 = MGLEncryption.GenerateRandomDouble(0, 1); DateTime randomVal4 = MGLEncryption.GenerateRandomDateTime(TestParameters.DateMin, TestParameters.DateMax); List <DatabaseSearchPattern> testPatterns = new List <DatabaseSearchPattern>() { // Bool new DatabaseSearchPattern("TestBool", MGLEncryption.GenerateRandomBool()), // Score - equivalent (int) new DatabaseSearchPattern("TestInt", randomVal), // Score - greater than new DatabaseSearchPattern("TestInt", randomVal, true), // Score - less than new DatabaseSearchPattern("TestInt", randomVal, false), // Score - between new DatabaseSearchPattern("TestInt", randomVal, randomVal + TestParameters.SearchRangeSize), // Text - Starts with new DatabaseSearchPattern("TestStr", MGLEncryption.GetSalt(RedisWrapper.TextIndexLength).ToString().ToLower()), // Score - between (long) new DatabaseSearchPattern("TestLong", randomVal2, randomVal2 + (4000000000 * TestParameters.SearchRangeSize / 1000000)), // Primary key new DatabaseSearchPattern((long)randomVal), // Score - between new DatabaseSearchPattern("TestDouble", randomVal3, randomVal3 + ((double)TestParameters.SearchRangeSize / 1000000.0)), // Date time - betwen new DatabaseSearchPattern("TestDT", randomVal4, randomVal4.AddDays(1)), // Date time - less than new DatabaseSearchPattern("TestDT", randomVal4, false), // Date time - greater than new DatabaseSearchPattern("TestDT", randomVal4, true), // Date time - equivalent new DatabaseSearchPattern("TestDT", randomVal4) }; // sort it testPatterns.Sort(DatabaseSearchPattern.Sort(riis)); string isItGucci = ""; }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Generates a random number between 1 and 10; normally 1 will be used for equivalence, 2 for less than or greater than and the remainder for between. /// A special case arises with the equivalence - we only want to use this if there is only one test (this one) in the group of search patterns /// </summary> public static int GenerateExpressionType(int numTestsInGroup) { // We will need to randomly choose the expression type =, >=, <=, BETWEEEN, with only a few results as equivalent // For most of the range queries 1 will be equivalence (and only if there is only one search pattern), 2 is <= or >= and anything else is between... // We want to weight heavily to the between queries as these are truely random and will pull out results from the full range, rather than just the top and tail .. int randomET = MGLEncryption.GenerateRandomInt(1, 10); // If there are more than one query do not go for the equivalence as these will generate too few results... if (randomET == 1 && numTestsInGroup > 1) { while (randomET == 1) { randomET = MGLEncryption.GenerateRandomInt(1, 10); } } return(randomET); }
//----------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Checks whether or not the Key in the CID parameter for this page is valid (this computer based on the AnonID) and the time stamp is current /// If the key should be extracted from the Page URL parameters, just set the encryptedKey to null... /// </summary> protected bool KeyIsValid(StringBuilder encryptedKey) { bool keyIsValid = false; try { // 11-May-2016 - the MGLEncryption.Decrypt method throws a serious level 9 error if no key is provided. // It is better to catch this here and simply return false as this is just due to people not using the tool correctly (or trying to cut corners) if (encryptedKey != null && encryptedKey.Length > 0) { //-----a----- Decrypt the key ... encryptedKey = MGLEncryption.DeHTMLifyString(encryptedKey); StringBuilder decryptedKey = MGLEncryption.Decrypt(encryptedKey); //-----b----- Pull out the anon ID StringBuilder anonID = new StringBuilder(decryptedKey.ToString().Substring(1, 36)); StringBuilder dtStr = new StringBuilder(decryptedKey.ToString().Substring(38, 19)); //-----c----- now check that the dt is within tolerances DateTime dt; DateTime.TryParse(dtStr.ToString(), out dt); TimeSpan ts = DateTime.Now.Subtract(dt); //-----d----- get the anonvalue cookie again ... string tempValue = DefaultAnonID; if (Request.Cookies["AnonID"] != null) { tempValue = Request.Cookies["AnonID"].Value; } //-----e----- So then finally, do the validation on two fronts // a. that the elapsed time span is more than 0 and less than 10 seconds and // b. that the anonID is correct keyIsValid = (ts.TotalSeconds >= 0 && ts.TotalSeconds < 10) && MGLEncryption.AreEqual(anonID, new StringBuilder(tempValue)); } } catch (Exception ex) { Logger.LogError(8, "Problem checking if the authorisation key in the login page is valid. This is serious! The specific error was: " + ex.ToString()); } return(keyIsValid); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Generates a number of randomly generated RedisTestObj objects, with each parameter between a range... /// These are ONLY used for writing, so we can ignore if the readonly flag is enabled /// </summary> public static void GenerateRandomObjects() { // These are ONLY used for writing, so we can ignore if the readonly flag is enabled if (TestParameters.DoWrite == false) { Logger.Log("Skipping generating the random objects as the global TestParameter.JustDoRead parameter is set to read only."); return; } RandomObjects = new List <object>(); // Generate some random data! Logger.LogSubHeading("Generating " + NumIterations + " randomly generated TestObj objects..."); int i = 0; for (i = 0; i < NumIterations; i++) { RandomObjects.Add( // The primary key new TestObj((ulong)i, // A random int MGLEncryption.GenerateRandomInt(1, MaxIntegerInRange), // longs ... MGLEncryption.GenerateRandomLong(TestParameters.MinLongInRange, TestParameters.MaxLongInRange), // doubles ... MGLEncryption.GenerateRandomDouble(TestParameters.MinDoubleInRange, TestParameters.MaxDoubleInRange), // bools ... MGLEncryption.GenerateRandomBool(), // strings ... MGLEncryption.GetSalt(20).ToString(), // DateTime - Standardise the dates to the nearest second so that the MySQL vs Redis comparison is consistent // Otherwise Redis is stored to the nearest MS while MySQL only stores to the nearest second DatabaseSearchPattern.StandardiseDateToStartOfSecond(MGLEncryption.GenerateRandomDateTime(TestParameters.DateMin, TestParameters.DateMax), false))); // Log the progress ... Logger.Log(i, 1000, NumIterations); } Logger.Log(i, 1, NumIterations); Logger.Log("\n"); }
//----------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Get Widget /// </summary> public static PasswordResetWidget GetWidget(StringBuilder guid) { PasswordResetWidget paw = null; if (guid != null && guid.Length > 0) { foreach (PasswordResetWidget tempPAW in Widgets) { // 17-Jul-15 - the MGLPasswordHash is overkill here, lets just use one level of encryption... //if (MGLPasswordHash.Compare( tempPAW.Guid, hashedGUID ) == true) { if (MGLEncryption.AreEqual(guid, tempPAW.Token) == true) { paw = tempPAW; break; } } } // random sleep to confuse on the checking if anyone is monitoring the timings!! Thread.Sleep(new Random().Next(0, 100)); return(paw); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Tests the combining of lists as intersection or union operations ... /// </summary> public static void TestListCombining() { Logger.LogSubHeading("Testing the List combining algorithm ..."); // ok three lists of 1000, 10000 and 100000 done multiple times // Also try to increase this by a factor of 10 too .. /* * Note that the lists wont exactly be this length because of possible duplicates: * Q: How many iterations does it take to cover a range with random values? * A: This is known as the coupon collector's problem. See the link for details and references. * Asymptotically, the expected number of trials needed grows as n ln n (plus lower order terms). * ln is the natural logarithm - see https://en.wikipedia.org/wiki/Natural_logarithm * * More on the coupon collectors problem - https://en.wikipedia.org/wiki/Coupon_collector%27s_problem * For example, when n = 50 it takes about 225 trials to collect all 50 coupons. * This is calculated as 1/probability1 + 1/probability2 + 1/probabilityN e.g. 1/ (Num already chosen/Total Number) * The upshot is that 1000 iterations of a range of randomly generated numbers between 1 and 1000, is likely to produce around 631 unique values. For 10,000, its around 6,320... * So how close we get to this (not too high OR low), is a good indication that our random number generator is on the money.... */ int numIterations = 100; int list1Length = 1000000; // 100000; int list2Length = 10000; // 10000; int list3Length = 100000; // 1000000; int rangeMin = 1; int rangeMax = 1000000; RedisWrapper rw = new RedisWrapper(); Logger.Log("Running " + numIterations + " iterations with three lists of " + list1Length.ToString("N0") + ", " + list2Length.ToString("N0") + " and " + list3Length.ToString("N0") + " randomly generated integers ..."); DateTime start = DateTime.Now; for (int i = 0; i < numIterations; i++) { //-----a----- Generate the random data ... Logger.Log("Iteration " + i + " - Generating the random data ..."); List <List <uint> > listOfLists = new List <List <uint> >(); List <uint> outputIntersection = new List <uint>(); List <uint> outputUnion = new List <uint>(); // List 1 ... we use hashsets to ensure no duplicates... HashSet <uint> list1 = new HashSet <uint>(); for (int j = 0; j < list1Length; j++) { list1.Add((uint)MGLEncryption.GenerateRandomInt(rangeMin, rangeMax)); } listOfLists.Add(list1.ToList()); // List 2 ... HashSet <uint> list2 = new HashSet <uint>(); for (int j = 0; j < list2Length; j++) { list2.Add((uint)MGLEncryption.GenerateRandomInt(rangeMin, rangeMax)); } listOfLists.Add(list2.ToList()); // List 3 ... HashSet <uint> list3 = new HashSet <uint>(); for (int j = 0; j < list3Length; j++) { list3.Add((uint)MGLEncryption.GenerateRandomInt(rangeMin, rangeMax)); } listOfLists.Add(list3.ToList()); Logger.Log("Iteration " + i + " has the following number of unique values for each list: " + list1.Count.ToString("N0") + ", " + list2.Count.ToString("N0") + " and " + list3.Count.ToString("N0") + "."); // Now combine the lists .... Intersection outputIntersection = DataStructures.CombineLists(listOfLists, true); // And union outputUnion = DataStructures.CombineLists(listOfLists, false); Logger.Log("Iteration " + i + " had " + outputIntersection.Count + " matching by intersection and " + outputUnion.Count + " by union."); } TimeSpan procTime = DateTime.Now.Subtract(start); Logger.Log("Completed testing the combining of lists in " + procTime.TotalMilliseconds.ToString("N0") + " seconds."); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- public static DatabaseSearchPattern GenerateSearchPatternDateTime(DateTime min, DateTime max, int numTestsInGroup) { DatabaseSearchPattern rsp = null; //-----a----- Get the expression type (==, <=, >= or between) int randomET = GenerateExpressionType(numTestsInGroup); //-----b----- The default range in HOURS - note that we calculate this in the same manner as the other ranges from the integer parameter (approx 3.6 hrs) int range = (int)Math.Round(TestParameters.DateMax.Subtract(TestParameters.DateMin).TotalHours *TestParameters.SearchRangeSize / TestParameters.MaxIntegerInRange); //----c----- so we want to generalise for multiple tests --- so if numTests > 0, then increase the range and bring in the min and max to ensure a larger range ..... if (numTestsInGroup > 1) { range = range * 18; // becomes roughly three days // 8; // For >= or <= lets also tweak the min and max to ensure the range is larger if (randomET == 2) { min = min.AddHours(range); max = max.AddHours(-range); } } //-----d----- Generate the random value DateTime randomVal = DatabaseSearchPattern.StandardiseDateToStartOfSecond(MGLEncryption.GenerateRandomDateTime(min, max), false); //-----e----- And generate the search pattern as well... if (randomET == 1) //_____ == _____ // Note that for dates equal to - would result in all the results for a specific date and time being returned - which is only very rarely going to return results { rsp = new DatabaseSearchPattern("TestDT", randomVal); } else if (randomET == 2) //_____ >= or <= range search _____ // We need a random bool to determine if this is a >= or a <= search ... { bool randomBool = MGLEncryption.GenerateRandomBool(); // Generate ranges between the temporarily defined max and min above and a range's width above or below these parameters // depending on whether this is greater than or less than ... if (randomBool == true) { randomVal = DatabaseSearchPattern.StandardiseDateToStartOfSecond(MGLEncryption.GenerateRandomDateTime(max.AddHours(-range), max), false); } else { randomVal = DatabaseSearchPattern.StandardiseDateToStartOfSecond(MGLEncryption.GenerateRandomDateTime(min, min.AddHours(range)), false); } // Now add this randomVal as a range query rsp = new DatabaseSearchPattern("TestDT", randomVal, randomBool); } else //_____ Between _____ // Between our randomly generated date and a range's width above this ... { rsp = new DatabaseSearchPattern("TestDT", randomVal, randomVal.AddHours(range)); } return(rsp); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- public static DatabaseSearchPattern GenerateSearchPatternString() { return(new DatabaseSearchPattern("TestStr", MGLEncryption.GetSalt(RedisWrapper.TextIndexLength).ToString().ToLower())); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- public static DatabaseSearchPattern GenerateSearchPatternPrimaryKey(long start, long end) { // We just generate a random number between the start and the end return(new DatabaseSearchPattern(MGLEncryption.GenerateRandomLong(start, end))); }
//-------------------------------------------------------------------------------------------------------------------------------------------------------------- /// <summary> /// Generates n search patterns with between 1 and 3 search parameters randomly chosen from 6 of the RedisTestObj attributes /// 11-Aug-2016 - updated so that the patterns we are searching for are broader if there are multiple tests ... /// 16-Aug-2016 - No longer searching using the TestBool parameter as the query results are far too broad. /// </summary> public static void GenerateRandomPatterns(List <DatabaseIndexInfo> riis) { //-----0----- Reset the list of patterns to search for PatternsToSearchFor = new List <List <DatabaseSearchPattern> >(); // 1=PrimaryKey, 2=Integer, 3=Long, 4=Double, 5=String, 6=DateTime (Note we are not using bool searches here as they are far too sloooow) int totalNumPatterns = 6; //-----1----- Process the number of search pattern groups specified in the global parameter for (int i = 0; i < NumSearchPatterns; i++) { List <DatabaseSearchPattern> rsps = new List <DatabaseSearchPattern>(); //-----2----- Determine how many tests to run and from which parameters... int numTests = MGLEncryption.GenerateRandomInt(1, 3); List <int> testTypes = new List <int>(); for (int j = 0; j < numTests; j++) { int testType = MGLEncryption.GenerateRandomInt(1, totalNumPatterns); //-----2a----- Reduce the number of PK queries in the multiple search parameter queries and instead choose integer range parameters.. if (testType == 1 && j > 0) { testType = 2; } //-----2b----- If this test type already exists, then iterate through and find a test type that has not yet already been chosen while (testTypes.Contains(testType) == true) { testType = MGLEncryption.GenerateRandomInt(1, totalNumPatterns); // Reduce the number of PK queries in the multiple search parameter queries and instead choose integer range parameters.. if (testType == 1 && j > 0) { testType = 2; } } testTypes.Add(testType); //-----3----- Now go through and randomly generate the SearchPattern for each of these test types // We now have about six types of test we are processing... if (testType == 1) //-----a----- ID - Primary Key - Equivalent - individual result ... { rsps.Add(GenerateSearchPatternPrimaryKey(0, TestParameters.NumIterations)); } else if (testType == 2) //-----b----- TestInt - Try to ensure that max results returned is 20% { rsps.Add(GenerateSearchPatternInteger(1, TestParameters.MaxIntegerInRange, numTests)); } else if (testType == 3) //-----c----- TestLong - a range of 4 billion and we are searching between for ranges of 10,000,000 (i.e. 0.25%) { rsps.Add(GenerateSearchPatternLong(TestParameters.MinLongInRange, TestParameters.MaxLongInRange, numTests)); } else if (testType == 4) //-----d----- TestDouble - Try to ensure that max results return is 20% { rsps.Add(GenerateSearchPatternDouble(TestParameters.MinDoubleInRange, TestParameters.MaxDoubleInRange, numTests)); } else if (testType == 5) //-----e----- TestStr - max results returned is 1/(40*40) when using a two char search length { rsps.Add(GenerateSearchPatternString()); } else if (testType == 6) //-----f----- TestDT - searching for ranges in hours { rsps.Add(GenerateSearchPatternDateTime(TestParameters.DateMin, TestParameters.DateMax, numTests)); } } // 19-Aug-2016 - if DoDebug == true, we need to sort here so that the views in the MySQL and Redis debug lists are consistent! // Otherwise it is difficult to compare the results of the two databases afterwards .. if (RedisWrapper.DoDebug == true) { rsps.Sort(DatabaseSearchPattern.Sort(riis)); } // add our new search patterns ... PatternsToSearchFor.Add(rsps); } }
//------------------------------------------------------------------------------------------------------------------------------------------------------------- private void LoadAppDefaults() { TimeSpan t1 = new TimeSpan(DateTime.Now.Ticks); //_____1_____ Set the Application Defaults { MGLApplicationInterface.Instance().ApplicationName = WebConfigurationManager.AppSettings["ApplicationName"]; MGLApplicationInterface.Instance().ApplicationShortName = WebConfigurationManager.AppSettings["ApplicationShortName"]; MGLApplicationInterface.Instance().ApplicationURL = WebConfigurationManager.AppSettings["ApplicationURL"]; // Note that this is reset internally, but good to leave the ref here as a reminder that this deepest darkest code exists ... Authorisation.ApplicationName = MGLApplicationInterface.Instance().ApplicationName; double tempDouble = 0; double.TryParse(WebConfigurationManager.AppSettings["ApplicationVersion"], out tempDouble); KeyInfoExtended.SoftwareVersion = tempDouble; // 16-Mar-2016 - set the PersistentViewState subdirectory PagePersistViewStateToFileSystem.AppendSiteShortNameToFolderName(MGLApplicationInterface.Instance().ApplicationShortName); // 18-Mar-2016 - Get the JS Version ... MGLApplicationInterface.Instance().JSVersion = WebConfigurationManager.AppSettings["JSVersion"]; // 22-Mar-2016 - extract the static resource settings. These are used in HTMLUtilities.BuildStaticResourcesHTML to generate the resource references for static libraries like scripts and styles // Firstly, are the resources stored locally or pulled accross from another domain? MGLApplicationInterface.Instance().StaticResourcePath = WebConfigurationManager.AppSettings["StaticResourcePath"]; // Secondly, is the Javascript in these resources minified bool tempBool = false; bool.TryParse(WebConfigurationManager.AppSettings["StaticJavascriptMinified"], out tempBool); MGLApplicationInterface.Instance().StaticJavascriptIsMinified = tempBool; // 29-Mar-2016 - explicitly turn on or off the removal of leading and trailing whitespace during the page rendering (this saves about 25% of the download size) bool.TryParse(WebConfigurationManager.AppSettings["RemoveWhitespaceFromAllPages"], out tempBool); MGLApplicationInterface.Instance().RemoveWhitespaceFromAllPages = tempBool; } //_____2_____ Start the Logging Activities Logger.StartLog(MGLApplicationInterface.Instance().ApplicationShortName, "c:/logs", false, true, true); //_____3a_____ Load the Configuration Information MglWebConfigurationInfo mwci = MglWebConfigurationInfo.GetConfig(); MglWebConfigurationInfoParamsCollection mwcipc = mwci.ConfigInfoList; ConfigurationInfo ci = new ConfigurationInfo(); bool success = ci.LoadConfigurationInfoFromWebConfig(); // 30-Sep-2015 - Get the username and password from the XML config file ... { SecureString key = null; SecureString auth = null; if (MGLXMLReader.GetInfo(MGLApplicationInterface.Instance().ApplicationShortName, "DatabaseLogin", out key, out auth) == true) { DatabaseConnectionInfo dbConInfo = ci.DbConInfo; dbConInfo.USER = key; dbConInfo.PASSWORD = auth; ci.DbConInfo = dbConInfo; } } // 30-Sep-2015 - Get the SSL Certificate and Password from the XML config file ... { SecureString key = null; SecureString auth = null; if (MGLXMLReader.GetInfo(MGLApplicationInterface.Instance().ApplicationShortName, "DatabaseCertificate", out key, out auth) == true) { DatabaseConnectionInfo dbConInfo = ci.DbConInfo; dbConInfo.SSLCertificatePath = key; dbConInfo.SSLCertificatePassword = auth; ci.DbConInfo = dbConInfo; } } MGL.Web.WebUtilities.MGLApplicationInterface.Instance().ConfigDefault = ci; // Test the database connection string .... DatabaseWrapper dbInfo = new DatabaseWrapper(ci); dbInfo.Connect(); //_____ 1-Dec-2015 - Get the GeoLocation database XML config file settings ... { // The clone method works, we just need to be aware that really robust passwords with special characters don't work fantastically with the mySQL connector ConfigurationInfo ciGeoLocation = ci.Clone(); DatabaseConnectionInfo dbConInfo = ciGeoLocation.DbConInfo; SecureString key = null; SecureString auth = null; if (MGLXMLReader.GetInfo(MGLApplicationInterface.Instance().ApplicationShortName, "DatabaseLoginGeoLocation", out key, out auth) == true) { dbConInfo.USER = key; dbConInfo.PASSWORD = auth; dbConInfo.NAME = "DataNirvana_GeoLocation"; } ciGeoLocation.DbConInfo = dbConInfo; MGLApplicationInterface.Instance().GeoLocationConfig = ciGeoLocation; } //_____3b_____ Set up the physical application path ONCE .... if (MGLApplicationInterface.Instance().ConfigDefault != null && MGLApplicationInterface.Instance().PhysicalPathToApplicationRoot == null) { // 14-Oct-2013 - Changed this to use app domain - that seems to be a better usage of the process and it also means that we can put it in the global.asax string physicalPath = AppDomain.CurrentDomain.BaseDirectory.ToString(); physicalPath = physicalPath.Replace("\\", "/"); MGLApplicationInterface.Instance().PhysicalPathToApplicationRoot = physicalPath; } //_____4a_____ Setup the default email settings ... SetupDefaultEmail(); //_____4b_____ Setup the default cryptography stuff ... // The temporary application encryption key (e.g. for the search tables ...) { MGLApplicationInterface.Instance().EncryptionAppKey = MGLEncryption.GenerateKey(); } // 5-Jul-15 - Set the MGLEncryption Key from the web config ... { SecureString key = null; SecureString auth = null; if (MGLXMLReader.GetInfo(MGLApplicationInterface.Instance().ApplicationShortName, "EncryptKeyDefault", out key, out auth) == true) { MGLEncryption.SetCryptKey = key; } } //_____5a_____ Application Specific Setup - Setup all the countries, application variables for Organisations, Indicators and Sectors DataNirvanaWebProcessing wpHA = new DataNirvanaWebProcessing(MGLApplicationInterface.Instance().ConfigDefault); // Uncomment when the database is setup .... // success = success & wp.SetAllIndicators(); // success = success & wp.SetAllSectors(); success = success & wpHA.SetAllOrganisations(true); // success = success & wp.SetAllActivityStates(); // success = success & wp.SetAllCountries(); // success = success & wp.SetSpatialReferenceDefault(); WebDocProcessing wdp = new WebDocProcessing(MGLApplicationInterface.Instance().ConfigDefault); KeyInfo.Tags = wdp.GetAllWebDocTags(); //_____5b_____ Application Specific Setup - Set the ProGres Application key ... // 5-Jul-15 - Set the ProgresTokens (Public and Private) //{ // SecureString key = null; // SecureString auth = null; // if (MGLXMLReader.GetInfo(MGLApplicationInterface.Instance().ApplicationShortName, "EncryptKeyProGresPrivate", out key, out auth) == true) { // PNAApplicationInterface.Instance().ProGresEncryptionTokenPrivate = key; // } //} //{ // SecureString key = null; // SecureString auth = null; // if (MGLXMLReader.GetInfo(MGLApplicationInterface.Instance().ApplicationShortName, "EncryptKeyProGresPublic", out key, out auth) == true) { // PNAApplicationInterface.Instance().ProGresEncryptionTokenPublic = key; // } //} //_____5c_____ Application Specific Setup - Setup all the lookup lists //PNACaseWebProcessing pnaCaseWP = new PNACaseWebProcessing(MGLApplicationInterface.Instance().ConfigDefault); bool tempSuccess = false; // ListOfPNACaseStatuses //PNAApplicationInterface.Instance().ListOfPNACaseStatuses = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfPNACaseStatuses, out tempSuccess, true); success = success & tempSuccess; // ListOfPNAIndividualStatuses //PNAApplicationInterface.Instance().ListOfPNAIndividualStatuses = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfPNAIndividualStatuses, out tempSuccess, true); success = success & tempSuccess; // ListOfPNAPriorities - added -15-Dec-2015 //PNAApplicationInterface.Instance().ListOfPNAPriorities = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfPNAPriorities, out tempSuccess, true); success = success & tempSuccess; // ListOfUNHCROffices //PNAApplicationInterface.Instance().ListOfUNHCROffices = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfUNHCROffices, out tempSuccess, true); success = success & tempSuccess; // ListOfAlreadyRegistered //PNAApplicationInterface.Instance().ListOfAlreadyRegistered = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfAlreadyRegistered, out tempSuccess, true); success = success & tempSuccess; // ListOfTravelledBefore //PNAApplicationInterface.Instance().ListOfTravelledBefore = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfTravelledBefore, out tempSuccess, true); success = success & tempSuccess; // ListOfHasPoRCard //PNAApplicationInterface.Instance().ListOfHasPoRCard = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfHasPoRCard, out tempSuccess, true); success = success & tempSuccess; // ListOfReligion //PNAApplicationInterface.Instance().ListOfReligion = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfReligion, out tempSuccess, true); success = success & tempSuccess; // ListOfLanguage //PNAApplicationInterface.Instance().ListOfLanguage = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfLanguage, out tempSuccess, true); success = success & tempSuccess; // ListOfEthnicity //PNAApplicationInterface.Instance().ListOfEthnicity = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfEthnicity, out tempSuccess, true); success = success & tempSuccess; // ListOfDocumentaryProof //PNAApplicationInterface.Instance().ListOfDocumentaryProof = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfDocumentaryProof, out tempSuccess, true); success = success & tempSuccess; // ListOfCountries //PNAApplicationInterface.Instance().ListOfCountries = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfCountries, out tempSuccess, true); success = success & tempSuccess; // ListOfCoACountries - a rather shortened affair ... //PNAApplicationInterface.Instance().ListOfCoACountries = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfCoACountries, out tempSuccess, true); success = success & tempSuccess; // ListOfNationalities //PNAApplicationInterface.Instance().ListOfNationalities = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfNationalities, out tempSuccess, true); success = success & tempSuccess; // ListOfYesNo //PNAApplicationInterface.Instance().ListYesNo = pnaCaseWP.SetupListGeneric(KeyInfo.ListYesNo, out tempSuccess, true); success = success & tempSuccess; // ListOfSex //PNAApplicationInterface.Instance().ListOfSex = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfSex, out tempSuccess, true); success = success & tempSuccess; // ListOfMaritalStatusesPNA //PNAApplicationInterface.Instance().ListMaritalStatus = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfMaritalStatusesPNA, out tempSuccess, true); success = success & tempSuccess; // ListOfRelationshipToHoH //PNAApplicationInterface.Instance().ListOfRelationshipToHoH = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfRelationshipToHoH, out tempSuccess, true); success = success & tempSuccess; // ListOfEducationLevels //PNAApplicationInterface.Instance().ListOfEducationLevels = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfEducationLevels, out tempSuccess, true); success = success & tempSuccess; // ListOfEducationDegreeTypes //PNAApplicationInterface.Instance().ListOfEducationDegreeTypes = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfEducationQualificationTypes, out tempSuccess, true); success = success & tempSuccess; // ListOfOccupations //PNAApplicationInterface.Instance().ListOfOccupations = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfOccupations, out tempSuccess, true); success = success & tempSuccess; // ListOfWillingToReturn //PNAApplicationInterface.Instance().ListOfWillingToReturn = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfWillingToReturn, out tempSuccess, true); success = success & tempSuccess; // ListOfAddressLocationTypes //PNAApplicationInterface.Instance().ListOfAddressLocationTypes = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfAddressLocationTypes, out tempSuccess, true); success = success & tempSuccess; // ListOfAddressTypes //PNAApplicationInterface.Instance().ListOfAddressTypes = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfAddressTypes, out tempSuccess, true); success = success & tempSuccess; // ListOfPNAReferralRecommendations - added 16-Dec-2015 //PNAApplicationInterface.Instance().ListOfPNAReferralRecommendations = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfPNAReferralRecommendations, out tempSuccess, true); success = success & tempSuccess; // ListOfPNANonReferralReasons - added 16-Dec-2015 //PNAApplicationInterface.Instance().ListOfPNANonReferralReasons = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfPNANonReferralReasons, out tempSuccess, true); success = success & tempSuccess; //_____ Set up the Geographies // For the PNA tool, we cannot use the lists of geographies that EVERYONE ELSE IN THE ENTIRE WORLD USES, so we need to use the old ones from ProGres to be consistent // In this ancient list from ProGres, FATA and KP are equivalent to NWFP!!!! // CoO Province //PNAApplicationInterface.Instance().ListOfCoOProvinces = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfCoOProvinces, out tempSuccess, true); success = success & tempSuccess; // CoO District //PNAApplicationInterface.Instance().ListOfCoODistricts = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfCoODistricts, out tempSuccess, true); success = success & tempSuccess; // CoA Province //PNAApplicationInterface.Instance().ListOfCoAProvinces = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfCoAProvinces, out tempSuccess, true); success = success & tempSuccess; // CoA District //PNAApplicationInterface.Instance().ListOfCoADistricts = pnaCaseWP.SetupListGeneric(KeyInfo.ListOfCoADistricts, out tempSuccess, true); success = success & tempSuccess; //_____6_____ Configure the Security ... MGL.Security.SecuritySetup.Configure(true, MGLApplicationInterface.Instance().ApplicationName, MGLApplicationInterface.Instance().ApplicationURL, ci.Clone()); // 25-Jan-2015 - also store the list of Users in the KeyInfo static class so that they are accessible to other threads that cannot access application variables // Also wipe the passwords from the objects as these are irrelevant (and weak security) .... // note that wiping the passwords in this way (essentially by the linked "by reference" objects" means that the passwords are wiped from both the online repositories ... KeyInfo.AllUsers = new Dictionary <int, MGUser>(); foreach (int key in MGLApplicationSecurityInterface.Instance().Users.Keys) { MGUser u; MGLApplicationSecurityInterface.Instance().Users.TryGetValue(key, out u); u.Password = null; KeyInfo.AllUsers.Add(key, u); } // now reset the original application interface with the users without passwords ... MGLApplicationSecurityInterface.Instance().Users = KeyInfo.AllUsers; //_____7_____ Application Specific Setup - // Make the default root an absolute path so that if links are called in e.g. Ajax pages then they will work ... HTMLUtilities.DefaultPath = ((MGLApplicationSecurityInterface.Instance().AppLoginConfig.UseHTTPS) ? "https://" : "http://") + ci.WebProjectPath(); HTMLUtilities.ImageRootDirectory = "Images/"; // 23-Dec-2015 - allows applications to use the https independently in a specific session, even if it is turned off in the global applications settings (sourced from the web.config) MGLApplicationInterface.Instance().UseHttpsSessionsIndependently = true; //_____8_____ Log the application start in the db .... // Check whether the connection to the db is using SSL DatabaseWrapper dbInfo2 = new DatabaseWrapper(ci); string sslCipher, sslStartDate, sslEndDate, sslProtocol; bool isSSLConn = dbInfo2.IsSSLConnection(out sslCipher, out sslStartDate, out sslEndDate, out sslProtocol); // Calculate how long the start up took TimeSpan t2 = new TimeSpan(DateTime.Now.Ticks); TimeSpan diff = t2.Subtract(t1); // build the "url" with all the params ... string logURL = "Application_Start?AppIsSSL=" + MGLApplicationSecurityInterface.Instance().AppLoginConfig.UseHTTPS + "&DBIsSSL=" + isSSLConn + "&Protocol=" + sslProtocol + "&SSLCipher=" + sslCipher + "&SSLStart=" + sslStartDate + "&SSLEnd=" + sslEndDate; // 14-Jan-2016 - Get the IP Address // 31-Jan-2016 - But this doesn't work unfortunately in the context of the applcation start - produces an error "Request not available in this context" string srcIPAddress = "0.0.0.0"; // Log the application start using a special user ID LoggerDB.LogPageRequestInDatabase(ci, MGLApplicationInterface.Instance().ApplicationName, "Application_Start", "Application_Start", logURL, DateTime.Now, diff.TotalMilliseconds, 1010101, srcIPAddress); // And send an email with that the application has started ... // MGLSecureEmailer.SendEmail("*****@*****.**", "Eddie", "Application Started - " + MGLApplicationInterface.Instance().ApplicationName, // "Application " + MGLApplicationInterface.Instance().ApplicationName + " started at " + DateTime.Now.ToString(), // "", null, null, null, null, 0, true); }