|
|
|
@ -14,6 +14,10 @@ import dns.reversename
|
|
|
|
|
# http://code.google.com/p/netaddr/ https://github.com/drkjam/netaddr
|
|
|
|
|
import netaddr
|
|
|
|
|
|
|
|
|
|
# http://webob.org/
|
|
|
|
|
# Debian package python-webob
|
|
|
|
|
from webob import Request
|
|
|
|
|
|
|
|
|
|
# Internal modules
|
|
|
|
|
import Formatter
|
|
|
|
|
from LeakyBucket import LeakyBucket
|
|
|
|
@ -110,7 +114,7 @@ Disallow: /
|
|
|
|
|
send_response(start_response, '404 Not Found' , output, 'text/plain')
|
|
|
|
|
return [output]
|
|
|
|
|
|
|
|
|
|
def query(self, start_response, path, client, format="HTML", alt_resolver=None,
|
|
|
|
|
def query(self, start_response, req, path, client, format="", alt_resolver=None,
|
|
|
|
|
do_dnssec=False, tcp=False, cd=False, edns_size=default_edns_size,
|
|
|
|
|
reverse=False):
|
|
|
|
|
""" path must starts with a /, then the domain name then an
|
|
|
|
@ -119,22 +123,40 @@ Disallow: /
|
|
|
|
|
if not path.startswith('/'):
|
|
|
|
|
raise Exception("Internal error: no / at the beginning of %s" % path)
|
|
|
|
|
plaintype = 'text/plain; charset=%s' % self.encoding
|
|
|
|
|
if format == "TEXT" or format == "TXT":
|
|
|
|
|
format = "TEXT"
|
|
|
|
|
mtype = 'text/plain; charset=%s' % self.encoding
|
|
|
|
|
elif format == "HTML":
|
|
|
|
|
mtype = 'text/html; charset=%s' % self.encoding
|
|
|
|
|
elif format == "JSON":
|
|
|
|
|
mtype = 'application/json'
|
|
|
|
|
elif format == "ZONE":
|
|
|
|
|
mtype = 'text/dns' # RFC 4027
|
|
|
|
|
# TODO: application/dns, "detached" DNS (binary), see issue #20
|
|
|
|
|
elif format == "XML":
|
|
|
|
|
mtype = 'application/xml'
|
|
|
|
|
if not format:
|
|
|
|
|
mformat = req.accept.best_match(['text/html', 'application/xml',
|
|
|
|
|
'application/json', 'text/dns',
|
|
|
|
|
'text/plain'])
|
|
|
|
|
if mformat == "text/html":
|
|
|
|
|
format = "HTML"
|
|
|
|
|
elif mformat == "application/xml":
|
|
|
|
|
format = "XML"
|
|
|
|
|
elif mformat == "application/json":
|
|
|
|
|
format = "JSON"
|
|
|
|
|
elif mformat == "text/dns":
|
|
|
|
|
format = "ZONE"
|
|
|
|
|
elif mformat == "text/plain":
|
|
|
|
|
format = "TEXT"
|
|
|
|
|
if not mformat:
|
|
|
|
|
mformat = "text/html"
|
|
|
|
|
mtype = '%s; charset=%s' % (mformat, self.encoding)
|
|
|
|
|
else:
|
|
|
|
|
output = "Unsupported format \"%s\"\n" % format
|
|
|
|
|
send_response(start_response, '400 Bad request', output, plaintype)
|
|
|
|
|
return [output]
|
|
|
|
|
if format == "TEXT" or format == "TXT":
|
|
|
|
|
format = "TEXT"
|
|
|
|
|
mtype = 'text/plain; charset=%s' % self.encoding
|
|
|
|
|
elif format == "HTML":
|
|
|
|
|
mtype = 'text/html; charset=%s' % self.encoding
|
|
|
|
|
elif format == "JSON":
|
|
|
|
|
mtype = 'application/json'
|
|
|
|
|
elif format == "ZONE":
|
|
|
|
|
mtype = 'text/dns' # RFC 4027
|
|
|
|
|
# TODO: application/dns, "detached" DNS (binary), see issue #20
|
|
|
|
|
elif format == "XML":
|
|
|
|
|
mtype = 'application/xml'
|
|
|
|
|
else:
|
|
|
|
|
output = "Unsupported format \"%s\"\n" % format
|
|
|
|
|
send_response(start_response, '400 Bad request', output, plaintype)
|
|
|
|
|
return [output]
|
|
|
|
|
ip_client = netaddr.IPAddress(client)
|
|
|
|
|
if ip_client.version == 4:
|
|
|
|
|
ip_prefix = netaddr.IPNetwork(client + "/28")
|
|
|
|
@ -310,8 +332,6 @@ Disallow: /
|
|
|
|
|
resolver = None
|
|
|
|
|
resolver = queries.get("server", [''])[0]
|
|
|
|
|
format = queries.get("format", [''])[0].upper()
|
|
|
|
|
if format == "":
|
|
|
|
|
format = "HTML"
|
|
|
|
|
dodnssec = queries.get("dodnssec", '')
|
|
|
|
|
do_dnssec = not(len(dodnssec) == 0 or dodnssec[0] == "0" or \
|
|
|
|
|
dodnssec[0].lower() == "false" or dodnssec[0] == "")
|
|
|
|
@ -362,8 +382,7 @@ Disallow: /
|
|
|
|
|
# directive, 'Alias /robots.txt
|
|
|
|
|
# /usr/local/www/documents/robots.txt" etc.
|
|
|
|
|
pure_path = path[len(self.base_url):]
|
|
|
|
|
# TODO: content negotiation, see issue #10
|
|
|
|
|
return self.query(start_response, pure_path, client, format, resolver,
|
|
|
|
|
return self.query(start_response, Request(environ), pure_path, client, format, resolver,
|
|
|
|
|
do_dnssec, tcp, cd, edns_size, reverse)
|
|
|
|
|
else:
|
|
|
|
|
return self.default(start_response, path)
|
|
|
|
|