#!/usr/bin/perl -w # encode1.pl - Don Yang (uguu.org) # # 09/06/08 use strict; use constant BASE => 90; # Encode block of bytes sub Encode($) { my ($input) = @_; my $output = ""; my $remainder = length($input) % 4; foreach my $x (unpack 'V*', $input . "\0\0\0") { my $e = $x % BASE; my $d = ($x /= BASE) % BASE; my $c = ($x /= BASE) % BASE; my $b = ($x /= BASE) % BASE; my $a = $x / BASE; $output .= pack 'C*', $a + 33, $b + 33, $c + 33, $d + 33, $e + 33; } if( $remainder > 0 ) { substr($output, length($output) - 5, 1) = chr(122 + $remainder); } return $output; } # Decode block of bytes sub Decode($) { my ($input) = @_; my $input_length = length($input); return "" if( $input_length == 0 ); my $extra_char = 0; my $sentinel = ord(substr($input, $input_length - 5, 1)); if( $sentinel > 122 ) { $extra_char = 4 - ($sentinel - 122); substr($input, $input_length - 5, 1) = chr(33); } my $output = ""; for(my $i = 0; $i < $input_length; $i += 5) { my ($a, $b, $c, $d, $e) = unpack 'C*', substr($input, $i, 5); my $x = (((($a - 33) * BASE + $b - 33) * BASE + $c - 33) * BASE + $d - 33) * BASE + $e - 33; $output .= pack 'V', $x; } for(; $extra_char > 0; $extra_char--) { chop $output; } return $output; } # Test Encode/Decode pairs sub Test() { die if( Decode(Encode("")) ne "" ); for(my $i = 0; $i < 8; $i++) { my $input = ""; for(my $j = 0; $j < 1024 * 1024 + $i; $j++) { $input .= chr(rand 256); } die if( Decode(Encode($input)) ne $input ); } } Test();