From 80f1c2cf75f3ef491e6a242199f54793eadf1571 Mon Sep 17 00:00:00 2001 From: dvkt Date: Fri, 27 Dec 2019 22:17:42 -0800 Subject: [PATCH] .reverse --- README.md | 3 ++- src/server.rs | 14 ++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1474fb9..2737bca 100644 --- a/README.md +++ b/README.md @@ -12,10 +12,11 @@ point it at a directory and it'll serve up all its text files, sub-directories, special files: -- **header.gph**: if it exists in a directoy, its content will be shown above the directory's content. put ascii art in it. +- **header.gph**: if it exists in a directory, its content will be shown above the directory's content. put ascii art in it. - **footer.gph**: same, but will be shown below a directory's content. - **index.gph**: completely replaces a directory's content with what's in this file. - **??.gph**: visiting gopher://yoursite/1/dog/ will try to render `dog.gph` on disk. +- **.reverse**: if this exists, the directory contents will be listed in reverse alphanumeric order. useful for phloggin'. Any line in a `.gph` file that doesn't contain any tabs (`\t`) and doesn't start with an `i` will get an `i` automatically prefixed, turning it into a gopher information item. diff --git a/src/server.rs b/src/server.rs index af0598c..a113be3 100644 --- a/src/server.rs +++ b/src/server.rs @@ -19,6 +19,9 @@ const MAX_PEEK_SIZE: usize = 1024; /// how many bytes to read() from the socket at a time. const TCP_BUF_SIZE: usize = 1024; +/// Files not displayed in directory listings. +const IGNORED_FILES: [&str; 3] = ["header.gph", "footer.gph", ".reverse"]; + /// Starts a Gopher server at the specified host, port, and root directory. pub fn start(host: &str, port: u16, root: &str) -> Result<()> { let addr = format!("{}:{}", host, port); @@ -127,11 +130,18 @@ where // sort directory entries let mut paths: Vec<_> = fs::read_dir(&path)?.filter_map(|r| r.ok()).collect(); - paths.sort_by_key(|dir| dir.path()); + let mut reverse = path.clone(); + reverse.push_str("/.reverse"); + if Path::new(&reverse).exists() { + paths.sort_by_key(|dir| std::cmp::Reverse(dir.path())); + } else { + paths.sort_by_key(|dir| dir.path()); + } for entry in paths { let file_name = entry.file_name(); - if file_name == "header.gph" || file_name == "footer.gph" { + let f = file_name.to_string_lossy().to_string(); + if IGNORED_FILES.contains(&f.as_ref()) { continue; } let mut path = rel_path.clone();