diff --git a/Cargo.lock b/Cargo.lock index 53b2db9..49c8530 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,11 +13,6 @@ dependencies = [ "memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "gophermap" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "hermit-abi" version = "0.1.5" @@ -51,7 +46,6 @@ version = "0.1.10-dev" dependencies = [ "alphanumeric-sort 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)", "content_inspector 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)", - "gophermap 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "shell-escape 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", "threadpool 1.7.1 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -72,7 +66,6 @@ dependencies = [ [metadata] "checksum alphanumeric-sort 1.0.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f37ce94154d73f6961f87571a3ab7814e1608f373bd55a933e3e771b6dd59fc4" "checksum content_inspector 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38" -"checksum gophermap 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6ec2186bfad5a5dcbc9307dbc2d2444062300a836ae91b00dd80c3b71c34af3b" "checksum hermit-abi 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "f629dc602392d3ec14bfc8a09b5e644d7ffd725102b48b81e59f90f2633621d7" "checksum libc 0.2.66 (registry+https://github.com/rust-lang/crates.io-index)" = "d515b1f41455adea1313a4a2ac8a8a477634fbae63cc6100e3aebb207ce61558" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" diff --git a/Cargo.toml b/Cargo.toml index f62fb90..b9e2366 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,5 @@ dev-version-ext = "dev" [dependencies] content_inspector = "0.2.4" threadpool = "1.7.1" -gophermap = "0.1.2" alphanumeric-sort = "1.0.11" shell-escape = "0.1.4" diff --git a/src/gopher.rs b/src/gopher.rs new file mode 100644 index 0000000..7656aff --- /dev/null +++ b/src/gopher.rs @@ -0,0 +1,127 @@ +//! Gopher type "borrowed" from phetch. +use std::fmt; + +/// Gopher types are defined according to RFC 1436. +#[allow(missing_docs)] +#[derive(Copy, Clone, PartialEq, Debug)] +pub enum Type { + Text, // 0 + Menu, // 1 + CSOEntity, // 2 + Error, // 3 + Binhex, // 4 + DOSFile, // 5 + UUEncoded, // 6 + Search, // 7 + Telnet, // 8 + Binary, // 9 + Mirror, // + + GIF, // g + Telnet3270, // T + HTML, // h + Image, // I + PNG, // p + Info, // i + Sound, // s + Document, // d +} + +impl Type { + /// Is this an info line? + pub fn is_info(self) -> bool { + self == Type::Info + } + + /// Text document? + pub fn is_text(self) -> bool { + self == Type::Text + } + + /// HTML link? + pub fn is_html(self) -> bool { + self == Type::HTML + } + + /// Telnet link? + pub fn is_telnet(self) -> bool { + self == Type::Telnet + } + + /// Is this a link, ie something we can navigate to or open? + pub fn is_link(self) -> bool { + !self.is_info() + } + + /// Is this something we can download? + pub fn is_download(self) -> bool { + match self { + Type::Binhex + | Type::DOSFile + | Type::UUEncoded + | Type::Binary + | Type::GIF + | Type::Image + | Type::PNG + | Type::Sound + | Type::Document => true, + _ => false, + } + } + + /// Gopher Item Type to RFC char. + pub fn to_char(self) -> char { + match self { + Type::Text => '0', + Type::Menu => '1', + Type::CSOEntity => '2', + Type::Error => '3', + Type::Binhex => '4', + Type::DOSFile => '5', + Type::UUEncoded => '6', + Type::Search => '7', + Type::Telnet => '8', + Type::Binary => '9', + Type::Mirror => '+', + Type::GIF => 'g', + Type::Telnet3270 => 'T', + Type::HTML => 'h', + Type::Image => 'I', + Type::PNG => 'p', + Type::Info => 'i', + Type::Sound => 's', + Type::Document => 'd', + } + } + + /// Create a Gopher Item Type from its RFC char code. + pub fn from(c: char) -> Option { + Some(match c { + '0' => Type::Text, + '1' => Type::Menu, + '2' => Type::CSOEntity, + '3' => Type::Error, + '4' => Type::Binhex, + '5' => Type::DOSFile, + '6' => Type::UUEncoded, + '7' => Type::Search, + '8' => Type::Telnet, + '9' => Type::Binary, + '+' => Type::Mirror, + 'g' => Type::GIF, + 'T' => Type::Telnet3270, + 'h' => Type::HTML, + 'I' => Type::Image, + 'p' => Type::PNG, + 'i' => Type::Info, + 's' => Type::Sound, + 'd' => Type::Document, + _ => return None, + }) + } +} + +impl fmt::Display for Type { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "{}", self.to_char()) + } +} diff --git a/src/lib.rs b/src/lib.rs index 908cbca..8d04bc8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,6 +11,7 @@ #![allow(clippy::while_let_on_iterator)] pub mod color; +pub mod gopher; pub mod request; pub mod server; diff --git a/src/server.rs b/src/server.rs index 1dfa583..84c0211 100644 --- a/src/server.rs +++ b/src/server.rs @@ -1,7 +1,6 @@ //! A simple multi-threaded Gopher server. -use crate::{color, Request, Result}; -use gophermap::ItemType; +use crate::{color, gopher, Request, Result}; use std::{ cmp::Ordering, fs::{self, DirEntry}, @@ -326,9 +325,9 @@ where } /// Determine the gopher type for a DirEntry on disk. -fn file_type(dir: &fs::DirEntry) -> ItemType { +fn file_type(dir: &fs::DirEntry) -> gopher::Type { let metadata = match dir.metadata() { - Err(_) => return ItemType::Error, + Err(_) => return gopher::Type::Error, Ok(md) => md, }; @@ -337,17 +336,17 @@ fn file_type(dir: &fs::DirEntry) -> ItemType { let mut buffer: Vec = vec![]; let _ = file.take(MAX_PEEK_SIZE as u64).read_to_end(&mut buffer); if content_inspector::inspect(&buffer).is_binary() { - ItemType::Binary + gopher::Type::Binary } else { - ItemType::File + gopher::Type::Text } } else { - ItemType::Error + gopher::Type::Error } } else if metadata.is_dir() { - ItemType::Directory + gopher::Type::Menu } else { - ItemType::Error + gopher::Type::Error } }