exception Bad_selector let make_digests (arr:string array) = Array.map (fun str -> Digest.string str) arr let file_is_safe requested_file dig_list = let dig = Digest.string requested_file in Array.fold_left (fun acc digest -> if Digest.compare dig digest = 0 then true else acc) false dig_list let read_in_and_print ic = try while true do print_endline (input_line ic); done with | End_of_file -> () | Sys_error e -> Printf.fprintf stderr "%s\n" e let get_real_file rootdir basename = Stdlib.Filename.concat rootdir (Stdlib.Filename.basename basename) let check_exists full_path = Sys.file_exists full_path && Sys.is_regular_file full_path let validate_file_path rootdir path = check_exists (get_real_file rootdir path) let read_safe_root_digests rootdir = try Sys.readdir rootdir |> make_digests with Sys_error e -> Printf.fprintf stderr "%s\n" e; [||] let rec get_dir_from_selector selector dirpairs = match dirpairs with | [] -> None | hd :: tl -> match hd with | (tuple_selector, dir) when selector = tuple_selector -> Some dir | _ -> get_dir_from_selector selector tl let read_selector_and_filename () = let selector = read_line () and filename = read_line() in (selector, filename) let validate_and_print rootdir filename = let digests = read_safe_root_digests rootdir in if Array.length digests = 0 then false else begin match file_is_safe filename digests with | true -> begin match validate_file_path rootdir filename with | true -> begin try In_channel.with_open_bin (get_real_file rootdir filename) read_in_and_print; true with Sys_error e -> false end | false -> false end | false -> false end let program selector dirpairs filename = validate_and_print (match (get_dir_from_selector selector dirpairs) with | None -> (Printf.fprintf stderr "No directory found for selector '%s'\n" selector; raise Bad_selector) | Some dir -> dir ) filename .