#!/usr/bin/env python

# Test Wikileaks _DNS_ mirrors. Not suitable for Web mirrors because
# it does not send the proper HTTP Host: header
__PROGRAM__ = "test-wikileaks"
__VERSION__ = "0.1"
__AUTHOR__ = "Stephane Bortzmeyer <stephane@bortzmeyer.org>"
# With help from Pierre Beyssac

# DNS Python http://www.dnspython.org/
import dns.resolver

import getopt
import urllib
import sys
import re

# Defaults
edns_size = 4096
domain = "all-wikileaks.bortzmeyer.fr"
path = "/cablegate.html"
pattern = "Currently released so far... ([0-9,]+) / [0-9,]+"
verbose = False
dnsrr = False
ttl = 600

def usage(msg=None):
    print >>sys.stderr, "Usage: %s [-v] [-s n] [-d] domain-name" % sys.argv[0]
    if msg is not None:
        print >>sys.stderr, msg

class AppURLopener(urllib.FancyURLopener):
    version = "%s/%s (test-wikileaks.py; Python %s; http://www.bortzmeyer.org/testing-wikileaks.html)" % (__PROGRAM__, __VERSION__, sys.version[0:5])

if int(sys.version[0:1]) < 2 or int(sys.version[2:3]) < 6:
    print >>sys.stderr, "Python 2.6 minimum required"
    sys.exit(1)

try:
    optlist, args = getopt.getopt (sys.argv[1:], "vs:hdt:",
                                   ["verbose", "size=", "help", "dns", "ttl"])
    for option, value in optlist:
        if option == "--help" or option == "-h":
            usage()
            sys.exit(0)
        elif option == "--size" or option == "-s":
            edns_size = int(value) # TODO: handle the possible conversion exception
            # to provide a better error message?
        elif option == "--ttl" or option == "-t":
            ttl = int(value)
        elif option == "--verbose" or option == "-v":
            verbose = True
        elif option == "--dns" or option == "-d":
            dnsrr = True
        else:
            # Should never occur, it is trapped by getopt
            print >>sys.stderr, "Unknown option %s" % option
            usage()
            sys.exit(1)
except getopt.error, reason:
    usage(reason)
    sys.exit(1)
if len(args) > 1:
    usage()
    sys.exit(1)
elif len(args) == 1:
    domain = args[0]

myresolver = dns.resolver.Resolver()
myresolver.use_edns(0, 0, edns_size)
urllib._urlopener = AppURLopener()
for address_family in ['A', 'AAAA']:
    try:
        answers = myresolver.query(domain, address_family)
        for rdata in answers:
            if address_family == 'A':
                url = "http://%s%s" % (rdata, path)
            else:
                url = "http://[%s]%s" % (rdata, path)
            if verbose:
                if dnsrr:
                  print >>sys.stderr, "; ",
                print >>sys.stderr, "Testing %s..." % url
            try:
                urldata = urllib.urlopen(url)
            except IOError:
                if dnsrr:
                  print >>sys.stderr, "; ",
                print >>sys.stderr, "Cannot open URL %s (network error)" % url
                continue
            if urldata.getcode() != 200:
                if dnsrr:
                    print >>sys.stderr, "; ",
                print >>sys.stderr, "Wrong result %i for %s" % (urldata.getcode(), url)
                continue
            data = urldata.read()
            match = re.search(pattern, data)
            if match:
                if verbose:
                    print ""
                if verbose and not dnsrr:
                    print "%s cables on %s" % (match.group(1), rdata)
                if dnsrr:
                     print " %d %s %s ; %s cables today" % (ttl, address_family,
                                                            rdata, match.group(1))
            else:
                if dnsrr:
                    print >>sys.stderr, "; ",
                print >>sys.stderr, "Wrong data in %s, not a Wikileaks mirror?" % url
    except dns.resolver.NoAnswer:
        pass
    

