#!/usr/bin/perl -w
# Created by Ben Okopnik on Sun May  6 23:53:32 EDT 2007
$|++;
use lib "$ENV{HOME}/myperl/lib";
use Term::ReadKey;
use Crypt::CBC; 

$ENV{TERM} = 'xterm';

$search = shift;

unless ( $search ){
	print STDOUT "Usage: ", $0 =~ /([^\/]+)$/, " <search_term|-e>\n";
	sleep 2;
	exit 1;
}

# Read the password silently
print "Password: ";
ReadMode( 2 );
my $pass = ReadLine( 0 );
ReadMode( 0 );
print "\n";
# DES uses 8-byte keys, complains if they're longer
chomp( $pass = substr $pass, 0, 8 );

# Get the content of the 'pass' file
open Pass, "$ENV{HOME}/pass" or die "pass: $!\n";
$c = new Crypt::CBC( $pass );

{ 
	local $/; 
	@out = split /\n/, $c -> decrypt( <Pass> );
}
close Pass;

END { unlink "$ENV{HOME}/.pass_edit"; system "/usr/bin/clear"; }

if ( $search =~ /^-e$/ ) {
	# Check for lock...
	die "The file is currently being edited; please try again later.\n"
		if -e "$ENV{HOME}/.pass_edit";

	# ...and create one of our own if it doesn't exist.
	system ">$ENV{HOME}/.pass_edit";

	{
		system "/usr/bin/clear";
		$answer ||= ".";
		for ( 0 .. $#out ){
			printf "%3d. %s\n", $_, $out[$_] if $out[$_] =~ /$answer/;
		}
		undef $answer;

		print "\nNumber to edit, 'a' to add, 'f' to find, 's' to save, or 'q' to quit: ";
		chomp( my $todo = lc <STDIN> );

		$todo =~ s/^\s*(.*?)\s*$/$1/;

		unless ( $todo =~ /^(\d+|[afsq])$/ ){
			print "Unknown option '$todo'\n";
			sleep 1;
			redo;
		}
		print "\n";

		if	( $todo eq 'a' ) {
			add_entry();
		}
		elsif ( $todo eq 'f' ) {
			print "Search for: ";
			chomp( $answer = <STDIN> );
		}
		elsif ( $todo eq 's' ) {
			save();
		}
		elsif ( $todo eq 'q' ) {
			exit 0;
		}
		else {
			edit_entry($todo);
		}
		print "\n";

		redo;
	}
}
else {
	for (@out) {
		print "$_\n" if /$search/i;
	}
	print "\nPress 'Enter' to continue";
	<STDIN>;
	exit 0;
}

sub edit_entry {
	my $offset = shift;

	print "Can't find offset '$offset'\n", return
	  unless ( $offset >= 0 and $offset <= @out );

	print "Old entry:\n", "-" x 65, "\n$out[$offset]\n", "-" x 65, "\n";
	print "New entry ('XXX' to erase):\n", "-" x 65, "\n";

	chomp( my $entry = <STDIN> );
	if ( $entry =~ /^XXX$/ ) {
		print "Erasing...\n";
		splice @out, $offset, 1;
	}
	else {
		$out[$offset] = $entry;
	}
}

sub add_entry {
	print "What to add: ";
	chomp(my $str = <STDIN>);
	print "NOTHING ADDED", return unless $str =~ /\S/;
	push @out, $str;
}

sub save {
	open Pass, ">pass" or die "pass: $!\n";
	$c = new Crypt::CBC( $pass );
	print Pass $c -> encrypt( join "\n", sort @out );
	close Pass or die "Pipe close failed.\n";
}

