Added reverse lookup

This commit is contained in:
Barry Warsaw 1998-03-11 16:46:04 +00:00
parent 664b36ff59
commit d2c210df62
1 changed files with 94 additions and 33 deletions

View File

@ -1,6 +1,6 @@
#! /usr/bin/env python #! /usr/bin/env python
"""Print the long name of an Internet domain. """Print mappings between country names and DNS country codes.
This script will take an Internet address and print out where in the This script will take an Internet address and print out where in the
world that message originated from, based on the top-level domain code world that message originated from, based on the top-level domain code
@ -10,8 +10,22 @@ found in the address. Addresses can be in any of the following forms:
host.domain.xx -- any Internet host or network name host.domain.xx -- any Internet host or network name
somebody@where.xx -- an Internet email address somebody@where.xx -- an Internet email address
If the country code is not recognizable, it will attempt a reverse lookup,
searching for the country name and printing a list of matching country codes.
You can force reverse mappings with the `-r' flag (see below).
For example:
% world tz us
tz originated from Tanzania, United Republic of
us originated from United States
% world united
Country codes are maintained by the RIPE Network Coordination Centre, Country codes are maintained by the RIPE Network Coordination Centre,
in coordination with the ISO 3166 Maintenance Agency at DIN Berlin. in coordination with the ISO 3166 Maintenance Agency at DIN Berlin. The
authoritative source of counry code mappings is:
<url:ftp://info.ripe.net/iso3166-countrycodes> <url:ftp://info.ripe.net/iso3166-countrycodes>
@ -28,22 +42,33 @@ Usage: %s [-d] [-p|-P file] [-h] addr [addr ...]
Print mapping of all top-level domains. Print mapping of all top-level domains.
--parse file --parse file
--p file -p file
--P file Parse an iso3166-countrycodes file extracting the two letter country
--Parse file code followed by the country name. Note that the three leter country
Parse an iso3166-countrycodes file (given as the argument). code and number, which are also provided in the standard format file,
This first the two letter country code (it ignores the three are ignored.
letter code), followed by the country name. With -P option,
output is in the form of a Python dictionary, and country --outputdict
names are normalized w.r.t. capitalization. This makes it -o
appropriate for cutting and pasting back into this file. With used in conjunction with the `-p' option, output is in the form
of a Python dictionary, and country names are normalized
w.r.t. capitalization. This makes it appropriate for cutting and
pasting back into this file.
--reverse
-r
Force reverse lookup. In this mode the address can be any Python
regular expression; this is matched against all country names and a
list of matching mappings is printed. In normal mode (e.g. without
this flag), reverse lookup is performed on addresses if no matching
country code is found.
-h -h
--help --help
Print this message. Print this message.
""" """
__version__ = '2.0' __version__ = '3.0'
__author__ = 'Barry Warsaw <bwarsaw@python.org>' __author__ = 'Barry Warsaw <bwarsaw@python.org>'
__source__ = '<url:http://www.python.org/~bwarsaw/pyware/>' __source__ = '<url:http://www.python.org/~bwarsaw/pyware/>'
@ -51,6 +76,12 @@ __source__ = '<url:http://www.python.org/~bwarsaw/pyware/>'
import sys import sys
import string import string
import getopt import getopt
try:
import re
except ImportError:
print sys.argv[0], 'requires Python 1.5'
sys.exit(1)
@ -59,28 +90,48 @@ def usage(status=0):
sys.exit(status) sys.exit(status)
def resolve(rawaddr): def resolve(rawaddr):
parts = string.splitfields(rawaddr, '.') parts = string.splitfields(rawaddr, '.')
if not len(parts): if not len(parts):
print 'No top-level domain in:', rawaddr # no top level domain found, bounce it to the next step
return return rawaddr
addr = parts[-1] addr = parts[-1]
if nameorg.has_key(addr): if nameorgs.has_key(addr):
print rawaddr, 'is from a', nameorg[addr], 'organization' print rawaddr, 'is from a', nameorgs[addr], 'organization'
elif country.has_key(addr): return None
print rawaddr, 'originated from', country[addr] elif countries.has_key(addr):
print rawaddr, 'originated from', countries[addr]
return None
else: else:
print 'Where in the world is %s?' % rawaddr # Not resolved, bounce it to the next step
return rawaddr
def reverse(regexp):
matches = []
cre = re.compile(regexp, re.IGNORECASE)
for code, country in all.items():
mo = cre.search(country)
if mo:
matches.append(code)
# print results
if not matches:
# not resolved, bounce it to the next step
return regexp
if len(matches) == 1:
code = matches[0]
print regexp, "matches code `%s', %s" % (code, all[code])
else:
print regexp, 'matches %d countries:' % len(matches)
for code in matches:
print " %s: %s" % (code, all[code])
return None
def parse(file, normalize): def parse(file, normalize):
try:
import re
except ImportError:
print 'Parsing requires Python 1.5'
sys.exit(1)
try: try:
fp = open(file) fp = open(file)
except IOError, (err, msg): except IOError, (err, msg):
@ -149,10 +200,12 @@ def main():
dump = 0 dump = 0
parsefile = None parsefile = None
normalize = 0 normalize = 0
forcerev = 0
opts, args = getopt.getopt(sys.argv[1:], opts, args = getopt.getopt(
'p:P:hd', sys.argv[1:],
['parse', 'Parse', 'PARSE', 'help', 'dump']) 'p:rohd',
['parse', 'reverse', 'outputdict', 'help', 'dump'])
for arg, val in opts: for arg, val in opts:
if arg in ('-h', '--help'): if arg in ('-h', '--help'):
help = 1 help = 1
@ -160,9 +213,10 @@ def main():
dump = 1 dump = 1
elif arg in ('-p', '--parse'): elif arg in ('-p', '--parse'):
parsefile = val parsefile = val
elif arg in ('-P', '--Parse', '--PARSE'): elif arg in ('-o', '--output'):
parsefile = val
normalize = 1 normalize = 1
elif arg in ('-r', '--reverse'):
forcerev = 1
if help: if help:
usage(status) usage(status)
@ -182,12 +236,16 @@ def main():
elif parsefile: elif parsefile:
parse(parsefile, normalize) parse(parsefile, normalize)
else: else:
map(resolve, args) if not forcerev:
args = filter(None, map(resolve, args))
args = filter(None, map(reverse, args))
for arg in args:
print 'Where in the world is %s?' % arg
# The mappings # The mappings
nameorg = { nameorgs = {
"arpa": "Arpanet", "arpa": "Arpanet",
"com": "commercial", "com": "commercial",
"edu": "educational", "edu": "educational",
@ -200,7 +258,7 @@ nameorg = {
country = { countries = {
"af": "Afghanistan", "af": "Afghanistan",
"al": "Albania", "al": "Albania",
"dz": "Algeria", "dz": "Algeria",
@ -442,6 +500,9 @@ country = {
"zw": "Zimbabwe", "zw": "Zimbabwe",
} }
all = nameorgs.copy()
all.update(countries)
if __name__ == '__main__': if __name__ == '__main__':
main() main()