module Network.HGopher (mainServer, GResponse(..), Item(..), Record(..)) where
import Network.Socket
import System.IO
import Control.Exception
import Control.Concurrent
import Control.Monad
import Data.ByteString (ByteString)
import Data.List (intercalate)
data Record = Record { name :: String
, selector :: String
, host :: String
, port :: PortNumber
, other :: [String] }
data Item = PlainText
| Directory
| CSOSearch
| ErrorMess
| BinHexTxt
| BinaryArc
| UUEncoded
| SearchEng
| TelnetPtr
| BinaryFil
| GIFImage
| HTMLFile
| Info
| Image
| Audio
| TN3270Ptr
deriving Show
itemKey :: Item -> Char
itemKey PlainText = '0'
itemKey Directory = '1'
itemKey CSOSearch = '2'
itemKey ErrorMess = '3'
itemKey BinHexTxt = '4'
itemKey BinaryArc = '5'
itemKey UUEncoded = '6'
itemKey SearchEng = '7'
itemKey TelnetPtr = '8'
itemKey BinaryFil = '9'
itemKey GIFImage = 'g'
itemKey HTMLFile = 'h'
itemKey Info = 'i'
itemKey Image = 'l'
itemKey Audio = 's'
itemKey TN3270Ptr = 'T'
data GResponse = GItems [(Item, Record)]
| GFile ByteString
formatResp :: GResponse -> String
formatResp (GItems xs) = intercalate ""
$ map (\s -> field s ++ "\r\n") xs
where
field (i, (Record n s h p os)) = intercalate "\t"
$ [(itemKey i): n, s, h, show p] ++ os
formatResp (GFile bs) = show bs
mainServer :: PortNumber -> (String -> IO GResponse) -> IO ()
mainServer port process = do
sock <- socket AF_INET Stream 0
setSocketOption sock ReuseAddr 1
bindSocket sock (SockAddrInet port iNADDR_ANY)
listen sock 1024
mainLoop sock process
mainLoop :: Socket -> (String -> IO GResponse) -> IO ()
mainLoop sock process = do
conn <- accept sock
forkIO (runConn conn process)
mainLoop sock process
runConn :: (Socket, SockAddr) -> (String -> IO GResponse) -> IO ()
runConn (sock, _) process = do
hdl <- socketToHandle sock ReadWriteMode
hSetBuffering hdl NoBuffering
request <- hGetLine hdl
putStrLn $ "Request: " ++ request
response <- formatResp `fmap` process (strip request)
hPutStr hdl response
hPutStr hdl ".\r\n"
hClose hdl
strip x
| null x = x
| last x == '\r' = init x
| otherwise = x