package Xchat::VPIT::Net;

use strict;
use warnings;

use List::Util      qw/max/;
use Locale::Country qw/code2country/;

use Xchat qw/:all/;

use lib get_info 'xchatdir';
use Xchat::XPI;
use Xchat::XPI::Net qw/resolve whois/;

our $VERSION = '0.02';

my $ph;

sub parse_url {
 local $_ = $_[0];
 return unless defined;
 my %h = ();
 if (s/^([^:]*)://) { $h{proto} = lc $1; }
 ($_, my @path) = grep length, (split m!/!);
 return unless defined;
 if (s/:([0-9]*)$// && length $1) { $h{port} = $1; }
 if (s/(.*)@([^@]*)$/$2/) { ($h{user}, $h{passwd}) = split /:/, $1, 2; }
 $h{host} = lc;
 $h{path} = \@path if @path;
 return \%h;
}

sub output {
 my ($motif, $head, @strings) = @_;
 $head = join ' ', ($motif x 3), $head, ($motif x 3);
 if (@strings) {
  my $l = max(map length, @strings) - length($head) - 1; # -1 for CR
  $head .= ($motif x $l) if $l > 0;
 }
 print $ph "\002$head\n", @strings;
}

hook_command 'DIG', sub {
 my @reqs = @{$_[0]};
 shift @reqs;
 return EAT_ALL unless @reqs;
 my @users = get_info('users');
 my $context = get_context;
 for (@reqs) {
  my $info = user_info $_;
  my $req = parse_url($info ? $info->{host} : $_);
  resolve $req->{host}, \&dig_print, [ $context, $req ];
 }
 return EAT_ALL;
}, {
 help_text => 'DIG <ip(s)/hostname(s)>, resolve given names/addresses'
};

sub dig_print {
 my $p = $_[0];
 my ($context, $req) = @{$_[1]};
 my $oldctxt = get_context;
 set_context $context;
 if ($p) {
  my @a = $p->answer;
  if (@a) {
   output '-', 'Results for ' . $req->{host},
             map { $_->string . "\n" } (@a, $p->authority, $p->additional);
  } else {
   output '*', 'Resolution failed for ' . $req->{host},
          map {
           $_->mname . ' IN SOA ' . $_->rname . "\n", 
           join ' ', 'serial:' . $_->serial, 'ref:' . $_->refresh,
                     'ret:' . $_->retry, 'exp:' . $_->expire,
                     'min:' . $_->minimum . "\n";
          } grep { $_->type eq 'SOA' } $p->authority;
  }
 } else {
  print $ph 'Request ' . $req->{host} . " timed out\n";
 }
 set_context $oldctxt;
}

hook_command 'NETWHOIS', sub {
 my @reqs = @{$_[0]};
 shift @reqs;
 return EAT_ALL unless @reqs;
 my $context = get_context;
 for (@reqs) {
  my $info = user_info $_;
  my $req = parse_url($info ? $info->{host} : $_);
  whois $req->{host}, \&netwhois_print, [ $context, $req ];
 } 
 return EAT_ALL; 
}, {
 help_text => 'NETWHOIS <ip(s)/hostname(s)>, retrieve domain/ip information'
};

sub netwhois_print {
 my $raw = $_[0];
 my ($context, $req) = @{$_[1]};
 my $oldctxt = get_context;
 set_context $context;
 if ($raw) {
  $raw =~ s/.*(Domain|inetnum)/$1/s;
  $raw =~ s/[\r\n]*\>\>\>.*//s;
  output '-', 'Results for ' . $req->{host},
         map {
          s/^\s+//; s/\s+$//;
          $_ . "\n";
         } grep { !/^\s*(#|%)/ } split /\r?\n/, $raw;
 } else {
  output '*', 'No results for ' . $req->{host};
 }
 set_context $oldctxt;
}

hook_command 'TLD', sub {
 my @reqs = @{$_[0]};
 shift @reqs;
 return EAT_ALL unless @reqs;
 for (@reqs) {
  my $info = user_info $_;
  my $host = parse_url($info ? $info->{host} : $_)->{host};
  my ($tld) = $host =~ /\.([a-z]+)\.*$/;
  next unless $tld;
  my $name = code2country $tld;
  print $ph $tld . ' is ' . ($name ? $name : 'unknown') . "\n";
 }  
 return EAT_ALL;
}, {
 help_text => 'TLD <hostname(s)>, give the TLD text representation of the hosts'
};

$ph = new Xchat::XPI name   => 'Networking tools',
                     tag    => 'Net',
                     desc   => 'DNS & Whois clients, TLD names',
                     author => 'Vincent Pit (VPIT)',
                     email  => 'perl@profvince.com',
                     url    => 'http://www.profvince.com';

1;
