1module Gopher
2
3import Builtin
4import Data.Strings
5import Network.Socket
6
7-- Valid gopher item types as defined in RFC 1436.
8public export
9data ItemType = Document |
10 Directory |
11 PhoneBook |
12 Error |
13 BinHex |
14 PCDOS |
15 UnixUuencoded |
16 SearchService |
17 TelnetSession |
18 Binary |
19 Duplicated |
20 Gif |
21 Image |
22 Tn3270Session |
23 InfoLine |
24 HTML
25
26public export
27Show ItemType where
28 show Document = "Document"
29 show Directory = "Directory"
30 show PhoneBook = "Phonebook"
31 show Error = "Error"
32 show BinHex = "BINHEX"
33 show PCDOS = "PCDOS"
34 show UnixUuencoded = "Uuencoded"
35 show SearchService = "SearchService"
36 show TelnetSession = "Telnet"
37 show Binary = "Binary"
38 show Duplicated = "Duplicated"
39 show Gif = "Gif"
40 show Image = "Image"
41 show Tn3270Session ="Tn3270"
42 show InfoLine = "Info"
43 show HTML = "HTML"
44
45-- Selector used to retrieve a document from a server.
46public export
47Selector : Type
48Selector = String
49
50-- Address of a server which stores a given document.
51public export
52Address : Type
53Address = (String, Nat)
54
55-- Product type for a Gopher menu entry.
56public export
57data Item = MkItem ItemType String Selector Address
58
59public export
60unmarshalType : Char -> Maybe ItemType
61unmarshalType '0' = Just Document
62unmarshalType '1' = Just Directory
63unmarshalType '2' = Just PhoneBook
64unmarshalType '3' = Just Error
65unmarshalType '4' = Just BinHex
66unmarshalType '5' = Just PCDOS
67unmarshalType '6' = Just UnixUuencoded
68unmarshalType '7' = Just SearchService
69unmarshalType '8' = Just TelnetSession
70unmarshalType '9' = Just Binary
71unmarshalType '+' = Just Duplicated
72unmarshalType 'g' = Just Gif
73unmarshalType 'I' = Just Image
74unmarshalType 'i' = Just InfoLine
75unmarshalType 'T' = Just Tn3270Session
76unmarshalType 'h' = Just HTML
77unmarshalType _ = Nothing
78
79public export
80isUnAscii : Char -> Bool
81isUnAscii '\r' = False
82isUnAscii '\n' = False
83isUnAscii '\t' = False
84isUnAscii '\0' = False
85isUnAscii _ = True
86
87public export
88isHostPart : Char -> Bool
89isHostPart c = (isUnAscii c) && (c /= '.')
90
91partial
92recvMsg' : HasIO io => Socket -> List String -> io (Either SocketError String)
93recvMsg' sock acc = do
94 res <- recv sock bufsiz
95 case res of
96 Left err => if err == 0
97 then pure $ Right (concat acc)
98 else pure $ Left err
99 Right (str, n) => if isSuffixOf delim str
100 then pure $ let out = rmDelim str in
101 Right (concat $ acc ++ [out])
102 else recvMsg' sock (acc ++ [str])
103 where
104 bufsiz : ByteLength
105 bufsiz = 4096
106
107 delim : String
108 delim = "\r\n.\r\n"
109
110 rmDelim : String -> String
111 rmDelim s = strSubstr 0 (cast $ minus (length s) (length ".\r\n")) s
112
113export
114recvMsg : HasIO io => (sock : Socket) -> io (Either SocketError String)
115recvMsg sock = recvMsg' sock []