{-# LANGUAGE DeriveDataTypeable #-} {- odec - command line utility for data decoding Copyright (C) 2008 Magnus Therning This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -} module Main ( main ) where import Paths_omnicodec (version) import Codec.Binary.Base64 as B64 import qualified Codec.Binary.Base64Url as B64U import qualified Codec.Binary.Base32 as B32 import qualified Codec.Binary.Base32Hex as B32H import qualified Codec.Binary.Base16 as B16 import qualified Codec.Binary.Base85 as B85 import qualified Codec.Binary.PythonString as PS import qualified Codec.Binary.QuotedPrintable as QP import qualified Codec.Binary.Url as Url import qualified Codec.Binary.Uu as Uu import qualified Codec.Binary.Xx as Xx import Data.ByteString.Iteratee import Data.ByteString.Iteratee.Internals import qualified Data.ByteString as BS import qualified Data.ByteString.Char8 as BSC import System.Console.CmdArgs import Data.Version(showVersion) import System.IO import Data.Maybe -- {{{1 command line options ver :: String ver = "omnicode decode (odec) " ++ (showVersion version) ++ "\nCopyright 2007-2011 Magnus Therning " data Codec = B64 | B64U | B32 | B32H | B16 | B85 | PS | QP | Url | Uu | Xx deriving(Show, Eq, Data, Typeable) codecMap :: [(Codec, DecIncData String -> DecIncRes String)] codecMap = [ (B64, B64.decodeInc) , (B64U, B64U.decodeInc) , (B32, B32.decodeInc) , (B32H, B32H.decodeInc) , (B16, B16.decodeInc) , (B85, B85.decodeInc) , (PS, PS.decodeInc) , (QP, QP.decodeInc) , (Url, Url.decodeInc) , (Uu, Uu.decodeInc) , (Xx, Xx.decodeInc) ] data MyArgs = MyArgs { argInput :: Maybe FilePath, argOutput :: Maybe FilePath, argCodec :: Codec } deriving(Show, Data, Typeable) myArgs :: MyArgs myArgs = MyArgs { argInput = Nothing &= name "i" &= name "in" &= explicit &= typFile &= help "read encoded data from file" , argOutput = Nothing &= name "o" &= name "out" &= explicit &= typFile &= help "write decoded data to file" , argCodec = B64 &= name "c" &= name "codec" &= explicit &= typ "CODEC" &= help "codec b64, b64u, b32, b32h, b16, b85, ps, qp, url, uu, xx (b64)" } &= summary ver &= details [ "Decoder tool for multiple encodings:" , " b64 - base64 (default)" , " b64u - base64url" , " b32 - base32" , " b32h - base32hex" , " b16 - base16" , " b85 - base85" , " ps - python string escaping" , " qp - quoted printable" , " url - url encoding" , " uu - uu encoding" , " xx - xx encoding" ] -- {{{1 decode enumeratee decEnumeratee :: Monad m => (DecIncData String -> DecIncRes String) -> Enumeratee m a decEnumeratee decF iter = Iteratee $ step decF iter where step f i Eof = let d = f DDone in do case d of DFinal dbs _ -> do ir <- runIteratee i (Chunk $ BS.pack dbs) case ir of Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a Eof) Eof NeedAnotherChunk i' -> do ir' <- runIteratee i' Eof case ir' of Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a Eof) Eof NeedAnotherChunk _ -> error "decEnumeratee: inner iteratee diverges on Eof" DFail _ _ -> error "decEnumeratee: decoder failed on data" DPart _ _ -> error "decEnumeratee: decoder didn't terminate on DDone" step f i (Chunk bs) = let d = f (DChunk $ BSC.unpack bs) in do case d of DFinal dbs r -> do ir <- runIteratee i (Chunk $ BS.pack dbs) case ir of Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a (Chunk $ BSC.pack r)) (Chunk $ BSC.pack r) NeedAnotherChunk i' -> do ir' <- runIteratee i' Eof case ir' of Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a Eof) Eof NeedAnotherChunk _ -> error "decEnumeratee: inner iteratee diverges on Eof" DFail _ _ -> error "decEnumeratee: decoder failed on data" DPart dbs f' -> do ir <- runIteratee i (Chunk $ BS.pack dbs) case ir of Done a _ -> return $ Done (Iteratee $ \ _ -> return $ Done a (Chunk BS.empty)) (Chunk BS.empty) NeedAnotherChunk i' -> return $ NeedAnotherChunk $ Iteratee $ step f' i' -- {{{1 main main :: IO () main = do cmdArgs myArgs >>= \ a -> do hIn <- maybe (return stdin) (\ fn -> openFile fn ReadMode) (argInput a) hOut <- maybe (return stdout) (\ fn -> openFile fn WriteMode) (argOutput a) let dI = fromJust $ lookup (argCodec a) codecMap (enumHandle hIn $ decEnumeratee dI (sinkHandle hOut)) >>= run >>= run hClose hOut