2022-04-17 18:11:33 +00:00
package download
2021-12-31 08:50:50 +00:00
import (
"database/sql"
2024-01-16 06:06:13 +00:00
"log/slog"
2022-04-11 11:57:40 +00:00
"os"
2021-12-31 08:50:50 +00:00
"sort"
2022-01-11 10:19:17 +00:00
"strings"
2022-04-17 18:11:33 +00:00
"time"
2022-01-11 10:19:17 +00:00
2022-04-11 07:53:19 +00:00
"github.com/tidwall/gjson"
2024-01-19 07:45:24 +00:00
_ "modernc.org/sqlite" // import sqlite3 driver
2023-03-10 06:52:26 +00:00
2024-04-12 11:10:41 +00:00
"github.com/moond4rk/hackbrowserdata/extractor"
"github.com/moond4rk/hackbrowserdata/types"
2023-06-04 05:47:43 +00:00
"github.com/moond4rk/hackbrowserdata/utils/typeutil"
2021-12-31 08:50:50 +00:00
)
2024-04-12 11:10:41 +00:00
func init ( ) {
extractor . RegisterExtractor ( types . ChromiumDownload , func ( ) extractor . Extractor {
return new ( ChromiumDownload )
} )
extractor . RegisterExtractor ( types . FirefoxDownload , func ( ) extractor . Extractor {
return new ( FirefoxDownload )
} )
}
2021-12-31 08:50:50 +00:00
type ChromiumDownload [ ] download
2022-04-17 18:11:33 +00:00
type download struct {
TargetPath string
2022-08-14 13:22:34 +00:00
URL string
2022-04-17 18:11:33 +00:00
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 `
)
2024-04-12 11:10:41 +00:00
func ( c * ChromiumDownload ) Extract ( _ [ ] byte ) error {
db , err := sql . Open ( "sqlite" , types . ChromiumDownload . TempFilename ( ) )
2021-12-31 08:50:50 +00:00
if err != nil {
return err
}
2024-04-12 11:10:41 +00:00
defer os . Remove ( types . ChromiumDownload . TempFilename ( ) )
2023-03-12 06:23:54 +00:00
defer db . Close ( )
rows , err := db . Query ( queryChromiumDownload )
2021-12-31 08:50:50 +00:00
if err != nil {
return err
}
defer rows . Close ( )
for rows . Next ( ) {
var (
2022-08-14 13:22:34 +00:00
targetPath , tabURL , mimeType string
2021-12-31 08:50:50 +00:00
totalBytes , startTime , endTime int64
)
2022-08-14 13:22:34 +00:00
if err := rows . Scan ( & targetPath , & tabURL , & totalBytes , & startTime , & endTime , & mimeType ) ; err != nil {
2024-01-16 06:06:13 +00:00
slog . Warn ( "scan chromium download error" , "err" , err )
2021-12-31 08:50:50 +00:00
}
data := download {
TargetPath : targetPath ,
2022-08-14 13:22:34 +00:00
URL : tabURL ,
2021-12-31 08:50:50 +00:00
TotalBytes : totalBytes ,
2022-04-17 08:35:40 +00:00
StartTime : typeutil . TimeEpoch ( startTime ) ,
EndTime : typeutil . TimeEpoch ( endTime ) ,
2021-12-31 08:50:50 +00:00
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"
}
2022-01-11 10:19:17 +00:00
2023-03-12 06:23:54 +00:00
func ( c * ChromiumDownload ) Len ( ) int {
2022-06-05 07:27:14 +00:00
return len ( * c )
}
2022-01-11 10:19:17 +00:00
type FirefoxDownload [ ] download
2022-04-17 18:11:33 +00:00
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 `
)
2024-04-12 11:10:41 +00:00
func ( f * FirefoxDownload ) Extract ( _ [ ] byte ) error {
db , err := sql . Open ( "sqlite" , types . FirefoxDownload . TempFilename ( ) )
2022-01-11 10:19:17 +00:00
if err != nil {
return err
}
2024-04-12 11:10:41 +00:00
defer os . Remove ( types . FirefoxDownload . TempFilename ( ) )
2023-03-12 06:23:54 +00:00
defer db . Close ( )
_ , err = db . Exec ( closeJournalMode )
2022-01-11 10:19:17 +00:00
if err != nil {
2024-01-16 06:06:13 +00:00
slog . Error ( "close journal mode error" , "err" , err )
2022-01-11 10:19:17 +00:00
}
2023-03-12 06:23:54 +00:00
rows , err := db . Query ( queryFirefoxDownload )
2022-01-11 10:19:17 +00:00
if err != nil {
return err
}
2023-03-12 06:23:54 +00:00
defer rows . Close ( )
for rows . Next ( ) {
2022-01-11 10:19:17 +00:00
var (
content , url string
placeID , dateAdded int64
)
2023-03-12 06:23:54 +00:00
if err = rows . Scan ( & placeID , & content , & url , & dateAdded ) ; err != nil {
2024-01-16 06:06:13 +00:00
slog . Warn ( "scan firefox download error" , "err" , err )
2022-01-11 10:19:17 +00:00
}
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 ,
2022-08-14 13:22:34 +00:00
URL : url ,
2022-01-11 10:19:17 +00:00
TotalBytes : fileSize . Int ( ) ,
2022-04-17 08:35:40 +00:00
StartTime : typeutil . TimeStamp ( dateAdded / 1000000 ) ,
EndTime : typeutil . TimeStamp ( endTime . Int ( ) / 1000 ) ,
2022-01-11 10:19:17 +00:00
} )
}
}
sort . Slice ( * f , func ( i , j int ) bool {
return ( * f ) [ i ] . TotalBytes < ( * f ) [ j ] . TotalBytes
} )
return nil
}
func ( f * FirefoxDownload ) Name ( ) string {
return "download"
}
2022-06-05 07:27:14 +00:00
2023-03-12 06:23:54 +00:00
func ( f * FirefoxDownload ) Len ( ) int {
2022-06-05 07:27:14 +00:00
return len ( * f )
}