#!/usr/bin/perl
# $Id: ekgsearch,v 1.5 2002/09/24 16:31:22 wysek Exp $
# skrypt do szukania osb w katalogu publicznym GG
#  na podstawie opisu ekg-20020705/docs/html.txt [1]
# (C) Piotr Wysocki, wysek@linux.bydg.org, http://wysek.thanedd.sk

# Rnice midzy opisem [1] a moim skryptem:
# 1) cyfra statusu: 1-niedostpny, 2-dostpny, 3-zajty
# 2) pole NextStart w odpowiedzi wystpuje, gdy ilo pasujcych rekordw > 20
# i wynosi ono 0 :), bior poprostu w nowym szukaniu jako start ostatni UIN z
# uprzednio otrzymanej listy rekordw

# TODO:
# - doj do tego, jakie cyfry statusu co oznaczaj (nie mam pewnoci)
# - uy moduu Net::HTTP (?)
#
# Dodatkowe opcje:
# opcja --debug zamiast [ndz] pokazuje [123] w rubryce pci
# opcja --show nie przetwarza wyniku, wywietla na ekran to, co otrzymuje
# 		(nie ma obsugi --all, nie reaguje na --debug)

use IO::Socket;

my $host = "pubdir.gadu-gadu.pl";
my $path = "/appsvc/fmpubquery2.asp";

my ($mode, $uin, $first, $last, $nick, $city, $born1) = undef;
my ($born2, $phone, $email, $active, $gender, $start) = undef;
my ($all, $nextstart, $lastuin) = undef;
my ($debug,$show) = undef; #debugging options

