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
Changes from 2 commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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.
The same applies to 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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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 | ||
--- ~ |
There was a problem hiding this comment.
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.
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).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, done :-)