line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Parse::Sums; |
2
|
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
our $DATE = '2016-11-23'; # DATE |
4
|
|
|
|
|
|
|
our $VERSION = '0.001'; # VERSION |
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
15490
|
use 5.010001; |
|
1
|
|
|
|
|
3
|
|
7
|
1
|
|
|
1
|
|
4
|
use strict; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
20
|
|
8
|
1
|
|
|
1
|
|
3
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
27
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
3
|
use Exporter qw(import); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
611
|
|
11
|
|
|
|
|
|
|
our @EXPORT_OK = qw(parse_sums); |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
our %SPEC; |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
sub _guess_algo { |
16
|
10
|
|
|
10
|
|
31
|
my $str = shift; |
17
|
10
|
|
|
|
|
10
|
my $len = length($str); |
18
|
10
|
50
|
|
|
|
35
|
if ($len == 8) { |
|
|
100
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
19
|
0
|
|
|
|
|
0
|
return ('crc32', 0); |
20
|
|
|
|
|
|
|
} elsif ($len == 32) { |
21
|
7
|
|
|
|
|
16
|
return ('md5', 0); |
22
|
|
|
|
|
|
|
} elsif ($len == 40) { |
23
|
2
|
|
|
|
|
5
|
return ('sha1', 0); |
24
|
|
|
|
|
|
|
} elsif ($len == 56) { |
25
|
0
|
|
|
|
|
0
|
return ('sha224', 1); # or sha512224 |
26
|
|
|
|
|
|
|
} elsif ($len == 64) { |
27
|
0
|
|
|
|
|
0
|
return ('sha256', 1); # or sha512256 |
28
|
|
|
|
|
|
|
} elsif ($len == 96) { |
29
|
0
|
|
|
|
|
0
|
return ('sha384', 0); |
30
|
|
|
|
|
|
|
} elsif ($len == 128) { |
31
|
0
|
|
|
|
|
0
|
return ('sha512', 0); |
32
|
|
|
|
|
|
|
} else { |
33
|
1
|
|
|
|
|
2
|
return ''; |
34
|
|
|
|
|
|
|
} |
35
|
|
|
|
|
|
|
} |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
$SPEC{parse_sums} = { |
38
|
|
|
|
|
|
|
v => 1.1, |
39
|
|
|
|
|
|
|
summary => 'Parse checksums file (e.g. MD5SUMS, SHA1SUMS)', |
40
|
|
|
|
|
|
|
args => { |
41
|
|
|
|
|
|
|
filename => { |
42
|
|
|
|
|
|
|
summary => 'Checksums filename', |
43
|
|
|
|
|
|
|
schema => 'filename*', |
44
|
|
|
|
|
|
|
}, |
45
|
|
|
|
|
|
|
content => { |
46
|
|
|
|
|
|
|
summary => 'Content of checksums file', |
47
|
|
|
|
|
|
|
schema => 'str*', |
48
|
|
|
|
|
|
|
description => <<'_', |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
If specified, then `filename` contents will not be read. |
51
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
_ |
53
|
|
|
|
|
|
|
}, |
54
|
|
|
|
|
|
|
}, |
55
|
|
|
|
|
|
|
examples => [ |
56
|
|
|
|
|
|
|
], |
57
|
|
|
|
|
|
|
}; |
58
|
|
|
|
|
|
|
sub parse_sums { |
59
|
6
|
|
|
6
|
1
|
8604
|
my %args = @_; |
60
|
|
|
|
|
|
|
|
61
|
6
|
|
|
|
|
9
|
my $filename = $args{filename}; |
62
|
6
|
|
|
|
|
7
|
my $content = $args{content}; |
63
|
6
|
50
|
|
|
|
17
|
unless (defined $content) { |
64
|
0
|
0
|
|
|
|
0
|
open my($fh), "<", $filename |
65
|
|
|
|
|
|
|
or return [500, "Can't read '$filename': $!"]; |
66
|
0
|
|
|
|
|
0
|
local $/; |
67
|
0
|
|
|
|
|
0
|
$content = <$fh>; |
68
|
|
|
|
|
|
|
} |
69
|
|
|
|
|
|
|
|
70
|
6
|
|
|
|
|
6
|
my $algo; |
71
|
6
|
100
|
|
|
|
12
|
if (defined $filename) { |
72
|
4
|
50
|
|
|
|
30
|
if ($filename =~ /(crc32|md5|sha[_-]?(?:512224|512256|224|256|384|512|1))/i) { |
73
|
4
|
|
|
|
|
13
|
$algo = lc($1); |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
} |
76
|
|
|
|
|
|
|
|
77
|
6
|
|
|
|
|
6
|
my @res; |
78
|
6
|
|
|
|
|
6
|
my $num_invalid_lines = 0; |
79
|
6
|
|
|
|
|
6
|
my $linenum = 0; |
80
|
6
|
|
|
|
|
19
|
for my $line (split /^/, $content) { |
81
|
20
|
|
|
|
|
17
|
$linenum++; |
82
|
20
|
100
|
|
|
|
61
|
next unless $line =~ /\S/; |
83
|
10
|
|
|
|
|
9
|
my ($digest, $line_algo, $multiple, $file); |
84
|
10
|
100
|
|
|
|
51
|
if ($line =~ /\A([0-9A-Fa-f]+)\s+\*?(.+)$/) { |
|
|
50
|
|
|
|
|
|
85
|
8
|
|
|
|
|
12
|
$digest = $1; |
86
|
8
|
|
|
|
|
15
|
($line_algo, $multiple) = _guess_algo($1); |
87
|
8
|
|
|
|
|
13
|
$file = $2; |
88
|
|
|
|
|
|
|
} elsif ($line =~ /\A(\w+) \((.+)\) = ([0-9A-Fa-f]+)$/) { |
89
|
2
|
|
|
|
|
6
|
$digest = $3; |
90
|
2
|
|
|
|
|
6
|
(undef, $multiple) = _guess_algo($3); |
91
|
2
|
|
|
|
|
6
|
$file = $2; |
92
|
2
|
|
|
|
|
6
|
$line_algo = lc($1); $line_algo =~ s/-//g; |
|
2
|
|
|
|
|
5
|
|
93
|
|
|
|
|
|
|
} else { |
94
|
0
|
|
|
|
|
0
|
$num_invalid_lines++; |
95
|
0
|
|
|
|
|
0
|
next; |
96
|
|
|
|
|
|
|
} |
97
|
10
|
100
|
66
|
|
|
101
|
if ($algo && !$multiple && $algo ne $line_algo) { |
|
|
|
100
|
|
|
|
|
98
|
2
|
|
|
|
|
4
|
$num_invalid_lines++; |
99
|
2
|
|
|
|
|
5
|
next; |
100
|
|
|
|
|
|
|
} |
101
|
8
|
100
|
|
|
|
14
|
$line_algo = $algo if $algo; |
102
|
8
|
100
|
|
|
|
15
|
if (!$line_algo) { |
103
|
1
|
|
|
|
|
1
|
$num_invalid_lines++; |
104
|
1
|
|
|
|
|
3
|
next; |
105
|
|
|
|
|
|
|
} |
106
|
7
|
|
|
|
|
35
|
push @res, {algorithm=>$line_algo, file=>$file, digest=>$digest, linenum=>$linenum}; |
107
|
|
|
|
|
|
|
} |
108
|
6
|
50
|
|
|
|
48
|
[200, "OK", \@res, { |
109
|
|
|
|
|
|
|
('func.warning' => ($num_invalid_lines > 1 ? "$num_invalid_lines lines are" : "1 line is")." improperly formatted") x !!$num_invalid_lines, |
110
|
|
|
|
|
|
|
}]; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
1; |
114
|
|
|
|
|
|
|
# ABSTRACT: Parse checksums file (e.g. MD5SUMS, SHA1SUMS) |
115
|
|
|
|
|
|
|
|
116
|
|
|
|
|
|
|
__END__ |