-- -- Miguel's Naive -- Base64 Encoder -- Coded on a winter afterfnoon on 19th Feb 2018 A.D. -- to fully understand base64 encoding and play with -- haskell, which is always an indisputable pleasure. -- -- The following lines were written in full awareness -- that 'libraries' for this purpose, which perform way -- better, are in existence. -- -- Coded in big anger due to nick's stories about saving his binary -- format, encrypted passwords in an ascii config file, featuring -- strange letters and characters. -- -- Example Usage: echo "just testing" | stack runghc base64.hs | stack runghc base64 -- -d -- (You can cross check with base64 / base64 -d) import System.Environment import qualified Data.List.Split as T import qualified Data.List as L import qualified Data.Map.Strict as M import qualified Data.ByteString.Lazy as B import Text.Printf import Data.Maybe import Data.Char import Control.Monad main = do args<-getArgs if length args == 0 then go encode64 else when (args!!0 == "-d") $ go decode64 where go f = getContents >>= putStr.(++"\n").f fromBase64 x = (['A'..'Z']++['a'..'z']++['0'..'9']++['+','/']) !! x mapBase64 = M.fromList $ map (\x-> (fromBase64 x,x)) [0..63] binToDec = sum . map (2^) . L.findIndices (=='1') . reverse encode64 x = pad64 (length x) . map (fromBase64 . binToDec) . T.chunksOf 6 . concat . map (printf "%08b" ) $ x ++ cycle "\000" decode64 x = map (chr . binToDec) . T.chunksOf 8 . concat . map ( printf "%06b" . fromJust) . filter isJust . map (flip M.lookup mapBase64) $ x pad64 l = (++(take m ((cycle "=")))) . take ((l+m)*3 `div` 2 -3-m) where m = mod (3 - mod l 3) 3