├── .gitignore ├── .travis.yml ├── Gemfile ├── LICENSE ├── README.md ├── Rakefile ├── bin └── nicinfo ├── lib ├── nicinfo.rb └── nicinfo │ ├── autnum.rb │ ├── bootstrap.rb │ ├── bsfiles │ ├── asn.json │ ├── dns.json │ ├── entity.json │ ├── ipv4.json │ └── ipv6.json │ ├── cache.rb │ ├── cidrs.rb │ ├── common_json.rb │ ├── common_names.rb │ ├── config.rb │ ├── constants.rb │ ├── data_tree.rb │ ├── demo │ ├── autnum.json │ ├── domain-dnr.json │ ├── domain-rir.json │ ├── domains.json │ ├── entities.json │ ├── entity-dnr.json │ ├── entity-rir.json │ ├── error-code.json │ ├── help.json │ ├── ip.json │ ├── nameservers.json │ ├── ns-simple.json │ ├── ns-very-simple.json │ ├── ns.json │ ├── simple-ip.json │ └── simple.json │ ├── domain.rb │ ├── ds_data.rb │ ├── entity.rb │ ├── enum.rb │ ├── error_code.rb │ ├── factory.rb │ ├── female-first-names.txt │ ├── ip.rb │ ├── jcr │ ├── rdap.jcr │ └── strict.jcr │ ├── key_data.rb │ ├── last-names.txt │ ├── male-first-names.txt │ ├── nicinfo_logger.rb │ ├── nicinfo_main.rb │ ├── notices.rb │ ├── ns.rb │ ├── traceroute.rb │ └── utils.rb ├── nicinfo.gemspec └── spec ├── bootstrap_spec.rb ├── cache_spec.rb ├── common_names_spec.rb ├── config_spec.rb ├── data_tree_spec.rb ├── demo_spec.rb ├── enum_spec.rb ├── live_spec.rb ├── logger_spec.rb ├── nicinfo_main_spec.rb ├── notices_spec.rb ├── recorded_responses ├── arin-entity-search.txt ├── arin-o.txt ├── arin_net.txt ├── autnum_703.txt ├── iana_asn.txt ├── iana_dns.txt ├── iana_ipv4.txt ├── iana_ipv6.txt ├── ip_108_45_128_208.txt └── ns1_arin_net.txt ├── spec_helper.rb ├── utils_spec.rb └── webmock_spec.rb /.gitignore: -------------------------------------------------------------------------------- 1 | *.iml 2 | .idea 3 | coverage/ 4 | *.gem 5 | !/README.md 6 | Gemfile.lock 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | os: 3 | - linux 4 | rvm: 5 | - 2.1.3 6 | - 2.3.4 7 | - 2.4.0 8 | script: 9 | - "bundle exec rake test" 10 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | gem 'rspec', :require => false, :group => :test 3 | gem 'coveralls', require: false 4 | gem 'rake', :require => false, :group => :test 5 | gem 'webmock', :require => false, :group => :test 6 | 7 | gemspec 8 | 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, ARIN Labs <> 2 | 3 | Permission to use, copy, modify, and/or distribute this software for any 4 | purpose with or without fee is hereby granted, provided that the above 5 | copyright notice and this permission notice appear in all copies. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 13 | OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deprecated 2 | 3 | This repository is no longer maintained. 4 | 5 | Please consider using [ICANN RDAP](https://github.com/icann/icann-rdap) as an alternative. 6 | 7 | # Overview 8 | [![Gem Version](https://badge.fury.io/rb/nicinfo.svg)](https://badge.fury.io/rb/nicinfo) 9 | [![Build Status](https://travis-ci.org/arineng/nicinfo.svg?branch=master)](https://travis-ci.org/arineng/nicinfo) 10 | [![Coverage Status](https://coveralls.io/repos/github/arineng/nicinfo/badge.svg?branch=master)](https://coveralls.io/github/arineng/nicinfo?branch=master) 11 | 12 | NicInfo is a general purpose, command line Registry Data Access Protocol (RDAP) client released under 13 | an open source, ISC derivative BSD style license. RDAP is an HTTP-based RESTful protocol defined by 14 | the IETF as a replacement for Whois. 15 | 16 | The general usage of this software from the command line is "nicinfo QUERY_VALUE" where the 17 | QUERY_VALUE is an IP address, domain name, autonomous system number, name server host name, 18 | or entity identifier. NicInfo will attempt to determine the most appropriate RDAP server to query 19 | and follow redirects to other RDAP servers as needed. 20 | 21 | ## Features 22 | 23 | NicInfo has the following features: 24 | 25 | * Query type detection: it will attempt to determine what type of query is needed based on the supplied query value. 26 | * Plain text output: default output is a text version of the RDAP results. 27 | * JSON output: the RDAP JSON can be passed directly to a calling program for intergration with scripts with 28 | the ability to select specific JSON values. 29 | * Multiple output controls: the amount of text detail and process execution can be varied and sent to different files. 30 | * A Built-in cache: RDAP queries are cached. 31 | * Bootstrapping using the IANA bootstrap files or by using a 32 | bootstrap server. 33 | * Demonstration queries: a set of built-in queries and results are provided for demonstration purposes. 34 | 35 | The following is an example of using NicInfo: 36 | 37 | $ bin/nicinfo --pager no 1.1.1.1 38 | # NicInfo v.0.1.0-snapshot 39 | 40 | [ NOTICE ] Source 41 | 1 Objects returned came from source 42 | 2 APNIC 43 | 44 | [ NOTICE ] Terms and Conditions 45 | 1 This is the APNIC WHOIS Database query service. The objects are in RDAP format. 46 | TOS http://www.apnic.net/db/dbcopyright.html 47 | 48 | [ RESPONSE DATA ] 49 | 1= 1.1.1.0 - 1.1.1.255 50 | |--- 1= APNIC RESEARCH ( AR302-AP ) 51 | `--- 2= IRT-APNICRANDNET-AU ( IRT-APNICRANDNET-AU ) 52 | 53 | [ IP NETWORK ] 54 | Handle: 1.1.1.0 - 1.1.1.255 55 | Start Address: 1.1.1.0 56 | End Address: 1.1.1.255 57 | IP Version: v4 58 | Country: AU 59 | Type: ASSIGNED PORTABLE 60 | Last Changed: Mon, 12 May 2014 04:16:03 -0000 61 | Remarks: -- description -- 62 | 1: Research prefix for APNIC Labs 63 | 2: APNIC 64 | 65 | [ ENTITY ] 66 | Handle: AR302-AP 67 | Name: APNIC RESEARCH 68 | Email: research@apnic.net 69 | Phone: +61-7-3858-3188 ( voice ) 70 | Phone: +61-7-3858-3199 ( fax ) 71 | Roles: Technical, Administrative 72 | Excessive Remarks: Use "-V" or "--data extra" to see them. 73 | 74 | [ ENTITY ] 75 | Handle: IRT-APNICRANDNET-AU 76 | Name: IRT-APNICRANDNET-AU 77 | Email: abuse@apnic.net 78 | Email: abuse@apnic.net 79 | Roles: Abuse 80 | 81 | # Use "nicinfo -r 1.1.1.1" to see reverse DNS information. 82 | # Use "nicinfo 1=" to show 1.1.1.0 - 1.1.1.255 83 | # Use "nicinfo 1.1=" to show APNIC RESEARCH ( AR302-AP ) 84 | # Use "nicinfo 1.2=" to show IRT-APNICRANDNET-AU ( IRT-APNICRANDNET-AU ) 85 | # Use "nicinfo http://rdap.apnic.net/ip/1.1.1.0/24" to directly query this resource in the future. 86 | # Use "nicinfo -h" for help. 87 | 88 | 89 | # Live examples 90 | 91 | ```bash 92 | nicinfo -V . 93 | nicinfo nic.br 94 | nicinfo nic.cz 95 | ``` 96 | 97 | # Versions 98 | 99 | Information about the various versions of NicInfo can be found in the [CHANGE LOG](https://github.com/arineng/nicinfo/wiki/CHANGELOG) 100 | on the [project wiki](https://github.com/arineng/nicinfo/wiki). 101 | 102 | # Getting and Installing 103 | 104 | Getting and installing NicInfo is easily accomplished as a Ruby Gem using the command `gem install nicinfo`. 105 | If that does not work for you, follow the instructions and advice for your platform on the project Wiki 106 | [here](https://github.com/arineng/nicinfo/wiki/Installing). 107 | 108 | If you wish to build and test this software from source, it follows the typical Ruby development process. 109 | More information may be found [here](https://github.com/arineng/nicinfo/wiki/Building-and-Testing). 110 | 111 | ## Getting Help 112 | 113 | Helpful information about NicInfo (and RDAP) may be found on the [project wiki](https://github.com/arineng/nicinfo/wiki). 114 | 115 | If you have questions or need help with this software, you may use the issue tracker on 116 | [GitHub](https://github.com/arinlabs/nicinfo/issues) or you may use the 117 | [ARIN Technical Discussions ](http://lists.arin.net/mailman/listinfo/arin-tech-discuss) 118 | mailing list (it is a very low volume list). 119 | 120 | 121 | # Demonstration Queries 122 | 123 | Demonstration queries are available with the --demo option, which will seed the cache with 124 | results and list the available demonstration queries. 125 | 126 | ``` 127 | nicinfo --demo 128 | ``` 129 | 130 | After the cache has been seeded, you will be presented with a list of example queries which will 131 | pull information from the cache. 132 | 133 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rspec/core/rake_task' 2 | require 'bundler/gem_tasks' 3 | 4 | RSpec::Core::RakeTask.new(:spec) 5 | 6 | RSpec::Core::RakeTask.new(:spec_live) do |t| 7 | t.rspec_opts = "--tag live" 8 | end 9 | 10 | desc "by default run tests" 11 | task :default => :test 12 | 13 | desc "run all tests" 14 | task :test => [:spec ] 15 | 16 | desc "run live tests" 17 | task :live_test => [ :spec_live ] -------------------------------------------------------------------------------- /bin/nicinfo: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | # Copyright (c) 2011-2015 American Registry for Internet Numbers 3 | # 4 | # Permission to use, copy, modify, and/or distribute this software for any 5 | # purpose with or without fee is hereby granted, provided that the above 6 | # copyright notice and this permission notice appear in all copies. 7 | # 8 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 14 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 | 16 | require 'rubygems' 17 | begin 18 | require 'nicinfo' 19 | rescue LoadError 20 | lib = File.expand_path("../lib",File.dirname(File.realdirpath(__FILE__))) 21 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 22 | require 'nicinfo' 23 | end 24 | app = NicInfo::Main.new( ARGV ) 25 | app.run() 26 | -------------------------------------------------------------------------------- /lib/nicinfo.rb: -------------------------------------------------------------------------------- 1 | require 'nicinfo/nicinfo_main' 2 | -------------------------------------------------------------------------------- /lib/nicinfo/autnum.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011-2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'nicinfo/config' 16 | require 'nicinfo/nicinfo_logger' 17 | require 'nicinfo/utils' 18 | require 'nicinfo/common_json' 19 | require 'nicinfo/entity' 20 | require 'nicinfo/data_tree' 21 | 22 | module NicInfo 23 | 24 | def NicInfo.display_autnum json_data, config, data_tree 25 | autnum = config.factory.new_autnum.process( json_data ) 26 | NicInfo::display_object_with_entities( autnum, config, data_tree ) 27 | end 28 | 29 | # deals with RDAP autonomous number structures 30 | class Autnum 31 | 32 | attr_accessor :entities, :objectclass, :asEventActors 33 | 34 | def initialize config 35 | @config = config 36 | @common = CommonJson.new config 37 | @entities = Array.new 38 | @asEventActors = Array.new 39 | end 40 | 41 | def process json_data 42 | @objectclass = json_data 43 | @entities = @common.process_entities @objectclass 44 | return self 45 | end 46 | 47 | def display 48 | @config.logger.start_data_item 49 | @config.logger.data_title "[ AS NUMBER ]" 50 | @config.logger.terse "Handle", NicInfo::get_handle( @objectclass ), NicInfo::AttentionType::SUCCESS 51 | @config.logger.extra "Object Class Name", NicInfo::get_object_class_name( @objectclass, "autnum", @config ) 52 | endNum = NicInfo.get_endAutnum @objectclass 53 | startNum = NicInfo.get_startAutnum @objectclass 54 | if endNum 55 | @config.logger.terse "Start AS Number", startNum, NicInfo::AttentionType::SUCCESS 56 | @config.logger.terse "End AS Number", endNum, NicInfo::AttentionType::SUCCESS 57 | else 58 | @config.logger.terse "AS Number", startNum, NicInfo::AttentionType::SUCCESS 59 | end 60 | @config.logger.extra "Name", NicInfo.get_name( @objectclass ) 61 | @config.logger.terse "Country", NicInfo.get_country( @objectclass ) 62 | @config.logger.datum "Type", NicInfo.get_type( @objectclass ) 63 | @common.display_status @objectclass 64 | @common.display_events @objectclass 65 | @common.display_as_events_actors @asEventActors 66 | @common.display_remarks @objectclass 67 | @common.display_links( get_cn, @objectclass ) 68 | @config.logger.end_data_item 69 | end 70 | 71 | def get_cn 72 | handle = NicInfo::get_handle @objectclass 73 | if !handle 74 | startNum = NicInfo.get_startAutnum @objectclass 75 | handle = startNum if startNum 76 | endNum = NicInfo.get_endAutnum @objectclass 77 | handle << " - " if startNum and endNum 78 | handle << endNum if endNum 79 | end 80 | return handle if handle 81 | return "(unidentifiable autonomous system number #{object_id})" 82 | end 83 | 84 | def to_node 85 | DataNode.new( get_cn, nil, NicInfo::get_self_link( NicInfo::get_links( @objectclass, @config ) ) ) 86 | end 87 | 88 | end 89 | 90 | end 91 | -------------------------------------------------------------------------------- /lib/nicinfo/bootstrap.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'rexml/document' 16 | require 'nicinfo/constants' 17 | require 'ipaddr' 18 | require 'json' 19 | 20 | module NicInfo 21 | 22 | class Bootstrap 23 | 24 | def initialize config 25 | @config = config 26 | end 27 | 28 | 29 | def find_url_by_ip addr 30 | retval = nil 31 | if ! addr.instance_of? IPAddr 32 | addr = IPAddr.new addr 33 | end 34 | file = File.join( @config.rdap_bootstrap_dir , NicInfo::IPV6_BOOTSTRAP ) if addr.ipv6? 35 | file = File.join( @config.rdap_bootstrap_dir , NicInfo::IPV4_BOOTSTRAP ) if addr.ipv4? 36 | @config.logger.trace "Looking up bootstrap from #{file}" 37 | data = JSON.parse( File.read( file ) ) 38 | services = get_services data 39 | services.each do |service| 40 | service[ 0 ].each do |service_entry| 41 | if addr.ipv6? 42 | prefix = IPAddr.new( service_entry ) 43 | else 44 | entry = service_entry.split( "/" )[0].to_i.to_s + ".0.0.0" 45 | prefix = IPAddr.new( entry ) 46 | prefix = prefix.mask( 8 ) 47 | end 48 | if prefix.include?( addr ) 49 | retval = get_service_url( service[ 1 ] ) 50 | break 51 | end 52 | end 53 | end if services 54 | retval = @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::IP_ROOT_URL ] if retval == nil 55 | return retval 56 | end 57 | 58 | def find_url_by_as as 59 | if as.instance_of? String 60 | as = as.sub( /^AS/i, '') 61 | as = as.to_i 62 | end 63 | retval = nil 64 | file = File.join( @config.rdap_bootstrap_dir , NicInfo::ASN_BOOTSTRAP ) 65 | @config.logger.trace "Looking up bootstrap from #{file}" 66 | data = JSON.parse( File.read( file ) ) 67 | services = get_services data 68 | services.each do |service| 69 | service[ 0 ].each do |service_entry| 70 | numbers = service_entry.split( "-" ) 71 | min = numbers[ 0 ].to_i 72 | max = numbers[ -1 ].to_i 73 | if (as >= min ) && (as <= max) 74 | retval = get_service_url( service[ 1 ] ) 75 | break 76 | end 77 | end 78 | end if services 79 | retval = @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::AS_ROOT_URL ] if retval == nil 80 | return retval 81 | end 82 | 83 | def get_ip4_by_inaddr inaddr 84 | inaddr = inaddr.sub( /\.in\-addr\.arpa\.?/, "") 85 | a = inaddr.split( "." ).reverse 86 | ip = Array.new( 4 ).fill( 0 ) 87 | for i in 0..a.length-1 do 88 | ip[ i ] = a[ i ].to_i 89 | end 90 | return IPAddr.new( ip.join( "." ) ) 91 | end 92 | 93 | def get_ip6_by_inaddr inaddr 94 | inaddr = inaddr.sub( /\.ip6\.arpa\.?/, "") 95 | a = inaddr.split( "." ).reverse.join 96 | ip = Array.new( 16 ).fill( 0 ) 97 | i = 0 98 | while i <= a.length-1 do 99 | ip[ i/2 ] = ( a[ i..i+1 ].to_i(16) ) 100 | i = i +2 101 | end 102 | ipstr = "" 103 | i = 0 104 | while i <= ip.length-1 do 105 | ipstr << ("%02X" % ip[i]) 106 | if ((i+1) % 2) == 0 107 | ipstr << ":" if i != ip.length-1 108 | end 109 | i = i +1 110 | end 111 | return IPAddr.new( ipstr ) 112 | end 113 | 114 | def find_url_by_domain domain 115 | retval = nil 116 | domain = domain.sub( /\.$/, '' ) #remove trailing dot if there is one 117 | if domain.end_with?( ".ip6.arpa" ) 118 | addr = get_ip6_by_inaddr domain 119 | retval = find_url_by_ip addr 120 | elsif domain.end_with?( ".in-addr.arpa" ) 121 | addr = get_ip4_by_inaddr domain 122 | retval = find_url_by_ip addr 123 | else 124 | retval = find_url_by_forward_domain domain 125 | end 126 | return retval 127 | end 128 | 129 | def find_url_by_forward_domain domain 130 | retval = nil 131 | file = File.join( @config.rdap_bootstrap_dir , NicInfo::DNS_BOOTSTRAP ) 132 | @config.logger.trace "Looking up bootstrap from #{file}" 133 | data = JSON.parse( File.read( file ) ) 134 | longest_domain = nil 135 | longest_urls = nil 136 | services = get_services data 137 | services.each do |service| 138 | service[ 0 ].each do |service_entry| 139 | if domain.end_with?( service_entry ) 140 | if longest_domain == nil || longest_domain.length < service_entry.length 141 | longest_domain = service_entry 142 | longest_urls = service[ 1 ] 143 | end 144 | end 145 | end 146 | end if services 147 | if longest_urls != nil 148 | retval = get_service_url( longest_urls ) 149 | end 150 | retval = @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::DOMAIN_ROOT_URL ] if retval == nil 151 | return retval 152 | end 153 | 154 | def find_url_by_entity entity_name 155 | retval = nil 156 | suffix = entity_name.downcase.split( '-' ).last 157 | if suffix 158 | file = File.join( @config.rdap_bootstrap_dir , NicInfo::ENTITY_BOOTSTRAP ) 159 | @config.logger.trace "Looking up bootstrap from #{file}" 160 | data = JSON.parse( File.read( file ) ) 161 | services = get_services data 162 | services.each do |service| 163 | service[ 0 ].each do |service_entry| 164 | if service_entry.downcase == suffix 165 | retval = get_service_url( service[ 1 ] ) 166 | break 167 | end 168 | end 169 | end if services 170 | end 171 | retval = @config.config[ NicInfo::BOOTSTRAP ][ NicInfo::ENTITY_ROOT_URL ] if retval == nil 172 | return retval 173 | end 174 | 175 | def get_services data 176 | data["services"] 177 | end 178 | 179 | def get_service_url service_url_array 180 | http_url = nil 181 | https_url = nil 182 | service_url_array.each do |url| 183 | if url.start_with?( "https" ) 184 | https_url = url 185 | elsif url.start_with?( "http" ) 186 | http_url = url 187 | end 188 | end 189 | if https_url != nil 190 | return https_url 191 | end 192 | #else 193 | return http_url 194 | end 195 | 196 | end 197 | 198 | end 199 | 200 | -------------------------------------------------------------------------------- /lib/nicinfo/bsfiles/dns.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "RDAP bootstrap file for Domain Name System registrations", 3 | "publication": "2017-10-31T04:42:05Z", 4 | "services": [ 5 | [ 6 | [ 7 | "com", 8 | "net" 9 | ], 10 | [ 11 | "https://rdap-pilot.verisignlabs.com/rdap/v1/" 12 | ] 13 | ], 14 | [ 15 | [ 16 | "ar" 17 | ], 18 | [ 19 | "https://rdap.nic.ar" 20 | ] 21 | ], 22 | [ 23 | [ 24 | "cz" 25 | ], 26 | [ 27 | "https://rdap.nic.cz" 28 | ] 29 | ], 30 | [ 31 | [ 32 | "br" 33 | ], 34 | [ 35 | "https://rdap.registro.br/" 36 | ] 37 | ] 38 | ], 39 | "version": "1.0" 40 | } 41 | -------------------------------------------------------------------------------- /lib/nicinfo/bsfiles/entity.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0", 3 | "publication": "2014-09-09T15:39:03-0400", 4 | "services": [ 5 | [ 6 | [ 7 | "ARIN" 8 | ], 9 | [ 10 | "https://rdap.arin.net/registry", 11 | "http://rdap.arin.net/registry" 12 | ] 13 | ], 14 | [ 15 | [ 16 | "AP" 17 | ], 18 | [ 19 | "https://rdap.apnic.net/", 20 | "http://rdap.apnic.net" 21 | ] 22 | ], 23 | [ 24 | [ 25 | "RIPE" 26 | ], 27 | [ 28 | "https://rdap.db.ripe.net/", 29 | "http://rdap.db.ripe.net/" 30 | ] 31 | ], 32 | [ 33 | [ 34 | "AFRINIC" 35 | ], 36 | [ 37 | "https://rdap.afrinic.net/rdap/", 38 | "http://rdap.afrinic.net/rdap/" 39 | ] 40 | ], 41 | [ 42 | [ 43 | "LACNIC" 44 | ], 45 | [ 46 | "https://rdap.lacnic.net/rdap/", 47 | "http://rdap.lacnic.net/rdap/" 48 | ] 49 | ] 50 | ] 51 | } -------------------------------------------------------------------------------- /lib/nicinfo/bsfiles/ipv4.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "RDAP bootstrap file for IPv4 address allocations", 3 | "publication": "2015-08-11T00:09:31Z", 4 | "services": [ 5 | [ 6 | [ 7 | "41.0.0.0/8", 8 | "102.0.0.0/8", 9 | "105.0.0.0/8", 10 | "154.0.0.0/8", 11 | "196.0.0.0/8", 12 | "197.0.0.0/8" 13 | ], 14 | [ 15 | "https://rdap.afrinic.net/rdap/", 16 | "http://rdap.afrinic.net/rdap/" 17 | ] 18 | ], 19 | [ 20 | [ 21 | "1.0.0.0/8", 22 | "14.0.0.0/8", 23 | "27.0.0.0/8", 24 | "36.0.0.0/8", 25 | "39.0.0.0/8", 26 | "42.0.0.0/8", 27 | "43.0.0.0/8", 28 | "49.0.0.0/8", 29 | "58.0.0.0/8", 30 | "59.0.0.0/8", 31 | "60.0.0.0/8", 32 | "61.0.0.0/8", 33 | "101.0.0.0/8", 34 | "103.0.0.0/8", 35 | "106.0.0.0/8", 36 | "110.0.0.0/8", 37 | "111.0.0.0/8", 38 | "112.0.0.0/8", 39 | "113.0.0.0/8", 40 | "114.0.0.0/8", 41 | "115.0.0.0/8", 42 | "116.0.0.0/8", 43 | "117.0.0.0/8", 44 | "118.0.0.0/8", 45 | "119.0.0.0/8", 46 | "120.0.0.0/8", 47 | "121.0.0.0/8", 48 | "122.0.0.0/8", 49 | "123.0.0.0/8", 50 | "124.0.0.0/8", 51 | "125.0.0.0/8", 52 | "126.0.0.0/8", 53 | "133.0.0.0/8", 54 | "150.0.0.0/8", 55 | "153.0.0.0/8", 56 | "163.0.0.0/8", 57 | "171.0.0.0/8", 58 | "175.0.0.0/8", 59 | "180.0.0.0/8", 60 | "182.0.0.0/8", 61 | "183.0.0.0/8", 62 | "202.0.0.0/8", 63 | "203.0.0.0/8", 64 | "210.0.0.0/8", 65 | "211.0.0.0/8", 66 | "218.0.0.0/8", 67 | "219.0.0.0/8", 68 | "220.0.0.0/8", 69 | "221.0.0.0/8", 70 | "222.0.0.0/8", 71 | "223.0.0.0/8" 72 | ], 73 | [ 74 | "https://rdap.apnic.net/" 75 | ] 76 | ], 77 | [ 78 | [ 79 | "3.0.0.0/8", 80 | "4.0.0.0/8", 81 | "6.0.0.0/8", 82 | "7.0.0.0/8", 83 | "8.0.0.0/8", 84 | "9.0.0.0/8", 85 | "11.0.0.0/8", 86 | "12.0.0.0/8", 87 | "13.0.0.0/8", 88 | "15.0.0.0/8", 89 | "16.0.0.0/8", 90 | "17.0.0.0/8", 91 | "18.0.0.0/8", 92 | "19.0.0.0/8", 93 | "20.0.0.0/8", 94 | "21.0.0.0/8", 95 | "22.0.0.0/8", 96 | "23.0.0.0/8", 97 | "24.0.0.0/8", 98 | "26.0.0.0/8", 99 | "28.0.0.0/8", 100 | "29.0.0.0/8", 101 | "30.0.0.0/8", 102 | "32.0.0.0/8", 103 | "33.0.0.0/8", 104 | "34.0.0.0/8", 105 | "35.0.0.0/8", 106 | "38.0.0.0/8", 107 | "40.0.0.0/8", 108 | "44.0.0.0/8", 109 | "45.0.0.0/8", 110 | "47.0.0.0/8", 111 | "48.0.0.0/8", 112 | "50.0.0.0/8", 113 | "52.0.0.0/8", 114 | "54.0.0.0/8", 115 | "55.0.0.0/8", 116 | "56.0.0.0/8", 117 | "63.0.0.0/8", 118 | "64.0.0.0/8", 119 | "65.0.0.0/8", 120 | "66.0.0.0/8", 121 | "67.0.0.0/8", 122 | "68.0.0.0/8", 123 | "69.0.0.0/8", 124 | "70.0.0.0/8", 125 | "71.0.0.0/8", 126 | "72.0.0.0/8", 127 | "73.0.0.0/8", 128 | "74.0.0.0/8", 129 | "75.0.0.0/8", 130 | "76.0.0.0/8", 131 | "96.0.0.0/8", 132 | "97.0.0.0/8", 133 | "98.0.0.0/8", 134 | "99.0.0.0/8", 135 | "100.0.0.0/8", 136 | "104.0.0.0/8", 137 | "107.0.0.0/8", 138 | "108.0.0.0/8", 139 | "128.0.0.0/8", 140 | "129.0.0.0/8", 141 | "130.0.0.0/8", 142 | "131.0.0.0/8", 143 | "132.0.0.0/8", 144 | "134.0.0.0/8", 145 | "135.0.0.0/8", 146 | "136.0.0.0/8", 147 | "137.0.0.0/8", 148 | "138.0.0.0/8", 149 | "139.0.0.0/8", 150 | "140.0.0.0/8", 151 | "142.0.0.0/8", 152 | "143.0.0.0/8", 153 | "144.0.0.0/8", 154 | "146.0.0.0/8", 155 | "147.0.0.0/8", 156 | "148.0.0.0/8", 157 | "149.0.0.0/8", 158 | "152.0.0.0/8", 159 | "155.0.0.0/8", 160 | "156.0.0.0/8", 161 | "157.0.0.0/8", 162 | "158.0.0.0/8", 163 | "159.0.0.0/8", 164 | "160.0.0.0/8", 165 | "161.0.0.0/8", 166 | "162.0.0.0/8", 167 | "164.0.0.0/8", 168 | "165.0.0.0/8", 169 | "166.0.0.0/8", 170 | "167.0.0.0/8", 171 | "168.0.0.0/8", 172 | "169.0.0.0/8", 173 | "170.0.0.0/8", 174 | "172.0.0.0/8", 175 | "173.0.0.0/8", 176 | "174.0.0.0/8", 177 | "184.0.0.0/8", 178 | "192.0.0.0/8", 179 | "198.0.0.0/8", 180 | "199.0.0.0/8", 181 | "204.0.0.0/8", 182 | "205.0.0.0/8", 183 | "206.0.0.0/8", 184 | "207.0.0.0/8", 185 | "208.0.0.0/8", 186 | "209.0.0.0/8", 187 | "214.0.0.0/8", 188 | "215.0.0.0/8", 189 | "216.0.0.0/8" 190 | ], 191 | [ 192 | "https://rdap.arin.net/registry", 193 | "http://rdap.arin.net/registry" 194 | ] 195 | ], 196 | [ 197 | [ 198 | "2.0.0.0/8", 199 | "5.0.0.0/8", 200 | "25.0.0.0/8", 201 | "31.0.0.0/8", 202 | "37.0.0.0/8", 203 | "46.0.0.0/8", 204 | "51.0.0.0/8", 205 | "53.0.0.0/8", 206 | "57.0.0.0/8", 207 | "62.0.0.0/8", 208 | "77.0.0.0/8", 209 | "78.0.0.0/8", 210 | "79.0.0.0/8", 211 | "80.0.0.0/8", 212 | "81.0.0.0/8", 213 | "82.0.0.0/8", 214 | "83.0.0.0/8", 215 | "84.0.0.0/8", 216 | "85.0.0.0/8", 217 | "86.0.0.0/8", 218 | "87.0.0.0/8", 219 | "88.0.0.0/8", 220 | "89.0.0.0/8", 221 | "90.0.0.0/8", 222 | "91.0.0.0/8", 223 | "92.0.0.0/8", 224 | "93.0.0.0/8", 225 | "94.0.0.0/8", 226 | "95.0.0.0/8", 227 | "109.0.0.0/8", 228 | "141.0.0.0/8", 229 | "145.0.0.0/8", 230 | "151.0.0.0/8", 231 | "176.0.0.0/8", 232 | "178.0.0.0/8", 233 | "185.0.0.0/8", 234 | "188.0.0.0/8", 235 | "193.0.0.0/8", 236 | "194.0.0.0/8", 237 | "195.0.0.0/8", 238 | "212.0.0.0/8", 239 | "213.0.0.0/8", 240 | "217.0.0.0/8" 241 | ], 242 | [ 243 | "https://rdap.db.ripe.net/" 244 | ] 245 | ], 246 | [ 247 | [ 248 | "177.0.0.0/8", 249 | "179.0.0.0/8", 250 | "181.0.0.0/8", 251 | "186.0.0.0/8", 252 | "187.0.0.0/8", 253 | "189.0.0.0/8", 254 | "190.0.0.0/8", 255 | "191.0.0.0/8", 256 | "200.0.0.0/8", 257 | "201.0.0.0/8" 258 | ], 259 | [ 260 | "https://rdap.lacnic.net/rdap/" 261 | ] 262 | ] 263 | ], 264 | "version": "1.0" 265 | } -------------------------------------------------------------------------------- /lib/nicinfo/bsfiles/ipv6.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "RDAP bootstrap file for IPv6 address allocations", 3 | "publication": "2016-03-22T15:40:01Z", 4 | "services": [ 5 | [ 6 | [ 7 | "2001:4200::/23", 8 | "2c00::/12" 9 | ], 10 | [ 11 | "https://rdap.afrinic.net/rdap/", 12 | "http://rdap.afrinic.net/rdap/" 13 | ] 14 | ], 15 | [ 16 | [ 17 | "2001:200::/23", 18 | "2001:4400::/23", 19 | "2001:8000::/19", 20 | "2001:a000::/20", 21 | "2001:b000::/20", 22 | "2001:c00::/23", 23 | "2001:e00::/23", 24 | "2400::/12" 25 | ], 26 | [ 27 | "https://rdap.apnic.net/" 28 | ] 29 | ], 30 | [ 31 | [ 32 | "2001:1800::/23", 33 | "2001:400::/23", 34 | "2001:4800::/23", 35 | "2600::/12", 36 | "2610::/23", 37 | "2620::/23" 38 | ], 39 | [ 40 | "https://rdap.arin.net/registry", 41 | "http://rdap.arin.net/registry" 42 | ] 43 | ], 44 | [ 45 | [ 46 | "2001:1400::/23", 47 | "2001:1600::/23", 48 | "2001:1a00::/23", 49 | "2001:1c00::/22", 50 | "2001:2000::/20", 51 | "2001:3000::/21", 52 | "2001:3800::/22", 53 | "2001:4000::/23", 54 | "2001:4600::/23", 55 | "2001:4a00::/23", 56 | "2001:4c00::/23", 57 | "2001:5000::/20", 58 | "2001:600::/23", 59 | "2001:800::/23", 60 | "2001:a00::/23", 61 | "2003::/18", 62 | "2a00::/12" 63 | ], 64 | [ 65 | "https://rdap.db.ripe.net/" 66 | ] 67 | ], 68 | [ 69 | [ 70 | "2001:1200::/23", 71 | "2800::/12" 72 | ], 73 | [ 74 | "https://rdap.lacnic.net/rdap/" 75 | ] 76 | ] 77 | ], 78 | "version": "1.0" 79 | } -------------------------------------------------------------------------------- /lib/nicinfo/cache.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | 16 | require 'time' 17 | require 'uri' 18 | require 'nicinfo/utils' 19 | 20 | module NicInfo 21 | 22 | class Cache 23 | 24 | def initialize config 25 | @config = config 26 | end 27 | 28 | # creates or updates an object in the cache 29 | def create_or_update url, data 30 | return nil if @config.config[ NicInfo::CACHE ][ NicInfo::USE_CACHE ] == false 31 | safe = NicInfo::make_safe(url) 32 | @config.logger.trace("Persisting " + url + " as " + safe) 33 | f = File.open(File.join(@config.rdap_cache_dir, safe), "w") 34 | f.puts data 35 | f.close 36 | end 37 | 38 | # creates an object in the cache. 39 | # if the object already exists in the cache, this does nothing. 40 | def create url, data 41 | safe = NicInfo::make_safe(url) 42 | file_name = File.join(@config.rdap_cache_dir, safe) 43 | expiry = Time.now - @config.config[ NicInfo::CACHE ][ NicInfo::CACHE_EXPIRY ] 44 | return if (File.exist?(file_name) && File.mtime(file_name) > expiry) 45 | create_or_update(url, data) 46 | end 47 | 48 | def get url 49 | return nil if @config.config[ NicInfo::CACHE ][ NicInfo::USE_CACHE ] == false 50 | safe = NicInfo::make_safe(url) 51 | file_name = File.join(@config.rdap_cache_dir, safe) 52 | expiry = Time.now - @config.config[ NicInfo::CACHE ][ NicInfo::CACHE_EXPIRY ] 53 | if (File.exist?(file_name) && File.mtime(file_name) > expiry) 54 | @config.logger.trace("Getting " + url + " from cache.") 55 | f = File.open(file_name, "r") 56 | data = '' 57 | f.each_line do |line| 58 | data += line 59 | end 60 | f.close 61 | return data 62 | end 63 | #else 64 | return nil 65 | end 66 | 67 | def clean 68 | cache_files = Dir::entries(@config.rdap_cache_dir) 69 | eviction = Time.now - @config.config[ NicInfo::CACHE ][ NicInfo::CACHE_EVICTION ] 70 | eviction_count = 0 71 | cache_files.each do |file| 72 | full_file_name = File.join(@config.rdap_cache_dir, file) 73 | if !file.start_with?(".") && (File.mtime(full_file_name) < eviction) 74 | @config.logger.trace("Evicting " + full_file_name) 75 | File::unlink(full_file_name) 76 | eviction_count += 1 77 | end 78 | end 79 | @config.logger.trace("Evicted " + eviction_count.to_s + " files from the cache") 80 | return eviction_count 81 | end 82 | 83 | def empty 84 | cache_files = Dir::entries(@config.rdap_cache_dir) 85 | eviction_count = 0 86 | cache_files.each do |file| 87 | full_file_name = File.join(@config.rdap_cache_dir, file) 88 | if !file.start_with?(".") 89 | @config.logger.trace("Evicting " + full_file_name) 90 | File::unlink(full_file_name) 91 | eviction_count += 1 92 | end 93 | end 94 | @config.logger.trace("Evicted " + eviction_count.to_s + " files from the cache") 95 | return eviction_count 96 | end 97 | 98 | def count 99 | count = 0 100 | cache_files = Dir::entries(@config.rdap_cache_dir) 101 | cache_files.each do |file| 102 | if !file.start_with?(".") 103 | count += 1 104 | end 105 | end 106 | return count 107 | end 108 | 109 | end 110 | 111 | end 112 | -------------------------------------------------------------------------------- /lib/nicinfo/cidrs.rb: -------------------------------------------------------------------------------- 1 | require('ipaddr') 2 | 3 | def split_range(s, e, pfx) 4 | diff = e - s 5 | pfx += 1 6 | return [[s, s + diff / 2, pfx], [s + diff/2 + 1, e, pfx]] 7 | end 8 | 9 | def cidr_to_str(ip, mask, type) 10 | ip = IPAddr.new(ip, type) 11 | return "%s/%i" % [ip.to_s, mask] 12 | end 13 | 14 | def find_start_cidrs(r, start) 15 | s = r[0] 16 | e = r[1] 17 | pfx = r[2] 18 | if s >= start 19 | return [r] 20 | elsif start > e 21 | return [] 22 | else 23 | nr1, nr2 = split_range(s, e, pfx) 24 | return find_start_cidrs(nr1, start) + find_start_cidrs(nr2, start) 25 | end 26 | end 27 | 28 | def find_end_cidrs(r, end_val) 29 | s = r[0] 30 | e = r[1] 31 | pfx = r[2] 32 | if e <= end_val 33 | return [r] 34 | elsif end_val < s 35 | return [] 36 | else 37 | nr1, nr2 = split_range(s, e, pfx) 38 | return find_end_cidrs(nr1, end_val) + find_end_cidrs(nr2, end_val) 39 | end 40 | end 41 | 42 | def clean_ip(ip) 43 | if ip.include? '.' 44 | ip = ip.split('.').map(&:to_i).join('.') 45 | end 46 | return ip 47 | end 48 | 49 | def find_cidrs(lower, upper) 50 | 51 | lower = clean_ip(lower) 52 | upper = clean_ip(upper) 53 | 54 | s = IPAddr.new lower 55 | e = IPAddr.new upper 56 | 57 | maxlen = 128 58 | type = Socket::AF_INET6 59 | if s.ipv4? 60 | maxlen = 32 61 | type = Socket::AF_INET 62 | end 63 | 64 | s = s.to_i 65 | e = e.to_i 66 | 67 | if s > e 68 | tmp = e 69 | e = s 70 | s = tmp 71 | end 72 | 73 | mask = e ^ s 74 | i = 0 75 | while mask != 0 76 | i += 1 77 | mask = mask >> 1 78 | end 79 | 80 | r_start = s - (s % 2**i) 81 | r_end = r_start + (2**i) - 1 82 | 83 | rs = [] 84 | if r_start == s and r_end == e 85 | rs = [[s, e, maxlen - i]] 86 | else 87 | r1, r2 = split_range(r_start, r_end, maxlen - i) 88 | rs = find_start_cidrs(r1, s) + find_end_cidrs(r2, e) 89 | end 90 | 91 | ret = [] 92 | for r in rs 93 | ret.push(cidr_to_str(r[0], r[2], type)) 94 | end 95 | return ret 96 | end 97 | -------------------------------------------------------------------------------- /lib/nicinfo/common_json.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011-2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'nicinfo/config' 16 | require 'nicinfo/nicinfo_logger' 17 | require 'nicinfo/utils' 18 | require 'time' 19 | require 'nicinfo/entity' 20 | 21 | module NicInfo 22 | 23 | def NicInfo.display_object_with_entities object, config, data_node 24 | obj_array = object 25 | unless object.instance_of? Array 26 | obj_array = Array.new 27 | obj_array << object 28 | end 29 | respobjs = ResponseObjSet.new config 30 | obj_array.each do |array_object| 31 | root = array_object.to_node 32 | data_node.add_root( root ) 33 | if !array_object.entities.empty? 34 | NicInfo::add_entity_nodes( array_object.entities, root ) 35 | end 36 | respobjs.add array_object 37 | NicInfo::add_entity_respobjs( array_object.entities, respobjs ) 38 | respobjs.associateEntities array_object.entities 39 | end 40 | data_node.to_normal_log( config.logger, true ) 41 | respobjs.display 42 | end 43 | 44 | def NicInfo.add_entity_nodes entities, node 45 | entities.each do |entity| 46 | entity_node = entity.to_node 47 | node.add_child( entity_node ) 48 | NicInfo::add_entity_nodes( entity.entities, entity_node ) 49 | end if entities 50 | end 51 | 52 | def NicInfo.add_entity_respobjs entities, respobjs 53 | entities.each do |entity| 54 | respobjs.add( entity ) 55 | NicInfo::add_entity_respobjs( entity.entities, respobjs ) 56 | end if entities 57 | end 58 | 59 | # deals with common JSON RDAP structures 60 | class CommonJson 61 | 62 | def initialize config 63 | @config = config 64 | end 65 | 66 | def process_entities objectclass 67 | entities = Array.new 68 | json_entities = NicInfo::get_entitites( objectclass ) 69 | json_entities.each do |json_entity| 70 | entity = @config.factory.new_entity 71 | entity.process( json_entity ) 72 | entities << entity 73 | end if json_entities 74 | return entities 75 | end 76 | 77 | def display_remarks objectclass 78 | remarks = objectclass[ "remarks" ] 79 | if remarks 80 | excessive_notice = @config.factory.new_notices.is_excessive_notice(remarks) 81 | if (excessive_notice && (@config.logger.data_amount != NicInfo::DataAmount::EXTRA_DATA)) 82 | @config.logger.datum "Excessive Remarks", "Use \"-V\" or \"--data extra\" to see them." 83 | else 84 | if remarks.instance_of?(Array) 85 | remarks.each do |remark| 86 | if remark.instance_of?(Hash) 87 | title = remark["title"] 88 | @config.logger.datum "Remarks", "-- #{title} --" if title 89 | descriptions = NicInfo::get_descriptions remark, @config 90 | i = 1 91 | descriptions.each do |line| 92 | if !title && i == 1 93 | @config.logger.datum "Remarks", line 94 | elsif i != 1 || title 95 | @config.logger.datum i.to_s, line 96 | end 97 | i = i + 1 98 | end if descriptions 99 | links = NicInfo::get_links remark, @config 100 | if links 101 | @config.logger.datum "More", NicInfo::get_alternate_link(links) 102 | @config.logger.datum "About", NicInfo::get_about_link(links) 103 | @config.logger.datum "TOS", NicInfo::get_tos_link(links) 104 | @config.logger.datum "(C)", NicInfo::get_copyright_link(links) 105 | @config.logger.datum "License", NicInfo::get_license_link(links) 106 | end 107 | else 108 | @config.conf_msgs << "remark is not an object." 109 | end 110 | end 111 | else 112 | @config.conf_msgs << "'remarks' is not an array." 113 | end 114 | end 115 | end 116 | end 117 | 118 | def display_string_array json_name, display_name, json_data, data_amount 119 | arr = json_data[ json_name ] 120 | if arr 121 | if arr.instance_of?( Array ) 122 | new_arr = Array.new 123 | arr.each do |str| 124 | if str.instance_of?( String ) 125 | new_arr << NicInfo::capitalize( str ) 126 | else 127 | @config.conf_msgs << "value in string array is not a string." 128 | end 129 | end 130 | @config.logger.info data_amount, display_name, new_arr.join( ", " ) 131 | else 132 | @config.conf_msgs << "'#{json_name}' is not an array." 133 | end 134 | end 135 | end 136 | 137 | def display_status objectclass 138 | display_string_array "status", "Status", objectclass, DataAmount::NORMAL_DATA 139 | end 140 | 141 | def display_port43 objectclass 142 | @config.logger.extra "Port 43 Whois", objectclass[ "port43" ] 143 | end 144 | 145 | def display_links cn, objectclass 146 | links = NicInfo::get_links objectclass, @config 147 | if links 148 | @config.logger.extra "Links", "-- for #{cn} --" 149 | @config.logger.extra "Reference", NicInfo::get_self_link( links ) 150 | @config.logger.extra "More", NicInfo::get_alternate_link( links ) 151 | @config.logger.extra "About", NicInfo::get_about_link( links ) 152 | @config.logger.extra "TOS", NicInfo::get_tos_link( links ) 153 | @config.logger.extra "(C)", NicInfo::get_copyright_link( links ) 154 | @config.logger.extra "License", NicInfo::get_license_link( links ) 155 | end 156 | end 157 | 158 | def display_events objectclass 159 | events = objectclass[ "events" ] 160 | if events 161 | if events.instance_of?( Array ) 162 | events.each do |event| 163 | item_name = NicInfo::capitalize( event[ "eventAction" ] ) 164 | item_value = Time.parse( event[ "eventDate" ] ).rfc2822 165 | actor = event[ "eventActor" ] 166 | if actor 167 | item_value << " by #{actor}" 168 | end 169 | @config.logger.datum item_name, item_value 170 | end 171 | else 172 | @config.conf_msgs << "'events' is not an array." 173 | end 174 | end 175 | end 176 | 177 | def display_as_events_actors asEventActors 178 | asEventActors.each do |asEventActor| 179 | item_name = NicInfo::capitalize( asEventActor.eventAction ) 180 | item_value = Time.parse( asEventActor.eventDate ).rfc2822 181 | item_value << " by #{asEventActor.entity_cn}" 182 | @config.logger.datum item_name, item_value 183 | end 184 | end 185 | 186 | def display_public_ids objectclass 187 | public_ids = objectclass[ "publicIds" ] 188 | if public_ids 189 | if public_ids.instance_of?( Array ) 190 | public_ids.each do |public_id| 191 | if public_id.instance_of?( Hash ) 192 | item_name = "Public ID" 193 | item_value = public_id[ "identifier" ] 194 | authority = public_id[ "type" ] 195 | item_value << " (#{authority})" if authority 196 | @config.logger.datum item_name, item_value 197 | else 198 | @config.conf_msgs << "public id in array 'publicIds' is not an object." 199 | end 200 | end 201 | else 202 | @config.conf_msgs << "'publicIds' is not an array." 203 | end 204 | end 205 | end 206 | 207 | def display_simple_links links 208 | if links 209 | if links.instance_of?( Array ) 210 | alternate = NicInfo.get_alternate_link links 211 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, "More", alternate, NicInfo::AttentionType::SECONDARY if alternate 212 | about = NicInfo.get_about_link links 213 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, "About", about, NicInfo::AttentionType::SECONDARY if about 214 | tos = NicInfo.get_tos_link links 215 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, "TOS", tos, NicInfo::AttentionType::SECONDARY if tos 216 | copyright = NicInfo.get_copyright_link links 217 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, "(C)", copyright, NicInfo::AttentionType::SECONDARY if copyright 218 | license = NicInfo.get_license_link links 219 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, "License", license, NicInfo::AttentionType::SECONDARY if license 220 | else 221 | @config.conf_msgs << "'links' is not an array." 222 | end 223 | end 224 | end 225 | 226 | end 227 | 228 | class EventActor 229 | attr_accessor :eventAction, :eventDate, :related, :entity_cn 230 | end 231 | 232 | # for keeping track of objects to display 233 | class ResponseObjSet 234 | 235 | def initialize config 236 | @config = config 237 | @arr = Array.new #for keeping track of insertion order 238 | @set = Hash.new 239 | @self_links = Hash.new 240 | end 241 | 242 | def add respObj 243 | if respObj.instance_of? Array 244 | respObj.each do |obj| 245 | add obj 246 | end 247 | else 248 | if !@set[ respObj.get_cn ] 249 | @set[ respObj.get_cn ] = respObj 250 | @arr << respObj 251 | self_link = NicInfo.get_self_link( NicInfo.get_links( respObj.objectclass, @config ) ) 252 | @self_links[ self_link ] = respObj if self_link 253 | end 254 | end 255 | end 256 | 257 | def display 258 | @arr.each do |object| 259 | object.display 260 | end 261 | end 262 | 263 | def associateEventActor eventActor 264 | return if !eventActor or !eventActor.related 265 | associate = @self_links[ eventActor.related ] 266 | if associate 267 | associate.asEventActors << eventActor 268 | end 269 | end 270 | 271 | def associateEntities entities 272 | entities.each do |entity| 273 | associateEntities entity.entities if !entity.entities.empty? 274 | entity.asEvents.each do |asEvent| 275 | asEvent.entity_cn = entity.get_cn 276 | associateEventActor asEvent 277 | end 278 | end if entities 279 | end 280 | 281 | end 282 | 283 | end 284 | -------------------------------------------------------------------------------- /lib/nicinfo/common_names.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | 16 | module NicInfo 17 | 18 | def NicInfo::is_last_name name 19 | is_name "last-names.txt", name 20 | end 21 | 22 | def NicInfo::is_male_name name 23 | is_name "male-first-names.txt", name 24 | end 25 | 26 | def NicInfo::is_female_name name 27 | is_name "female-first-names.txt", name 28 | end 29 | 30 | def NicInfo::is_name file_name, name 31 | retval = false 32 | name.gsub! '*','' 33 | names = name.split( ' ' ) 34 | 35 | file = File.new( File.join( File.dirname( __FILE__ ) , file_name ), "r" ) 36 | file.each_line do |line| 37 | names.each do |n| 38 | if line.start_with?( n ) 39 | retval = true 40 | break 41 | end 42 | end 43 | end 44 | file.close 45 | 46 | return retval 47 | end 48 | 49 | end 50 | -------------------------------------------------------------------------------- /lib/nicinfo/constants.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014,2015 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | # 16 | # IPv4 and IPv6 regular expressions are credited to Mike Poulson and are found here: 17 | # http://blogs.msdn.com/b/mpoulson/archive/2005/01/10/350037.aspx 18 | 19 | module NicInfo 20 | 21 | VERSION = "1.5.2" 22 | VERSION_LABEL = "NicInfo v." + VERSION 23 | COPYRIGHT = "Copyright (c) 2011-2017 American Registry for Internet Numbers (ARIN)" 24 | CONFIG_VERSION = 4 25 | 26 | # regular expressions 27 | NET_HANDLE_REGEX = /^NET-.*/i 28 | NET6_HANDLE_REGEX = /^NET6-.*/i 29 | AS_REGEX = /^[0-9]{1,10}$/ 30 | ASN_REGEX = /^AS[0-9]{1,20}$/i 31 | IP4_ARPA = /\.in-addr\.arpa[\.]?/i 32 | IP6_ARPA = /\.ip6\.arpa[\.]?/i 33 | DATA_TREE_ADDR_REGEX = /\d=$/ 34 | DOMAIN_REGEX = /^([\S\-]+\.?)+\.([a-z][a-z0\-]+)\.?$/i 35 | DOMAIN_SRCH_REGEX = /^([\S\-]+\.?)+\.([a-z][a-z0\-\*]+)\.?$/i 36 | NS_REGEX = /^ns[0-9]\.([\S\-]+\.?)+\.([a-z][a-z0\-]+)\.?$/i 37 | URL_REGEX = /^(http|https):\/\/.*/ 38 | ENTITY_REGEX = /^.*\-.*/ 39 | 40 | # IPv4 and IPv6 regular expressions are credited to Mike Poulson and are found here: 41 | # http://blogs.msdn.com/b/mpoulson/archive/2005/01/10/350037.aspx 42 | IPV4_REGEX = /\A(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}\z/ 43 | IPV6_REGEX = /\A(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}\z/ 44 | IPV6_HEXCOMPRESS_REGEX = /\A((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)\z/ 45 | 46 | # File Name Constants 47 | LASTTREE_YAML = "lasttree.yaml" 48 | DEMO_DIR = "demo" 49 | BOOTSTRAP_FILE_DIR = "bsfiles" 50 | ASN_BOOTSTRAP = "asn.json" 51 | DNS_BOOTSTRAP = "dns.json" 52 | ENTITY_BOOTSTRAP = "entity.json" 53 | IPV4_BOOTSTRAP = "ipv4.json" 54 | IPV6_BOOTSTRAP = "ipv6.json" 55 | 56 | # JCR Constants 57 | JCR_DIR = "jcr" 58 | RDAP_JCR = "rdap.jcr" 59 | STRICT_RDAP_JCR = "strict.jcr" 60 | JCR_ROOT_ENTITY = "entity_response" 61 | JCR_ROOT_NAMESERVER = "nameserver_response" 62 | JCR_ROOT_DOMAIN = "domain_response" 63 | JCR_ROOT_NETWORK = "network_response" 64 | JCR_ROOT_AUTNUM = "autnum_response" 65 | JCR_ROOT_ERROR = "error_response" 66 | JCR_ROOT_HELP = "help_response" 67 | JCR_ROOT_DOMAIN_SEARCH = "domainSearch_response" 68 | JCR_ROOT_NAMESERVER_SEARCH = "nameserverSearch_response" 69 | JCR_ROOT_ENTITY_SEARCH = "entitySearch_response" 70 | 71 | # Config constants 72 | OUTPUT = "output" 73 | MESSAGES = "messages" 74 | MESSAGES_FILE = "messages_file" 75 | DATA = "data" 76 | DATA_FILE = "data_file" 77 | PAGER = "pager" 78 | AUTO_WRAP = "auto_wrap" 79 | DETECT_WIDTH = "detect_width" 80 | DEFAULT_WIDTH = "default_width" 81 | COLOR_SCHEME = "color_scheme" 82 | CACHE = "cache" 83 | CACHE_EXPIRY = "cache_expiry" 84 | CACHE_EVICTION = "cache_eviction" 85 | USE_CACHE = "use_cache" 86 | CLEAN_CACHE = "clean_cache" 87 | BOOTSTRAP = "bootstrap" 88 | BOOTSTRAP_URL = "bootstrap_url" 89 | HELP_ROOT_URL = "help_root_url" 90 | ENTITY_ROOT_URL = "entity_root_url" 91 | IP_ROOT_URL = "ip_root_url" 92 | AS_ROOT_URL = "as_root_url" 93 | DOMAIN_ROOT_URL = "domain_root_url" 94 | CHECK_BSFILES_AGE = "check_bsfiles_age" 95 | BSFILES_AGE = "bsfiles_age" 96 | UPDATE_BSFILES = "update_bsfiles" 97 | SEARCH = "search" 98 | SUBSTRING = "substring" 99 | CONFIG = "config" 100 | VERSION_CONFIG = "version" 101 | SECURITY = "security" 102 | TRY_INSECURE = "try_insecure" 103 | 104 | # NicInfo values 105 | NICINFO_DEMO_URL = "nicInfo_demoUrl" 106 | NICINFO_DEMO_HINT = "nicInfo_demoHint" 107 | NICINFO_DEMO_ERROR = "nicInfo_demoError" 108 | 109 | # Other constants 110 | RDAP_CONTENT_TYPE = "application/rdap+json" 111 | JSON_CONTENT_TYPE = "application/json" 112 | 113 | DNSSEC_ALGORITHMS = { 114 | 0 => "reserved", 115 | 1 => "RSA/MD5", 116 | 2 => "Diffie-Hellman", 117 | 3 => "DSA/SHA-1", 118 | 4 => "Elliptic Curve", 119 | 5 => "RSA/SHA-1", 120 | 252 => "Indirect", 121 | 253 => "Private DNS", 122 | 254 => "Private OID", 123 | 255 => "reserved" 124 | } 125 | 126 | BSFILE_LAST_CHECK_FILENAME = "_last_check_time.txt" 127 | 128 | end 129 | -------------------------------------------------------------------------------- /lib/nicinfo/data_tree.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | 16 | require 'yaml' 17 | require 'nicinfo/nicinfo_logger' 18 | 19 | module NicInfo 20 | 21 | class DataNode 22 | 23 | attr_accessor :alert, :handle, :rest_ref, :data, :children, :data_type 24 | 25 | def initialize name, handle = nil, rest_ref = nil, data = nil, data_type = nil 26 | @name = name 27 | @children = [] 28 | @data = data 29 | @handle = handle 30 | @rest_ref = rest_ref 31 | @data_type = data_type 32 | end 33 | 34 | def add_child node 35 | @children << node if node 36 | end 37 | 38 | def to_s 39 | @name 40 | end 41 | 42 | def empty? 43 | @children.empty? 44 | end 45 | 46 | def <=> x 47 | @name <=> x.to_s 48 | end 49 | 50 | def has_meta_info 51 | return true if @handle 52 | return true if @rest_ref 53 | return true if @data 54 | return false 55 | end 56 | 57 | end 58 | 59 | class DataTree 60 | 61 | def initialize 62 | @roots = [] 63 | end 64 | 65 | def add_root node 66 | @roots << node if node 67 | end 68 | 69 | def add_child node 70 | add_root( node ) 71 | end 72 | 73 | def add_children_as_root node 74 | node.children.each do |child| 75 | add_root( child ) 76 | end if node 77 | end 78 | 79 | def roots 80 | @roots 81 | end 82 | 83 | def empty? 84 | @roots.empty? 85 | end 86 | 87 | def find_data data_address 88 | node = find_node data_address 89 | return node.data if node 90 | return nil 91 | end 92 | 93 | def find_handle data_address 94 | node = find_node data_address 95 | return node.handle if node 96 | return nil 97 | end 98 | 99 | def find_rest_ref data_address 100 | node = find_node data_address 101 | return node.rest_ref if node 102 | return nil 103 | end 104 | 105 | def find_node data_address 106 | node = NicInfo::DataNode.new( "fakeroot" ) 107 | node.children=roots 108 | data_address.split( /\D/ ).each do |index_str| 109 | index = index_str.to_i - 1 110 | node = node.children[ index ] if node 111 | end 112 | if node != nil 113 | return node 114 | end 115 | #else 116 | return nil 117 | end 118 | 119 | def to_terse_log logger, annotate = false 120 | @logger = logger 121 | @data_amount = DataAmount::TERSE_DATA 122 | to_log( annotate ) 123 | end 124 | 125 | def to_normal_log logger, annotate = false 126 | @logger = logger 127 | @data_amount = DataAmount::NORMAL_DATA 128 | to_log( annotate ) 129 | end 130 | 131 | def to_extra_log logger, annotate = false 132 | @logger = logger 133 | @data_amount = DataAmount::EXTRA_DATA 134 | to_log( annotate ) 135 | end 136 | 137 | private 138 | 139 | def to_log annotate 140 | retval = false 141 | print_tree = false 142 | @roots.each do |root| 143 | print_tree = true unless root.children.empty? 144 | end 145 | num_count = 1 146 | @logger.start_data_item if print_tree 147 | @logger.prose( @data_amount, "[ RESPONSE DATA ]", " ", NicInfo::AttentionType::SUCCESS ) 148 | @roots.each do |root| 149 | if annotate 150 | if root.alert 151 | s = format( " # %s", root.to_s ) 152 | elsif root.has_meta_info 153 | s = format( "%3d= %s", num_count, root.to_s ) 154 | else 155 | s = format( "%3d. %s", num_count, root.to_s ) 156 | end 157 | else 158 | s = root.to_s 159 | end 160 | retval = @logger.log_tree_item( @data_amount, s, NicInfo::AttentionType::SUCCESS ) 161 | if annotate 162 | prefix = " " 163 | child_num = 1 164 | else 165 | prefix = "" 166 | child_num = 0 167 | end 168 | root.children.each do |child| 169 | rprint( child_num, root, child, prefix ) 170 | child_num += 1 if child_num > 0 171 | end if root.children() != nil 172 | num_count += 1 173 | end if print_tree 174 | @logger.end_data_item if print_tree 175 | return retval 176 | end 177 | 178 | def rprint( num, parent, node, prefix ) 179 | if( num > 0 ) 180 | spacer = " " 181 | if node.alert 182 | num_str = format( " # ", num ) 183 | elsif node.has_meta_info 184 | num_str = format( " %d= ", num ) 185 | else 186 | num_str = format( " %d. ", num ) 187 | end 188 | num_str = num_str.rjust( 7, "-" ) 189 | child_num = 1 190 | else 191 | spacer = " " 192 | num_str = "- " 193 | child_num = 0 194 | end 195 | prefix = prefix.tr( "`", " ") + spacer + ( node == parent.children.last ? "`" : "|" ) 196 | @logger.log_tree_item( @data_amount, prefix + num_str + node.to_s, NicInfo::AttentionType::SUCCESS ) 197 | node.children.each do |child| 198 | rprint( child_num, node, child, prefix ) 199 | child_num += 1 if child_num > 0 200 | end if node.children() != nil 201 | end 202 | 203 | end 204 | 205 | end 206 | -------------------------------------------------------------------------------- /lib/nicinfo/demo/autnum.json: -------------------------------------------------------------------------------- 1 | { 2 | "nicInfo_demoUrl":"https://rdap.arin.net/registry/autnum/10", 3 | "nicInfo_demoHint":"nicinfo as10", 4 | "rdapConformance":[ 5 | "rdap_level_0" 6 | ], 7 | "notices":[ 8 | { 9 | "title":"ARIN's RDAP Service", 10 | "description":[ 11 | "ARIN has been a leader in RESTful Whois technologies and is proud to offer the Registration Data Access Protocol service.", 12 | "ARIN's RDAP server is complaint with RDAP Level 0." 13 | ] 14 | }, 15 | { 16 | "title":"Terms of Use", 17 | "description":[ 18 | "ARIN WHOIS data and services are subject to the Terms of Use available at: https://www.arin.net/whois_tou.html" 19 | ], 20 | "links":[ 21 | { 22 | "value":"http://whois.apnic.net/ip/2001:db8::0", 23 | "rel":"terms-of-service", 24 | "type":"text/html", 25 | "href":"https://www.arin.net/whois_tou.html" 26 | } 27 | ] 28 | } 29 | ], 30 | "handle":"AS10-RIR", 31 | "objectClassName":"autnum", 32 | "startAutnum":10, 33 | "endAutnum":15, 34 | "name":"AS-RTR-1", 35 | "description":[ "AS for Exchange" ], 36 | "type":"DIRECT ALLOCATION", 37 | "country":"AU", 38 | "remarks":[ 39 | { 40 | "description":[ 41 | "She sells sea shells down by the sea shore.", 42 | "Originally written by Terry Sullivan." 43 | ] 44 | } 45 | ], 46 | "links":[ 47 | { 48 | "value":"https://rdap.arin.net/registry/autnum/10", 49 | "rel":"self", 50 | "href":"https://rdap.arin.net/registry/autnum/10" 51 | } 52 | ], 53 | "events":[ 54 | { 55 | "eventAction":"registration", 56 | "eventDate":"1990-12-31T23:59:60Z" 57 | }, 58 | { 59 | "eventAction":"last changed", 60 | "eventDate":"1991-12-31T23:59:60Z" 61 | } 62 | ], 63 | "entities":[ 64 | { 65 | "handle":"MATTR-ARIN", 66 | "objectClassName":"entity", 67 | "vcardArray":[ 68 | "vcard", 69 | [ 70 | ["version", {}, "text", "4.0"], 71 | ["fn", {}, "text", "Matt Rowley"], 72 | ["kind", {}, "text", "individual"], 73 | ["org", { 74 | "type":"work" 75 | }, "text", "American Registry for Internet Numbers"], 76 | ["title", {}, "text", "Operations Manager"], 77 | ["role", {}, "text", "Project Lead"], 78 | ["adr", 79 | { 80 | "type":"work" 81 | }, 82 | "text", 83 | [ 84 | "", 85 | "Suite 200", 86 | "3635 Concorde Parkway", 87 | "Chantilly", 88 | "VA", 89 | "20151", 90 | "United States" 91 | ] 92 | ], 93 | ["tel", 94 | { 95 | "type":["work", "voice"], 96 | "pref":"1" 97 | }, 98 | "uri", 99 | "tel:+1-703-227-9840" 100 | ], 101 | ["email", 102 | { 103 | "type":"work" 104 | }, 105 | "text", 106 | "info@arin.net" 107 | ] 108 | ] 109 | ], 110 | "roles":[ "administrative" ], 111 | "remarks":[ 112 | { 113 | "title": "No Solicitations", 114 | "description":[ 115 | "Absolutely no solicitations are accepted at by this contact. If you wish to offer services or products to the American Registry for Internet Numbers, contact Pete Toscano at +1-703-227-9840." 116 | ] 117 | } 118 | ], 119 | "links":[ 120 | { 121 | "value":"http://example.net/entity/MATTR-ARIN", 122 | "rel":"self", 123 | "href":"http://example.net/entity/MATTR-ARIN" 124 | } 125 | ], 126 | "events":[ 127 | { 128 | "eventAction":"registration", 129 | "eventDate":"2012-12-31T23:59:60Z", 130 | "eventActor": "mattr@arin.net" 131 | }, 132 | { 133 | "eventAction":"last changed", 134 | "eventDate":"2013-12-31T23:59:60Z", 135 | "eventActor": "mattr@arin.net" 136 | } 137 | ], 138 | "asEventActor":[ 139 | { 140 | "eventAction":"last changed", 141 | "eventDate":"2013-12-31T23:59:60Z" 142 | } 143 | ] 144 | }, 145 | { 146 | "handle":"MAK21-ARIN", 147 | "objectClassName":"entity", 148 | "vcardArray":[ 149 | "vcard", 150 | [ 151 | ["version", {}, "text", "4.0"], 152 | ["fn", {}, "text", "Mark Kosters"], 153 | ["kind", {}, "text", "individual"], 154 | ["org", { 155 | "type":"work" 156 | }, "text", "American Registry for Internet Numbers"], 157 | ["title", {}, "text", "Chief Technical Officer"], 158 | ["role", {}, "text", "Pointy Haired Boss"], 159 | ["adr", 160 | { 161 | "type":"work", 162 | "label" : "3635 Concorde Parkway\nSuite200\nChantilly\nVA\n20151" 163 | }, 164 | "text", 165 | [ 166 | "", 167 | "", 168 | "", 169 | "", 170 | "", 171 | "", 172 | "" 173 | ] 174 | ], 175 | ["tel", 176 | { 177 | "type":["work", "voice"], 178 | "pref":"1" 179 | }, 180 | "uri", 181 | "tel:+1-703-227-9840" 182 | ], 183 | ["email", 184 | { 185 | "type":"work" 186 | }, 187 | "text", 188 | "info@arin.net" 189 | ] 190 | ] 191 | ], 192 | "roles":[ "technical" ], 193 | "remarks":[ 194 | { 195 | "title": "No Solicitations", 196 | "description":[ 197 | "Absolutely no solicitations are accepted at by this contact. If you wish to offer services or products to the American Registry for Internet Numbers, contact Pete Toscano at +1-703-227-9840." 198 | ] 199 | } 200 | ], 201 | "links":[ 202 | { 203 | "value":"http://example.net/entity/MAK21-ARIN", 204 | "rel":"self", 205 | "href":"http://example.net/entity/MAK21-ARIN" 206 | } 207 | ], 208 | "events":[ 209 | { 210 | "eventAction":"registration", 211 | "eventDate":"2012-12-31T23:59:60Z", 212 | "eventActor": "markk@arin.net" 213 | }, 214 | { 215 | "eventAction":"last changed", 216 | "eventDate":"2013-12-31T23:59:60Z", 217 | "eventActor": "markkb@arin.net" 218 | } 219 | ], 220 | "asEventActor":[ 221 | { 222 | "eventAction":"reregistration", 223 | "eventDate":"2012-12-31T23:59:60Z" 224 | } 225 | ] 226 | } 227 | ] 228 | } 229 | -------------------------------------------------------------------------------- /lib/nicinfo/demo/entity-dnr.json: -------------------------------------------------------------------------------- 1 | { 2 | "nicInfo_demoUrl" : "https://rdap.arin.net/registry/entity/entity-dnr", 3 | "nicInfo_demoHint" : "nicinfo --type entityhandle entity-dnr", 4 | "rdapConformance":[ 5 | "rdap_level_0" 6 | ], 7 | "notices":[ 8 | { 9 | "title":"Terms of Use", 10 | "description":[ 11 | "ARIN WHOIS data and services are subject to the Terms of Use available at: https://www.arin.net/whois_tou.html" 12 | ], 13 | "links":[ 14 | { 15 | "value":"http://whois.apnic.net/ip/2001:db8::0", 16 | "rel":"terms-of-service", 17 | "type":"text/html", 18 | "href":"https://www.arin.net/whois_tou.html" 19 | } 20 | ] 21 | } 22 | ], 23 | "handle":"entity-dnr", 24 | "objectClassName":"entity", 25 | "vcardArray" : [ 26 | "vcard", 27 | [ 28 | ["version", {}, "text", "4.0"], 29 | ["fn", {}, "text", "Simon Perreault"], 30 | ["n", 31 | {}, 32 | "text", 33 | ["Perreault", "Simon", "", "", ["ing. jr", "M.Sc."]] 34 | ], 35 | ["bday", {}, "date-and-or-time", "--02-03"], 36 | ["anniversary", 37 | {}, 38 | "date-and-or-time", 39 | "2009-08-08T14:30:00-05:00" 40 | ], 41 | ["gender", {}, "text", "M"], 42 | ["kind", {}, "text", "individual"], 43 | ["lang", { "pref": "1" }, "language-tag", "fr"], 44 | ["lang", { "pref": "2" }, "language-tag", "en"], 45 | ["org", { "type": "work" }, "text", "Viagenie"], 46 | ["title", {}, "text", "Research Scientist"], 47 | ["role", {}, "text", "Project Lead"], 48 | ["adr", 49 | { "type": "work" }, 50 | "text", 51 | [ 52 | "", 53 | "Suite D2-630", 54 | "2875 Laurier", 55 | "Quebec", 56 | "QC", 57 | "G1V 2M2", 58 | "Canada" 59 | ] 60 | ], 61 | ["adr", 62 | { "type": "home", 63 | "label": "123 Maple Ave\nSuite 90001\nVancouver\nBC\n1239\n"}, 64 | "text", 65 | [ 66 | "", 67 | "", 68 | "", 69 | "", 70 | "", 71 | "", 72 | "" 73 | ] 74 | ], 75 | ["tel", 76 | { "type": ["work", "voice"], "pref": "1" }, 77 | "uri", 78 | "tel:+1-418-656-9254;ext=102" 79 | ], 80 | ["tel", 81 | { "type": ["work", "cell", "voice", "video", "text"] }, 82 | "uri", 83 | "tel:+1-418-262-6501" 84 | ], 85 | ["email", 86 | { "type": "work" }, 87 | "text", 88 | "simon.perreault@viagenie.ca" 89 | ], 90 | ["geo", { "type": "work" }, "uri", "geo:46.772673,-71.282945"], 91 | ["key", 92 | { "type": "work" }, 93 | "uri", 94 | "http://www.viagenie.ca/simon.perreault/simon.asc" 95 | ], 96 | ["tz", {}, "utc-offset", "-05:00"], 97 | ["url", { "type": "home" }, "uri", "http://nomis80.org"] 98 | ] 99 | ], 100 | "status":[ "validated", "locked" ], 101 | "publicIds" : 102 | [ 103 | { 104 | "type": "IANA Registration", 105 | "identifier" : "1" 106 | } 107 | ], 108 | "remarks":[ 109 | { 110 | "title": "A Poem", 111 | "description":[ 112 | "She sells sea shells down by the sea shore.", 113 | "Originally written by Terry Sullivan." 114 | ] 115 | }, 116 | { 117 | "title": "A Story", 118 | "description":[ 119 | "It was the best of times, it was the worst of times, it was the age of wisdom, it was the age of foolishness, it was the epoch of belief, it was the epoch of incredulity, it was the season of Light, it was the season of Darkness, it was the spring of hope, it was the winter of despair, we had everything before us, we had nothing before us, we were all going direct to heaven, we were all going direct the other way - in short, the period was so far like the present period, that some of its noisiest authorities insisted on its being received, for good or for evil, in the superlative degree of comparison only.", 120 | "By Charles Dickens" 121 | ] 122 | } 123 | ], 124 | "links":[ 125 | { 126 | "value":"https://rdap-bootstrap.arin.net/bootstrap/entity/entity-dnr", 127 | "rel":"self", 128 | "href":"https://rdap-bootstrap.arin.net/bootstrap/entity/entity-dnr" 129 | } 130 | ], 131 | "port43":"whois.example.net", 132 | "events":[ 133 | { 134 | "eventAction":"registration", 135 | "eventDate":"1990-12-31T23:59:60Z" 136 | }, 137 | { 138 | "eventAction":"last changed", 139 | "eventDate":"1991-12-31T23:59:60Z", 140 | "eventActor":"joe@bob.com" 141 | } 142 | ] 143 | } 144 | -------------------------------------------------------------------------------- /lib/nicinfo/demo/error-code.json: -------------------------------------------------------------------------------- 1 | { 2 | "nicInfo_demoUrl" : "https://rdap.arin.net/registry/entity/restricted", 3 | "nicInfo_demoHint" : "nicinfo --type entityhandle restricted", 4 | "nicInfo_demoError" : "401", 5 | "rdapConformance":[ 6 | "rdap_level_0" 7 | ], 8 | "notices":[ 9 | { 10 | "title":"Terms of Use", 11 | "description":[ 12 | "THESE are the times that try men's souls. The summer soldier and the sunshine patriot will, in this crisis, shrink from the service of their country; but he that stands by it now, deserves the love and thanks of man and woman. Tyranny, like hell, is not easily conquered; yet we have this consolation with us, that the harder the conflict, the more glorious the triumph.", 13 | "So sayeth Thomas Paine" 14 | ], 15 | "links":[ 16 | { 17 | "value":"https://rdap-bootstrap.arin.net/bootstrap/entity/restricted", 18 | "rel":"terms-of-service", 19 | "type":"text/html", 20 | "href":"http://www.example.com/tos.html" 21 | } 22 | ] 23 | }, 24 | { 25 | "title":"Copyright", 26 | "description":[ 27 | "This test data is Copyright (C) 2015-2018 ARIN." 28 | ], 29 | "links":[ 30 | { 31 | "value":"https://rdap-bootstrap.arin.net/bootstrap/entity/restricted", 32 | "rel":"copyright", 33 | "type":"text/html", 34 | "href":"http://www.example.com/copyright.html" 35 | } 36 | ] 37 | }, 38 | { 39 | "title":"About", 40 | "description":[ 41 | "Questions regarding ARIN's RDAP service should be sent to arin-tech-discuss@arin.net.", 42 | "See our mailing list for more info." 43 | ], 44 | "links":[ 45 | { 46 | "value":"https://rdap-bootstrap.arin.net/bootstrap/entity/restricted", 47 | "rel":"about", 48 | "type":"text/html", 49 | "href":"https://lists.arin.net/mailman/listinfo/arin-tech-discuss" 50 | } 51 | ] 52 | } 53 | ], 54 | "errorCode":418, 55 | "title":"Your beverage choice is not available", 56 | "description":[ 57 | "I know coffee has more ummppphhh.", 58 | "But I cannot provide." 59 | ] 60 | } 61 | -------------------------------------------------------------------------------- /lib/nicinfo/demo/help.json: -------------------------------------------------------------------------------- 1 | { 2 | "nicInfo_demoUrl" : "https://rdap.arin.net/registry/help", 3 | "nicInfo_demoHint" : "nicinfo --type help ns1.xn--fo-5ja.example", 4 | "rdapConformance":[ 5 | "rdap_level_0" 6 | ], 7 | "notices":[ 8 | { 9 | "title":"Terms of Use", 10 | "description":[ 11 | "THESE are the times that try men's souls. The summer soldier and the sunshine patriot will, in this crisis, shrink from the service of their country; but he that stands by it now, deserves the love and thanks of man and woman. Tyranny, like hell, is not easily conquered; yet we have this consolation with us, that the harder the conflict, the more glorious the triumph.", 12 | "So sayeth Thomas Paine" 13 | ], 14 | "links":[ 15 | { 16 | "value":"http://whois.arin.net/nameserver/ns1.xn--fo-5ja.example", 17 | "rel":"terms-of-service", 18 | "type":"text/html", 19 | "href":"http://www.example.com/tos.html" 20 | } 21 | ] 22 | }, 23 | { 24 | "title":"Authorization Policy", 25 | "description":[ 26 | "Access to all data of these services are restricted. Follow the instructions below to receive full access.", 27 | "The first step is to submit your fingerprints for criminal analysis. Once it has been determined that you are a criminal, a criminal questionaire will be mailed to you.", 28 | "Fill out the criminal questionaire and send it back. It must be mailed with a postage paid envelope and a check for $1M. Upon acceptance, you will receive your credentials in the mail." 29 | ], 30 | "links":[ 31 | { 32 | "value":"http://whois.arin.net/nameserver/ns1.xn--fo-5ja.example", 33 | "rel":"about", 34 | "type":"text/html", 35 | "href":"http://www.example.com/auth.html" 36 | } 37 | ] 38 | }, 39 | { 40 | "title":"Rhetorical License", 41 | "description":[ 42 | "Lorem ipsum dolor sit amet, has reque blandit recusabo ex, id cibo epicuri erroribus pri. Qui epicurei facilisis deseruisse at. Posse fierent persecuti mei te, ut vix lucilius expetenda. Quo ei inani minimum. In cum delenit definiebas, et dico case delicata vim, mei unum feugiat suscipiantur et. Sale soluta democritum ea eum.", 43 | "Quo at diam fabulas. Cum dicant electram eu, his at graeco maiorum omittantur, numquam abhorreant instructior ad est. Legendos similique sea ei, fabellas voluptaria sed eu, pro et oblique utroque. Mea ornatus sapientem ex. Etiam gubergren eam id, eum id possit deleniti electram, dicat philosophia sed eu.", 44 | "Ut vis dicunt laboramus, vis dolorem nostrum at. Vix suas nihil nostrud an, te his tation placerat luptatum, no minim nobis sea. Cum cu congue platonem hendrerit. Ex sint dolor constituam per, per an novum qualisque, rebum prompta ius ex. Nec in fabellas referrentur, quot dicit veniam has at, mea fuisset denique ut. Ut justo munere sed, facilisis efficiendi ei has.", 45 | "Eros alterum oporteat nec ut, iriure malorum hendrerit ne est. Ius aliquam mandamus id, sea in vide soleat reprehendunt, has officiis maluisset prodesset cu. No qui dolore putent, ea veniam appetere persecuti mei, an eam tamquam delicata. Laoreet appetere scripserit mei eu, usu elit indoctum ex, error homero erroribus pro at. Cum an epicuri omittam conceptam. Ad tota utamur vix, illum eleifend efficiendi per ne.", 46 | "Meliore vivendo concludaturque in pro, congue dictas usu at, ei viris assueverit mea. Veri rebum dicant no mea, ea facer altera mentitum sit. Eros sale reprimique id duo, graeco invenire ex eos, has affert munere bonorum te. Fuisset corpora eu pri. Aliquid sensibus duo id, mea assum maiestatis ad, integre accommodare eum no." 47 | ], 48 | "links":[ 49 | { 50 | "value":"http://whois.arin.net/nameserver/ns1.xn--fo-5ja.example", 51 | "rel":"license", 52 | "type":"text/html", 53 | "href":"http://www.example.com/license.html" 54 | } 55 | ] 56 | } 57 | ] 58 | } 59 | -------------------------------------------------------------------------------- /lib/nicinfo/demo/ns-simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "nicInfo_demoUrl" : "https://rdap.arin.net/registry/nameserver/ns2.example.example", 3 | "nicInfo_demoHint" : "nicinfo ns2.example.example", 4 | "rdapConformance":[ 5 | "rdap_level_0" 6 | ], 7 | "notices":[ 8 | { 9 | "title":"Content Redacted", 10 | "description":[ 11 | "Without full authorization, content has been redacted.", 12 | "Sorry, dude!" 13 | ], 14 | "links":[ 15 | { 16 | "value":"http://example.net/ip/192.0.2.0/24", 17 | "rel":"alternate", 18 | "type":"text/html", 19 | "href":"http://www.example.com/redaction_policy.html" 20 | } 21 | ] 22 | }, 23 | { 24 | "title":"Terms of Use", 25 | "description":[ 26 | "THESE are the times that try men's souls. The summer soldier and the sunshine patriot will, in this crisis, shrink from the service of their country; but he that stands by it now, deserves the love and thanks of man and woman. Tyranny, like hell, is not easily conquered; yet we have this consolation with us, that the harder the conflict, the more glorious the triumph.", 27 | "So sayeth Thomas Paine" 28 | ], 29 | "links":[ 30 | { 31 | "value":"http://example.net/ip/192.0.2.0/24", 32 | "rel":"terms-of-service", 33 | "type":"text/html", 34 | "href":"http://www.example.com/tos.html" 35 | } 36 | ] 37 | } 38 | ], 39 | "handle" : "NS2.EXAMPLE.COM-01", 40 | "objectClassName":"nameserver", 41 | "ldhName":"ns2.example.com", 42 | "ipAddresses":{ 43 | "v6":[ "2001:db8::123", "2001:db8::124" ] 44 | }, 45 | "entities":[ 46 | { 47 | "handle":"MATTR-ARIN", 48 | "objectClassName":"entity", 49 | "vcardArray":[ 50 | "vcard", 51 | [ 52 | ["version", {}, "text", "4.0"], 53 | ["fn", {}, "text", "Matt Rowley"], 54 | ["kind", {}, "text", "individual"], 55 | ["org", { 56 | "type":"work" 57 | }, "text", "American Registry for Internet Numbers"], 58 | ["title", {}, "text", "Operations Manager"], 59 | ["role", {}, "text", "Project Lead"], 60 | ["adr", 61 | { 62 | "type":"work" 63 | }, 64 | "text", 65 | [ 66 | "", 67 | "Suite 200", 68 | "3635 Concorde Parkway", 69 | "Chantilly", 70 | "VA", 71 | "20151", 72 | "United States" 73 | ] 74 | ], 75 | ["tel", 76 | { 77 | "type":["work", "voice"], 78 | "pref":"1" 79 | }, 80 | "uri", 81 | "tel:+1-703-227-9840" 82 | ], 83 | ["email", 84 | { 85 | "type":"work" 86 | }, 87 | "text", 88 | "info@arin.net" 89 | ] 90 | ] 91 | ], 92 | "roles":[ "administrative" ], 93 | "remarks":[ 94 | { 95 | "title": "No Solicitations", 96 | "description":[ 97 | "Absolutely no solicitations are accepted at by this contact. If you wish to offer services or products to the American Registry for Internet Numbers, contact Pete Toscano at +1-703-227-9840." 98 | ] 99 | } 100 | ], 101 | "links":[ 102 | { 103 | "value":"http://example.net/entity/MATTR-ARIN", 104 | "rel":"self", 105 | "href":"http://example.net/entity/MATTR-ARIN" 106 | } 107 | ], 108 | "events":[ 109 | { 110 | "eventAction":"registration", 111 | "eventDate":"2012-12-31T23:59:60Z", 112 | "eventActor": "mattr@arin.net" 113 | }, 114 | { 115 | "eventAction":"last changed", 116 | "eventDate":"2013-12-31T23:59:60Z", 117 | "eventActor": "mattr@arin.net" 118 | } 119 | ], 120 | "asEventActor":[ 121 | { 122 | "eventAction":"last changed", 123 | "eventDate":"2013-12-31T23:59:60Z" 124 | } 125 | ] 126 | }, 127 | { 128 | "handle":"MAK21-ARIN", 129 | "objectClassName":"entity", 130 | "vcardArray":[ 131 | "vcard", 132 | [ 133 | ["version", {}, "text", "4.0"], 134 | ["fn", {}, "text", "Mark Kosters"], 135 | ["kind", {}, "text", "individual"], 136 | ["org", { 137 | "type":"work" 138 | }, "text", "American Registry for Internet Numbers"], 139 | ["title", {}, "text", "Chief Technical Officer"], 140 | ["role", {}, "text", "Pointy Haired Boss"], 141 | ["adr", 142 | { 143 | "type":"work", 144 | "label" : "3635 Concorde Parkway\nSuite200\nChantilly\nVA\n20151" 145 | }, 146 | "text", 147 | [ 148 | "", 149 | "", 150 | "", 151 | "", 152 | "", 153 | "", 154 | "" 155 | ] 156 | ], 157 | ["tel", 158 | { 159 | "type":["work", "voice"], 160 | "pref":"1" 161 | }, 162 | "uri", 163 | "tel:+1-703-227-9840" 164 | ], 165 | ["email", 166 | { 167 | "type":"work" 168 | }, 169 | "text", 170 | "info@arin.net" 171 | ] 172 | ] 173 | ], 174 | "roles":[ "technical" ], 175 | "remarks":[ 176 | { 177 | "title": "No Solicitations", 178 | "description":[ 179 | "Absolutely no solicitations are accepted at by this contact. If you wish to offer services or products to the American Registry for Internet Numbers, contact Pete Toscano at +1-703-227-9840." 180 | ] 181 | } 182 | ], 183 | "links":[ 184 | { 185 | "value":"http://example.net/entity/MAK21-ARIN", 186 | "rel":"self", 187 | "href":"http://example.net/entity/MAK21-ARIN" 188 | } 189 | ], 190 | "events":[ 191 | { 192 | "eventAction":"registration", 193 | "eventDate":"2012-12-31T23:59:60Z", 194 | "eventActor": "markk@arin.net" 195 | }, 196 | { 197 | "eventAction":"last changed", 198 | "eventDate":"2013-12-31T23:59:60Z", 199 | "eventActor": "markkb@arin.net" 200 | } 201 | ], 202 | "asEventActor":[ 203 | { 204 | "eventAction":"reregistration", 205 | "eventDate":"2012-12-31T23:59:60Z" 206 | } 207 | ] 208 | } 209 | ] 210 | } 211 | -------------------------------------------------------------------------------- /lib/nicinfo/demo/ns-very-simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "nicInfo_demoUrl" : "https://rdap.arin.net/registry/nameserver/ns1.example.example", 3 | "nicInfo_demoHint" : "nicinfo ns1.example.example", 4 | "rdapConformance":[ 5 | "rdap_level_0" 6 | ], 7 | "notices":[ 8 | { 9 | "title":"Content Redacted", 10 | "description":[ 11 | "Without full authorization, content has been redacted.", 12 | "Sorry, dude!" 13 | ], 14 | "links":[ 15 | { 16 | "value":"http://example.net/ip/192.0.2.0/24", 17 | "rel":"alternate", 18 | "type":"text/html", 19 | "href":"http://www.example.com/redaction_policy.html" 20 | } 21 | ] 22 | }, 23 | { 24 | "title":"Terms of Use", 25 | "description":[ 26 | "THESE are the times that try men's souls. The summer soldier and the sunshine patriot will, in this crisis, shrink from the service of their country; but he that stands by it now, deserves the love and thanks of man and woman. Tyranny, like hell, is not easily conquered; yet we have this consolation with us, that the harder the conflict, the more glorious the triumph.", 27 | "So sayeth Thomas Paine" 28 | ], 29 | "links":[ 30 | { 31 | "value":"http://example.net/ip/192.0.2.0/24", 32 | "rel":"terms-of-service", 33 | "type":"text/html", 34 | "href":"http://www.example.com/tos.html" 35 | } 36 | ] 37 | } 38 | ], 39 | "ldhName":"ns1.example.com", 40 | "objectClassName":"nameserver" 41 | } 42 | -------------------------------------------------------------------------------- /lib/nicinfo/demo/ns.json: -------------------------------------------------------------------------------- 1 | { 2 | "nicInfo_demoUrl" : "https://rdap.arin.net/registry/nameserver/ns1.xn--fo-5ja.example", 3 | "nicInfo_demoHint" : "nicinfo ns1.xn--fo-5ja.example", 4 | "rdapConformance":[ 5 | "rdap_level_0" 6 | ], 7 | "notices":[ 8 | { 9 | "title":"Rhetorical License", 10 | "description":[ 11 | "Lorem ipsum dolor sit amet, has reque blandit recusabo ex, id cibo epicuri erroribus pri. Qui epicurei facilisis deseruisse at. Posse fierent persecuti mei te, ut vix lucilius expetenda. Quo ei inani minimum. In cum delenit definiebas, et dico case delicata vim, mei unum feugiat suscipiantur et. Sale soluta democritum ea eum.", 12 | "Quo at diam fabulas. Cum dicant electram eu, his at graeco maiorum omittantur, numquam abhorreant instructior ad est. Legendos similique sea ei, fabellas voluptaria sed eu, pro et oblique utroque. Mea ornatus sapientem ex. Etiam gubergren eam id, eum id possit deleniti electram, dicat philosophia sed eu.", 13 | "Ut vis dicunt laboramus, vis dolorem nostrum at. Vix suas nihil nostrud an, te his tation placerat luptatum, no minim nobis sea. Cum cu congue platonem hendrerit. Ex sint dolor constituam per, per an novum qualisque, rebum prompta ius ex. Nec in fabellas referrentur, quot dicit veniam has at, mea fuisset denique ut. Ut justo munere sed, facilisis efficiendi ei has.", 14 | "Eros alterum oporteat nec ut, iriure malorum hendrerit ne est. Ius aliquam mandamus id, sea in vide soleat reprehendunt, has officiis maluisset prodesset cu. No qui dolore putent, ea veniam appetere persecuti mei, an eam tamquam delicata. Laoreet appetere scripserit mei eu, usu elit indoctum ex, error homero erroribus pro at. Cum an epicuri omittam conceptam. Ad tota utamur vix, illum eleifend efficiendi per ne.", 15 | "Meliore vivendo concludaturque in pro, congue dictas usu at, ei viris assueverit mea. Veri rebum dicant no mea, ea facer altera mentitum sit. Eros sale reprimique id duo, graeco invenire ex eos, has affert munere bonorum te. Fuisset corpora eu pri. Aliquid sensibus duo id, mea assum maiestatis ad, integre accommodare eum no." 16 | ], 17 | "links":[ 18 | { 19 | "value":"http://example.net/ip/192.0.2.0/24", 20 | "rel":"license", 21 | "type":"text/html", 22 | "href":"http://www.example.com/license.html" 23 | } 24 | ] 25 | } 26 | ], 27 | "handle":"XXXX", 28 | "objectClassName":"nameserver", 29 | "ldhName":"ns1.xn--fo-5ja.example", 30 | "unicodeName":"ns1.foo.example", 31 | "status":[ "active" ], 32 | "ipAddresses":{ 33 | "v4":[ "192.0.2.1", "192.0.2.2" ], 34 | "v6":[ "2001:db8::123" ] 35 | }, 36 | "remarks":[ 37 | { 38 | "description":[ 39 | "She sells sea shells down by the sea shore.", 40 | "Originally written by Terry Sullivan." 41 | ] 42 | } 43 | ], 44 | "links":[ 45 | { 46 | "value":"https://rdap-bootstrap.arin.net/bootstrap/nameserver/ns1.xn--fo-5ja.example", 47 | "rel":"self", 48 | "href":"https://rdap-bootstrap.arin.net/bootstrap/nameserver/ns1.xn--fo-5ja.example" 49 | } 50 | ], 51 | "port43":"whois.example.net", 52 | "events":[ 53 | { 54 | "eventAction":"registration", 55 | "eventDate":"1990-12-31T23:59:60Z" 56 | }, 57 | { 58 | "eventAction":"last changed", 59 | "eventDate":"1991-12-31T23:59:60Z", 60 | "eventActor":"joe@bob.com" 61 | } 62 | ] 63 | } 64 | -------------------------------------------------------------------------------- /lib/nicinfo/demo/simple-ip.json: -------------------------------------------------------------------------------- 1 | { 2 | "nicInfo_demoUrl" : "https://rdap.arin.net/registry/ip/192.0.2.0/24", 3 | "nicInfo_demoHint" : "nicinfo 192.0.2.0/24", 4 | "rdapConformance":[ 5 | "rdap_level_0" 6 | ], 7 | "notices":[ 8 | { 9 | "title":"Content Redacted", 10 | "description":[ 11 | "Without full authorization, content has been redacted.", 12 | "Sorry, dude!" 13 | ], 14 | "links":[ 15 | { 16 | "value":"http://example.net/ip/192.0.2.0/24", 17 | "rel":"alternate", 18 | "type":"text/html", 19 | "href":"http://www.example.com/redaction_policy.html" 20 | } 21 | ] 22 | } 23 | ], 24 | "lang":"en", 25 | "startAddress":"192.0.2.0", 26 | "endAddress":"192.0.2.255", 27 | "handle":"XXXX-RIR", 28 | "objectClassName":"ip network", 29 | "ipVersion":"v4", 30 | "name":"NET-RTR-1", 31 | "description":[ "A network used for example documentation" ], 32 | "parentHandle":"YYYY-RIR", 33 | "remarks":[ 34 | { 35 | "description":[ 36 | "She sells sea shells down by the sea shore.", 37 | "Originally written by Terry Sullivan." 38 | ] 39 | } 40 | ] 41 | } 42 | -------------------------------------------------------------------------------- /lib/nicinfo/demo/simple.json: -------------------------------------------------------------------------------- 1 | { 2 | "nicInfo_demoUrl" : "https://rdap.arin.net/registry/entity/ABC123", 3 | "nicInfo_demoHint" : "nicinfo --type entityhandle ABC123", 4 | "handle":"ABC123", 5 | "remarks":[ 6 | { 7 | "description":[ 8 | "She sells sea shells down by the sea shore.", 9 | "Originally written by Terry Sullivan." 10 | ] 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /lib/nicinfo/domain.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'nicinfo/config' 16 | require 'nicinfo/nicinfo_logger' 17 | require 'nicinfo/utils' 18 | require 'nicinfo/common_json' 19 | require 'nicinfo/entity' 20 | require 'nicinfo/ns' 21 | require 'nicinfo/ds_data' 22 | require 'nicinfo/key_data' 23 | require 'nicinfo/data_tree' 24 | 25 | module NicInfo 26 | 27 | def NicInfo.display_domain json_data, config, data_node 28 | obj_array = json_data 29 | unless json_data.instance_of? Array 30 | obj_array = Array.new 31 | obj_array << json_data 32 | end 33 | respObjs = ResponseObjSet.new config 34 | obj_array.each do |array_object| 35 | domain = config.factory.new_domain.process( array_object ) 36 | root = domain.to_node 37 | data_node.add_root( root ) 38 | if !domain.entities.empty? or !domain.nameservers.empty? 39 | domain.ds_data_objs.each do |ds| 40 | ds_node = ds.to_node 41 | root.add_child( ds_node ) 42 | end 43 | domain.key_data_objs.each do |key| 44 | key_node = key.to_node 45 | root.add_child( key_node ) 46 | end 47 | NicInfo::add_entity_nodes( domain.entities, root ) 48 | domain.nameservers.each do |ns| 49 | ns_node = ns.to_node 50 | root.add_child( ns_node ) 51 | NicInfo::add_entity_nodes( ns.entities, ns_node ) 52 | end 53 | end 54 | if domain.network 55 | net_node = domain.network.to_node 56 | root.add_child net_node 57 | NicInfo::add_entity_nodes( domain.network.entities, net_node ) 58 | end 59 | respObjs.add domain 60 | domain.ds_data_objs.each do |ds| 61 | respObjs.add ds 62 | end 63 | domain.key_data_objs.each do |key| 64 | respObjs.add key 65 | end 66 | NicInfo::add_entity_respobjs( domain.entities, respObjs ) 67 | respObjs.associateEntities domain.entities 68 | domain.nameservers.each do |ns| 69 | respObjs.add ns 70 | NicInfo::add_entity_respobjs( ns.entities, respObjs ) 71 | respObjs.associateEntities ns.entities 72 | end 73 | if domain.network 74 | respObjs.add domain.network 75 | NicInfo::add_entity_respobjs( domain.network.entities, respObjs ) 76 | end 77 | end 78 | data_node.to_normal_log( config.logger, true ) 79 | respObjs.display 80 | end 81 | 82 | def NicInfo.display_domains json_data, config, data_tree 83 | domain_array = json_data[ "domainSearchResults" ] 84 | if domain_array != nil 85 | if domain_array.instance_of? Array 86 | NicInfo.display_domain( domain_array, config, data_tree ) 87 | else 88 | config.conf_msgs << "'domainSearchResults' is not an array" 89 | end 90 | else 91 | config.conf_msgs << "'domainSearchResults' is not present" 92 | end 93 | end 94 | 95 | # deals with RDAP nameserver structures 96 | class Domain 97 | 98 | attr_accessor :entities, :nameservers, :ds_data_objs, :key_data_objs, :objectclass, :asEventActors, :network 99 | 100 | def initialize config 101 | @config = config 102 | @common = CommonJson.new config 103 | @entities = Array.new 104 | @asEventActors = Array.new 105 | @nameservers = Array.new 106 | @ds_data_objs = Array.new 107 | @key_data_objs = Array.new 108 | end 109 | 110 | def process json_data 111 | @objectclass = json_data 112 | @entities = @common.process_entities @objectclass 113 | json_nses = NicInfo::get_nameservers json_data 114 | json_nses.each do |json_ns| 115 | ns = @config.factory.new_ns 116 | ns.process( json_ns ) 117 | @nameservers << ns 118 | end if json_nses 119 | json_net = NicInfo::get_network json_data 120 | if json_net 121 | ip = @config.factory.new_ip 122 | ip.process json_net 123 | @network = ip 124 | end 125 | json_ds_data_objs = NicInfo::get_ds_data_objs @objectclass 126 | json_ds_data_objs.each do |json_ds| 127 | dsData = DsData.new( @config ) 128 | dsData.process( json_ds ) 129 | @ds_data_objs << dsData 130 | end if json_ds_data_objs 131 | json_key_data_objs = NicInfo::get_key_data_objs @objectclass 132 | json_key_data_objs.each do |json_key| 133 | keyData = KeyData.new( @config ) 134 | keyData.process( json_key ) 135 | @key_data_objs << keyData 136 | end if json_key_data_objs 137 | return self 138 | end 139 | 140 | def display 141 | @config.logger.start_data_item 142 | @config.logger.data_title "[ DOMAIN ]" 143 | @config.logger.terse "Handle", NicInfo::get_handle( @objectclass ), NicInfo::AttentionType::SUCCESS 144 | @config.logger.extra "Object Class Name", NicInfo::get_object_class_name( @objectclass, "domain", @config ) 145 | @config.logger.terse "Domain Name", NicInfo::get_ldhName( @objectclass ), NicInfo::AttentionType::SUCCESS 146 | @config.logger.datum "I18N Domain Name", NicInfo::get_unicodeName( @objectclass ), NicInfo::AttentionType::SUCCESS 147 | variants = @objectclass[ "variants" ] 148 | variant_no = 1 149 | variants.each do |variant| 150 | relation = variant[ "relation" ] 151 | item_value = "" 152 | if relation 153 | arr = Array.new 154 | relation.each do |rel| 155 | arr << NicInfo.capitalize( rel ) 156 | end 157 | item_value = arr.join( ", " ) 158 | end 159 | @config.logger.extra "Variant #{variant_no}", item_value 160 | @config.logger.extra "IDN Table", variant[ "idnTable" ] 161 | variant_names = variant[ "variantNames" ] 162 | variant_names.each do |variant_name| 163 | @config.logger.extra "Variant Domain", NicInfo::get_ldhName( variant_name ) 164 | @config.logger.extra "Variant IDN", NicInfo::get_unicodeName( variant_name ) 165 | end if variant_names 166 | variant_no = variant_no + 1 167 | end if variants 168 | @common.display_public_ids @objectclass 169 | @common.display_status @objectclass 170 | @common.display_events @objectclass 171 | @common.display_as_events_actors @asEventActors 172 | @common.display_port43 @objectclass 173 | @common.display_remarks @objectclass 174 | @common.display_links( get_cn, @objectclass ) 175 | secure_dns = NicInfo::get_secure_dns( @objectclass ) 176 | if secure_dns.instance_of? Array 177 | secure_dns = secure_dns[ 0 ] 178 | end 179 | if secure_dns 180 | @config.logger.terse "Zone Signed", secure_dns[ "zoneSigned" ] 181 | @config.logger.terse "Delegation Signed", secure_dns[ "delegationSigned" ] 182 | @config.logger.terse "Max Signature Life", secure_dns[ "maxSigLife" ] 183 | end 184 | @config.logger.end_data_item 185 | end 186 | 187 | def get_cn 188 | handle = NicInfo::get_handle @objectclass 189 | handle = NicInfo::get_ldhName @objectclass if !handle 190 | handle = "(unidentifiable domain #{object_id})" if !handle 191 | if (name = NicInfo::get_ldhName( @objectclass ) ) != nil 192 | return "#{name} ( #{handle} )" 193 | end 194 | return handle 195 | end 196 | 197 | def to_node 198 | DataNode.new( get_cn, nil, NicInfo::get_self_link( NicInfo::get_links( @objectclass, @config ) ) ) 199 | end 200 | 201 | end 202 | 203 | end 204 | -------------------------------------------------------------------------------- /lib/nicinfo/ds_data.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'nicinfo/config' 16 | require 'nicinfo/nicinfo_logger' 17 | require 'nicinfo/utils' 18 | require 'nicinfo/common_json' 19 | require 'nicinfo/data_tree' 20 | 21 | module NicInfo 22 | 23 | def NicInfo.display_ds_data json_data, config, data_node 24 | ds_data = DsData.new( config ).process( json_data ).display 25 | end 26 | 27 | # deals with RDAP ds_data structures 28 | class DsData 29 | 30 | attr_accessor :objectclass, :asEventActors 31 | 32 | def initialize config 33 | @config = config 34 | @common = CommonJson.new config 35 | @asEventActors = Array.new 36 | end 37 | 38 | def process json_data 39 | @objectclass = json_data 40 | return self 41 | end 42 | 43 | def display 44 | @config.logger.start_data_item 45 | @config.logger.data_title "[ DELEGATION SIGNER ]" 46 | @config.logger.terse "Algorithm", NicInfo::get_algorithm( @objectclass ) 47 | @config.logger.terse "Digest", @objectclass[ "digest" ] 48 | @config.logger.terse "Digest Type", @objectclass[ "digestType" ] 49 | @config.logger.terse "Key Tag", @objectclass[ "keyTag" ] 50 | @common.display_events @objectclass 51 | @common.display_as_events_actors @asEventActors 52 | @config.logger.end_data_item 53 | end 54 | 55 | def get_cn 56 | algorithm = NicInfo::DNSSEC_ALGORITHMS[ NicInfo::get_algorithm( @objectclass ) ] 57 | algorithm = algorithm + " DS Data" if algorithm 58 | algorithm = "(unidentifiable DS data #{object_id})" if !algorithm 59 | return algorithm 60 | end 61 | 62 | def to_node 63 | node = DataNode.new( get_cn, nil, NicInfo::get_self_link( NicInfo::get_links( @objectclass, @config ) ) ) 64 | node.data_type=self.class.name 65 | return node 66 | end 67 | 68 | end 69 | 70 | end 71 | -------------------------------------------------------------------------------- /lib/nicinfo/enum.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | 16 | # Code based on "Enumerations and Ruby" 17 | # http://www.rubyfleebie.com/enumerations-and-ruby/ 18 | 19 | module NicInfo 20 | 21 | # A base class for enumerations 22 | class Enum 23 | 24 | def Enum.add_item( key, value ) 25 | @hash ||= {} 26 | @hash[ key ] = value 27 | end 28 | 29 | def Enum.const_missing( key ) 30 | @hash[ key ] 31 | end 32 | 33 | def Enum.each 34 | @hash.each { |key,value| yield( key, value ) } 35 | end 36 | 37 | def Enum.has_value? value 38 | @hash.value?( value ) 39 | end 40 | 41 | def Enum.values 42 | @hash.values 43 | end 44 | 45 | end 46 | 47 | end 48 | -------------------------------------------------------------------------------- /lib/nicinfo/error_code.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'nicinfo/config' 16 | require 'nicinfo/nicinfo_logger' 17 | require 'nicinfo/utils' 18 | require 'nicinfo/common_json' 19 | 20 | module NicInfo 21 | 22 | # deals with RDAP error code structures 23 | class ErrorCode 24 | 25 | attr_accessor :config 26 | 27 | def initialize( config ) 28 | @config = config 29 | @common = CommonJson.new( config ) 30 | end 31 | 32 | def display_error_code ec 33 | @config.logger.start_data_item 34 | title = ec[ "title" ] 35 | if title == nil 36 | title = "" 37 | end 38 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, "[ ERROR ]", title, NicInfo::AttentionType::ERROR 39 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, "Code", ec[ "errorCode" ] 40 | description = ec[ "description" ] 41 | i = 1 42 | description.each do |line| 43 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, i.to_s, line 44 | i = i + 1 45 | end 46 | links = ec[ "links" ] 47 | @common.display_simple_links( links ) 48 | @config.logger.end_data_item 49 | end 50 | 51 | end 52 | 53 | end 54 | -------------------------------------------------------------------------------- /lib/nicinfo/factory.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | module NicInfo 16 | 17 | # Creates objects we want to mock 18 | class Factory 19 | 20 | attr_accessor :config 21 | 22 | def initialize( config ) 23 | @config = config 24 | end 25 | 26 | def new_error_code 27 | return ErrorCode.new( config ) 28 | end 29 | 30 | def new_autnum 31 | return Autnum.new( config ) 32 | end 33 | 34 | def new_domain 35 | return Domain.new( config ) 36 | end 37 | 38 | def new_entity 39 | return Entity.new( config ) 40 | end 41 | 42 | def new_ip 43 | return Ip.new( config ) 44 | end 45 | 46 | def new_notices 47 | return Notices.new( config ) 48 | end 49 | 50 | def new_ns 51 | return Ns.new( config ) 52 | end 53 | 54 | end 55 | 56 | end 57 | -------------------------------------------------------------------------------- /lib/nicinfo/ip.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011-2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'netaddr' 16 | 17 | require 'nicinfo/config' 18 | require 'nicinfo/nicinfo_logger' 19 | require 'nicinfo/utils' 20 | require 'nicinfo/common_json' 21 | require 'nicinfo/entity' 22 | require 'nicinfo/data_tree' 23 | require 'nicinfo/cidrs' 24 | 25 | module NicInfo 26 | 27 | def NicInfo.display_ip json_data, config, data_tree 28 | ip = config.factory.new_ip.process( json_data ) 29 | NicInfo::display_object_with_entities( ip, config, data_tree ) 30 | end 31 | 32 | # deals with RDAP IP network structures 33 | class Ip 34 | 35 | attr_accessor :entities, :objectclass, :asEventActors 36 | 37 | def initialize config 38 | @config = config 39 | @common = CommonJson.new config 40 | @entities = Array.new 41 | @asEventActors = Array.new 42 | end 43 | 44 | def process json_data 45 | @objectclass = json_data 46 | @entities = @common.process_entities @objectclass 47 | return self 48 | end 49 | 50 | def display 51 | @config.logger.start_data_item 52 | @config.logger.data_title "[ IP NETWORK ]" 53 | @config.logger.terse "Handle", NicInfo::get_handle( @objectclass ), NicInfo::AttentionType::SUCCESS 54 | @config.logger.extra "Object Class Name", NicInfo::get_object_class_name( @objectclass, "ip network", @config ) 55 | start_addr = NicInfo.get_startAddress( @objectclass ) 56 | if start_addr.include?( '/' ) 57 | @config.conf_msgs << "start IP #{start_addr} is not an IP address (possibly a CIDR)" 58 | end 59 | @config.logger.terse "Start Address", start_addr , NicInfo::AttentionType::SUCCESS 60 | end_addr = NicInfo.get_endAddress( @objectclass ) 61 | if end_addr.include?( '/' ) 62 | @config.conf_msgs << "end IP #{end_addr} is not an IP address (possibly a CIDR)" 63 | end 64 | @config.logger.terse "End Address", end_addr, NicInfo::AttentionType::SUCCESS 65 | @config.logger.terse "CIDRs", get_CIDRs 66 | @config.logger.datum "IP Version", @objectclass[ "ipVersion" ] 67 | @config.logger.extra "Name", NicInfo.get_name( @objectclass ) 68 | @config.logger.terse "Country", NicInfo.get_country( @objectclass ) 69 | @config.logger.datum "Type", NicInfo.get_type( @objectclass ) 70 | @config.logger.extra "Parent Handle", @objectclass[ "parentHandle" ] 71 | @common.display_status @objectclass 72 | @common.display_events @objectclass 73 | @common.display_as_events_actors @asEventActors 74 | @common.display_remarks @objectclass 75 | @common.display_links( get_cn, @objectclass ) 76 | @config.logger.end_data_item 77 | end 78 | 79 | def get_cn 80 | handle = NicInfo::get_handle @objectclass 81 | if !handle 82 | startAddress = NicInfo.get_startAddress @objectclass 83 | handle << startAddress if startAddress 84 | endAddress = NicInfo.get_endAddress @objectclass 85 | handle << " - " if startAddress and endAddress 86 | handle << endAddress if endAddress 87 | end 88 | return handle if handle 89 | return "(unidentifiable network #{object_id})" 90 | end 91 | 92 | def get_CIDRs 93 | startAddress = NicInfo.get_startAddress @objectclass 94 | endAddress = NicInfo.get_endAddress @objectclass 95 | if startAddress and endAddress 96 | cidrs = find_cidrs(startAddress, endAddress) 97 | return cidrs.join(', ') 98 | elsif startAddress 99 | return NetAddr::CIDR.create(startAddress).to_s 100 | elsif endAddress 101 | return NetAddr::CIDR.create(endAddress).to_s 102 | else 103 | return "" 104 | end 105 | end 106 | 107 | def to_node 108 | DataNode.new( get_cn, nil, NicInfo::get_self_link( NicInfo::get_links( @objectclass, @config ) ) ) 109 | end 110 | 111 | end 112 | 113 | end 114 | -------------------------------------------------------------------------------- /lib/nicinfo/jcr/strict.jcr: -------------------------------------------------------------------------------- 1 | ; all_parts strict_all.jcr 2 | ; 3 | ; Override rules for strict RDAP checking. 4 | ; 5 | 6 | ; 7 | ; Object class response 8 | ; 9 | 10 | ; start_part strict_object_classes.jcr 11 | @{root} $entity_response = { 12 | $response_mixin, 13 | $entity_mixin, 14 | @{not} $error_mixin, 15 | @{not} $search_results 16 | } 17 | 18 | @{root} $nameserver_response = { 19 | $response_mixin, 20 | $nameserver_mixin, 21 | @{not} $error_mixin, 22 | @{not} $search_results 23 | } 24 | 25 | @{root} $domain_response = { 26 | $response_mixin, 27 | $domain_mixin, 28 | @{not} $error_mixin, 29 | @{not} $search_results 30 | } 31 | 32 | @{root} $network_response = { 33 | $response_mixin, 34 | $network_mixin, 35 | @{not} $error_mixin, 36 | @{not} $search_results 37 | } 38 | 39 | @{root} $autnum_response = { 40 | $response_mixin, 41 | $autnum_mixin, 42 | @{not} $error_mixin, 43 | @{not} $search_results 44 | } 45 | ; end_part 46 | ; 47 | ; Help and error response 48 | ; 49 | 50 | ; start_part strict_help_and_error.jcr 51 | @{root} $error_response = { 52 | $response_mixin, 53 | $error_mixin, 54 | @{not} $object_class, 55 | @{not} $search_results 56 | } 57 | 58 | @{root} $help_response = { 59 | $response_mixin, 60 | $lang ?, 61 | @{not} $error_mixin, 62 | @{not} $object_class, 63 | @{not} $search_results 64 | } 65 | ; end_part 66 | ; 67 | ; Search responses 68 | ; 69 | 70 | ; start_part strict_search_responses.jcr 71 | @{root} $domainSearch_response = { 72 | $response_mixin, 73 | $lang ?, 74 | $domainSearchResult, 75 | @{not} $error_mixin, 76 | @{not} $object_class 77 | } 78 | 79 | @{root} $nameserverSearch_response = { 80 | $response_mixin, 81 | $lang ?, 82 | $nameserverSearchResult, 83 | @{not} $error_mixin, 84 | @{not} $object_class 85 | } 86 | 87 | @{root} $entitySearch_response = { 88 | $response_mixin, 89 | $lang ?, 90 | $entitySearchResult, 91 | @{not} $error_mixin, 92 | @{not} $object_class 93 | } 94 | ; end_part 95 | ; 96 | ; Object class mixins 97 | ; 98 | 99 | ; start_part strict_object_class_mixins.jcr 100 | $object_class = ( 101 | $entity_mixin | 102 | $nameserver_mixin | 103 | $domain_mixin | 104 | $network_mixin | 105 | $autnum_mixin 106 | ) 107 | ; end_part 108 | ; 109 | ; All search results 110 | ; 111 | 112 | ; start_part strict_searches.jcr 113 | $search_results = ( 114 | $domainSearchResult | 115 | $nameserverSearchResult | 116 | $entitySearchResult 117 | ) 118 | ; end_part 119 | ; 120 | ; IANA Status Values 121 | ; 122 | 123 | ; start_part strict_iana_status_values.jcr 124 | $status = "status" : [ $status_values * ] 125 | 126 | $status_values = ( 127 | "validated" | 128 | "renew prohibited" | 129 | "update prohibited" | 130 | "transfer prohibited" | 131 | "delete prohibited" | 132 | "proxy" | 133 | "private" | 134 | "removed" | 135 | "obscured" | 136 | "associated" | 137 | "active" | 138 | "inactive" | 139 | "locked" | 140 | "pending create" | 141 | "pending renew" | 142 | "pending transfer" | 143 | "pending update" | 144 | "pending delete" | 145 | "add period" | 146 | "auto renew period" | 147 | "client delete prohibited" | 148 | "client hold" | 149 | "client renew prohibited" | 150 | "client transfer prohibited" | 151 | "client update prohibited" | 152 | "pending restore" | 153 | "redemption period" | 154 | "renew period" | 155 | "server delete prohibited" | 156 | "server renew prohibited" | 157 | "server transfer prohibited" | 158 | "server update prohibited" | 159 | "server hold" | 160 | "transfer period" 161 | ) 162 | ; end_part 163 | ; 164 | ; IANA Notice and Remark Types 165 | ; 166 | 167 | ; start_part strict_iana_notice_remark_types.jcr 168 | $noticeRemarkType = "type" : $noticeRemarkType_values 169 | 170 | $noticeRemarkType_values = ( 171 | "result set truncated due to authorization" | 172 | "result set truncated due to excessive load" | 173 | "result set truncated due to unexplainable reasons" | 174 | "object truncated due to authorization" | 175 | "object truncated due to excessive load" | 176 | "object truncated due to unexplainable reasons" 177 | ) 178 | ; end_part 179 | ; 180 | ; IANA Roles 181 | ; 182 | 183 | ; start_part strict_iana_roles.jcr 184 | $roles = "roles" : [ $role_values * ] 185 | 186 | $role_values = ( 187 | "registrant" | 188 | "technical" | 189 | "administrative" | 190 | "abuse" | 191 | "billing" | 192 | "registrar" | 193 | "reseller" | 194 | "sponsor" | 195 | "proxy" | 196 | "notifications" | 197 | "noc" 198 | ) 199 | 200 | ; end_part 201 | ; 202 | ; IANA Domain Variant Relations 203 | ; 204 | 205 | ; start_part strict_iana_domain_variant_relations.jcr 206 | $variantRelation = "relation" : [ $variantRelation_values * ] 207 | 208 | $variantRelation_values = ( 209 | "registered" | 210 | "unregistered" | 211 | "registration restricted" | 212 | "open registration" | 213 | "conjoined" 214 | ) 215 | ; end_part 216 | ; 217 | ; IANA Event Actions 218 | ; 219 | 220 | ; start_part strict_iana_event_actions.jcr 221 | $eventAction = "eventAction" : $eventAction_values 222 | 223 | $eventAction_values = ( 224 | "registration" | 225 | "reregistration" | 226 | "last changed" | 227 | "expiration" | 228 | "deletion" | 229 | "reinstantiation" | 230 | "transfer" | 231 | "locked" | 232 | "unlocked" | 233 | "last update of RDAP database" | 234 | "registrar expiration" | 235 | "enum validation expiration" 236 | ) 237 | ; end_part 238 | 239 | -------------------------------------------------------------------------------- /lib/nicinfo/key_data.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'nicinfo/config' 16 | require 'nicinfo/nicinfo_logger' 17 | require 'nicinfo/utils' 18 | require 'nicinfo/common_json' 19 | require 'nicinfo/data_tree' 20 | 21 | module NicInfo 22 | 23 | def NicInfo.display_key_data json_data, config, data_node 24 | key_data = KeyData.new( config ).process( json_data ).display 25 | end 26 | 27 | # deals with RDAP key data structures 28 | class KeyData 29 | 30 | attr_accessor :objectclass, :asEventActors 31 | 32 | def initialize config 33 | @config = config 34 | @common = CommonJson.new config 35 | @asEventActors = Array.new 36 | end 37 | 38 | def process json_data 39 | @objectclass = json_data 40 | return self 41 | end 42 | 43 | def display 44 | @config.logger.start_data_item 45 | @config.logger.data_title "[ KEY DATA ]" 46 | @config.logger.terse "Algorithm", NicInfo::get_algorithm( @objectclass ) 47 | @config.logger.terse "Flags", @objectclass[ "flags" ] 48 | @config.logger.terse "Protocol", @objectclass[ "protocol" ] 49 | @config.logger.terse "Public Key", @objectclass[ "publicKey" ] 50 | @common.display_events @objectclass 51 | @common.display_as_events_actors @asEventActors 52 | @config.logger.end_data_item 53 | end 54 | 55 | def get_cn 56 | algorithm = NicInfo::DNSSEC_ALGORITHMS[ NicInfo::get_algorithm( @objectclass ) ] 57 | algorithm = algorithm + " Key Data" if algorithm 58 | algorithm = "(unidentifiable key data #{object_id})" if !algorithm 59 | return algorithm 60 | end 61 | 62 | def to_node 63 | node = DataNode.new( get_cn, nil, NicInfo::get_self_link( NicInfo::get_links( @objectclass, @config ) ) ) 64 | node.data_type=self.class.name 65 | return node 66 | end 67 | 68 | end 69 | 70 | end 71 | -------------------------------------------------------------------------------- /lib/nicinfo/notices.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011-2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'nicinfo/config' 16 | require 'nicinfo/nicinfo_logger' 17 | require 'nicinfo/utils' 18 | require 'nicinfo/common_json' 19 | 20 | module NicInfo 21 | 22 | # deals with RDAP notices structures 23 | class Notices 24 | 25 | attr_accessor :config 26 | 27 | def initialize( config ) 28 | @config = config 29 | @common = CommonJson.new( config ) 30 | end 31 | 32 | def is_excessive_notice notices 33 | return false if !notices 34 | return false if notices.length == 0 35 | return true if notices.length > 2 36 | word_count = 0 37 | line_count = 0 38 | notices.each do |notice| 39 | descriptions = NicInfo::get_descriptions notice, @config 40 | descriptions.each do |line| 41 | line_count = line_count + 1 42 | word_count = word_count + line.length 43 | end if descriptions and descriptions.instance_of? Array 44 | end 45 | return true if line_count > 10 46 | return true if word_count > 700 47 | #otherwise 48 | return false 49 | end 50 | 51 | def display_notices json_response, ignore_excessive 52 | 53 | notices = json_response[ "notices" ] 54 | return if notices == nil 55 | if (is_excessive_notice(notices) ) && (@config.logger.data_amount != NicInfo::DataAmount::EXTRA_DATA) && !ignore_excessive 56 | @config.logger.start_data_item 57 | @config.logger.raw NicInfo::DataAmount::NORMAL_DATA, "Excessive Notices", NicInfo::AttentionType::INFO 58 | @config.logger.raw NicInfo::DataAmount::NORMAL_DATA, "-----------------", NicInfo::AttentionType::INFO 59 | @config.logger.raw NicInfo::DataAmount::NORMAL_DATA, "Response contains excessive notices.", NicInfo::AttentionType::INFO 60 | @config.logger.raw NicInfo::DataAmount::NORMAL_DATA, "Use the \"-V\" or \"--data extra\" options to see them.", NicInfo::AttentionType::INFO 61 | @config.logger.end_data_item 62 | else 63 | notices.each do |notice| 64 | display_single_notice notice 65 | end 66 | end 67 | 68 | end 69 | 70 | def display_single_notice notice 71 | @config.logger.start_data_item 72 | title = notice[ "title" ] 73 | if title == nil 74 | title = "" 75 | end 76 | @config.conf_msgs << "'title' in 'notice' is not a string." unless title.instance_of?( String ) 77 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, "[ NOTICE ]", title, NicInfo::AttentionType::SECONDARY 78 | type = notice[ "type" ] 79 | if type != nil 80 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, "Type", NicInfo.capitalize( type ), NicInfo::AttentionType::SECONDARY 81 | end 82 | description = notice[ "description" ] 83 | i = 1 84 | if description.instance_of?( Array ) 85 | description.each do |line| 86 | if line.instance_of?( String ) 87 | @config.logger.prose NicInfo::DataAmount::NORMAL_DATA, i.to_s, line, NicInfo::AttentionType::SECONDARY 88 | i = i + 1 89 | else 90 | @config.conf_msgs << "eleemnt of 'description' in 'notice' is not a string." 91 | end 92 | end 93 | else 94 | @config.conf_msgs << "'description' in 'notice' is not an array." 95 | end 96 | links = notice[ "links" ] 97 | @common.display_simple_links( links ) 98 | @config.logger.end_data_item 99 | end 100 | 101 | end 102 | 103 | end 104 | -------------------------------------------------------------------------------- /lib/nicinfo/ns.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'nicinfo/config' 16 | require 'nicinfo/nicinfo_logger' 17 | require 'nicinfo/utils' 18 | require 'nicinfo/common_json' 19 | require 'nicinfo/entity' 20 | require 'nicinfo/data_tree' 21 | 22 | module NicInfo 23 | 24 | def NicInfo.display_ns json_data, config, data_node 25 | ns = config.factory.new_ns.process( json_data ) 26 | NicInfo::display_object_with_entities( ns, config, data_node ) 27 | end 28 | 29 | def NicInfo.display_nameservers json_data, config, data_node 30 | ns_array = json_data[ "nameserverSearchResults" ] 31 | if ns_array != nil 32 | if ns_array.instance_of? Array 33 | display_array = Array.new 34 | ns_array.each do |ea| 35 | ns = config.factory.new_ns.process( ea ) 36 | display_array << ns 37 | end 38 | NicInfo::display_object_with_entities( display_array, config, data_node ) 39 | else 40 | config.conf_msgs << "'nameserverSearchResults' is not an array" 41 | end 42 | else 43 | config.conf_msgs << "'nameserverSearchResults' is not present" 44 | end 45 | end 46 | 47 | # deals with RDAP nameserver structures 48 | class Ns 49 | 50 | attr_accessor :entities, :objectclass, :asEventActors 51 | 52 | def initialize config 53 | @config = config 54 | @common = CommonJson.new config 55 | @entities = Array.new 56 | @asEventActors = Array.new 57 | end 58 | 59 | def process json_data 60 | @objectclass = json_data 61 | @entities = @common.process_entities @objectclass 62 | return self 63 | end 64 | 65 | def display 66 | @config.logger.start_data_item 67 | @config.logger.data_title "[ NAME SERVER ]" 68 | @config.logger.terse "Handle", NicInfo::get_handle( @objectclass ), NicInfo::AttentionType::SUCCESS 69 | @config.logger.extra "Object Class Name", NicInfo::get_object_class_name( @objectclass, "nameserver", @config ) 70 | @config.logger.terse "Host Name", NicInfo::get_ldhName( @objectclass ), NicInfo::AttentionType::SUCCESS 71 | @config.logger.terse "IDN Host Name", NicInfo::get_unicodeName( @objectclass ), NicInfo::AttentionType::SUCCESS 72 | ipAddrs = @objectclass[ "ipAddresses" ] 73 | if ipAddrs 74 | v6Addrs = ipAddrs[ "v6" ] 75 | v6Addrs.each do |v6| 76 | @config.logger.terse "IPv6 Address", v6, NicInfo::AttentionType::SUCCESS 77 | end if v6Addrs 78 | v4Addrs = ipAddrs[ "v4" ] 79 | v4Addrs.each do |v4| 80 | @config.logger.terse "IPv4 Address", v4, NicInfo::AttentionType::SUCCESS 81 | end if v4Addrs 82 | end 83 | @common.display_status @objectclass 84 | @common.display_events @objectclass 85 | @common.display_as_events_actors @asEventActors 86 | @common.display_port43 @objectclass 87 | @common.display_remarks @objectclass 88 | @common.display_links( get_cn, @objectclass ) 89 | @config.logger.end_data_item 90 | end 91 | 92 | def get_cn 93 | handle = NicInfo::get_handle @objectclass 94 | handle = NicInfo::get_ldhName @objectclass if !handle 95 | handle = "(unidentifiable nameserver #{object_id})" if !handle 96 | if (name = NicInfo::get_ldhName( @objectclass ) ) != nil 97 | return "#{name} ( #{handle} )" 98 | end 99 | return handle 100 | end 101 | 102 | def to_node 103 | DataNode.new( get_cn, nil, NicInfo::get_self_link( NicInfo::get_links( @objectclass, @config ) ) ) 104 | end 105 | 106 | end 107 | 108 | end 109 | -------------------------------------------------------------------------------- /lib/nicinfo/traceroute.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2009 Original Author Unknown 2 | # Copyright (C) 2016 American Registry for Internet Numbers 3 | # Adopted from https://code.google.com/archive/p/rubyroute/ 4 | # 5 | # Redistribution and use in source and binary forms, with or without modification, are permitted 6 | # provided that the following conditions are met: 7 | # 8 | # 1. Redistributions of source code must retain the above copyright notice, this list of 9 | # conditions and the following disclaimer. 10 | # 11 | # 2. Redistributions in binary form must reproduce the above copyright notice, this list 12 | # of conditions and the following disclaimer in the documentation and/or other materials 13 | # provided with the distribution. 14 | # 15 | # 3. Neither the name of the copyright holder nor the names of its contributors may be used to 16 | # endorse or promote products derived from this software without specific prior written permission. 17 | # 18 | # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY 19 | # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 20 | # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21 | # THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 22 | # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23 | # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 24 | # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | # EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | 29 | require 'timeout' 30 | require 'socket' 31 | require 'nicinfo/config' 32 | require 'nicinfo/nicinfo_logger' 33 | 34 | module NicInfo 35 | 36 | def NicInfo.random_port 37 | 1024 + rand(64511) 38 | end 39 | 40 | def NicInfo.traceroute host, config 41 | ips = Array.new 42 | 43 | begin 44 | myname = Socket.gethostname 45 | rescue SocketError => err_msg 46 | config.logger.mesg "Can't get my own host name (#{err_msg})." 47 | exit 1 48 | end 49 | 50 | config.logger.mesg "Tracing route to #{host}" 51 | 52 | ttl = 1 53 | max_ttl = 255 54 | max_contiguaous_timeout = 16 55 | localport = random_port 56 | dgram_sock = UDPSocket::new 57 | 58 | begin 59 | dgram_sock.bind( myname, localport ) 60 | rescue 61 | localport = random_port 62 | retry 63 | end 64 | 65 | begin 66 | icmp_sock = Socket.open( Socket::PF_INET, Socket::SOCK_RAW, Socket::IPPROTO_ICMP ) 67 | icmp_sockaddr = Socket.pack_sockaddr_in( localport, myname ) 68 | icmp_sock.bind( icmp_sockaddr ) 69 | rescue SystemCallError => socket_error 70 | config.logger.mesg "Error with ICMP socket. You probably need to be root: #{socket_error}" 71 | exit 1 72 | end 73 | 74 | 75 | begin 76 | dgram_sock.connect( host, 999 ) 77 | rescue SocketError => err_msg 78 | config.logger.mesg "Can't connect to remote host (#{err_msg})." 79 | exit 1 80 | end 81 | 82 | stop_tracing = false 83 | continguous_timeout = 0 84 | until stop_tracing 85 | dgram_sock.setsockopt( 0, Socket::IP_TTL, ttl ) 86 | dgram_sock.send( "RubyRoute says hello!", 0 ) 87 | 88 | begin 89 | Timeout::timeout( 1 ) { 90 | data, sender = icmp_sock.recvfrom( 8192 ) 91 | # 20th and 21th bytes of IP+ICMP datagram carry the ICMP type and code resp. 92 | icmp_type = data.unpack( '@20C' )[0] 93 | icmp_code = data.unpack( '@21C' )[0] 94 | # Extract the ICMP sender from response. 95 | ip = Socket.unpack_sockaddr_in( sender )[1].to_s 96 | ips << ip 97 | config.logger.mesg "TTL = #{ttl}: " + ip 98 | continguous_timeout = 0 99 | if ( icmp_type == 3 and icmp_code == 13 ) 100 | config.logger.mesg "'Communication Administratively Prohibited' from this hop." 101 | # ICMP 3/3 is port unreachable and usually means that we've hit the target. 102 | elsif ( icmp_type == 3 and icmp_code == 3 ) 103 | config.logger.mesg "Destination reached. Trace complete." 104 | stop_tracing = true 105 | end 106 | } 107 | rescue Timeout::Error 108 | config.logger.mesg "Timeout error with TTL = #{ttl}!" 109 | continguous_timeout += 1 110 | end 111 | 112 | ttl += 1 113 | stop_tracing = true if ttl > max_ttl 114 | if continguous_timeout > max_contiguaous_timeout 115 | stop_tracing = true 116 | config.logger.mesg "Getting a lot of contiguous timeouts. Prematurely terminating trace." 117 | end 118 | end 119 | 120 | ips 121 | end 122 | 123 | end 124 | 125 | 126 | -------------------------------------------------------------------------------- /lib/nicinfo/utils.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011,2012,2013,2014 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | 16 | require 'stringio' 17 | require 'uri' 18 | require 'nicinfo/config' 19 | 20 | module NicInfo 21 | 22 | def NicInfo.make_safe( url ) 23 | p = URI::Parser.new 24 | safe = p.escape( url ) 25 | safe = p.escape( safe, "!*'();:@&=+$,/?#[]" ) 26 | return safe 27 | end 28 | 29 | def NicInfo.get_secure_dns json_data 30 | return json_data[ "secureDNS" ] 31 | end 32 | 33 | def NicInfo.get_ds_data_objs json_data 34 | secure_dns = NicInfo::get_secure_dns json_data 35 | if secure_dns.instance_of? Array 36 | secure_dns = secure_dns[ 0 ] 37 | end 38 | return secure_dns[ "dsData" ] if secure_dns 39 | return nil 40 | end 41 | 42 | def NicInfo.get_key_data_objs json_data 43 | secure_dns = NicInfo::get_secure_dns json_data 44 | if secure_dns.instance_of? Array 45 | secure_dns = secure_dns[ 0 ] 46 | end 47 | return secure_dns[ "keyData" ] if secure_dns 48 | return nil 49 | end 50 | 51 | def NicInfo.get_algorithm json_data 52 | return json_data[ "algorithm" ] 53 | end 54 | 55 | def NicInfo.get_handle json_data 56 | return json_data[ "handle" ] 57 | end 58 | 59 | def NicInfo.get_object_class_name json_data, expected, config 60 | objectClassName = json_data[ "objectClassName" ] 61 | if objectClassName == nil 62 | config.conf_msgs << "Expected 'objectClassName' is not present." 63 | elsif objectClassName != expected 64 | config.conf_msgs << "Expected 'objectClassName' to be '#{expected}' but it is '#{objectClassName}'." 65 | end 66 | return objectClassName 67 | end 68 | 69 | def NicInfo.get_ldhName json_data 70 | return json_data[ "ldhName" ] 71 | end 72 | 73 | def NicInfo.get_unicodeName json_data 74 | return json_data[ "unicodeName" ] 75 | end 76 | 77 | def NicInfo.get_descriptions json_data, config 78 | return if !json_data 79 | if json_data.instance_of?( Hash ) 80 | retval = json_data[ "description" ] 81 | unless retval.instance_of?( Array ) 82 | config.conf_msgs << "'description' is not an array." 83 | retval = nil 84 | end 85 | else 86 | config.conf_msgs << "expected object for 'remarks' or 'notices'." 87 | retval = nil 88 | end 89 | return retval 90 | end 91 | 92 | def NicInfo.get_entitites json_data 93 | return json_data[ "entities" ] 94 | end 95 | 96 | def NicInfo.get_networks json_data 97 | return json_data[ "networks" ] 98 | end 99 | 100 | def NicInfo.get_network json_data 101 | return json_data[ "network" ] 102 | end 103 | 104 | def NicInfo.get_autnums json_data 105 | return json_data[ "autnums" ] 106 | end 107 | 108 | def NicInfo.get_nameservers json_data 109 | return json_data[ "nameservers" ] 110 | end 111 | 112 | def NicInfo.get_startAddress json_data 113 | return json_data[ "startAddress" ] 114 | end 115 | 116 | def NicInfo.get_endAddress json_data 117 | return json_data[ "endAddress" ] 118 | end 119 | 120 | def NicInfo.get_startAutnum json_data 121 | return json_data[ "startAutnum" ] 122 | end 123 | 124 | def NicInfo.get_endAutnum json_data 125 | return json_data[ "endAutnum" ] 126 | end 127 | 128 | def NicInfo.get_name json_data 129 | return json_data[ "name" ] 130 | end 131 | 132 | def NicInfo.get_type json_data 133 | return json_data[ "type" ] 134 | end 135 | 136 | def NicInfo.get_country json_data 137 | return json_data[ "country" ] 138 | end 139 | 140 | def NicInfo.get_links json_data, config 141 | retval = json_data[ "links" ] 142 | return nil unless retval 143 | if !retval.instance_of?( Array ) 144 | config.conf_msgs << "'links' is not an array." 145 | retval = nil 146 | end 147 | return retval 148 | end 149 | 150 | def NicInfo.get_related_link links 151 | get_link "related", links 152 | end 153 | 154 | def NicInfo.get_alternate_link links 155 | get_link "alternate", links 156 | end 157 | 158 | def NicInfo.get_tos_link links 159 | get_link "terms-of-service", links 160 | end 161 | 162 | def NicInfo.get_license_link links 163 | get_link "license", links 164 | end 165 | 166 | def NicInfo.get_copyright_link links 167 | get_link "copyright", links 168 | end 169 | 170 | def NicInfo.get_about_link links 171 | get_link "about", links 172 | end 173 | 174 | def NicInfo.get_self_link links 175 | get_link "self", links 176 | end 177 | 178 | def NicInfo.get_link rel, links 179 | return nil if !links 180 | links.each do |link| 181 | if link[ "rel" ] == rel 182 | return link[ "href" ] 183 | end 184 | end 185 | return nil 186 | end 187 | 188 | def NicInfo.capitalize str 189 | words = str.split( /\s/ ) 190 | words.each do |word| 191 | word.capitalize! 192 | end 193 | return words.join( " " ) 194 | end 195 | 196 | end 197 | -------------------------------------------------------------------------------- /nicinfo.gemspec: -------------------------------------------------------------------------------- 1 | lib = File.expand_path('../lib', __FILE__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | 4 | require 'nicinfo/constants' 5 | 6 | Gem::Specification.new do |s| 7 | s.name = 'nicinfo' 8 | s.version = NicInfo::VERSION 9 | s.date = Time.now.strftime( "%Y-%m-%d" ) 10 | s.summary = "RDAP Client" 11 | s.description = "A command-line RDAP client." 12 | s.authors = ["Andrew Newton","Garth Dubin"] 13 | s.email = 'gdubin@arin.net' 14 | s.files = Dir["lib/**/*"].entries 15 | s.homepage = 'https://github.com/arinlabs/nicinfo' 16 | s.license = 'ISC' 17 | s.executables << 'nicinfo' 18 | s.add_dependency 'netaddr', '~> 2.0.4' 19 | s.add_dependency 'rainbow', '~> 3.0' 20 | s.add_dependency 'jcrvalidator', '= 0.8.3' 21 | end 22 | -------------------------------------------------------------------------------- /spec/bootstrap_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2013-2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'spec_helper' 16 | require 'rspec' 17 | require 'pp' 18 | require_relative '../lib/nicinfo/bootstrap' 19 | require_relative '../lib/../lib/nicinfo/config' 20 | 21 | describe 'bootstrap rspec tests' do 22 | 23 | CZ_URL = "https://rdap.nic.cz" 24 | IANA_URL = "https://rdap.iana.org" 25 | ARIN_URL = "https://rdap.arin.net/registry" 26 | APNIC_URL = "https://rdap.apnic.net/" 27 | LACNIC_URL = "https://rdap.lacnic.net/rdap/" 28 | AFRINIC_URL = "https://rdap.afrinic.net/rdap/" 29 | RIPE_URL = "https://rdap.db.ripe.net/" 30 | 31 | @work_dir = nil 32 | 33 | before(:all) do 34 | @work_dir = Dir.mktmpdir 35 | end 36 | 37 | after(:all) do 38 | FileUtils.rm_r( @work_dir ) 39 | end 40 | 41 | it 'should test find urls by ipv4' do 42 | dir = File.join( @work_dir, "test_find_url_by_v4" ) 43 | c = NicInfo::Config.new( dir ) 44 | c.logger.message_level = "NONE" 45 | c.setup_workspace 46 | bootstrap = NicInfo::Bootstrap.new c 47 | expect( bootstrap.find_url_by_ip( "216.0.0.1" ) ).to eq( ARIN_URL ) 48 | expect( bootstrap.find_url_by_ip( "218.0.0.1" ) ).to eq( APNIC_URL ) 49 | expect( bootstrap.find_url_by_ip( "1.1.1.1" ) ).to eq( APNIC_URL ) 50 | expect( bootstrap.find_url_by_ip( "212.0.0.1" ) ).to eq( RIPE_URL ) 51 | expect( bootstrap.find_url_by_ip( "200.0.0.1" ) ).to eq( LACNIC_URL ) 52 | expect( bootstrap.find_url_by_ip( "102.0.0.1" ) ).to eq( AFRINIC_URL ) 53 | expect( bootstrap.find_url_by_ip( "128.0.0.1" ) ).to eq( ARIN_URL ) 54 | expect( bootstrap.find_url_by_ip( "133.0.0.1" ) ).to eq( APNIC_URL ) 55 | expect( bootstrap.find_url_by_ip( "151.0.0.1" ) ).to eq( RIPE_URL ) 56 | expect( bootstrap.find_url_by_ip( "191.0.0.1" ) ).to eq( LACNIC_URL ) 57 | expect( bootstrap.find_url_by_ip( "196.0.0.1" ) ).to eq( AFRINIC_URL ) 58 | end 59 | 60 | it 'should find urls by ipv6' do 61 | dir = File.join( @work_dir, "test_find_url_by_v6" ) 62 | c = NicInfo::Config.new( dir ) 63 | c.logger.message_level = "NONE" 64 | c.setup_workspace 65 | bootstrap = NicInfo::Bootstrap.new c 66 | expect( bootstrap.find_url_by_ip( "1001:0000::1") ).to eq( c.config[ NicInfo::BOOTSTRAP ][ NicInfo::IP_ROOT_URL ] ) 67 | expect( bootstrap.find_url_by_ip( "2001:0400::/23" ) ).to eq( ARIN_URL ) 68 | expect( bootstrap.find_url_by_ip( "2001:0200::/23" ) ).to eq( APNIC_URL ) 69 | expect( bootstrap.find_url_by_ip( "2001:0600::/23" ) ).to eq( RIPE_URL ) 70 | expect( bootstrap.find_url_by_ip( "2001:1200::/23" ) ).to eq( LACNIC_URL ) 71 | expect( bootstrap.find_url_by_ip( "2001:4200::/23" ) ).to eq( AFRINIC_URL ) 72 | end 73 | 74 | it 'should find url by as' do 75 | dir = File.join( @work_dir, "test_find_url_by_as" ) 76 | c = NicInfo::Config.new( dir ) 77 | c.logger.message_level = "NONE" 78 | c.setup_workspace 79 | bootstrap = NicInfo::Bootstrap.new c 80 | expect( bootstrap.find_url_by_as( 26756 ) ).to eq( ARIN_URL ) 81 | expect( bootstrap.find_url_by_as( 26755 ) ).to eq( ARIN_URL ) 82 | expect( bootstrap.find_url_by_as( 27575 ) ).to eq( ARIN_URL ) 83 | expect( bootstrap.find_url_by_as( 23552 ) ).to eq( APNIC_URL ) 84 | expect( bootstrap.find_url_by_as( 27648 ) ).to eq( LACNIC_URL ) 85 | expect( bootstrap.find_url_by_as( 24735 ) ).to eq( RIPE_URL ) 86 | expect( bootstrap.find_url_by_as( 23541 ) ).to eq( LACNIC_URL ) 87 | expect( bootstrap.find_url_by_as( 23549 ) ).to eq( AFRINIC_URL ) 88 | expect( bootstrap.find_url_by_as( 393216 ) ).to eq( ARIN_URL ) 89 | expect( bootstrap.find_url_by_as( 0 ) ).to eq( c.config[ NicInfo::BOOTSTRAP ][ NicInfo::AS_ROOT_URL ] ) 90 | end 91 | 92 | it 'should get ipv4 from inaddr' do 93 | dir = File.join( @work_dir, "test_find_ip4_from_inaddr" ) 94 | c = NicInfo::Config.new( dir ) 95 | c.logger.message_level = "NONE" 96 | c.setup_workspace 97 | bootstrap = NicInfo::Bootstrap.new c 98 | expect( bootstrap.get_ip4_by_inaddr( "1.0.0.192.in-addr.arpa.") ).to eq( IPAddr.new( "192.0.0.1" ) ) 99 | expect( bootstrap.get_ip4_by_inaddr( "1.0.0.192.in-addr.arpa") ).to eq( IPAddr.new( "192.0.0.1" ) ) 100 | expect( bootstrap.get_ip4_by_inaddr( "0.0.192.in-addr.arpa") ).to eq( IPAddr.new( "192.0.0.0" ) ) 101 | expect( bootstrap.get_ip4_by_inaddr( "0.192.in-addr.arpa") ).to eq( IPAddr.new( "192.0.0.0" ) ) 102 | expect( bootstrap.get_ip4_by_inaddr( "192.in-addr.arpa") ).to eq( IPAddr.new( "192.0.0.0" ) ) 103 | end 104 | 105 | it 'should get ip6 from inaddr' do 106 | dir = File.join( @work_dir, "test_find_ip6_from_inaddr" ) 107 | c = NicInfo::Config.new( dir ) 108 | c.logger.message_level = "NONE" 109 | c.setup_workspace 110 | bootstrap = NicInfo::Bootstrap.new c 111 | expect( bootstrap.get_ip6_by_inaddr( "b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2.ip6.arpa.") ).to eq( IPAddr.new( "2001:db8::567:89ab" ) ) 112 | expect( bootstrap.get_ip6_by_inaddr( "8.b.d.0.1.0.0.2.ip6.arpa.") ).to eq( IPAddr.new( "2001:db8::0" ) ) 113 | end 114 | 115 | it 'should find url by domain' do 116 | dir = File.join( @work_dir, "test_find_url_by_domain" ) 117 | c = NicInfo::Config.new( dir ) 118 | c.logger.message_level = "NONE" 119 | c.setup_workspace 120 | bootstrap = NicInfo::Bootstrap.new c 121 | expect( bootstrap.find_url_by_domain( "0.0.4.0.1.0.0.2.ip6.arpa.") ).to eq( ARIN_URL ) 122 | expect( bootstrap.find_url_by_domain( "192.in-addr.arpa") ).to eq( ARIN_URL ) 123 | expect( bootstrap.find_url_by_domain( "www.exmaple.cz") ).to eq( CZ_URL ) 124 | expect( bootstrap.find_url_by_domain( "www.exmaple.museuum") ).to eq( c.config[ NicInfo::BOOTSTRAP ][ NicInfo::DOMAIN_ROOT_URL ] ) 125 | end 126 | 127 | it 'should find url by forward domain' do 128 | dir = File.join( @work_dir, "test_find_url_by_forward_domain" ) 129 | c = NicInfo::Config.new( dir ) 130 | c.logger.message_level = "NONE" 131 | c.setup_workspace 132 | bootstrap = NicInfo::Bootstrap.new c 133 | expect( bootstrap.find_url_by_forward_domain( "www.exmaple.cz") ).to eq( CZ_URL ) 134 | expect( bootstrap.find_url_by_forward_domain( "www.exmaple.museuum") ).to eq( c.config[ NicInfo::BOOTSTRAP ][ NicInfo::DOMAIN_ROOT_URL ] ) 135 | end 136 | 137 | it 'should find url by entity' do 138 | dir = File.join( @work_dir, "test_find_url_by_entity" ) 139 | c = NicInfo::Config.new( dir ) 140 | c.logger.message_level = "NONE" 141 | c.setup_workspace 142 | bootstrap = NicInfo::Bootstrap.new c 143 | expect( bootstrap.find_url_by_entity( "XXX-ARIN") ).to eq( ARIN_URL ) 144 | expect( bootstrap.find_url_by_entity( "xxx-arin") ).to eq( ARIN_URL ) 145 | expect( bootstrap.find_url_by_entity( "xxx-afrinic") ).to eq( AFRINIC_URL ) 146 | expect( bootstrap.find_url_by_entity( "xxx-ap") ).to eq( APNIC_URL ) 147 | expect( bootstrap.find_url_by_entity( "xxx-lacnic") ).to eq( LACNIC_URL ) 148 | expect( bootstrap.find_url_by_entity( "xxx-ripe") ).to eq( RIPE_URL ) 149 | expect( bootstrap.find_url_by_entity( "xxx-museum") ).to eq( c.config[ NicInfo::BOOTSTRAP ][ NicInfo::ENTITY_ROOT_URL ] ) 150 | end 151 | end 152 | -------------------------------------------------------------------------------- /spec/cache_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011-2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | 16 | require 'spec_helper' 17 | require 'rspec' 18 | require 'pp' 19 | require 'tmpdir' 20 | require 'fileutils' 21 | require_relative '../lib/nicinfo/config' 22 | require_relative '../lib/nicinfo/cache' 23 | require_relative '../lib/nicinfo/constants' 24 | 25 | 26 | describe 'cache rspec tests' do 27 | 28 | @work_dir = nil 29 | 30 | before(:all) do 31 | 32 | @work_dir = Dir.mktmpdir 33 | 34 | # the contents are important... just that it is an XML blob 35 | @net_xml = < 37 | 2002-04-17T00:00:00-04:00 38 | http://whois.arin.net/rest/net/NET-192-136-136-0-1 39 | 192.136.136.255 40 | NET-192-136-136-0-1 41 | ARIN-BLK-2 42 | 43 | AS10745 44 | AS107450 45 | 46 | http://whois.arin.net/rest/org/ARIN 47 | http://whois.arin.net/rest/net/NET-192-0-0-0-0 48 | 192.136.136.0 49 | 2011-03-19T00:00:00-04:00 50 | 4 51 | 52 | NET_XML 53 | 54 | end 55 | 56 | after(:all) do 57 | 58 | FileUtils.rm_rf( @work_dir ) 59 | 60 | end 61 | 62 | it 'should make_safe correctly' do 63 | 64 | expect( NicInfo::make_safe( "http://" ) ).to eq( "http%3A%2F%2F" ) 65 | expect( NicInfo::make_safe( "http://whois.arin.net/rest/nets;q=192.136.136.1?showDetails=true&showARIN=false" ) ).to eq( "http%3A%2F%2Fwhois.arin.net%2Frest%2Fnets%3Bq%3D192.136.136.1%3FshowDetails%3Dtrue%26showARIN%3Dfalse" ) 66 | expect( NicInfo::make_safe( "marry had a little lamb!" ) ).to eq( "marry%20had%20a%20little%20lamb%21" ) 67 | 68 | end 69 | 70 | it 'should create or update the cache' do 71 | 72 | dir = File.join( @work_dir, "test_create_or_update" ) 73 | c = NicInfo::Config.new( dir ) 74 | c.logger.message_level = "NONE" 75 | c.setup_workspace 76 | 77 | cache = NicInfo::Cache.new c 78 | url = "http://whois.arin.net/rest/net/NET-192-136-136-0-1" 79 | cache.create_or_update( url, @net_xml ) 80 | 81 | safe = NicInfo::make_safe( url ) 82 | file_name = File.join( c.rdap_cache_dir, safe ) 83 | expect( File.exist?( file_name ) ).to be_truthy 84 | f = File.open( file_name, "r" ) 85 | data = '' 86 | f.each_line do |line| 87 | data += line 88 | end 89 | f.close 90 | expect( data ).to eq( @net_xml ) 91 | 92 | # do it again 93 | new_xml = @net_xml + "\n**Second**Time**\n" 94 | cache.create_or_update( url, new_xml ) 95 | expect( File.exist?( file_name ) ).to be_truthy 96 | f = File.open( file_name, "r" ) 97 | data = '' 98 | f.each_line do |line| 99 | data += line 100 | end 101 | f.close 102 | expect( new_xml ).to eq( data ) 103 | end 104 | 105 | it 'should create a cache' do 106 | 107 | dir = File.join( @work_dir, "test_create" ) 108 | c = NicInfo::Config.new( dir ) 109 | c.logger.message_level = "NONE" 110 | c.setup_workspace 111 | c.config[ NicInfo::CACHE ][ NicInfo::CACHE_EXPIRY ] = 9000 # really any number above 1 should be good 112 | 113 | cache = NicInfo::Cache.new c 114 | url = "http://whois.arin.net/rest/net/NET-192-136-136-0-1" 115 | cache.create_or_update( url, @net_xml ) 116 | 117 | safe = NicInfo::make_safe( url ) 118 | file_name = File.join( c.rdap_cache_dir, safe ) 119 | expect( File.exist?( file_name ) ).to be_truthy 120 | f = File.open( file_name, "r" ) 121 | data = '' 122 | f.each_line do |line| 123 | data += line 124 | end 125 | f.close 126 | expect( data ).to eq( @net_xml ) 127 | 128 | # do it again, but the data should be the same as the first time when read back out 129 | new_xml = @net_xml + "\n**Second**Time**\n" 130 | cache.create( url, new_xml ) 131 | expect( File.exist?( file_name ) ).to be_truthy 132 | f = File.open( file_name, "r" ) 133 | data = '' 134 | f.each_line do |line| 135 | data += line 136 | end 137 | f.close 138 | expect( data ).to eq( @net_xml ) 139 | end 140 | 141 | it 'should get a cache hit' do 142 | 143 | dir = File.join( @work_dir, "test_get_hit" ) 144 | c = NicInfo::Config.new( dir ) 145 | c.logger.message_level = "NONE" 146 | c.setup_workspace 147 | 148 | c.config[ NicInfo::CACHE ][ NicInfo::USE_CACHE ] = true 149 | c.config[ NicInfo::CACHE ][ NicInfo::CACHE_EXPIRY ] = 9000 # really any number above 1 should be good 150 | cache = NicInfo::Cache.new c 151 | url = "http://whois.arin.net/rest/net/NET-192-136-136-0-1" 152 | cache.create_or_update( url, @net_xml ) 153 | 154 | data = cache.get( url ) 155 | expect( data ).to eq( @net_xml ) 156 | 157 | end 158 | 159 | it 'should get no cache hit' do 160 | 161 | dir = File.join( @work_dir, "test_get_no_hit" ) 162 | c = NicInfo::Config.new( dir ) 163 | c.logger.message_level = "NONE" 164 | c.setup_workspace 165 | 166 | c.config[ NicInfo::CACHE ][ NicInfo::USE_CACHE ] = true 167 | c.config[ NicInfo::CACHE ][ NicInfo::CACHE_EXPIRY ] = 9000 # really any number above 1 should be good 168 | cache = NicInfo::Cache.new c 169 | url = "http://whois.arin.net/rest/net/NET-192-136-136-0-1" 170 | cache.create_or_update( url, @net_xml ) 171 | 172 | data = cache.get( "http://whois.arin.net/rest/net/NET-192-136-136-0-2" ) 173 | expect( data ).to be_nil 174 | 175 | end 176 | 177 | it 'should get expired hit' do 178 | 179 | dir = File.join( @work_dir, "test_get_expired_hit" ) 180 | c = NicInfo::Config.new( dir ) 181 | c.logger.message_level = "NONE" 182 | c.setup_workspace 183 | 184 | c.config[ NicInfo::CACHE ][ NicInfo::USE_CACHE ] = true 185 | c.config[ NicInfo::CACHE ][ NicInfo::CACHE_EXPIRY ] = -19000 # really any number less than -1 should be good 186 | cache = NicInfo::Cache.new c 187 | url = "http://whois.arin.net/rest/net/NET-192-136-136-0-1" 188 | cache.create_or_update( url, @net_xml ) 189 | 190 | data = cache.get( url ) 191 | expect( data ).to be_nil 192 | 193 | end 194 | 195 | it 'should not use the cache' do 196 | 197 | dir = File.join( @work_dir, "test_no_use_cache" ) 198 | c = NicInfo::Config.new( dir ) 199 | c.logger.message_level = "NONE" 200 | c.setup_workspace 201 | 202 | c.config[ NicInfo::CACHE ][ NicInfo::USE_CACHE ] = false 203 | c.config[ NicInfo::CACHE ][ NicInfo::CACHE_EXPIRY ] = 9000 # really any number above 1 should be good 204 | cache = NicInfo::Cache.new c 205 | url = "http://whois.arin.net/rest/net/NET-192-136-136-0-1" 206 | cache.create_or_update( url, @net_xml ) 207 | 208 | data = cache.get( url ) 209 | expect( data ).to be_nil 210 | 211 | end 212 | 213 | it 'should clean out the cache' do 214 | 215 | dir = File.join( @work_dir, "test_clean" ) 216 | c = NicInfo::Config.new( dir ) 217 | c.logger.message_level = "NONE" 218 | c.setup_workspace 219 | 220 | c.config[ NicInfo::CACHE ][ NicInfo::USE_CACHE ] = true 221 | c.config[ NicInfo::CACHE ][ NicInfo::CACHE_EVICTION ] = -19000 # really any number less than -1 should be good 222 | cache = NicInfo::Cache.new c 223 | url = "http://whois.arin.net/rest/net/NET-192-136-136-0-" 224 | cache.create_or_update( url + "1", @net_xml ) 225 | cache.create_or_update( url + "2", @net_xml ) 226 | cache.create_or_update( url + "3", @net_xml ) 227 | 228 | count = cache.clean 229 | expect( count ).to eq( 3 ) 230 | 231 | end 232 | 233 | it 'should empty the cache' do 234 | 235 | dir = File.join( @work_dir, "test_empty" ) 236 | c = NicInfo::Config.new( dir ) 237 | c.logger.message_level = "NONE" 238 | c.setup_workspace 239 | 240 | c.config[ NicInfo::CACHE ][ NicInfo::USE_CACHE ] = true 241 | cache = NicInfo::Cache.new c 242 | url = "http://whois.arin.net/rest/net/NET-192-136-136-0-" 243 | cache.create_or_update( url + "1", @net_xml ) 244 | cache.create_or_update( url + "2", @net_xml ) 245 | cache.create_or_update( url + "3", @net_xml ) 246 | 247 | count = cache.empty 248 | expect( count ).to eq( 3 ) 249 | expect( cache.count ).to eq( 0 ) 250 | 251 | end 252 | 253 | end 254 | 255 | -------------------------------------------------------------------------------- /spec/common_names_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011-2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | 16 | require 'spec_helper' 17 | require 'rspec' 18 | require_relative '../lib/nicinfo/common_names' 19 | 20 | describe 'common names test' do 21 | 22 | it 'should test last names' do 23 | 24 | expect( NicInfo::is_last_name( "JOHNSON") ).to be_truthy 25 | expect( NicInfo::is_last_name( "NEWTON") ).to be_truthy 26 | expect( NicInfo::is_last_name( "KOSTERS") ).to be_truthy 27 | expect( NicInfo::is_last_name( "AALDERINK") ).to be_truthy 28 | expect( NicInfo::is_last_name( "..........") ).to be_falsey 29 | 30 | end 31 | 32 | it 'should test male names' do 33 | 34 | expect( NicInfo::is_male_name( "JOHN" ) ).to be_truthy 35 | expect( NicInfo::is_male_name( "JAMES" ) ).to be_truthy 36 | expect( NicInfo::is_male_name( "ANDREW" ) ).to be_truthy 37 | expect( NicInfo::is_male_name( "MARK" ) ).to be_truthy 38 | expect( NicInfo::is_male_name( ".........." ) ).to be_falsey 39 | 40 | end 41 | 42 | it 'should test female names' do 43 | 44 | expect( NicInfo::is_female_name( "LINDA" ) ).to be_truthy 45 | expect( NicInfo::is_female_name( "MARY" ) ).to be_truthy 46 | expect( NicInfo::is_female_name( "GAIL" ) ).to be_truthy 47 | expect( NicInfo::is_female_name( "ALLYN" ) ).to be_truthy 48 | expect( NicInfo::is_female_name( "........" ) ).to be_falsey 49 | 50 | end 51 | 52 | end 53 | -------------------------------------------------------------------------------- /spec/config_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2011-2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | 16 | require 'spec_helper' 17 | require 'rspec' 18 | require 'tmpdir' 19 | require 'fileutils' 20 | require_relative '../lib/nicinfo/config' 21 | require_relative '../lib/nicinfo/nicinfo_logger' 22 | require_relative '../lib/nicinfo/constants' 23 | 24 | describe 'configuration tests' do 25 | 26 | @work_dir = nil 27 | 28 | before(:all) do 29 | @work_dir = Dir.mktmpdir 30 | end 31 | 32 | after(:all) do 33 | FileUtils.rm_rf( @work_dir ) 34 | end 35 | 36 | it 'test initialization with not config files' do 37 | 38 | dir = File.join( @work_dir, "test_init_no_config_file" ) 39 | 40 | c = NicInfo::Config.new( dir ) 41 | expect( c.config[ "output" ][ "messages" ] ).to eq( "SOME" ) 42 | expect( c.config[ "output" ][ "data" ] ).to eq( "NORMAL" ) 43 | expect( c.config[ NicInfo::OUTPUT ][ NicInfo::MESSAGES_FILE ] ).to be_nil 44 | expect( c.config[ NicInfo::OUTPUT ][ NicInfo::DATA_FILE ] ).to be_nil 45 | expect( c.config[ NicInfo::BOOTSTRAP ][ NicInfo::IP_ROOT_URL ] ).to eq( "https://rdap.arin.net/registry" ) 46 | 47 | expect( c.logger.data_amount ).to eq( "NORMAL" ) 48 | expect( c.logger.message_level ).to eq( "SOME" ) 49 | 50 | end 51 | 52 | it 'should test an init config file' do 53 | 54 | dir = File.join( @work_dir, "test_init_config_file" ) 55 | Dir.mkdir( dir ) 56 | not_default_config = < true 21 | end -------------------------------------------------------------------------------- /spec/utils_spec.rb: -------------------------------------------------------------------------------- 1 | # Copyright (C) 2013-2017 American Registry for Internet Numbers 2 | # 3 | # Permission to use, copy, modify, and/or distribute this software for any 4 | # purpose with or without fee is hereby granted, provided that the above 5 | # copyright notice and this permission notice appear in all copies. 6 | # 7 | # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 8 | # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 9 | # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 10 | # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 11 | # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 12 | # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR 13 | # IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 | 15 | require 'spec_helper' 16 | require 'rspec' 17 | require_relative '../lib/nicinfo/utils' 18 | 19 | describe 'tests for utility methods' do 20 | 21 | it 'should capitalize' do 22 | expect( NicInfo::capitalize( "my myself & i" ) ).to eq( "My Myself & I" ) 23 | expect( NicInfo::capitalize( "me" ) ).to eq( "Me" ) 24 | end 25 | end 26 | --------------------------------------------------------------------------------