import Control.Monad.Unicode
import Control.Monad.Trans
import qualified Data.Ascii as A
-import qualified Data.ByteString.Lazy.Char8 as B
+import Data.ByteString (ByteString)
+import qualified Data.ByteString.Lazy.Char8 as LBS
import Data.Monoid.Unicode
+import Data.String
import qualified Data.Text as T
+import qualified Data.Text.Encoding as T
import Data.Time.Clock.POSIX
import Network.HTTP.Lucu.Abortion
import Network.HTTP.Lucu.Config
import Network.HTTP.Lucu.MIMEType
import Network.HTTP.Lucu.MIMEType.Guess
import Network.HTTP.Lucu.Resource
-import Network.HTTP.Lucu.Resource.Tree
+import Network.HTTP.Lucu.Resource.Internal
import Network.HTTP.Lucu.Response
import Prelude.Unicode
import System.FilePath
handleStaticFile sendContent path
= do exists ← liftIO $ fileExist path
unless exists
- $ foundNoEntity Nothing
+ foundNoEntity'
readable ← liftIO $ fileAccess path True False False
unless readable
- $ abort Forbidden [] Nothing
+ $ abort
+ $ mkAbortion Forbidden [] Nothing
stat ← liftIO $ getFileStatus path
when (isDirectory stat)
- $ abort Forbidden [] Nothing
+ $ abort
+ $ mkAbortion Forbidden [] Nothing
tag ← liftIO $ generateETagFromFile path
let lastMod = posixSecondsToUTCTime
Just mime → setContentType mime
when sendContent
- $ liftIO (B.readFile path) ≫= putChunk
+ $ liftIO (LBS.readFile path) ≫= putChunks
-- |@'generateETagFromFile' fpath@ generates a strong entity tag from
-- a file. The file doesn't necessarily have to be a regular file; it
return $ strongETag tag
-- | @'staticDir' dir@ is a 'ResourceDef' which maps all files in
--- @dir@ and its subdirectories on the filesystem to the 'ResTree'.
+-- @dir@ and its subdirectories on the filesystem to the
+-- 'Network.HTTP.Lucu.Resource.Tree.ResTree'.
--
-- Note that 'staticDir' currently doesn't have a directory-listing
-- capability. Requesting the content of a directory will end up being
, resHead = Just $ handleStaticDir False path
}
+-- TODO: implement directory listing.
handleStaticDir ∷ Bool → FilePath → Resource ()
handleStaticDir sendContent basePath
= do extraPath ← getPathInfo
securityCheck extraPath
- let path = basePath </> joinPath (map T.unpack extraPath)
-
+ let path = basePath </> joinPath (map dec8 extraPath)
handleStaticFile sendContent path
where
- securityCheck pathElems
- = when (any (≡ "..") pathElems)
- $ fail ("security error: " ⧺ show pathElems)
--- TODO: implement directory listing.
+ dec8 ∷ ByteString → String
+ dec8 = T.unpack ∘ T.decodeUtf8
+
+securityCheck ∷ (Eq s, Show s, IsString s, Monad m) ⇒ [s] → m ()
+securityCheck pathElems
+ = when (any (≡ "..") pathElems)
+ $ fail ("security error: " ⧺ show pathElems)