###########################################################################
##
## Blowfish for irssi 
## Like IDEA plugin but helps you to blow a fish :-)
##
## RootBear / OH3NWQ Aug 2009
##
## See the color formats near the end of the script
##
## Based on MORSE for irssi by
## Goblet / OH2MMY  Nov 2001
##
## Seems to support WTF8.
##
## This script is published under EVVKTVH license: http://evvk.com/evvktvh.html
## Insert your bug reports and/or complaints into your ass.
##
## Uses MIME::Base64
## Uses Crypt::OpenSSL::Blowfish
##
###########################################################################

use Irssi;
use Irssi::Irc;
use Irssi::UI;
use Crypt::OpenSSL::Blowfish;
use MIME::Base64;

use strict;

## enter here key that is used for Blowfish, exactly 8 characters
##                                         12345678
my $cipher = new Crypt::OpenSSL::Blowfish("passwd");

my $version = "1.0";
my $dec_status;
my $original;


sub encode_blowfish {
  my ($str) = @_;
  while ((length($str)) %8 != 0){
      $str = $str . " ";
  }

  my $blocks = length($str) / 8;

  my $encoded = "";
  my $substring;
  my $count;

  for ($count=0; $count<$blocks; $count++) {
	$substring = substr($str,($count)*8,8);

	$substring = $cipher->encrypt($substring);
	$encoded = $encoded . $substring;
  }
  return $encoded;
}


sub decode_blowfish {
  my ($str) = @_;

  if ((length ($str)) %8 != 0){
      return "BLOWFISH ERROR: invalid length ". length ($str)." bytes";
  }

  my $decoded = "";
  my $substring;
  my $count;
  my $blocks = length($str) / 8;

  for ($count=0; $count<$blocks; $count++) {
        $substring = substr($str,($count)*8,8);

	$substring = $cipher->decrypt($substring);
	$decoded = $decoded . $substring;
  }
  $dec_status = 1;
  return $decoded;
}


sub decode_wtf8 {
  my ($str) = @_;
        $str =~ s/\xC3\xA5/å/g;
        $str =~ s/\xC3\xA4/ä/g;
        $str =~ s/\xC3\xB6/ö/g;
        $str =~ s/\xC3\x85/Å/g;
        $str =~ s/\xC3\x84/Ä/g;
        $str =~ s/\xC3\x96/Ö/g;
        $str =~ s/\xE2\x82\xAC/¤/g;
        $str =~ s/\xC2\xB5/µ/g;    
        $str =~ s/\xC2\xA9/©/g;    
  return $str;
}


sub cmd_blowfish_say {
  my ($data,$server,$witem) = @_;
  my $window = Irssi::active_win();
  my $encoded;

  if (!$server || !$server->{connected}) {
      Irssi::print("Not connected to server");
      return;
  }
  if ($data && $witem->{type} eq "CHANNEL") {

      # blowfish
      $encoded = encode_blowfish($data);

      # b64
      $encoded = encode_b64($encoded);

      $witem->command("^MSG ".$witem->{name}.
                     " |*E*|BLOW|$version|$encoded|");
  } else {
      Irssi::print("No active channel in window");
  }
  $window->printformat(MSGLEVEL_MSGS,'blowfish_own',$data);
}


sub encode_b64 {
  my ($inp) = @_;
  my $str = encode_base64($inp);
  return $str;
}


sub decode_b64 {
  my ($inp) = @_;
  if ((length ($inp)) %4 != 0){
      return "blowfish B64 ERROR: invalid length ". length($inp)." bytes";
  }
  my $str = decode_base64($inp);
  return $str;
}


sub check_blowfish {
  my ($srv, $data, $nick, $addr) = @_;
  my ($dest, $text) = split(/ :/, $data, 2);
  my $server = Irssi::active_server();
  my ($dummy, $tag, $proto, $ver, $txt) = split(/\|/,$text);

  if ($tag eq "*E*" && $proto eq "BLOW") {
    $original = $text;
    $dec_status = 0;

    # b64
    $txt = decode_b64($txt);

    # blowfish
    $txt = decode_blowfish($txt);

    # wtf8
    $txt = decode_wtf8($txt);

    if ($dec_status) {
	$server->printformat($dest,MSGLEVEL_PUBLIC,'blowfish_pub',$nick,$txt);
    } else {
	$server->printformat($dest,MSGLEVEL_PUBLIC,'blowfish_error',$nick,$original);
    }

    Irssi::signal_stop();
  }
}


Irssi::theme_register([
  'blowfish_own', '%yblowfish %n%w>%g $0-',
  'blowfish_pub', '%yblowfish %n%c<$0>%n $1-',
  'blowfish_error', '%rBLOWFISH ERROR %n%c<$0>%n $1-'
]);


Irssi::signal_add("event privmsg", "check_blowfish");
Irssi::command_bind("blowfish", "cmd_blowfish_say");
Irssi::print("Blowfish $version loaded :-P");


