-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/
-- | Gopher server library and daemon
--
-- Simple gopher library that allows writing custom gopher applications.
-- Also includes a fully-featured gopher server daemon complete with
-- gophermap-support built on top of it.
@package spacecookie
@version 1.0.0.2
-- | Helper utilities used within the library and the server which also
-- could be useful for other application code.
module Network.Gopher.Util
-- | Normalise a path and prevent directory traversal attacks.
sanitizePath :: RawFilePath -> RawFilePath
-- | Use sanitizePath except if the path starts with URL:
-- in which case the original string is returned.
sanitizeIfNotUrl :: RawFilePath -> RawFilePath
-- | Call setGroupID and setUserID to switch to the given
-- user and their primary group. Requires special privileges. Will raise
-- an exception if either the user does not exist or the current user has
-- no permission to change UID/GID.
dropPrivileges :: String -> IO ()
-- | ord a Word8
asciiOrd :: Char -> Word8
-- | chr a Word8
asciiChr :: Word8 -> Char
-- | Transform a Word8 to lowercase if the solution is in bounds.
asciiToLower :: Word8 -> Word8
-- | Encode a String to a UTF-8 ByteString
uEncode :: String -> ByteString
-- | Decode a UTF-8 ByteString to a String
uDecode :: ByteString -> String
-- | Strip \r and \n from ByteStrings
stripNewline :: ByteString -> ByteString
-- |
-- boolToMaybe True x == Just x
--
--
--
-- boolToMaybe False x == Nothing
--
boolToMaybe :: Bool -> a -> Maybe a
-- | This module implements a parser for gophermap files.
--
-- Example usage:
--
--
-- import Network.Gopher.Util.Gophermap
-- import qualified Data.ByteString as B
-- import Data.Attoparsec.ByteString
--
-- main = do
-- file <- B.readFile "gophermap"
-- print $ parseOnly parseGophermap file
--
module Network.Gopher.Util.Gophermap
-- | Attoparsec Parser for the gophermap file format
parseGophermap :: Parser Gophermap
-- | A gophermap entry makes all values of a gopher menu item optional
-- except for file type and description. When converting to a
-- GopherMenuItem, appropriate default values are used.
data GophermapEntry
-- | file type, description, path, server name, port number
GophermapEntry :: GopherFileType -> ByteString -> Maybe GophermapFilePath -> Maybe ByteString -> Maybe Integer -> GophermapEntry
-- | Wrapper around RawFilePath to indicate whether it is relative
-- or absolute.
data GophermapFilePath
-- | Absolute path starting with /
GophermapAbsolute :: RawFilePath -> GophermapFilePath
-- | Relative path
GophermapRelative :: RawFilePath -> GophermapFilePath
-- | URL to another protocol starting with URL:
GophermapUrl :: RawFilePath -> GophermapFilePath
type Gophermap = [GophermapEntry]
-- | Given a directory and a Gophermap contained within it, return the
-- corresponding gopher menu response.
gophermapToDirectoryResponse :: RawFilePath -> Gophermap -> GopherResponse
instance GHC.Classes.Eq Network.Gopher.Util.Gophermap.GophermapFilePath
instance GHC.Show.Show Network.Gopher.Util.Gophermap.GophermapFilePath
instance GHC.Classes.Eq Network.Gopher.Util.Gophermap.GophermapEntry
instance GHC.Show.Show Network.Gopher.Util.Gophermap.GophermapEntry
-- | Overview
--
-- This is the main module of the spacecookie library. It allows to write
-- gopher applications by taking care of handling gopher requests while
-- leaving the application logic to a user-supplied function.
--
-- For a small tutorial an example of a trivial pure gopher application:
--
--
-- import Network.Gopher
-- import Network.Gopher.Util
--
-- cfg :: GopherConfig
-- cfg = defaultConfig
-- { cServerName = "localhost"
-- , cServerPort = 7000
-- }
--
-- handler :: GopherRequest -> GopherResponse
-- handler request =
-- case requestSelector request of
-- "hello" -> FileResponse "Hello, stranger!"
-- "" -> rootMenu
-- "/" -> rootMenu
-- _ -> ErrorResponse "Not found"
-- where rootMenu = MenuResponse
-- [ Item File "greeting" "hello" Nothing Nothing ]
--
-- main :: IO ()
-- main = runGopherPure cfg handler
--
--
-- There are three possibilities for a GopherResponse:
--
--
--
-- If you use runGopher, it is the same story like in the example
-- above, but you can do IO effects. To see a more elaborate
-- example, have a look at the server code in this package.
module Network.Gopher
-- | Run a gopher application that may cause effects in IO. The
-- application function is given the GopherRequest sent by the
-- client and must produce a GopherResponse.
runGopher :: GopherConfig -> (GopherRequest -> IO GopherResponse) -> IO ()
-- | Like runGopher, but may not cause effects in IO (or
-- anywhere else).
runGopherPure :: GopherConfig -> (GopherRequest -> GopherResponse) -> IO ()
-- | Same as runGopher, but allows you to setup the Socket
-- manually and calls an user provided action soon as the server is ready
-- to accept requests. When the server terminates, it calls the given
-- clean up action which must close the socket and may perform other
-- shutdown tasks (like notifying a supervisor it is stopping).
--
-- Spacecookie assumes the Socket is properly set up to listen on
-- the port and host specified in the GopherConfig (i. e.
-- bind and listen have been called). This can be achieved
-- using setupGopherSocket. Especially note that spacecookie does
-- not check if the listening address and port of the given socket
-- match cListenAddr and cServerPort.
--
-- This is intended for supporting systemd socket activation and storage,
-- but may also be used to support other use cases where more control is
-- necessary. Always use runGopher if possible, as it offers less
-- ways of messing things up.
runGopherManual :: IO (Socket Inet6 Stream TCP) -> IO () -> (Socket Inet6 Stream TCP -> IO ()) -> GopherConfig -> (GopherRequest -> IO GopherResponse) -> IO ()
-- | Necessary information to handle gopher requests
data GopherConfig
GopherConfig :: ByteString -> Maybe ByteString -> Integer -> Maybe GopherLogHandler -> GopherConfig
-- | Public name of the server (either ip address or dns name). Gopher
-- clients will use this name to fetch any resources listed in gopher
-- menus located on the same server.
[cServerName] :: GopherConfig -> ByteString
-- | Address or hostname to listen on (resolved by getaddrinfo).
-- If Nothing, listen on all addresses.
[cListenAddr] :: GopherConfig -> Maybe ByteString
-- | Port to listen on
[cServerPort] :: GopherConfig -> Integer
-- | IO action spacecookie will call to output its log messages. If
-- it is Nothing, logging is disabled. See the logging
-- section for an overview on how to implement a log handler.
[cLogHandler] :: GopherConfig -> Maybe GopherLogHandler
-- | Default GopherConfig describing a server on
-- localhost:70 with no registered log handler.
defaultConfig :: GopherConfig
data GopherRequest
GopherRequest :: ByteString -> ByteString -> Maybe ByteString -> (Word16, Word16, Word16, Word16, Word16, Word16, Word16, Word16) -> GopherRequest
-- | raw selector sent by the client (without the terminating \r\n
[requestRawSelector] :: GopherRequest -> ByteString
-- | only the request selector minus the search expression if present
[requestSelector] :: GopherRequest -> ByteString
-- | raw search string if the clients sends a search transaction
[requestSearchString] :: GopherRequest -> Maybe ByteString
-- | IPv6 address of the client which sent the request. IPv4 addresses are
-- mapped to an IPv6 address.
[requestClientAddr] :: GopherRequest -> (Word16, Word16, Word16, Word16, Word16, Word16, Word16, Word16)
data GopherResponse
-- | gopher menu, wrapper around a list of GopherMenuItems
MenuResponse :: [GopherMenuItem] -> GopherResponse
-- | return the given ByteString as a file
FileResponse :: ByteString -> GopherResponse
-- | gopher menu containing a single error with the given ByteString
-- as text
ErrorResponse :: ByteString -> GopherResponse
-- | entry in a gopher menu
data GopherMenuItem
-- | file type, menu text, selector, server name (optional), port
-- (optional). None of the given ByteStrings may contain tab
-- characters.
Item :: GopherFileType -> ByteString -> ByteString -> Maybe ByteString -> Maybe Integer -> GopherMenuItem
-- | rfc-defined gopher file types plus info line and HTML
data GopherFileType
-- | text file, default type
File :: GopherFileType
-- | a gopher menu
Directory :: GopherFileType
PhoneBookServer :: GopherFileType
-- | error entry in menu
Error :: GopherFileType
BinHexMacintoshFile :: GopherFileType
DOSArchive :: GopherFileType
UnixUuencodedFile :: GopherFileType
IndexSearchServer :: GopherFileType
TelnetSession :: GopherFileType
-- | binary file
BinaryFile :: GopherFileType
RedundantServer :: GopherFileType
Tn3270Session :: GopherFileType
-- | gif
GifFile :: GopherFileType
-- | image of any format
ImageFile :: GopherFileType
-- | menu entry without associated file
InfoLine :: GopherFileType
-- | Special type for HTML, most commonly used for links to other
-- protocols
Html :: GopherFileType
-- | Type for an user defined IO action which handles logging a
-- given GopherLogStr of a given GopherLogLevel. It may
-- process the string and format in any way desired, but it must be
-- thread safe and should not block (too long) since it is called
-- syncronously.
type GopherLogHandler = GopherLogLevel -> GopherLogStr -> IO ()
-- | UTF-8 encoded string which may have parts of it marked as sensitive
-- (see makeSensitive). Use its ToGopherLogStr,
-- Semigroup and IsString instances to construct
-- GopherLogStrs and FromGopherLogStr to convert to the
-- commonly used Haskell string types.
data GopherLogStr
-- | Mark a GopherLogStr as sensitive. This is used by this library
-- mostly to mark IP addresses of connecting clients. By using
-- hideSensitive on a GopherLogStr sensitive parts will be
-- hidden from the string — even if the sensitive string was concatenated
-- to other strings.
makeSensitive :: GopherLogStr -> GopherLogStr
-- | Replaces all chunks of the GopherLogStr that have been marked
-- as sensitive by makeSensitive with [redacted]. Note
-- that the chunking is dependent on the way the string was assembled by
-- the user and the internal implementation of GopherLogStr which
-- can lead to multiple consecutive [redacted] being returned
-- unexpectedly. This may be improved in the future.
hideSensitive :: GopherLogStr -> GopherLogStr
-- | Indicates the log level of a GopherLogStr to a
-- GopherLogHandler. If you want to filter by log level you can
-- use either the Ord or Enum instance of
-- GopherLogLevel as the following holds:
--
--
-- GopherLogLevelError < GopherLogLevelWarn < GopherLogLevelInfo
--
data GopherLogLevel
GopherLogLevelError :: GopherLogLevel
GopherLogLevelWarn :: GopherLogLevel
GopherLogLevelInfo :: GopherLogLevel
-- | Convert something to a GopherLogStr. In terms of performance it
-- is best to implement a Builder for the type you are trying to
-- render to GopherLogStr and then reuse its ToGopherLogStr
-- instance.
class ToGopherLogStr a
toGopherLogStr :: ToGopherLogStr a => a -> GopherLogStr
-- | Convert GopherLogStrs to other string types. Since it is used
-- internally by GopherLogStr, it is best to use the
-- Builder instance for performance if possible.
class FromGopherLogStr a
fromGopherLogStr :: FromGopherLogStr a => GopherLogStr -> a
-- | Auxiliary function that sets up the listening socket for
-- runGopherManual correctly and starts to listen.
--
-- May throw a SocketException if an error occurs while setting up
-- the socket.
setupGopherSocket :: GopherConfig -> IO (Socket Inet6 Stream TCP)
-- | Given a directory and a Gophermap contained within it, return the
-- corresponding gopher menu response.
gophermapToDirectoryResponse :: RawFilePath -> Gophermap -> GopherResponse
type Gophermap = [GophermapEntry]
-- | A gophermap entry makes all values of a gopher menu item optional
-- except for file type and description. When converting to a
-- GopherMenuItem, appropriate default values are used.
data GophermapEntry
-- | file type, description, path, server name, port number
GophermapEntry :: GopherFileType -> ByteString -> Maybe GophermapFilePath -> Maybe ByteString -> Maybe Integer -> GophermapEntry
instance GHC.Classes.Eq Network.Gopher.GopherRequest
instance GHC.Show.Show Network.Gopher.GopherRequest
instance Control.Monad.Reader.Class.MonadReader Network.Gopher.Env Network.Gopher.GopherM
instance Control.Monad.IO.Class.MonadIO Network.Gopher.GopherM
instance GHC.Base.Monad Network.Gopher.GopherM
instance GHC.Base.Applicative Network.Gopher.GopherM
instance GHC.Base.Functor Network.Gopher.GopherM