gopher-proxy 0.1.0.1 → 0.1.0.2
raw patch · 4 files changed
+144/−1 lines, 4 files
Files
- gopher-proxy.cabal +4/−1
- src/GopherProxy/Params.hs +79/−0
- src/GopherProxy/Protocol.hs +43/−0
- src/GopherProxy/Types.hs +18/−0
gopher-proxy.cabal view
@@ -2,7 +2,7 @@ -- documentation, see http://haskell.org/cabal/users-guide/ name: gopher-proxy-version: 0.1.0.1+version: 0.1.0.2 synopsis: proxy gopher over http description: A simple gopher-over-http proxy to http-ify gopher spaces. license: GPL-3@@ -22,6 +22,9 @@ main-is: Main.hs default-extensions: CPP other-modules: Paths_gopher_proxy+ , GopherProxy.Types+ , GopherProxy.Protocol+ , GopherProxy.Params build-depends: base >=4.9 && <4.10 , wai , warp
+ src/GopherProxy/Params.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE OverloadedStrings #-}+module GopherProxy.Params+ ( Params (..)+ , params+ , helpfulParams+ ) where++import qualified Data.ByteString as BS+import Data.Maybe (fromMaybe)+import Data.Monoid ((<>))+import Data.Text (Text ())+import Network.Mime (MimeType (), defaultMimeType)+import Network.Socket (HostName (), PortNumber ())+import Options.Applicative++data Params+ = Params+ { hostname :: HostName+ , port :: PortNumber+ , httpPort :: Int+ , cssPath :: Maybe FilePath+ , cssUrl :: BS.ByteString+ , baseUrl :: Text+ , listenPublic :: Bool+ , defaultMime :: MimeType+ , timeoutms :: Int+ }++helpfulParams :: ParserInfo Params+helpfulParams = info (helper <*> params) fullDesc++params :: Parser Params+params = Params+ <$> strOption+ (long "host"+ <> metavar "HOSTNAME"+ <> help "hostname of the target gopher server")+ <*> optionalWithDefault 70 (option auto+ (long "port"+ <> metavar "PORT"+ <> help "port of the target gopher server"))+ <*> option auto+ (long "http-port"+ <> metavar "PORT"+ <> help "port gopher-proxy should listen on")+ <*> optional (strOption+ (long "css-path"+ <> metavar "PATH"+ <> help "path of the css to be used"))+ <*> optionalWithDefault "/gopher-proxy.css" (option auto+ (long "css-url"+ <> metavar "PATH"+ <> help "absolute location of the css on the web server, defaults to \"/gopher-proxy.css\""))+ <*> optionalWithDefault "/" (option auto+ (long "base-url"+ <> metavar "PATH"+ <> help "base url where gopher-proxy is running, defaults to \"/\""))+ <*> switch+ (long "listen-public"+ <> help "wether gopher-proxy should accept connection on public IP addresses.")+ <*> optionalWithDefault defaultMimeType (option auto+ (long "default-mime-type"+ <> metavar "MIMETYPE"+ <> help "spacecookie uses this mimetype, if it can't guess the type, defaults to application/octet-stream"))+ <*> optionalWithDefault 10000000 (option auto+ (long "timeout"+ <> metavar "MILLISECONDS"+ <> help "timeout for connecting to the specified gopher server, defaults to 10s."))+++optionalWithDefault :: a -> Parser a -> Parser a+optionalWithDefault def p = fromMaybe def <$> optional p++-- Thanks enum! <3+#if !MIN_VERSION_network(2,6,3)+instance Read PortNumber where+ readsPrec i str = fmap (\(i,str) -> (fromInteger i,str)) $ readsPrec i str+#endif
+ src/GopherProxy/Protocol.hs view
@@ -0,0 +1,43 @@+{-# LANGUAGE OverloadedStrings #-}+module GopherProxy.Protocol where++import GopherProxy.Types+import Control.Applicative ((<|>), some)+import Control.Error.Safe (readErr)+import Data.Attoparsec.ByteString.Lazy+import qualified Data.ByteString.Lazy as B+import Data.Char (chr)+import Data.Text (Text ())+import qualified Data.Text as T+import Data.Text.Encoding (decodeUtf8)++itemValue = takeTill (inClass "\t\r\n")++gopherMenuParser :: Parser GopherResponse+gopherMenuParser = MenuResponse <$> some gopherMenuLine++gopherMenuLine :: Parser MenuItem+gopherMenuLine = do+ char <- chr . fromIntegral <$> anyWord8+ title <- B.fromStrict <$> itemValue+ string "\t"+ filePath <- B.fromStrict <$> itemValue+ string "\t"+ hostName <- itemValue+ string "\t"+ port <- T.unpack . decodeUtf8 <$> itemValue+ string "\n" <|> string "\r\n"++ case (readErr "port" port) of+ Left e+ -> fail e+ Right p+ -> pure $ MenuItem char title filePath (T.unpack (decodeUtf8 hostName)) p++gopherFileParser :: Parser GopherResponse+gopherFileParser = FileResponse <$> takeLazyByteString++gopherResponseParser :: Maybe GopherResponseType -> Parser GopherResponse+gopherResponseParser (Just Menu) = gopherMenuParser+gopherResponseParser (Just File) = gopherFileParser+gopherResponseParser Nothing = gopherMenuParser <|> gopherFileParser
+ src/GopherProxy/Types.hs view
@@ -0,0 +1,18 @@+module GopherProxy.Types where++import Data.ByteString.Lazy (ByteString ())+import Network.Socket (HostName (), PortNumber ())++data GopherResponse+ = MenuResponse [MenuItem]+ | FileResponse ByteString+ deriving Show++data GopherResponseType+ = Menu+ | File++data MenuItem+ = MenuItem Char ByteString ByteString HostName PortNumber+ deriving Show+