maxmind_geoip2 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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: []