#!/usr/bin/perl
#===============================================================================
#  DESCRIPTION:  Anonymizer checker - скрипт для проверки списка анонимайзеров
#                на работоспособность. Имеется возможность создания списка
#                путём парсинга поисковой выдачи Google.
#
#        USAGE:  anocheck.pl -i [input_method] -g [good_proxy_file]
#                -b [bad_proxy_file]
#
#      OPTIONS:  -i [input_method]: google, ajax or .txt file
#                -g [good_proxy]: filename for save work proxy
#                -b [bad_proxy]: filename for save not work proxy
#
#       AUTHOR:  dimio
#          URL:  http://www.dimio.org
#      VERSION:  0.6
#      CREATED:  2010-08-25
#===============================================================================
require 5.8.8;
use warnings;
use strict;
use LWP::UserAgent;
use HTTP::Cookies;
use MIME::Base64;
use Getopt::Std;
use utf8;
#===============================================================================
$| = 1;
our $VERSION = 0.6;

my %options = (                     # Настройки по умолчанию:
    'i'     => 'good.txt',          # файл со списком анонимайзеров
    'g'     => 'good.txt',          # имя файла для вывода рабочих анонимайзеров
    'b'     => 'bad.txt',           # то же для нерабочих
);
getopts('i:g:b:rh', \%options);

# Вывод справки и завершение работы программы
if ($options{h}) {
    usage($VERSION);
    exit;
}

# Формат запроса для поиска определённых типов анонимайзеров
# 1 - на движке PHPProxy
my $phproxy_sreq = '"Rotate13" "Base64" "Strip" inurl:index.php?q=';
# 2 - на движке Glype
my $glype_sreq = '"Encode URL" "Allow Cookies" "Remove Scripts" inurl:browse.php?u=';

#===============================================================================
my %proxy_list;
my $ua = UAInit();

# Проверка на работоспособность анонимайзеров, перечисленных в указанном файле
if ( $options{i} ne 'google' && -s $options{i} ) {
    print 'Read proxy from '.$options{i},"...\n";
    ReadProxyFile(\%options, \%proxy_list);
    print "Done\n";
}
# Составление списка анонимайзеров при помощи веб-поиска Google
elsif ($options{i} eq 'google'){
    GetProxyList_Web($ua,\%proxy_list,$phproxy_sreq,$glype_sreq);
}
# Составление списка анонимайзеров через API Google
# (выдача очень маленькая по сравнению с веб-поиском)
elsif ($options{i} eq 'ajax') {
    GetProxyList_Ajax($ua,\%proxy_list,$phproxy_sreq);
}

# Проверка списка анонимайзеров на валидность, разделение рабочих и нерабочих
my $bad_proxy_list = CheckProxy($ua,\%proxy_list);

# Сохранение результатов проверки в файлах
SaveResult(\%options,\%proxy_list,$bad_proxy_list);


exit 0;
#===============================================================================

sub GetProxyList_Web {
    # Получение списка анонимайзеров через веб-поиск Google
    my ($ua,$proxy_list,$phproxy_sreq,$glype_sreq) = @_;

    # Поиск анонимайзеров. Разбит на 2 цикла для удобства возможного разнесения
    # результатов поиска в будущем.
    # 1 - искать основанные на движке PHProxy
    print "\nGetting PHProxy from Google search\n";
    for (my $page= 0; $page<= 400; $page+= 100){ # парсинг первых 5 страниц найденного
        print '.';

        my $google_search_string =
            'http://www.google.ru/search?num=100&start='.$page.'&q='.$phproxy_sreq;

        my $response = $ua->get($google_search_string);
            die "Error: $response->status_line\n" unless $response->is_success;
        my $source = $response->decoded_content;

        while ($source =~ m#<h3 class="r"><a href="(https?://w{0,3}\.?[\w-]+\.[a-z]{2,4}[/\w-]*/index\.php)\?q#ig) {
            $proxy_list->{$1}++;
        }
    }
    print "\nDone\n";

    # 2 - искать работающие на Glype
    print "\nGetting Glype proxy from Google search\n";
    for (my $page= 0; $page<= 400; $page+= 100){ # парсинг первых 5 страниц найденного
        print '.';

        my $google_search_string =
            'http://www.google.ru/search?num=100&start='.$page.'&q='.$glype_sreq;

        my $response = $ua->get($google_search_string);
            die "Error: $response->status_line\n" unless $response->is_success;
        my $source = $response->decoded_content;

        while ($source =~ m#<h3 class="r"><a href="(https?://w{0,3}\.?[\w-]+\.[a-z]{2,4}[/\w-]*/browse\.php)\?u#ig) {
            $proxy_list->{$1}++;
        }
    }
    print "\nDone\n";
}

