Example #1
0
        public void TestDistance()
        {
            string s1 = "This is the first string";
            string s2 = "And this is another string";

            var sift4 = new Sift4
            {
                MaxOffset = 5
            };

            double result = sift4.Distance(s1, s2);

            Assert.Equal(
                expected: 11.0,
                actual: result,
                precision: 1); // 0.0

            sift4.MaxOffset = 10;

            result = sift4.Distance(
                "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
                "Amet Lorm ispum dolor sit amet, consetetur adixxxpiscing elit.");

            Assert.Equal(
                expected: 12.0,
                actual: result,
                precision: 1); // 0.0
        }
Example #2
0
        internal static IEnumerable <FileInfo> SortListExecutables(IEnumerable <FileInfo> targets, string targetString)
        {
            int GetPenaltyPoints(FileInfo fileInfo)
            {
                if (fileInfo.Name.Equals("uninstaller.exe", StringComparison.OrdinalIgnoreCase) ||
                    fileInfo.Name.Equals("uninstall.exe", StringComparison.OrdinalIgnoreCase) ||
                    fileInfo.Name.Contains("unins00", StringComparison.OrdinalIgnoreCase))
                {
                    return(20);
                }
                if (fileInfo.Name.Contains("uninsta", StringComparison.OrdinalIgnoreCase))
                {
                    return(4);
                }
                if (fileInfo.Name.Contains("unins", StringComparison.OrdinalIgnoreCase))
                {
                    return(2);
                }
                return(0);
            }

            return(targets.Select(x => new { x, p = GetPenaltyPoints(x) })
                   .OrderBy(x => Sift4.SimplestDistance(x.x.Name, targetString, 3) + x.p)
                   .Select(x => x.x));
        }
        /// <summary>
        /// Check if there are any similar names that match DisplayNameTrimmed, and if there are then add negative confidence to names other than the best match.
        /// This is to avoid e.g. `AppX Extended` matching junk entries from `AppX`
        /// </summary>
        internal static void TestForSimilarNames(ApplicationUninstallerEntry thisUninstaller, IEnumerable <ApplicationUninstallerEntry> otherUninstallers,
                                                 ICollection <KeyValuePair <JunkResultBase, string> > createdJunk)
        {
            if (createdJunk.Count == 0)
            {
                return;
            }

            var thisDisplayName = thisUninstaller.DisplayNameTrimmed;

            // Check if any of the other apps match any of the entries, as long as the app names don't contain this app's name
            var otherFiltered     = otherUninstallers.Where(x => x != thisUninstaller && !x.DisplayNameTrimmed.Contains(thisDisplayName)).ToList();
            var matchingWithOther = createdJunk.Where(x => otherFiltered.Any(y => y.DisplayNameTrimmed.Contains(x.Value)));

            if (createdJunk.Count >= 2)
            {
                // Check for folders with similar names like `AppX Extended` and `AppX` and give confidence penalty to every one other than the best match
                matchingWithOther = matchingWithOther
                                    .Concat(createdJunk
                                            .Where(x => x.Value.Contains(thisDisplayName) || thisDisplayName.Contains(x.Value))
                                            .OrderBy(x => Sift4.SimplestDistance(x.Value, thisDisplayName, 100))
                                            .Skip(1))
                                    .Distinct();
            }

            foreach (var sketchyJunk in matchingWithOther)
            {
                sketchyJunk.Key.Confidence.Add(ConfidenceRecords.UsedBySimilarNamedApp);
            }
        }
        /// <summary>
        /// -1 if match failed, 0 if string matched perfectly, higher if match was worse
        /// </summary>
        internal static int MatchStringToProductName(ApplicationUninstallerEntry applicationUninstallerEntry, string str)
        {
            var productName = applicationUninstallerEntry.DisplayNameTrimmed.ToLowerInvariant();

            str = str.Replace('_', ' ').ToLowerInvariant().Trim();
            var lowestLength = Math.Min(productName.Length, str.Length);

            // Don't match short strings
            if (lowestLength <= 4)
            {
                return(-1);
            }

            var result = Sift4.SimplestDistance(productName, str, 1);

            // Strings match perfectly
            if (result <= 1)
            {
                return(result);
            }

            // If the product name contains company name, try trimming it and testing again
            var publisher = applicationUninstallerEntry.PublisherTrimmed.ToLower();

            if (publisher.Length > 4 && productName.Contains(publisher))
            {
                var trimmedProductName = productName.Replace(publisher, "").Trim();
                if (trimmedProductName.Length <= 4)
                {
                    return(-1);
                }

                var trimmedResult = Sift4.SimplestDistance(trimmedProductName, str, 1);

                if (trimmedResult <= 1)
                {
                    return(trimmedResult);
                }
            }

            var dirToName = str.Contains(productName);
            var nameToDir = productName.Contains(str);

            if (dirToName || nameToDir)
            {
                return(2);
            }

            // Hard cut-off if the difference is more than a third of the checked name
            if (result < lowestLength / 3)
            {
                return(result);
            }

            return(-1);
        }
