Ruby ha un nuovo Whois

Vorrei segnalarvi che ho aperto ieri pubblicamente il repository di una
libreria Whois scritta in pure Ruby.
Il repository si trova all’indirizzo GitHub - weppos/whois: An intelligent — pure Ruby — WHOIS client and parser.
mentre
il progetto è http://code.simonecarletti.com/whois.
La libreria non è ancora stata rilasciata sotto forma di GEM.

In questi mesi sto lavorando ad un progetto Ruby/Rails che basa una
fetta
importante del suo funzionamento su interrogazioni whois per ottenere
informazioni sui domini. Quando cominciai, a maggio, investigai il
panorama
dei whois Ruby esistenti ed il risultato fu disastroso. Erano tutti
incompleti, non aggiornati o dipendenti da altre librerie come il
famosissimo package Whois per Linux sviluppato da Marco d’Itri.

Utilizzare il whois di Marco era un’alternativa, ma c’erano due problemi
a
riguardo

  1. Ruby non è molto veloce nell’eseguire chiamate a binari di sistema
    (ad
    esempio, motivo per cui GitHub ha sviluppato Grit)
  2. La soluzione non era flessibile (niente controllo sulla libreria,
    errori, eccezioni…)

Così ho deciso di sviluppare una soluzione in pure Ruby che potesse
offrire
la maggior parte delle funzioni necessarie. Ho anche contattato Marco
d’Itri
per alcune delucidazioni sul sorgente della sua lib C.

Mi piacerebbe avere qualche parere sul risultato. Qualcuno di voi ha mai
avuto esigenza di eseguire interrogazioni Whois?

La libreria sarà disponibile con licenza MIT. Ho contattato lo
sviluppatore
della GEM Whois originale che mi ha gentilmente concesso le chiavi del
progetto su RubyForge. La nuova libreria rimpiazzerà quindi l’attuale GEM
Whois offrendo un’API più completa ed aggiornata.

Conto di rilasciare la lib entro
lunedì.Ogni feedback o critica è bene accetta, inclusi eventuali commenti sul
codice.


Simone C.

Site & Blog: http://www.simonecarletti.com
Email: [email protected]
LinkedIn: http://linkedin.com/in/weppos
Nick: weppos | Skype: weppos

Simone C. wrote:

Mi piacerebbe avere qualche parere sul risultato. Qualcuno di voi ha mai
avuto esigenza di eseguire interrogazioni Whois?

Non ho ancora provato il tuo programma ma mi capita di fare query whois
per verificare l’esistenza di dominii e tutto sommato poterne dare un
elenco in pasto ad un programma potrebbe risparmiare un po’ di tempo.

Mi fa piacere vedere che usi redmine, è il sw che uso pure io per tutti
i miei progetti :slight_smile:

Paolo

Ciao Paolo,
sì, uso Redmine per i miei progetti ma anche in azienda lo usiamo come
issue
tracker per ogni progetto.

Approfitto per segnalarti che da qualche ora la nuova versione della
libreria è anche disponibile via RubyGems,

http://rubyforge.org/forum/forum.php?forum_id=34130

Quando avrai modo di provarla, fammi sapere cosa ne pensi. :slight_smile:

– Simone

2009/8/9 Paolo M. [email protected]

Paolo

Posted via http://www.ruby-forum.com/.


Ml mailing list
[email protected]
http://lists.ruby-it.org/mailman/listinfo/ml


Simone C.

Site & Blog: http://www.simonecarletti.com
Email: [email protected]
LinkedIn: http://linkedin.com/in/weppos
Nick: weppos | Skype: weppos

Simone C. wrote:

Ciao Paolo,
s�, uso Redmine per i miei progetti ma anche in azienda lo usiamo come
issue
tracker per ogni progetto.

Approfitto per segnalarti che da qualche ora la nuova versione della
libreria � anche disponibile via RubyGems,

Ruby has a new WHOIS library — Simone Carletti
http://rubyforge.org/forum/forum.php?forum_id=34130

Quando avrai modo di provarla, fammi sapere cosa ne pensi. :slight_smile:

Ciao Simone,

ho installato la gemma e l’ho provata. Funziona e i vantaggi rispetto ad
una ricerca manuale ci sono anche se non sono poi così grandi. Mi
piacerebbe infatti avere una risposta automatica sull’esistenza o meno
del dominio e poter estrarre delle informazioni dalla risposta del
server.

Non è semplice, dato che ogni registrar presenta i dati in un formato
diverso, ma ho sviluppato un rapido concept. API e implementazione sono
molto provvisori.

Nella dir della gemma aggiungiamo il file lib/info.rb (facendone require
in whois.rb) con questo contenuto


