-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathextract_with_checksum.go
121 lines (98 loc) · 2.47 KB
/
extract_with_checksum.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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package unneko
import (
"hash/crc32"
"sort"
)
type checksumFileMap struct {
checksums map[uint32]int
fileSizes map[int]struct{}
}
type checksumCompleteCond struct {
maps []*checksumFileMap
}
func newChecksumCompleteCond(checksumFiles []*checksumFile) *checksumCompleteCond {
maps := make([]*checksumFileMap, 0, len(checksumFiles))
for _, v := range checksumFiles {
checksums := make(map[uint32]int, len(v.Files))
fileSizes := make(map[int]struct{}, len(v.Files))
for _, f := range v.Files {
checksums[f.Crc32]++
fileSizes[f.Size] = struct{}{}
}
maps = append(maps, &checksumFileMap{
checksums: checksums,
fileSizes: fileSizes,
})
}
return &checksumCompleteCond{
maps: maps,
}
}
func (c *checksumCompleteCond) Complete(neko *nekoData, uncompressed []byte) bool {
if neko.fullyRead() {
return true
}
// To optimize the decompression we will only calculate the checksum when the len(uncompressed)
// matches a file in the checksumfile.
validFileSize := false
for _, v := range c.maps {
if _, ok := v.fileSizes[len(uncompressed)]; ok {
validFileSize = true
break
}
}
if !validFileSize {
return false
}
// file successfully extracted if it's a known checksum from the checksum file
chSum := crc32.ChecksumIEEE(uncompressed)
for _, v := range c.maps {
if n, ok := v.checksums[chSum]; ok {
return n > 0
}
}
return false
}
func (c *checksumCompleteCond) MarkAsFound(data []byte) {
chSum := crc32.ChecksumIEEE(data)
// As we don't know which checksum file we found is the correct one
// we will decrement the checksum on each checksum file.
// When the first one is empty it will indicate that the decompression is finished
for _, v := range c.maps {
if v.checksums[chSum] > 0 {
v.checksums[chSum]--
}
}
}
func (c *checksumCompleteCond) FoundAll() bool {
for _, m := range c.maps {
// if a single map is completed, we consider the extraction complete
// all other maps are probably nested checksum files of compressed nekodata
foundAll := true
for _, v := range m.checksums {
if v > 0 {
foundAll = false
break
}
}
if foundAll {
return true
}
}
return false
}
func (c *checksumCompleteCond) PossibleFileSizes() []int {
var result []int
alreadySeen := make(map[int]struct{})
for _, m := range c.maps {
for fs, _ := range m.fileSizes {
if _, ok := alreadySeen[fs]; ok {
continue
}
alreadySeen[fs] = struct{}{}
result = append(result, fs)
}
}
sort.Ints(result)
return result
}