package main import ( "encoding/json" "fmt" "math/big" "net" "sort" "strconv" "strings" "github.com/pyke369/golang-support/rcache" ) func stringInSlice(a string, list []string) bool { for _, b := range list { if b == a { return true } } return false } // inArray checks if there is a member of "search" in "list". sort list to be more // efficiant. adapt with sorting "search" too func inArray(search, list []string) bool { sort.Strings(list) for _, g := range search { i := sort.Search(len(list), func(i int) bool { return list[i] >= g }) if i < len(list) && list[i] == g { return true } } return false } // printJSON pretty print d func printJSON(d interface{}) []byte { ret, _ := json.MarshalIndent(d, " ", " ") return ret } // reverse the part order on every member of the array func reverse(s string) string { part := strings.Split(s, ".") for i, j := 0, len(part)-1; i < j; i, j = i+1, j-1 { part[i], part[j] = part[j], part[i] } return strings.Join(part, ".") } // domainSort sort string by first reversing them func domainSort(s []string) { for i := range s { s[i] = reverse(s[i]) } sort.Strings(s) for i := range s { s[i] = reverse(s[i]) } } func ptrToIP(s string) string { s = reverse(s) count := 0 ip := "" version := 4 for _, elt := range strings.Split(s, ".") { switch elt { case "": case "ip6": version = 6 case "in-addr": case "arpa": default: count++ ip += elt if version == 4 && count != 4 { ip += "." } if version == 6 && count%4 == 0 && count != 32 { ip += ":" } } } return ip } func ipToInt(ip string) *big.Int { return big.NewInt(0).SetBytes([]byte(net.ParseIP(ip))) } // iPtoReverse calculate the reverse name associated with an IPv4 or v6 func iPtoReverse(ip net.IP) (arpa string) { const hexDigit = "0123456789abcdef" // code copied and adapted from the net library // ip can be 4 or 16 bytes long if ip.To4() != nil { if len(ip) == 16 { return uitoa(uint(ip[15])) + "." + uitoa(uint(ip[14])) + "." + uitoa(uint(ip[13])) + "." + uitoa(uint(ip[12])) + ".in-addr.arpa." } return uitoa(uint(ip[3])) + "." + uitoa(uint(ip[2])) + "." + uitoa(uint(ip[1])) + "." + uitoa(uint(ip[0])) + ".in-addr.arpa." } // Must be IPv6 buf := make([]byte, 0, len(ip)*4+len("ip6.arpa.")) // Add it, in reverse, to the buffer for i := len(ip) - 1; i >= 0; i-- { v := ip[i] buf = append(buf, hexDigit[v&0xF]) buf = append(buf, '.') buf = append(buf, hexDigit[v>>4]) buf = append(buf, '.') } // Append "ip6.arpa." and return (buf already has the final .) buf = append(buf, "ip6.arpa."...) return string(buf) } // Convert unsigned integer to decimal string. // code copied from the net library func uitoa(val uint) string { if val == 0 { // avoid string allocation return "0" } var buf [20]byte // big enough for 64bit value base 10 i := len(buf) - 1 for val >= 10 { q := val / 10 buf[i] = byte('0' + val - q*10) i-- val = q } // val < 10 buf[i] = byte('0' + val) return string(buf[i:]) } func trimPoint(s string) string { return strings.TrimRight(s, ".") } func addPoint(s string) string { s = trimPoint(s) if !strings.HasSuffix(s, ".") && !strings.HasSuffix(s, "*") { s = s + "." } return s } // add double quotes at the begining and the end of the string. func addQuotes(s string) string { const q = "\"" s = strings.Trim(s, q) s = strings.Replace(s, q, "\\\"", -1) return q + s + q } func validSRVName(s string) bool { return rcache.Get("^_[a-z0-9]+\\._(tcp|udp|tls)[^ ]+$").MatchString(s) } func validSRV(s string) string { // _service._proto.name. TTL class SRV priority weight port target. match := rcache.Get("^([0-9]+) +([0-9]+) +([0-9]+) +(.+)$").FindStringSubmatch(s) if len(match) > 0 && validName(match[4], false) { return match[4] } return "" } func validName(s string, wildcard bool) bool { if !wildcard { return rcache.Get( "^(([a-z0-9]|[a-z0-9_][a-z0-9_\\-]*[a-z0-9])\\.)*([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])\\.$").MatchString(s) } return rcache.Get( "^(\\*\\.)?(([a-z0-9]|[a-z0-9_][a-z0-9_\\-]*[a-z0-9])\\.)*([a-z0-9]|[a-z0-9][a-z0-9\\-]*[a-z0-9])\\.$").MatchString(s) } func validMX(s string) string { match := rcache.Get("^([0-9]+) +(.+)$").FindStringSubmatch(s) if len(match) > 0 && validName(match[2], false) { return match[2] } return "" } func validCAA(s string) string { match := rcache.Get("^([0-9]+) +(issue|issuewild|iodef) +(.+)$").FindStringSubmatch(s) if len(match) == 0 { return "" } i, _ := strconv.Atoi(match[1]) if i < 0 || i > 255 { return "" } return fmt.Sprintf("%s %s %s", match[1], match[2], addQuotes(match[3])) }