Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support whois.smallregistry.net #144

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions lib/whois/definitions/tlds.rb
Expand Up @@ -125,6 +125,10 @@
Whois::Server.define :tld, ".fk", nil, { :adapter => Whois::Server::Adapters::None }
Whois::Server.define :tld, ".fm", nil, { :web => "http://www.dot.fm/whois.html", :adapter => Whois::Server::Adapters::Web }
Whois::Server.define :tld, ".fo", "whois.ripe.net"
# keep before .fr
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid Ruby syntax here. Just keep a flatten list.

Whois::Server.define :tld, ". aeroport.fr", "whois.smallregistry.net"
Whois::Server.define :tld, ". avocat.fr", "whois.smallregistry.net"
...

It's a little bit more verbose, but I'm planning to convert this file into a JSON definition file and I'd like to keep it flatten. Also, this file was originally generated by a rake task (that is actually still in place).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, done :-)

%w(aeroport avocat chambagri chirurgiens-dentistes experts-comptables geometre-expert medecin notaires pharmacien port veterinaire).each do |t|
Whois::Server.define :tld, ".#{t}.fr", "whois.smallregistry.net"
end
Whois::Server.define :tld, ".fr", "whois.nic.fr"
Whois::Server.define :tld, ".ga", nil, { :adapter => Whois::Server::Adapters::None }
Whois::Server.define :tld, ".gb", nil, { :adapter => Whois::Server::Adapters::None }
Expand Down
159 changes: 159 additions & 0 deletions lib/whois/record/parser/scanners/whois.smallregistry.net.rb
@@ -0,0 +1,159 @@
#--
# Ruby Whois
#
# An intelligent pure Ruby WHOIS client and parser.
#
# Copyright (c) 2009-2012 Simone Carletti <weppos@weppos.net>
#++


require 'whois/record/parser/scanners/base'


module Whois
class Record
class Parser
module Scanners

class WhoisSmallregistryNet < Base

self.tokenizers += [
:scan_yaml_header,
:scan_disclaimer,
:scan_request_time,
:scan_not_found,
:scan_domain,
:scan_status,
:scan_date_created,
:scan_date_expired,
:scan_date_updated,
:scan_name_servers,
:scan_ds_list,
:scan_registrar,
:scan_registrant,
:scan_administrative_contact,
:scan_technical_contact,
:scan_billing_contact,
]

tokenizer :scan_yaml_header do
# skip the YAML prelude
@input.scan(/^---.*\n/)
end

