module Web.Action(actionWeb) where import CmdLine.All import Hoogle.All import Hoogle.Query.All import Hoogle.Item.All import Hoogle.Search.All import Numeric import General.Code import System.IO.Unsafe(unsafeInterleaveIO) import Web.Page import Web.Text import Text.ParserCombinators.Parsec import Data.TagStr import Data.Range import Data.Binary.Defer.Index import Data.Generics.Uniplate import Data.Time.Clock import Data.Time.Calendar import General.CGI(cgiArgs) import Paths_hoogle logFile = "log.txt" actionWeb :: CmdQuery -> IO () actionWeb q = do logMessage q res <- if Mode "suggest" `elem` queryFlags q then do putStr "Content-type: application/json\n\n" runSuggest q else do putStr "Content-type: text/html\n\n" (skipped,dbs) <- loadDataBases q return $ unlines $ header (escapeHTML $ queryText q) ++ runQuery dbs q ++ footer putStrLn res when (Debug `elem` queryFlags q) $ writeFile "temp.htm" res sequence_ [writeFile x res | Output x <- queryFlags q] logMessage :: CmdQuery -> IO () logMessage q = do time <- getCurrentTime cgi <- liftM (fromMaybe []) cgiArgs appendFile logFile $ (++ "\n") $ unwords $ [showGregorian (utctDay time) ,show (queryText q)] ++ ["?" ++ a ++ "=" ++ c ++ b ++ c | (a,b) <- cgi, let c = ['\"' | any isSpace b]] runSuggest :: CmdQuery -> IO String runSuggest CmdQuery{query=Right Query{scope=[], names=[x], typeSig=Nothing}} = do root <- getDataDir db <- loadDataBase $ root > "default.hoo" let res = take 8 $ completions db x return $ "[" ++ show x ++ "," ++ show res ++ "]" runSuggest _ = return "" -- is the package not something that might go wrong safePackage :: String -> Bool safePackage = all $ \x -> isAlphaNum x || x `elem` "-_" -- return the databases you loaded, and those you can't -- guarantees not to actually load the databases unless necessary -- TODO: Should say which databases are ignored loadDataBases :: CmdQuery -> IO ([String], [DataBase]) loadDataBases CmdQuery{query=Right q} = do let pkgs = nub [x | PlusPackage x <- scope q, safePackage x] files = if null pkgs then ["default"] else pkgs root <- getDataDir files <- filterM doesFileExist $ map (\x -> root > x <.> "hoo") files dbs <- unsafeInterleaveIO $ mapM loadDataBase files return ([], dbs) loadDataBases _ = return ([], []) -- TODO: Should escape the query text runQuery :: [DataBase] -> CmdQuery -> [String] runQuery dbs CmdQuery{queryText = text, query = Left err} = ["
"
," Query: " +& pre ++ "" +& post2 ++ "
"
,"
"
," Error: " +& drop 1 (dropWhile (/= ':') $ show err) ++ "
"
,"
" ," For information on what queries should look like, see the" ," user manual." ,"
" ] where (pre,post) = splitAt (sourceColumn (errorPos err) - 1) text post2 = if null post then concat (replicate 3 " ") else post runQuery dbs q | not $ usefulQuery $ fromRight $ query q = welcome runQuery dbs cq@CmdQuery{query = Right q, queryFlags = flags} = ["" ++ showTagHTML (transform qurl sug) ++ "
" | Just sug <- [suggestQuery dbs q]] ++ if null res then ["No results found
"] else ["