geoip2_compat 0.0.3

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: 9f9ed49b988f87ea47456f82c323a7e0520dc910
4
+ data.tar.gz: 663287416d22813c84be2cd401ac5a31f607c450
5
+ SHA512:
6
+ metadata.gz: 08b74a2d6381a209c2a9968e55a9b68af4b275689d43d329d6777a4fac2353879f096a8e757b925cd9dd7a3ba9bae4ae24df244be96fbe7257614828d758301f
7
+ data.tar.gz: fddf485a7961547ac96ef674b072e86c1b53d97d0256a53525cb2b79570b427879688b9cf96d7b0b1e919c5a45f62389048003d1ea2636b8fce5735a283a109b
@@ -0,0 +1,5 @@
1
+ *.bundle
2
+ *.so
3
+ test/*.mmdb
4
+ tmp/
5
+ *.gem
@@ -0,0 +1,9 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2
4
+ - 2.1
5
+ - 2.0.0
6
+ - 1.9.3
7
+ - rbx-2
8
+ sudo: false
9
+ cache: bundler
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "https://rubygems.org"
2
+
3
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Dirkjan Bussink
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 all
13
+ 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 THE
21
+ SOFTWARE.
@@ -0,0 +1,19 @@
1
+ # Ruby GeoIP2 compatibility bindings
2
+
3
+ Implements the new Maxmind database format while keeping the output
4
+ complatible with https://github.com/mtodd/geoip
5
+
6
+ ## Dependencies
7
+
8
+ This depends on [libmaxminddb](https://github.com/maxmind/libmaxminddb)
9
+
10
+ ## Installation
11
+
12
+ `gem install geoip2_compat`
13
+
14
+ ## Usage
15
+
16
+ ```
17
+ geoip = GeoIP2Compat.new(dbfile)
18
+ geoip.lookup("24.24.24.24")
19
+ ```
@@ -0,0 +1,34 @@
1
+ require "rake/extensiontask"
2
+ require 'rake/testtask'
3
+
4
+ Rake::ExtensionTask.new "geoip2_compat" do |ext|
5
+ ext.lib_dir = "lib/geoip2_compat"
6
+ end
7
+
8
+ Rake::TestTask.new do |t|
9
+ t.libs << "test"
10
+ t.test_files = FileList['test/test*.rb']
11
+ t.verbose = true
12
+ end
13
+
14
+ task :download do
15
+ file = "test/GeoLite2-City.mmdb"
16
+ unless File.exist?(file)
17
+ `curl http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.mmdb.gz | gzip -d > #{file}`
18
+ end
19
+ end
20
+
21
+ task :vendor do
22
+ version = "1.0.3"
23
+ mkdir_p "tmp/"
24
+ dir = "tmp/libmaxminddb-#{version}"
25
+ cd "tmp/" do
26
+ sh "curl -L https://github.com/maxmind/libmaxminddb/releases/download/#{version}/libmaxminddb-#{version}.tar.gz | tar xz"
27
+ end
28
+ cp "#{dir}/src/maxminddb-compat-util.h", "ext/geoip2_compat/maxminddb-compat-util.h"
29
+ cp "#{dir}/src/maxminddb.c", "ext/geoip2_compat/maxminddb.c"
30
+ cp "#{dir}/include/maxminddb.h", "ext/geoip2_compat/maxminddb.h"
31
+ cp "#{dir}/include/maxminddb_config.h.in", "ext/geoip2_compat/maxminddb_config.h"
32
+ end
33
+
34
+ task default: [:compile, :download, :test]
@@ -0,0 +1,11 @@
1
+ require "mkmf"
2
+ extension_name = "geoip2_compat"
3
+
4
+ $LDFLAGS << " #{ENV['LDFLAGS']}"
5
+ $CFLAGS << " -std=c99 #{ENV['CFLAGS']}"
6
+
7
+ RbConfig::MAKEFILE_CONFIG['CC'] = ENV['CC'] if ENV['CC']
8
+
9
+ $defs << ' -DPACKAGE_VERSION=\"1.0.3\"'
10
+
11
+ create_makefile("#{extension_name}/#{extension_name}")
@@ -0,0 +1,186 @@
1
+ #include <ruby.h>
2
+ #include <ruby/encoding.h>
3
+
4
+ #include <stdio.h>
5
+ #include <stdlib.h>
6
+ #include <string.h>
7
+ #include <errno.h>
8
+ #include <stdarg.h>
9
+
10
+ #include <maxminddb.h>
11
+
12
+ VALUE cgeoip2_compat;
13
+ VALUE egeoip2_compat_Exception;
14
+
15
+ ID geoip2_compat_COUNTRY_CODE;
16
+ ID geoip2_compat_COUNTRY_NAME;
17
+ ID geoip2_compat_REGION;
18
+ ID geoip2_compat_REGION_NAME;
19
+ ID geoip2_compat_CITY;
20
+ ID geoip2_compat_POSTAL_CODE;
21
+ ID geoip2_compat_LATITUDE;
22
+ ID geoip2_compat_LONGITUDE;
23
+
24
+ static void geoip2_compat_internal_close(MMDB_s* mmdb)
25
+ {
26
+ if(mmdb->file_content) {
27
+ MMDB_close(mmdb);
28
+ }
29
+ mmdb->file_content = NULL;
30
+ }
31
+
32
+ static VALUE geoip2_compat_close(VALUE self)
33
+ {
34
+ MMDB_s *mmdb;
35
+ Data_Get_Struct(self, MMDB_s, mmdb);
36
+ geoip2_compat_internal_close(mmdb);
37
+ return self;
38
+ }
39
+
40
+ static VALUE geoip2_compat_path(VALUE self)
41
+ {
42
+ MMDB_s *mmdb;
43
+ Data_Get_Struct(self, MMDB_s, mmdb);
44
+
45
+ return rb_str_new2(mmdb->filename);
46
+ }
47
+
48
+ static void geoip2_compat_lookup_internal(MMDB_lookup_result_s* result, VALUE hash, ID name, ...)
49
+ {
50
+ MMDB_entry_data_s entry_data;
51
+
52
+ va_list path;
53
+ va_start(path, name);
54
+ int status = MMDB_vget_value(&result->entry, &entry_data, path);
55
+ va_end(path);
56
+
57
+ if (MMDB_SUCCESS != status) return;
58
+
59
+ if (entry_data.has_data) {
60
+ VALUE val = Qnil;
61
+ switch (entry_data.type) {
62
+ case MMDB_DATA_TYPE_UTF8_STRING:
63
+ val = rb_enc_str_new(entry_data.utf8_string, entry_data.data_size, rb_utf8_encoding());
64
+ break;
65
+ case MMDB_DATA_TYPE_BYTES:
66
+ val = rb_str_new((const char*)entry_data.bytes, entry_data.data_size);
67
+ break;
68
+ case MMDB_DATA_TYPE_DOUBLE:
69
+ val = rb_float_new(entry_data.double_value);
70
+ break;
71
+ case MMDB_DATA_TYPE_UINT16:
72
+ val = UINT2NUM(entry_data.uint16);
73
+ break;
74
+ case MMDB_DATA_TYPE_UINT32:
75
+ val = UINT2NUM(entry_data.uint32);
76
+ break;
77
+ case MMDB_DATA_TYPE_INT32:
78
+ val = INT2NUM(entry_data.int32);
79
+ break;
80
+ case MMDB_DATA_TYPE_UINT64:
81
+ val = UINT2NUM(entry_data.uint64);
82
+ break;
83
+ case MMDB_DATA_TYPE_BOOLEAN:
84
+ val = entry_data.boolean ? Qtrue : Qfalse;
85
+ break;
86
+ case MMDB_DATA_TYPE_FLOAT:
87
+ val = rb_float_new(entry_data.float_value);
88
+ break;
89
+ }
90
+ rb_hash_aset(hash, ID2SYM(name), val);
91
+ }
92
+ }
93
+
94
+ static VALUE geoip2_compat_lookup(VALUE self, VALUE ip)
95
+ {
96
+ int status, gai_error, mmdb_error;
97
+ Check_Type(ip, T_STRING);
98
+
99
+ char* ip_addr = StringValuePtr(ip);
100
+ MMDB_s *mmdb;
101
+ Data_Get_Struct(self, MMDB_s, mmdb);
102
+
103
+ MMDB_lookup_result_s result =
104
+ MMDB_lookup_string(mmdb, ip_addr, &gai_error, &mmdb_error);
105
+
106
+ if (mmdb_error != MMDB_SUCCESS) {
107
+ rb_raise(egeoip2_compat_Exception,
108
+ "geoip2_compat - lookup failed: %s", MMDB_strerror(mmdb_error)
109
+ );
110
+ }
111
+
112
+ if (gai_error != 0) {
113
+ rb_raise(egeoip2_compat_Exception,
114
+ "geoip2_compat - getaddrinfo failed: %s", gai_strerror(gai_error)
115
+ );
116
+ }
117
+
118
+ if (!result.found_entry) return Qnil;
119
+
120
+ VALUE hash = rb_hash_new();
121
+
122
+ geoip2_compat_lookup_internal(&result, hash, geoip2_compat_COUNTRY_CODE, "country", "iso_code", NULL);
123
+ geoip2_compat_lookup_internal(&result, hash, geoip2_compat_COUNTRY_NAME, "country", "names", "en", NULL);
124
+ geoip2_compat_lookup_internal(&result, hash, geoip2_compat_REGION, "subdivisions", "0", "iso_code", NULL);
125
+ geoip2_compat_lookup_internal(&result, hash, geoip2_compat_REGION_NAME, "subdivisions", "0", "names", "en", NULL);
126
+ geoip2_compat_lookup_internal(&result, hash, geoip2_compat_CITY, "city", "names", "en", NULL);
127
+ geoip2_compat_lookup_internal(&result, hash, geoip2_compat_POSTAL_CODE, "postal", "code", NULL);
128
+ geoip2_compat_lookup_internal(&result, hash, geoip2_compat_LATITUDE, "location", "latitude", NULL);
129
+ geoip2_compat_lookup_internal(&result, hash, geoip2_compat_LONGITUDE, "location", "longitude", NULL);
130
+
131
+ return hash;
132
+ }
133
+
134
+ static void geoip2_compat_free(MMDB_s *mmdb)
135
+ {
136
+ geoip2_compat_internal_close(mmdb);
137
+ ruby_xfree(mmdb);
138
+ }
139
+
140
+ static VALUE geoip2_compat_allocate(VALUE klass)
141
+ {
142
+ MMDB_s* mmdb = ruby_xmalloc(sizeof(MMDB_s));
143
+ mmdb->file_content = NULL;
144
+ return Data_Wrap_Struct(klass, NULL, geoip2_compat_free, mmdb);
145
+ }
146
+
147
+ static VALUE geoip2_compat_initialize(VALUE self, VALUE path)
148
+ {
149
+ Check_Type(path, T_STRING);
150
+ char* db = StringValuePtr(path);
151
+ MMDB_s *mmdb;
152
+ Data_Get_Struct(self, MMDB_s, mmdb);
153
+
154
+ int status = MMDB_open(db, MMDB_MODE_MMAP, mmdb);
155
+
156
+ if (status != MMDB_SUCCESS) {
157
+ rb_raise(egeoip2_compat_Exception, "GeoIP2Compat - %s: %s",
158
+ MMDB_strerror(status), db
159
+ );
160
+ }
161
+ return self;
162
+ }
163
+
164
+ void Init_geoip2_compat()
165
+ {
166
+ cgeoip2_compat = rb_define_class("GeoIP2Compat", rb_cObject);
167
+ egeoip2_compat_Exception = rb_define_class_under(cgeoip2_compat, "Error", rb_eStandardError);
168
+
169
+ rb_global_variable(&cgeoip2_compat);
170
+ rb_global_variable(&egeoip2_compat_Exception);
171
+
172
+ rb_define_alloc_func(cgeoip2_compat, geoip2_compat_allocate);
173
+ rb_define_method(cgeoip2_compat, "initialize", geoip2_compat_initialize, 1);
174
+ rb_define_method(cgeoip2_compat, "path", geoip2_compat_path, 0);
175
+ rb_define_method(cgeoip2_compat, "close", geoip2_compat_close, 0);
176
+ rb_define_method(cgeoip2_compat, "lookup", geoip2_compat_lookup, 1);
177
+
178
+ geoip2_compat_COUNTRY_CODE = rb_intern("country_code");
179
+ geoip2_compat_COUNTRY_NAME = rb_intern("country_name");
180
+ geoip2_compat_REGION = rb_intern("region");
181
+ geoip2_compat_REGION_NAME = rb_intern("region_name");
182
+ geoip2_compat_CITY = rb_intern("city");
183
+ geoip2_compat_POSTAL_CODE = rb_intern("postal_code");
184
+ geoip2_compat_LATITUDE = rb_intern("latitude");
185
+ geoip2_compat_LONGITUDE = rb_intern("longitude");
186
+ }
@@ -0,0 +1,167 @@
1
+ #include <stdlib.h>
2
+ #include <string.h>
3
+
4
+ /* *INDENT-OFF* */
5
+
6
+ /* The memmem, strdup, and strndup functions were all copied from the
7
+ * FreeBSD source, along with the relevant copyright notice.
8
+ *
9
+ * It'd be nicer to simply use the functions available on the system if they
10
+ * exist, but there doesn't seem to be a good way to detect them without also
11
+ * defining things like _GNU_SOURCE, which we want to avoid, because then we
12
+ * end up _accidentally_ using GNU features without noticing, which then
13
+ * breaks on systems like OSX.
14
+ *
15
+ * C is fun! */
16
+
17
+ /* Applies to memmem implementation */
18
+ /*-
19
+ * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
20
+ *
21
+ * Redistribution and use in source and binary forms, with or without
22
+ * modification, are permitted provided that the following conditions
23
+ * are met:
24
+ * 1. Redistributions of source code must retain the above copyright
25
+ * notice, this list of conditions and the following disclaimer.
26
+ * 2. Redistributions in binary form must reproduce the above copyright
27
+ * notice, this list of conditions and the following disclaimer in the
28
+ * documentation and/or other materials provided with the distribution.
29
+ * 3. The name of the author may not be used to endorse or promote
30
+ * products derived from this software without specific prior written
31
+ * permission.
32
+ *
33
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
34
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
37
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43
+ * SUCH DAMAGE.
44
+ */
45
+ static void *
46
+ mmdb_memmem(const void *l, size_t l_len, const void *s, size_t s_len)
47
+ {
48
+ register char *cur, *last;
49
+ const char *cl = (const char *)l;
50
+ const char *cs = (const char *)s;
51
+
52
+ /* we need something to compare */
53
+ if (l_len == 0 || s_len == 0)
54
+ return NULL;
55
+
56
+ /* "s" must be smaller or equal to "l" */
57
+ if (l_len < s_len)
58
+ return NULL;
59
+
60
+ /* special case where s_len == 1 */
61
+ if (s_len == 1)
62
+ return memchr(l, (int)*cs, l_len);
63
+
64
+ /* the last position where its possible to find "s" in "l" */
65
+ last = (char *)cl + l_len - s_len;
66
+
67
+ for (cur = (char *)cl; cur <= last; cur++)
68
+ if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
69
+ return cur;
70
+
71
+ return NULL;
72
+ }
73
+
74
+ /* Applies to strnlen implementation */
75
+ /*-
76
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
77
+ * All rights reserved.
78
+ *
79
+ * Redistribution and use in source and binary forms, with or without
80
+ * modification, are permitted provided that the following conditions
81
+ * are met:
82
+ * 1. Redistributions of source code must retain the above copyright
83
+ * notice, this list of conditions and the following disclaimer.
84
+ * 2. Redistributions in binary form must reproduce the above copyright
85
+ * notice, this list of conditions and the following disclaimer in the
86
+ * documentation and/or other materials provided with the distribution.
87
+ *
88
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
89
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
90
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
91
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
92
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
93
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
94
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
95
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
96
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
97
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
98
+ * SUCH DAMAGE.
99
+ */
100
+ static size_t
101
+ mmdb_strnlen(const char *s, size_t maxlen)
102
+ {
103
+ size_t len;
104
+
105
+ for (len = 0; len < maxlen; len++, s++) {
106
+ if (!*s)
107
+ break;
108
+ }
109
+ return (len);
110
+ }
111
+
112
+ /* Applies to strdup and strndup implementation */
113
+ /*
114
+ * Copyright (c) 1988, 1993
115
+ * The Regents of the University of California. All rights reserved.
116
+ *
117
+ * Redistribution and use in source and binary forms, with or without
118
+ * modification, are permitted provided that the following conditions
119
+ * are met:
120
+ * 1. Redistributions of source code must retain the above copyright
121
+ * notice, this list of conditions and the following disclaimer.
122
+ * 2. Redistributions in binary form must reproduce the above copyright
123
+ * notice, this list of conditions and the following disclaimer in the
124
+ * documentation and/or other materials provided with the distribution.
125
+ * 3. Neither the name of the University nor the names of its contributors
126
+ * may be used to endorse or promote products derived from this software
127
+ * without specific prior written permission.
128
+ *
129
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
130
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
131
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
132
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
133
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
134
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
135
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
136
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
137
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
138
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
139
+ * SUCH DAMAGE.
140
+ */
141
+ static char *
142
+ mmdb_strdup(const char *str)
143
+ {
144
+ size_t len;
145
+ char *copy;
146
+
147
+ len = strlen(str) + 1;
148
+ if ((copy = malloc(len)) == NULL)
149
+ return (NULL);
150
+ memcpy(copy, str, len);
151
+ return (copy);
152
+ }
153
+
154
+ static char *
155
+ mmdb_strndup(const char *str, size_t n)
156
+ {
157
+ size_t len;
158
+ char *copy;
159
+
160
+ len = mmdb_strnlen(str, n);
161
+ if ((copy = malloc(len + 1)) == NULL)
162
+ return (NULL);
163
+ memcpy(copy, str, len);
164
+ copy[len] = '\0';
165
+ return (copy);
166
+ }
167
+ /* *INDENT-ON* */