forked from browserutils/kooky
-
Notifications
You must be signed in to change notification settings - Fork 0
/
magiclite.go
68 lines (61 loc) · 1.8 KB
/
magiclite.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
package utils
import (
"bytes"
"os"
)
type signature struct {
start int
sig []byte
}
var signatures = map[string][]signature{
`ese`: {{start: 4, sig: []byte{0xEF, 0xCD, 0xAB, 0x89}}}, // ESE database
`sqlite`: {{start: 0, sig: []byte("SQLite format 3\x00")}}, // SQLite 3 database
`konqueror`: {{start: 0, sig: []byte("# KDE Cookie File")}}, // Konqueror cookie text file
`safari`: {{start: 0, sig: []byte("cook")}}, // Safari cookie binary file
`opera_cookies4_1.0`: {{start: 0, sig: []byte{0x00, 0x00, 0x10, 0x00}}}, // Opera Presto cookie binary file (file format v1.0) (cookies4.dat)
`ie_cache`: {
{start: 0, sig: []byte("Client UrlCache MMF")}, // Internet Explorer cache file
{start: 0, sig: []byte("WINE URLCache Ver ")}, // wine index.dat // TODO
},
`netscape`: {
{start: 0, sig: []byte("# Netscape HTTP Cookie File")}, // Netscape cookie text file
{start: 0, sig: []byte("# HTTP Cookie File")}, // Netscape cookie text file (not strict)
},
}
func DetectFileType(filename string) (f *os.File, typ string, e error) {
f, err := os.Open(filename)
if err != nil {
return nil, ``, err
}
fi, err := f.Stat()
if err != nil {
return nil, ``, err
}
if fi.IsDir() {
return f, `text`, nil
}
var maxLen int
for _, sigs := range signatures {
for _, sig := range sigs {
l := sig.start + len(sig.sig)
if l > maxLen {
maxLen = l
}
}
}
signature := make([]byte, maxLen)
if _, err := f.Read(signature); err != nil {
return nil, ``, err
}
if _, err := f.Seek(0, 0); err != nil {
return nil, ``, err
}
for name, sigs := range signatures {
for _, sig := range sigs {
if bytes.Equal(signature[sig.start:sig.start+len(sig.sig)], sig.sig) {
return f, name, nil
}
}
}
return f, `unknown`, nil
}