Beispiel #1
0
        public Entry[] FindLogins(string[] URLs, string actionURL, string httpRealm, LoginSearchType lst, bool requireFullURLMatches, string uniqueID, string dbFileName, string freeTextSearch)
        {
            List<PwDatabase> dbs = null;
            int count = 0;
            List<Entry> allEntries = new List<Entry>();

            if (!string.IsNullOrEmpty(dbFileName))
            {
                // find the database
                PwDatabase db = SelectDatabase(dbFileName);
                dbs = new List<PwDatabase>();
                dbs.Add(db);
            } else
                // if DB list is not populated, look in all open DBs
                dbs = host.MainWindow.DocumentManager.GetOpenDatabases();

            //string hostname = URLs[0];
            string actionHost = actionURL;

            // Make sure there is an active database
            if (!ensureDBisOpen()) { return null; }

            // if uniqueID is supplied, match just that one login. if not found, move on to search the content of the logins...
            if (uniqueID != null && uniqueID.Length > 0)
            {
                PwUuid pwuuid = new PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray(uniqueID));

                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    PwEntry matchedLogin = GetRootPwGroup(db).FindEntry(pwuuid, true);

                    if (matchedLogin == null)
                        continue;

                    Entry[] logins = new Entry[1];
                    logins[0] = (Entry)GetEntryFromPwEntry(matchedLogin, true, true, db);
                    if (logins[0] != null)
                        return logins;
                }
            }

            if (!string.IsNullOrEmpty(freeTextSearch))
            {
                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    KeePassLib.Collections.PwObjectList<PwEntry> output = new KeePassLib.Collections.PwObjectList<PwEntry>();

                    PwGroup searchGroup = GetRootPwGroup(db);
                    //output = searchGroup.GetEntries(true);
                    SearchParameters sp = new SearchParameters();
                    sp.ComparisonMode = StringComparison.InvariantCultureIgnoreCase;
                    sp.SearchString = freeTextSearch;
                    sp.SearchInUserNames = true;
                    sp.SearchInTitles = true;
                    sp.SearchInTags = true;
                    searchGroup.SearchEntries(sp, output, false);

                    foreach (PwEntry pwe in output)
                    {
                        Entry kpe = (Entry)GetEntryFromPwEntry(pwe, true, true, db);
                        allEntries.Add(kpe);
                        count++;
                    }
                }

            }
            // else we search for the URLs

            if (count == 0 && URLs.Length > 0 && !string.IsNullOrEmpty(URLs[0]))
            {
                int protocolIndex = -1;
                Dictionary<string, string> URLHostnames = new Dictionary<string, string>();

                // make sure that hostname and actionURL always represent only the hostname portion
                // of the URL
                // It's tempting to demand that the protocol must match too (e.g. http forms won't
                // match a stored https login) but best not to define such a restriction in KeePassRPC
                // - the RPC client (e.g. KeeFox) can decide to penalise protocol mismatches,
                // potentially dependant on user configuration options in the client.
                for (int i = 0; i < URLs.Length; i++)
                {
                    string URL = URLs[i];
                    string newURL = URL;
                    protocolIndex = URL.IndexOf("://");
                    string hostAndPort = "";
                    if (URL.IndexOf("file://") > -1)
                    {
                        // the "host and port" of a file is the actual file name (i.e. just not the query string)

                        int qsIndex = URL.IndexOf("?");
                        if (qsIndex > -1)
                            newURL = URL.Substring(8, qsIndex - 8);
                        else
                            newURL = URL.Substring(8);
                    }
                    else if (protocolIndex > -1)
                    {
                        string URLExcludingProt = URL.Substring(protocolIndex + 3);
                        int pathStart = URLExcludingProt.IndexOf("/", 0);

                        if (pathStart > -1 && URLExcludingProt.Length > pathStart)
                        {
                            hostAndPort = URL.Substring(protocolIndex + 3, pathStart);
                            newURL = URL.Substring(0, pathStart + protocolIndex + 3);
                        }
                        else if (pathStart == -1) // it's already just a hostname
                        {
                            hostAndPort = URLExcludingProt;
                        }
                    }
                    else
                    {
                        // we havn't received a protocol but may still have a query string
                        // we'd like to remove from the URL (e.g. especially if we're dealing with an unknown file:///)
                        int qsIndex = URL.IndexOf("?");
                        if (qsIndex > -1)
                            newURL = URL.Substring(1, qsIndex - 1);
                    }

                    URLHostnames.Add(URLs[i], hostAndPort);
                }

                protocolIndex = (actionURL == null) ? -1 : actionURL.IndexOf("://");
                if (protocolIndex > -1)
                {
                    string actionURLAndPort = actionURL.Substring(protocolIndex + 3);
                    int pathStart = actionURLAndPort.IndexOf("/", 0);
                    if (pathStart > -1 && actionURLAndPort.Length > pathStart)
                    {
                        actionHost = actionURL.Substring(0, pathStart + protocolIndex + 3);
                    }
                }

                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    KeePassLib.Collections.PwObjectList<PwEntry> output = new KeePassLib.Collections.PwObjectList<PwEntry>();

                    PwGroup searchGroup = GetRootPwGroup(db);
                    output = searchGroup.GetEntries(true);

                    // Search every entry in the DB
                    foreach (PwEntry pwe in output)
                    {
                        if (db.RecycleBinUuid.EqualsValue(pwe.ParentGroup.Uuid))
                            continue; // ignore if it's in the recycle bin

                        if (pwe.Strings.Exists("Hide from KeeFox") || pwe.Strings.Exists("Hide from KPRPC") || string.IsNullOrEmpty(pwe.Strings.ReadSafe("URL")))
                            continue; // entries must have a standard URL entry

                        bool allowHostnameOnlyMatch = true;
                        if (pwe.Strings.Exists("KPRPC Block hostname-only match"))
                        {
                            allowHostnameOnlyMatch = false;
                        }

                        bool entryIsAMatch = false;
                        bool entryIsAnExactMatch = false;

                        string regexPatterns = null;
                        if (pwe.Strings.Exists("KeeFox URL Regex match"))
                            regexPatterns = pwe.Strings.ReadSafe("KeeFox URL Regex match");
                        if (pwe.Strings.Exists("KPRPC URL Regex match"))
                            regexPatterns = pwe.Strings.ReadSafe("KPRPC URL Regex match");
                        if (!string.IsNullOrEmpty(regexPatterns))
                            foreach (string URL in URLs)
                                foreach (string regexPattern in regexPatterns.Split(' '))
                                {
                                    if (!string.IsNullOrEmpty(regexPattern) && System.Text.RegularExpressions.Regex.IsMatch(URL, regexPattern))
                                    {
                                        entryIsAMatch = true;
                                        break;
                                    }
                                }

                        foreach (string URL in URLs)
                        {
                            if (!entryIsAMatch && lst != LoginSearchType.LSTnoForms && matchesAnyURL(pwe, URL, URLHostnames[URL], allowHostnameOnlyMatch))
                            {
                                if (pwe.Strings.Exists("Form match URL") && pwe.Strings.ReadSafe("Form match URL") == actionURL && pwe.Strings.ReadSafe("URL") == URL)
                                {
                                    entryIsAnExactMatch = true;
                                    entryIsAMatch = true;
                                }
                                else if (!requireFullURLMatches)
                                    entryIsAMatch = true;
                            }
                        }

                        foreach (string URL in URLs)
                        {
                            if (!entryIsAMatch && lst != LoginSearchType.LSTnoRealms && matchesAnyURL(pwe, URL, URLHostnames[URL], allowHostnameOnlyMatch))
                            {
                                if ((
                                    (pwe.Strings.Exists("Form HTTP realm")
                                    && pwe.Strings.ReadSafe("Form HTTP realm").Length > 0
                                    && (httpRealm == "" || pwe.Strings.ReadSafe("Form HTTP realm") == httpRealm)
                                    )
                                    ||
                                    (pwe.Strings.Exists("KPRPC HTTP realm")
                                    && pwe.Strings.ReadSafe("KPRPC HTTP realm").Length > 0
                                    && (httpRealm == "" || pwe.Strings.ReadSafe("KPRPC HTTP realm") == httpRealm)
                                    ))
                                    && pwe.Strings.ReadSafe("URL") == URL)
                                {
                                    entryIsAnExactMatch = true;
                                    entryIsAMatch = true;
                                }
                                else if (!requireFullURLMatches)
                                    entryIsAMatch = true;
                            }
                        }

                        foreach (string URL in URLs)
                        {
                            // If we think we found a match, check it's not on a block list
                            if (entryIsAMatch && matchesAnyBlockedURL(pwe, URL))
                            {
                                entryIsAMatch = false;
                                break;
                            }
                            if (entryIsAMatch && pwe.Strings.Exists("KPRPC URL Regex block"))
                            {
                                string patterns = pwe.Strings.ReadSafe("KPRPC URL Regex block");
                                foreach (string pattern in patterns.Split(' '))
                                {
                                    if (!string.IsNullOrEmpty(pattern) && System.Text.RegularExpressions.Regex.IsMatch(URL, pattern))
                                    {
                                        entryIsAMatch = false;
                                        break;
                                    }
                                }
                            }
                        }

                        if (entryIsAMatch)
                        {
                            Entry kpe = (Entry)GetEntryFromPwEntry(pwe, entryIsAnExactMatch, true, db);
                            allEntries.Add(kpe);
                            count++;
                        }
                    }
                }
            }

            allEntries.Sort(delegate(Entry e1, Entry e2)
                {
                    return e1.Title.CompareTo(e2.Title);
                });

            return allEntries.ToArray();
        }
