#! /usr/bin/perl -w
# password grep utility
# author: rupi <rupi@servus.at>
# licence: gpl v.3 or later 
# http://www.gnu.org/licenses/gpl.html
#
# this tool reads an gpg encrypted file and greps for given arguments.
# the last column of the matching line is copied into the X primary selection.
use strict;
use warnings;
use Env qw( DISPLAY HOME );

# configuration
my $pwdir="$HOME/.p/";
my $filearg = shift(@ARGV);
$filearg =~ /^(\w+)$/;
my $pwfile = $pwdir . $1 . ".gpg";

die "can't read $pwfile\n" if ( ! -r $pwfile ); 
	

# clean path
$ENV{PATH} = "";

# regex helper vars
my $searchex = qq{ ^ };
my $sp = '\s';
my $w = '\w';
$w = qq{ [-+$w:@.] };
my $p = '\S';
$p = qq{ [$p]+ };

# read and parse commandline 
# construct search regex and color highlighted replace
my $i = 0;
while ( my $arg = shift(@ARGV) ) {
	$arg =~ /^($w+)/x; # sanitize
	if ( $i++ > 0 ) {
		$searchex = qq{ $searchex $sp+};
	}
	$searchex = qq{$searchex $arg$w*};
}
die "no arguments given" if ( $i == 0 );
# make $1 hold our desc and $2 our password
$searchex = qq{ ($searchex (?: $sp+ .*)?) $sp+ ($p) };

# open gpg encrypted file and search
my @matches = ();
my @passphrases = ();
open F, "/usr/bin/gpg -d $pwfile |" || die("can't open gpg pipe");
while ( <F> ) {
	if ( /$searchex/x ) {
		push(@matches, "$1");
		push(@passphrases, $2);
	}
}
close(F);

# count matches -> make user select one if there are more matches
my $num = 0;
if ( @matches > 1 ) {
	$i = 0;
	print "several results found:\n";
	while ( $i < @matches ) {
		print " $i: $matches[$i++]\n";
	}
	print "select a result: ";
	my $ans = 0;
	read STDIN,$ans,1; # read one char (more than 10 matches == stupid search)
	if ( $ans =~ /^\d$/ && $ans < @matches ) {
		$num = $ans;
	} else {
		print STDERR "invalid input\n";
		exit(1);
	}
} 

# output key and write password to x primary selection
if ( @matches > 0 ) {
	print "\e[00;31mselected\e[00m $matches[$num]\n";

	if ( defined($DISPLAY) ) {
		open XSEL,"|/usr/bin/xsel -i" || die "can't open xsel";
		print XSEL "$passphrases[$num]";
		close XSEL;
	} else {
		print STDOUT "$passphrases[$num]\n";
	}
} else {
	print "no match found\n";
}
