# IP Locator script | Copyright C.Leonhardt Nov. 27 2006 - http://members.dandy.net/~fbn/iplocator.tcl.txt
#-----------------------------------------------------------------------------------------------------------------|
#
# Purpose: Gets IP Geo-Location data from AntiOnline or Geobytes databases. Don't expect 100% Accuracy!!!
#          Also note that both services below have USAGE QUOTAS. Don't complain to me if you let your users 
#          exceed the quota constantly and you find your address permanently banned from using these databases.
#          I made this script for my own personal use, if it helps you, great. I offer NO support for it!!!
#          And no, I do not check for valid input, if you feed the script garbage, you won't get any results.
#          -Rosc
#
# Nov 27 2006 - Added DNS Stuff's ip locator.
#
# Usage: Commands typed in channel or msg (see binds below)
#
# AntiOnline's IP Locator:  .iploc <hostname OR ip address>
#
# GeoByte's IP Locator:     .geoip <hostname OR ip address>
#
# DnsStuff's IP Locator:    .dnsip <hostname OR ip address>
#-----------------------------------------------------------------------------------------------------------------|
# Config |
#---------

# Channels where we allow public use.
set iplocchans "#Lady"

# Quiet chans (will only send responses to PRIVMSG.)
set iplocquiet "#gyuvetch"

# geturl timeout (1/1000th's of a second)
set ipltout "30000"
#-----------------------------------------------------------------------------------------------------------------|
# Begin script |
#---------------
package require http

bind pub - .iplocate iplocator
bind pub - .iploc iplocator
bind msg - .iploc iplocatormsg
bind msg - iploc iplocatormsg
bind msg - .iplocate iplocatormsg
bind pub - .geoip geoip
bind msg - .geoip geoipmsg
bind msg - geoip geoipmsg
bind pub - .dnsip dnsiploc
bind msg - .dnsip dnsiplocmsg
bind msg - dnsip dnsiplocmsg


proc iplocatormsg {nick uhost hand text} {
	if {![onchan $nick]} {return}
	if {$text == ""} {puthelp "PRIVMSG $nick :Please supply an IP number or hostname address.";return}
	iplocator $nick $uhost $hand privmsg $text
	return
}

proc iplocator {nick uhost hand chan text} {
	if {([lsearch -exact $::iplocchans $chan] == -1) && ($chan != "privmsg")} {return}
	if {([lsearch -exact $::iplocquiet $chan] != -1) || ($chan == "privmsg")} {set chan $nick}
	set text [split [string trim $text]]
	if {$text == ""} {puthelp "PRIVMSG $chan :Please supply an IP number or hostname address.";return}
	set iplocurl "http://antionline.com/tools-and-toys/ip-locate/index.php?address="
	set page ""
	catch {set page [::http::geturl $iplocurl$text -timeout $::ipltout]} error
	if {[string match -nocase "*couldn't open socket*" $error]} {
		puthelp "PRIVMSG $chan :Error: couldn't connect to AntiOnline.com..Try again later"
		::http::cleanup $page
		return
	}
	if { [::http::status $page] == "timeout" } {
		puthelp "PRIVMSG $chan :Error: Connection to AntiOnline.com timed out."
		::http::cleanup $page
		return
	}
	set html [::http::data $page]
	::http::cleanup $page
	set iplocation ""
	if {[regexp {<br><b>(.*?)<br><br>} $html - iplocation]} {
		set iplocation [string map {<b> "" </b> ""} $iplocation]
		puthelp "PRIVMSG $chan :AntiOnline results for '$text': $iplocation"
	} else {
		puthelp "PRIVMSG $chan :AntiOnline IP Locator: Location '[join $text]' could not be found. Sorry.."
	}
}

proc geoipmsg {nick uhost hand text} {
	if {![onchan $nick]} {return}
	if {$text == ""} {puthelp "PRIVMSG $nick :Please supply an IP number or hostname address.";return}
	geoip $nick $uhost $hand privmsg $text
	return
}