# wczytanie parametrw
usage() unless (@ARGV);
for ($i=0;$i<=$#ARGV;$i+=2)
{
	usage()
		if (($ARGV[$i] eq "-h") || ($ARGV[$i] eq "--help"));
	if ($i < $#ARGV)
	{	if (($ARGV[$i] eq "-u") || ($ARGV[$i] eq "--uin"))
		{
			usage() if (defined $uin);
			$mode = 3;
			$uin = $ARGV[$i+1];
			next;
		}
		if (($ARGV[$i] eq "-s") || ($ARGV[$i] eq "--start"))
		{
			usage() if (defined $start);
			$start = $ARGV[$i+1];
			next;
		}
		if (($ARGV[$i] eq "-f") || ($ARGV[$i] eq "--first"))
		{
			usage() if (defined $first);
			$first = $ARGV[$i+1];
			next;
		}
		if (($ARGV[$i] eq "-l") || ($ARGV[$i] eq "--last"))
		{
			usage() if (defined $last);
			$last = $ARGV[$i+1];
			next;
		}
		if (($ARGV[$i] eq "-n") || ($ARGV[$i] eq "--nick"))
		{
			usage() if (defined $nick);
			$nick = $ARGV[$i+1];
			next;
		}
		if (($ARGV[$i] eq "-c") || ($ARGV[$i] eq "--city"))
		{
			usage() if (defined $city);
			$city = $ARGV[$i+1];
			next;
		}
		if (($ARGV[$i] eq "-b") || ($ARGV[$i] eq "--born"))
		{
			usage() if (defined $born1);
			@born = split(/:/,$ARGV[$i+1]);
			$born1 = @born[0];
			$born2 = @born[1];
			usage() if ($born1 > $born2);
			next;
		}
		if (($ARGV[$i] eq "-p") || ($ARGV[$i] eq "--phone"))
		{
			usage() if (defined $phone);
			$phone = $ARGV[$i+1];
			next;
		}
		if (($ARGV[$i] eq "-e") || ($ARGV[$i] eq "--email"))
		{
			usage() if (defined $email);
			$email = $ARGV[$i+1];
			next;
		}
	}
	if (($ARGV[$i] eq "-a") || ($ARGV[$i] eq "--active"))
	{
		usage() if (defined $active);
		$active = 1;
		$i--;
		next;
	}
	if (($ARGV[$i] eq "-F") || ($ARGV[$i] eq "--female"))
	{
		usage() if (defined $sex);
		$sex = 1;
		$i--;
		next;
	}
	if (($ARGV[$i] eq "-M") || ($ARGV[$i] eq "--male"))
	{
		usage() if (defined $sex);
		$sex = 2;
		$i--;
		next;
	}
	if ($ARGV[$i] eq "--debug")
	{
		usage() if (defined $debug);
		$debug = 1;
		$i--;
		next;
	}
	if (($ARGV[$i] eq "--all") || ($ARGV[$i] eq "-A"))
	{
		usage() if (defined $all);
		$all = 1;
		$i--;
		next;
	}
	if ($ARGV[$i] eq "--show")
	{
		usage() if (defined $show);
		$show = 1;
		$i--;
		next;
	}
	usage();
}

again:
$start = $nextstart if (defined $nextstart);
$nextstart = undef;

$sock = IO::Socket::INET->new(PeerAddr => $host,
				PeerPort => 80,
				Proto => "tcp")
				or die "Nieudana prba poczenia: $!\n";
$length = length("Mode=&UserId=&start=") + length($start);
$tosend = "POST $path HTTP/1.0\r\nHost: $host\r\n";
$tosend .= "Content-Type: application/x-www-form-urlencoded\r\n";
$tosend .= "User-Agent: Mozilla/4.0 (compatible; MSIE 5.0; Windows 98)\r\n";
$tosend .= "Content-Length: ";
if ($mode == 3)
{
	$content = "Mode=$mode&UserId=$uin";
	$content .= "&start=$start" if (defined $start);
} else
{
	$sex = -1 unless $sex;
	$born1 = 0 unless $born1;
	$born2 = 0 unless $born2;
	$mode = 0;
	map { s/ /%20/g } $first,$last,$nick,$city,$phone,$email;
	$content = "Mode=$mode&FirstName=$first&LastName=$last&NickName=$nick&Gender=$sex&City=$city&MinBirth=$born1&MaxBirth=$born2";
	$content .= "&ActiveOnly=$active" if (defined $active);
	$content .= "&start=$start" if (defined $start);
}
$tosend .= length($content) . "\r\nPragma: nocache\r\n\r\n" . $content;
$tosend =~ tr//\xa5\xb9\x8c\x9c\x8f\x9f/; # cp_to_iso
$sock->print($tosend);
if ($show)
{
	print $_ while (<$sock>);
	$sock->close();
	exit;
}
$in = <$sock>;
if (! $in =~ /HTTP\/1\.[01] 200 OK/)
{
	print "Bd, otrzymaem: $in";
	$sock->close();
	exit;
}
# ommit the header
while (<$sock>)
{
	s/\r\n//;
	last if /^$/;
}
$in = <$sock>;
$in =~ s/\r\n//;
if (! $in =~ /^query_results:$/)
{
	print "Bd, otrzymaem: \"$in\" zamiast \"query_results:\"\n";
	exit;
}
for ($i=0;<$sock>;$i++)
{
	s/\r\n//;
	if (/^NextStart:[0-9]+$/)
	{
		s/^NextStart://;
		if ($_ == 0)
		{
			printf("koniec danych (NextStart:0)\n") if (defined $debug);
			$sock->close();
			exit;
		}
		$nextstart = $_;
		last;
	}
	if (/^1$/) { $status = "n"; }
	elsif (/^2$/) { $status = "d"; }
	elsif (/^3$/) { $status = "z"; }
	else
	{
		printf("Zdaje si, e %s pad.\n",$host);
		$sock->close();
		exit 1;
	}
	$status = "$_" if (defined $debug);
	# $ruin - received_uin, ...
	foreach $data ($ruin,$rname,$rsurname,$rnick,$ryear,$rsex,$rcity)
	{
		$data = <$sock>;
		$data =~ s/\r\n//;
		$data =~ tr/\xa5\xb9\x8c\x9c\x8f\x9f//; # iso_to_cp
	}
	if ($lastuin == $ruin)
	{
		printf("$lastuin == $ruin..\n") if (defined $debug);
		$sock->close();
		exit;
	}
	$lastuin = $ruin;
	if ($rsex =~ /^1$/) { $rsex = "k"; }
	elsif ($rsex =~ /^2$/) { $rsex = "m"; }
	else { $rsex = " "; }
	printf ("%s | %9d | %20.20s | %12.12s | %4d | %s | %15.15s\n",$status,
		$ruin,$rname . " " . $rsurname,$rnick,$ryear,$rsex,$rcity);
}
$sock->close();
$nextstart = $ruin unless $nextstart;
goto again if ($i > 19 && defined $all);

if (defined $debug)
{
	if ($i <= 19)
	{
		printf("koniec danych\n");
		printf("brak opcji --all\n") if (! defined $all);
	}
}
exit;

sub usage
{
	print "Uycie: $0 [opcje]\n";
	print "\t-u, --uin <numerek>\n";
	print "\t-f, --first <imi>\n";
	print "\t-l, --last <nazwisko>\n";
	print "\t-n, --nick <pseudonim>\n";
	print "\t-c, --city <miasto>\n";
	print "\t-b, --born <min:max>\n";
	print "\t-p, --phone <telefon>\n";
	print "\t-e, --email <e-mail>\n";
	print "\t-a, --active\n";
	print "\t-F, --female\n";
	print "\t-M, --male\n";
	print "\t-s, --start <od>\n";
	print "\t-A, --all\n";
	print "\t--debug\t\t/ informacji na temat tych opcji  \\\n";
	print "\t--show\t\t\\ zasignij w rdle tego skryptu /\n";
	exit;
}

