diff options
Diffstat (limited to 'vendor/github.com/oschwald/geoip2-golang/reader.go')
-rw-r--r-- | vendor/github.com/oschwald/geoip2-golang/reader.go | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/vendor/github.com/oschwald/geoip2-golang/reader.go b/vendor/github.com/oschwald/geoip2-golang/reader.go new file mode 100644 index 0000000..ac5108f --- /dev/null +++ b/vendor/github.com/oschwald/geoip2-golang/reader.go @@ -0,0 +1,327 @@ +// Package geoip2 provides an easy-to-use API for the MaxMind GeoIP2 and +// GeoLite2 databases; this package does not support GeoIP Legacy databases. +// +// The structs provided by this package match the internal structure of +// the data in the MaxMind databases. +// +// See github.com/oschwald/maxminddb-golang for more advanced used cases. +package geoip2 + +import ( + "fmt" + "net" + + "github.com/oschwald/maxminddb-golang" +) + +// The City struct corresponds to the data in the GeoIP2/GeoLite2 City +// databases. +type City struct { + City struct { + GeoNameID uint `maxminddb:"geoname_id"` + Names map[string]string `maxminddb:"names"` + } `maxminddb:"city"` + Continent struct { + Code string `maxminddb:"code"` + GeoNameID uint `maxminddb:"geoname_id"` + Names map[string]string `maxminddb:"names"` + } `maxminddb:"continent"` + Country struct { + GeoNameID uint `maxminddb:"geoname_id"` + IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` + IsoCode string `maxminddb:"iso_code"` + Names map[string]string `maxminddb:"names"` + } `maxminddb:"country"` + Location struct { + AccuracyRadius uint16 `maxminddb:"accuracy_radius"` + Latitude float64 `maxminddb:"latitude"` + Longitude float64 `maxminddb:"longitude"` + MetroCode uint `maxminddb:"metro_code"` + TimeZone string `maxminddb:"time_zone"` + } `maxminddb:"location"` + Postal struct { + Code string `maxminddb:"code"` + } `maxminddb:"postal"` + RegisteredCountry struct { + GeoNameID uint `maxminddb:"geoname_id"` + IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` + IsoCode string `maxminddb:"iso_code"` + Names map[string]string `maxminddb:"names"` + } `maxminddb:"registered_country"` + RepresentedCountry struct { + GeoNameID uint `maxminddb:"geoname_id"` + IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` + IsoCode string `maxminddb:"iso_code"` + Names map[string]string `maxminddb:"names"` + Type string `maxminddb:"type"` + } `maxminddb:"represented_country"` + Subdivisions []struct { + GeoNameID uint `maxminddb:"geoname_id"` + IsoCode string `maxminddb:"iso_code"` + Names map[string]string `maxminddb:"names"` + } `maxminddb:"subdivisions"` + Traits struct { + IsAnonymousProxy bool `maxminddb:"is_anonymous_proxy"` + IsSatelliteProvider bool `maxminddb:"is_satellite_provider"` + } `maxminddb:"traits"` +} + +// The Country struct corresponds to the data in the GeoIP2/GeoLite2 +// Country databases. +type Country struct { + Continent struct { + Code string `maxminddb:"code"` + GeoNameID uint `maxminddb:"geoname_id"` + Names map[string]string `maxminddb:"names"` + } `maxminddb:"continent"` + Country struct { + GeoNameID uint `maxminddb:"geoname_id"` + IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` + IsoCode string `maxminddb:"iso_code"` + Names map[string]string `maxminddb:"names"` + } `maxminddb:"country"` + RegisteredCountry struct { + GeoNameID uint `maxminddb:"geoname_id"` + IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` + IsoCode string `maxminddb:"iso_code"` + Names map[string]string `maxminddb:"names"` + } `maxminddb:"registered_country"` + RepresentedCountry struct { + GeoNameID uint `maxminddb:"geoname_id"` + IsInEuropeanUnion bool `maxminddb:"is_in_european_union"` + IsoCode string `maxminddb:"iso_code"` + Names map[string]string `maxminddb:"names"` + Type string `maxminddb:"type"` + } `maxminddb:"represented_country"` + Traits struct { + IsAnonymousProxy bool `maxminddb:"is_anonymous_proxy"` + IsSatelliteProvider bool `maxminddb:"is_satellite_provider"` + } `maxminddb:"traits"` +} + +// The AnonymousIP struct corresponds to the data in the GeoIP2 +// Anonymous IP database. +type AnonymousIP struct { + IsAnonymous bool `maxminddb:"is_anonymous"` + IsAnonymousVPN bool `maxminddb:"is_anonymous_vpn"` + IsHostingProvider bool `maxminddb:"is_hosting_provider"` + IsPublicProxy bool `maxminddb:"is_public_proxy"` + IsTorExitNode bool `maxminddb:"is_tor_exit_node"` +} + +// The ASN struct corresponds to the data in the GeoLite2 ASN database. +type ASN struct { + AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"` + AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"` +} + +// The ConnectionType struct corresponds to the data in the GeoIP2 +// Connection-Type database. +type ConnectionType struct { + ConnectionType string `maxminddb:"connection_type"` +} + +// The Domain struct corresponds to the data in the GeoIP2 Domain database. +type Domain struct { + Domain string `maxminddb:"domain"` +} + +// The ISP struct corresponds to the data in the GeoIP2 ISP database. +type ISP struct { + AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"` + AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"` + ISP string `maxminddb:"isp"` + Organization string `maxminddb:"organization"` +} + +type databaseType int + +const ( + isAnonymousIP = 1 << iota + isASN + isCity + isConnectionType + isCountry + isDomain + isEnterprise + isISP +) + +// Reader holds the maxminddb.Reader struct. It can be created using the +// Open and FromBytes functions. +type Reader struct { + mmdbReader *maxminddb.Reader + databaseType databaseType +} + +// InvalidMethodError is returned when a lookup method is called on a +// database that it does not support. For instance, calling the ISP method +// on a City database. +type InvalidMethodError struct { + Method string + DatabaseType string +} + +func (e InvalidMethodError) Error() string { + return fmt.Sprintf(`geoip2: the %s method does not support the %s database`, + e.Method, e.DatabaseType) +} + +// UnknownDatabaseTypeError is returned when an unknown database type is +// opened. +type UnknownDatabaseTypeError struct { + DatabaseType string +} + +func (e UnknownDatabaseTypeError) Error() string { + return fmt.Sprintf(`geoip2: reader does not support the "%s" database type`, + e.DatabaseType) +} + +// Open takes a string path to a file and returns a Reader struct or an error. +// The database file is opened using a memory map. Use the Close method on the +// Reader object to return the resources to the system. +func Open(file string) (*Reader, error) { + reader, err := maxminddb.Open(file) + if err != nil { + return nil, err + } + dbType, err := getDBType(reader) + return &Reader{reader, dbType}, err +} + +// FromBytes takes a byte slice corresponding to a GeoIP2/GeoLite2 database +// file and returns a Reader struct or an error. Note that the byte slice is +// use directly; any modification of it after opening the database will result +// in errors while reading from the database. +func FromBytes(bytes []byte) (*Reader, error) { + reader, err := maxminddb.FromBytes(bytes) + if err != nil { + return nil, err + } + dbType, err := getDBType(reader) + return &Reader{reader, dbType}, err +} + +func getDBType(reader *maxminddb.Reader) (databaseType, error) { + switch reader.Metadata.DatabaseType { + case "GeoIP2-Anonymous-IP": + return isAnonymousIP, nil + case "GeoLite2-ASN": + return isASN, nil + // We allow City lookups on Country for back compat + case "GeoLite2-City", + "GeoIP2-City", + "GeoIP2-City-Africa", + "GeoIP2-City-Asia-Pacific", + "GeoIP2-City-Europe", + "GeoIP2-City-North-America", + "GeoIP2-City-South-America", + "GeoIP2-Precision-City", + "GeoLite2-Country", + "GeoIP2-Country": + return isCity | isCountry, nil + case "GeoIP2-Connection-Type": + return isConnectionType, nil + case "GeoIP2-Domain": + return isDomain, nil + case "GeoIP2-Enterprise": + return isEnterprise | isCity | isCountry, nil + case "GeoIP2-ISP", "GeoIP2-Precision-ISP": + return isISP, nil + default: + return 0, UnknownDatabaseTypeError{reader.Metadata.DatabaseType} + } +} + +// City takes an IP address as a net.IP struct and returns a City struct +// and/or an error. Although this can be used with other databases, this +// method generally should be used with the GeoIP2 or GeoLite2 City databases. +func (r *Reader) City(ipAddress net.IP) (*City, error) { + if isCity&r.databaseType == 0 { + return nil, InvalidMethodError{"City", r.Metadata().DatabaseType} + } + var city City + err := r.mmdbReader.Lookup(ipAddress, &city) + return &city, err +} + +// Country takes an IP address as a net.IP struct and returns a Country struct +// and/or an error. Although this can be used with other databases, this +// method generally should be used with the GeoIP2 or GeoLite2 Country +// databases. +func (r *Reader) Country(ipAddress net.IP) (*Country, error) { + if isCountry&r.databaseType == 0 { + return nil, InvalidMethodError{"Country", r.Metadata().DatabaseType} + } + var country Country + err := r.mmdbReader.Lookup(ipAddress, &country) + return &country, err +} + +// AnonymousIP takes an IP address as a net.IP struct and returns a +// AnonymousIP struct and/or an error. +func (r *Reader) AnonymousIP(ipAddress net.IP) (*AnonymousIP, error) { + if isAnonymousIP&r.databaseType == 0 { + return nil, InvalidMethodError{"AnonymousIP", r.Metadata().DatabaseType} + } + var anonIP AnonymousIP + err := r.mmdbReader.Lookup(ipAddress, &anonIP) + return &anonIP, err +} + +// ASN takes an IP address as a net.IP struct and returns a ASN struct and/or +// an error +func (r *Reader) ASN(ipAddress net.IP) (*ASN, error) { + if isASN&r.databaseType == 0 { + return nil, InvalidMethodError{"ASN", r.Metadata().DatabaseType} + } + var val ASN + err := r.mmdbReader.Lookup(ipAddress, &val) + return &val, err +} + +// ConnectionType takes an IP address as a net.IP struct and returns a +// ConnectionType struct and/or an error +func (r *Reader) ConnectionType(ipAddress net.IP) (*ConnectionType, error) { + if isConnectionType&r.databaseType == 0 { + return nil, InvalidMethodError{"ConnectionType", r.Metadata().DatabaseType} + } + var val ConnectionType + err := r.mmdbReader.Lookup(ipAddress, &val) + return &val, err +} + +// Domain takes an IP address as a net.IP struct and returns a +// Domain struct and/or an error +func (r *Reader) Domain(ipAddress net.IP) (*Domain, error) { + if isDomain&r.databaseType == 0 { + return nil, InvalidMethodError{"Domain", r.Metadata().DatabaseType} + } + var val Domain + err := r.mmdbReader.Lookup(ipAddress, &val) + return &val, err +} + +// ISP takes an IP address as a net.IP struct and returns a ISP struct and/or +// an error +func (r *Reader) ISP(ipAddress net.IP) (*ISP, error) { + if isISP&r.databaseType == 0 { + return nil, InvalidMethodError{"ISP", r.Metadata().DatabaseType} + } + var val ISP + err := r.mmdbReader.Lookup(ipAddress, &val) + return &val, err +} + +// Metadata takes no arguments and returns a struct containing metadata about +// the MaxMind database in use by the Reader. +func (r *Reader) Metadata() maxminddb.Metadata { + return r.mmdbReader.Metadata +} + +// Close unmaps the database file from virtual memory and returns the +// resources to the system. +func (r *Reader) Close() error { + return r.mmdbReader.Close() +} |