proc geoip {nick uhost hand chan text} {
	if {([lsearch -exact $::iplocchans $chan] == -1) && ($chan != "privmsg")} {return}
	if {([lsearch -exact $::iplocquiet $chan] != -1) || ($chan == "privmsg")} {set chan $nick}
	set text [split [string trim $text]]
	if {$text == ""} {puthelp "PRIVMSG $chan :Please supply an IP number or hostname address.";return}
	set geoquery [::http::formatQuery cid "0" c "0" Template "iplocator.htm" ipaddress "$text"]
	set geoipurl "http://www.geobytes.com/IpLocator.htm?GetLocation"
	set page ""
	catch {set page [::http::geturl $geoipurl -query $geoquery -timeout $::ipltout]} error
	if {[string match -nocase "*couldn't open socket*" $error]} {
		puthelp "PRIVMSG $chan :Error: couldn't connect to Geobytes.com..Try again later"
		::http::cleanup $page
		return
	}
	if { [::http::status $page] == "timeout" } {
		puthelp "PRIVMSG $chan :Error: Connection timed out to Geobytes.com."
		::http::cleanup $page
		return
	}
	set html [::http::data $page]
	::http::cleanup $page
	set iplocation "";set country "";set region "";set city "";set certainty ""
	if {[regexp {<html><head></head><body>The IP Address that you are currently using: .*? has exceeded} $html]} {
		puthelp "PRIVMSG $chan :Sorry, cannot do any more lookups on geobytes right now, quota exceeded.. \;/"
		return
	}
	if {[regexp {<p>We are unable to locate the address (.*?) at this time.*?<p>} $html]} {
		puthelp "PRIVMSG $chan :Sorry, geobytes could not find '[join $text]'"
		return
	}
	regexp {.*?>Country</td>.*? value="(.*?)" .*?>Region</td>.*? value="(.*?)" .*?>City</td>.*? value="(.*?)" .*?>Certainty</td>.*? value="(.*?)" .*?} $html match country region city certainty
	puthelp "PRIVMSG $chan :GeoBytes results for '$text': $city, $region, $country. Accuracy: $certainty\%"
	return
}

proc dnsiplocmsg {nick uhost hand text} {
	if {![onchan $nick]} {return}
	if {$text == ""} {puthelp "PRIVMSG $nick :Please supply an IP number or hostname address.";return}
	dnsiploc $nick $uhost $hand privmsg $text
	return
}

proc dnsiploc {nick uhost hand chan text} {
	if {([lsearch -exact $::iplocchans $chan] == -1) && ($chan != "privmsg")} {return}
	if {([lsearch -exact $::iplocquiet $chan] != -1) || ($chan == "privmsg")} {set chan $nick}
	set text [split [string trim $text]]
	if {$text == ""} {puthelp "PRIVMSG $chan :Please supply an IP number or hostname address.";return}
	if {[regexp {[^0-9\.]} $text]} {
		# Got hostname, resolve to ip..
		dnslookup $text checkresolved $nick $chan $text
		return
	} else {
		dnsiplocate $nick $chan $text
		return
	}
}

proc checkresolved {ipadd hostn status nick chan text} {
	if {$status} {
		dnsiplocate $nick $chan $ipadd
		return
	} else {
		puthelp "PRIVMSG $chan :Couldn't resolve '$text'"
		return
	}
}

proc dnsiplocate {nick chan text} {
	set dnssurl "http://www.dnsstuff.com/tools/city.ch?ip=$text"
	set page ""
	set page [::http::config -useragent "MSIE 6.0"]
	catch {set page [::http::geturl $dnssurl -timeout $::ipltout]} error
	if {[string match -nocase "*couldn't open socket*" $error]} {
		puthelp "PRIVMSG $chan :Error: couldn't connect to DNSStuff.com..Try again later"
		::http::cleanup $page
		return
	}
	if { [::http::status $page] == "timeout" } {
		puthelp "PRIVMSG $chan :Error: Connection to DNSStuff.com timed out."
		::http::cleanup $page
		return
	}
	set html [::http::data $page]
	::http::cleanup $page
	set iplocation "";set dnscountry "";set dnscity ""
	if {[regexp {IP:.*?Country:(.*?)City:(.*?)\n} $html match dnscountry dnscity]} {
		set dnscountry [string trim $dnscountry];set dnscity [string trim $dnscity]
		puthelp "PRIVMSG $chan :DNSStuff results for '$text': \002City:\002 $dnscity \002Country:\002 $dnscountry"
	} else {
		puthelp "PRIVMSG $chan :DNSStuff IP Locator: Location '[join $text]' could not be found. Sorry.."
	}
}


# add maxmind's db maybe?
putlog "IP-Locator script by SmasHinG loaded.."