Beispiel #2
0
        public int CountLogins(string URL, string actionURL, string httpRealm, LoginSearchType lst, bool requireFullURLMatches)
        {
            string hostname = URL;
            string actionHost = actionURL;

            // make sure that hostname and actionURL always represent only the hostname portion
            // of the URL

            int protocolIndex = URL.IndexOf("://");
            if (URL.IndexOf("file://") > -1)
            {
                // the "host and port" of a file is the actual file name (i.e. just not the query string)

                int qsIndex = URL.IndexOf("?");
                if (qsIndex > -1)
                    hostname = URL.Substring(8, qsIndex - 8);
                else
                    hostname = URL.Substring(8);
            }
            else if (protocolIndex > -1)
            {
                string hostAndPort = URL.Substring(protocolIndex + 3);
                int pathStart = hostAndPort.IndexOf("/", 0);
                if (pathStart > -1 && hostAndPort.Length > pathStart)
                {
                    hostname = URL.Substring(0, pathStart + protocolIndex + 3);
                }
            }
            else
            {
                // we havn't received a protocol but may still have a query string
                // we'd like to remove from the URL (e.g. especially if we're dealing with a file:///
                int qsIndex = URL.IndexOf("?");
                if (qsIndex > -1)
                    hostname = URL.Substring(1, qsIndex - 1);
            }

            protocolIndex = actionURL.IndexOf("://");
            if (protocolIndex > -1)
            {
                string actionURLAndPort = actionURL.Substring(protocolIndex + 3);
                int pathStart = actionURLAndPort.IndexOf("/", 0);
                if (pathStart > -1 && actionURLAndPort.Length > pathStart)
                {
                    actionHost = actionURL.Substring(0, pathStart + protocolIndex + 3);
                }
            }

            int count = 0;
            ArrayList allEntries = new ArrayList();

            // Make sure there is an active database
            if (!ensureDBisOpen()) return -1;

            // Narrow down the possible matches by doing a KeePass search
            // (We could match on an irrelevant string field but chances are that any matches are suitable)
            SearchParameters sp = new SearchParameters();
            sp.SearchInUrls = true;
            sp.SearchInOther = true;
            sp.RegularExpression = true;
            if (URL.Length == 0)
                sp.SearchString = ".*";
            else if (requireFullURLMatches)
                sp.SearchString = System.Text.RegularExpressions.Regex.Escape(URL);
            else
                sp.SearchString = System.Text.RegularExpressions.Regex.Escape(hostname);

            KeePassLib.Collections.PwObjectList<PwEntry> output;
            output = new KeePassLib.Collections.PwObjectList<PwEntry>();

            PwGroup searchGroup = GetRootPwGroup(host.Database);
            searchGroup.SearchEntries(sp, output, false);
            foreach (PwEntry pwe in output)
            {
                if (host.Database.RecycleBinUuid.EqualsValue(pwe.ParentGroup.Uuid))
                    continue; // ignore if it's in the recycle bin

                if (pwe.Strings.Exists("Hide from KeeFox") || pwe.Strings.Exists("Hide from KPRPC") || string.IsNullOrEmpty(pwe.Strings.ReadSafe("URL")))
                    continue;

                bool entryIsAMatch = false;

                if (lst != LoginSearchType.LSTnoForms && matchesAnyURL(pwe, hostname,hostname,false))
                {
                    if (pwe.Strings.Exists("Form match URL") && pwe.Strings.ReadSafe("Form match URL") == actionURL && pwe.Strings.ReadSafe("URL") == URL)
                    {
                        entryIsAMatch = true;
                    }
                    else if (!requireFullURLMatches)
                        entryIsAMatch = true;
                }

                if (lst != LoginSearchType.LSTnoRealms && matchesAnyURL(pwe, hostname, hostname, false))
                {
                    if ((
                        (pwe.Strings.Exists("Form HTTP realm")
                        && pwe.Strings.ReadSafe("Form HTTP realm").Length > 0
                        && (httpRealm == "" || pwe.Strings.ReadSafe("Form HTTP realm") == httpRealm)
                        )
                        ||
                        (pwe.Strings.Exists("KPRPC HTTP realm")
                        && pwe.Strings.ReadSafe("KPRPC HTTP realm").Length > 0
                        && (httpRealm == "" || pwe.Strings.ReadSafe("KPRPC HTTP realm") == httpRealm)
                        ))
                        && pwe.Strings.ReadSafe("URL") == URL)
                    {
                        entryIsAMatch = true;
                    }
                    else if (!requireFullURLMatches)
                        entryIsAMatch = true;
                }

                if (entryIsAMatch)
                    count++;

            }

            return count;
        }
