package base64;

# Synopsis:
#       require 'base64.pl';
#
#       $base64_string = &base64::encode($binary_string);
#       $binary_string = &base64::decode($base64_string);

$base64_pad = '=';
$uuencode_alphabet =
    '`!"#$%&\'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`';
$uuencode_pad = '`';


sub encode
{
    local($_) = @_;
    my($chunk, $result);

    # break into chunks of 45 input chars, use perl's builtin
    # uuencoder to convert each chunk to uuencode format,
    # then kill the leading 'M', translate to the base64 alphabet,
    # and finally append a newline.
    while(s/^((.|\n){45})//) {
	$chunk = substr(pack('u', $&), $[+1, 60);
	$chunk =~ tr/`!-`/A-Za-z0-9+\//;
	$result .= $chunk;
    }

    # any leftover chars go onto a shorter line
    # with uuencode padding converted to base64 padding
    if($_ ne '') {
	$chunk = substr(pack('u', $_), $[+1,
			int((length($_)+2)/3)*4 - (45-length($_))%3);
	$chunk =~ tr/`!-`/A-Za-z0-9+\//;
	$result .= $chunk . ($base64_pad x ((60 - length($chunk)) % 4));
    }

    # return result
    $result;
}

sub decode
{
    local($_) = @_;
    my($result);
    
    # zap bad characters and translate others to uuencode alphabet
    tr/A-Za-z0-9+\///cd;
    tr/A-Za-z0-9+\//`!-`/;

    # break into lines of 60 encoded chars, prepending 'M' for uuencode,
    # and then using perl's builtin uudecoder to convert to binary.
    $result .= unpack('u', 'M' . $&) while(s/^(.{60})//);
    $result .= unpack('u', substr($uuencode_alphabet, length($_)*3/4, 1) . $_)
	if $_ ne '';

    # return result
    $result;
}
1;