sub GetProxyList_Ajax {
    #Получение списка анонимайзеров через GoogleAPI для поиска
    my ($ua,$proxy_list,$phproxy_sreq) = @_;

    my $gsstr =
    'http://ajax.googleapis.com/ajax/services/search/web?v=1.0&start=0&rsz=large&q=';

    my $response = $ua->get($gsstr.$phproxy_sreq);
        die "Error: $response->status_line\n" unless $response->is_success;
    my $source = $response->decoded_content;

    while ($source =~ m#"unescapedUrl":"(http://w{0,3}\.?[\w-]+\.[a-z]{2,4}[/\w-]*/index\.php)\?q#ig) {
        #push(@$proxy_list, $1);
        $proxy_list->{$1}++;
    }
}

sub SaveResult {
    #Сохранение результатов проверки списка анонимайзеров
    my ($options,$proxy_list,$bad_proxy_list) = @_;

    my ($min, $hour, $day, $month, $year) = (localtime)[1..5];

    open(GOOD,'>>',$options->{g});
        printf GOOD ( "#Checked: %04d-%02d-%02d %02d:%02d\n",
                      $year+1900, $month+1, $day, $hour, $min );
        print GOOD join("\n", keys %$proxy_list);
    close(GOOD);

    open(BAD,'>',$options->{b});
        printf BAD ( "#Checked: %04d-%02d-%02d %02d:%02d\n",
                      $year+1900, $month+1, $day, $hour, $min );
        print BAD join("\n",@$bad_proxy_list);
    close(BAD);

}

sub ReadProxyFile {
    #Считывание списка анонимайзеров из файла
    my ($options,$proxy_list) = @_;

    open(PROXY, '<', $options->{i}) or die "Can't open $options->{i}: $!\n";
        while(<PROXY>) {
            chomp;
            s/(#.*|^\s+|\s+$)//;
            next unless length;
            #push(@$proxy_list, $_);
            $proxy_list->{$_}++;
        }
    close(PROXY);
}

sub CheckProxy {
    #Проверка списка анонимайзеров на валидность с разделением на валидные
    #и невалидные
    my ($ua,$proxy_list) = @_;

    my @bad_proxy;

    print "\nChecking proxy...\n";

    foreach my $proxy_url (keys %$proxy_list) {

        my $response = $ua->get( $proxy_url.'?q='.encode_base64('http://www.google.com') );
            #warn "Error: $response->status_line\n" unless $response->is_success;

        if ($response->decoded_content =~ m#<title>Google</title>#) {
            printf ("%-45s %10s", $proxy_url, "\x1b[32m [OK]\x1b[0m\n");
        }
        else {
            printf ("%-45s %10s", $proxy_url, "\x1b[31m [ERROR]\x1b[0m\n");
            push(@bad_proxy, $proxy_url);
            delete($proxy_list->{$proxy_url});
        }
    }

    printf ( "Done. Proxy (good | bad): %3d | %-3d\n\n", scalar(keys %$proxy_list), scalar(@bad_proxy) );
    return \@bad_proxy;
}

sub UAInit {
    #Инициализация "браузера"
    my $cookies=HTTP::Cookies->new('file'=>'./cookies.lwp','autosave'=>0);
    my $browser=LWP::UserAgent->new('agent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.11) Gecko/2009060215 Firefox/3.0.11)',
                                 'cookie_jar' => $cookies,
                                 'requests_redirectable' => ['GET', 'POST']);
    $browser->default_header(
            'Accept' => 'text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1',
            'Accept-Charset' => 'utf-8; *;q=0.1',
            'Accept-Language' => 'ru,en-us;q=0.7,en;q=0.3',
            'Accept-Encoding' => 'deflate, gzip, x-gzip, identity, *;q=0',
            );
return ($browser);
}

sub usage {
    #Вывод справки по использованию программы
    my $ver = shift;

print <<EOF;
    Anonymizer checker ver. $ver by dimio (www.dimio.org)

    Использование: anocheck [КЛЮЧ]...

    Ключи:
            -i  [input_method]      \x1b[1mfilename\x1b[0m - имя входящего файла со списком анонимайзеров
                                    для проверки
                                    или
                                    \x1b[1mgoogle\x1b[0m - собрать список анонимайзеров при помощи
                                    поиска Google (может требовать ввод капчи)
                                    или
                                    \x1b[1majax\x1b[0m - запрос к GoogleAPI для получения списка
                                    анонимайзеров (не требует ввода капчи, выдаёт
                                    мало результатов);
            -g  [filename]          Имя файла для записи рабочих анонимайзеров
                                    (по умолчанию - good.txt);
            -b  [filename]          Имя файла для записи нерабочих анонимайзеров
                                    (по умолчанию - bad.txt);
            -h                      Вывод данной справки и завершение программы;

    Пример использования: anocheck -i google -g good_proxy.txt -b not_work.txt
EOF
}