package header import ( "net" "regexp" ) // IpRegExp matches characters allowed in IPv4 or IPv6 network addresses. // Kept for backwards compatibility (other packages reference it), but IP() no longer uses it. var IpRegExp = regexp.MustCompile(`[^a-zA-Z0-9:.]`) const ( // IPv6Length represents the maximum length of an IPv6 address string. IPv6Length = 39 ) // IsIP returns true if the string matches a valid IP address. func IsIP(s string) bool { return IP(s, "") != "" } // IP returns the sanitized and normalized network address if it is valid, or the default otherwise. func IP(s, defaultIp string) string { // Return default if invalid. if s == "" || len(s) > 64 || s == defaultIp { return defaultIp } // Filter invalid characters: allow only [A-Za-z0-9:.] fastOK := true for i := 0; i < len(s); i++ { b := s[i] isAlphaNum := (b >= '0' && b <= '9') || (b >= 'a' && b <= 'z') || (b >= 'A' && b <= 'Z') if !isAlphaNum && b != ':' && b != '.' { fastOK = false break } } if !fastOK { dst := make([]byte, 0, len(s)) for i := 0; i < len(s); i++ { c := s[i] if (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == ':' || c == '.' { dst = append(dst, c) } } s = string(dst) if s == "" { return defaultIp } } // Limit string length to 39 characters. if len(s) > IPv6Length { s = s[:IPv6Length] } // Parse IP address and return it as string. if ip := net.ParseIP(s); ip == nil { return defaultIp } else { return ip.String() } }