#!/usr/local/bin/perl
#
# Tk GUI to access the NCSU whois server for convenient lookup
# of campus personnel and students.
#
# Perl/Tk version by Brabec 6/15/99
#    based on original Tcl/Tk code by TKM 2/10/98
#

use Tk;
use IO::Socket;

$whois_serv = 'whois.ncsu.edu';
$whois_port = '43';

$theName='';
$top = MainWindow->new();
$top->title('Whois @ NCSU.EDU');
$top->iconname('Whois');
$t = $top->Text(
       -width => 65,
       -height => 7,
       -background => 'white',
       -wrap => 'none',
       -font => 'fixed',
       -state => 'disabled',
     );
$f1 = $top->Frame();
$f1_l = $f1->Label( -text => 'Name (last, first)' );
$f1_e = $f1->Entry(
          -textvariable => \$theName,
          -background => 'white',
        );
$f1_e->bind('<Return>', \&do_whois);
$f2 = $top->Frame();
$f2_q = $f2->Button(
          -text => 'Query',
          -command => \&do_whois,
        );
$f2_c = $f2->Button(
          -text => 'Clear',
          -command => sub { 
                      $theName = ''; 
                      $t->configure( -state => 'normal' );
                      $t->delete( '1.0', end );
                      $t->configure( -state => 'disabled' );
                      },
        );
$f2_x = $f2->Button(
          -text => 'Exit',
          -command => sub { exit(0); },
        );
$f1_l->pack( -side => 'left', -padx => 2 );
$f1_e->pack( -side => 'left', -padx => 2 );
$f2_q->pack( -side => 'left', -expand => 1 );
$f2_c->pack( -side => 'left', -expand => 1 );
$f2_x->pack( -side => 'left', -expand => 1 );
$t->pack( -pady => 4, -padx => 4, -fill => 'x', -expand => 1 );
$f1->pack( -pady => 4, -padx => 4, -expand => 1 );
$f2->pack( -pady => 4, -padx => 4, -fill => 'x' );

if ($ARGV[0]) {  # we have a name on the command line
   $theName = $ARGV[0];
   &do_whois;
}

MainLoop();

sub do_whois {
   @who = query_whois('-ex', $theName);
   $type = 'NA';
   if ($who[0] =~ /TY:\s+(\S\S)/) { $type = $1; }
   if ($type eq 'LL') { print_who(@who); }
   elsif ($type eq 'SL') { handle_list(@who); }
   elsif ($type eq 'MC') { too_many(); }
   else { not_available(); }
}

sub query_whois {
   my ($flag, $name) = @_;
   $socket = IO::Socket::INET->new(Proto=>"tcp", PeerAddr=>$whois_serv, 
             PeerPort=>$whois_port);
   return () if (! $socket);
   $socket->autoflush;
   my $next = "\015\012";
   print $socket "$flag $name$next";
   my @res = <$socket>;
   return @res;
}

sub too_many {
   $t->configure( -state => 'normal' );
   $t->delete( '1.0', end );
   $t->insert( end, 'More than 30 names match, please be more specific...' );
   $t->configure( -state => 'disabled' );
}

sub not_available {
   $t->configure( -state => 'normal' );
   $t->delete( '1.0', end );
   $t->insert( end, 'No names match your query...' );
   $t->configure( -state => 'disabled' );
}

sub print_who {
   my (@who) = @_;
   my %hash = ();
   foreach $line (@who) {
      my ($key, $val) = split /:\s+/, $line, 2;
      $val =~ s/[\r\n]+$//;
      $hash{$key} = $val;
   }
   my ($phone, $fax) = split /\s+/, $hash{CP};
   $t->configure( -state => 'normal' );
   $t->delete( '1.0', end );
   $t->insert( end, "Name:   $hash{NM}\n" );
   $t->insert( end, "Title:  $hash{PO}\n" );
   $t->insert( end, "Dept:   $hash{DP}\n" );
   $t->insert( end, "Addr:   $hash{CA}\n" );
   $t->insert( end, "Phone:  $phone\n" );
   $t->insert( end, "Fax:    $fax\n" );
   $t->insert( end, "E-mail: $hash{EA}" );
   $t->configure( -state => 'disabled' );
}

sub handle_list {
   my (@who) = @_;
   if ($list) {
      $list->destroy();
      undef $list;
   }
   $list = $top->Toplevel( -class => 'Dialog' );
   $list_box = $list->Scrolled( Listbox, 
                   -width => 80,
                   -height => 6,
                   -font => 'fixed',
                   -background => 'white',
                   -scrollbars => 'e',
                 );
   $list_g = $list->Frame();
   $list_g_select = $list_g->Button(
                      -text => 'Select',
                      -command => \&do_select,
                    );
   $list_g_cancel = $list_g->Button(
                      -text => 'Cancel',
                      -command => sub { $list->destroy(); undef $list; },
                    );
   $list_g_select->pack( -side => 'left', -expand => 1 );
   $list_g_cancel->pack( -side => 'left', -expand => 1 );
   $list_box->pack( -fill => 'x' );
   $list_g->pack( -fill => 'x' );
   $list_box->bind('<Double-Button-1>', \&do_select);
   foreach $line (@who) {
      my ($id, $text) = ($line =~ /^\s*(\d+)\s+(.*)$/);
      next if ($id !~ /\d/);
      $text =~ s/[\r\n]+$//;
      $list_box->insert( end, $text );
   }
}

sub do_select {
   my $idx = $list_box->index('active') + 1; # shift over 0 index
   my ($id) = ($who[$idx] =~ /^\s*(\d+)\s/);
   my @info = query_whois('-id', $id);
   print_who(@info);
   $list->destroy();
   undef $list;
}
