#!/usr/local/bin/perl # b64 -- Base 64 decoder/encoder # Brian Katzung 8 February 1996 # # This software is provided on a strictly as-is basis. # Use it at your own risk. $True = 1; $False = 0; ###################################################################### # Decode base 64 input sub Decode { local($Data1); local($Data2); local($Length); while (defined($Data1 = <>)) { # Zap anything outside of the character set $Data1 =~ s/[^A-Za-z0-9+\/=]//g; $Data2 .= $Data1; # Left over + new # Grab the largest group of 24 bits and leave the # rest for the next iteration while ($Length = length($Data2) & ~3) { $Length = 64 if ($Length > 64); # For this iteration $Data1 = substr($Data2, 0, $Length); # For the next one $Data2 = substr($Data2, $Length); # Figure out how many characters to decode $Data1 =~ /=*$/; $Length = $Length / 4 * 3 - length($&); # Convert base 64 to uuencode so that we can just # unpack('u') (which is fast) instead of manipulating # the bits explicitly (which is slow). $Data1 =~ tr/A-Za-z0-9+\/=/ -_ /; print unpack('u', pack('c', $Length + 32) . $Data1); } } } ###################################################################### # Return the next 45 characters of input $I45'Data = ''; $I45'EOF = $False; sub Input45 { local($Data); local($Length); while (length($I45'Data) < 45 && $I45'EOF != $True) { # Try to refill the input buffer $Length = sysread(STDIN, $Data, 8192); if ($Length < 8192) { if (scalar(@ARGV) == 0) { # No more files to read $I45'EOF = $True; } else { # Start reading the next file open(STDIN, '< ' . shift(@ARGV)); } } # Perform NL -> CRLF translation if requested $Data =~ s/\n/\r\n/g if $CRLF == $True; $I45'Data .= $Data; } # Return the next 45 characters $Data = substr($I45'Data, 0, 45); $I45'Data = substr($I45'Data, 45); $Data; } ###################################################################### # Encode input in base 64 sub Encode { local(*FILE) = $_[0]; local($Output); local($Data); local($Length); # Grab the input in chunks of 45 characters while (($Data = &Input45) ne '') { $Length = length($Data); # Instead of directly manipulating bits to generate base 64 # (which is slow), use pack('u') first (which is fast)... $Data = substr(pack('u', $Data), 1, int(($Length * 8 + 5) / 6)); # And then translate from uuencode to base 64 $Data =~ tr/` -_/AA-Za-z0-9+\//; # Reformat the results as lines of 76 characters $Output .= $Data; if (length($Output) > 76) { print substr($Output, 0, 76), "\n"; $Output = substr($Output, 76); } } # Handle any remainder if ($Output ne '') { # Pad encoding to 32 bits $Length = length($Output) & 3; $Output .= '==' if $Length == 2; $Output .= '=' if $Length == 3; print "$Output\n"; } } ###################################################################### # Main program $Mode = 'decode'; $CRLF = $False; while ($ARGV[0] =~ /^-/) { $Arg = shift; last if $Arg eq '--'; $CRLF = $True if $Arg =~ /c/; # NL -> CRLF mapping $Mode = 'decode' if $Arg =~ /d/; $Mode = 'encode' if $Arg =~ /e/; } if ($Mode eq 'encode') { open(STDIN, '< ' . shift) if scalar(@ARGV) > 0; &Encode; } else { &Decode; }