#!/bin/bash
#
# $Id: proxtest,v 0.5 2009/04/11 09:59:19 st3f Exp $
#
# proxtest is a straightforward way to test HTTP proxy lists for usability.
# It will download and create (or use an existing) list of proxy addresses
# and ports. (They must be in "ipaddress:port" format.) The anonymity of
# each proxy is tested by connecting to a proxy judge CGI and looking for
# our own IP in the output. If this works out the proxy will be used to
# visit two test pages (Facebook and CNN by default) and measure the
# roundtrip time. The fastest anonymous proxies are saved to a log file,
# the rest are discarded.
#
# Copyright (c) 2009, Stefan Pettersson, http://www.bigpointyteeth.se/
#
# Permission to use, copy, modify, and distribute this software for any
# purpose with or without fee is hereby granted, provided that the above
# copyright notice and this permission notice appear in all copies.
#
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
#
# Example lists:
#  http://www.checkedproxylists.com/     good list but incorrect syntax
#  http://www.samair.ru/proxy/           so so but correct syntax
#  http://www.proxy4free.info/           so so but correct syntax
#
# Example judges:
#  http://www.cooleasy.com/cgi-bin/prxjdg.cgi
#  http://www.anonymitytest.com/cgi-bin/azenv.pl
#  http://anonymitytest.com/cgi-bin/prxjdg.cgi
#  http://polishtracker.org:81/cgi-bin/prxjdg.cgi
#  http://www.google.com/search?q=inurl%3Aprxjdg.cgi
#

PATH="/bin:/usr/bin:/usr/local/bin"
me=$(basename $0)

function usage() { echo "Usage: $me <proxies url|file> [proxyjudge url]"; }
function error() { echo "$me: $1" 1>&2; }

function logfilename() {
    if test -f $1; then
        i=1
        while test -f $1.$i; do
            i=$(($i + 1))
        done
        echo $1.$i
    else
        echo $1
    fi
}

tmpfile=$(mktemp /tmp/proxiesXXXXXXXX)
outfile=$(logfilename proxies)

function finish() {
    echo "Saving output to '$outfile'"
    sort -n $tmpfile > $outfile
    rm -f $tmpfile
    if test $(wc -c $outfile | awk '{print $1}') -eq 0; then
        echo "Removing empty file '$outfile'"
        rm -f $outfile
    fi
        
}

trap "error 'user abort'; finish; exit 1" 1 2 3 15

if test -z $1; then
    error "bad number of arguments"
    usage
    exit 1
fi

proxylist=$1

if test -z $2; then
    judge="http://www.cooleasy.com/cgi-bin/prxjdg.cgi"
else
    judge=$2
fi

useragent="Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)"
testurl1="http://www.facebook.com/"
testurl2="http://www.cnn.com/"

# if it's a file, open it, else treat it as an URL
if test -f $proxylist; then
    proxies=$(cat $proxylist)
else
    curl --silent -A "$useragent" $proxylist > $tmpfile
    proxies=$(egrep -o "[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}:[0-9]{2,5}" < $tmpfile)
    cat /dev/null > $tmpfile
fi

wc=$(echo $proxies | wc -w)

myip=$(curl --silent http://www.whatismyip.org/)
if test $(echo $myip | wc -c) -lt 16; then
    echo "Current IP address: $myip"
else
    error "cannot get own ip"
    exit 1
fi
echo "Found $wc proxy addresses"
echo "Saving good proxies to '$outfile'"
echo "--"


for proxy in $proxies; do
    ip=$(echo $proxy | cut -d ":" -f 1)
    curlcmd="curl --silent --connect-timeout 5 --max-time 10 --fail -A '$useragent' -x $proxy"
    echo -n "Judging $proxy... "
    output=$($curlcmd $judge)

    # if curl exited successfully
    if test $? -eq 0; then
        echo "done"
        # did our IP show up in the proxy judge?
        count=$(echo $output | grep -c $myip)
        if test $count -ge 1; then
            echo "Proxy leaks IP address, skipping"
        else
            echo -n "Timing against $testurl1... "
            rt=$(\time -f "\n%e second(s)" $curlcmd $testurl1 2>&1 | grep " second(s)")
            echo $rt

            if test $? -eq 0; then
                echo -n "Timing against $testurl2... "
                rt=$(\time -f "\n%e second(s)" $curlcmd $testurl2 2>&1 | grep " second(s)")
                echo $rt
                if test $? -eq 0; then 
                    echo -e "$rt\t$proxy\t$(host $ip | awk '{print $NF}')" >> $tmpfile
                fi
            fi
        fi
    else
        echo "failed"
    fi
    echo "--"
done

finish
echo "Finished testing proxies"
exit 0

# eof