tokenizer :scan_disclaimer do
if @input.match?(/^#/) && disc = @input.scan_until(/^#\n/)
@ast["field:disclaimer"] = disc
end
end

tokenizer :scan_request_time do
if @input.scan(/^# (\d+-\d+-\d+T.*)\n/)
@ast["request_time"] = DateTime.parse(@input[1].strip)
end
end

tokenizer :scan_not_found do
if @input.scan(/^# Object not found.*\n/)
@ast["status:not_found"] = true
end

end

tokenizer :scan_domain do
if @input.match?(/^name:\s+(.*)\n/) && @input.scan(/^name:\s+(.*?)\n/)
@ast["field:domain"] = @input[1].strip
end
end

tokenizer :scan_status do
if @input.match?(/^status:\s+(.*)\n/) && @input.scan(/^status:\s+(.*?)\n/)
@ast["field:status"] = @input[1].strip.downcase
end
end

%w(created expired updated).each do |date|
tokenizer :"scan_date_#{date}" do
if @input.match?(/^#{date}:\s+"(.*)"\n/) && @input.scan(/^#{date}:\s+"(.*)"\n/)
@ast["field:#{date}"] = DateTime.parse(@input[1].strip)
end
end
end

tokenizer :scan_name_servers do
if @input.match?(/^name_servers: $\n/) && @input.scan(/^name_servers: \n/)
@ast["nameservers"] = []
while line = @input.scan(/^- (\S+)(?: - (.*?)(?: - (.*?))?)?\n/)
@ast["nameservers"] << Record::Nameserver.new(@input[1], @input[2], @input[3])
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Scanners should never use complex object. In this case, it's better to return a Hash and initialize the objects directly in the parser using the Hash as input.

# In the scanner
@ast["nameservers"] << { :name => @input[1], :ipv4 => @input[2], :ipv6 => @input[3] }

# In the parser
Array.wrap(node("nameservers")).each { |hash| Record::Nameserver.new(hash) }

The same applies to :scan_registrar.

This is a convention I'm trying to follow because I'd like to move scanners from a Ruby-based implementation to something more efficient such as Racc or Treetop.

end
end
end

tokenizer :scan_ds_list do
if @input.match?(/^ds-list: $/) && @input.scan(/^ds-list: \n/)
@ast["ds"] = []
while line = @input.scan(/^- (.*)\n/)
@ast["ds"] << @input[1].strip
end
end
end

tokenizer :scan_registrar do
if @input.match?(/^registrar: /) && @input.scan(/^registrar: .*\n/)
registrar = Parser::WhoisSmallregistryNet::Registrar.new
%w(name address phone fax mobile web trouble).each do |field|
ret = parse_string(field, 2)
registrar.send("#{field}=", ret) unless ret.nil?
end
@ast["registrar"] = registrar
end
end

{
'registrant' => Whois::Record::Contact::TYPE_REGISTRANT,
'administrative_contact' => Whois::Record::Contact::TYPE_ADMIN,
'technical_contact' => Whois::Record::Contact::TYPE_TECHNICAL,
'billing_contact' => nil,
}.each do |type, id|
tokenizer :"scan_#{type}" do
if @input.match?(/^#{type}: /) && @input.scan(/^#{type}: .*\n/)
contact = Record::Contact.new
contact.type = id
[
['nic-handle', :id=],
['name', :name=],
['company', :organization=],
['type', nil],
['address', :address=],
['phone', :phone=],
['fax', :fax=],
['mobile', nil],
].each do |k,v|
ret = parse_string(k, 2)
contact.send(v, ret.strip) unless ret.nil? || v.nil?
end
if @input.match?(/^ updated:\s+"(.*)"\n/) && @input.scan(/^ updated:\s+"(.*)"\n/)
contact.updated_on = DateTime.parse(@input[1].strip)
end
@ast["contact:#{type}"] = contact
end
end
end

private
def parse_string(k, spaces = 0)
if @input.match?(/^#{" "*spaces}#{k}: \|-/) && @input.scan(/^#{" "*spaces}#{k}: .*\n/)
val = ""
while line = @input.scan(/^#{" "*(spaces+2)}.*\n/)
val << line.sub(/^#{" "*(spaces+2)}/, '')
end
val.chomp
elsif @input.match?(/^#{" "*spaces}#{k}: /) && @input.scan(/^#{" "*spaces}#{k}: ("?)(.*)\1\n/)
@input[2]
end
end
end
end
end
end
end
105 changes: 105 additions & 0 deletions lib/whois/record/parser/whois.smallregistry.net.rb
@@ -0,0 +1,105 @@
#--
# Ruby Whois
#
# An intelligent pure Ruby WHOIS client and parser.
#
# Copyright (c) 2009-2012 Simone Carletti <weppos@weppos.net>
#++


require 'whois/record/parser/base'
require 'whois/record/parser/scanners/whois.smallregistry.net.rb'


module Whois
class Record
class Parser

# Parser for the whois.smallregistry.net server.
#
# @author Mathieu Arnold <m@absolight.fr>
#
class WhoisSmallregistryNet < Base
class Registrar < SuperStruct.new(:id, :name, :organization, :url, :address, :phone, :fax, :mobile, :trouble)
alias web= url=
end

include Scanners::Ast

property_supported :disclaimer do
node("field:disclaimer")
end


property_supported :domain do
node("field:domain")
end

property_not_supported :domain_id


property_supported :status do
if node?("status:not_found")
:available
elsif node?("field:status")
node("field:status").to_sym
else
:unknown
end
end

property_supported :available? do
status == :available
end

property_supported :registered? do
!available?
end

property_supported :created_on do
node("field:created")
end

property_supported :updated_on do
node("field:updated")
end

property_supported :expires_on do
node("field:expired")
end

property_supported :registrar do
node("registrar")
end

property_supported :registrant_contacts do
node("contact:registrant")
end

property_supported :admin_contacts do
node("contact:administrative_contact")
end

property_supported :technical_contacts do
node("contact:technical_contact")
end

# Seems nobody cares about that.
# property_supported :billing_contacts do
# node("contact:billing_contact")
# end

property_supported :nameservers do
node('nameservers') || []
end

# Also, there could be some DS records.

def parse
Scanners::WhoisSmallregistryNet.new(content_for_scanner).parse
end

end
end
end
end
@@ -0,0 +1,37 @@
#status
should: %s == :available

#available?
should: %s be_true

#registered?
should: %s be_false

#created_on
should: %s be_nil

#updated_on
should: %s be_nil

#expires_on
should: %s be_nil

#nameservers
should: %s be_a(Array)
should: %s be_empty

#registrar
should: %s be_nil

#registrant_contacts
should: %s be_a(Array)
should: %s be_empty

#admin_contacts
should: %s be_a(Array)
should: %s be_empty

#technical_contacts
should: %s be_a(Array)
should: %s be_empty

@@ -0,0 +1,21 @@
--- #YAML:1.0
# Welcome to the SMALLREGISTRY WHOIS Server. Datas are available in order to
# supply you with information purpose only, PROMOPIXEL is not responsible
# for its accuracy. Copy of whole or part of the data without permission from
# PROMOPIXEL is strictly forbidden. The sole owner of a domain is the entity
# described in the relevant "registrant:" record. Domain or subdomain
# ownership disputes should be settled by contacting SMALLREGISTRY registry:
# https://www.smallregistry.net, or PROMOPIXEL: http://www.promopixel.com
#
# Bienvenue sur le serveur WHOIS de SMALLREGISTRY. Les données fournies sont
# disponibles à titre informatif uniquement, PROMOPIXEL ne garantit pas leurs
# exactitudes. La copie de tout ou partie de la base de données est interdite
# sans l'autorisation expresse de PROMOPIXEL. Le seul propriétaire d'un domaine
# ou d'un sous-domaine est l'entité décrite dans l’enregistrement "registrant:"
# correspondant. Un différent sur la propriété d'un nom de domaine ou de
# sous-domaine peut être réglé en contactant le registre SMALLREGISTRY:
# https://www.smallregistry.net, ou PROMOPIXEL: http://www.promopixel.com
#
# 2012-01-20T12:24:07+01:00
# Object not found
--- ~