#!/usr/local/bin/perl
#################################################################
#
# + FtpLocate - FTP search engine
#
# by Distributed System Lab E.E. NCKU Taiwan 2000
# http://ftp.ee.ncku.edu.tw/ftplocate/
#
#################################################################

use IO::Socket;
use CGI;

$URL = "http://moerbeke./cgi-bin/ftplocate/flserv.pl";

############################# subs ##############################

@MONTH{"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"}=(1,2,3,4,5,6,7,8,9,10,11,12);

sub sizestr {
  my $size=$_[0];
  my ($s, $n);

  if ( $size>=1024*1024*1024 ) {
    $n=int($size/1024/1024/1024*100+0.5)/100;
    $s=$n."GB";
  } elsif ( $size>=1024*1024 ) {
    $n=int($size/1024/1024*10+0.5)/10;
    $s=$n."MB";
  } elsif ( $size>=1024 ) {
    $n=int($size/1024*10+0.5)/10;
    $s=$n."k";
  } else {
    $s=int($size)."byte";
  }
  $s;
}

# http_open(url)
# return: a socket to web server or proxy
sub http_open {
  my ($server, $proxyserver, $proxyport, $remote_sock);  

  $_=$_[0]; 
  ($server, $script)=m!http://([^/]+)(/.*)!i;
  if ( $server eq "" ) {  return 0; }	# not http

  $_=$ENV{'http_proxy'};
  ($proxyserver, $proxyport)=m!http://([^/]+):(\d+)/.*!i;

  if ($proxyserver ne "" ) {	# if defined proxy, try proxy first!
    $remote_sock=new IO::Socket::INET(	Proto=>'tcp',
					PeerAddr=>$proxyserver,
					PeerPort=>$proxyport,);
    if ( $remote_sock ) {
      $remote_sock->autoflush(1);
      return $remote_sock;
    }
  }

  $remote_sock=new IO::Socket::INET(	Proto=>'tcp',
					PeerAddr=>$server,
					PeerPort=>80,);
  $remote_sock->autoflush(1) if ($remote_sock);
  return $remote_sock;
}

sub show_summary {
  my $url=$_[0];
  my ($remote_sock, $site, $info);
  my (@site, %avg, %count, %date, %dcount, %rate, %size);
  my ($totalcount, $totaldcount, $totalsize);
  my ($i, $s, $v);

  $remote_sock=http_open($url);
  die "socket create error($!)" unless($remote_sock);
  print stderr "Server connected\n";

  print $remote_sock "GET $url?cmd=get_summary HTTP/1.0\n\n";
  while (<$remote_sock>) {
    chop;
    if ( m!^Content-Type: text/plain!i ) { last; }
  }
    
  $i=0;
  while (<$remote_sock>) {
    chop;
    if ( $_ !~ "!!" ) { next; }
    ($site[$i],$info)=split(/!!/,$_,2);
    ($dcount{$site[$i]},$count{$site[$i]},$size{$site[$i]},$rate{$site[$i]},$date{$site[$i]})=split(/!!/,$info);
    $date{$site[$i]}=~s!\d\d\d\d/(\d\d/\d\d \d\d:\d\d):\d\d!$1!;

    if ( $count{$site[$i]} > 0 ) {
      $avg{$site[$i]}=$size{$site[$i]}/$count{$site[$i]};
    } else {
      $avg{$site[$i]}=0;
    }
    $totaldcount+=$dcount{$site[$i]};
    $totalcount+=$count{$site[$i]};
    $totalsize+=$size{$site[$i]};
    $i++;
  }
  die "data format error!\n" unless $i>0;

  printf("%2s %25s %6s %6s %8s %6s %6s %11s\n",
	"#", "FtpSite", "Dir", "File", "Total", "Avg", "Rate", "DataTime");
  $i=1;
  foreach $site (@site) {
    printf("%02d %25s %6s %6s %8s %6s %6s %11s\n",
	$i,substr($site,0,25), $dcount{$site}, $count{$site},
	sizestr($size{$site}),sizestr($avg{$site}),sizestr($rate{$site}),$date{$site});
    $i++;
  }

  $s=sizestr($totalsize);
  if ( $totalcount==0 ) {
    $v=0;
  } else {
    $v=sizestr($totalsize/$totalcount);
  }
  print "-"x78;
  print "\nDir: $totaldcount, File: $totalcount, Total: $s, Avg: $v\n";
}

sub show_flsearch {
  my ($url, $query)=@_;
  my ($query_raw, $remote_sock);
  my ($host,$path,$type,$size,$date);
  my ($y, $m, $d);
  my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) =localtime;
  $year+=1900; $mon++;

  $remote_sock=http_open($url);
  die "socket create error($!)" unless($remote_sock);
  print stderr "Server connected\n";

  $query_raw=CGI::escape($query);
  print $remote_sock "GET $url?cmd=exec_flsearch&query=$query_raw HTTP/1.0\n\n";
  while (<$remote_sock>) {
    chop;
    if ( m!^Content-Type: text/plain!i ) { last; }
  }
    
  while (<$remote_sock>) {
    chop;
    if ( $_ !~ "!!" ) { next; }
    ($host,$path,$type,$size,$date)=/(.*)\/\d+:\s*(.*)!!(.)!!(\d+)!!(.*)/;
    $path=~s!^\s*\.?/?!!;
    $size=sprintf("%8d", $size);
    ($m,$d,$y)=split(/\s+/,$date,3);
    if ( $y=~/\d\d\d\d/ ) {
      $date=sprintf("%04d%02d%02d",$y,$MONTH{$m},$d);
    } else {
      $date=sprintf("%04d%02d%02d",$year,$MONTH{$m},$d);
    }
    print "$date $size $host:/$path\n";
  }
}

############################# main ##############################

select(stderr); $|=1;
select(stdout); $|=1;

if ( defined($ENV{'REMOTE_ADDR'}) ) { exit; }	# cgi not allowed

$_=$URL;
($proto, $server, $script)=m!([\w]+)://([^/]+)(/.*)!;
die "$URL must be http://....\n" unless lc($proto) eq "http";

print stderr "+ FtpLocate - FTP search engine ($server)
by Distributed System Lab E.E. NCKU Taiwan 2000
http://ftp.ee.ncku.edu.tw/ftplocate/\n";

if ( $ARGV[0] eq "" ) {		# show banner at interactive mode
  $q=<>; chop($q);
} else {
  $q=$ARGV[0];
}

$q =~ s!\s+! !g; $q =~ s!^\s*!!; $q =~ s!\s*$!!; 

if ( $q eq "" ) {
  show_summary($URL);
} else {
  show_flsearch($URL, $q);
}

