| 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__ |