maxmind-geoip2 1.0.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +27 -0
  3. data/README.md +13 -10
  4. data/lib/maxmind/geoip2/client.rb +18 -9
  5. data/lib/maxmind/geoip2/errors.rb +17 -8
  6. data/lib/maxmind/geoip2/model/city.rb +4 -5
  7. data/lib/maxmind/geoip2/model/connection_type.rb +3 -2
  8. data/lib/maxmind/geoip2/model/enterprise.rb +2 -3
  9. data/lib/maxmind/geoip2/model/insights.rb +3 -5
  10. data/lib/maxmind/geoip2/model/isp.rb +16 -0
  11. data/lib/maxmind/geoip2/reader.rb +1 -2
  12. data/lib/maxmind/geoip2/record/traits.rb +58 -26
  13. data/lib/maxmind/geoip2/version.rb +8 -0
  14. data/maxmind-geoip2.gemspec +8 -2
  15. data/test/data/MaxMind-DB-spec.md +15 -11
  16. data/test/data/cmd/write-test-data/main.go +68 -0
  17. data/test/data/go.mod +13 -0
  18. data/test/data/go.sum +16 -0
  19. data/test/data/perltidyrc +6 -0
  20. data/test/data/pkg/writer/decoder.go +178 -0
  21. data/test/data/pkg/writer/geoip2.go +182 -0
  22. data/test/data/pkg/writer/ip.go +39 -0
  23. data/test/data/pkg/writer/maxmind.go +245 -0
  24. data/test/data/pkg/writer/nestedstructures.go +73 -0
  25. data/test/data/pkg/writer/writer.go +58 -0
  26. data/test/data/source-data/GeoIP2-City-Test.json +402 -48
  27. data/test/data/source-data/GeoIP2-Connection-Type-Test.json +35 -10
  28. data/test/data/source-data/GeoIP2-Country-Test.json +145 -58
  29. data/test/data/source-data/GeoIP2-Domain-Test.json +5 -0
  30. data/test/data/source-data/GeoIP2-Enterprise-Test.json +408 -4
  31. data/test/data/source-data/GeoIP2-ISP-Test.json +10 -0
  32. data/test/data/source-data/GeoIP2-Precision-Enterprise-Sandbox-Test.json +296 -0
  33. data/test/data/source-data/GeoIP2-Precision-Enterprise-Test.json +473 -6
  34. data/test/data/source-data/GeoIP2-Static-IP-Score-Test.json +15 -0
  35. data/test/data/source-data/GeoIP2-User-Count-Test.json +18 -0
  36. data/test/data/source-data/GeoLite2-ASN-Test.json +4091 -8
  37. data/test/data/source-data/GeoLite2-City-Test.json +12972 -0
  38. data/test/data/source-data/GeoLite2-Country-Test.json +11372 -0
  39. data/test/data/test-data/GeoIP2-Anonymous-IP-Test.mmdb +0 -0
  40. data/test/data/test-data/GeoIP2-City-Test-Broken-Double-Format.mmdb +0 -0
  41. data/test/data/test-data/GeoIP2-City-Test-Invalid-Node-Count.mmdb +0 -0
  42. data/test/data/test-data/GeoIP2-City-Test.mmdb +0 -0
  43. data/test/data/test-data/GeoIP2-Connection-Type-Test.mmdb +0 -0
  44. data/test/data/test-data/GeoIP2-Country-Test.mmdb +0 -0
  45. data/test/data/test-data/GeoIP2-DensityIncome-Test.mmdb +0 -0
  46. data/test/data/test-data/GeoIP2-Domain-Test.mmdb +0 -0
  47. data/test/data/test-data/GeoIP2-Enterprise-Test.mmdb +0 -0
  48. data/test/data/test-data/GeoIP2-ISP-Test.mmdb +0 -0
  49. data/test/data/test-data/GeoIP2-Precision-Enterprise-Test.mmdb +0 -0
  50. data/test/data/test-data/GeoIP2-Static-IP-Score-Test.mmdb +0 -0
  51. data/test/data/test-data/GeoIP2-User-Count-Test.mmdb +0 -0
  52. data/test/data/test-data/GeoLite2-ASN-Test.mmdb +0 -0
  53. data/test/data/test-data/GeoLite2-City-Test.mmdb +0 -0
  54. data/test/data/test-data/GeoLite2-Country-Test.mmdb +0 -0
  55. data/test/data/test-data/MaxMind-DB-no-ipv4-search-tree.mmdb +0 -0
  56. data/test/data/test-data/MaxMind-DB-string-value-entries.mmdb +0 -0
  57. data/test/data/test-data/MaxMind-DB-test-broken-pointers-24.mmdb +0 -0
  58. data/test/data/test-data/MaxMind-DB-test-broken-search-tree-24.mmdb +0 -0
  59. data/test/data/test-data/MaxMind-DB-test-decoder.mmdb +0 -0
  60. data/test/data/test-data/MaxMind-DB-test-ipv4-24.mmdb +0 -0
  61. data/test/data/test-data/MaxMind-DB-test-ipv4-28.mmdb +0 -0
  62. data/test/data/test-data/MaxMind-DB-test-ipv4-32.mmdb +0 -0
  63. data/test/data/test-data/MaxMind-DB-test-ipv6-24.mmdb +0 -0
  64. data/test/data/test-data/MaxMind-DB-test-ipv6-28.mmdb +0 -0
  65. data/test/data/test-data/MaxMind-DB-test-ipv6-32.mmdb +0 -0
  66. data/test/data/test-data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  67. data/test/data/test-data/MaxMind-DB-test-mixed-24.mmdb +0 -0
  68. data/test/data/test-data/MaxMind-DB-test-mixed-28.mmdb +0 -0
  69. data/test/data/test-data/MaxMind-DB-test-mixed-32.mmdb +0 -0
  70. data/test/data/test-data/MaxMind-DB-test-nested.mmdb +0 -0
  71. data/test/data/test-data/MaxMind-DB-test-pointer-decoder.mmdb +0 -0
  72. data/test/data/test-data/README.md +30 -14
  73. data/test/test_client.rb +18 -2
  74. data/test/test_reader.rb +37 -3
  75. metadata +21 -8
  76. data/test/data/MaxMind-DB-test-metadata-pointers.mmdb +0 -0
  77. data/test/data/source-data/README +0 -15
  78. data/test/data/test-data/write-test-data.pl +0 -691
