File-KeePass-Agent
view release on metacpan or search on metacpan
lib/File/KeePass/Agent/unix.pm view on Meta::CPAN
my $raw;
sub _term_raw { ReadMode 'raw', \*STDOUT; $raw = 1 }
sub _term_restore { ReadMode 'restore', \*STDOUT; ($raw, my $prev) = (0, $raw); return $prev }
sub init {
my $self = shift;
$self->{'no_menus'} = grep {$_ eq '--no_menus'} @ARGV;
}
sub prompt_for_file {
my ($self, $args) = @_;
my $last_file = $self->read_config('last_file');
if ($last_file && $last_file =~ m{ ^./..(/.+)$ }x) {
$last_file = $self->home_dir . $1;
}
$last_file = '' if $last_file && grep {$_->[0] eq $last_file} @{ $self->keepass };
my $file = $self->_file_prompt("Choose the KeePass database file to open: ", $last_file);
if ($last_file
&& $file
&& $last_file ne $file
&& -e $file
&& !$args->{'no_save'}
&& require IO::Prompt
&& IO::Prompt::prompt("Save $file as default KeePass database? ", -yn, -d => 'y', -tty)) {
my $home = $self->home_dir;
my $copy = ($file =~ m{^\Q$home\E(/.+)$ }x) ? "./..$1" : $file;
$self->write_config(last_file => $copy);
}
return $file;
}
sub prompt_for_pass {
my ($self, $file) = @_;
require IO::Prompt;
return ''.IO::Prompt::prompt("Enter your master password for $file: ", -e => '*', -tty);
}
sub prompt_for_keyfile {
my ($self, $file) = @_;
return $self->_file_prompt("Enter a master key filename (optional) for $file: ");
}
sub _file_prompt {
my ($self, $msg, $def) = @_;
#$msg =~ s/(:\s*)$/ [$def]$1/ or $msg .= " [$def] " if $def;
require Term::ReadLine;
my $was_raw = _term_restore();
my $out = Term::ReadLine->new('fkp')->readline($msg, $def);
_term_raw() if $was_raw;
$out = '' if ! defined $out;
$out =~ s/\s+$//;
$out =~ s{~/}{$self->home_dir.'/'}e;
return length($out) ? $out : $def;
}
sub home_dir {
my ($user,$passwd,$uid,$gid,$quota,$comment,$gcos,$home,$shell,$expire) = getpwuid($<);
return $home || croak "Couldn't find home dir for uid $<";
}
sub _config_file {
my $self = shift;
my $home = $self->home_dir;
return "$home/.keepassx/config" if -e "$home/.keepassx/config";
return "$home/.config/keepassx/config.ini";
}
my %map = (
last_file => 'LastFile',
pre_gap => 'AutoTypePreGap',
key_delay => 'AutoTypeKeyStrokeDelay',
);
sub read_config {
my ($self, $key) = @_;
my $c = $self->{'config'} ||= $self->_ini_parse($self->_config_file);
if (! $key) {
return $c;
} elsif (my $_key = $map{$key}) {
return $c->{'Options'}->{$_key};
}
elsif ($key eq 'global_shortcut') {
return if ! defined(my $key = $c->{'Options'}->{'GlobalShortcutKey'});
my $mod = $c->{'Options'}->{'GlobalShortcutMods'};
return if !$mod || $mod !~ m{ ^\@Variant\( \\0\\0\\0\\r\\0\\0\\0\\x5\\x? ([a-f0-9]+) \)$ }x; # non-portable - qvariant \r should be QBitArray, \x5 is 5 bits
my $val = hex($1);
my $s = {
key => chr($key),
ctrl => $val & 0b00001 ? 1 : 0,
shift => $val & 0b00010 ? 1 : 0,
alt => $val & 0b00100 ? 1 : 0,
altgr => $val & 0b01000 ? 1 : 0,
win => $val & 0b10000 ? 1 : 0,
};
@{ $s }{qw(ctrl alt)} = (1, 1) if delete $s->{'altgr'};
return $s;
} else {
die "Unknown key $key";
}
}
sub write_config {
my ($self, $key, $val) = @_;
my $c = $self->_ini_parse($self->_config_file, 1);
if (my $_key = $map{$key}) {
$c->{'Options'}->{$_key} = $val;
} else {
return;
}
$self->_ini_write($c, $self->_config_file);
delete $self->{'config'};
}
sub x {
shift->{'x'} ||= do {
my $x = X11::Protocol->new;
$x->{'error_handler'} = sub { my ($x, $d) = @_; die $x->format_error_msg($d) };
( run in 1.208 second using v1.01-cache-2.11-cpan-39bf76dae61 )