forked from NiceLabs/geoip-seeker
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathupdate.go
119 lines (105 loc) · 2.71 KB
/
update.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
package qqwry
import (
"bytes"
"compress/zlib"
"encoding/binary"
"errors"
"io/ioutil"
"net/http"
"time"
"github.com/OpenIPDB/geoip-seeker/shared"
)
const (
updateCopyWrite = "http://update.cz88.net/ip/copywrite.rar"
updateQQWay = "http://update.cz88.net/ip/qqwry.rar"
)
type updater struct {
client *http.Client
version, size, key uint32
}
func DownloadUpdate(client *http.Client) (update shared.Update, err error) {
resp, err := client.Do(newRequest(updateCopyWrite))
if err != nil {
return
}
defer resp.Body.Close()
copywrite := new(struct {
Magic [4]byte
Version, _, Size, _, Key uint32
Text, Link [128]byte
})
err = binary.Read(resp.Body, binary.LittleEndian, copywrite)
if err != nil {
return
}
if string(copywrite.Magic[:]) != "CZIP" {
err = errors.New("magic error")
return
}
update = &updater{
client: client,
version: copywrite.Version,
size: copywrite.Size,
key: copywrite.Key,
}
return
}
func (u *updater) BuildTime() time.Time {
year, month, day := versionToDate(
u.version + dateToVersion(1899, 12, 30),
)
location := time.FixedZone("CST", +8*3600)
return time.Date(year, time.Month(month), day, 0, 0, 0, 0, location)
}
func (u *updater) Size() uint64 { return uint64(u.size) }
func (u *updater) Download() (payload []byte, err error) {
resp, err := u.client.Do(newRequest(updateQQWay))
if err != nil {
return
}
defer resp.Body.Close()
payload, err = ioutil.ReadAll(resp.Body)
if err != nil {
return
}
return u.decode(payload)
}
func (u *updater) decode(payload []byte) (data []byte, err error) {
key := u.key
for index := 0; index < 0x200; index++ {
key *= 0x805
key += 1
key &= 0xFF
payload[index] = byte(key ^ uint32(payload[index]))
}
reader, err := zlib.NewReader(bytes.NewReader(payload))
if err != nil {
return
}
return ioutil.ReadAll(reader)
}
func newRequest(url string) *http.Request {
request, _ := http.NewRequest(http.MethodGet, url, nil)
request.Header = http.Header{
"Accept": []string{"text/html, */*"},
"User-Agent": []string{"Mozilla/3.0 (compatible; Indy Library)"},
}
return request
}
// see https://github.com/shuax/LocateIP/blob/master/loci/cz_update.c#L23-L29
func dateToVersion(year, month, day uint32) uint32 {
month = (month + 9) % 12
year = year - month/10
day = 365*year + year/4 - year/100 + year/400 + (month*153+2)/5 + day - 1
return day
}
// see https://github.com/shuax/LocateIP/blob/master/loci/cz_update.c#L31-L41
func versionToDate(version uint32) (year, month, day int) {
y := (version*33 + 999) / 12053
t := version - y*365 - y/4 + y/100 - y/400
m := (t*5+2)/153 + 2
year = int(y + m/12)
month = int(m%12 + 1)
day = int(t - (m*153-304)/5 + 1)
return
}