@@ -1,4 +1,5 @@
11{-# LANGUAGE OverloadedStrings #-}
2+{-# LANGUAGE ScopedTypeVariables #-}
23{-# LANGUAGE TemplateHaskell, CPP #-}
34-- | Static file serving for WAI.
45module Network.Wai.Application.Static
@@ -66,7 +67,8 @@ import System.PosixCompat.Files (fileSize, getFileStatus, modificationTime)
6667import System.Posix.Types (EpochTime)
6768import Control.Monad.IO.Class (liftIO)
6869import qualified Crypto.Hash.MD5 as MD5
69−import Control.Monad (filterM)
70+import Control.Monad (forM)
71+import Control.Exception (SomeException, try)
7072
7173import Text.Blaze ((!))
7274import qualified Text.Blaze.Html5 as H
@@ -433,23 +435,25 @@ defaultFileServerSettings = StaticSettings
433435 }
434436
435437fileHelper :: ETagLookup
436− -> FilePath -> FilePath -> IO File
438+ -> FilePath -> FilePath -> IO (Maybe File)
437439fileHelper hashFunc fp name = do
438− fs <- getFileStatus $ fromFilePath fp
439− return File
440− { fileGetSize = fromIntegral $ fileSize fs
441− , fileToResponse = \s h -> W.ResponseFile s h (fromFilePath fp) Nothing
442− , fileName = name
443− , fileGetHash = hashFunc fp
444− , fileGetModified = Just $ modificationTime fs
445− }
440+ efs <- try $ getFileStatus $ fromFilePath fp
441+ case efs of
442+ Left (_ :: SomeException) -> return Nothing
443+ Right fs -> return $ Just File
444+ { fileGetSize = fromIntegral $ fileSize fs
445+ , fileToResponse = \s h -> W.ResponseFile s h (fromFilePath fp) Nothing
446+ , fileName = name
447+ , fileGetHash = hashFunc fp
448+ , fileGetModified = Just $ modificationTime fs
449+ }
446450
447451type ETagLookup = (FilePath -> IO (Maybe ByteString))
448452
449453webAppLookup :: ETagLookup -> FilePath -> Pieces -> IO FileLookup
450454webAppLookup cachedLookupHash prefix pieces = do
451− file <- fileHelper cachedLookupHash fp (last pieces)
452− return $ Just $ Right $ file
455+ mfile <- fileHelper cachedLookupHash fp (last pieces)
456+ return $ fmap Right mfile
453457 where
454458 fp = pathFromPieces prefix pieces
455459
@@ -479,21 +483,22 @@ fileSystemLookupHash hashFunc prefix pieces = do
479483 let fp = pathFromPieces prefix pieces
480484 fe <- doesFileExist $ fromFilePath fp
481485 if fe
482− then fmap (Just . Right) $ fileHelper hashFunc fp $ last pieces
486+ then (fmap . fmap) Right $ fileHelper hashFunc fp $ last pieces
483487 else do
484488 de <- doesDirectoryExist $ fromFilePath fp
485489 if de
486490 then do
487− let isVisible ('.':_) = return False
488− isVisible "" = return False
489− isVisible _ = return True
490− entries <- getDirectoryContents (fromFilePath fp) >>= filterM isVisible >>= mapM (\nameRaw -> do
491+ let isVisible ('.':_) = False
492+ isVisible "" = False
493+ isVisible _ = True
494+ entries' <- fmap (filter isVisible) $ getDirectoryContents (fromFilePath fp)
495+ entries <- forM entries' $ \nameRaw -> do
491496 let name = toFilePath nameRaw
492497 let fp' = fp </> name
493− fe' <- doesFileExist $ fromFilePath fp'
494− if fe'
495− then fmap Right $ fileHelper hashFunc fp' name
496− else return $ Left $ Folder name [])
498+ mfile' <- fileHelper hashFunc fp' name
499+ case mfile' of
500+ Nothing -> return $ Left $ Folder name []
501+ Just file' -> return $ Right file'
497502 return $ Just $ Left $ Folder (error "Network.Wai.Application.Static.fileSystemLookup") entries
498503 else return Nothing
499504
@@ -765,28 +770,3 @@ renderDirectoryContentsTable haskellSrc folderSrc fps =
765770 addCommas s = (++ (' ' : s)) . reverse . addCommas' . reverse . show
766771 addCommas' (a:b:c:d:e) = a : b : c : ',' : addCommas' (d : e)
767772 addCommas' x = x
768−
769−{-
770−mdIsFile :: MetaData -> Bool
771−mdIsFile FileMetaData{} = True
772−mdIsFile FolderMetaData{} = False
773−
774−-- | look up the meta data associated with a file
775−getMetaData :: FilePath -- ^ path to directory on disk containing the entry
776− -> FilePath -- ^ entry in that directory
777− -> IO (Maybe MetaData)
778−getMetaData _ ('.':_) = return Nothing
779−getMetaData localPath fp = do
780− let fp' = localPath ++ '/' : fp
781− fe <- doesFileExist fp'
782− let fpPretty = T.pack $ fixPathName fp
783− if fe
784− then do
785− fs <- getFileStatus fp'
786− let modTime = modificationTime fs
787− let count = fileSize fs
788− return $ Just $ FileMetaData fpPretty (Just modTime) count
789− else do
790− de <- doesDirectoryExist fp'
791− return $ if de then Just (FolderMetaData fpPretty) else Nothing
792−-}