From eed1d12282a8098d12c9b43a299999ae39a7d118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E1=B4=8D=E1=B4=8F=E1=B4=8F=C9=B4D4=CA=80=E1=B4=8B?= Date: Sat, 13 Jan 2024 15:58:53 +0800 Subject: [PATCH] dev: refactor items and update repo deploy (#278) * refactor: Refactor file paths and use map to store item names - Refactored file paths for various browsing data types to use a consistent method of generating temporary file names - Modified parsing functions in many browsing data types to use the new temporary file naming scheme - Renamed `FileName` to `Filename` for consistency in the `item` package - Removed unnecessary code and comments throughout various files - Made minor improvements to some Item methods such as `TempFilename` and `FileName` * ci: Optimize GitHub actions and update Go versions. (#274) * ci: Optimize GitHub actions and update Go versions. - Add GitHub actions for unit testing, linting, building, and releasing - Use a matrix strategy to test on different versions and platforms - Update setup-go and go-version options for compatibility - Format code and build zip files for different operating systems - Upload releases to GitHub with specific asset names and types * fix: Refactor item file naming convention - Update `filename()` function to return `UnsupportedItem` in specific cases - Replace `UnknownItem` with `UnsupportedItem` in `Filename` method of `Item` struct - Refactor code for clarity and consistency * ci: Update GitHub workflow with latest setup-go version - Update setup-go action to v3 in lint.yml GitHub workflow - Omits some big changes in file diff summary - Improve overall workflow reliability and efficiency * ci: Improve GitHub actions across platforms - Improve Windows compatibility in build workflow - Optimize unit testing for pull requests - Upgrade Coveralls GitHub action to v2 for improved coverage tracking * build: Optimize build process for consistency and efficiency - Ensure consistency of line endings by disabling Git's automatic conversion - Add format check for Windows systems - Update Go version in strategy matrix to `1.21.x` - Remove unused dependencies from build process - Include all packages in repository in build command * ci: Refactor GitHub workflow configuration - Remove unnecessary checks for `windows-latest` in github workflow - Change `gofmt` check to `diff` for formatting - Remove unneeded Git configuration for encoding of line endings - Close #273 * ci: Update default branch references in GitHub Actions workflows (#277) - Update Github Actions workflows to use `main` branch instead of `master`. - Rename `master` branch to `main` in `lint.yml` and `build.yml` files. - Change default branch to `main` in `contributors.yml` workflow file. --- .github/workflows/build.yml | 50 +++--- .github/workflows/contributors.yml | 2 +- .github/workflows/lint.yml | 5 +- .github/workflows/release.yml | 2 +- .github/workflows/unittest.yml | 43 +++++ .gitignore | 3 + browser/chromium/chromium.go | 8 +- browser/chromium/chromium_darwin.go | 2 +- browser/chromium/chromium_linux.go | 2 +- browser/chromium/chromium_windows.go | 4 +- browser/firefox/firefox.go | 4 +- browsingdata/bookmark/bookmark.go | 8 +- browsingdata/cookie/cookie.go | 8 +- browsingdata/creditcard/creditcard.go | 8 +- browsingdata/download/download.go | 8 +- browsingdata/extension/extension.go | 8 +- browsingdata/history/history.go | 8 +- browsingdata/localstorage/localstorage.go | 8 +- browsingdata/password/password.go | 14 +- browsingdata/sessionstorage/sessionstorage.go | 8 +- item/filename.go | 57 ------ item/item.go | 166 ++++++++---------- item/item_test.go | 129 ++++++++++++++ 23 files changed, 328 insertions(+), 227 deletions(-) create mode 100644 .github/workflows/unittest.yml delete mode 100644 item/filename.go create mode 100644 item/item_test.go diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0eddb54..8791aa2 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,34 +1,42 @@ name: build + on: push: branches: - - master + - main pull_request: + jobs: build: - name: Build - runs-on: ubuntu-latest + name: Build on ${{ matrix.os }} + runs-on: ${{ matrix.os }} strategy: matrix: - goVer: ["1.21"] + os: [ubuntu-latest, windows-latest, macos-latest] + goVer: ["1.21.x"] steps: - - name: Set up Go ${{ matrix.goVer }} - uses: actions/setup-go@v1 - with: - go-version: ${{ matrix.goVer }} - id: go + - name: Set up Go ${{ matrix.goVer }} + uses: actions/setup-go@v1 + with: + go-version: ${{ matrix.goVer }} + id: go - - name: Check out code into the Go module directory - uses: actions/checkout@v2 + - name: Check out code into the Go module directory + uses: actions/checkout@v2 - - name: Get dependencies - run: | - go get -v -t -d ./... - go get gopkg.in/check.v1 - - - name: Format - run: diff -u <(echo -n) <(gofmt -d .) - - - name: Build - run: go build -v ./... + - name: Set Git to handle line endings consistently + run: git config --global core.autocrlf false + + - name: Format Check + if: matrix.os != 'windows-latest' + run: | + diff -u <(echo -n) <(gofmt -d .) + + - name: Get dependencies + run: | + go get -v -t -d ./... + go get gopkg.in/check.v1 + + - name: Build + run: go build -v ./... diff --git a/.github/workflows/contributors.yml b/.github/workflows/contributors.yml index da90b3c..e07091b 100644 --- a/.github/workflows/contributors.yml +++ b/.github/workflows/contributors.yml @@ -4,7 +4,7 @@ on: - cron: '0 1 * * 0' # At 01:00 on Sunday. push: branches: - - master + - main workflow_dispatch: inputs: logLevel: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 655665b..c1a8af0 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -2,9 +2,8 @@ name: Lint on: push: branches: - - master + - main pull_request: - jobs: lint: name: Lint @@ -13,7 +12,7 @@ jobs: - name: Set Golang uses: actions/setup-go@v3 with: - go-version: "1.21" + go-version: "1.21.x" - name: Checkout code uses: actions/checkout@v3 - name: Lint diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c5d2a6b..f97f5b6 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,7 +13,7 @@ jobs: - name: Use Golang uses: actions/setup-go@v3 with: - go-version: "1.21" + go-version: "1.21.x" - name: Build with xgo uses: crazy-max/ghaction-xgo@v2 diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml new file mode 100644 index 0000000..5411269 --- /dev/null +++ b/.github/workflows/unittest.yml @@ -0,0 +1,43 @@ +on: + [pull_request] + +name: run tests +jobs: + test: + strategy: + matrix: + go-version: [ "1.21.x" ] + platform: [ubuntu-latest] + runs-on: ${{ matrix.platform }} + steps: + - name: Install Go + if: success() + uses: actions/setup-go@v3 + with: + go-version: ${{ matrix.go-version }} + - name: Checkout code + uses: actions/checkout@v2 + - name: Run tests + run: go test -v ./... -covermode=count + + coverage: + runs-on: ubuntu-latest + steps: + - name: Install Go + if: success() + uses: actions/setup-go@v3 + with: + go-version: "1.21.x" + - name: Checkout code + uses: actions/checkout@v2 + - name: Calc coverage + run: | + go test -v ./... -covermode=count -coverprofile=coverage.out + + - name: Convert coverage.out to coverage.lcov + uses: jandelgado/gcov2lcov-action@v1 + - name: Coveralls + uses: coverallsapp/github-action@v2 + with: + github-token: ${{ secrets.github_token }} + path-to-lcov: coverage.lcov \ No newline at end of file diff --git a/.gitignore b/.gitignore index cc894e9..ad208e1 100644 --- a/.gitignore +++ b/.gitignore @@ -194,3 +194,6 @@ hack-browser-data !/browsingdata/history !/browsingdata/history/history.go !/browsingdata/history/history_test.go + +# github action +!/.github/workflows/unittest.yml \ No newline at end of file diff --git a/browser/chromium/chromium.go b/browser/chromium/chromium.go index 9968f15..4dd498b 100644 --- a/browser/chromium/chromium.go +++ b/browser/chromium/chromium.go @@ -76,7 +76,7 @@ func (c *Chromium) BrowsingData(isFullExport bool) (*browsingdata.Data, error) { func (c *Chromium) copyItemToLocal() error { for i, path := range c.itemPaths { - filename := i.String() + filename := i.TempFilename() var err error switch { case fileutil.IsDirExists(path): @@ -109,7 +109,7 @@ func (c *Chromium) userItemPaths(profilePath string, items []item.Item) (map[str var dir string for userDir, v := range multiItemPaths { for _, p := range v { - if strings.HasSuffix(p, item.ChromiumKey.FileName()) { + if strings.HasSuffix(p, item.ChromiumKey.Filename()) { keyPath = p dir = userDir break @@ -132,7 +132,7 @@ func (c *Chromium) userItemPaths(profilePath string, items []item.Item) (map[str func chromiumWalkFunc(items []item.Item, multiItemPaths map[string]map[item.Item]string) filepath.WalkFunc { return func(path string, info fs.FileInfo, err error) error { for _, v := range items { - if info.Name() == v.FileName() { + if info.Name() == v.Filename() { if strings.Contains(path, "System Profile") { continue } @@ -153,7 +153,7 @@ func chromiumWalkFunc(items []item.Item, multiItemPaths map[string]map[item.Item func fillLocalStoragePath(itemPaths map[item.Item]string, storage item.Item) { if p, ok := itemPaths[item.ChromiumHistory]; ok { - lsp := filepath.Join(filepath.Dir(p), storage.FileName()) + lsp := filepath.Join(filepath.Dir(p), storage.Filename()) if fileutil.IsDirExists(lsp) { itemPaths[item.ChromiumLocalStorage] = lsp } diff --git a/browser/chromium/chromium_darwin.go b/browser/chromium/chromium_darwin.go index 549b4be..b69b599 100644 --- a/browser/chromium/chromium_darwin.go +++ b/browser/chromium/chromium_darwin.go @@ -24,7 +24,7 @@ var ( func (c *Chromium) GetMasterKey() ([]byte, error) { // don't need chromium key file for macOS - defer os.Remove(item.TempChromiumKey) + defer os.Remove(item.ChromiumKey.TempFilename()) // Get the master key from the keychain // $ security find-generic-password -wa 'Chrome' var ( diff --git a/browser/chromium/chromium_linux.go b/browser/chromium/chromium_linux.go index da23500..e950c22 100644 --- a/browser/chromium/chromium_linux.go +++ b/browser/chromium/chromium_linux.go @@ -18,7 +18,7 @@ import ( func (c *Chromium) GetMasterKey() ([]byte, error) { // what is d-bus @https://dbus.freedesktop.org/ // don't need chromium key file for Linux - defer os.Remove(item.TempChromiumKey) + defer os.Remove(item.ChromiumKey.TempFilename()) conn, err := dbus.SessionBus() if err != nil { diff --git a/browser/chromium/chromium_windows.go b/browser/chromium/chromium_windows.go index bbe26b3..ca41780 100644 --- a/browser/chromium/chromium_windows.go +++ b/browser/chromium/chromium_windows.go @@ -18,11 +18,11 @@ import ( var errDecodeMasterKeyFailed = errors.New("decode master key failed") func (c *Chromium) GetMasterKey() ([]byte, error) { - b, err := fileutil.ReadFile(item.TempChromiumKey) + b, err := fileutil.ReadFile(item.ChromiumKey.TempFilename()) if err != nil { return nil, err } - defer os.Remove(item.TempChromiumKey) + defer os.Remove(item.ChromiumKey.TempFilename()) encryptedKey := gjson.Get(b, "os_crypt.encrypted_key") if !encryptedKey.Exists() { diff --git a/browser/firefox/firefox.go b/browser/firefox/firefox.go index d690826..31778e7 100644 --- a/browser/firefox/firefox.go +++ b/browser/firefox/firefox.go @@ -43,7 +43,7 @@ func New(profilePath string, items []item.Item) ([]*Firefox, error) { func (f *Firefox) copyItemToLocal() error { for i, path := range f.itemPaths { - filename := i.String() + filename := i.TempFilename() if err := fileutil.CopyFile(path, filename); err != nil { return err } @@ -54,7 +54,7 @@ func (f *Firefox) copyItemToLocal() error { func firefoxWalkFunc(items []item.Item, multiItemPaths map[string]map[item.Item]string) fs.WalkDirFunc { return func(path string, info fs.DirEntry, err error) error { for _, v := range items { - if info.Name() == v.FileName() { + if info.Name() == v.Filename() { parentBaseDir := fileutil.ParentBaseDir(path) if _, exist := multiItemPaths[parentBaseDir]; exist { multiItemPaths[parentBaseDir][v] = path diff --git a/browsingdata/bookmark/bookmark.go b/browsingdata/bookmark/bookmark.go index 364359b..90252b6 100644 --- a/browsingdata/bookmark/bookmark.go +++ b/browsingdata/bookmark/bookmark.go @@ -27,11 +27,11 @@ type bookmark struct { } func (c *ChromiumBookmark) Parse(_ []byte) error { - bookmarks, err := fileutil.ReadFile(item.TempChromiumBookmark) + bookmarks, err := fileutil.ReadFile(item.ChromiumBookmark.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempChromiumBookmark) + defer os.Remove(item.ChromiumBookmark.TempFilename()) r := gjson.Parse(bookmarks) if r.Exists() { roots := r.Get("roots") @@ -94,11 +94,11 @@ const ( ) func (f *FirefoxBookmark) Parse(_ []byte) error { - db, err := sql.Open("sqlite3", item.TempFirefoxBookmark) + db, err := sql.Open("sqlite3", item.FirefoxBookmark.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempFirefoxBookmark) + defer os.Remove(item.FirefoxBookmark.TempFilename()) defer db.Close() _, err = db.Exec(closeJournalMode) if err != nil { diff --git a/browsingdata/cookie/cookie.go b/browsingdata/cookie/cookie.go index 505a4fd..8cf6a92 100644 --- a/browsingdata/cookie/cookie.go +++ b/browsingdata/cookie/cookie.go @@ -36,11 +36,11 @@ const ( ) func (c *ChromiumCookie) Parse(masterKey []byte) error { - db, err := sql.Open("sqlite3", item.TempChromiumCookie) + db, err := sql.Open("sqlite3", item.ChromiumCookie.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempChromiumCookie) + defer os.Remove(item.ChromiumCookie.TempFilename()) defer db.Close() rows, err := db.Query(queryChromiumCookie) if err != nil { @@ -104,11 +104,11 @@ const ( ) func (f *FirefoxCookie) Parse(_ []byte) error { - db, err := sql.Open("sqlite3", item.TempFirefoxCookie) + db, err := sql.Open("sqlite3", item.FirefoxCookie.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempFirefoxCookie) + defer os.Remove(item.FirefoxCookie.TempFilename()) defer db.Close() rows, err := db.Query(queryFirefoxCookie) diff --git a/browsingdata/creditcard/creditcard.go b/browsingdata/creditcard/creditcard.go index e48f2ea..4f601d1 100644 --- a/browsingdata/creditcard/creditcard.go +++ b/browsingdata/creditcard/creditcard.go @@ -29,11 +29,11 @@ const ( ) func (c *ChromiumCreditCard) Parse(masterKey []byte) error { - db, err := sql.Open("sqlite3", item.TempChromiumCreditCard) + db, err := sql.Open("sqlite3", item.ChromiumCreditCard.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempChromiumCreditCard) + defer os.Remove(item.ChromiumCreditCard.TempFilename()) defer db.Close() rows, err := db.Query(queryChromiumCredit) @@ -85,11 +85,11 @@ func (c *ChromiumCreditCard) Len() int { type YandexCreditCard []card func (c *YandexCreditCard) Parse(masterKey []byte) error { - db, err := sql.Open("sqlite3", item.TempYandexCreditCard) + db, err := sql.Open("sqlite3", item.YandexCreditCard.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempYandexCreditCard) + defer os.Remove(item.YandexCreditCard.TempFilename()) defer db.Close() rows, err := db.Query(queryChromiumCredit) if err != nil { diff --git a/browsingdata/download/download.go b/browsingdata/download/download.go index b9b24c2..8c6807b 100644 --- a/browsingdata/download/download.go +++ b/browsingdata/download/download.go @@ -32,11 +32,11 @@ const ( ) func (c *ChromiumDownload) Parse(_ []byte) error { - db, err := sql.Open("sqlite3", item.TempChromiumDownload) + db, err := sql.Open("sqlite3", item.ChromiumDownload.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempChromiumDownload) + defer os.Remove(item.ChromiumDownload.TempFilename()) defer db.Close() rows, err := db.Query(queryChromiumDownload) if err != nil { @@ -83,11 +83,11 @@ const ( ) func (f *FirefoxDownload) Parse(_ []byte) error { - db, err := sql.Open("sqlite3", item.TempFirefoxDownload) + db, err := sql.Open("sqlite3", item.FirefoxDownload.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempFirefoxDownload) + defer os.Remove(item.FirefoxDownload.TempFilename()) defer db.Close() _, err = db.Exec(closeJournalMode) diff --git a/browsingdata/extension/extension.go b/browsingdata/extension/extension.go index f7f0132..e45d3ae 100644 --- a/browsingdata/extension/extension.go +++ b/browsingdata/extension/extension.go @@ -25,11 +25,11 @@ type extension struct { } func (c *ChromiumExtension) Parse(_ []byte) error { - extensionFile, err := fileutil.ReadFile(item.TempChromiumExtension) + extensionFile, err := fileutil.ReadFile(item.ChromiumExtension.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempChromiumExtension) + defer os.Remove(item.ChromiumExtension.TempFilename()) result, err := parseChromiumExtensions(extensionFile) if err != nil { @@ -114,11 +114,11 @@ type FirefoxExtension []*extension var lang = language.Und func (f *FirefoxExtension) Parse(_ []byte) error { - s, err := fileutil.ReadFile(item.TempFirefoxExtension) + s, err := fileutil.ReadFile(item.FirefoxExtension.TempFilename()) if err != nil { return err } - _ = os.Remove(item.TempFirefoxExtension) + _ = os.Remove(item.FirefoxExtension.TempFilename()) j := gjson.Parse(s) for _, v := range j.Get("addons").Array() { // https://searchfox.org/mozilla-central/source/toolkit/mozapps/extensions/internal/XPIDatabase.jsm#157 diff --git a/browsingdata/history/history.go b/browsingdata/history/history.go index eafc8bf..f543fbd 100644 --- a/browsingdata/history/history.go +++ b/browsingdata/history/history.go @@ -28,11 +28,11 @@ const ( ) func (c *ChromiumHistory) Parse(_ []byte) error { - db, err := sql.Open("sqlite3", item.TempChromiumHistory) + db, err := sql.Open("sqlite3", item.ChromiumHistory.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempChromiumHistory) + defer os.Remove(item.ChromiumHistory.TempFilename()) defer db.Close() rows, err := db.Query(queryChromiumHistory) @@ -79,11 +79,11 @@ const ( ) func (f *FirefoxHistory) Parse(_ []byte) error { - db, err := sql.Open("sqlite3", item.TempFirefoxHistory) + db, err := sql.Open("sqlite3", item.FirefoxHistory.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempFirefoxHistory) + defer os.Remove(item.FirefoxHistory.TempFilename()) defer db.Close() _, err = db.Exec(closeJournalMode) diff --git a/browsingdata/localstorage/localstorage.go b/browsingdata/localstorage/localstorage.go index 37cf7fe..1fe3a6b 100644 --- a/browsingdata/localstorage/localstorage.go +++ b/browsingdata/localstorage/localstorage.go @@ -29,11 +29,11 @@ type storage struct { const maxLocalStorageValueLength = 1024 * 2 func (c *ChromiumLocalStorage) Parse(_ []byte) error { - db, err := leveldb.OpenFile(item.TempChromiumLocalStorage, nil) + db, err := leveldb.OpenFile(item.ChromiumLocalStorage.TempFilename(), nil) if err != nil { return err } - defer os.RemoveAll(item.TempChromiumLocalStorage) + defer os.RemoveAll(item.ChromiumLocalStorage.TempFilename()) defer db.Close() iter := db.NewIterator(nil, nil) @@ -106,11 +106,11 @@ const ( ) func (f *FirefoxLocalStorage) Parse(_ []byte) error { - db, err := sql.Open("sqlite3", item.TempFirefoxLocalStorage) + db, err := sql.Open("sqlite3", item.FirefoxLocalStorage.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempFirefoxLocalStorage) + defer os.Remove(item.FirefoxLocalStorage.TempFilename()) defer db.Close() _, err = db.Exec(closeJournalMode) diff --git a/browsingdata/password/password.go b/browsingdata/password/password.go index 36a3abe..47dffee 100644 --- a/browsingdata/password/password.go +++ b/browsingdata/password/password.go @@ -34,11 +34,11 @@ const ( ) func (c *ChromiumPassword) Parse(masterKey []byte) error { - db, err := sql.Open("sqlite3", item.TempChromiumPassword) + db, err := sql.Open("sqlite3", item.ChromiumPassword.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempChromiumPassword) + defer os.Remove(item.ChromiumPassword.TempFilename()) defer db.Close() rows, err := db.Query(queryChromiumLogin) @@ -101,11 +101,11 @@ const ( ) func (c *YandexPassword) Parse(masterKey []byte) error { - db, err := sql.Open("sqlite3", item.TempYandexPassword) + db, err := sql.Open("sqlite3", item.YandexPassword.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempYandexPassword) + defer os.Remove(item.YandexPassword.TempFilename()) defer db.Close() rows, err := db.Query(queryYandexLogin) @@ -170,7 +170,7 @@ const ( ) func (f *FirefoxPassword) Parse(masterKey []byte) error { - globalSalt, metaBytes, nssA11, nssA102, err := getFirefoxDecryptKey(item.TempFirefoxKey4) + globalSalt, metaBytes, nssA11, nssA102, err := getFirefoxDecryptKey(item.FirefoxKey4.TempFilename()) if err != nil { return err } @@ -252,11 +252,11 @@ func getFirefoxDecryptKey(key4file string) (item1, item2, a11, a102 []byte, err } func getFirefoxLoginData() ([]loginData, error) { - s, err := os.ReadFile(item.TempFirefoxPassword) + s, err := os.ReadFile(item.FirefoxPassword.TempFilename()) if err != nil { return nil, err } - defer os.Remove(item.TempFirefoxPassword) + defer os.Remove(item.FirefoxPassword.TempFilename()) loginsJSON := gjson.GetBytes(s, "logins") var logins []loginData if loginsJSON.Exists() { diff --git a/browsingdata/sessionstorage/sessionstorage.go b/browsingdata/sessionstorage/sessionstorage.go index adaa7d2..79dd356 100644 --- a/browsingdata/sessionstorage/sessionstorage.go +++ b/browsingdata/sessionstorage/sessionstorage.go @@ -29,11 +29,11 @@ type session struct { const maxLocalStorageValueLength = 1024 * 2 func (c *ChromiumSessionStorage) Parse(_ []byte) error { - db, err := leveldb.OpenFile(item.TempChromiumSessionStorage, nil) + db, err := leveldb.OpenFile(item.ChromiumSessionStorage.TempFilename(), nil) if err != nil { return err } - defer os.RemoveAll(item.TempChromiumSessionStorage) + defer os.RemoveAll(item.ChromiumSessionStorage.TempFilename()) defer db.Close() iter := db.NewIterator(nil, nil) @@ -114,11 +114,11 @@ const ( ) func (f *FirefoxSessionStorage) Parse(_ []byte) error { - db, err := sql.Open("sqlite3", item.TempFirefoxSessionStorage) + db, err := sql.Open("sqlite3", item.FirefoxSessionStorage.TempFilename()) if err != nil { return err } - defer os.Remove(item.TempFirefoxSessionStorage) + defer os.Remove(item.FirefoxSessionStorage.TempFilename()) defer db.Close() _, err = db.Exec(closeJournalMode) diff --git a/item/filename.go b/item/filename.go deleted file mode 100644 index 6ce86ae..0000000 --- a/item/filename.go +++ /dev/null @@ -1,57 +0,0 @@ -package item - -// item's default filename -const ( - fileChromiumKey = "Local State" - fileChromiumCredit = "Web Data" - fileChromiumPassword = "Login Data" - fileChromiumHistory = "History" - fileChromiumDownload = "History" - fileChromiumCookie = "Cookies" - fileChromiumBookmark = "Bookmarks" - fileChromiumLocalStorage = "Local Storage/leveldb" - fileChromiumSessionStorage = "Session Storage" - fileChromiumExtension = "Secure Preferences" // TODO: add more extension files and folders, eg: Preferences - - fileYandexPassword = "Ya Passman Data" - fileYandexCredit = "Ya Credit Cards" - - fileFirefoxKey4 = "key4.db" - fileFirefoxCookie = "cookies.sqlite" - fileFirefoxPassword = "logins.json" - fileFirefoxData = "places.sqlite" - fileFirefoxLocalStorage = "webappsstore.sqlite" - fileFirefoxExtension = "extensions.json" -) - -const ( - UnknownItem = "unknown item" - UnsupportedItem = "unsupported item" -) - -const ( - TempChromiumKey = "chromiumKey" - TempChromiumPassword = "password" - TempChromiumCookie = "cookie" - TempChromiumBookmark = "bookmark" - TempChromiumHistory = "history" - TempChromiumDownload = "download" - TempChromiumCreditCard = "creditCard" - TempChromiumLocalStorage = "localStorage" - TempChromiumSessionStorage = "sessionStorage" - TempChromiumExtension = "extension" - - TempYandexPassword = "yandexPassword" - TempYandexCreditCard = "yandexCreditCard" - - TempFirefoxKey4 = "firefoxKey4" - TempFirefoxPassword = "firefoxPassword" - TempFirefoxCookie = "firefoxCookie" - TempFirefoxBookmark = "firefoxBookmark" - TempFirefoxHistory = "firefoxHistory" - TempFirefoxDownload = "firefoxDownload" - TempFirefoxLocalStorage = "firefoxLocalStorage" - TempFirefoxSessionStorage = "firefoxSessionStorage" - TempFirefoxCreditCard = "" - TempFirefoxExtension = "firefoxExtension" -) diff --git a/item/item.go b/item/item.go index 9d8576e..577e2b6 100644 --- a/item/item.go +++ b/item/item.go @@ -1,5 +1,11 @@ package item +import ( + "fmt" + "os" + "path/filepath" +) + type Item int const ( @@ -29,104 +35,45 @@ const ( FirefoxExtension ) -func (i Item) FileName() string { - switch i { - case ChromiumKey: - return fileChromiumKey - case ChromiumPassword: - return fileChromiumPassword - case ChromiumCookie: - return fileChromiumCookie - case ChromiumBookmark: - return fileChromiumBookmark - case ChromiumDownload: - return fileChromiumDownload - case ChromiumLocalStorage: - return fileChromiumLocalStorage - case ChromiumSessionStorage: - return fileChromiumSessionStorage - case ChromiumCreditCard: - return fileChromiumCredit - case ChromiumExtension: - return fileChromiumExtension - case ChromiumHistory: - return fileChromiumHistory - case YandexPassword: - return fileYandexPassword - case YandexCreditCard: - return fileYandexCredit - case FirefoxKey4: - return fileFirefoxKey4 - case FirefoxPassword: - return fileFirefoxPassword - case FirefoxCookie: - return fileFirefoxCookie - case FirefoxBookmark: - return fileFirefoxData - case FirefoxDownload: - return fileFirefoxData - case FirefoxLocalStorage: - return fileFirefoxLocalStorage - case FirefoxHistory: - return fileFirefoxData - case FirefoxExtension: - return fileFirefoxExtension - case FirefoxCreditCard: - return UnsupportedItem - default: - return UnknownItem - } +var itemFileNames = map[Item]string{ + ChromiumKey: fileChromiumKey, + ChromiumPassword: fileChromiumPassword, + ChromiumCookie: fileChromiumCookie, + ChromiumBookmark: fileChromiumBookmark, + ChromiumDownload: fileChromiumDownload, + ChromiumLocalStorage: fileChromiumLocalStorage, + ChromiumSessionStorage: fileChromiumSessionStorage, + ChromiumCreditCard: fileChromiumCredit, + ChromiumExtension: fileChromiumExtension, + ChromiumHistory: fileChromiumHistory, + YandexPassword: fileYandexPassword, + YandexCreditCard: fileYandexCredit, + FirefoxKey4: fileFirefoxKey4, + FirefoxPassword: fileFirefoxPassword, + FirefoxCookie: fileFirefoxCookie, + FirefoxBookmark: fileFirefoxData, + FirefoxDownload: fileFirefoxData, + FirefoxLocalStorage: fileFirefoxLocalStorage, + FirefoxHistory: fileFirefoxData, + FirefoxExtension: fileFirefoxExtension, + FirefoxSessionStorage: UnsupportedItem, + FirefoxCreditCard: UnsupportedItem, } -func (i Item) String() string { - switch i { - case ChromiumKey: - return TempChromiumKey - case ChromiumPassword: - return TempChromiumPassword - case ChromiumCookie: - return TempChromiumCookie - case ChromiumBookmark: - return TempChromiumBookmark - case ChromiumDownload: - return TempChromiumDownload - case ChromiumLocalStorage: - return TempChromiumLocalStorage - case ChromiumSessionStorage: - return TempChromiumSessionStorage - case ChromiumCreditCard: - return TempChromiumCreditCard - case ChromiumExtension: - return TempChromiumExtension - case ChromiumHistory: - return TempChromiumHistory - case YandexPassword: - return TempYandexPassword - case YandexCreditCard: - return TempYandexCreditCard - case FirefoxKey4: - return TempFirefoxKey4 - case FirefoxPassword: - return TempFirefoxPassword - case FirefoxCookie: - return TempFirefoxCookie - case FirefoxBookmark: - return TempFirefoxBookmark - case FirefoxDownload: - return TempFirefoxDownload - case FirefoxHistory: - return TempFirefoxHistory - case FirefoxLocalStorage: - return TempFirefoxLocalStorage - case FirefoxSessionStorage: - return TempFirefoxSessionStorage - case FirefoxCreditCard: - return UnsupportedItem - case FirefoxExtension: - return TempFirefoxExtension - default: - return UnknownItem +func (i Item) Filename() string { + if fileName, ok := itemFileNames[i]; ok { + return fileName } + return UnsupportedItem +} + +const tempSuffix = "temp" + +// TempFilename returns the temp filename for the item with suffix +// eg: chromiumKey_0.temp +func (i Item) TempFilename() string { + tempFile := fmt.Sprintf("%s_%d.%s", i.Filename(), i, tempSuffix) + return filepath.Join(os.TempDir(), tempFile) } // IsSensitive returns whether the item is sensitive data @@ -194,3 +141,32 @@ var DefaultChromium = []Item{ ChromiumSessionStorage, ChromiumExtension, } + +// item's default filename +const ( + fileChromiumKey = "Local State" + fileChromiumCredit = "Web Data" + fileChromiumPassword = "Login Data" + fileChromiumHistory = "History" + fileChromiumDownload = "History" + fileChromiumCookie = "Cookies" + fileChromiumBookmark = "Bookmarks" + fileChromiumLocalStorage = "Local Storage/leveldb" + fileChromiumSessionStorage = "Session Storage" + fileChromiumExtension = "Secure Preferences" // TODO: add more extension files and folders, eg: Preferences + + fileYandexPassword = "Ya Passman Data" + fileYandexCredit = "Ya Credit Cards" + + fileFirefoxKey4 = "key4.db" + fileFirefoxCookie = "cookies.sqlite" + fileFirefoxPassword = "logins.json" + fileFirefoxData = "places.sqlite" + fileFirefoxLocalStorage = "webappsstore.sqlite" + fileFirefoxExtension = "extensions.json" +) + +const ( + UnknownItem = "unknown item" + UnsupportedItem = "unsupported item" +) diff --git a/item/item_test.go b/item/item_test.go new file mode 100644 index 0000000..87f1d1d --- /dev/null +++ b/item/item_test.go @@ -0,0 +1,129 @@ +package item + +import ( + "fmt" + "os" + "strconv" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestItem_FileName(t *testing.T) { + for _, item := range DefaultChromium { + assert.Equal(t, item.Filename(), item.filename()) + } + for _, item := range DefaultFirefox { + assert.Equal(t, item.Filename(), item.filename()) + } + for _, item := range DefaultYandex { + assert.Equal(t, item.Filename(), item.filename()) + } +} + +func TestItem_TempFilename(t *testing.T) { + asserts := assert.New(t) + + testCases := []struct { + item Item + expected string + }{ + {ChromiumKey, "Local State"}, + {ChromiumPassword, "Login Data"}, + {ChromiumLocalStorage, "Local Storage/leveldb"}, + {FirefoxSessionStorage, "unsupported item"}, + {FirefoxLocalStorage, "webappsstore.sqlite"}, + {YandexPassword, "Ya Passman Data"}, + {YandexCreditCard, "Ya Credit Cards"}, + } + + for _, tc := range testCases { + expectedPrefix := tc.expected + "_" + strconv.Itoa(int(tc.item)) + ".temp" + actualPath := tc.item.TempFilename() + asserts.Contains(actualPath, expectedPrefix, "TempFilename should contain the correct prefix for "+tc.expected) + asserts.Contains(actualPath, os.TempDir(), "TempFilename should be in the system temp directory for "+tc.expected) + } +} + +func TestItem_IsSensitive(t *testing.T) { + asserts := assert.New(t) + testCases := []struct { + item Item + expected bool + }{ + {ChromiumKey, true}, + {ChromiumPassword, true}, + {ChromiumBookmark, false}, + } + for _, tc := range testCases { + asserts.Equal(tc.expected, tc.item.IsSensitive(), fmt.Sprintf("IsSensitive for %v should be %v", tc.item, tc.expected)) + } +} + +func TestFilterSensitiveItems(t *testing.T) { + asserts := assert.New(t) + testCases := []struct { + items []Item + expected int + }{ + {[]Item{ChromiumKey, ChromiumBookmark, ChromiumPassword}, 2}, + {[]Item{ChromiumBookmark, ChromiumHistory}, 0}, + } + + for _, tc := range testCases { + filteredItems := FilterSensitiveItems(tc.items) + asserts.Len(filteredItems, tc.expected, "FilterSensitiveItems should return the correct number of sensitive items") + for _, item := range filteredItems { + asserts.True(item.IsSensitive(), "Filtered items should be sensitive") + } + } +} + +func (i Item) filename() string { + switch i { + case ChromiumKey: + return fileChromiumKey + case ChromiumPassword: + return fileChromiumPassword + case ChromiumCookie: + return fileChromiumCookie + case ChromiumBookmark: + return fileChromiumBookmark + case ChromiumDownload: + return fileChromiumDownload + case ChromiumLocalStorage: + return fileChromiumLocalStorage + case ChromiumSessionStorage: + return fileChromiumSessionStorage + case ChromiumCreditCard: + return fileChromiumCredit + case ChromiumExtension: + return fileChromiumExtension + case ChromiumHistory: + return fileChromiumHistory + case YandexPassword: + return fileYandexPassword + case YandexCreditCard: + return fileYandexCredit + case FirefoxKey4: + return fileFirefoxKey4 + case FirefoxPassword: + return fileFirefoxPassword + case FirefoxCookie: + return fileFirefoxCookie + case FirefoxBookmark: + return fileFirefoxData + case FirefoxDownload: + return fileFirefoxData + case FirefoxLocalStorage: + return fileFirefoxLocalStorage + case FirefoxHistory: + return fileFirefoxData + case FirefoxExtension: + return fileFirefoxExtension + case FirefoxCreditCard: + return UnsupportedItem + default: + return UnsupportedItem + } +}