maxminder 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,36 @@
1
+ require 'uri'
2
+ require 'net/https'
3
+ require 'logger'
4
+ require 'timeout'
5
+
6
+ require 'max_mind/enquiry'
7
+ require 'max_mind/lookup'
8
+
9
+ module MaxMind
10
+
11
+ ## Exception class for generic errors.
12
+ class Error < StandardError; end
13
+
14
+ ## Exception class for when connection to the max mind service fails.
15
+ class ConnectionError < Error; end
16
+
17
+ class << self
18
+ ## Licence key for accessing the maxmind service. A trial key
19
+ ## can be requested from http://www.maxmind.com/app/ccv2r_signup
20
+ attr_accessor :licence_key
21
+
22
+ ## The server (or servers) to accept your request
23
+ attr_accessor :endpoints
24
+
25
+ ## Return a default array of end points if none are specified.
26
+ def endpoints
27
+ @endpoints || ["https://minfraud1.maxmind.com/app/ccv2r", "https://minfraud3.maxmind.com/app/ccv2r"]
28
+ end
29
+
30
+ ## Return a logger object for this MaxMind interaction
31
+ def logger
32
+ @logger ||= Logger.new(STDOUT)
33
+ end
34
+ end
35
+
36
+ end
@@ -0,0 +1,120 @@
1
+ module MaxMind
2
+ class Enquiry
3
+
4
+ attr_accessor :attributes
5
+
6
+ def initialize(attributes = {})
7
+ self.attributes = attributes if attributes.is_a?(Hash)
8
+ end
9
+
10
+ ## The attributes here will be sent to max mind
11
+ def sendable_attributes
12
+ hash = Hash.new
13
+ for field, data in attributes
14
+ hash[mapping[field]] = data
15
+ end
16
+ hash['license_key'] = MaxMind.licence_key
17
+ hash
18
+ end
19
+
20
+ ## Run the check and return a hash of responses from the server.
21
+ def lookup
22
+ MaxMind.logger.debug "Beginning lookups"
23
+ MaxMind.logger.debug "('#{sendable_attributes.inspect}')"
24
+ for endpoint in MaxMind.endpoints
25
+ MaxMind.logger.debug "Attempting lookup on #{endpoint}"
26
+ uri = URI.parse(endpoint)
27
+ req = Net::HTTP::Post.new(uri.path)
28
+ req.set_form_data(sendable_attributes)
29
+ res = Net::HTTP.new(uri.host, uri.port)
30
+ if uri.scheme == 'https'
31
+ res.use_ssl = true
32
+ res.verify_mode = OpenSSL::SSL::VERIFY_NONE
33
+ end
34
+
35
+ begin
36
+ case res = res.request(req)
37
+ when Net::HTTPSuccess
38
+ return Lookup.new(res.body)
39
+ else
40
+ MaxMind.logger.debug "Error on #{endpoint} (#{res.class.to_s})"
41
+ next
42
+ end
43
+ rescue Timeout::Error
44
+ MaxMind.logger.debug "Timed out connecting to #{endpoint}"
45
+ next
46
+ end
47
+ end
48
+
49
+ false
50
+ end
51
+
52
+ ## Set or get an attribute from the attributes hash or raise
53
+ ## no method error if it doesn't exist in our mapping.
54
+ def method_missing(name, value = nil)
55
+ attribute_name = name.to_s.gsub(/\=\z/, '').to_sym
56
+ return super unless mapping.keys.include?(attribute_name)
57
+ value ? (attributes[attribute_name] = value) : attributes[attribute_name]
58
+ end
59
+
60
+ ## Various methods to make setting fields in the attributes hash
61
+ ## a little easier.
62
+ attr_reader :email, :username, :password
63
+
64
+ def email=(value)
65
+ @email = value
66
+ self.attributes[:email_md5] = Digest::MD5.hexdigest(value)
67
+ self.attributes[:email_domain] = value.split('@', 2).last
68
+ value
69
+ end
70
+
71
+ def username=(value)
72
+ @username = value
73
+ self.attributes[:username_md5] = Digest::MD5.hexdigest(value)
74
+ value
75
+ end
76
+
77
+ def password=(value)
78
+ @password = value
79
+ self.attributes[:password_md5] = Digest::MD5.hexdigest(value)
80
+ value
81
+ end
82
+
83
+ private
84
+
85
+ ## This method returns a mapping of method names to the appropriate attribute
86
+ ## expected by the MaxMind API.
87
+ def mapping
88
+ {
89
+ :ip_address => 'i',
90
+ :forwarded_ip => 'forwardedIP',
91
+
92
+ :city => 'city',
93
+ :region => 'region',
94
+ :postal => 'postal',
95
+ :country => 'country',
96
+
97
+ :shipping_address => 'shipAddr',
98
+ :shipping_city => 'shipCity',
99
+ :shipping_region => 'shipRegion',
100
+ :shipping_postal => 'shipPostal',
101
+ :shipping_country => 'shipCountry',
102
+
103
+ :email_domain => 'domain',
104
+ :email_md5 => 'emailMD5',
105
+ :username_md5 => 'usernameMD5',
106
+ :password_md5 => 'passwordMD5',
107
+
108
+ :bin => 'bin',
109
+ :bin_name => 'binName',
110
+ :bin_phone => 'binPhone',
111
+
112
+ :transaction_id => 'txnID',
113
+ :session_id => 'sessionID',
114
+ :user_agent => 'user_agent',
115
+ :accept_language => 'accept_language'
116
+ }
117
+ end
118
+
119
+ end
120
+ end
@@ -0,0 +1,78 @@
1
+ module MaxMind
2
+ class Lookup
3
+
4
+ def initialize(raw)
5
+ @attributes = Hash.new
6
+ for key, value in raw.split(';').map{|r| r.split('=', 2)}
7
+ field_name, type = mapping[key]
8
+ @attributes[field_name] = parse_value(value, type)
9
+ end
10
+ end
11
+
12
+ ## Return the appropriate attribute from the attributes hash.
13
+ def method_missing(name)
14
+ super unless mapping.values.map(&:first).include?(name.to_sym)
15
+ @attributes[name.to_sym]
16
+ end
17
+
18
+ private
19
+
20
+ ## This is the mapping of response attributes to their local variable name
21
+ ## and type of data which is expected.
22
+ def mapping
23
+ {
24
+ 'countryMatch' => [:country_match, :boolean],
25
+ 'countryCode' => [:country_code, :string],
26
+ 'highRiskCountry' => [:high_risk_country?, :boolean],
27
+ 'distance' => [:distance, :integer],
28
+ 'ip_region' => [:ip_region, :string],
29
+ 'ip_city' => [:ip_city, :string],
30
+ 'ip_latitude' => [:ip_latitude, :decimal],
31
+ 'ip_longitude' => [:ip_longitude, :decimal],
32
+ 'ip_isp' => [:ip_isp, :string],
33
+ 'ip_org' => [:ip_organisation, :string],
34
+ 'anonymousProxy' => [:anonymous_proxy?, :boolean],
35
+ 'proxyScore' => [:proxy_score, :float],
36
+ 'isTransProxy' => [:transparent_proxy?, :boolean],
37
+ 'freeMail' => [:free_email?, :boolean],
38
+ 'carderEmail' => [:high_risk_email?, :boolean],
39
+ 'highRiskUsername' => [:high_risk_username?, :boolean],
40
+ 'highRiskPassword' => [:high_risk_password?, :boolean],
41
+ 'binMatch' => [:bin_match?, :boolean],
42
+ 'binCountry' => [:bin_country, :string],
43
+ 'binNameMatch' => [:bin_name_match?, :boolean],
44
+ 'binName' => [:bin_name, :string],
45
+ 'binPhoneMatch' => [:bin_phone_match?, :boolean],
46
+ 'binPhone' => [:bin_phone, :string],
47
+ 'custPhoneInBillingLoc' => [:phone_in_billing_location?, :boolean],
48
+ 'shipForward' => [:mail_drop_address?, :boolean],
49
+ 'cityPostalMatch' => [:city_matches_postal?, :boolean],
50
+ 'shipCityPostalMatch' => [:ship_city_matches_postal?, :boolean],
51
+ 'score' => [:score, :decimal],
52
+ 'explanation' => [:explanation, :string],
53
+ 'riskScore' => [:risk_score, :decimal],
54
+ 'queriesRemaining' => [:queries_remaining, :decimal],
55
+ 'maxmindID' => [:id, :string],
56
+ 'err' => [:error, :string]
57
+ }
58
+ end
59
+
60
+ ## Return a value as an instance of an appropriate ruby object.
61
+ def parse_value(value, type = :string)
62
+ case type
63
+ when :integer then value.to_i
64
+ when :decimal then value.to_f
65
+ when :boolean
66
+ case value
67
+ when 'Yes' then true
68
+ when 'No' then false
69
+ else
70
+ nil
71
+ end
72
+ else
73
+ value
74
+ end
75
+ end
76
+
77
+ end
78
+ end
metadata ADDED
@@ -0,0 +1,64 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: maxminder
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 1
7
+ - 0
8
+ - 0
9
+ version: 1.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Adam Cooke
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-09-05 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description:
22
+ email: adam@atechmedia.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - lib/max_mind/enquiry.rb
31
+ - lib/max_mind/lookup.rb
32
+ - lib/max_mind.rb
33
+ has_rdoc: false
34
+ homepage: http://github.com/adamcooke/maxminder
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options: []
39
+
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ">="
45
+ - !ruby/object:Gem::Version
46
+ segments:
47
+ - 0
48
+ version: "0"
49
+ required_rubygems_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 0
55
+ version: "0"
56
+ requirements: []
57
+
58
+ rubyforge_project:
59
+ rubygems_version: 1.3.6
60
+ signing_key:
61
+ specification_version: 3
62
+ summary: Simple (non-bloated) Ruby library for MaxMind
63
+ test_files: []
64
+