@@ -1,691 +0,0 @@
1
- #!/usr/bin/env perl
2
-
3
- use strict;
4
- use warnings;
5
- use autodie;
6
- use utf8;
7
-
8
- use Cwd qw( abs_path );
9
- use File::Basename qw( dirname );
10
- use File::Slurper qw( read_binary write_binary );
11
- use Cpanel::JSON::XS 4.16 qw( decode_json );
12
- use Math::Int128 qw( MAX_UINT128 string_to_uint128 uint128 );
13
- use MaxMind::DB::Writer::Serializer 0.100004;
14
- use MaxMind::DB::Writer::Tree 0.100004;
15
- use MaxMind::DB::Writer::Util qw( key_for_data );
16
- use Net::Works::Network ();
17
- use Test::MaxMind::DB::Common::Util qw( standard_test_metadata );
18
-
19
- my $Dir = dirname( abs_path($0) );
20
-
21
- sub main {
22
- my @sizes = ( 24, 28, 32 );
23
- my @ipv4_range = ( '1.1.1.1', '1.1.1.32' );
24
-
25
- my @ipv4_subnets = Net::Works::Network->range_as_subnets(@ipv4_range);
26
- for my $record_size (@sizes) {
27
- write_test_db(
28
- $record_size,
29
- \@ipv4_subnets,
30
- { ip_version => 4 },
31
- 'ipv4',
32
- );
33
- }
34
-
35
- write_broken_pointers_test_db(
36
- 24,
37
- \@ipv4_subnets,
38
- { ip_version => 4 },
39
- 'broken-pointers',
40
- );
41
-
42
- write_broken_search_tree_db(
43
- 24,
44
- \@ipv4_subnets,
45
- { ip_version => 4 },
46
- 'broken-search-tree',
47
- );
48
-
49
- my @ipv6_subnets = Net::Works::Network->range_as_subnets(
50
- '::1:ffff:ffff',
51
- '::2:0000:0059'
52
- );
53
-
54
- for my $record_size (@sizes) {
55
- write_test_db(
56
- $record_size,
57
- \@ipv6_subnets,
58
- { ip_version => 6 },
59
- 'ipv6',
60
- );
61
-
62
- write_test_db(
63
- $record_size,
64
- [
65
- @ipv6_subnets,
66
- Net::Works::Network->range_as_subnets( @ipv4_range, 6 ),
67
- ],
68
- { ip_version => 6 },
69
- 'mixed',
70
- );
71
- }
72
-
73
- write_decoder_test_db();
74
- write_pointer_decoder_test_db();
75
- write_deeply_nested_structures_db();
76
-
77
- write_geoip2_dbs();
78
- write_broken_geoip2_city_db();
79
- write_invalid_node_count();
80
-
81
- write_no_ipv4_tree_db();
82
-
83
- write_no_map_db( \@ipv4_subnets );
84
-
85
- write_test_serialization_data();
86
-
87
- write_db_with_metadata_pointers();
88
- }
89
-
90
- sub write_broken_pointers_test_db {
91
- no warnings 'redefine';
92
-
93
- my $orig_store_data = MaxMind::DB::Writer::Serializer->can('store_data');
94
-
95
- # This breaks the value of the record for the 1.1.1.32 network, causing it
96
- # to point outside the database.
97
- local *MaxMind::DB::Writer::Serializer::store_data = sub {
98
- my $data_pointer = shift->$orig_store_data(@_);
99
- my $value = $_[1];
100
- if ( ref($value) eq 'HASH'
101
- && exists $value->{ip}
102
- && $value->{ip} eq '1.1.1.32' ) {
103
-
104
- $data_pointer += 100_000;
105
- }
106
- return $data_pointer;
107
- };
108
-
109
- # The next hack will poison the data section for the 1.1.16/28 subnet
110
- # value. It's value will be a pointer that resolves to an offset outside
111
- # the database.
112
-
113
- my $key_to_poison = key_for_data( { ip => '1.1.1.16' } );
114
-
115
- my $orig_position_for_data
116
- = MaxMind::DB::Writer::Serializer->can('_position_for_data');
117
- local *MaxMind::DB::Writer::Serializer::_position_for_data = sub {
118
- my $key = $_[1];
119
-
120
- if ( $key eq $key_to_poison ) {
121
- return 1_000_000;
122
- }
123
- else {
124
- return shift->$orig_position_for_data(@_);
125
- }
126
- };
127
-
128
- write_test_db(@_);
129
-
130
- return;
131
- }
132
-
133
- sub write_broken_search_tree_db {
134
- my $filename = ( write_test_db(@_) )[1];
135
-
136
- my $content = read_binary($filename);
137
-
138
- # This causes the right record of the first node to be 0, meaning it
139
- # points back to the top of the tree. This should never happen in a
140
- # database that follows the spec.
141
- substr( $content, 5, 1 ) = "\0";
142
- write_binary( $filename, $content );
143
-
144
- return;
145
- }
146
-
147
- sub write_test_db {
148
- my $record_size = shift;
149
- my $subnets = shift;
150
- my $metadata = shift;
151
- my $ip_version_name = shift;
152
-
153
- my $writer = MaxMind::DB::Writer::Tree->new(
154
- ip_version => $subnets->[0]->version(),
155
- record_size => $record_size,
156
- alias_ipv6_to_ipv4 => ( $subnets->[0]->version() == 6 ? 1 : 0 ),
157
- map_key_type_callback => sub { 'utf8_string' },
158
- standard_test_metadata(),
159
- %{$metadata},
160
- );
161
-
162
- for my $subnet ( @{$subnets} ) {
163
- $writer->insert_network(
164
- $subnet,
165
- { ip => $subnet->first()->as_string() }
166
- );
167
- }
168
-
169
- my $filename = sprintf(
170
- "$Dir/MaxMind-DB-test-%s-%i.mmdb",
171
- $ip_version_name,
172
- $record_size,
173
- );
174
- open my $fh, '>', $filename;
175
-
176
- $writer->write_tree($fh);
177
-
178
- close $fh;
179
-
180
- return ( $writer, $filename );
181
- }
182
-
183
- {
184
- # We will store this once for each subnet so we will also be testing
185
- # pointers, since the serializer will generate a pointer to this
186
- # structure.
187
- my %all_types = (
188
- utf8_string => 'unicode! ☯ - ♫',
189
- double => 42.123456,
190
- bytes => pack( 'N', 42 ),
191
- uint16 => 100,
192
- uint32 => 2**28,
193
- int32 => -1 * ( 2**28 ),
194
- uint64 => uint128(1) << 60,
195
- uint128 => uint128(1) << 120,
196
- array => [ 1, 2, 3, ],
197
- map => {
198
- mapX => {
199
- utf8_stringX => 'hello',
200
- arrayX => [ 7, 8, 9 ],
201
- },
202
- },
203
- boolean => 1,
204
- float => 1.1,
205
- );
206
-
207
- my %all_types_0 = (
208
- utf8_string => q{},
209
- double => 0,
210
- bytes => q{},
211
- uint16 => 0,
212
- uint32 => 0,
213
- int32 => 0,
214
- uint64 => uint128(0),
215
- uint128 => uint128(0),
216
- array => [],
217
- map => {},
218
- boolean => 0,
219
- float => 0,
220
- );
221
-
222
- # We limit this to numeric types as the other types would generate
223
- # very large databases
224
- my %numeric_types_max = (
225
- double => 'Inf',
226
- float => 'Inf',
227
- int32 => 0x7fffffff,
228
- uint16 => 0xffff,
229
- uint32 => string_to_uint128('0xffff_ffff'),
230
- uint64 => string_to_uint128('0xffff_ffff_ffff_ffff'),
231
- uint128 => MAX_UINT128,
232
- );
233
-
234
- sub write_decoder_test_db {
235
- my $writer = _decoder_writer();
236
-
237
- my @subnets
238
- = map { Net::Works::Network->new_from_string( string => $_ ) }
239
- qw(
240
- ::1.1.1.0/120
241
- ::2.2.0.0/112
242
- ::3.0.0.0/104
243
- ::4.5.6.7/128
244
- abcd::/64
245
- 1000::1234:0000/112
246
- );
247
-
248
- for my $subnet (@subnets) {
249
- $writer->insert_network(
250
- $subnet,
251
- \%all_types,
252
- );
253
- }
254
-
255
- $writer->insert_network(
256
- Net::Works::Network->new_from_string( string => '::0.0.0.0/128' ),
257
- \%all_types_0,
258
- );
259
-
260
- $writer->insert_network(
261
- Net::Works::Network->new_from_string(
262
- string => '::255.255.255.255/128'
263
- ),
264
- \%numeric_types_max,
265
- );
266
-
267
- open my $fh, '>', "$Dir/MaxMind-DB-test-decoder.mmdb";
268
- $writer->write_tree($fh);
269
- close $fh;
270
-
271
- return;
272
- }
273
-
274
- sub write_pointer_decoder_test_db {
275
-
276
- # We want to create a database where most values are pointers
277
- no warnings 'redefine';
278
- local *MaxMind::DB::Writer::Serializer::_should_cache_value
279
- = sub { 1 };
280
- my $writer = _decoder_writer();
281
-
282
- # We add these slightly different records so that we end up with
283
- # pointers for the individual values in the maps, not just pointers
284
- # to the map
285
- $writer->insert_network(
286
- '1.0.0.0/32',
287
- {
288
- %all_types,
289
- booleanX => 0,
290
- arrayX => [ 1, 2, 3, 4, ],
291
- mapXX => {
292
- utf8_stringX => 'hello',
293
- arrayX => [ 7, 8, 9, 10 ],
294
- booleanX => 0,
295
- },
296
- },
297
- );
298
-
299
- $writer->insert_network(
300
- '1.1.1.0/32',
301
- {
302
- %all_types,
303
-
304
- # This has to be 0 rather than 1 as otherwise the buggy
305
- # Perl writer will think it is the same as an uint32 value of
306
- # 1 and make a pointer to a value of a different type.
307
- boolean => 0,
308
- },
309
- );
310
-
311
- open my $fh, '>', "$Dir/MaxMind-DB-test-pointer-decoder.mmdb";
312
- $writer->write_tree($fh);
313
- close $fh;
314
-
315
- return;
316
- }
317
-
318
- sub _decoder_writer {
319
- return MaxMind::DB::Writer::Tree->new(
320
- ip_version => 6,
321
- record_size => 24,
322
- database_type => 'MaxMind DB Decoder Test',
323
- languages => ['en'],
324
- description => {
325
- en =>
326
- 'MaxMind DB Decoder Test database - contains every MaxMind DB data type',
327
- },
328
- alias_ipv6_to_ipv4 => 1,
329
- remove_reserved_networks => 0,
330
- map_key_type_callback => sub {
331
- my $key = $_[0];
332
- $key =~ s/X*$//;
333
- return $key eq 'array' ? [ 'array', 'uint32' ] : $key;
334
- },
335
- );
336
- }
337
- }
338
-
339
- {
340
- my %nested = (
341
- map1 => {
342
- map2 => {
343
- array => [
344
- {
345
- map3 => { a => 1, b => 2, c => 3 },
346
- },
347
- ],
348
- },
349
- },
350
- );
351
-
352
- sub write_deeply_nested_structures_db {
353
- my $writer = MaxMind::DB::Writer::Tree->new(
354
- ip_version => 6,
355
- record_size => 24,
356
- ip_version => 6,
357
- database_type => 'MaxMind DB Nested Data Structures',
358
- languages => ['en'],
359
- description => {
360
- en =>
361
- 'MaxMind DB Nested Data Structures Test database - contains deeply nested map/array structures',
362
- },
363
- alias_ipv6_to_ipv4 => 1,
364
- map_key_type_callback => sub {
365
- my $key = shift;
366
- return
367
- $key =~ /^map/ ? 'map'
368
- : $key eq 'array' ? [ 'array', 'map' ]
369
- : 'uint32';
370
- }
371
- );
372
-
373
- my @subnets
374
- = map { Net::Works::Network->new_from_string( string => $_ ) }
375
- qw(
376
- ::1.1.1.0/120
377
- ::2.2.0.0/112
378
- ::3.0.0.0/104
379
- ::4.5.6.7/128
380
- abcd::/64
381
- 1000::1234:0000/112
382
- );
383
-
384
- for my $subnet (@subnets) {
385
- $writer->insert_network(
386
- $subnet,
387
- \%nested,
388
- );
389
- }
390
-
391
- open my $fh, '>', "$Dir/MaxMind-DB-test-nested.mmdb";
392
- $writer->write_tree($fh);
393
- close $fh;
394
-
395
- return;
396
- }
397
- }
398
-
399
- sub write_geoip2_dbs {
400
- _write_geoip2_db( @{$_}[ 0, 1 ], 'Test' )
401
- for (
402
- [ 'GeoIP2-Anonymous-IP', {} ],
403
- ['GeoIP2-City'],
404
- ['GeoIP2-Connection-Type'],
405
- ['GeoIP2-Country'],
406
- ['GeoIP2-DensityIncome'],
407
- ['GeoIP2-Domain'],
408
- ['GeoIP2-Enterprise'],
409
- ['GeoIP2-ISP'],
410
- ['GeoIP2-Precision-Enterprise'],
411
- ['GeoIP2-Static-IP-Score'],
412
- ['GeoIP2-User-Count'],
413
- ['GeoLite2-ASN'],
414
- );
415
- }
416
-
417
- sub write_broken_geoip2_city_db {
418
- no warnings 'redefine';
419
-
420
- # This is how we _used_ to encode doubles. Storing them this way with the
421
- # current reader tools can lead to weird errors. This broken database is a
422
- # good way to test the robustness of reader code in the face of broken
423
- # databases.
424
- local *MaxMind::DB::Writer::Serializer::_encode_double = sub {
425
- my $self = shift;
426
- my $value = shift;
427
-
428
- $self->_simple_encode( double => $value );
429
- };
430
-
431
- _write_geoip2_db( 'GeoIP2-City', 0, 'Test Broken Double Format' );
432
- }
433
-
434
- sub write_invalid_node_count {
435
- no warnings 'redefine';
436
- local *MaxMind::DB::Writer::Tree::node_count = sub { 100000 };
437
-
438
- _write_geoip2_db( 'GeoIP2-City', 0, 'Test Invalid Node Count' );
439
- }
440
-
441
- sub _universal_map_key_type_callback {
442
- my $map = {
443
-
444
- # languages
445
- de => 'utf8_string',
446
- en => 'utf8_string',
447
- es => 'utf8_string',
448
- fr => 'utf8_string',
449
- ja => 'utf8_string',
450
- 'pt-BR' => 'utf8_string',
451
- ru => 'utf8_string',
452
- 'zh-CN' => 'utf8_string',
453
-
454
- # production
455
- accuracy_radius => 'uint16',
456
- autonomous_system_number => 'uint32',
457
- autonomous_system_organization => 'utf8_string',
458
- average_income => 'uint32',
459
- city => 'map',
460
- code => 'utf8_string',
461
- confidence => 'uint16',
462
- connection_type => 'utf8_string',
463
- continent => 'map',
464
- country => 'map',
465
- domain => 'utf8_string',
466
- geoname_id => 'uint32',
467
- ipv4_24 => 'uint32',
468
- ipv4_32 => 'uint32',
469
- ipv6_32 => 'uint32',
470
- ipv6_48 => 'uint32',
471
- ipv6_64 => 'uint32',
472
- is_anonymous => 'boolean',
473
- is_anonymous_proxy => 'boolean',
474
- is_anonymous_vpn => 'boolean',
475
- is_hosting_provider => 'boolean',
476
- is_in_european_union => 'boolean',
477
- is_legitimate_proxy => 'boolean',
478
- is_public_proxy => 'boolean',
479
- is_residential_proxy => 'boolean',
480
- is_satellite_provider => 'boolean',
481
- is_tor_exit_node => 'boolean',
482
- iso_code => 'utf8_string',
483
- isp => 'utf8_string',
484
- latitude => 'double',
485
- location => 'map',
486
- longitude => 'double',
487
- metro_code => 'uint16',
488
- names => 'map',
489
- organization => 'utf8_string',
490
- population_density => 'uint32',
491
- postal => 'map',
492
- registered_country => 'map',
493
- represented_country => 'map',
494
- score => 'double',
495
- static_ip_score => 'double',
496
- subdivisions => [ 'array', 'map' ],
497
- time_zone => 'utf8_string',
498
- traits => 'map',
499
- traits => 'map',
500
- type => 'utf8_string',
501
- user_type => 'utf8_string',
502
-
503
- # for testing only
504
- foo => 'utf8_string',
505
- bar => 'utf8_string',
506
- buzz => 'utf8_string',
507
- our_value => 'utf8_string',
508
- };
509
-
510
- my $callback = sub {
511
- my $key = shift;
512
-
513
- return $map->{$key} || die <<"ERROR";
514
- Unknown tree key '$key'.
515
-
516
- The universal_map_key_type_callback doesn't know what type to use for the passed
517
- key. If you are adding a new key that will be used in a frozen tree / mmdb then
518
- you should update the mapping in both our internal code and here.
519
- ERROR
520
- };
521
-
522
- return $callback;
523
- }
524
-
525
- sub _write_geoip2_db {
526
- my $type = shift;
527
- my $populate_all_networks_with_data = shift;
528
- my $description = shift;
529
-
530
- my $writer = MaxMind::DB::Writer::Tree->new(
531
- ip_version => 6,
532
- record_size => 28,
533
- ip_version => 6,
534
- database_type => $type,
535
- languages => [ 'en', $type eq 'GeoIP2-City' ? ('zh') : () ],
536
- description => {
537
- en => ( $type =~ s/-/ /gr )
538
- . " $description Database (fake GeoIP2 data, for example purposes only)",
539
- $type eq 'GeoIP2-City' ? ( zh => '小型数据库' ) : (),
540
- },
541
- alias_ipv6_to_ipv4 => 1,
542
- map_key_type_callback => _universal_map_key_type_callback(),
543
- );
544
-
545
- _populate_all_networks( $writer, $populate_all_networks_with_data )
546
- if $populate_all_networks_with_data;
547
-
548
- my $value = shift;
549
- my $nodes
550
- = decode_json( read_binary("$Dir/../source-data/$type-Test.json") );
551
-
552
- for my $node (@$nodes) {
553
- for my $network ( keys %$node ) {
554
- $writer->insert_network(
555
- Net::Works::Network->new_from_string( string => $network ),
556
- $node->{$network}
557
- );
558
- }
559
- }
560
-
561
- my $suffix = $description =~ s/ /-/gr;
562
- open my $output_fh, '>', "$Dir/$type-$suffix.mmdb";
563
- $writer->write_tree($output_fh);
564
- close $output_fh;
565
-
566
- return;
567
- }
568
-
569
- sub _populate_all_networks {
570
- my $writer = shift;
571
- my $data = shift;
572
-
573
- my $max_uint128 = uint128(0) - 1;
574
- my @networks = Net::Works::Network->range_as_subnets(
575
- Net::Works::Address->new_from_integer(
576
- integer => 0,
577
- version => 6,
578
- ),
579
- Net::Works::Address->new_from_integer(
580
- integer => $max_uint128,
581
- version => 6,
582
- ),
583
- );
584
-
585
- for my $network (@networks) {
586
- $writer->insert_network( $network => $data );
587
- }
588
- }
589
-
590
- sub write_no_ipv4_tree_db {
591
- my $subnets = shift;
592
-
593
- my $writer = MaxMind::DB::Writer::Tree->new(
594
- ip_version => 6,
595
- record_size => 24,
596
- ip_version => 6,
597
- database_type => 'MaxMind DB No IPv4 Search Tree',
598
- languages => ['en'],
599
- description => {
600
- en => 'MaxMind DB No IPv4 Search Tree',
601
- },
602
- remove_reserved_networks => 0,
603
- root_data_type => 'utf8_string',
604
- map_key_type_callback => sub { {} },
605
- );
606
-
607
- my $subnet = Net::Works::Network->new_from_string( string => '::/64' );
608
- $writer->insert_network( $subnet, $subnet->as_string() );
609
-
610
- open my $output_fh, '>', "$Dir/MaxMind-DB-no-ipv4-search-tree.mmdb";
611
- $writer->write_tree($output_fh);
612
- close $output_fh;
613
-
614
- return;
615
- }
616
-
617
- # The point of this database is to provide something where we can test looking
618
- # up a single value. In other words, each IP address points to a non-compound
619
- # value, a string rather than a map or array.
620
- sub write_no_map_db {
621
- my $subnets = shift;
622
-
623
- my $writer = MaxMind::DB::Writer::Tree->new(
624
- ip_version => 4,
625
- record_size => 24,
626
- database_type => 'MaxMind DB String Value Entries',
627
- languages => ['en'],
628
- description => {
629
- en =>
630
- 'MaxMind DB String Value Entries (no maps or arrays as values)',
631
- },
632
- root_data_type => 'utf8_string',
633
- map_key_type_callback => sub { {} },
634
- );
635
-
636
- for my $subnet ( @{$subnets} ) {
637
- $writer->insert_network( $subnet, $subnet->as_string() );
638
- }
639
-
640
- open my $output_fh, '>', "$Dir/MaxMind-DB-string-value-entries.mmdb";
641
- $writer->write_tree($output_fh);
642
- close $output_fh;
643
-
644
- return;
645
- }
646
-
647
- sub write_test_serialization_data {
648
- my $serializer = MaxMind::DB::Writer::Serializer->new(
649
- map_key_type_callback => sub { 'utf8_string' } );
650
-
651
- $serializer->store_data( map => { long_key => 'long_value1' } );
652
- $serializer->store_data( map => { long_key => 'long_value2' } );
653
- $serializer->store_data( map => { long_key2 => 'long_value1' } );
654
- $serializer->store_data( map => { long_key2 => 'long_value2' } );
655
- $serializer->store_data( map => { long_key => 'long_value1' } );
656
- $serializer->store_data( map => { long_key2 => 'long_value2' } );
657
-
658
- open my $fh, '>', 'maps-with-pointers.raw';
659
- print {$fh} ${ $serializer->buffer() }
660
- or die "Cannot write to maps-with-pointers.raw: $!";
661
- close $fh;
662
-
663
- return;
664
- }
665
-
666
- sub write_db_with_metadata_pointers {
667
- my $repeated_string = 'Lots of pointers in metadata';
668
- my $writer = MaxMind::DB::Writer::Tree->new(
669
- ip_version => 6,
670
- record_size => 24,
671
- map_key_type_callback => sub { 'utf8_string' },
672
- database_type => $repeated_string,
673
- languages => [ 'en', 'es', 'zh' ],
674
- description => {
675
- en => $repeated_string,
676
- es => $repeated_string,
677
- zh => $repeated_string,
678
- },
679
-
680
- );
681
-
682
- _populate_all_networks( $writer, {} );
683
-
684
- open my $fh, '>', 'MaxMind-DB-test-metadata-pointers.mmdb';
685
-
686
- $writer->write_tree($fh);
687
-
688
- close $fh;
689
- }
690
-
691
- main();