Example #5
0
        /// <summary>
        /// -1 if match failed, 0 if string matched perfectly, higher if match was worse
        /// </summary>
        protected int MatchStringToProductName(string str)
        {
            var productName = Uninstaller.DisplayNameTrimmed.ToLowerInvariant();

            str = str.Replace('_', ' ').ToLowerInvariant().Trim();
            var lowestLength = Math.Min(productName.Length, str.Length);

            // Don't match short strings
            if (lowestLength <= 4)
            {
                return(-1);
            }

            var result = Sift4.SimplestDistance(productName, str, 1);

            // Strings match perfectly
            if (result <= 1)
            {
                return(result);
            }

            // If the product name contains company name, try trimming it and testing again
            var publisher = Uninstaller.PublisherTrimmed.ToLower();

            if (publisher.Length > 4 && productName.Contains(publisher))
            {
                var trimmedProductName = productName.Replace(publisher, "").Trim();
                if (trimmedProductName.Length <= 4)
                {
                    return(-1);
                }

                var trimmedResult = Sift4.SimplestDistance(trimmedProductName, str, 1);

                if (trimmedResult <= 1)
                {
                    return(trimmedResult);
                }
            }

            var dirToName = str.Contains(productName);
            var nameToDir = productName.Contains(str);

            if (dirToName || nameToDir)
            {
                return(2);
            }

            if (result < lowestLength / 3)
            {
                return(result);
            }

            return(-1);
        }
        private static bool CompareStrings(string a, string b)
        {
            if (a == null || a.Length < 5 || b == null || b.Length < 5)
            {
                return(false);
            }

            /* Old algorithm, much slower
             * var changesRequired = StringTools.CompareSimilarity(a, b);
             * return changesRequired < a.Length / 6;*/

            var changesRequired = Sift4.SimplestDistance(a, b, 3);

            return(changesRequired < a.Length / 6);
        }
        private static bool?CompareStrings(string a, string b, bool relaxMatchRequirement = false)
        {
            var lengthRequirement = !relaxMatchRequirement ? 5 : 4;

            if (a == null || (a.Length < lengthRequirement) || b == null || b.Length < lengthRequirement)
            {
                return(null);
            }

            if (relaxMatchRequirement)
            {
                if (a.StartsWith(b, StringComparison.Ordinal) || b.StartsWith(a, StringComparison.Ordinal))
                {
                    return(true);
                }
            }

            var changesRequired = Sift4.SimplestDistance(a, b, 3);

            return(changesRequired == 0 || changesRequired < a.Length / 6);
        }
 internal static IEnumerable <FileInfo> SortListExecutables(IEnumerable <FileInfo> targets, string targetString)
 {
     return(targets.OrderBy(x => Sift4.SimplestDistance(x.Name, targetString, 3)));
 }