feat: add Firefox extract methods and complete data model fields (#527)

* feat: add Firefox extract methods and complete data model fields

Firefox extract methods:
- extractPasswords: JSON + ASN1PBE decryption via decryptPBE helper
- extractCookies: SQLite, plaintext (no encryption), journalOff
- extractHistories: SQLite, visit count ASC sort (matches old behavior)
- extractDownloads: SQLite, moz_annos JOIN with JSON content parsing
- extractBookmarks: SQLite, moz_bookmarks JOIN moz_places
- extractExtensions: JSON, filter by location=app-profile
- extractLocalStorage: SQLite webappsstore2, reversed originKey parsing

Complete data model fields (union of Chromium and Firefox):
- CookieEntry: add HasExpire, IsPersistent
- DownloadEntry: add MimeType
- CreditCardEntry: add NickName, Address
- ExtensionEntry: add HomepageURL, Enabled

Update Chromium extractors to populate new fields:
- extract_cookie.go: fill HasExpire, IsPersistent
- extract_download.go: SELECT and fill mime_type
- extract_creditcard.go: SELECT nickname, billing_address_id
- extract_extension.go: fill HomepageURL, Enabled (state==1)

Tests:
- Full test coverage for all 7 Firefox extract functions
- Password test uses known ASN1PBE test vectors from crypto package
- Table-driven tests for parseOriginKey
- Updated Chromium tests for new fields

* fix: add COALESCE for nullable bookmark title in Firefox query

Firefox moz_bookmarks.title can be NULL (PR #500 fixed this in old code).
Add COALESCE to handle NULL gracefully in SQL instead of relying on
driver-specific NULL→string conversion behavior.

* fix: enable journalOff for all Firefox SQLite extractors and populate cookie flags

- Set journalOff=true for extract_history, extract_download, extract_bookmark
  (Firefox databases require PRAGMA journal_mode=off to avoid lock errors)
- Populate HasExpire and IsPersistent for Firefox cookies (derived from expiry>0)
- Add test assertions for HasExpire/IsPersistent in both Chromium and Firefox
This commit is contained in:
Roger
2026-03-30 20:52:11 +08:00
committed by moonD4rk
parent 2c4e871e59
commit 1ec2781131
25 changed files with 937 additions and 38 deletions
+19 -12
View File
@@ -12,14 +12,16 @@ type LoginEntry struct {
// CookieEntry represents a single browser cookie.
type CookieEntry struct {
Host string `json:"host" csv:"host"`
Path string `json:"path" csv:"path"`
Name string `json:"name" csv:"name"`
Value string `json:"value" csv:"value"`
IsSecure bool `json:"is_secure" csv:"is_secure"`
IsHTTPOnly bool `json:"is_http_only" csv:"is_http_only"`
ExpireAt time.Time `json:"expire_at" csv:"expire_at"`
CreatedAt time.Time `json:"created_at" csv:"created_at"`
Host string `json:"host" csv:"host"`
Path string `json:"path" csv:"path"`
Name string `json:"name" csv:"name"`
Value string `json:"value" csv:"value"`
IsSecure bool `json:"is_secure" csv:"is_secure"`
IsHTTPOnly bool `json:"is_http_only" csv:"is_http_only"`
HasExpire bool `json:"has_expire" csv:"has_expire"`
IsPersistent bool `json:"is_persistent" csv:"is_persistent"`
ExpireAt time.Time `json:"expire_at" csv:"expire_at"`
CreatedAt time.Time `json:"created_at" csv:"created_at"`
}
// BookmarkEntry represents a single browser bookmark.
@@ -42,6 +44,7 @@ type HistoryEntry struct {
type DownloadEntry struct {
URL string `json:"url" csv:"url"`
TargetPath string `json:"target_path" csv:"target_path"`
MimeType string `json:"mime_type" csv:"mime_type"`
TotalBytes int64 `json:"total_bytes" csv:"total_bytes"`
StartTime time.Time `json:"start_time" csv:"start_time"`
EndTime time.Time `json:"end_time" csv:"end_time"`
@@ -53,6 +56,8 @@ type CreditCardEntry struct {
Number string `json:"number" csv:"number"`
ExpMonth string `json:"exp_month" csv:"exp_month"`
ExpYear string `json:"exp_year" csv:"exp_year"`
NickName string `json:"nick_name" csv:"nick_name"`
Address string `json:"address" csv:"address"`
}
// StorageEntry represents a single key-value pair from local or session storage.
@@ -64,8 +69,10 @@ type StorageEntry struct {
// ExtensionEntry represents a single browser extension.
type ExtensionEntry struct {
Name string `json:"name" csv:"name"`
ID string `json:"id" csv:"id"`
Description string `json:"description" csv:"description"`
Version string `json:"version" csv:"version"`
Name string `json:"name" csv:"name"`
ID string `json:"id" csv:"id"`
Description string `json:"description" csv:"description"`
Version string `json:"version" csv:"version"`
HomepageURL string `json:"homepage_url" csv:"homepage_url"`
Enabled bool `json:"enabled" csv:"enabled"`
}