###########################################################################
##
## IDEA for irssi 
## Like MORSE plugin but uses IDEA :-)
##
## Including encode of Latin9 "characters" \xE5 \xE4 \xF6 \xC5 \xC4 \xD6
## to UTF-8 (or vice versa)
##
## RootBear / OH3NWQ Mar 2011
##
##
## See the color formats near the end of the script
##
## Based on MORSE for irssi by
## Goblet / OH2MMY  Dec 2001
##
## This script is published under EVVKTVH: http://evvk.com/evvktvh.html
## Insert your bug reports and/or complaints into your ass.
##
## FBI / CIA / Yo Momma is watching you!
##
## Syntax for the encryption keys on 	~/.irssi/scripts/ideakey.conf
##				 	#channel:key
##
##
## the instructions how to make the ~/bin/laden are in the ideaXXX.tgz 
## file
##
###########################################################################

use Irssi;
use Irssi::Irc;
use Irssi::UI;
use strict;
use Text::Iconv;
use Encode::Detect::Detector;

my $version = "8.0";

# variables use the following values:
# 1 = on / true
# 0 = off /false

# use the color theme for IDEA lines
my $use_theme = "1";

# utf8-conversion between utf8 and latin9 
my $utf8_to_l9 = "0";
my $l9_to_utf8 = "1";

# configuration file for the keys used in IRC channels
my $configfile = $ENV{HOME}.'/.irssi/scripts/ideakey.conf';

# try to decode using all keys in config file
my $try_all_keys = "0";

# shows the used key after the decoded message in square brackets
# works only when $try_all_keys is also set
my $keydebug = "0";

if ($utf8_to_l9 and $l9_to_utf8) {  
  die "Insufficient user IQ error.\n"; 
}

my $conv_to_l9 = Text::Iconv->new("UTF-8", "ISO-8859-15");
my $conv_to_utf8 = Text::Iconv->new("ISO-8859-15", "UTF-8");

sub find_chan_key {
        my($curr_chan) = @_;
        my $line;
	my $chan;
	my $xpass;
	# default key (also used if the configfile is missing)
        my $curr_pass="........";

        open (CONFIG,"<$configfile") or
		  return $curr_pass;

        foreach $line (<CONFIG>) {
                chomp($line);
                ($chan,$xpass) = split(/:/,$line);
                if ($curr_chan eq $chan) {
                        $curr_pass=$xpass;
                }
        }

        close CONFIG;
        return $curr_pass;
}

sub try_keys {
        my($input_line) = @_;
        my $line;
        my $chan;
        my $xpass;
	my $tryline;

        my $decoded_line = $input_line;

        open (CONFIG,"<$configfile") or
                  return $decoded_line;

        foreach $line (<CONFIG>) {
                chomp($line); 
                ($chan,$xpass) = split(/:/,$line);

		$tryline = `~/bin/laden \"decrypt :$input_line\" \"$chan\" \"$xpass\"`;
		if ($tryline ne "Decryption error:Unknown key\n") {
		if ($keydebug) {
				chomp $tryline;
				$decoded_line = "$tryline [$xpass]\n";
			} else {
				$decoded_line = $tryline;
			}
                }
        }

        close CONFIG;
        return $decoded_line;
}


sub encode_idea {
  my ($str,$own,$ch) = @_;
  my $pass = find_chan_key($ch);
  $str =~ s/\x60/'/g;
  $str =~ s/\\/\\\\/g;
  $str =~ s/\"/\\\"/g;
  $str = `~/bin/laden \"encrypt $ch $own :$str\" \"$ch\" \"$pass\"`;
  return $str;
}

sub decode_idea {
  my ($str,$ch) = @_;

  if ($try_all_keys) {
	$str = try_keys($str);	
  } else {
  	my $pass = find_chan_key($ch);
	$str = `~/bin/laden \"decrypt :$str\" \"$ch\" \"$pass\"`;
  }
  $str = substr($str, 0, -1);
  $str =~ s/^[^\:]*\:(.*)$/\1/s;

  my $encoding_name = Encode::Detect::Detector::detect($str);

    if ($l9_to_utf8) {
	if ( $encoding_name ne "UTF-8") {
	        $str = $conv_to_utf8->convert($str);
	}
    } 

    if ($utf8_to_l9) {
        if ( $encoding_name eq "UTF-8") {
	 	$str = $conv_to_l9->convert($str);
	}
    }

  return $str;
}

sub cmd_idea_say {
  my ($data,$server,$witem) = @_;
  my $window = Irssi::active_win();
  my $encoded;
  my $ch;
  my $own = Irssi::settings_get_str('nick');

  if (!$server || !$server->{connected}) {
      Irssi::print("Not connected to IRC server.");
      return;
  }

  if ($data && $witem->{type} eq "CHANNEL") {
      $ch = $witem->{name};

      $encoded = substr(encode_idea($data,$own,$ch), 0, -1);
        if ($encoded =~ /error/) {
                $window->printformat(MSGLEVEL_MSGS,'idea_own',"IDEA error: $encoded");
        } else {
                $encoded = substr $encoded, 1;
                $witem->command("^MSG ".$witem->{name}.
                     " $encoded");
        }
  } else {
      Irssi::print("No active channel in window.");
  }
  $window->printformat(MSGLEVEL_MSGS,'idea_own',$data);
}

sub sanitize {
  my ($input) = @_;
  $input =~ s/[^A-Za-z0-9\+\/\=\|\*\.]//g;
  return $input;
}

sub check_idea {
  my ($srv, $data, $nick, $addr) = @_;
  my ($dest, $text) = split(/ :/, $data, 2);
  my $server = Irssi::active_server();
  my ($dummy, $tag, $proto, $ver, $key, $txt) = split(/\|/,$text);
  if ($tag eq "*E*" && $proto eq "IDEA") {
    my $stext = sanitize($text);
    my $hit = decode_idea($stext,$dest);
        if (($hit eq "Decryption failed") or ($hit eq "Invalid message format") or ($hit eq "Unknown key") ) {
            $server->printformat($dest,MSGLEVEL_PUBLIC,'idea_no',$nick,$text);
        }
    $server->printformat($dest,MSGLEVEL_PUBLIC,'idea_pub',$nick,$hit);
    Irssi::signal_stop();
  }
}

if ($use_theme) {
  # Here you can change the color formats
  Irssi::theme_register([
    'idea_no',  '%n%w <$0> $1',
    'idea_own', '%yIDEA %n%w>%B $0-',
    'idea_pub', '%yIDEA %n%w<%W$0%w>%B $1-'
  ]);
} else {
  Irssi::theme_register([
    'idea_no',  '<$0> $1',
    'idea_own', 'IDEA > $0-',
    'idea_pub', 'IDEA <$0> $1-'
  ]);
}

Irssi::signal_add("event privmsg", "check_idea");
Irssi::command_bind("idea", "cmd_idea_say");
if ($l9_to_utf8) {
	Irssi::print("IDEA $version WTF-8 loaded :-P");
} else {
        Irssi::print("IDEA $version loaded :-P");
}
