File Coverage

blib/lib/Crypt/Rhash.pm
Criterion Covered Total %
statement 173 182 95.0
branch 13 32 40.6
condition 4 7 57.1
subroutine 56 58 96.5
pod 14 16 87.5
total 260 295 88.1


line stmt bran cond sub pod time code
1             package Crypt::Rhash;
2              
3 3     3   203795 use 5.006001;
  3         29  
4 3     3   21 use strict;
  3         5  
  3         70  
5 3     3   20 use warnings;
  3         5  
  3         458  
6              
7             require Exporter;
8             our @ISA = (qw(Exporter));
9              
10             # possible tags for export
11             our %EXPORT_TAGS = (
12             Functions => [qw(raw2hex raw2base32 raw2base64)],
13             Constants => [qw(RHASH_CRC32 RHASH_CRC32C RHASH_MD4 RHASH_MD5
14             RHASH_SHA1 RHASH_TIGER RHASH_TTH RHASH_BTIH RHASH_ED2K
15             RHASH_AICH RHASH_WHIRLPOOL RHASH_RIPEMD160 RHASH_GOST94
16             RHASH_GOST94_CRYPTOPRO RHASH_GOST12_256 RHASH_GOST12_512
17             RHASH_SHA224 RHASH_SHA256 RHASH_SHA384 RHASH_SHA512
18             RHASH_SHA3_224 RHASH_SHA3_256 RHASH_SHA3_384 RHASH_SHA3_512
19             RHASH_HAS160 RHASH_EDONR256 RHASH_EDONR512
20             RHASH_SNEFRU128 RHASH_SNEFRU256 RHASH_ALL)]
21             );
22              
23             Exporter::export_tags( );
24             Exporter::export_ok_tags( qw(Functions Constants) );
25              
26             our $VERSION = '0.97';
27              
28             require XSLoader;
29             XSLoader::load('Crypt::Rhash', $VERSION);
30              
31             ##############################################################################
32             # ids of hash functions
33 3     3   33 use constant RHASH_CRC32 => 0x01;
  3         6  
  3         330  
34 3     3   19 use constant RHASH_MD4 => 0x02;
  3         7  
  3         146  
35 3     3   16 use constant RHASH_MD5 => 0x04;
  3         6  
  3         143  
36 3     3   19 use constant RHASH_SHA1 => 0x08;
  3         5  
  3         166  
37 3     3   19 use constant RHASH_TIGER => 0x10;
  3         7  
  3         149  
38 3     3   18 use constant RHASH_TTH => 0x20;
  3         14  
  3         161  
39 3     3   25 use constant RHASH_BTIH => 0x40;
  3         7  
  3         158  
40 3     3   26 use constant RHASH_ED2K => 0x80;
  3         7  
  3         139  
41 3     3   16 use constant RHASH_AICH => 0x100;
  3         4  
  3         144  
42 3     3   18 use constant RHASH_WHIRLPOOL => 0x200;
  3         5  
  3         133  
43 3     3   21 use constant RHASH_RIPEMD160 => 0x400;
  3         15  
  3         204  
44 3     3   19 use constant RHASH_GOST94 => 0x800;
  3         5  
  3         149  
45 3     3   21 use constant RHASH_GOST94_CRYPTOPRO => 0x1000;
  3         7  
  3         147  
46 3     3   17 use constant RHASH_HAS160 => 0x2000;
  3         33  
  3         170  
47 3     3   19 use constant RHASH_GOST12_256 => 0x4000;
  3         5  
  3         194  
48 3     3   35 use constant RHASH_GOST12_512 => 0x8000;
  3         7  
  3         145  
49 3     3   17 use constant RHASH_SHA224 => 0x10000;
  3         5  
  3         136  
50 3     3   18 use constant RHASH_SHA256 => 0x20000;
  3         8  
  3         133  
51 3     3   17 use constant RHASH_SHA384 => 0x40000;
  3         6  
  3         166  
52 3     3   20 use constant RHASH_SHA512 => 0x80000;
  3         5  
  3         143  
53 3     3   17 use constant RHASH_EDONR256 => 0x100000;
  3         5  
  3         129  
54 3     3   16 use constant RHASH_EDONR512 => 0x200000;
  3         4  
  3         142  
55 3     3   18 use constant RHASH_SHA3_224 => 0x0400000;
  3         5  
  3         139  
56 3     3   30 use constant RHASH_SHA3_256 => 0x0800000;
  3         8  
  3         144  
57 3     3   18 use constant RHASH_SHA3_384 => 0x1000000;
  3         12  
  3         147  
58 3     3   17 use constant RHASH_SHA3_512 => 0x2000000;
  3         6  
  3         129  
59 3     3   17 use constant RHASH_CRC32C => 0x4000000;
  3         7  
  3         136  
60 3     3   17 use constant RHASH_SNEFRU128 => 0x8000000;
  3         27  
  3         142  
61 3     3   21 use constant RHASH_SNEFRU256 => 0x10000000;
  3         7  
  3         143  
62 3     3   25 use constant RHASH_ALL => 0x1FFFFFFF;
  3         7  
  3         1912  