module Whois
class Info
attr_reader :registrar, :whois_server, :url, :name_servers,
:statuses,
:registrant, :technical_contact,
:administrative_contact,
:created_at, :updated_at, :expires_at

def initialize(info_lines)
  @registrant = []
  @technical_contact = []
  @administrative_contact = []
  @names = []
  @contact_ids = []
  @name_servers = []
  @statuses = []
  @exists = true
  info_lines.split("\n").each do |line|
    # available domain detection part 1
    if line.match /No match for/
      @exists = false
      break
    end
    name, value = line.split(": ")
    next unless value
    next if name.match /NOTICE|TERMS OF USE/
    @registrar = value if name.match /Registrar/
    @whois_server = value if name.match /Whois Server/
    @url = value if name.match /Referral URL/
    @registrant << value if name.match /Registrant/
    @technical_contact << value if name.match /Technical/
    @administrative_contact << value if name.match /Administrative/
    @name_servers << value if name.match /Name Server/
    @statuses << value if name.match /Status/
    @created_at = value if name.match /Creation Date|Created/
    @updated_at = value if name.match /Updated Date|Updated|Last 

Update/
@expires_at = value if name.match /Expiration
Date|Expires|Expire Date/
end
end

def exists?
  # available domain detection part 2, more euristics required
  return false if @statuses.length == 1 && @statuses[0].gsub(" ", 

“”) == “AVAILABLE”
@exists
end

end
end


poi siamo in grado di scrivere codice come


require ‘rubygems’
require ‘whois’

domain = ARGV[0]
response = Whois.whois(domain)
info = Whois::Info.new(response)
unless info.exists?
puts “No match for #{domain}”
exit
end

puts “Registrar #{info.registrar}”
puts “Server #{info.whois_server}”
puts “Registrant #{info.registrant.join(”, “)}”
puts “Tech contact #{info.technical_contact.join(”, “)}”
puts “Adm contact #{info.administrative_contact.join(”, “)}”
puts “Name servers #{info.name_servers.join(”, “)}”
puts “Status #{info.statuses.join(”, “)}”
puts “Created at #{info.created_at}”
puts “Updated at #{info.updated_at}”
puts “Expires at #{info.expires_at}”

e chiamare il programma con

$ ruby whois_test.rb google.com
$ ruby whois_test.rb simonecarletti.it
$ ruby whois_test.rb simonecarletti.com
$ ruby whois_test.rb asdfasdfasdf.com (sorpresa!)
$ ruby whois_test.rb asdfasdfasdf123123.com
$ ruby whois_test.rb asdfasdfasdf123123.it

Probabilmente l’euristica per estrarre le informazioni andrebbe messa in
una serie di adapter per i vari registrar (ora riesce ad estrarre
informazioni solo in pochi casi) e sicuramente si tratta di un
lavoraccio. Tuttavia se il progetto coinvolgesse molti sviluppatori ed
ognuno si scrivesse l’adapter per uno dei propri registrar lo sforzo per
il singolo sarebbe ragionevole. La cosa difficile sarà coordinare gli
sviluppi stabilendo l’organizzazione delle informazioni estratte. Nota
poi che il client whois di linux già fa un’aggregazione perché spesso
prima della risposta del server presenta un riassunto con un minimo di
informazioni. Ad esempio:

Domain Name: ASDFASDFASDF.COM
Registrar: NAMEVIEW, INC.
Whois Server: whois.nameview.com
Referral URL: http://www.nameview.com
Name Server: NS1.HITFARM.COM
Name Server: NS2.HITFARM.COM
Status: clientTransferProhibited
Updated Date: 12-mar-2009
Creation Date: 19-mar-2002
Expiration Date: 19-mar-2010

Chissà che scavando nei suoi sorgenti non si possa recuperare del codice
da portare a Ruby.

Un’ultima cosa: l’API della demo non mi soddisfa. Whois::Info potrebbe
sparire e i metodi per leggere i suoi attributi dovrebbero forse essere
metodi del client, ma in fondo è solo del codice scritto per spiegarmi
meglio.

Che ne dici? Comunque è già un buon progetto perché se non lo fosse non
ci si potrebbe costruire sopra del sw in un’oretta, post sul forum
incluso :slight_smile:

Ciao
Paolo

Come al solito… spettacolo !
Ho forkato la libreria, se posso contribuire fammi sapere :slight_smile:
In ogni caso adesso gli do’ un’occhiata

Sandro

2009/8/10 Simone C. [email protected]

Ciao Paolo

2009/8/10 Paolo M. [email protected]

