-#################################################################\r
-# IP Lookup Plugin\r
-# ----------------------------\r
-# by Chris Gahan (chris@ill-logic.com)\r
-#\r
-# Purpose:\r
-# ------------------\r
-# Lets you lookup the owner and their address for any IP address\r
-# or IRC user.\r
-#\r
-#################################################################\r
-\r
-require 'socket'\r
-require 'resolv'\r
-\r
-#################################################################\r
-## ARIN Whois module...\r
-##\r
-\r
-module ArinWhois\r
-\r
- class Chunk < Hash\r
- def customer?\r
- keys.grep(/^(City|Address|StateProv|(Org|Cust)Name)$/).any?\r
- end\r
- \r
- def network?\r
- keys.grep(/^(CIDR|NetHandle|Parent)$/).any?\r
- end\r
-\r
- def contact?\r
- keys.grep(/^(R|Org)(Tech|Abuse)(Handle|Name|Phone|Email)$/).any?\r
- end\r
- \r
- def valid?\r
- customer? or network? or contact?\r
- end\r
- \r
- def owner\r
- self[keys.grep(/^(Org|Cust)Name$/).first]\r
- end\r
- \r
- def location\r
- "#{self['City']}, #{self['StateProv']}, #{self['Country']}"\r
- end\r
- \r
- def address\r
- "#{self['Address']}, #{location} #{self['PostalCode']}"\r
- end\r
- \r
- end\r
-\r
- class ArinWhoisParser\r
- \r
- def initialize(data)\r
- @data = data\r
- end\r
- \r
- def split_array_at(a, &block)\r
- return a unless a.any?\r
- a = a.to_a\r
- \r
- results = []\r
- last_cutpoint = 0\r
- \r
- a.each_with_index do |el,i|\r
- if block.call(el)\r
- unless i == 0\r
- results << a[last_cutpoint...i]\r
- last_cutpoint = i\r
- end\r
- end\r
- end\r
- \r
- if last_cutpoint < a.size or last_cutpoint == 0\r
- results << a[last_cutpoint..-1]\r
- end\r
- \r
- results\r
- end\r
- \r
- # Whois output format\r
- # ------------------------\r
- # Owner info block:\r
- # {Org,Cust}Name\r
- # Address\r
- # City\r
- # StateProv\r
- # PostalCode\r
- # Country (2-digit)\r
- #\r
- # Network Information:\r
- # CIDR (69.195.25.0/25)\r
- # NetHandle (NET-72-14-192-0-1)\r
- # Parent (NET-72-0-0-0-0)\r
- #\r
- # Contacts:\r
- # ({R,Org}{Tech,Abuse}{Handle,Name,Phone,Email})*\r
- \r
- def parse_chunks\r
- return if @data =~ /^No match found /\r
- chunks = @data.gsub(/^# ARIN WHOIS database, last updated.+/m, '').scan(/(([^\n]+\n)+\n)/m)\r
- chunks.map do |chunk|\r
- result = Chunk.new\r
- \r
- chunk[0].scan(/([A-Za-z]+?):(.*)/).each do |tuple|\r
- #puts tuple.inspect\r
- result[tuple[0]] = tuple[1].strip\r
- end\r
- \r
- result\r
- end\r
- end\r
- \r
- \r
- def get_parsed_data\r
- return unless chunks = parse_chunks\r
- \r
- results = split_array_at(parse_chunks) {|chunk|chunk.customer?}\r
- results.map do |chunks|\r
- {\r
- :customer => chunks.select{|x|x.customer?}[0],\r
- :net => chunks.select{|x|x.network?}[0],\r
- :contacts => chunks.select{|x|x.contact?}\r
- }\r
- end\r
- end\r
- \r
- # Return a hash with :customer, :net, and :contacts info filled in.\r
- def get_most_specific_owner\r
- return unless datas = get_parsed_data\r
- \r
- datas_with_bitmasks = datas.map do |data| \r
- bitmask = data[:net]['CIDR'].split('/')[1].to_i\r
- [bitmask, data]\r
- end\r
- #datas_with_bitmasks.sort.each{|x|puts x[0]}\r
- winner = datas_with_bitmasks.sort[-1][1]\r
- end\r
-\r
- end # of class ArinWhoisParser\r
-\r
-module_function\r
-\r
- def raw_whois(query_string, host)\r
- s = TCPsocket.open(host, 43)\r
- s.write(query_string+"\n")\r
- ret = s.read\r
- s.close\r
- return ret\r
- end\r
-\r
- def lookup(ip)\r
- data = raw_whois("+#{ip}", 'whois.arin.net')\r
- arin = ArinWhoisParser.new data\r
- arin.get_most_specific_owner\r
- end\r
- \r
- def lookup_location(ip)\r
- result = lookup(ip)\r
- result[:customer].location\r
- end\r
- \r
- def lookup_address(ip)\r
- result = lookup(ip)\r
- result[:customer].address\r
- end\r
-\r
- def lookup_info(ip)\r
- if result = lookup(ip)\r
- "#{result[:net]['CIDR']} => #{result[:customer].owner} (#{result[:customer].address})"\r
- else\r
- "Address not found."\r
- end\r
- end\r
-\r
-end\r
-\r
-\r
-\r
-#################################################################\r
-## The Plugin\r
-##\r
-\r
-class IPLookupPlugin < Plugin\r
+#################################################################
+# IP Lookup Plugin
+# ----------------------------
+# by Chris Gahan (chris@ill-logic.com)
+#
+# Purpose:
+# ------------------
+# Lets you lookup the owner and their address for any IP address
+# or IRC user.
+#
+#################################################################
+
+require 'socket'
+require 'resolv'
+
+#################################################################
+## ARIN Whois module...
+##
+
+module ArinWhois
+
+ class Chunk < Hash
+ def customer?
+ keys.grep(/^(City|Address|StateProv|(Org|Cust)Name)$/).any?
+ end
+
+ def network?
+ keys.grep(/^(CIDR|NetHandle|Parent)$/).any?
+ end
+
+ def contact?
+ keys.grep(/^(R|Org)(Tech|Abuse)(Handle|Name|Phone|Email)$/).any?
+ end
+
+ def valid?
+ customer? or network? or contact?
+ end
+
+ def owner
+ self[keys.grep(/^(Org|Cust)Name$/).first]
+ end
+
+ def location
+ [ self['City'], self['StateProv'], self['Country'] ].compact.join(', ')
+ end
+
+ def address
+ [ self['Address'], location, self['PostalCode'] ].compact.join(', ')
+ end
+
+ end
+
+ class ArinWhoisParser
+
+ def initialize(data)
+ @data = data
+ end
+
+ def split_array_at(a, &block)
+ return a unless a.any?
+ a = a.to_a
+
+ results = []
+ last_cutpoint = 0
+
+ a.each_with_index do |el,i|
+ if block.call(el)
+ unless i == 0
+ results << a[last_cutpoint...i]
+ last_cutpoint = i
+ end
+ end
+ end
+
+ if last_cutpoint < a.size or last_cutpoint == 0
+ results << a[last_cutpoint..-1]
+ end
+
+ results
+ end
+
+ # Whois output format
+ # ------------------------
+ # Owner info block:
+ # {Org,Cust}Name
+ # Address
+ # City
+ # StateProv
+ # PostalCode
+ # Country (2-digit)
+ #
+ # Network Information:
+ # CIDR (69.195.25.0/25)
+ # NetHandle (NET-72-14-192-0-1)
+ # Parent (NET-72-0-0-0-0)
+ #
+ # Contacts:
+ # ({R,Org}{Tech,Abuse}{Handle,Name,Phone,Email})*
+
+ def parse_chunks
+ return if @data =~ /^No match found /
+ chunks = @data.gsub(/^# ARIN WHOIS database, last updated.+/m, '').scan(/(([^\n]+\n)+\n)/m)
+ chunks.map do |chunk|
+ result = Chunk.new
+
+ chunk[0].scan(/([A-Za-z]+?):(.*)/).each do |tuple|
+ tuple[1].strip!
+ result[tuple[0]] = tuple[1].empty? ? nil : tuple[1]
+ end
+
+ result
+ end
+ end
+
+
+ def get_parsed_data
+ return unless chunks = parse_chunks
+
+ results = split_array_at(parse_chunks) {|chunk|chunk.customer?}
+ results.map do |chunks|
+ {
+ :customer => chunks.select{|x|x.customer?}[0],
+ :net => chunks.select{|x|x.network?}[0],
+ :contacts => chunks.select{|x|x.contact?}
+ }
+ end
+ end
+
+ # Return a hash with :customer, :net, and :contacts info filled in.
+ def get_most_specific_owner
+ return unless datas = get_parsed_data
+
+ datas_with_bitmasks = datas.map do |data|
+ bitmask = data[:net]['CIDR'].split('/')[1].to_i
+ [bitmask, data]
+ end
+ #datas_with_bitmasks.sort.each{|x|puts x[0]}
+ winner = datas_with_bitmasks.sort[-1][1]
+ end
+
+ end # of class ArinWhoisParser
+
+module_function
+
+ def raw_whois(query_string, host)
+ s = TCPsocket.open(host, 43)
+ s.write(query_string+"\n")
+ ret = s.read
+ s.close
+ return ret
+ end
+
+ def lookup(ip)
+ data = raw_whois("+#{ip}", 'whois.arin.net')
+ arin = ArinWhoisParser.new data
+ arin.get_most_specific_owner
+ end
+
+ def lookup_location(ip)
+ result = lookup(ip)
+ result[:customer].location
+ end
+
+ def lookup_address(ip)
+ result = lookup(ip)
+ result[:customer].address
+ end
+
+ def lookup_info(ip)
+ if result = lookup(ip)
+ "#{result[:net]['CIDR']} => #{result[:customer].owner} (#{result[:customer].address})"
+ else
+ "Address not found."
+ end
+ end
+
+end
+
+
+
+#################################################################
+## The Plugin
+##
+
+class IPLookupPlugin < Plugin
def help(plugin, topic="")
"iplookup [ip address / domain name] => lookup info about the owner of the IP address from the ARIN whois database"
- end\r
- \r
- def iplookup(m, params)\r
- reply = ""\r
- if params[:domain]\r
- ip = Resolv.getaddress(params[:domain])\r
- reply += "(#{params[:domain]} = #{ip}) "\r
- else\r
- ip = params[:ip]\r
- end\r
- \r
- reply += ArinWhois.lookup_info(ip)\r
- m.reply reply\r
- end\r
-\r
- def userip(m, params)\r
- #users = @channels[m.channel].users\r
- #m.reply "users = #{users.inspect}"\r
- #m.reply @bot.sendq("WHO #{params[:user]}")\r
- end\r
- \r
-end\r
-\r
+ end
+
+ def iplookup(m, params)
+ reply = ""
+ if params[:domain]
+ begin
+ ip = Resolv.getaddress(params[:domain])
+ reply += "#{params[:domain]} | "
+ rescue => e
+ m.reply "#{e.message}"
+ return
+ end
+ else
+ ip = params[:ip]
+ end
+
+ reply += ArinWhois.lookup_info(ip)
+ m.reply reply
+ end
+
+ def userip(m, params)
+ #users = @channels[m.channel].users
+ #m.reply "users = #{users.inspect}"
+ #m.reply @bot.sendq("WHO #{params[:user]}")
+ end
+
+end
+
plugin = IPLookupPlugin.new
-plugin.map 'iplookup :ip', :action => 'iplookup', :requirements => {:ip => /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/}\r
-plugin.map 'iplookup :domain', :action => 'iplookup', :requirements => {:domain => /^[a-z0-9\.\-]{4,255}$/i}\r
+plugin.map 'iplookup :ip', :action => 'iplookup', :requirements => {:ip => /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/}
+plugin.map 'iplookup :domain', :action => 'iplookup', :requirements => {:domain => /^[a-z0-9\.\-]{4,255}$/i}
plugin.map 'userip :user', :action => 'userip', :requirements => {:user => /\w+/}
-\r
-\r
-if __FILE__ == $0\r
- include ArinWhois\r
- data = open('whoiscgm.txt').read\r
- c = ArinWhoisParser.new data\r
- puts c.get_parsed_data.inspect\r
-end
\ No newline at end of file
+
+
+if __FILE__ == $0
+ include ArinWhois
+ data = open('whoistest.txt').read
+ c = ArinWhoisParser.new data
+ puts c.get_parsed_data.inspect
+end