File Coverage

blib/lib/gb64.pm
Criterion Covered Total %
statement 69 69 100.0
branch 13 14 92.8
condition 17 25 68.0
subroutine 9 9 100.0
pod 6 6 100.0
total 114 123 92.6


line stmt bran cond sub pod time code
1             package gb64;
2              
3 1     1   149075 use strict;
  1         3  
  1         49  
4 1     1   5 use warnings;
  1         2  
  1         89  
5 1     1   6 use Exporter qw(import);
  1         1  
  1         1505  
6              
7             our $VERSION = '1.0.0';
8             our @EXPORT_OK = qw(enc_b64 dec_b64);
9              
10             sub new {
11 7     7 1 3454 my ($class) = @_;
12 7         18 my $self = bless { buffer => '' }, $class;
13 7         35 return $self;
14             }
15              
16             sub add {
17 8     8 1 36 my ($self, $data) = @_;
18 8 100       24 die "Input must be defined" unless defined $data;
19 7         14 $self->{buffer} .= $data;
20 7         10 return $self;
21             }
22              
23             sub encode {
24 4     4 1 14 my ($self) = @_;
25 4         10 my $data = $self->{buffer};
26 4         6 $self->{buffer} = '';
27 4         11 return enc_b64($data);
28             }
29              
30             sub decode {
31 4     4 1 11 my ($self) = @_;
32 4         6 my $data = $self->{buffer};
33 4         4 $self->{buffer} = '';
34 4         9 return dec_b64($data);
35             }
36              
37             # Lookup-tabel voor encoderen (ASCII-waarden voor A-Z, a-z, 0-9, +, /)
38             my @b64_table = (65..90, 97..122, 48..57, 43, 47);
39              
40             # Lookup-tabel voor decoderen (array in plaats van hash)
41             my @b64_decode_array = (undef) x 128;
42             @b64_decode_array[65..90] = 0..25; # A-Z
43             @b64_decode_array[97..122] = 26..51; # a-z
44             @b64_decode_array[48..57] = 52..61; # 0-9
45             $b64_decode_array[43] = 62; # +
46             $b64_decode_array[47] = 63; # /
47              
48             sub enc_b64 {
49 11     11 1 183937 my ($data) = @_;
50 11   100     36 my $len = length($data) || 0;
51 11         19 my $pos = 0;
52 11         12 my @bytes;
53              
54             # Verwerk groepen van 3 bytes
55 11         27 while ($pos + 2 < $len) {
56 8         25 my ($b1, $b2, $b3) = unpack("C3", substr($data, $pos, 3));
57 8         76 push @bytes,
58             ($b1 >> 2) & 0x3F,
59             (($b1 & 0x3) << 4) | (($b2 >> 4) & 0xF),
60             (($b2 & 0xF) << 2) | (($b3 >> 6) & 0x3),
61             $b3 & 0x3F;
62 8         18 $pos += 3;
63             }
64              
65             # Behandel restanten
66 11 100       75 if ($pos < $len) {
67 5         11 my $rest = substr($data, $pos);
68 5 100       14 if (length($rest) == 1) {
    50          
69 2         2 my $b1 = ord($rest);
70 2         6 push @bytes,
71             ($b1 >> 2) & 0x3F,
72             ($b1 & 0x3) << 4;
73 2         6 return pack("C*", map { $b64_table[$_] } @bytes) . "==";
  4         18  
74             }
75             elsif (length($rest) == 2) {
76 3         7 my ($b1, $b2) = unpack("C2", $rest);
77 3         11 push @bytes,
78             ($b1 >> 2) & 0x3F,
79             (($b1 & 0x3) << 4) | (($b2 >> 4) & 0xF),
80             ($b2 & 0xF) << 2;
81 3         11 return pack("C*", map { $b64_table[$_] } @bytes) . "=";
  21         38  
82             }
83             }
84              
85 6         33 return pack("C*", map { $b64_table[$_] } @bytes);
  20         49  
86             }
87              
88             sub dec_b64 {
89 13     13 1 1575 my ($data) = @_;
90 13   100     33 my $len = length($data) || 0;
91 13 100 100     50 die "Invalid Base64 length" unless $len == 0 || $len % 4 == 0;
92 12         13 my $pos = 0;
93 12         11 my @bytes;
94              
95             # Verwerk groepen van 4 karakters
96 12         22 while ($pos + 3 < $len) {
97 14         42 my ($c1, $c2, $c3, $c4) = unpack("C4", substr($data, $pos, 4));
98 14 100       23 if ($c4 == ord("=")) {
99 6 100       11 if ($c3 == ord("=")) {
100 3   50     9 my $v1 = $b64_decode_array[$c1] // die "Invalid Base64 character at position $pos";
101 3   100     17 my $v2 = $b64_decode_array[$c2] // die "Invalid Base64 character at position " . ($pos + 1);
102 2         9 push @bytes, ($v1 << 2) | (($v2 >> 4) & 0x3);
103             }
104             else {
105 3   50     9 my $v1 = $b64_decode_array[$c1] // die "Invalid Base64 character at position $pos";
106 3   50     5 my $v2 = $b64_decode_array[$c2] // die "Invalid Base64 character at position " . ($pos + 1);
107 3   50     6 my $v3 = $b64_decode_array[$c3] // die "Invalid Base64 character at position " . ($pos + 2);
108 3         9 push @bytes,
109             ($v1 << 2) | (($v2 >> 4) & 0x3),
110             (($v2 & 0xF) << 4) | (($v3 >> 2) & 0xF);
111             }
112 5         9 last;
113             }
114 8   50     17 my $v1 = $b64_decode_array[$c1] // die "Invalid Base64 character at position $pos";
115 8   50     13 my $v2 = $b64_decode_array[$c2] // die "Invalid Base64 character at position " . ($pos + 1);
116 8   50     17 my $v3 = $b64_decode_array[$c3] // die "Invalid Base64 character at position " . ($pos + 2);
117 8   50     13 my $v4 = $b64_decode_array[$c4] // die "Invalid Base64 character at position " . ($pos + 3);
118 8         22 push @bytes,
119             ($v1 << 2) | (($v2 >> 4) & 0x3),
120             (($v2 & 0xF) << 4) | (($v3 >> 2) & 0xF),
121             (($v3 & 0x3) << 6) | $v4;
122 8         15 $pos += 4;
123             }
124              
125 11         65 return pack("C*", @bytes);
126             }
127              
128             1; # EOF gb64.pm (C) 2025 OnEhIppY, Domero