#!/usr/bin/perl $_ = shift; die "usage: base64 -e|-d [file...]" unless /^[^edED]*([edED])[^edED]*$/; warn "Ignoring extra options" unless /^-?([edED])/; if($1 =~ /[eE]/) { my $to64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; use bytes; local $/; $_ = <>; my $out = ""; while($_ ne "") { if(length >= 3) { my $b1 = ord; $_ = substr $_,1; my $b2 = ord; $_ = substr $_,1; my $b3 = ord; $_ = substr $_,1; my $d1 = ($b1 & 0b11111100)>>2, $d2 = ($b1 & 0b00000011)<<4 | ($b2 & 0b11110000)>>4, $d3 = ($b2 & 0b00001111)<<2 | ($b3 & 0b11000000)>>6, $d4 = ($b3 & 0b00111111); $out .= substr($to64,$d1,1) . substr($to64,$d2,1) . substr($to64,$d3,1) . substr($to64,$d4,1); } elsif(length == 2) { my $b1 = ord; $_ = substr $_,1; my $b2 = ord; $_ = substr $_,1; my $d1 = ($b1 & 0b11111100)>>2, $d2 = ($b1 & 0b00000011)<<4 | ($b2 & 0b11110000)>>4, $d3 = ($b2 & 0b00001111)<<2; $out .= substr($to64,$d1,1) . substr($to64,$d2,1) . substr($to64,$d3,1) . '='; } elsif(length == 1) { my $b1 = ord; $_ = substr $_,1; my $d1 = ($b1 & 0b11111100)>>2, $d2 = ($b1 & 0b00000011)<<4; $out .= substr($to64,$d1,1) . substr($to64,$d2,1) . '=='; } } while(length $out >= 64) { print substr($out,0,64), "\x0d\x0a"; $out = substr $out,64; } print $out, "\x0d\x0a" if $out ne ""; } else { # # @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_ !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~? # my $from64 = ' ~ ?tuvwxyz{|} = @ABCDEFGHIJKLMNOPQRSTUVWXY Z[\]^_`abcdefghijklmnopqrs ' use bytes; local $/; $_ = <>; s"[^A-Za-z0-9+/=]""g; tr"A-Za-z0-9+/="-?P"; while($_ ne "") { if((length) < 4) { warn "Not a multiple of four bytes!"; $_ .= "P" x (4 - length); } my $d1 = ord; $_ = substr $_,1; my $d2 = ord; $_ = substr $_,1; my $d3 = ord; $_ = substr $_,1; my $d4 = ord; $_ = substr $_,1; my $nbytes; die "Unexpected =" if $d1>0b00111111 || $d2>0b00111111 || ($d3>0b00111111 && $d4<=0b00111111); if($d3>0b00111111) { $nbytes = 1; $d3 = 0; $d4 = 0; } elsif($d4>0b00111111) { $nbytes = 2; $d4 = 0; } else { $nbytes = 3; } my $b1 = ($d1 & 0b111111)<<2 | ($d2 & 0b110000)>>4, $b2 = ($d2 & 0b001111)<<4 | ($d3 & 0b111100)>>2, $b3 = ($d3 & 0b000011)<<6 | ($d4 & 0b111111); print chr $b1; print chr $b2 if $nbytes >= 2; print chr $b3 if $nbytes >= 3; } }