#!/usr/local/bin/python """Canonicalize domain names. We maintain an in-memory data structure mapping domains to canonical domains. Whenever the web directory changes, we rebuild our data structure """ import os import stat import sys import traceback from commands import getoutput from os.path import basename, islink, isfile, join, realpath from pprint import pprint WWW = "/usr/local/www" class Base(object): __modtime = 0 def main(self, command): """Main loop per mod_rewrite > RewriteMap > prg. """ rebuild = self._canonizer if (command == 'canonizer') else self._porter while 1: host = sys.stdin.readline().strip() if self.isstale(): map_ = rebuild() print map_.get(host, 'NULL') sys.stdout.flush() def dump(self): """Build and print a domain map. """ pprint(self._canonizer()) pprint(self._porter()) def isstale(self): """Return a boolean based on whether the WWW directory has changed. """ _modtime = os.stat(WWW)[stat.ST_MTIME] if _modtime != self.__modtime: self.__modtime = _modtime return True else: return False def _canonizer(self): """Build a domain map from filesystem links. """ domain_map = dict() for name in os.listdir(WWW): if name.endswith('.flanderous.com'): canonical = name elif name.endswith('.zetaweb.com'): canonical = name else: canonical = basename(realpath(join(WWW, name))) if name != canonical: domain_map[name] = canonical # Automatically handle www for aliases. # ===================================== if name.startswith('www.'): www_alt = name[4:] else: www_alt = 'www.' + name if not islink(join(WWW, www_alt)): domain_map[www_alt] = canonical # Automatically handle www for canonical as well. # =============================================== if canonical.startswith('www.'): www_alt = canonical[4:] else: www_alt = 'www.' + canonical domain_map[www_alt] = canonical return domain_map def _porter(self): """Build a port map from conf files. """ port_map = dict() for hostname in os.listdir(WWW): home = realpath(join(WWW, hostname)) if hostname.endswith('.flanderous.com'): canonical = hostname else: canonical = basename(home) if canonical != hostname: continue port = None zope_conf = join(home, 'etc', 'zope.conf') aspen_conf = join(home, '__', 'etc', 'aspen.conf') if isfile(zope_conf): try: out = getoutput("grep -E 'address [0-9]{4,5}' %s" % zope_conf) port = out.strip().split()[1] port = int(port) assert 1024 < port < 65535 except: traceback.print_exc() elif isfile(aspen_conf): try: out = getoutput("grep -E 'address.*?[0-9]{4,5}' %s" % aspen_conf) port = out.split(':')[1] port = int(port) assert 1024 < port < 65535 except: traceback.print_exc() if port is not None: port_map[hostname] = port return port_map if __name__ == '__main__': try: command = sys.argv[1] except IndexError: command = basename(sys.argv[0])[:-3] assert command in ('porter', 'canonizer', 'dump'), command base = Base() base.dump() if (command == 'dump') else base.main(command)