App-Greple-pw
view release on metacpan or search on metacpan
lib/App/Greple/PwBlock.pm view on Meta::CPAN
pattern => make_pattern(split /\s+/, config('id_keys')),
chars => config('id_chars'),
start_label => '0',
label_format => '[%s]',
color => config('id_color'),
label_color => config('id_label_color'),
blackout => 0,
);
}
sub parse_pw {
shift->parse_xx(
hash => 'pw',
pattern => make_pattern({IGNORE => [ 'URL' ]}, split /\s+/, config('pw_keys')),
chars => config('pw_chars'),
start_label => 'a',
label_format => '[%s]',
color => config('pw_color'),
label_color => config('pw_label_color'),
blackout => config('pw_blackout'),
);
}
sub parse_xx {
my $obj = shift;
my %opt = @_;
my %hash;
$obj->{$opt{hash}} = \%hash;
my $label_id = $opt{start_label};
my $chars = qr/$opt{chars}/;
$obj->{masked} =~ s{ (?!.*\e) $opt{pattern} }{
local $_ = $1;
s{ (?| () (https?://[^\s{}|\\\^\[\]\`]+) # URL
| ([(]) ([^)]+)(\)) # ( text )
| () ($chars+) ) # text
}{
my($pre, $match, $post) = ($1, $2, $3 // '');
$hash{$label_id} = $match;
my $label = sprintf $opt{label_format}, $label_id++;
if ($opt{blackout}) {
if ($opt{blackout} > 1) {
$match = 'x' x $opt{blackout};
} else {
my $char = $opt{blackout_char} // 'x';
$match =~ s/./$char/g;
}
}
$label = colorize($opt{label_color}, $label) if $opt{label_color};
$match = colorize($opt{color}, $match) if $opt{color};
$pre . $label . $match . $post;
}xge;
$_;
}igex;
$obj;
}
sub parse_matrix {
my $obj = shift;
my @area = guess_matrix_area($obj->{masked});
my %matrix;
$obj->{matrix} = \%matrix;
for my $area (@area) {
my $start = $area->[0];
my $len = $area->[1] - $start;
my $matrix = substr($obj->{masked}, $start, $len);
$matrix =~ s{ \b (?<index>\d) \W+ \K (?<chars>.*) $}{
my $index = $+{index};
my $chars = $+{chars};
my $col = 'A';
$chars =~ s{(\S+)}{
my $cell = $1;
$matrix{$col}{$index} = $cell;
$col++;
$cell =~ s/./x/g;
colorize('D;R', $cell);
}ge;
$chars;
}xmge;
substr($obj->{masked}, $start, $len) = $matrix;
last; # process 1st segment only
}
$obj;
}
sub guess_matrix_area {
my $text = shift;
my @text = $text =~ /(.*\n|.+\z)/g;
my @length = map { length } @text;
my @words = map { [ /(\w+)/g ] } @text;
my @one = map { [ grep { length == 1 } @$_ ] } @words;
my @two = map { [ grep { length == 2 } @$_ ] } @words;
my @more = map { [ grep { length >= 3 } @$_ ] } @words;
my $series = 5;
map { [ sum(@length[0 .. $_->[0]]) - $length[$->[0]],
sum(@length[0 .. $_->[1]]) ] }
sort { $b->[1] - $b->[0] <=> $a->[1] - $a->[0] }
grep { $_->[0] + $series - 1 <= $_->[1] }
map { defined $_ ? ref $_ ? @$_ : [$_, $_] : () }
reduce {
my $r = ref $a eq 'ARRAY' ? $a : [ [$a, $a] ];
my $l = $r->[-1][1];
if ($l + 1 == $b
and @{$one[$l]} == @{$one[$b]}
and @{$two[$l]} == @{$two[$b]}
) {
$r->[-1][1] = $b;
} else {
push @$r, [ $b, $b ];
}
$r;
}
grep { $one[$_][0] =~ /\d/ }
grep { @{$one[$_]} >= 10 || @{$two[$_]} >= 5 and @{$more[$_]} == 0 }
0 .. $#text;
}
1;
=encoding utf-8
=head1 NAME
App::Greple::PwBlock - Password and ID information block parser for greple
=head1 SYNOPSIS
use App::Greple::PwBlock;
# Create a new PwBlock object
my $pb = App::Greple::PwBlock->new($text);
# Access parsed information
my $id = $pb->id('0'); # Get ID by label
my $pw = $pb->pw('a'); # Get password by label
my $cell = $pb->cell('A', 0); # Get matrix cell value
# Configuration
use App::Greple::PwBlock qw(config);
config('id_keys', 'LOGIN EMAIL USER ACCOUNT');
config('pw_blackout', 0);
=head1 DESCRIPTION
B<App::Greple::PwBlock> is a specialized parser for extracting and managing
( run in 1.561 second using v1.01-cache-2.11-cpan-8f98c5d2c55 )