package download import ( "database/sql" "os" "sort" "strings" "time" "hack-browser-data/internal/item" "hack-browser-data/internal/log" "hack-browser-data/internal/utils/typeutil" // import sqlite3 driver _ "github.com/mattn/go-sqlite3" "github.com/tidwall/gjson" ) type ChromiumDownload []download type download struct { TargetPath string URL string TotalBytes int64 StartTime time.Time EndTime time.Time MimeType string } const ( queryChromiumDownload = `SELECT target_path, tab_url, total_bytes, start_time, end_time, mime_type FROM downloads` ) func (c *ChromiumDownload) Parse(masterKey []byte) error { historyDB, err := sql.Open("sqlite3", item.TempChromiumDownload) if err != nil { return err } defer os.Remove(item.TempChromiumDownload) defer historyDB.Close() rows, err := historyDB.Query(queryChromiumDownload) if err != nil { return err } defer rows.Close() for rows.Next() { var ( targetPath, tabURL, mimeType string totalBytes, startTime, endTime int64 ) if err := rows.Scan(&targetPath, &tabURL, &totalBytes, &startTime, &endTime, &mimeType); err != nil { log.Warn(err) } data := download{ TargetPath: targetPath, URL: tabURL, TotalBytes: totalBytes, StartTime: typeutil.TimeEpoch(startTime), EndTime: typeutil.TimeEpoch(endTime), MimeType: mimeType, } *c = append(*c, data) } sort.Slice(*c, func(i, j int) bool { return (*c)[i].TotalBytes > (*c)[j].TotalBytes }) return nil } func (c *ChromiumDownload) Name() string { return "download" } func (c *ChromiumDownload) Length() int { return len(*c) } type FirefoxDownload []download const ( queryFirefoxDownload = `SELECT place_id, GROUP_CONCAT(content), url, dateAdded FROM (SELECT * FROM moz_annos INNER JOIN moz_places ON moz_annos.place_id=moz_places.id) t GROUP BY place_id` closeJournalMode = `PRAGMA journal_mode=off` ) func (f *FirefoxDownload) Parse(masterKey []byte) error { var ( err error keyDB *sql.DB downloadRows *sql.Rows ) keyDB, err = sql.Open("sqlite3", item.TempFirefoxDownload) if err != nil { return err } defer os.Remove(item.TempFirefoxDownload) defer keyDB.Close() _, err = keyDB.Exec(closeJournalMode) if err != nil { return err } defer keyDB.Close() downloadRows, err = keyDB.Query(queryFirefoxDownload) if err != nil { return err } defer downloadRows.Close() for downloadRows.Next() { var ( content, url string placeID, dateAdded int64 ) if err = downloadRows.Scan(&placeID, &content, &url, &dateAdded); err != nil { log.Warn(err) } contentList := strings.Split(content, ",{") if len(contentList) > 1 { path := contentList[0] json := "{" + contentList[1] endTime := gjson.Get(json, "endTime") fileSize := gjson.Get(json, "fileSize") *f = append(*f, download{ TargetPath: path, URL: url, TotalBytes: fileSize.Int(), StartTime: typeutil.TimeStamp(dateAdded / 1000000), EndTime: typeutil.TimeStamp(endTime.Int() / 1000), }) } } sort.Slice(*f, func(i, j int) bool { return (*f)[i].TotalBytes < (*f)[j].TotalBytes }) return nil } func (f *FirefoxDownload) Name() string { return "download" } func (f *FirefoxDownload) Length() int { return len(*f) }