File Coverage

blib/lib/OpenSSL/Versions.pm
Criterion Covered Total %
statement 51 57 89.4
branch 21 28 75.0
condition n/a
subroutine 10 11 90.9
pod 1 1 100.0
total 83 97 85.5


line stmt bran cond sub pod time code
1             package OpenSSL::Versions;
2              
3 2     2   214386 use 5.006;
  2         8  
  2         80  
4 2     2   11 use strict;
  2         3  
  2         69  
5 2     2   11 use warnings;
  2         9  
  2         101  
6 2     2   11 use Carp;
  2         4  
  2         183  
7 2     2   11 use Exporter qw( import );
  2         5  
  2         2457  
8              
9             our $VERSION = '0.002';
10             $VERSION = eval $VERSION;
11              
12             our @EXPORT = ();
13             our @EXPORT_OK = qw( parse_openssl_version_number );
14              
15             sub parse_openssl_version_number {
16 75     75 1 71002 my ($vstr) = @_;
17              
18 75         368 $vstr =~ s/^0x//; # remove hex prefix
19              
20             # 0.9.6 or later : MNNFFPPS : major, minor, fix, patch, status (0-f)
21             # 0.9.5a to before 0.9.6 : high bit of PP is set in MNNFFPPS
22             # 0.9.3-dev to before 0.9.5a : MNNFFRBB : major, minor, fix, status (0-1), beta
23             # prior to 0.9.3-dev, MNFP
24              
25 75         109 my @ret;
26              
27 75 100       350 if ( $vstr =~ /^(?:[1-9]|0090[6-9])/ ) {
    100          
    100          
28 68         142 @ret = ( OpenSSL => _parse_openssl_v096_or_later( $vstr ) );
29             }
30             elsif ( $vstr =~ /^00905[8-9]/ ) {
31 1         5 @ret = ( OpenSSL => _parse_openssl_v095a_096( $vstr ) );
32             }
33             elsif ( $vstr =~ /^0090[3-5][01]/ ) {
34 4         15 @ret = ( OpenSSL => _parse_openssl_v093dev_095a( $vstr ) );
35             }
36             else {
37 2         7 @ret = ( SSLeay => _parse_openssl_pre_v093dev( $vstr ) );
38             }
39              
40 75 50       850 return wantarray ? reverse @ret : $ret[1];
41             }
42              
43             sub _parse_openssl_v096_or_later {
44 69     69   136 my ($vstr) = @_;
45              
46             # 0.9.6 or later : MNNFFPPS : major, minor, fix, patch, status (0-f)
47 69         607 my $pat = join '', map "([[:xdigit:]]{$_})", (1, 2, 2, 2, 1);
48            
49 69         848 my @v = $vstr =~ /^$pat\z/;
50            
51 69 50       586 unless (@v == 5) {
52 0         0 _croak_invalid_vstr($vstr);
53             }
54              
55             # The value of OPENSSL_VERSION_NUMBER for in crypto/opensslv.h in the
56             # OpenSSL 0.9.8f distribution is inconsistent with the description. We have
57             # #define OPENSSL_VERSION_NUMBER 0x00908070L in the header file.
58             # However, the comment above the definition states: "The status nibble has
59             # one of the values 0 for development, 1 to e for betas 1 to 14, and f for
60             # release." According to that description, the version string for that
61             # number should be 0.9.8f-dev. This number is special cased below due to
62             # that discrepancy.
63              
64 69 100       441 if ($vstr eq '00908070') {
65 1         6 return '0.9.8f';
66             }
67              
68 68         287 my ($major, $minor, $fix, $patch, $status) = map hex, @v;
69              
70 68 100       377 $patch = $patch ? chr( ord('a') + $patch - 1 ) : '';
71              
72 68 50       182 if ( $status == 0 ) { $status = '-dev' }
  0 100       0  
73 59         102 elsif ( $status == 15 ) { $status = '' }
74 9         22 else { $status = "-beta$status" }
75 68         480 return sprintf( '%u.%u.%u%s%s', $major, $minor, $fix, $patch, $status);
76             }
77              
78             sub _parse_openssl_v095a_096 {
79 1     1   3 my ($vstr) = @_;
80              
81             # 0.9.5a to before 0.9.6 :
82             # high bit of PP is set in MNNFFPPS
83              
84 1         8 return _parse_openssl_v096_or_later(
85             sprintf '%08x', hex($vstr) & 0xfffff7ff
86             );
87             }
88              
89             sub _parse_openssl_v093dev_095a {
90 4     4   5 my ($vstr) = @_;
91              
92             # Prior to 0.9.5a beta1, a different scheme was used:
93             # MMNNFFRBB for major minor fix final patch/beta)
94              
95 4         23 my @v = $vstr =~ /^(0)(09)(0[3-5])([0-1])(..)\z/;
96              
97 4 50       16 unless (@v == 5) {
98 0         0 _croak_invalid_vstr($vstr);
99             }
100              
101 4         26 my ($major, $minor, $fix, $status, $patch) = map hex, @v;
102              
103 4 100       13 $patch = $patch ? chr( ord('a') + $patch - 1 ) : '';
104 4 50       13 $status = $status ? '' : '-dev';
105 4         79 return sprintf( '%u.%u.%u%s%s', $major, $minor, $fix, $patch, $status );
106             }
107              
108             sub _parse_openssl_pre_v093dev {
109 2     2   5 my ($vstr) = @_;
110              
111             # prior to 0.9.3-dev,
112             # MNFP : major, minor, fix, patch
113              
114 2         12 my @v = $vstr =~ /^(0)(9)([12])([0-9])$/;
115              
116 2 50       10 unless (@v == 4) {
117 0         0 croak "'$vstr' does not look like a valid value for OPENSSL_VERSION_NUMBER";
118             }
119              
120 2         14 my ($major, $minor, $fix, $patch) = map hex, @v;
121              
122 2 50       12 $patch = $patch ? chr( ord('a') + $patch - 1 ) : '';
123 2         20 return sprintf( '%u.%u.%u%s', $major, $minor, $fix, $patch );
124             }
125              
126             sub _croak_invalid_vstr {
127 0     0     my ($vstr) = @_;
128            
129 0           croak "'$vstr' does not look like a valid value for OPENSSL_VERSION_NUMBER";
130             }
131              
132             1;
133              
134             __END__