gdritter repos frontit / b42ebd1
Improve path-handling and add public-by-default option Getty Ritter 7 years ago
1 changed file(s) with 24 addition(s) and 8 deletion(s). Collapse all Expand all
88 import Data.Monoid ((<>))
99 import qualified Data.Time.Clock as Time
1010 import qualified Data.Time.Format as Time
11 import qualified Data.Text as T
12 import qualified Data.Text.Encoding as T
1113 import qualified Network.Gitit.Config as Gitit
1214 import qualified Network.Gitit.Page as Gitit
1315 import qualified Network.Gitit.Types as Gitit
2224 import qualified Text.Pandoc as Pandoc
2325 import Text.Printf (printf)
2426
27 data Protection
28 = PrivateByDefault
29 | PublicByDefault
30 deriving (Eq, Show)
31
2532 data FrontitOpts = FrontitOpts
2633 { optPort :: Int
2734 , optData :: Maybe FilePath
2835 , optGititConfig :: Maybe FilePath
2936 , optTemplate :: Maybe FilePath
37 , optProtection :: Protection
3038 } deriving (Eq, Show)
3139
3240 defaultOpts :: FrontitOpts
3543 , optData = Nothing
3644 , optGititConfig = Nothing
3745 , optTemplate = Nothing
46 , optProtection = PrivateByDefault
3847 }
3948
4049 frontitOptDescr :: [Opt.OptDescr (FrontitOpts -> FrontitOpts)]
5160 , Opt.Option ['t'] ["template"]
5261 (Opt.ReqArg (\ s opts -> opts { optTemplate = Just s }) "path")
5362 "The location of the desired HTML template"
63 , Opt.Option ['o'] ["public-by-default"]
64 (Opt.NoArg (\ opts -> opts { optProtection = PublicByDefault}))
65 "Allow all pages to be browsed by default"
5466 ]
5567
5668 optsToConfiguration :: FrontitOpts -> IO FrontitConf
6476 fcGititConfig <- case optGititConfig of
6577 Just path -> Gitit.getConfigFromFile path
6678 Nothing -> Gitit.getDefaultConfig
79 let fcProtection = optProtection
6780 return FrontitConf { .. }
6881
6982 defaultTemplate :: String
7386 { fcData :: FilePath
7487 , fcGititConfig :: Gitit.Config
7588 , fcTemplate :: String
89 , fcProtection :: Protection
7690 }
7791
7892 data Result
90104 rawPage <- readFile localPath
91105 let pg = Gitit.stringToPage (fcGititConfig conf) path rawPage
92106 case lookup "public" (Gitit.pageMeta pg) of
93 Just "yes" -> return (Found pg)
94 _ -> return Private
107 Just "yes" | fcProtection conf == PrivateByDefault -> return (Found pg)
108 Just "no" | fcProtection conf == PublicByDefault -> return Private
109 _ | fcProtection conf == PublicByDefault -> return (Found pg)
110 | otherwise -> return Private
95111
96112 convertLinks :: Pandoc.Inline -> Pandoc.Inline
97113 convertLinks link@(Pandoc.Link as name ("",title)) =
126142 Gitit.DocBook -> Pandoc.readDocBook def pageText
127143 Gitit.MediaWiki -> Pandoc.readMediaWiki def pageText
128144
129 getLocalPath :: FrontitConf -> BS.ByteString -> Maybe FilePath
145 getLocalPath :: FrontitConf -> T.Text -> Maybe FilePath
130146 getLocalPath conf req
131 | BS.any (== '.') req = Nothing
132 | req == "/" = Just (Gitit.frontPage (fcGititConfig conf) <> ".page")
133 | otherwise = Just (BS.unpack (req <> ".page"))
147 | T.any (== '.') req = Nothing
148 | req == "" = Just (Gitit.frontPage (fcGititConfig conf) <> ".page")
149 | otherwise = Just (T.unpack (req <> ".page"))
134150
135151 app :: FrontitConf -> Wai.Application
136152 app conf = \ req respond -> do
137 let respond' st pg = respond (Wai.responseLBS st [] (LBS.pack pg))
153 let respond' st pg = respond (Wai.responseLBS st [] (LBS.fromStrict (T.encodeUtf8 (T.pack pg))))
138154 if Wai.requestMethod req == "GET"
139155 then do
140 case getLocalPath conf (Wai.rawPathInfo req) of
156 case getLocalPath conf (T.intercalate ("/") (Wai.pathInfo req)) of
141157 Nothing -> respond' Http.status403 "invalid URL"
142158 Just path -> do
143159 result <- fetchPage conf path