63              
64             ##############################################################################
65             # Rhash class methods
66              
67             # Rhash object constructor
68             sub new
69             {
70 5 50   5 0 332 my $hash_id = $_[1] or die "hash_id not specified";
71 5 50       103 my $context = rhash_init(scalar($hash_id)) or return undef;
72 5         17 my $self = {
73             context => $context,
74             };
75 5         21 return bless $self;
76             }
77              
78             # destructor
79             sub DESTROY($)
80             {
81 3     3   7 my $self = shift;
82             # the 'if' added as workaround for perl 'global destruction' bug
83             # ($self->{context} can disappear on global destruction)
84 3 50       27 rhash_free($self->{context}) if $self->{context};
85             }
86              
87             sub update($$)
88             {
89 4     4 1 18 my $self = shift;
90 4         7 my $message = shift;
91 4         75 rhash_update($self->{context}, $message);
92 4         20 return $self;
93             }
94              
95             sub update_fd($$;$$)
96             {
97 3     3 1 9 my ($self, $fd, $start, $size) = @_;
98 3         5 my $res = 0;
99 3         6 my $num = 0;
100              
101 3         23 binmode($fd);
102 3 100       17 if(defined($start)) {
103 1 50       13 seek($fd, scalar($start), 0) or return undef;
104             }
105              
106 3         7 my $data;
107 3 100       9 if(defined($size)) {
108 1         4 for(my $left = scalar($size); $left > 0; $left -= 8192) {
109 1 50       16 ($res = read($fd, $data,
    50          
110             ($left < 8192 ? $left : 8192))) || last;
111 1         7 rhash_update($self->{context}, $data);
112 1         4 $num += $res;
113             }
114             } else {
115 2         47 while( ($res = read($fd, $data, 8192)) ) {
116 2         12 rhash_update($self->{context}, $data);
117 2         8 $num += $res;
118             }
119             }
120              
121 3 50       13 return (defined($res) ? $num : undef); # return undef on read error
122             }
123              
124             sub update_file($$;$$)
125             {
126 2     2 1 10 my ($self, $file, $start, $size) = @_;
127 2 50       73 open(my $fd, "<", $file) or return undef;
128 2         10 my $res = $self->update_fd($fd, $start, $size);
129 2         22 close($fd);
130 2         16 return $res;
131             }
132              
133             sub final($)
134             {
135 3     3 1 7 my $self = shift;
136 3         443 rhash_final($self->{context});
137 3         12 return $self;
138             }
139              
140             sub reset($)
141             {
142 3     3 1 8 my $self = shift;
143 3         16 rhash_reset($self->{context});
144 3         10 return $self;
145             }
146              
147             sub hashed_length($)
148             {
149 1     1 1 3 my $self = shift;
150 1         9 return rhash_get_hashed_length($self->{context});
151             }
152              
153             sub hash_id($)
154             {
155 1     1 1 3 my $self = shift;
156 1         8 return rhash_get_hash_id($self->{context});
157             }
158              
159             ##############################################################################
160             # Hash formatting functions
161              
162             # printing constants
163 3     3   24 use constant RHPR_DEFAULT => 0x0;
  3         6  
  3         171  
164 3     3   18 use constant RHPR_RAW => 0x1;
  3         6  
  3         151  
165 3     3   19 use constant RHPR_HEX => 0x2;
  3         7  
  3         131  
166 3     3   17 use constant RHPR_BASE32 => 0x3;
  3         6  
  3         163  
167 3     3   19 use constant RHPR_BASE64 => 0x4;
  3         5  
  3         136  
168 3     3   15 use constant RHPR_UPPERCASE => 0x8;
  3         6  
  3         136  
169 3     3   17 use constant RHPR_REVERSE => 0x10;
  3         7  
  3         1922  
170              
171             sub hash($;$$)
172             {
173 40     40 1 80 my $self = shift;
174 40   100     117 my $hash_id = scalar(shift) || 0;
175 40   100     128 my $print_flags = scalar(shift) || RHPR_DEFAULT;
176 40         373 return rhash_print($self->{context}, $hash_id, $print_flags);
177             }
178              
179             sub hash_base32($;$)
180             {
181 1     1 1 4 hash($_[0], $_[1], RHPR_BASE32);
182             }
183              
184             sub hash_base64($;$)
185             {
186 0     0 1 0 hash($_[0], $_[1], RHPR_BASE64);
187             }
188              
189             sub hash_hex($;$)
190             {
191 2     2 1 8 hash($_[0], $_[1], RHPR_HEX);
192             }
193              
194             sub hash_rhex($;$)
195             {
196 1     1 1 5 hash($_[0], $_[1], RHPR_HEX | RHPR_REVERSE);
197             }
198              
199             sub hash_raw($;$)
200             {
201 1     1 0 4 hash($_[0], $_[1], RHPR_RAW);
202             }
203              
204             sub magnet_link($;$$)
205             {
206 3     3 1 8 my ($self, $filename, $hash_mask) = @_;
207 3         34 return rhash_print_magnet($self->{context}, $filename, $hash_mask);
208             }
209              
210             our $AUTOLOAD;
211              
212             # report error if a script called unexisting method/field
213             sub AUTOLOAD
214             {
215 0     0   0 my ($self, $field, $type, $pkg) = ($_[0], $AUTOLOAD, undef, __PACKAGE__);
216 0         0 $field =~ s/.*://;
217 0 0       0 die "function $field does not exist" if $field =~ /^(rhash_|raw2)/;
218 0 0       0 die "no arguments specified to $field()" if !@_;
219 0 0       0 die "the $field() argument is undefined" if !defined $self;
220              
221 0 0 0     0 ($type = ref($self)) && $type eq $pkg || die "the $field() argument is not a $pkg reference";
222 0 0       0 my $text = (exists $self->{$field} ? "is not accessible" : "does not exist");
223 0         0 die "the method $field() $text in the class $pkg";
224             }
225              
226             # static functions
227              
228             sub msg($$)
229             {
230 1     1 1 5069 my ($hash_id, $msg) = @_;
231 1         13 my $raw = rhash_msg_raw($hash_id, $msg); # get binary hash
232 1 50       9 return (is_base32($hash_id) ? raw2base32($raw) : raw2hex($raw));
233             }
234              
235             1;
236             __END__