{-# LANGUAGE DeriveDataTypeable #-} {- odec - command line utility for data decoding Copyright (C) 2012 Magnus Therning Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. -} module Main where import Paths_omnicodec (version) import Control.Exception import Control.Monad.IO.Class -- import Control.Monad import Data.ByteString as BS import Data.Maybe import Data.Version(showVersion) import System.Console.CmdArgs -- import System.Exit import System.IO as SIO import Data.Conduit import Data.Conduit.Binary import qualified Data.Conduit.Codec.Base64 as B64 import qualified Data.Conduit.Codec.Base64Url as B64U import qualified Data.Conduit.Codec.Base32 as B32 import qualified Data.Conduit.Codec.Base32Hex as B32H import qualified Data.Conduit.Codec.Base16 as B16 import qualified Data.Conduit.Codec.Base85 as B85 import qualified Data.Conduit.Codec.QuotedPrintable as QP import qualified Data.Conduit.Codec.Uu as Uu import qualified Data.Conduit.Codec.Xx as Xx -- {{{1 command line options ver :: String ver = "omnicode decode (odec) " ++ (showVersion version) ++ "\nCopyright 2012 Magnus Therning " data Codec = B64 | B64U | B32 | B32H | B16 | B85 | QP | Uu | Xx deriving(Show, Eq, Data, Typeable) codecMap :: [(Codec, Conduit ByteString (ResourceT IO) ByteString)] codecMap = [ (B64, B64.decode) , (B64U, B64U.decode) , (B32, B32.decode) , (B32H, B32H.decode) , (B16, B16.decode) , (B85, B85.decode) , (QP, QP.decode) , (Uu, Uu.decode) , (Xx, Xx.decode) -- , (PS, PS.decode) -- , (Url, Url.decode) ] 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" , " qp - quoted printable" , " uu - uu encoding" , " xx - xx encoding" -- , " ps - python string escaping" -- , " url - url encoding" ] -- {{{1 main main :: IO () main = do cmdArgs myArgs >>= \ a -> do let decFunc = lookup (argCodec a) codecMap withMaybeFile (argInput a) ReadMode $ \ inputFile -> withMaybeFile (argOutput a) WriteMode $ \ outputFile -> runResourceT $ decodeFile (fromJust decFunc) inputFile outputFile withMaybeFile :: Maybe FilePath -> IOMode -> (Handle -> IO r) -> IO r withMaybeFile fn mode func = let dH = if mode == ReadMode then stdin else stdout in bracket (maybe (return dH) (flip openFile mode) fn) hClose func -- decodeFile :: (BS.ByteString -> Either a BS.ByteString) -> Handle -> Handle -> IO () decodeFile :: (MonadIO m) => Conduit ByteString m ByteString -> Handle -> Handle -> m () decodeFile decFunc inF outF = sourceHandle inF $= decFunc $$ sinkHandle outF