- Server and client now have dedicated module files - Menu and Item have their own module files - Wrote parsers for Menu and Item - Switch from jbuilder to dune - Introducing gopher client - IPv6
80 lines
2.1 KiB
OCaml
80 lines
2.1 KiB
OCaml
type item_t =
|
|
| Text_file
|
|
| Submenu
|
|
| CCSO_nameserver
|
|
| Error
|
|
| Binhexencoded_file
|
|
| DOS_file
|
|
| Uuencoded_file
|
|
| Text_search
|
|
| Telnet
|
|
| Binary_file
|
|
| Alternate_server
|
|
| GIF_file
|
|
| Image_file
|
|
| Telnet_3270
|
|
| HTML_file
|
|
| Informational_message
|
|
| Sound_file
|
|
| Unknown
|
|
|
|
type t = { item_type : item_t; display_string : string; selector : string; hostname : string; port : int }
|
|
|
|
let char_of_type = function
|
|
| Text_file -> '0'
|
|
| Submenu -> '1'
|
|
| CCSO_nameserver -> '2'
|
|
| Error -> '3'
|
|
| Binhexencoded_file -> '4'
|
|
| DOS_file -> '5'
|
|
| Uuencoded_file -> '6'
|
|
| Text_search -> '7'
|
|
| Telnet -> '8'
|
|
| Binary_file -> '9'
|
|
| Alternate_server -> '+'
|
|
| GIF_file -> 'g'
|
|
| Image_file -> 'I'
|
|
| Telnet_3270 -> 'T'
|
|
| HTML_file -> 'h'
|
|
| Informational_message -> 'i'
|
|
| Sound_file -> 's'
|
|
| Unknown -> ' '
|
|
|
|
let type_of_char = function
|
|
| '0' -> Text_file
|
|
| '1' -> Submenu
|
|
| '2' -> CCSO_nameserver
|
|
| '3' -> Error
|
|
| '4' -> Binhexencoded_file
|
|
| '5' -> DOS_file
|
|
| '6' -> Uuencoded_file
|
|
| '7' -> Text_search
|
|
| '8' -> Telnet
|
|
| '9' -> Binary_file
|
|
| '+' -> Alternate_server
|
|
| 'g' -> GIF_file
|
|
| 'I' -> Image_file
|
|
| 'T' -> Telnet_3270
|
|
| 'h' -> HTML_file
|
|
| 'i' -> Informational_message
|
|
| 's' -> Sound_file
|
|
| _ -> Unknown
|
|
|
|
let line item_type user_display selector hostname port =
|
|
let (<+>) a b = a ^ "\t" ^ b in
|
|
(Char.escaped (char_of_type item_type)) ^ user_display <+> selector <+> hostname <+> string_of_int port <+> "\r\n"
|
|
|
|
let empty = { item_type = Unknown; display_string = ""; selector = ""; hostname = ""; port = 0 }
|
|
|
|
let of_line line =
|
|
let item_type = try type_of_char @@ String.get line 0 with _ -> Unknown in
|
|
if item_type = Unknown then empty
|
|
else (
|
|
let fields = String.split_on_char '\t' (String.sub line 1 (String.length line - 1)) in
|
|
let nth n = match List.nth_opt fields n with Some v -> v | None -> "" in
|
|
let port = try int_of_string (nth 3) with Failure _ -> 0 in
|
|
{ item_type; display_string = nth 0; selector = nth 1; hostname = nth 2; port }
|
|
)
|
|
|
|
let v item_type display_string selector hostname port =
|
|
{ item_type; display_string; selector; hostname; port }
|