packages feed

getemx-0.1: Emx/Dl.hs

module Emx.Dl where

import System.FilePath
import System.Directory
import System.IO
import Control.Applicative
import System.Process (runProcess, waitForProcess)
import Text.Printf (printf)
import Control.Monad
import Network.Curl
import Network.Curl.Easy
import Network.Curl.Opts
import Data.Ratio
import Data.Char
import Data.List
import Data.IORef


dl :: String -> String -> IO (String, String) -> IO ()
dl a epath remloc = do
  (rem, loc) <- remloc
  notexists <- not <$> doesFileExist loc
  when notexists $ runProcess epath [rem, a, loc] Nothing Nothing Nothing Nothing Nothing >>= waitForProcess >> return ()
dlcurl = dl "-o"
dlwget = dl "-O"

-- native download. How likely is it that curl(1) won't be available
-- but libcurl will be?
colheaders :: IORef Integer -> String -> IO ()
colheaders tot s = do
  (key, val) <- return $ parseHeader $ map toLower s
  when (key == "content-length") $ writeIORef tot $ read val

writebody sofar tot handle s = do
  clen <- readIORef tot
  modifyIORef sofar (+ genericLength s)
  sof <- readIORef sofar
  if clen /= 0
     then do
       if sof == clen 
          then putStrLn "\b\b\b100%"
          else putStr $ printf "\b\b\b%2.0f%%"  (fromRational (100*sof%clen)::Float)
       hFlush stdout
     else when (sof == clen) $ putStrLn "... Done"
  hPutStr handle s
  return ()

dlnative :: IO (String, String) -> IO ()
dlnative remloc = do 
      (rem, loc) <- remloc
      tot <- newIORef (0::Integer)
      sofar <- newIORef (0::Integer)
      curl <- initialize
      h <- openFile loc WriteMode
      setopts curl [CurlHeaderFunction $ callbackWriter (colheaders tot),
                    CurlWriteFunction $ callbackWriter (writebody sofar tot h),
                    CurlURL rem,
                    CurlFailOnError True]
      setDefaultSSLOpts curl rem
      putStrLn $ printf "Downloading %s ..." rem
      putStrLn $ printf "To %s" loc
      perform curl
      rspCode <- getResponseCode curl
      hFlush h
      hClose h
      return ()