line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Convert::zBase32; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
20646
|
use 5.006; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
29
|
|
4
|
1
|
|
|
1
|
|
4
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
32
|
|
5
|
1
|
|
|
1
|
|
5
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
849
|
|
6
|
|
|
|
|
|
|
|
7
|
|
|
|
|
|
|
require Exporter; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( 'all' => [ qw( |
12
|
|
|
|
|
|
|
encode_zbase32 decode_zbase32 encode_base32 decode_base32 |
13
|
|
|
|
|
|
|
) ] ); |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
our @EXPORT = qw( encode_zbase32 decode_zbase32 ); |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
our $VERSION = '0.0201'; |
20
|
|
|
|
|
|
|
$VERSION = eval $VERSION; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
our @zBASE32 = qw( y b n d r f g 8 e j k m c p q x |
23
|
|
|
|
|
|
|
o t 1 u w i s z a 3 4 5 h 7 6 9 ); |
24
|
|
|
|
|
|
|
my $q=0; |
25
|
|
|
|
|
|
|
our %zB2N = map { $_ => $q++ } @zBASE32; |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
our @BASE32 = qw( a b c d e f g h i j k l m n o p |
28
|
|
|
|
|
|
|
q r s t u v w x y z 2 3 4 5 6 7 ); |
29
|
|
|
|
|
|
|
$q=0; |
30
|
|
|
|
|
|
|
our %B2N = map { $_ => $q++ } @BASE32; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
# masks to use if the begining of 5-bit is w/in this octet |
33
|
|
|
|
|
|
|
# keyed on the position w/in the octet |
34
|
|
|
|
|
|
|
my @masks = ( 0x1f, 0x3e, 0x7c, 0xf8, # all 5 bits in the octet |
35
|
|
|
|
|
|
|
0xf0, 0xe0, 0xc0, 0x80 # into the next one |
36
|
|
|
|
|
|
|
); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# masks of up to 4 bits in the next octet |
39
|
|
|
|
|
|
|
# keyed on the sub offset |
40
|
|
|
|
|
|
|
my @more_masks = ( 0x1, 0x3, 0x7, 0xf ); |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
################################################################## |
43
|
|
|
|
|
|
|
sub encode_zbase32 |
44
|
|
|
|
|
|
|
{ |
45
|
4
|
|
|
4
|
1
|
2258
|
my( $string ) = @_; |
46
|
|
|
|
|
|
|
|
47
|
4
|
|
|
|
|
7
|
my $ret; |
48
|
4
|
|
|
|
|
11
|
foreach my $part ( _split_string( $string ) ) { |
49
|
61
|
50
|
|
|
|
88
|
die "There is no $part" unless $part < 32; |
50
|
61
|
|
|
|
|
74
|
$ret .= $zBASE32[ $part ]; |
51
|
|
|
|
|
|
|
} |
52
|
4
|
|
|
|
|
12
|
return $ret; |
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
################################################################## |
56
|
|
|
|
|
|
|
sub decode_zbase32 |
57
|
|
|
|
|
|
|
{ |
58
|
8
|
|
|
8
|
1
|
3954
|
my( $string ) = @_; |
59
|
8
|
|
|
|
|
44
|
return _join_string( map { $zB2N{$_} } split '', lc $string ); |
|
122
|
|
|
|
|
388
|
|
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
################################################################## |
64
|
|
|
|
|
|
|
sub encode_base32 |
65
|
|
|
|
|
|
|
{ |
66
|
0
|
|
|
0
|
1
|
0
|
my( $string ) = @_; |
67
|
|
|
|
|
|
|
|
68
|
0
|
|
|
|
|
0
|
my $ret; |
69
|
0
|
|
|
|
|
0
|
foreach my $part ( _split_string( $string ) ) { |
70
|
0
|
0
|
|
|
|
0
|
die "There is no $part" unless $part < 32; |
71
|
0
|
|
|
|
|
0
|
$ret .= $BASE32[ $part ]; |
72
|
|
|
|
|
|
|
} |
73
|
0
|
|
|
|
|
0
|
return $ret; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
################################################################## |
77
|
|
|
|
|
|
|
sub decode_base32 |
78
|
|
|
|
|
|
|
{ |
79
|
0
|
|
|
0
|
1
|
0
|
my( $string ) = @_; |
80
|
0
|
|
|
|
|
0
|
return _join_string( map { $B2N{$_} } split '', lc $string ); |
|
0
|
|
|
|
|
0
|
|
81
|
|
|
|
|
|
|
} |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
################################################################## |
85
|
|
|
|
|
|
|
sub _split_string |
86
|
|
|
|
|
|
|
{ |
87
|
14
|
|
|
14
|
|
5799
|
my( $string ) = @_; |
88
|
14
|
|
|
|
|
30
|
my $len = 8 * length $string; |
89
|
14
|
|
|
|
|
19
|
my( @output, $chunk, $part, $offset, $suboffset ); |
90
|
|
|
|
|
|
|
# we want to build an array of 5 bit numbers |
91
|
14
|
|
|
|
|
36
|
foreach( my $q=0; $q < $len ; $q+=5 ) { |
92
|
131
|
|
|
|
|
166
|
$offset = int $q / 8; |
93
|
131
|
|
|
|
|
127
|
$suboffset = $q % 8; |
94
|
|
|
|
|
|
|
# warn "$offset, $suboffset"; |
95
|
|
|
|
|
|
|
# first part |
96
|
131
|
|
|
|
|
175
|
$part = ord substr $string, $offset, 1; |
97
|
|
|
|
|
|
|
# lower bits |
98
|
131
|
|
|
|
|
149
|
$chunk = ( $part & $masks[ $suboffset ] ) >> $suboffset; |
99
|
|
|
|
|
|
|
# is this all we need? |
100
|
131
|
|
|
|
|
144
|
$suboffset -= 4; |
101
|
131
|
100
|
|
|
|
207
|
if( $suboffset >= 0 ) { |
102
|
|
|
|
|
|
|
# next part |
103
|
71
|
100
|
|
|
|
98
|
if( $q + 5 > $len ) { |
104
|
14
|
|
|
|
|
18
|
$part = 0; # past the end |
105
|
|
|
|
|
|
|
} |
106
|
|
|
|
|
|
|
else { |
107
|
57
|
|
|
|
|
65
|
$part = ord substr $string, $offset+1, 1; |
108
|
|
|
|
|
|
|
} |
109
|
71
|
|
|
|
|
88
|
$chunk |= ( $part & $more_masks[ $suboffset ] ) |
110
|
|
|
|
|
|
|
<< (4- $suboffset); |
111
|
|
|
|
|
|
|
} |
112
|
131
|
|
|
|
|
271
|
push @output, $chunk; |
113
|
|
|
|
|
|
|
} |
114
|
14
|
|
|
|
|
55
|
return @output; |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
################################################################## |
118
|
|
|
|
|
|
|
sub _join_string |
119
|
|
|
|
|
|
|
{ |
120
|
15
|
|
|
15
|
|
5364
|
my( @output ) = @_; |
121
|
15
|
|
|
|
|
29
|
my $len = 5 * @output; |
122
|
15
|
|
|
|
|
50
|
my @ret = (0) x int( $len / 8); |
123
|
|
|
|
|
|
|
|
124
|
15
|
|
|
|
|
42
|
my $n = 0; |
125
|
15
|
|
|
|
|
17
|
my( $offset, $suboffset, $part, $chunk ); |
126
|
15
|
|
|
|
|
39
|
foreach( my $q=0; $q < $len ; $q+=5 ) { |
127
|
171
|
|
|
|
|
167
|
$offset = int $q / 8; |
128
|
171
|
|
|
|
|
174
|
$suboffset = $q % 8; |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# warn "$offset, $suboffset"; |
131
|
|
|
|
|
|
|
# first part |
132
|
171
|
|
|
|
|
153
|
$part = $output[ $n ]; |
133
|
|
|
|
|
|
|
# lower bits |
134
|
171
|
|
|
|
|
167
|
$chunk = ($part << $suboffset ) & $masks[ $suboffset ]; |
135
|
171
|
|
|
|
|
141
|
$ret[ $offset ] |= $chunk; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# is this all we needed? |
138
|
171
|
|
|
|
|
157
|
$suboffset -= 4; |
139
|
171
|
100
|
|
|
|
297
|
if( $suboffset >= 0 ) { |
140
|
90
|
|
|
|
|
119
|
$ret[ $offset +1 ] |= |
141
|
|
|
|
|
|
|
( $part >> (4-$suboffset) ) & $more_masks[ $suboffset ]; |
142
|
|
|
|
|
|
|
} |
143
|
171
|
|
|
|
|
332
|
$n++; |
144
|
|
|
|
|
|
|
} |
145
|
15
|
|
|
|
|
100
|
my $ret = join '', map chr, @ret; |
146
|
|
|
|
|
|
|
# remove any padding... |
147
|
15
|
50
|
|
|
|
57
|
substr( $ret, -1, 1, '' ) if 0 == ord substr( $ret, -1 ); |
148
|
15
|
|
|
|
|
53
|
return $ret; |
149
|
|
|
|
|
|
|
} |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
################################################################## |
153
|
|
|
|
|
|
|
|
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
1; |
156
|
|
|
|
|
|
|
__END__ |