h&&$J      !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQ experimentalPOSIX Safe-Inferred"  spacecookieR a S spacecookieT a S spacecookie Transform a S+ to lowercase if the solution is in bounds. spacecookie Encode a U to a UTF-8 V spacecookieDecode a UTF-8 V to a U spacecookieStrip \r and \n from Vs spacecookieNormalise a path and prevent  8https://en.wikipedia.org/wiki/Directory_traversal_attackdirectory traversal attacks. spacecookieUse  except if the path starts with URL:2 in which case the original string is returned. spacecookieboolToMaybe True x == Just xboolToMaybe False x == Nothing  spacecookieCall W and X 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.    Safe-Inferred  spacecookie5rfc-defined gopher file types plus info line and HTML  spacecookietext file, default type  spacecookie a gopher menu spacecookieerror entry in menu spacecookie binary file spacecookiegif spacecookieimage of any format spacecookie"menu entry without associated file spacecookie.Special type for HTML, most commonly used for =https://en.wikipedia.org/wiki/Gopher_%28protocol%29#URL_linkslinks to other protocols spacecookie&gopher menu, wrapper around a list of s spacecookiereturn the given V as a file spacecookie5gopher menu containing a single error with the given V as text spacecookieentry in a gopher menu  spacecookiefile type, menu text, selector, server name (optional), port (optional). None of the given Vs may contain tab characters.   YZ[ Safe-Inferred"! spacecookieConvert something to a %7. In terms of performance it is best to implement a \- for the type you are trying to render to % and then reuse its ! instance.# spacecookieConvert %;s to other string types. Since it is used internally by %, it is best to use the \) instance for performance if possible.% spacecookieUTF-8 encoded string which may have parts of it marked as sensitive (see * ). Use its !, ] and ^ instances to construct %s and #9 to convert to the commonly used Haskell string types.& spacecookieIndicates the log level of a % to a ?. If you want to filter by log level you can use either the _ or ` instance of & as the following holds: ' < ( < ) * spacecookieMark a % as sensitive. This is used by this library mostly to mark IP addresses of connecting clients. By using + on a % sensitive parts will be hidden from the string @ even if the sensitive string was concatenated to other strings.+ spacecookieReplaces all chunks of the %* that have been marked as sensitive by * with  [redacted]. Note that the chunking is dependent on the way the string was assembled by the user and the internal implementation of %+ which can lead to multiple consecutive  [redacted] being returned unexpectedly. This may be improved in the future. !"#$%&'()*+ experimentalPOSIX Safe-Inferred" - spacecookieA gophermap entry makes all values of a gopher menu item optional except for file type and description. When converting to a &, appropriate default values are used.. spacecookie6file type, description, path, server name, port number/ spacecookieWrapper around a3 to indicate whether it is relative or absolute.0 spacecookieAbsolute path starting with /1 spacecookie Relative path2 spacecookie&URL to another protocol starting with URL:3 spacecookieGiven a directory and a Gophermap contained within it, return the corresponding gopher menu response.b spacecookieTake V from gophermap, decode it, sanitize and determine path type.Gophermap paths that start with a slash are considered to be absolute.Gophermap paths that start with "URL:" are considered as an external URL and left as-is.-everything else is considered a relative path4 spacecookie Attoparsec c for the gophermap file format ,-./01234 4-./012,3 Safe-InferredNd spacecookieDisallow Reading (calls to e are empty).f spacecookieDisallow Writing (calls to send throw).g spacecookieDisallow both.h spacecookieShutdown a stream connection (partially). Will send TCP FIN and prompt a client to close the connection.)Not exposed to prevent future name clash.i spacecookieShutdown connection and give client a bit of time to clean up on its end before closing the connection to avoid a broken pipe on the other side.i experimentalPOSIX Safe-Inferred"#; spacecookie9raw selector sent by the client (without the terminating \r\n< spacecookieonly the request selector minus the search expression if present= spacecookie;raw search string if the clients sends a search transaction> spacecookieIPv6 address of the client which sent the request. IPv4 addresses are  =https://en.wikipedia.org/wiki/IPv6#IPv4-mapped_IPv6_addressesmapped to an IPv6 address.? spacecookieType for an user defined j) action which handles logging a given % of a given &. 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.@ spacecookie/Necessary information to handle gopher requestsB spacecookiePublic 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.C spacecookie.Address or hostname to listen on (resolved by  getaddrinfo ). If k, listen on all addresses.D spacecookiePort to listen onE spacecookiej action spacecookie will call to output its log messages. If it is k, logging is disabled. See  #loggingthe logging section6 for an overview on how to implement a log handler.F spacecookieDefault @ describing a server on  localhost:70# with no registered log handler.l spacecookieRead request from a client socket. The complexity of this function is caused by the following design features:0Requests may be terminated by either "nr" or "n"7After the terminating newline no extra data is acceptedGive up on waiting on a request from the client after a certain amount of time (request timeout)Don't accept selectors bigger than a certain size to avoid DoS attacks filling up our memory.G spacecookie?@ABCDEFGHIJ8HJI@ABCDEF9:;<=>  ?%*+&'()!"#$G3,-.      !"#$%&'()*+,-./01234556789:;<=>?@@ABCDEEFGHIJKLMNOPQRSTUVWXVYZV[\V[]^_`abcabdefg^hiV[jVklmnoVpqarstuvwxyz{|}~mVyyyzyz*spacecookie-1.0.0.2-FRmxVFj2qCd5Lj3HNgJVkRNetwork.Gopher.UtilNetwork.GopherNetwork.Gopher.Util.GophermapNetwork.Gopher.TypesNetwork.Gopher.LogGopherLogHandlerNetwork.Gopher.Util.SocketasciiChrasciiOrd asciiToLoweruEncodeuDecode stripNewline sanitizePathsanitizeIfNotUrl boolToMaybedropPrivilegesGopherFileTypeFile DirectoryPhoneBookServerErrorBinHexMacintoshFile DOSArchiveUnixUuencodedFileIndexSearchServer TelnetSession BinaryFileRedundantServer Tn3270SessionGifFile ImageFileInfoLineHtmlGopherResponse MenuResponse FileResponse ErrorResponseGopherMenuItemItemToGopherLogStrtoGopherLogStrFromGopherLogStrfromGopherLogStr GopherLogStrGopherLogLevelGopherLogLevelErrorGopherLogLevelWarnGopherLogLevelInfo makeSensitive hideSensitive GophermapGophermapEntryGophermapFilePathGophermapAbsoluteGophermapRelative GophermapUrlgophermapToDirectoryResponseparseGophermap$fShowGophermapEntry$fEqGophermapEntry$fShowGophermapFilePath$fEqGophermapFilePath GopherRequestrequestRawSelectorrequestSelectorrequestSearchStringrequestClientAddr GopherConfig cServerName cListenAddr cServerPort cLogHandler defaultConfigsetupGopherSocket runGopherrunGopherManual runGopherPure$fFunctorGopherM$fApplicativeGopherM$fMonadGopherM$fMonadIOGopherM$fMonadReaderEnvGopherM$fShowGopherRequest$fEqGopherRequestbaseGHC.CharchrGHC.WordWord8GHC.BaseordStringbytestring-0.11.3.1Data.ByteString.Internal ByteString unix-2.7.2.2System.Posix.User setGroupID setUserIDfileTypeToCharcharToFileTypeisFile Data.ByteString.Builder.InternalBuilder Semigroup Data.StringIsStringghc-prim GHC.ClassesOrdGHC.EnumEnum System.Posix.ByteString.FilePath RawFilePathmakeGophermapFilePath(attoparsec-0.14.4-71LaZYVwF7e8hNWK3nF9jy#Data.Attoparsec.ByteString.InternalParser ShutdownRead%socket-0.8.3.0-2AgGHWphazpEfBI5XXuUrm System.Socketreceive ShutdownWriteShutdownReadWriteshutdown gracefulClose GHC.TypesIO GHC.MaybeNothingreceiveRequest System.Socket.Internal.ExceptionSocketExceptionSystem.Socket.Internal.SocketSocketbindlisten splitSelector