Beispiel #3
0
 public int CountLogins(string URL, string actionURL, string httpRealm, LoginSearchType lst, bool requireFullURLMatches)
 {
     throw new NotImplementedException();
 }
Beispiel #4
0
        public Entry[] FindLogins(string[] URLs, string actionURL, string httpRealm, LoginSearchType lst, bool requireFullURLMatches, 
            string uniqueID, string dbFileName, string freeTextSearch, string username)
        {
            List<PwDatabase> dbs = null;
            int count = 0;
            List<Entry> allEntries = new List<Entry>();

            if (!string.IsNullOrEmpty(dbFileName))
            {
                // find the database
                PwDatabase db = SelectDatabase(dbFileName);
                dbs = new List<PwDatabase>();
                dbs.Add(db);
            }
            else
            {
                // if DB list is not populated, look in all open DBs
                dbs = host.MainWindow.DocumentManager.GetOpenDatabases();
                // unless the DB is the wrong version
                dbs = dbs.FindAll(ConfigIsCorrectVersion);
            }

            //string hostname = URLs[0];
            string actionHost = actionURL;

            // Make sure there is an active database
            if (!ensureDBisOpen()) { return null; }

            // if uniqueID is supplied, match just that one login. if not found, move on to search the content of the logins...
            if (uniqueID != null && uniqueID.Length > 0)
            {
                PwUuid pwuuid = new PwUuid(KeePassLib.Utility.MemUtil.HexStringToByteArray(uniqueID));

                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    PwEntry matchedLogin = GetRootPwGroup(db).FindEntry(pwuuid, true);

                    if (matchedLogin == null)
                        continue;

                    Entry[] logins = new Entry[1];
                    logins[0] = (Entry)GetEntryFromPwEntry(matchedLogin, MatchAccuracy.Best, true, db);
                    if (logins[0] != null)
                        return logins;
                }
            }

            if (!string.IsNullOrEmpty(freeTextSearch))
            {
                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    KeePassLib.Collections.PwObjectList<PwEntry> output = new KeePassLib.Collections.PwObjectList<PwEntry>();

                    PwGroup searchGroup = GetRootPwGroup(db);
                    //output = searchGroup.GetEntries(true);
                    SearchParameters sp = new SearchParameters();
                    sp.ComparisonMode = StringComparison.InvariantCultureIgnoreCase;
                    sp.SearchString = freeTextSearch;
                    sp.SearchInUserNames = true;
                    sp.SearchInTitles = true;
                    sp.SearchInTags = true;
                    MethodInfo mi;

                    // SearchEntries method signature changed in KP 2.17 so we use
                    // reflection to enable support for both 2.17 and earlier versions
                    try
                    {
                        mi = typeof(PwGroup).GetMethod("SearchEntries", new Type[] { typeof(SearchParameters), typeof(KeePassLib.Collections.PwObjectList<PwEntry>) });
                        mi.Invoke(searchGroup, new object[] { sp, output });
                    }
                    catch (AmbiguousMatchException ex)
                    {
                        // can't find the 2.17 method definition so try for an earlier version
                        mi = typeof(PwGroup).GetMethod("SearchEntries", new Type[] { typeof(SearchParameters), typeof(KeePassLib.Collections.PwObjectList<PwEntry>), typeof(bool) });
                        mi.Invoke(searchGroup, new object[] { sp, output, false });

                        // If an exception is thrown here it would be unexpected and
                        // require a new version of the application to be released
                    }

                    foreach (PwEntry pwe in output)
                    {
                        Entry kpe = (Entry)GetEntryFromPwEntry(pwe, MatchAccuracy.None, true, db);
                        if (kpe != null)
                        {
                            allEntries.Add(kpe);
                            count++;
                        }
                    }
                }

            }
            // else we search for the URLs

            if (count == 0 && URLs.Length > 0 && !string.IsNullOrEmpty(URLs[0]))
            {
                int protocolIndex = -1;
                Dictionary<string, URLSummary> URLHostnameAndPorts = new Dictionary<string, URLSummary>();

                // make sure that hostname and actionURL always represent only the hostname portion
                // of the URL
                // It's tempting to demand that the protocol must match too (e.g. http forms won't
                // match a stored https login) but best not to define such a restriction in KeePassRPC
                // - the RPC client (e.g. KeeFox) can decide to penalise protocol mismatches,
                // potentially dependant on user configuration options in the client.
                for (int i = 0; i < URLs.Length; i++)
                {
                    URLHostnameAndPorts.Add(URLs[i], URLSummary.FromURL(URLs[i]));
                }

                //foreach DB...
                foreach (PwDatabase db in dbs)
                {
                    KeePassLib.Collections.PwObjectList<PwEntry> output = new KeePassLib.Collections.PwObjectList<PwEntry>();

                    PwGroup searchGroup = GetRootPwGroup(db);
                    output = searchGroup.GetEntries(true);
                    List<string> configErrors = new List<string>(1);

                    // Search every entry in the DB
                    foreach (PwEntry pwe in output)
                    {
                        string entryUserName = pwe.Strings.ReadSafe(PwDefs.UserNameField);
                        entryUserName = KeePassRPCPlugin.GetPwEntryStringFromDereferencableValue(pwe, entryUserName, db);
                        if (EntryIsInRecycleBin(pwe, db))
                            continue; // ignore if it's in the recycle bin

                        //if (string.IsNullOrEmpty(pwe.Strings.ReadSafe("URL")))
                        //    continue; // entries must have a standard URL entry

                        string json = KeePassRPCPlugin.GetPwEntryString(pwe, "KPRPC JSON", db);
                        EntryConfig conf;
                        if (string.IsNullOrEmpty(json))
                        {
                            conf = new EntryConfig();
                        }
                        else
                        {
                            try
                            {
                                conf = (EntryConfig)Jayrock.Json.Conversion.JsonConvert.Import(typeof(EntryConfig), json);
                            }
                            catch (Exception ex)
                            {
                                configErrors.Add("Username: "******". URL: " + pwe.Strings.ReadSafe("URL"));
                                continue;
                            }
                        }

                        if (conf.Hide)
                            continue;

                        bool entryIsAMatch = false;
                        int bestMatchAccuracy = MatchAccuracy.None;

                        if (conf.RegExURLs != null)
                            foreach (string URL in URLs)
                                foreach (string regexPattern in conf.RegExURLs)
                                {
                                    try
                                    {
                                        if (!string.IsNullOrEmpty(regexPattern) && System.Text.RegularExpressions.Regex.IsMatch(URL, regexPattern))
                                        {
                                            entryIsAMatch = true;
                                            bestMatchAccuracy = MatchAccuracy.Best;
                                            break;
                                        }
                                    }
                                    catch (ArgumentException)
                                    {
                                        MessageBox.Show("'" + regexPattern + "' is not a valid regular expression. This error was found in an entry in your database called '" + pwe.Strings.ReadSafe(PwDefs.TitleField) + "'. You need to fix or delete this regular expression to prevent this warning message appearing.", "Warning: Broken regular expression", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                        break;
                                    }
                                }

                        // Check for matching URLs for the page containing the form
                        if (!entryIsAMatch && lst != LoginSearchType.LSTnoForms
                                && (string.IsNullOrEmpty(username) || username == entryUserName))
                        {
                            foreach (string URL in URLs)
                        {

                                int accuracy = bestMatchAccuracyForAnyURL(pwe, conf, URL, URLHostnameAndPorts[URL]);
                                if (accuracy > bestMatchAccuracy)
                                    bestMatchAccuracy = accuracy;

                            }
                        }

                        // Check for matching URLs for the HTTP Auth containing the form
                        if (!entryIsAMatch && lst != LoginSearchType.LSTnoRealms
                                && (string.IsNullOrEmpty(username) || username == entryUserName))

                        {
                            foreach (string URL in URLs)
                            {
                                int accuracy = bestMatchAccuracyForAnyURL(pwe, conf, URL, URLHostnameAndPorts[URL]);
                                if (accuracy > bestMatchAccuracy)
                                    bestMatchAccuracy = accuracy;
                            }
                        }

                        if (bestMatchAccuracy == MatchAccuracy.Best
                            || (!requireFullURLMatches && bestMatchAccuracy > MatchAccuracy.None))
                            entryIsAMatch = true;

                        foreach (string URL in URLs)
                        {
                            // If we think we found a match, check it's not on a block list
                            if (entryIsAMatch && matchesAnyBlockedURL(pwe, conf, URL))
                            {
                                entryIsAMatch = false;
                                break;
                            }
                            if (conf.RegExBlockedURLs != null)
                                foreach (string pattern in conf.RegExBlockedURLs)
                                {
                                    try
                                    {
                                        if (!string.IsNullOrEmpty(pattern) && System.Text.RegularExpressions.Regex.IsMatch(URL, pattern))
                                        {
                                            entryIsAMatch = false;
                                            break;
                                        }
                                    }
                                    catch (ArgumentException)
                                    {
                                        MessageBox.Show("'" + pattern + "' is not a valid regular expression. This error was found in an entry in your database called '" + pwe.Strings.ReadSafe(PwDefs.TitleField) + "'. You need to fix or delete this regular expression to prevent this warning message appearing.", "Warning: Broken regular expression", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                                        break;
                                    }
                                }
                        }

                        if (entryIsAMatch)
                        {
                            Entry kpe = (Entry)GetEntryFromPwEntry(pwe, bestMatchAccuracy, true, db);
                            if (kpe != null)
                            {
                                allEntries.Add(kpe);
                                count++;
                            }
                        }

                    }
                    if (configErrors.Count > 0)
                        MessageBox.Show("There are configuration errors in your database called '" + db.Name + "'. To fix the entries listed below and prevent this warning message appearing, please edit the value of the 'KeePassRPC JSON config' advanced string. Please ask for help on http://keefox.org/help/forum if you're not sure how to fix this. These entries are affected:" + Environment.NewLine + string.Join(Environment.NewLine, configErrors.ToArray()), "Warning: Configuration errors", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }
            }
            allEntries.Sort(delegate(Entry e1, Entry e2)
            {
                return e1.Title.CompareTo(e2.Title);
            });

            return allEntries.ToArray();
        }
Beispiel #5
0
        public int CountLogins(string URL, string actionURL, string httpRealm, LoginSearchType lst, bool requireFullURLMatches)
        {
            throw new NotImplementedException();

            //string hostname = URL;
            //string actionHost = actionURL;

            //// make sure that hostname and actionURL always represent only the hostname portion
            //// of the URL

            //int protocolIndex = URL.IndexOf("://");
            //if (URL.IndexOf("file://") > -1)
            //{
            //    // the "host and port" of a file is the actual file name (i.e. just not the query string)

            //    int qsIndex = URL.IndexOf("?");
            //    if (qsIndex > -1)
            //        hostname = URL.Substring(8, qsIndex - 8);
            //    else
            //        hostname = URL.Substring(8);
            //}
            //else if (protocolIndex > -1)
            //{
            //    string hostAndPort = URL.Substring(protocolIndex + 3);
            //    int pathStart = hostAndPort.IndexOf("/", 0);
            //    if (pathStart > -1 && hostAndPort.Length > pathStart)
            //    {
            //        hostname = URL.Substring(0, pathStart + protocolIndex + 3);
            //    }
            //}
            //else
            //{
            //    // we havn't received a protocol but may still have a query string
            //    // we'd like to remove from the URL (e.g. especially if we're dealing with a file:///
            //    int qsIndex = URL.IndexOf("?");
            //    if (qsIndex > -1)
            //        hostname = URL.Substring(1, qsIndex - 1);
            //}

            //protocolIndex = actionURL.IndexOf("://");
            //if (protocolIndex > -1)
            //{
            //    string actionURLAndPort = actionURL.Substring(protocolIndex + 3);
            //    int pathStart = actionURLAndPort.IndexOf("/", 0);
            //    if (pathStart > -1 && actionURLAndPort.Length > pathStart)
            //    {
            //        actionHost = actionURL.Substring(0, pathStart + protocolIndex + 3);
            //    }
            //}

            //int count = 0;
            //ArrayList allEntries = new ArrayList();

            //// Make sure there is an active database
            //if (!ensureDBisOpen()) return -1;

            //// Narrow down the possible matches by doing a KeePass search
            //// (We could match on an irrelevant string field but chances are that any matches are suitable)
            //SearchParameters sp = new SearchParameters();
            //sp.SearchInUrls = true;
            //sp.SearchInOther = true;
            //sp.RegularExpression = true;
            //if (URL.Length == 0)
            //    sp.SearchString = ".*";
            //else if (requireFullURLMatches)
            //    sp.SearchString = System.Text.RegularExpressions.Regex.Escape(URL);
            //else
            //    sp.SearchString = System.Text.RegularExpressions.Regex.Escape(hostname);

            //KeePassLib.Collections.PwObjectList<PwEntry> output;
            //output = new KeePassLib.Collections.PwObjectList<PwEntry>();

            //PwGroup searchGroup = GetRootPwGroup(host.Database);
            //MethodInfo mi;

            //// SearchEntries method signature changed in KP 2.17 so we use
            //// reflection to enable support for both 2.17 and earlier versions
            //try
            //{
            //    mi = typeof(PwGroup).GetMethod("SearchEntries", new Type[] { typeof(SearchParameters), typeof(KeePassLib.Collections.PwObjectList<PwEntry>) });
            //    mi.Invoke(searchGroup, new object[] { sp, output });
            //}
            //catch (AmbiguousMatchException ex)
            //{
            //    // can't find the 2.17 method definition so try for an earlier version
            //    mi = typeof(PwGroup).GetMethod("SearchEntries", new Type[] { typeof(SearchParameters), typeof(KeePassLib.Collections.PwObjectList<PwEntry>), typeof(bool) });
            //    mi.Invoke(searchGroup, new object[] { sp, output, false });

            //    // If an exception is thrown here it would be unexpected and
            //    // require a new version of the application to be released
            //}

            //foreach (PwEntry pwe in output)
            //{
            //    if (host.Database.RecycleBinUuid.EqualsValue(pwe.ParentGroup.Uuid))
            //        continue; // ignore if it's in the recycle bin

            //    if (pwe.Strings.Exists("Hide from KeeFox") || pwe.Strings.Exists("Hide from KPRPC") || string.IsNullOrEmpty(pwe.Strings.ReadSafe("URL")))
            //        continue;

            //    bool entryIsAMatch = false;

            //    if (lst != LoginSearchType.LSTnoForms && matchesAnyURL(pwe, hostname, hostname, false))
            //    {
            //        if (pwe.Strings.Exists("Form match URL") && pwe.Strings.ReadSafe("Form match URL") == actionURL && pwe.Strings.ReadSafe("URL") == URL)
            //        {
            //            entryIsAMatch = true;
            //        }
            //        else if (!requireFullURLMatches)
            //            entryIsAMatch = true;
            //    }

            //    if (lst != LoginSearchType.LSTnoRealms && matchesAnyURL(pwe, hostname, hostname, false))
            //    {
            //        if ((
            //            (pwe.Strings.Exists("Form HTTP realm")
            //            && pwe.Strings.ReadSafe("Form HTTP realm").Length > 0
            //            && (httpRealm == "" || pwe.Strings.ReadSafe("Form HTTP realm") == httpRealm)
            //            )
            //            ||
            //            (pwe.Strings.Exists("KPRPC HTTP realm")
            //            && pwe.Strings.ReadSafe("KPRPC HTTP realm").Length > 0
            //            && (httpRealm == "" || pwe.Strings.ReadSafe("KPRPC HTTP realm") == httpRealm)
            //            ))
            //            && pwe.Strings.ReadSafe("URL") == URL)
            //        {
            //            entryIsAMatch = true;
            //        }
            //        else if (!requireFullURLMatches)
            //            entryIsAMatch = true;
            //    }

            //    if (entryIsAMatch)
            //        count++;

            //}

            //return count;
        }