func (self RedisDB) UnbanAddr(addr string) (err error) { _, err = self.client.Del(IP_BAN_PREFIX + addr).Result() isnet, ipnet := util.IsSubnet(addr) var start string var range_start string if isnet { min, max := util.IPNet2MinMax(ipnet) range_start = util.ZeroIPString(min) start = util.ZeroIPString(max) } else { _, err = self.client.Del(IP_BAN_PREFIX + addr).Result() return } res, err := self.client.ZRangeByLex(IP_RANGE_BAN_KR, redis.ZRangeByScore{Min: "[" + start, Max: "+", Count: 1}).Result() if err == nil && len(res) > 0 { var range_min string range_max := res[0] range_min, err = self.client.HGet(IP_RANGE_BAN_PREFIX+range_max, "start").Result() if err != nil { return } banned := strings.Compare(range_start, range_min) >= 0 if banned { self.client.ZRem(IP_RANGE_BAN_KR, range_max) self.client.Del(IP_RANGE_BAN_PREFIX + range_max) } } return }
func (self RedisDB) CheckIPBanned(addr string) (banned bool, err error) { banned, err = self.client.Exists(IP_BAN_PREFIX + addr).Result() if banned { return } isnet, ipnet := util.IsSubnet(addr) var start string var range_start string if isnet { min, max := util.IPNet2MinMax(ipnet) range_start = util.ZeroIPString(min) start = util.ZeroIPString(max) } else { ip := net.ParseIP(addr) if ip == nil { return false, errors.New("Couldn't parse IP") } start = util.ZeroIPString(ip) range_start = start } res, err := self.client.ZRangeByLex(IP_RANGE_BAN_KR, redis.ZRangeByScore{Min: "[" + start, Max: "+", Count: 1}).Result() if err == nil && len(res) > 0 { var range_min string range_max := res[0] range_min, err = self.client.HGet(IP_RANGE_BAN_PREFIX+range_max, "start").Result() if err != nil { return } banned = strings.Compare(range_start, range_min) >= 0 } return }
func (self RedisDB) GetMessageIDByCIDR(cidr *net.IPNet) (msgids []string, err error) { min, max := util.IPNet2MinMax(cidr) start := util.ZeroIPString(min) stop := util.ZeroIPString(max) res, err := self.client.ZRangeByLex(IP_WKR, redis.ZRangeByScore{Min: "[" + start, Max: "[" + stop}).Result() if err == nil && len(res) > 0 { for _, ip := range res { posts, _ := self.client.SMembers(IP_ARTICLE_KR_PREFIX + ip).Result() msgids = append(msgids, posts...) } } return }
func (self RedisDB) BanAddr(addr string) (err error) { isnet, ipnet := util.IsSubnet(addr) if !isnet { _, err = self.client.HMSet(IP_BAN_PREFIX+addr, "addr", addr, "made", strconv.Itoa(int(util.TimeNow()))).Result() return } isBanned, err := self.CheckIPBanned(addr) if !isBanned && err == nil { //make sure this range isn't banned already min, max := util.IPNet2MinMax(ipnet) start := util.ZeroIPString(min) end := util.ZeroIPString(max) self.clearIPRange(start, end) //delete all banned ranges that are contained within this range _, err = self.client.ZAdd(IP_RANGE_BAN_KR, redis.Z{Score: 0.0, Member: end}).Result() if err != nil { return } _, err = self.client.HMSet(IP_RANGE_BAN_PREFIX+end, "start", start, "end", end, "made", strconv.Itoa(int(util.TimeNow()))).Result() } return }
func (self RedisDB) DeleteArticle(msgid string) error { p, err := self.GetPost(msgid) if err == nil { if !p.OP { self.client.ZRem(THREAD_POST_WKR+p.Parent, msgid) } hash, _ := self.client.HGet(ARTICLE_PREFIX+msgid, "message_id_hash").Result() if hash != "" { self.client.Del(HASH_MESSAGEID_PREFIX + hash) } //self.client.Del(ARTICLE_PREFIX+msgid, ARTICLE_POST_PREFIX+msgid, ARTICLE_KEY_PREFIX+msgid) self.client.ZRem(GROUP_ARTICLE_POSTTIME_WKR_PREFIX+p.Board, msgid) self.client.ZRem(ARTICLE_WKR, msgid) headers, _ := self.client.SMembers(MESSAGEID_HEADER_KR_PREFIX + msgid).Result() for _, h := range headers { self.client.SRem(HEADER_KR_PREFIX+h, msgid) } self.client.Del(MESSAGEID_HEADER_KR_PREFIX + msgid) atts, _ := self.client.SMembers(ARTICLE_ATTACHMENT_KR_PREFIX + msgid).Result() for _, a := range atts { self.client.SRem(ATTACHMENT_ARTICLE_KR_PREFIX+a, msgid) exists, _ := self.client.Exists(ATTACHMENT_ARTICLE_KR_PREFIX + a).Result() if !exists { //no other post uses this attachment any more //TODO delete files from disk self.client.Del(ATTACHMENT_PREFIX + a) } } self.client.Del(ARTICLE_ATTACHMENT_KR_PREFIX + msgid) self.client.ZRem(ARTICLE_NUMBERS_PREFIX+"group::"+p.Board, msgid) addr := p.Addr ip := net.ParseIP(addr) if ip != nil { addr = util.ZeroIPString(ip) } self.client.SRem(IP_ARTICLE_KR_PREFIX+addr, msgid) if ip != nil { count, err := self.client.SRem(IP_ARTICLE_KR_PREFIX + addr).Result() if err == nil && count <= 0 { self.client.ZRem(IP_WKR, addr) } } } return err }
// register a message with the database func (self RedisDB) RegisterArticle(message *model.Article) (err error) { pipe := self.client.Pipeline() defer pipe.Close() msgid := message.MessageID group := message.Newsgroup has, _ := self.HasNewsgroup(group) if !has { self.RegisterNewsgroup(group) } has, _ = self.HasArticle(msgid) if has { return } //insert IP addr := message.Addr ip := net.ParseIP(addr) if ip != nil { addr = util.ZeroIPString(ip) pipe.ZAddNX(IP_RANGE_BAN_KR, redis.Z{Score: 0.0, Member: addr}) } pipe.SAdd(IP_ARTICLE_KR_PREFIX+addr, msgid) now := util.TimeNow() // insert article metadata pipe.HMSet(ARTICLE_PREFIX+msgid, "msgid", msgid, "message_id_hash", util.HashMessageID(msgid), "message_newsgroup", group, "time_obtained", strconv.Itoa(int(now)), "message_ref_id", message.Reference) pipe.Set(HASH_MESSAGEID_PREFIX+util.HashMessageID(msgid), msgid, 0) // update newsgroup pipe.ZAddXX(GROUP_POSTTIME_WKR, redis.Z{Score: float64(now), Member: group}) pipe.ZAddNX(GROUP_ARTICLE_POSTTIME_WKR_PREFIX+group, redis.Z{Score: float64(now), Member: msgid}) // insert article post pipe.HMSet(ARTICLE_POST_PREFIX+msgid, "newsgroup", group, "message_id", msgid, "ref_id", message.Reference, "name", message.Name, "subject", message.Subject, "path", message.Path, "time_posted", strconv.Itoa(int(message.Posted)), "message", message.Text, "addr", addr) if group != "ctl" { // control messages aren't added to the global keyring pipe.ZAddNX(ARTICLE_WKR, redis.Z{Score: float64(now), Member: msgid}) } // set / update thread state if message.Reference == "" { // insert new thread for op pipe.ZAddNX(GROUP_THREAD_POSTTIME_WKR_PREFIX+group, redis.Z{Score: float64(message.Posted), Member: msgid}) pipe.ZAddNX(GROUP_THREAD_BUMPTIME_WKR_PREFIX+group, redis.Z{Score: float64(message.Posted), Member: msgid}) if group != "ctl" { pipe.ZAddNX(THREAD_BUMPTIME_WKR, redis.Z{Score: float64(message.Posted), Member: msgid}) } } else { ref := message.Reference if !util.IsSage(message.Subject) { // bump it nigguh pipe.ZAddXX(GROUP_THREAD_BUMPTIME_WKR_PREFIX+group, redis.Z{Score: float64(message.Posted), Member: ref}) pipe.ZAddXX(THREAD_BUMPTIME_WKR, redis.Z{Score: float64(message.Posted), Member: ref}) } // update last posted pipe.ZAddXX(GROUP_THREAD_POSTTIME_WKR_PREFIX+group, redis.Z{Score: float64(message.Posted), Member: ref}) pipe.ZAddNX(THREAD_POST_WKR+ref, redis.Z{Score: float64(message.Posted), Member: msgid}) } // register article header for k, val := range message.Header { k = strings.ToLower(k) for _, v := range val { k = strings.ToLower(k) header := "Name::" + k + "::Value::" + v pipe.SAdd(HEADER_KR_PREFIX+header, msgid) pipe.SAdd(MESSAGEID_HEADER_KR_PREFIX+msgid, header) } } // add nntp message numbers number, _ := self.client.ZIncrBy(ARTICLE_NUMBERS_PREFIX+"last", float64(1), group).Result() pipe.ZAddNX(ARTICLE_NUMBERS_PREFIX+"group::"+group, redis.Z{Score: number, Member: msgid}) // register all attachments atts := message.Attachments if atts != nil { for _, att := range atts { hash := att.Hash pipe.SAdd(ATTACHMENT_ARTICLE_KR_PREFIX+hash, msgid) pipe.SAdd(ARTICLE_ATTACHMENT_KR_PREFIX+msgid, hash) pipe.HSetNX(ATTACHMENT_PREFIX+hash, "message_id", msgid) pipe.HSetNX(ATTACHMENT_PREFIX+hash, "sha_hash", hash) pipe.HSetNX(ATTACHMENT_PREFIX+hash, "filename", att.Name) pipe.HSetNX(ATTACHMENT_PREFIX+hash, "filepath", att.Path) pipe.HSetNX(ATTACHMENT_PREFIX+hash, "mime", att.Mime) } } _, err = pipe.Exec() if err != nil { log.Println("failed to register nntp article", err) } return }