Mi piacerebbe infatti avere una risposta automatica sull’esistenza o meno
del dominio e poter estrarre delle informazioni dalla risposta del
server.

hai perfettamente ragione ed è il prossimo macro obiettivo, l’unico
infatti
che ho voluto inserire nella Roadmap nella documentazione della lib.

Non è semplice, dato che ogni registrar presenta i dati in un formato
diverso,

Il punto è proprio questo. Inoltre si somma un problema. Quando il whois
server è di tipo thin, come nel caso dei .com o .tv, esistono due
risposte:
quella del whois padre e quella del whois specifico.
Entrambe sono ovviamente in formati specifici.

Non solo, GoDaddy risponde in modo diverso da Tucows dunque anche
all’interno della stessa estensione esistono differenze sostanziali.

Probabilmente l’euristica per estrarre le informazioni andrebbe messa in
una serie di adapter per i vari registrar (ora riesce ad estrarre
informazioni solo in pochi casi) e sicuramente si tratta di un
lavoraccio. Tuttavia se il progetto coinvolgesse molti sviluppatori ed
ognuno si scrivesse l’adapter per uno dei propri registrar lo sforzo per
il singolo sarebbe ragionevole. La cosa difficile sarà coordinare gli
sviluppi stabilendo l’organizzazione delle informazioni estratte.

In realtà il mio obiettivo sarebbe quello di non presentare un sistema
euristico bensì dotare la libreria di un parser per ogni whois server.
Fortunatamente, ogni whois ha una risposta univoca per cui la mia idea
era
di ritornare come risposta un oggetto che estende stringa (per
compatibilità
con l’implementazione attuale) che salvi al suo interno anche l’oggetto
@server.

Si potrà quindi fare

d = Whois::Client.new.query(“weppos.com”)

=> stringa registry

d = Whois::Client.new.find(“weppos.com”)

=> oggetto decomposto

d.available?

=> false

d.contacts.first.name

=> Simone C.

d.nameservers

=> [“192.168.0.1”, “192.168.0.1”]

L’API è provvisoria. L’idea è quella di avere una lista di oggetti/attributi
normalzzati al quale ricondurre ogni risposta del whois. Ovviamente ci
saranno alcuni shortcut come

Whois.whois(“weppos.com”)

=> stringa

Whois.available?(“weppos.com”)

=> false

Nota
poi che il client whois di linux già fa un’aggregazione perché spesso
prima della risposta del server presenta un riassunto con un minimo di
informazioni. Ad esempio:

Sì, è un bug noto. Al momento non concateno le risposte nel caso di un thin
server.
http://code.simonecarletti.com/issues/show/259

Che ne dici? Comunque è già un buon progetto perché se non lo fosse non

ci si potrebbe costruire sopra del sw in un’oretta, post sul forum
incluso :slight_smile:

Grazie! :slight_smile:


Simone C.

Site & Blog: http://www.simonecarletti.com
Email: [email protected]
LinkedIn: http://linkedin.com/in/weppos
Nick: weppos | Skype: weppos

2009/8/10 Sandro P. [email protected]

Ho forkato la libreria, se posso contribuire fammi sapere :slight_smile:

Un paio di mani ed una tastiera in più fanno sempre comodo. :smiley:

In ogni caso adesso gli do’ un’occhiata

Ogni feedback è bene accetto.

A proposito di questo vi segnalo che

  • E’ uscita la release 0.5.1 che integra una utility eseguibile da
    command line, ad esempio $ ruby-whois google.com. Utile soprattutto a
    chi
    non ha utility whois perché si trova su un sistema operativo Windows.
  • La nuova release corregge il problema segnalato da Paolo riguardo
    ai
    Whois thin (esempio il .com)

Dulcis in fundo, prima di fuggire al mare ho appena eseguito il commit
della
nuova architettura con il supporto ai parser.
Ho preparato, come esempio, un primissimo parser per i domini .it.
Il tutto è disponibile in una branch sperimentale
http://github.com/weppos/whois/tree/response

Ora è possibile eseguire comandi tipo

require ‘whois’

Whois.available? “weppos.it”

=> false

r = Whois.query(“weppos.it”)
r.available?

=> false

r.status

=> :active

r.expires_on

=> Time.new(“2009-12-21”)

Per commenti o altro è disponibile una mailing list specifica così evito di
monopolizzare questa. :wink:
http://groups.google.com/group/ruby-whois

Grazie a tutti i per i feedback ricevuti fino ad ora.


Simone C.

Site & Blog: http://www.simonecarletti.com
Email: [email protected]
LinkedIn: http://linkedin.com/in/weppos
Nick: weppos | Skype: weppos