http_mini_lib/utils/
fs.rs1use std::fs;
2use std::io::{Error, ErrorKind};
3use std::path::Path;
4
5pub fn validate_path(path: &Path) -> bool {
11 !path.is_symlink() && !path.is_relative()
12}
13
14pub fn get_file_contents(path: &str) -> Result<Vec<u8>, Error> {
16 let path_metadata = fs::metadata(path);
17 if path_metadata.is_err() {
18 return Err(path_metadata.err().unwrap());
19 }
20
21 let file_data = fs::read(path);
22 if file_data.is_err() {
23 return Err(file_data.err().unwrap());
24 }
25
26 Ok(file_data.ok().unwrap())
27}
28
29const HTML_TEMPLATE: &str =
30 "<!DOCTYPE html><html><head><title>###TITLE###</title></head><body>###BODY###</body></html>";
31const LISTING_LIST_START: &str = "<ul>";
32const LISTING_LIST_END: &str = "</ul>";
33const LISTING_LIST_ITEM_START: &str = "<li>";
34const LISTING_LIST_ITEM_END: &str = "</li>";
35const LISTING_DIR: &str = "<strong>DIR</strong> ";
36const LISTING_FILE: &str = "file ";
37const LISTING_LINK_PART_1: &str = "<a href=\"";
38const LISTING_LINK_PART_2: &str = "\" target=\"_self\">";
39const LISTING_LINK_PART_3: &str = "</a>";
40const LISTING_DIR_SLASH: &str = "/";
41
42pub fn get_dir_contents_as_html(
43 path: &Path,
44 source_dir: &Path,
45 address: &str,
46) -> Result<String, Error> {
47 if !path.is_dir() {
48 return Err(Error::new(ErrorKind::NotFound, "Not a directory"));
49 }
50
51 if !path.starts_with(source_dir) {
52 return Err(Error::new(ErrorKind::NotFound, "Access forbidden"));
53 }
54
55 let dir_read = fs::read_dir(path);
56 if dir_read.is_err() {
57 return Err(dir_read.err().unwrap());
58 }
59
60 let mut result = format!("{}\n", LISTING_LIST_START);
61
62 let dir_paths = dir_read.unwrap();
63 for dir_path in dir_paths {
64 if dir_path.is_err() {
65 continue;
66 }
67
68 let dir_path = dir_path.unwrap();
69 let is_dir = dir_path.path().is_dir();
70 let entry_display_path = dir_path
71 .path()
72 .into_os_string()
73 .into_string()
74 .unwrap()
75 .replace(source_dir.to_str().unwrap(), ".");
76 let entry_server_uri = format!("{}{}", address, entry_display_path.trim_start_matches("."));
77
78 result = format!(
79 "{}{}{}{}{}{}{}{}{}{}\n",
80 result,
81 LISTING_LIST_ITEM_START,
82 if is_dir { LISTING_DIR } else { LISTING_FILE },
83 LISTING_LINK_PART_1,
84 entry_server_uri,
85 LISTING_LINK_PART_2,
86 entry_display_path,
87 LISTING_LINK_PART_3,
88 if is_dir { LISTING_DIR_SLASH } else { "" },
89 LISTING_LIST_ITEM_END,
90 );
91 }
92 result = format!("{}\n{}\n", result, LISTING_LIST_END);
93 result = HTML_TEMPLATE
94 .replace(
95 "###TITLE###",
96 path.to_str()
97 .unwrap()
98 .replace(source_dir.to_str().unwrap(), ".")
99 .as_str(),
100 )
101 .replace("###BODY###", result.as_str());
102
103 Ok(result)
104}