maxmind_geoip2 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d44d6918c53ce5896328cf616a9aa3a8ab27ab52
4
+ data.tar.gz: 8834d5eba9dcac03dd2fe670412da8d65e57d4ad
5
+ SHA512:
6
+ metadata.gz: c7f4cb6969a08e851c94c1112261bea19e8a81d306338fc6eb1e0172fd51237ab29f57974490dbf46a5e0400a080bbb291f28ccaed1d8c1081a755dbce3bf2f6
7
+ data.tar.gz: 20ae0471170fa6022f853257fcb93ff37ed9c3774b07e748db0aa562903e41c47cfdb14a1465f88e8618b1733ed3d20943a71751cc89411db0b616d35538d1ac
@@ -0,0 +1,7 @@
1
+ mkmf.log
2
+ Makefile
3
+ GeoIP2.so
4
+ *.o
5
+ Gemfile.lock
6
+ *.bundle
7
+ GeoLite2-City.mmdb
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,64 @@
1
+ # Ruby Maxmind GeoIP2 Bindings
2
+
3
+ ## Description
4
+
5
+ Searches city by ip address in local database from [maxmind.com](http://dev.maxmind.com/geoip/geoip2/geolite2/).
6
+
7
+ Use it with rails. For now, I think.
8
+
9
+ ## Installation
10
+
11
+ [libmaxminddb](https://github.com/maxmind/libmaxminddb) must be installed.
12
+
13
+ ```
14
+ gem 'maxmind_geoip2'
15
+ ```
16
+
17
+ ## Usage
18
+
19
+ ### Configuration, can be moved to rails initializer
20
+
21
+ ```ruby
22
+ MaxmindGeoIP2.file '<local_db_file.mmdb>' # default: GeoLite2-City.mmdb
23
+ MaxmindGeoIP2.locale 'ru' # default: 'ru'
24
+ ```
25
+
26
+ ### Further usage:
27
+
28
+ Returns nil if nothing found and raises exception if file not opened or not found
29
+
30
+ ```ruby
31
+ city = MaxmindGeoIP2.locate(<ip address>, <optional lang>)
32
+
33
+ city = MaxmindGeoIP2.locate '77.93.127.33'
34
+ => {"city"=>"Тамбов",
35
+ "city_geoname_id"=>484646,
36
+ "country"=>"Россия",
37
+ "country_geoname_id"=>2017370,
38
+ "country_code"=>"RU",
39
+ "continent"=>"Европа",
40
+ "continent_code"=>"EU",
41
+ "continent_geoname_id"=>6255148,
42
+ "subdivision"=>"Тамбовская область",
43
+ "subdivision_code"=>"TAM",
44
+ "postal_code"=>nil,
45
+ "latitude"=>52.731700000000004,
46
+ "longitude"=>41.4433,
47
+ "time_zone"=>"Europe/Moscow"}
48
+
49
+ city = MaxmindGeoIP2.locate '77.93.127.33', 'en'
50
+ => {"city"=>"Tambov",
51
+ "city_geoname_id"=>484646,
52
+ "country"=>"Russia",
53
+ "country_geoname_id"=>2017370,
54
+ "country_code"=>"RU",
55
+ "continent"=>"Europe",
56
+ "continent_code"=>"EU",
57
+ "continent_geoname_id"=>6255148,
58
+ "subdivision"=>"Tambovskaya Oblast'",
59
+ "subdivision_code"=>"TAM",
60
+ "postal_code"=>nil,
61
+ "latitude"=>52.731700000000004,
62
+ "longitude"=>41.4433,
63
+ "time_zone"=>"Europe/Moscow"}
64
+ ```
@@ -0,0 +1,37 @@
1
+ require "rake/extensiontask"
2
+ require 'rake/testtask'
3
+ require 'bundler'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ Rake::ExtensionTask.new "maxmind_geoip2" do |ext|
7
+ ext.lib_dir = "lib/maxmind_geoip2"
8
+ end
9
+
10
+ Rake::TestTask.new do |t|
11
+ t.pattern = 'spec/**/*_spec.rb'
12
+ t.libs.push 'spec'
13
+ end
14
+
15
+ desc "Download free IP to City database"
16
+ task :download_free_database do
17
+ file = 'GeoLite2-City.mmdb'
18
+ if File.exist?(file)
19
+ puts "File already exists"
20
+ else
21
+ puts "Downloading file"
22
+ `curl http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz | gzip -d > #{file}`
23
+ end
24
+ end
25
+
26
+ desc "An IRB console with the project loaded"
27
+ task :console do
28
+ $: << 'lib'
29
+ require 'maxmind_geoip2'
30
+ MaxmindGeoIP2.file('GeoLite2-City.mmdb')
31
+ require 'irb'
32
+ require 'irb/completion'
33
+ ARGV.clear
34
+ IRB.start
35
+ end
36
+
37
+ task default: [:compile, :test]
@@ -0,0 +1,14 @@
1
+ require 'mkmf'
2
+ extension_name = 'maxmind_geoip2'
3
+
4
+ $LDFLAGS << " #{ENV['LDFLAGS']}"
5
+ $CFLAGS << " #{ENV['CFLAGS']}"
6
+
7
+ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
8
+
9
+ if have_header('maxminddb.h') and have_library('maxminddb')
10
+ create_makefile("#{extension_name}/#{extension_name}")
11
+ else
12
+ abort "you must have mmdb library"
13
+ end
14
+
@@ -0,0 +1,150 @@
1
+ #include "maxminddb.h"
2
+
3
+ #include <ruby.h>
4
+ #include <ruby/encoding.h>
5
+
6
+ #include <stdio.h>
7
+ #include <stdlib.h>
8
+ #include <string.h>
9
+ #include <errno.h>
10
+
11
+ VALUE mMaxmindGeoIP2 = Qnil;
12
+
13
+ const char **lookup_path_parse(char *lookup_path, char *lang)
14
+ {
15
+
16
+ const char **result;
17
+ if (NULL != lang)
18
+ result = malloc(sizeof(char *) * (strlen(lookup_path) + strlen(lang) + 1 ));
19
+ else
20
+ result = malloc(sizeof(char *) * (strlen(lookup_path) + 1));
21
+
22
+ char *token;
23
+ char *string = strdup(lookup_path);
24
+
25
+ token = strtok(string, " ");
26
+ int i = 0;
27
+ while (token != NULL) {
28
+ result[i++] = token;
29
+ token = strtok(NULL, " ");
30
+ }
31
+ if (NULL != lang) {
32
+ result[i++] = lang;
33
+ }
34
+ result[i] = NULL;
35
+ return result;
36
+ }
37
+
38
+ VALUE locate_by_path(MMDB_lookup_result_s *result, char *lookup_path, char *lang)
39
+ {
40
+ VALUE return_value = Qnil;
41
+
42
+ MMDB_entry_data_s entry_data;
43
+ const char **lp = lookup_path_parse(lookup_path, lang);
44
+ int status = MMDB_aget_value(&result->entry, &entry_data, lp);
45
+ if (MMDB_SUCCESS == status)
46
+ {
47
+ if (entry_data.offset)
48
+ {
49
+ if (entry_data.has_data) {
50
+ if (entry_data.type == MMDB_DATA_TYPE_UTF8_STRING)
51
+ return_value = rb_enc_str_new(strndup((char *)entry_data.utf8_string, entry_data.data_size), entry_data.data_size, rb_utf8_encoding());
52
+ if (entry_data.type == MMDB_DATA_TYPE_UINT32)
53
+ return_value = rb_int_new(entry_data.uint32);
54
+ if (entry_data.type == MMDB_DATA_TYPE_DOUBLE)
55
+ return_value = rb_float_new(entry_data.double_value);
56
+ }
57
+ }
58
+ }
59
+ free(lp);
60
+ return return_value;
61
+ }
62
+
63
+ VALUE mMaxmindGeoIP2_locate(int argc, VALUE *argv, VALUE self)
64
+ {
65
+ VALUE locate_result = Qnil;
66
+
67
+ if (argc > 3 || argc == 0) {
68
+ rb_raise(rb_eArgError, "wrong number of arguments");
69
+ }
70
+
71
+
72
+ char *lang;
73
+ if (argc == 2) {
74
+ Check_Type(argv[1], T_STRING);
75
+ lang = StringValuePtr(argv[1]);
76
+ } else {
77
+ VALUE loc = rb_iv_get(self, "@_locale");
78
+ Check_Type(loc, T_STRING);
79
+ lang = StringValuePtr(loc);
80
+ }
81
+
82
+ VALUE ipaddr = argv[0];
83
+ Check_Type(ipaddr, T_STRING);
84
+ char *ip_address = StringValuePtr(ipaddr);
85
+
86
+ char *filename;
87
+ VALUE file = rb_iv_get(self, "@_file");
88
+ Check_Type(file, T_STRING);
89
+ filename = StringValuePtr(file);
90
+
91
+
92
+ MMDB_s mmdb;
93
+ int status = MMDB_open(filename, MMDB_MODE_MMAP, &mmdb);
94
+ if (MMDB_SUCCESS == status)
95
+ {
96
+ int gai_error, mmdb_error;
97
+ MMDB_lookup_result_s result =
98
+ MMDB_lookup_string(&mmdb, ip_address, &gai_error, &mmdb_error);
99
+
100
+ if (result.found_entry)
101
+ {
102
+ locate_result = rb_hash_new();
103
+ rb_hash_aset(locate_result, rb_str_new2("city"), locate_by_path(&result, "city names", lang));
104
+ rb_hash_aset(locate_result, rb_str_new2("city_geoname_id"), locate_by_path(&result, "city geoname_id", NULL));
105
+ rb_hash_aset(locate_result, rb_str_new2("country"), locate_by_path(&result, "country names", lang));
106
+ rb_hash_aset(locate_result, rb_str_new2("country_geoname_id"), locate_by_path(&result, "country geoname_id", NULL));
107
+ rb_hash_aset(locate_result, rb_str_new2("country_code"), locate_by_path(&result, "country iso_code", NULL));
108
+ rb_hash_aset(locate_result, rb_str_new2("continent"), locate_by_path(&result, "continent names", lang));
109
+ rb_hash_aset(locate_result, rb_str_new2("continent_code"), locate_by_path(&result, "continent code", NULL));
110
+ rb_hash_aset(locate_result, rb_str_new2("continent_geoname_id"), locate_by_path(&result, "continent geoname_id", NULL));
111
+ rb_hash_aset(locate_result, rb_str_new2("subdivision"), locate_by_path(&result, "subdivisions 0 names", lang));
112
+ rb_hash_aset(locate_result, rb_str_new2("subdivision_code"), locate_by_path(&result, "subdivisions 0 iso_code", NULL));
113
+ rb_hash_aset(locate_result, rb_str_new2("subdivision_geoname_id"), locate_by_path(&result, "subdivisions 0 geoname_id", NULL));
114
+ rb_hash_aset(locate_result, rb_str_new2("postal_code"), locate_by_path(&result, "postal code", NULL));
115
+ rb_hash_aset(locate_result, rb_str_new2("latitude"), locate_by_path(&result, "location latitude", NULL));
116
+ rb_hash_aset(locate_result, rb_str_new2("longitude"), locate_by_path(&result, "location longitude", NULL));
117
+ rb_hash_aset(locate_result, rb_str_new2("time_zone"), locate_by_path(&result, "location time_zone", NULL));
118
+ }
119
+ MMDB_close(&mmdb);
120
+ } else {
121
+ rb_raise(rb_eIOError, "unable to open file %s", filename);
122
+ }
123
+ return locate_result;
124
+ }
125
+
126
+ VALUE mMaxmindGeoIP2_file(VALUE self, VALUE filepath)
127
+ {
128
+ rb_iv_set(self, "@_file", filepath);
129
+ return Qtrue;
130
+ }
131
+
132
+ VALUE mMaxmindGeoIP2_locale(VALUE self, VALUE language)
133
+ {
134
+ rb_iv_set(self, "@_locale", language);
135
+ return Qtrue;
136
+ }
137
+
138
+ void Init_maxmind_geoip2()
139
+ {
140
+ mMaxmindGeoIP2 = rb_define_module("MaxmindGeoIP2");
141
+ rb_define_module_function(mMaxmindGeoIP2, "locate", mMaxmindGeoIP2_locate, -1);
142
+ rb_define_module_function(mMaxmindGeoIP2, "file", mMaxmindGeoIP2_file, 1);
143
+ rb_define_module_function(mMaxmindGeoIP2, "locale", mMaxmindGeoIP2_locale, 1);
144
+
145
+ rb_define_attr(mMaxmindGeoIP2, "_file", 1, 1);
146
+ rb_define_attr(mMaxmindGeoIP2, "_locale", 1, 1);
147
+
148
+ rb_iv_set(mMaxmindGeoIP2, "@_file", rb_str_new2("GeoLite2-City.mmdb"));
149
+ rb_iv_set(mMaxmindGeoIP2, "@_locale", rb_str_new2("ru"));
150
+ }
@@ -0,0 +1 @@
1
+ require 'maxmind_geoip2/maxmind_geoip2'
@@ -0,0 +1,20 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = 'maxmind_geoip2'
3
+ s.version = "0.0.8"
4
+
5
+ s.licenses = ['WTFPL']
6
+
7
+ s.authors = ['Maksim Stepanov']
8
+ s.email = ['stepanov.ms@mail.ru']
9
+
10
+ s.summary = "A Binding to the GeoIP2 C library"
11
+ s.description = 'Generic GeoIP2 lookup tool.'
12
+ s.homepage = "http://github.com"
13
+
14
+ s.files = `git ls-files`.split("\n")
15
+ s.extensions = ['ext/maxmind_geoip2/extconf.rb']
16
+ s.require_paths = ["lib"]
17
+
18
+ s.add_development_dependency 'rake', '~>10.0'
19
+ s.add_development_dependency 'rake-compiler'
20
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ describe MaxmindGeoIP2 do
4
+ describe '.locate' do
5
+ let(:result) { MaxmindGeoIP2.locate('74.125.237.168') }
6
+
7
+ it 'sets string encodings to utf8' do
8
+ result['country'].encoding.must_equal(Encoding::UTF_8)
9
+ end
10
+
11
+ it 'has a continent' do
12
+ result['continent'].must_be_instance_of(String)
13
+ end
14
+
15
+ it 'has a continent_code' do
16
+ result['continent_code'].must_be_instance_of(String)
17
+ end
18
+
19
+ it 'has a continent_geoname_id' do
20
+ result['continent_geoname_id'].must_be_instance_of(Fixnum)
21
+ end
22
+
23
+ it 'has the correct continent_geoname_id' do
24
+ result['continent_geoname_id'].must_equal(6255149)
25
+ end
26
+
27
+ it 'has a country' do
28
+ result['country'].must_be_instance_of(String)
29
+ end
30
+
31
+ it 'has a country_code' do
32
+ result['country_code'].must_be_instance_of(String)
33
+ end
34
+
35
+ it 'has a country_geoname_id' do
36
+ result['country_geoname_id'].must_be_instance_of(Fixnum)
37
+ end
38
+
39
+ it 'has a city' do
40
+ result['city'].must_be_instance_of(String)
41
+ end
42
+
43
+ it 'has a city_geoname_id' do
44
+ result['city_geoname_id'].must_be_instance_of(Fixnum)
45
+ end
46
+
47
+ it 'has a subdivision' do
48
+ result['subdivision'].must_be_instance_of(String)
49
+ end
50
+
51
+ it 'has a subdivision_code' do
52
+ result['subdivision_code'].must_be_instance_of(String)
53
+ end
54
+
55
+ it 'has a subdivision_geoname_id' do
56
+ result['subdivision_geoname_id'].must_be_instance_of(Fixnum)
57
+ end
58
+
59
+ it 'has a postal_code' do
60
+ result['postal_code'].must_be_instance_of(String)
61
+ end
62
+
63
+ it 'has a latitude' do
64
+ result['latitude'].must_be_instance_of(Float)
65
+ end
66
+
67
+ it 'has a longitude' do
68
+ result['longitude'].must_be_instance_of(Float)
69
+ end
70
+
71
+ it 'has a time_zone' do
72
+ result['time_zone'].must_be_instance_of(String)
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,10 @@
1
+ require 'bundler/setup'
2
+ require 'minitest/autorun'
3
+
4
+ require 'maxmind_geoip2'
5
+
6
+ unless File.exist?('GeoLite2-City.mmdb')
7
+ raise "GeoLite2-City.mmdb doesn't exist. Run rake download_free_database to get it"
8
+ end
9
+
10
+ MaxmindGeoIP2.file('GeoLite2-City.mmdb')
metadata ADDED
@@ -0,0 +1,83 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: maxmind_geoip2
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.8
5
+ platform: ruby
6
+ authors:
7
+ - Maksim Stepanov
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '10.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '10.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake-compiler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Generic GeoIP2 lookup tool.
42
+ email:
43
+ - stepanov.ms@mail.ru
44
+ executables: []
45
+ extensions:
46
+ - ext/maxmind_geoip2/extconf.rb
47
+ extra_rdoc_files: []
48
+ files:
49
+ - ".gitignore"
50
+ - Gemfile
51
+ - README.md
52
+ - Rakefile
53
+ - ext/maxmind_geoip2/extconf.rb
54
+ - ext/maxmind_geoip2/maxmind_geoip2.c
55
+ - lib/maxmind_geoip2.rb
56
+ - maxmind_geoip2.gemspec
57
+ - spec/maxmind_geoip2_spec.rb
58
+ - spec/spec_helper.rb
59
+ homepage: http://github.com
60
+ licenses:
61
+ - WTFPL
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubyforge_project:
79
+ rubygems_version: 2.4.3
80
+ signing_key:
81
+ specification_version: 4
82
+ summary: A Binding to the GeoIP2 C library
83
+ test_files: []