File Coverage

blib/lib/Session/Token.pm
Criterion Covered Total %
statement 37 41 90.2
branch 22 34 64.7
condition 8 18 44.4
subroutine 4 4 100.0
pod 0 1 0.0
total 71 98 72.4


line stmt bran cond sub pod time code
1             package Session::Token;
2              
3 6     6   3517 use strict;
  6         10  
  6         171  
4              
5 6     6   28 use Carp qw/croak/;
  6         10  
  6         371  
6 6     6   4607 use POSIX qw/ceil/;
  6         47043  
  6         33  
7              
8              
9             our $VERSION = '1.501';
10              
11             require XSLoader;
12             XSLoader::load('Session::Token', $VERSION);
13              
14              
15             my $default_alphabet = join('', ('0'..'9', 'a'..'z', 'A'..'Z',));
16             my $default_entropy = 128;
17              
18             my $is_windows;
19              
20             if ($^O =~ /mswin/i) {
21             require Crypt::Random::Source::Strong::Win32;
22             $is_windows = 1;
23             }
24              
25              
26             sub new {
27 16     16 0 28068 my ($class, @args) = @_;
28              
29             ## support arguments in a hash ref
30 16 100 66     81 @args = %{$args[0]} if @args == 1 && ref $args[0] eq 'HASH';
  1         5  
31              
32 16         51 my %args = @args;
33              
34              
35             ## Init seed
36              
37 16         24 my $seed;
38              
39 16 100       54 if (defined $args{seed}) {
40             croak "seed argument should be a 1024 byte long bytestring"
41 5 50       19 unless length($args{seed}) == 1024;
42 5         12 $seed = $args{seed};
43             }
44              
45 16 100       39 if (!defined $seed) {
46 11 50       20 if ($is_windows) {
47 0         0 my $windows_rng_source = Crypt::Random::Source::Strong::Win32->new;
48 0         0 $seed = $windows_rng_source->get(1024);
49 0 0       0 die "Win32 RNG source didn't provide 1024 bytes" unless length($seed) == 1024;
50             } else {
51 11         12 my ($fh, $err1, $err2);
52              
53 11 50       289 open($fh, '<:raw', '/dev/urandom') || ($err1 = $!);
54 11 50 0     25 open($fh, '<:raw', '/dev/arandom') || ($err2 = $!)
55             unless defined $fh;
56              
57 11 50       23 if (!defined $fh) {
58 0         0 croak "unable to open /dev/urandom ($err1) or /dev/arandom ($err2)";
59             }
60              
61 11 50       1422 sysread($fh, $seed, 1024) == 1024 || croak "unable to read from random device: $!";
62             }
63             }
64              
65              
66             ## Init alphabet
67              
68 16 100       56 my $alphabet = defined $args{alphabet} ? $args{alphabet} : $default_alphabet;
69 16 100       58 $alphabet = join('', @$alphabet) if ref $alphabet eq 'ARRAY';
70              
71 16 50 33     90 croak "alphabet must be between 2 and 256 bytes long"
72             if length($alphabet) < 2 || length($alphabet) > 256;
73              
74              
75             ## Init token length
76              
77             croak "you can't specify both length and entropy"
78 16 50 66     57 if defined $args{length} && defined $args{entropy};
79              
80 16         20 my $token_length;
81              
82 16 100       47 if (defined $args{length}) {
83 4 50 33     40 croak "bad value for length" unless $args{length} =~ m/^\d+$/ && $args{length} > 0;
84 4         8 $token_length = $args{length};
85             } else {
86 12   66     47 my $entropy = $args{entropy} || $default_entropy;
87 12 50       25 croak "bad value for entropy" unless $entropy > 0;
88 12         44 my $alphabet_entropy = log(length($alphabet)) / log(2);
89 12         81 $token_length = ceil($entropy / $alphabet_entropy);
90             }
91              
92              
93 16         378 return _new_context($seed, $alphabet, $token_length);
94             }
95              
96              
97              
98             1;
99              
100              
101              
102             __END__