diff --git a/cmd/update.go b/cmd/update.go index c96648e..4912f1b 100644 --- a/cmd/update.go +++ b/cmd/update.go @@ -21,7 +21,7 @@ var updateCmd = &cobra.Command{ filePath := filepath.Join(constant.HomePath, "qqwry.dat") log.Println("正在下载最新纯真 IP 库...") - tmpData, err := qqwry.GetOnline() + tmpData, err := qqwry.Download() if err != nil { log.Fatalln("下载失败", err.Error()) return diff --git a/pkg/common/const.go b/pkg/common/const.go index 9198703..844a139 100644 --- a/pkg/common/const.go +++ b/pkg/common/const.go @@ -1,6 +1,8 @@ package common const ( - RedirectMode1 = 0x01 // one mode - RedirectMode2 = 0x02 //another mode + // RedirectMode1 [IP][0x01][国家和地区信息的绝对偏移地址] + RedirectMode1 = 0x01 + // RedirectMode2 [IP][0x02][信息的绝对偏移][...] or [IP][国家][...] + RedirectMode2 = 0x02 ) diff --git a/pkg/common/dbtool.go b/pkg/common/dbtool.go index 1a948b0..79d6b8e 100644 --- a/pkg/common/dbtool.go +++ b/pkg/common/dbtool.go @@ -1,6 +1,5 @@ package common -// byteToUInt32 将 byte 转换为uint32 func ByteToUInt32(data []byte) uint32 { i := uint32(data[0]) & 0xff i |= (uint32(data[1]) << 8) & 0xff00 diff --git a/pkg/qqwry/qqwry.go b/pkg/qqwry/qqwry.go index d7b6862..ae75b32 100644 --- a/pkg/qqwry/qqwry.go +++ b/pkg/qqwry/qqwry.go @@ -19,19 +19,19 @@ type QQwry struct { // NewQQwry new db from path func NewQQwry(filePath string) QQwry { - var tmpData []byte + var fileData []byte var fileInfo common.FileInfo // 判断文件是否存在 _, err := os.Stat(filePath) if err != nil && os.IsNotExist(err) { log.Println("文件不存在,尝试从网络获取最新纯真 IP 库") - tmpData, err = GetOnline() + fileData, err = Download() if err != nil { panic(err) } else { - if err := ioutil.WriteFile(filePath, tmpData, 0644); err == nil { - log.Printf("已将最新的纯真 IP 库保存到本地 %s ", filePath) + if err := ioutil.WriteFile(filePath, fileData, 0644); err == nil { + log.Printf("已将最新的 纯真IP库 保存到本地: %s ", filePath) } } } else { @@ -42,13 +42,12 @@ func NewQQwry(filePath string) QQwry { } defer fileInfo.FileBase.Close() - tmpData, err = ioutil.ReadAll(fileInfo.FileBase) + fileData, err = ioutil.ReadAll(fileInfo.FileBase) if err != nil { panic(err) } } - - fileInfo.Data = tmpData + fileInfo.Data = fileData buf := fileInfo.Data[0:8] start := binary.LittleEndian.Uint32(buf[:4]) @@ -64,14 +63,14 @@ func NewQQwry(filePath string) QQwry { } // Find ip地址查询对应归属地信息 -func (q QQwry) Find(ip string) (res string) { +func (db QQwry) Find(ip string) (res string) { if strings.Count(ip, ".") != 3 { return } ip4 := binary.BigEndian.Uint32(net.ParseIP(ip).To4()) - offset := q.searchIndex(ip4) + offset := db.searchIndex(ip4) if offset <= 0 { return } @@ -79,27 +78,27 @@ func (q QQwry) Find(ip string) (res string) { var gbkCountry []byte var gbkArea []byte - mode := q.ReadMode(offset + 4) + mode := db.ReadMode(offset + 4) // [IP][0x01][国家和地区信息的绝对偏移地址] if mode == common.RedirectMode1 { - countryOffset := q.ReadUInt24() - mode = q.ReadMode(countryOffset) + countryOffset := db.ReadUInt24() + mode = db.ReadMode(countryOffset) if mode == common.RedirectMode2 { - c := q.ReadUInt24() - gbkCountry = q.ReadString(c) + c := db.ReadUInt24() + gbkCountry = db.ReadString(c) countryOffset += 4 } else { - gbkCountry = q.ReadString(countryOffset) + gbkCountry = db.ReadString(countryOffset) countryOffset += uint32(len(gbkCountry) + 1) } - gbkArea = q.ReadArea(countryOffset) + gbkArea = db.ReadArea(countryOffset) } else if mode == common.RedirectMode2 { - countryOffset := q.ReadUInt24() - gbkCountry = q.ReadString(countryOffset) - gbkArea = q.ReadArea(offset + 8) + countryOffset := db.ReadUInt24() + gbkCountry = db.ReadString(countryOffset) + gbkArea = db.ReadArea(offset + 8) } else { - gbkCountry = q.ReadString(offset + 4) - gbkArea = q.ReadArea(offset + uint32(5+len(gbkCountry))) + gbkCountry = db.ReadString(offset + 4) + gbkArea = db.ReadArea(offset + uint32(5+len(gbkCountry))) } enc := simplifiedchinese.GBK.NewDecoder() @@ -110,24 +109,24 @@ func (q QQwry) Find(ip string) (res string) { } // searchIndex 查找索引位置 -func (q *QQwry) searchIndex(ip uint32) uint32 { - header := q.ReadData(8, 0) +func (db *QQwry) searchIndex(ip uint32) uint32 { + header := db.ReadData(8, 0) start := binary.LittleEndian.Uint32(header[:4]) end := binary.LittleEndian.Uint32(header[4:]) - buf := make([]byte, q.IndexLen) + buf := make([]byte, db.IndexLen) mid := uint32(0) _ip := uint32(0) for { - mid = q.GetMiddleOffset(start, end) - buf = q.ReadData(q.IndexLen, mid) + mid = db.GetMiddleOffset(start, end) + buf = db.ReadData(db.IndexLen, mid) _ip = binary.LittleEndian.Uint32(buf[:4]) - if end-start == q.IndexLen { + if end-start == db.IndexLen { offset := common.ByteToUInt32(buf[4:]) - buf = q.ReadData(q.IndexLen) + buf = db.ReadData(db.IndexLen) if ip < binary.LittleEndian.Uint32(buf[:4]) { return offset } diff --git a/pkg/qqwry/update.go b/pkg/qqwry/update.go index be871e1..74cd9dc 100644 --- a/pkg/qqwry/update.go +++ b/pkg/qqwry/update.go @@ -8,7 +8,43 @@ import ( "net/http" ) -func getKey() (uint32, error) { +func Download() (data []byte, err error) { + resp, err := http.Get("https://qqwry.mirror.noc.one/qqwry.rar") + if err != nil { + return nil, err + } + defer resp.Body.Close() + + body, err := ioutil.ReadAll(resp.Body) + if err != nil { + return nil, err + } + key, err := getCopyWriteKey() + if err != nil { + return nil, err + } + + return unRar(body, key) +} + +func unRar(data []byte, key uint32) ([]byte, error) { + for i := 0; i < 0x200; i++ { + key = key * 0x805 + key++ + key = key & 0xff + + data[i] = byte(uint32(data[i]) ^ key) + } + + reader, err := zlib.NewReader(bytes.NewReader(data)) + if err != nil { + return nil, err + } + + return ioutil.ReadAll(reader) +} + +func getCopyWriteKey() (uint32, error) { resp, err := http.Get("https://qqwry.mirror.noc.one/copywrite.rar") if err != nil { return 0, err @@ -21,35 +57,3 @@ func getKey() (uint32, error) { return binary.LittleEndian.Uint32(body[5*4:]), nil } } - -// get db content from mirror -func GetOnline() ([]byte, error) { - resp, err := http.Get("https://qqwry.mirror.noc.one/qqwry.rar") - if err != nil { - return nil, err - } - defer resp.Body.Close() - - if body, err := ioutil.ReadAll(resp.Body); err != nil { - return nil, err - } else { - if key, err := getKey(); err != nil { - return nil, err - } else { - for i := 0; i < 0x200; i++ { - key = key * 0x805 - key++ - key = key & 0xff - - body[i] = byte(uint32(body[i]) ^ key) - } - - reader, err := zlib.NewReader(bytes.NewReader(body)) - if err != nil { - return nil, err - } - - return ioutil.ReadAll(reader) - } - } -} diff --git a/pkg/zxipv6wry/zxipv6wry.go b/pkg/zxipv6wry/zxipv6wry.go index 8b855c9..a68ddd6 100644 --- a/pkg/zxipv6wry/zxipv6wry.go +++ b/pkg/zxipv6wry/zxipv6wry.go @@ -49,8 +49,8 @@ func NewZXwry(filePath string) ZXwry { } } -func (q ZXwry) Find(ip string) (result string) { - q.Offset = 0 +func (db ZXwry) Find(ip string) (result string) { + db.Offset = 0 tp := big.NewInt(0) op := big.NewInt(0) @@ -60,58 +60,50 @@ func (q ZXwry) Find(ip string) (result string) { tp.SetString("FFFFFFFFFFFFFFFF", 16) op.And(op, tp) - v6ip := op.Uint64() - offset := q.searchIndex(v6ip) - - country, area := q.getAddr(offset) - - if area == "ZX" { - area = "" - } - + ipv6 := op.Uint64() + offset := db.searchIndex(ipv6) + country, area := db.getAddr(offset) return fmt.Sprintf("%s %s", country, area) } -func (q *ZXwry) getAddr(offset uint32) (string, string) { - mode := q.ReadMode(offset) +func (db *ZXwry) getAddr(offset uint32) (string, string) { + mode := db.ReadMode(offset) if mode == common.RedirectMode1 { - // [IP][0x01][国家和地区信息的绝对偏移地址] - offset = q.ReadUInt24() - return q.getAddr(offset) + offset = db.ReadUInt24() + return db.getAddr(offset) } - // [IP][0x02][信息的绝对偏移][...] or [IP][国家][...] - _offset := q.Offset - 1 - c1 := q.ReadArea(_offset) + _offset := db.Offset - 1 + c1 := db.ReadArea(_offset) if mode == common.RedirectMode2 { - q.Offset = 4 + _offset + db.Offset = 4 + _offset } else { - q.Offset = _offset + uint32(1+len(c1)) + db.Offset = _offset + uint32(1+len(c1)) } - c2 := q.ReadArea(q.Offset) + c2 := db.ReadArea(db.Offset) return string(c1), string(c2) } -func (q *ZXwry) searchIndex(ip uint64) uint32 { - q.ItemLen = 8 - q.IndexLen = 11 +func (db *ZXwry) searchIndex(ip uint64) uint32 { + db.ItemLen = 8 + db.IndexLen = 11 - header := q.Data.Data[8:24] + header := db.Data.Data[8:24] start := binary.LittleEndian.Uint32(header[8:]) counts := binary.LittleEndian.Uint32(header[:8]) - end := start + counts*q.IndexLen + end := start + counts*db.IndexLen - buf := make([]byte, q.IndexLen) + buf := make([]byte, db.IndexLen) for { - mid := q.GetMiddleOffset(start, end) - buf = q.Data.Data[mid : mid+q.IndexLen] - _ip := binary.LittleEndian.Uint64(buf[:q.ItemLen]) + mid := db.GetMiddleOffset(start, end) + buf = db.Data.Data[mid : mid+db.IndexLen] + _ip := binary.LittleEndian.Uint64(buf[:db.ItemLen]) - if end-start == q.IndexLen { - if ip >= binary.LittleEndian.Uint64(q.Data.Data[end:end+q.ItemLen]) { - buf = q.Data.Data[end : end+q.IndexLen] + if end-start == db.IndexLen { + if ip >= binary.LittleEndian.Uint64(db.Data.Data[end:end+db.ItemLen]) { + buf = db.Data.Data[end : end+db.IndexLen] } - return common.ByteToUInt32(buf[q.ItemLen:]) + return common.ByteToUInt32(buf[db.ItemLen:]) } if _ip > ip { @@ -119,7 +111,7 @@ func (q *ZXwry) searchIndex(ip uint64) uint32 { } else if _ip < ip { start = mid } else if _ip == ip { - return common.ByteToUInt32(buf[q.ItemLen:]) + return common.ByteToUInt32(buf[db.ItemLen:]) } } }