module Main where import System.IO (hSetEncoding, hPutStr, openFile, hClose, hGetContents, IOMode(..), mkTextEncoding) import Network.FTP.Client as C import Data.Either.Utils (forceEither) import Data.ConfigFile as CF import Data.Maybe (catMaybes) import Data.List (isPrefixOf) import System.Environment (getArgs) import System.Exit (exitFailure) import System.IO.Binary (readBinaryFile) import Control.Monad (when) data FileConfig = FileConfig { fcPath :: !String, fcTmpPath :: !String, fcRemotePath :: !String } deriving (Show, Eq) data Config = Config { cFiles :: [FileConfig], cFromEncoding :: !String, cToEncoding :: !String, cFtpHost :: !String, cFtpPort :: !Integer, cFtpUser :: !String, cFtpPassword :: !String, cFtpDebug :: !Bool } deriving (Show, Eq) withDefaultValue :: b -> Either a b -> b withDefaultValue default_value (Left _) = default_value withDefaultValue _ (Right x) = x readConfig file = do val <- CF.readfile CF.emptyCP file let cp = forceEither val let fromEncoding = withDefaultValue "CP1251" $ CF.get cp "encodings" "from" let toEncoding = withDefaultValue "UTF-8" $ CF.get cp "encodings" "to" let ftpHost = forceEither $ CF.get cp "ftp" "host" let ftpPort = forceEither $ CF.get cp "ftp" "port" let ftpUser = forceEither $ CF.get cp "ftp" "user" let ftpPassword = forceEither $ CF.get cp "ftp" "password" let ftpDebug = withDefaultValue False $ CF.get cp "ftp" "debug" --putStrLn $ withDefaultValue "sss" $ CF.get cp "DEFAULT" "opt1" let fileConfigs = catMaybes $ map transform $ CF.sections cp where transform section = if "file" `isPrefixOf` section then parseF else Nothing where parseF = Just $ FileConfig path tmp rempath path = forceEither $ CF.get cp section "source" rempath = forceEither $ CF.get cp section "uploadpath" tmp = withDefaultValue (path ++ ".converted") $ CF.get cp section "tmp" return $ Config fileConfigs fromEncoding toEncoding ftpHost ftpPort ftpUser ftpPassword ftpDebug convertFile encR encW fc = do r <- openFile (fcPath fc) ReadMode w <- openFile (fcTmpPath fc) WriteMode hSetEncoding r $ encR hSetEncoding w $ encW putStrLn $ "Converting the file " ++ (fcPath fc) c <- hGetContents r hPutStr w c hClose w uploadFile h fc = do putStrLn $ "Uploading the file " ++ (fcRemotePath fc) content <- readBinaryFile $ fcTmpPath fc C.putbinary h (fcRemotePath fc) content main1 configfile = do cfg <- readConfig configfile putStrLn $ show cfg encR <- mkTextEncoding $ cFromEncoding cfg encW <- mkTextEncoding $ cToEncoding cfg mapM_ (convertFile encR encW) $ cFiles cfg when (cFtpDebug cfg) C.enableFTPDebugging (h, _) <- C.connectFTP (cFtpHost cfg) (fromIntegral $ cFtpPort cfg) if null $ cFtpUser cfg then C.loginAnon h else C.login h (cFtpUser cfg) (Just $ cFtpPassword cfg) Nothing mapM_ (uploadFile h ) $ cFiles cfg putStrLn "Finished" main = do args <- getArgs if length args == 0 then main1 "config.ini" else if length args == 1 then main1 $ head args else do putStrLn "Usage: hsencodeftp [configfile]" exitFailure