/// <summary> /// Entry point to the detection process. Provided with a <see cref="Match"/> /// configured with the information about the request. /// </summary> /// <remarks> /// The dataSet may be used by other threads in parallel and is not assumed to be used /// by only one detection process at a time. /// </remarks> /// <param name="match"> /// The match object to be updated. /// </param> /// <remarks> /// The memory implementation of the data set will always perform fastest but does /// consume more memory. /// </remarks> internal static void Match( Match match) { if (match.DataSet.Disposed) throw new InvalidOperationException( "Data Set has been disposed and can't be used for match"); // If the user agent is too short then don't try to match and // return defaults. if (match.TargetUserAgentArray.Length == 0 || match.TargetUserAgentArray.Length < match.DataSet.MinUserAgentLength) { // Set the default values. MatchDefault(match); } else { // Starting at the far right evaluate the nodes in the data // set recording matched nodes. Continue until all character // positions have been checked. Evaluate(match); // Can a precise match be found based on the nodes? var signatureIndex = match.GetExactSignatureIndex(); if (signatureIndex >= 0) { // Yes a precise match was found. match._signature = match.DataSet.Signatures[signatureIndex]; match._method = MatchMethods.Exact; match.LowestScore = 0; } else { // No. So find any other nodes that match if numeric differences // are considered. EvaluateNumeric(match); // Can a precise match be found based on the nodes? signatureIndex = match.GetExactSignatureIndex(); if (signatureIndex >= 0) { // Yes a precise match was found. match._signature = match.DataSet.Signatures[signatureIndex]; match._method = MatchMethods.Numeric; } else if (match.Nodes.Count > 0) { // Look for the closest signatures to the nodes found. var closestSignatures = match.GetClosestSignatures(); #if DEBUG // Validate the list is in ascending order of ranked signature index. var enumerator = closestSignatures.GetEnumerator(); var lastIndex = -1; while (enumerator.MoveNext()) { Debug.Assert(lastIndex < enumerator.Current); lastIndex = enumerator.Current; } #endif // Try finding a signature with identical nodes just not in exactly the // same place. _nearest.EvaluateSignatures(match, closestSignatures.Select(i => match.DataSet.Signatures[match.DataSet.RankedSignatureIndexes[i].Value])); if (match._signature != null) { // All the sub strings matched, just in different character positions. match._method = MatchMethods.Nearest; } else { // Find the closest signatures and compare them // to the target looking at the smallest character // difference. _closest.EvaluateSignatures(match, closestSignatures.Select(i => match.DataSet.Signatures[match.DataSet.RankedSignatureIndexes[i].Value])); match._method = MatchMethods.Closest; } } } // If there still isn't a signature then set the default. if (match._profiles == null && match._signature == null) MatchDefault(match); } }