mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-05-19 18:58:03 +02:00
feat: cli migrate to cobra with subcommands (#550)
* feat: migrate CLI to cobra with dump/list/version subcommands (#546) * fix: remove residual duckduckgo references and add README/LICENSE to release archives * fix: address PR review feedback from Copilot
This commit is contained in:
@@ -57,6 +57,7 @@ func NewBrowsers(cfg types.BrowserConfig) ([]*Browser, error) {
|
||||
}
|
||||
|
||||
func (b *Browser) BrowserName() string { return b.cfg.Name }
|
||||
func (b *Browser) ProfileDir() string { return b.profileDir }
|
||||
func (b *Browser) ProfileName() string {
|
||||
if b.profileDir == "" {
|
||||
return ""
|
||||
@@ -173,8 +174,9 @@ func (b *Browser) extractCategory(data *types.BrowserData, cat types.Category, m
|
||||
}
|
||||
}
|
||||
|
||||
// discoverProfiles lists subdirectories of userDataDir that contain at least
|
||||
// one known data source. Each such directory is a browser profile.
|
||||
// discoverProfiles lists subdirectories of userDataDir that are valid
|
||||
// Chromium profile directories. A directory is considered a profile if it
|
||||
// contains a "Preferences" file, which Chromium creates for every profile.
|
||||
func discoverProfiles(userDataDir string, sources map[types.Category][]sourcePath) []string {
|
||||
entries, err := os.ReadDir(userDataDir)
|
||||
if err != nil {
|
||||
@@ -188,18 +190,41 @@ func discoverProfiles(userDataDir string, sources map[types.Category][]sourcePat
|
||||
continue
|
||||
}
|
||||
dir := filepath.Join(userDataDir, e.Name())
|
||||
if hasAnySource(sources, dir) {
|
||||
if isProfileDir(dir) {
|
||||
profiles = append(profiles, dir)
|
||||
}
|
||||
}
|
||||
|
||||
// Flat layout fallback (older Opera): data files directly in userDataDir
|
||||
// Flat layout fallback (older Opera): data files directly in userDataDir.
|
||||
// Opera stores data alongside Local State in userDataDir itself, so check
|
||||
// for any known source file instead of Preferences.
|
||||
if len(profiles) == 0 && hasAnySource(sources, userDataDir) {
|
||||
profiles = append(profiles, userDataDir)
|
||||
}
|
||||
return profiles
|
||||
}
|
||||
|
||||
// profileMarkers are filenames that identify a directory as a Chromium profile.
|
||||
// Chromium creates a per-profile preferences file on first use; checking for
|
||||
// its existence filters out non-profile subdirectories (Crashpad, ShaderCache, etc.).
|
||||
//
|
||||
// - "Preferences" — standard Chromium and all major forks (Chrome, Edge, Brave, …)
|
||||
// - "Preferences_02" — Tencent-based browsers (QQ Browser, Sogou Explorer)
|
||||
var profileMarkers = []string{
|
||||
"Preferences",
|
||||
"Preferences_02",
|
||||
}
|
||||
|
||||
// isProfileDir reports whether dir is a valid Chromium profile directory.
|
||||
func isProfileDir(dir string) bool {
|
||||
for _, name := range profileMarkers {
|
||||
if _, err := os.Stat(filepath.Join(dir, name)); err == nil {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// hasAnySource checks if dir contains at least one source file or directory.
|
||||
func hasAnySource(sources map[types.Category][]sourcePath, dir string) bool {
|
||||
for _, candidates := range sources {
|
||||
|
||||
@@ -45,6 +45,7 @@ func buildFixtures() {
|
||||
fixture.chrome = filepath.Join(fixture.root, "chrome")
|
||||
mkFile(fixture.chrome, "Local State")
|
||||
for _, p := range []string{"Default", "Profile 1", "Profile 3"} {
|
||||
mkFile(fixture.chrome, p, "Preferences")
|
||||
mkFile(fixture.chrome, p, "Login Data")
|
||||
mkFile(fixture.chrome, p, "History")
|
||||
mkFile(fixture.chrome, p, "Bookmarks")
|
||||
@@ -60,6 +61,7 @@ func buildFixtures() {
|
||||
|
||||
fixture.opera = filepath.Join(fixture.root, "opera")
|
||||
mkFile(fixture.opera, "Local State")
|
||||
mkFile(fixture.opera, "Default", "Preferences")
|
||||
mkFile(fixture.opera, "Default", "Login Data")
|
||||
mkFile(fixture.opera, "Default", "History")
|
||||
mkFile(fixture.opera, "Default", "Bookmarks")
|
||||
@@ -73,6 +75,7 @@ func buildFixtures() {
|
||||
|
||||
fixture.yandex = filepath.Join(fixture.root, "yandex")
|
||||
mkFile(fixture.yandex, "Local State")
|
||||
mkFile(fixture.yandex, "Default", "Preferences")
|
||||
mkFile(fixture.yandex, "Default", "Ya Passman Data")
|
||||
mkFile(fixture.yandex, "Default", "Ya Credit Cards")
|
||||
mkFile(fixture.yandex, "Default", "History")
|
||||
@@ -80,14 +83,17 @@ func buildFixtures() {
|
||||
mkFile(fixture.yandex, "Default", "Bookmarks")
|
||||
|
||||
fixture.oldCookies = filepath.Join(fixture.root, "old-cookies")
|
||||
mkFile(fixture.oldCookies, "Default", "Preferences")
|
||||
mkFile(fixture.oldCookies, "Default", "History")
|
||||
mkFile(fixture.oldCookies, "Default", "Cookies")
|
||||
|
||||
fixture.bothCookies = filepath.Join(fixture.root, "both-cookies")
|
||||
mkFile(fixture.bothCookies, "Default", "Preferences")
|
||||
mkFile(fixture.bothCookies, "Default", "Cookies")
|
||||
mkFile(fixture.bothCookies, "Default", "Network", "Cookies")
|
||||
|
||||
fixture.leveldb = filepath.Join(fixture.root, "leveldb")
|
||||
mkFile(fixture.leveldb, "Default", "Preferences")
|
||||
mkFile(fixture.leveldb, "Default", "History")
|
||||
mkDir(fixture.leveldb, "Default", "Local Storage", "leveldb")
|
||||
mkFile(fixture.leveldb, "Default", "Local Storage", "leveldb", "000001.ldb")
|
||||
@@ -95,6 +101,7 @@ func buildFixtures() {
|
||||
mkFile(fixture.leveldb, "Default", "Session Storage", "000001.ldb")
|
||||
|
||||
fixture.leveldbOnly = filepath.Join(fixture.root, "leveldb-only")
|
||||
mkFile(fixture.leveldbOnly, "Default", "Preferences")
|
||||
mkDir(fixture.leveldbOnly, "Default", "Local Storage", "leveldb")
|
||||
mkDir(fixture.leveldbOnly, "Default", "Session Storage")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user