use strict;
use Digest::MD5 qw(md5 md5_hex md5_base64);
use vars qw($VERSION %IRSSI);

#------------------------------------------------------------------------------
# passfail.pl - Help prevent you entering your passwords into IRC by mistake
#
# Copyright (C) 2010 Christopher Carey
# http://chriscarey.com
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
#------------------------------------------------------------------------------
#
# INSTALL:
#
# Stick the script passfail.pl into your .irssi/scripts/ directory.
# Symlink it into the autorun directory so it will run every time the
# application starts.
#
# cp passfail.pl .irssi/scripts/
# cd .irssi/scripts/
# ln -s passfail.pl autorun/
# 
#------------------------------------------------------------------------------
# USAGE:
#
# Passfail has three basic commands: add, remove, and clearall.
#
# /passfail add <password>
#
# The previous command will add the password into the list of protected words.
# That password, if entered in the chat window, will not be sent to channel.
#
# /passfail remove <password>
#
# The previous command will remove the password from the list of protected words.
# If you type the password, it will be sent to channel.
#
# /passfail clearall
# 
# The previous command will clear the list of protected words (start over).
#
#------------------------------------------------------------------------------
#
# TESTING:
#
# Test and configure on the (status) window, and not in a channel with users in it!
#
#------------------------------------------------------------------------------
# 
# OTHER NOTES:
#
# You can manually load or unload the script with the following commands:
#
# /script load passfail.pl
# /script unload passfail
#
#

$VERSION = '20100803';
%IRSSI = (
	authors		=> 'Chris Carey',
	contact		=> 'chris@chriscarey.com',
	name		=> 'passfail',
	description	=> 'Prevent your password(s) from going over the wire accidentally',
	license		=> 'BSD',
	url		=> 'none',
	modules		=> 'Digest::MD5'
);

my @password_md5s;

sub settings_register () {
  # register the irssi settings (with defaults)
  Irssi::settings_add_str("passfail", "passfail_hashes", "");
}

sub event_send_text () {

  my ($line, $server_rec, $wi_item_rec) = @_;

  # convert the input to a md5 hex value
  my $line_md5 = md5_hex($line);

  # compare the input to the array of password hashes
  if (grep(/\b$line_md5\b/,@password_md5s)) {
    # user entered password
		Irssi::print("passfail.pl blocking password entry for hash ".$line_md5);
  } else {
    # user did not enter password
    return;
  }
	Irssi::signal_stop();
}

sub settings_load {
  # convert the comma separated hash list into an array
  @password_md5s = split(',', Irssi::settings_get_str('passfail_hashes'));
  Irssi::print(scalar(@password_md5s)." password(s) loaded");
}

sub settings_save {
  # convert the array to a comma seperated hash list and store it
  my $hashes = join(',', @password_md5s);
  Irssi::settings_set_str('passfail_hashes', $hashes);
  Irssi::print(scalar(@password_md5s)." password(s) saved");
}

sub cmd_passfail {
  # user typed the command /passfail

  my $usage = "/passfail [add|remove|clearall] <password>";
  my ($arguments, $server, $witem) = @_;
  my @foo = split(/ /, $arguments);
  my $cmd = @foo[0];
  my $pw = @foo[1];
  my $pw_md5 = md5_hex($pw);

  # sanity check on inputs
  if (!$arguments) {
    Irssi::print($usage);
    return;
  }
  if (length($cmd) eq 0 || length($pw eq 0)) {
    Irssi::print($usage);
    return;
  }

  # switch based on which command was specified
  if ($cmd eq "add") {
    # add password 
    if (grep(/$pw_md5/, @password_md5s)) {
      Irssi::print("Password already exists");
    } else {
      Irssi::print("Adding new password...");
      push(@password_md5s, $pw_md5);
      &settings_save();
    }

  } elsif ($cmd eq "remove") {
    # remove password
    Irssi::print("Removing password...");
    @password_md5s = grep { $_ ne $pw_md5 } @password_md5s;    
    &settings_save();

  } elsif ($cmd eq "clearall") {
    # clear all passwords
    Irssi::print("Clearing all passwords...");
    splice(@password_md5s);
    &settings_save();

  } else {
    
    Irssi::print($usage);
  }
}

# program start
settings_register();
settings_load();
Irssi::signal_add_first('send text', "event_send_text");
Irssi::command_bind("passfail", "cmd_passfail");
