geoip2_c 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a385241251a43ddd2d075ae6edf6079eee160022
4
+ data.tar.gz: ba99231f74e179e16f3274eda636860123e2923b
5
+ SHA512:
6
+ metadata.gz: 460dc2adc04bb35833fe48b27688a8d1709ad39526e067bc13ce41d64bb85ee10326c6ff5f493668fad85d135ff213aad862f292e9754db518770e023b2e8756
7
+ data.tar.gz: 81b9fb3f1b408568894747fe0695d5892250a94dfdc373c663c6fdcd3d6d9def2fc3eacdeffbfdff77fb303b8fff75cb12ae742284eadba62400cf3b0f5a445d
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.gitmodules ADDED
@@ -0,0 +1,3 @@
1
+ [submodule "test/MaxMind-DB"]
2
+ path = test/MaxMind-DB
3
+ url = https://github.com/maxmind/MaxMind-DB.git
data/.travis.yml ADDED
@@ -0,0 +1,25 @@
1
+ sudo: required
2
+ services:
3
+ - docker
4
+
5
+ env:
6
+ DOCKER_COMPOSE_VERSION: 1.8.1
7
+
8
+ before_install:
9
+ #- sudo apt-get update
10
+ #- sudo apt-get install -y docker-engine
11
+ - sudo rm /usr/local/bin/docker-compose
12
+ - curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-$(uname -s)-$(uname -m) > docker-compose
13
+ - chmod +x docker-compose
14
+ - sudo mv docker-compose /usr/local/bin/
15
+
16
+ before_script:
17
+ - docker-compose build
18
+ - docker-compose ps
19
+ - docker-compose up -d
20
+ - docker-compose exec test bundle install
21
+ - docker-compose exec test bundle exec rake compile
22
+
23
+ script:
24
+ - docker-compose exec test bundle exec rake test
25
+
data/Dockerfile ADDED
@@ -0,0 +1,6 @@
1
+ FROM ruby:2.3.3-alpine
2
+
3
+ RUN apk --no-cache --update add build-base ruby-dev libc6-compat libmaxminddb-dev git
4
+
5
+ WORKDIR /app
6
+ COPY . .
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in geoip2_c.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 okkez
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,57 @@
1
+ # GeoIP2
2
+
3
+ This gem provides binding [libmaxminddb](http://maxmind.github.io/libmaxminddb/).
4
+
5
+ This binding does not traverse all elements in lookup result by default.
6
+ So you can get the element you want fast such as city name, country name or etc.
7
+
8
+ ## Requirements
9
+
10
+ * Ruby 2.3 or later
11
+
12
+ NOTE:
13
+
14
+ This library uses `Hash#dig` and `Array#dig`.
15
+ If you want to use this library with Ruby2.1 or Ruby2.2, you can install a gem which adds support `#dig` method.
16
+ But I don't want to add extra dependency to this library, so I decided not to add extra dependency to support old Ruby versions.
17
+
18
+ ## Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ ```ruby
23
+ gem 'geoip2_c'
24
+ ```
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install geoip2_c
33
+
34
+ ## Usage
35
+
36
+ ```ruby
37
+ require "geoip2"
38
+
39
+ db = GeoIP2::Databaes.new("/path/to/GeoLite2-City.mmdb")
40
+ result = db.lookup("66.102.9.80")
41
+ retuls.get_value("city", "names", "en") # => "Mountain View"
42
+ ```
43
+
44
+ ## Development
45
+
46
+ After checking out the repo, run `bundle install` to install dependencies. Then, run `rake test` to run the tests.
47
+
48
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
49
+
50
+ ## Contributing
51
+
52
+ Bug reports and pull requests are welcome on GitHub at https://github.com/okkez/geoip2_c.
53
+
54
+ ## License
55
+
56
+ The gem is available as open source under the terms of the [Apache-2.0](http://opensource.org/licenses/Apache-2.0).
57
+
data/Rakefile ADDED
@@ -0,0 +1,18 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ require "rake/extensiontask"
11
+
12
+ task :build => :compile
13
+
14
+ Rake::ExtensionTask.new("geoip2") do |ext|
15
+ ext.lib_dir = "lib/geoip2"
16
+ end
17
+
18
+ task :default => [:clobber, :compile, :test]
@@ -0,0 +1,6 @@
1
+ version: "2"
2
+ services:
3
+ test:
4
+ build:
5
+ context: .
6
+ command: ruby -run -e httpd
@@ -0,0 +1,10 @@
1
+ require "mkmf"
2
+
3
+ dir_config("maxminddb")
4
+ have_header("maxminddb.h")
5
+ have_library("maxminddb")
6
+
7
+ $CFLAGS << " -std=c99"
8
+ # $CFLAGS << " -g -O0"
9
+
10
+ create_makefile("geoip2/geoip2")
@@ -0,0 +1,421 @@
1
+ #include <ruby.h>
2
+ #include <ruby/encoding.h>
3
+ #include <maxminddb.h>
4
+
5
+ VALUE rb_mGeoIP2;
6
+ VALUE rb_cGeoIP2Database;
7
+ VALUE rb_cGeoIP2LookupResult;
8
+ VALUE rb_eGeoIP2Error;
9
+
10
+ static void mmdb_open(const char *db_path, MMDB_s *mmdb);
11
+ static void mmdb_close(MMDB_s *mmdb);
12
+ static bool mmdb_is_closed(MMDB_s *mmdb);
13
+ static void mmdb_free(void *mmdb);
14
+ static MMDB_lookup_result_s mmdb_lookup(MMDB_s *mmdb, const char *ip_str, bool cleanup);
15
+ static VALUE mmdb_entry_data_decode(MMDB_entry_data_s *entry_data);
16
+ static VALUE mmdb_guard_parse_entry_data_list(VALUE ptr);
17
+ static MMDB_entry_data_list_s *mmdb_parse_entry_data_list(MMDB_entry_data_list_s *data_list, VALUE *obj);
18
+
19
+ static VALUE rb_geoip2_db_alloc(VALUE klass);
20
+ static VALUE rb_geoip2_db_initialize(VALUE self, VALUE path);
21
+ static VALUE rb_geoip2_db_close(VALUE self);
22
+ static VALUE rb_geoip2_db_lookup(VALUE self, VALUE ip);
23
+
24
+ static VALUE rb_geoip2_lr_alloc(VALUE klass);
25
+ static VALUE rb_geoip2_lr_initialize(VALUE self);
26
+ static VALUE rb_geoip2_lr_get_value(int argc, VALUE *argv, VALUE self);
27
+ static VALUE rb_geoip2_lr_to_h(VALUE self);
28
+
29
+ // static void lookup_result_free(void *pointer);
30
+ // static size_t lookup_result_size(void *pointer);
31
+
32
+ static const rb_data_type_t rb_mmdb_type = {
33
+ "geoip2/mmdb", {
34
+ 0, mmdb_free, 0,
35
+ }, NULL, NULL
36
+ };
37
+
38
+ static const rb_data_type_t rb_lookup_result_type = {
39
+ "geoip2/lookup_result", {
40
+ 0, 0, 0,
41
+ }, NULL, NULL
42
+ };
43
+
44
+ static void
45
+ mmdb_open(const char *db_path, MMDB_s *mmdb)
46
+ {
47
+ int status = MMDB_open(db_path, MMDB_MODE_MMAP, mmdb);
48
+
49
+ if (status != MMDB_SUCCESS) {
50
+ rb_raise(rb_eGeoIP2Error, "%s: %s", MMDB_strerror(status), db_path);
51
+ }
52
+ }
53
+
54
+ static void
55
+ mmdb_close(MMDB_s *mmdb)
56
+ {
57
+ MMDB_close(mmdb);
58
+ mmdb->file_content = NULL;
59
+ }
60
+
61
+ static bool
62
+ mmdb_is_closed(MMDB_s *mmdb)
63
+ {
64
+ return mmdb->file_content == NULL;
65
+ }
66
+
67
+ static void
68
+ mmdb_free(void *ptr)
69
+ {
70
+ MMDB_s *mmdb = (MMDB_s *)ptr;
71
+ if (!mmdb_is_closed(mmdb)) {
72
+ mmdb_close(mmdb);
73
+ }
74
+
75
+ xfree(mmdb);
76
+ }
77
+
78
+ static MMDB_lookup_result_s
79
+ mmdb_lookup(MMDB_s *mmdb, const char *ip_str, bool cleanup)
80
+ {
81
+ int gai_error;
82
+ int mmdb_error;
83
+
84
+ MMDB_lookup_result_s result =
85
+ MMDB_lookup_string(mmdb, ip_str, &gai_error, &mmdb_error);
86
+
87
+ if (gai_error != 0) {
88
+ if (cleanup && !mmdb_is_closed(mmdb)) {
89
+ mmdb_close(mmdb);
90
+ }
91
+ rb_raise(rb_eGeoIP2Error,
92
+ "getaddrinfo failed: %s", gai_strerror(gai_error));
93
+ }
94
+
95
+ if (mmdb_error != MMDB_SUCCESS) {
96
+ if (cleanup && !mmdb_is_closed(mmdb)) {
97
+ mmdb_close(mmdb);
98
+ }
99
+ rb_raise(rb_eGeoIP2Error,
100
+ "lookup failed: %s", MMDB_strerror(mmdb_error));
101
+ }
102
+
103
+ return result;
104
+ }
105
+
106
+ static VALUE
107
+ mmdb_entry_data_decode(MMDB_entry_data_s *entry_data)
108
+ {
109
+ switch (entry_data->type) {
110
+ case MMDB_DATA_TYPE_EXTENDED:
111
+ /* TODO: not implemented */
112
+ return Qnil;
113
+ case MMDB_DATA_TYPE_POINTER:
114
+ /* TODO: not implemented */
115
+ return Qnil;
116
+ case MMDB_DATA_TYPE_UTF8_STRING:
117
+ return rb_enc_str_new(entry_data->utf8_string,
118
+ entry_data->data_size,
119
+ rb_utf8_encoding());
120
+ case MMDB_DATA_TYPE_DOUBLE:
121
+ return DBL2NUM(entry_data->double_value);
122
+ case MMDB_DATA_TYPE_BYTES:
123
+ return rb_enc_str_new((const char *)entry_data->bytes,
124
+ entry_data->data_size,
125
+ rb_ascii8bit_encoding());
126
+ case MMDB_DATA_TYPE_UINT16:
127
+ return UINT2NUM(entry_data->uint16);
128
+ case MMDB_DATA_TYPE_UINT32:
129
+ return UINT2NUM(entry_data->uint32);
130
+ case MMDB_DATA_TYPE_MAP:
131
+ /* TODO: not implemented */
132
+ return Qnil;
133
+ case MMDB_DATA_TYPE_INT32:
134
+ return INT2NUM(entry_data->int32);
135
+ case MMDB_DATA_TYPE_UINT64:
136
+ return UINT2NUM(entry_data->uint64);
137
+ case MMDB_DATA_TYPE_UINT128:
138
+ /* FIXME I'm not sure */
139
+ return UINT2NUM(entry_data->uint128);
140
+ case MMDB_DATA_TYPE_ARRAY:
141
+ /* TODO: not implemented */
142
+ return Qnil;
143
+ case MMDB_DATA_TYPE_CONTAINER:
144
+ /* TODO: not implemented */
145
+ return Qnil;
146
+ case MMDB_DATA_TYPE_END_MARKER:
147
+ return Qnil;
148
+ case MMDB_DATA_TYPE_BOOLEAN:
149
+ return entry_data->boolean ? Qtrue : Qfalse;
150
+ case MMDB_DATA_TYPE_FLOAT:
151
+ return rb_float_new(entry_data->float_value);
152
+ default:
153
+ rb_raise(rb_eGeoIP2Error, "Unkown type: %d", entry_data->type);
154
+ }
155
+ }
156
+
157
+ static VALUE
158
+ mmdb_guard_parse_entry_data_list(VALUE ptr)
159
+ {
160
+ MMDB_entry_data_list_s *data_list =
161
+ (struct MMDB_entry_data_list_s *)ptr;
162
+ VALUE obj;
163
+
164
+ mmdb_parse_entry_data_list(data_list, &obj);
165
+ return obj;
166
+ }
167
+
168
+ static MMDB_entry_data_list_s *
169
+ mmdb_parse_entry_data_list(MMDB_entry_data_list_s *data_list, VALUE *obj)
170
+ {
171
+ switch (data_list->entry_data.type) {
172
+ case MMDB_DATA_TYPE_MAP:
173
+ {
174
+ uint32_t data_size = data_list->entry_data.data_size;
175
+ VALUE hash = rb_hash_new();
176
+ for (data_list = data_list->next; data_size && data_list; data_size--) {
177
+ VALUE key;
178
+ VALUE val;
179
+ key = mmdb_entry_data_decode(&data_list->entry_data);
180
+ data_list = data_list->next;
181
+ data_list = mmdb_parse_entry_data_list(data_list, &val);
182
+ rb_hash_aset(hash, key, val);
183
+ }
184
+ *obj = hash;
185
+ break;
186
+ }
187
+ case MMDB_DATA_TYPE_ARRAY:
188
+ {
189
+ uint32_t data_size = data_list->entry_data.data_size;
190
+ VALUE array = rb_ary_new();
191
+ for (data_list = data_list->next; data_size && data_list; data_size--) {
192
+ VALUE val;
193
+ data_list = mmdb_parse_entry_data_list(data_list, &val);
194
+ rb_ary_push(array, val);
195
+ }
196
+ *obj = array;
197
+ break;
198
+ }
199
+ case MMDB_DATA_TYPE_UTF8_STRING: /* fall through */
200
+ case MMDB_DATA_TYPE_BYTES:
201
+ case MMDB_DATA_TYPE_DOUBLE:
202
+ case MMDB_DATA_TYPE_UINT16:
203
+ case MMDB_DATA_TYPE_UINT32:
204
+ case MMDB_DATA_TYPE_INT32:
205
+ case MMDB_DATA_TYPE_UINT64:
206
+ case MMDB_DATA_TYPE_UINT128:
207
+ case MMDB_DATA_TYPE_BOOLEAN:
208
+ case MMDB_DATA_TYPE_FLOAT:
209
+ {
210
+ VALUE val = mmdb_entry_data_decode(&data_list->entry_data);
211
+ data_list = data_list->next;
212
+ *obj = val;
213
+ break;
214
+ }
215
+ default:
216
+ rb_raise(rb_eGeoIP2Error,
217
+ "Unkown type: %d",
218
+ data_list->entry_data.type);
219
+ }
220
+ return data_list;
221
+ }
222
+
223
+ static VALUE
224
+ rb_geoip2_db_alloc(VALUE klass)
225
+ {
226
+ VALUE obj;
227
+ MMDB_s *mmdb;
228
+ obj = TypedData_Make_Struct(klass, struct MMDB_s, &rb_mmdb_type, mmdb);
229
+ return obj;
230
+ }
231
+
232
+ static VALUE
233
+ rb_geoip2_db_initialize(VALUE self, VALUE path)
234
+ {
235
+ char *db_path;
236
+ MMDB_s *mmdb;
237
+
238
+ Check_Type(path, T_STRING);
239
+
240
+ db_path = StringValueCStr(path);
241
+
242
+ TypedData_Get_Struct(self, struct MMDB_s, &rb_mmdb_type, mmdb);
243
+ mmdb_open(db_path, mmdb);
244
+
245
+ return Qnil;
246
+ }
247
+
248
+ static VALUE
249
+ rb_geoip2_db_close(VALUE self)
250
+ {
251
+ MMDB_s *mmdb;
252
+
253
+ TypedData_Get_Struct(self, struct MMDB_s, &rb_mmdb_type, mmdb);
254
+
255
+ if (!mmdb_is_closed(mmdb)) {
256
+ mmdb_close(mmdb);
257
+ }
258
+
259
+ return Qnil;
260
+ }
261
+
262
+ static VALUE
263
+ rb_geoip2_db_lookup(VALUE self, VALUE ip)
264
+ {
265
+ char *ip_str;
266
+ MMDB_s *mmdb;
267
+ MMDB_lookup_result_s result;
268
+ MMDB_lookup_result_s *result_ptr;
269
+ VALUE obj;
270
+
271
+ Check_Type(ip, T_STRING);
272
+ ip_str = StringValueCStr(ip);
273
+
274
+ TypedData_Get_Struct(self, struct MMDB_s, &rb_mmdb_type, mmdb);
275
+ result = mmdb_lookup(mmdb, ip_str, false);
276
+
277
+ if (!result.found_entry) {
278
+ return Qnil;
279
+ }
280
+
281
+ obj = TypedData_Make_Struct(rb_cGeoIP2LookupResult,
282
+ struct MMDB_lookup_result_s,
283
+ &rb_lookup_result_type,
284
+ result_ptr);
285
+ result_ptr->found_entry = result.found_entry;
286
+ result_ptr->entry = result.entry;
287
+ result_ptr->netmask = result.netmask;
288
+ return obj;
289
+ }
290
+
291
+ static VALUE
292
+ rb_geoip2_lr_alloc(VALUE klass)
293
+ {
294
+ VALUE obj;
295
+ MMDB_lookup_result_s *result;
296
+ obj = TypedData_Make_Struct(klass,
297
+ struct MMDB_lookup_result_s,
298
+ &rb_lookup_result_type,
299
+ result);
300
+ return obj;
301
+ }
302
+
303
+ static VALUE
304
+ rb_geoip2_lr_initialize(VALUE self)
305
+ {
306
+ return Qnil;
307
+ }
308
+
309
+ static VALUE
310
+ rb_geoip2_lr_get_value(int argc, VALUE *argv, VALUE self)
311
+ {
312
+ VALUE arg;
313
+ VALUE rest;
314
+ char **path;
315
+ int i = 0;
316
+ MMDB_lookup_result_s *result = NULL;
317
+ MMDB_entry_s entry;
318
+ MMDB_entry_data_s entry_data;
319
+ char *tmp;
320
+ VALUE e;
321
+ int status;
322
+
323
+ rb_scan_args(argc, argv, "1*", &arg, &rest);
324
+ Check_Type(arg, T_STRING);
325
+ path = malloc(sizeof(char *) * (RARRAY_LEN(rest) + 2));
326
+
327
+ TypedData_Get_Struct(self,
328
+ struct MMDB_lookup_result_s,
329
+ &rb_lookup_result_type,
330
+ result);
331
+
332
+ path[i] = StringValueCStr(arg);
333
+ while (RARRAY_LEN(rest) != 0) {
334
+ ++i;
335
+ e = rb_ary_shift(rest);
336
+ tmp = StringValueCStr(e);
337
+ path[i] = tmp;
338
+ }
339
+
340
+ path[i+1] = NULL;
341
+
342
+ entry = result->entry;
343
+
344
+ status = MMDB_aget_value(&entry, &entry_data, (const char *const *const)path);
345
+
346
+ if (status != MMDB_SUCCESS) {
347
+ free(path);
348
+ fprintf(stderr, "%s\n", MMDB_strerror(status));
349
+ return Qnil;
350
+ }
351
+
352
+ if (!entry_data.has_data) {
353
+ free(path);
354
+ return Qnil;
355
+ }
356
+
357
+ if (entry_data.type == MMDB_DATA_TYPE_MAP ||
358
+ entry_data.type == MMDB_DATA_TYPE_ARRAY) {
359
+ // FIXME optimize below code
360
+ VALUE array = rb_ary_new();
361
+ VALUE hash;
362
+ VALUE val;
363
+ for (int j = 0; path[j] != NULL; j++) {
364
+ rb_ary_push(array, rb_str_new_cstr(path[j]));
365
+ }
366
+ hash = rb_funcall(self, rb_intern("to_h"), 0);
367
+ val = rb_apply(hash, rb_intern("dig"), array);
368
+ free(path);
369
+ return val;
370
+ }
371
+
372
+ free(path);
373
+ return mmdb_entry_data_decode(&entry_data);
374
+ }
375
+
376
+ static VALUE
377
+ rb_geoip2_lr_to_h(VALUE self)
378
+ {
379
+ MMDB_lookup_result_s *result = NULL;
380
+ MMDB_entry_data_list_s *entry_data_list = NULL;
381
+ VALUE hash;
382
+ int status = 0;
383
+ int exception = 0;
384
+
385
+ TypedData_Get_Struct(self,
386
+ struct MMDB_lookup_result_s,
387
+ &rb_lookup_result_type,
388
+ result);
389
+ status = MMDB_get_entry_data_list(&result->entry, &entry_data_list);
390
+ if (status != MMDB_SUCCESS) {
391
+ rb_raise(rb_eGeoIP2Error, "%s", MMDB_strerror(status));
392
+ }
393
+
394
+ hash = rb_protect(mmdb_guard_parse_entry_data_list, (VALUE)entry_data_list, &exception);
395
+ MMDB_free_entry_data_list(entry_data_list);
396
+
397
+ if (exception != 0) {
398
+ rb_jump_tag(exception);
399
+ }
400
+
401
+ return hash;
402
+ }
403
+
404
+ void
405
+ Init_geoip2(void)
406
+ {
407
+ rb_mGeoIP2 = rb_define_module("GeoIP2");
408
+ rb_cGeoIP2Database = rb_define_class_under(rb_mGeoIP2, "Database", rb_cData);
409
+ rb_cGeoIP2LookupResult = rb_define_class_under(rb_mGeoIP2, "LookupResult", rb_cData);
410
+ rb_eGeoIP2Error = rb_define_class_under(rb_mGeoIP2, "Error", rb_eStandardError);
411
+
412
+ rb_define_alloc_func(rb_cGeoIP2Database, rb_geoip2_db_alloc);
413
+ rb_define_method(rb_cGeoIP2Database, "initialize", rb_geoip2_db_initialize, 1);
414
+ rb_define_method(rb_cGeoIP2Database, "close", rb_geoip2_db_close, 0);
415
+ rb_define_method(rb_cGeoIP2Database, "lookup", rb_geoip2_db_lookup, 1);
416
+
417
+ rb_define_alloc_func(rb_cGeoIP2LookupResult, rb_geoip2_lr_alloc);
418
+ rb_define_method(rb_cGeoIP2LookupResult, "initialize", rb_geoip2_lr_initialize, 0);
419
+ rb_define_method(rb_cGeoIP2LookupResult, "get_value", rb_geoip2_lr_get_value, -1);
420
+ rb_define_method(rb_cGeoIP2LookupResult, "to_h", rb_geoip2_lr_to_h, 0);
421
+ }
data/geoip2_c.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'geoip2/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "geoip2_c"
8
+ spec.version = GeoIP2::VERSION
9
+ spec.authors = ["okkez"]
10
+ spec.email = ["okkez000@gmail.com"]
11
+
12
+ spec.summary = %q{Write a short summary, because Rubygems requires one.}
13
+ spec.description = %q{Write a longer description or delete this line.}
14
+ spec.homepage = ""
15
+ spec.license = "Apache-2.0"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "bin"
21
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+ spec.extensions = ["ext/geoip2/extconf.rb"]
24
+
25
+ spec.add_development_dependency "bundler", "~> 1.13"
26
+ spec.add_development_dependency "rake", "~> 11.0"
27
+ spec.add_development_dependency "rake-compiler"
28
+ spec.add_development_dependency "test-unit", "~> 3.2"
29
+ end
@@ -0,0 +1,4 @@
1
+ module GeoIP2
2
+ class Database
3
+ end
4
+ end
@@ -0,0 +1,7 @@
1
+ module GeoIP2
2
+ class LookupResult
3
+ def dig(*keys)
4
+ get_value(*keys)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,3 @@
1
+ module GeoIP2
2
+ VERSION = "0.1.0"
3
+ end
data/lib/geoip2.rb ADDED
@@ -0,0 +1,7 @@
1
+ require "geoip2/version"
2
+ require "geoip2/geoip2"
3
+ require "geoip2/database"
4
+ require "geoip2/lookup_result"
5
+
6
+ module GeoIP2
7
+ end
metadata ADDED
@@ -0,0 +1,117 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geoip2_c
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - okkez
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-12-20 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.13'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '11.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '11.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake-compiler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: test-unit
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.2'
69
+ description: Write a longer description or delete this line.
70
+ email:
71
+ - okkez000@gmail.com
72
+ executables: []
73
+ extensions:
74
+ - ext/geoip2/extconf.rb
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - ".gitmodules"
79
+ - ".travis.yml"
80
+ - Dockerfile
81
+ - Gemfile
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - docker-compose.yml
86
+ - ext/geoip2/extconf.rb
87
+ - ext/geoip2/geoip2.c
88
+ - geoip2_c.gemspec
89
+ - lib/geoip2.rb
90
+ - lib/geoip2/database.rb
91
+ - lib/geoip2/lookup_result.rb
92
+ - lib/geoip2/version.rb
93
+ homepage: ''
94
+ licenses:
95
+ - Apache-2.0
96
+ metadata: {}
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ version: '0'
106
+ required_rubygems_version: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ requirements: []
112
+ rubyforge_project:
113
+ rubygems_version: 2.6.4
114
+ signing_key:
115
+ specification_version: 4
116
+ summary: Write a short summary, because Rubygems requires one.
117
+ test_files: []