diff --git a/crates/ptth_relay/src/lib.rs b/crates/ptth_relay/src/lib.rs index d4d0a96..25247fd 100644 --- a/crates/ptth_relay/src/lib.rs +++ b/crates/ptth_relay/src/lib.rs @@ -1,5 +1,9 @@ #![warn (clippy::pedantic)] +// I don't see the point of writing the type twice if I'm initializing a struct +// and the type is already in the struct definition. +#![allow (clippy::default_trait_access)] + // I'm not sure if I like this one #![allow (clippy::enum_glob_use)] @@ -7,15 +11,11 @@ // error type is defined. #![allow (clippy::missing_errors_doc)] -// I don't see the point of writing the type twice if I'm initializing a struct -// and the type is already in the struct definition. -#![allow (clippy::default_trait_access)] - // False positive on futures::select! macro #![allow (clippy::mut_mut)] use std::{ - borrow::Cow, + borrow::Cow, collections::HashMap, convert::TryFrom, iter::FromIterator, diff --git a/crates/ptth_server/src/bin/ptth_file_server.rs b/crates/ptth_server/src/bin/ptth_file_server.rs index cd517ae..ae5eaf3 100644 --- a/crates/ptth_server/src/bin/ptth_file_server.rs +++ b/crates/ptth_server/src/bin/ptth_file_server.rs @@ -40,14 +40,16 @@ struct ServerState <'a> { } fn status_reply > (status: StatusCode, b: B) --> Response +-> Result , hyper::http::Error> { - Response::builder ().status (status).body (b.into ()).unwrap () + Response::builder ().status (status).body (b.into ()) } async fn handle_all (req: Request , state: Arc >) --> Result , String> +-> Result , hyper::http::Error> { + use std::str::FromStr; + debug! ("req.uri () = {:?}", req.uri ()); let path_and_query = req.uri ().path_and_query ().map (|x| x.as_str ()).unwrap_or_else (|| req.uri ().path ()); @@ -58,7 +60,7 @@ async fn handle_all (req: Request , state: Arc >) let ptth_req = match RequestParts::from_hyper (parts.method, path_and_query, parts.headers) { Ok (x) => x, - _ => return Ok (status_reply (StatusCode::BAD_REQUEST, "Bad request")), + _ => return Ok (status_reply (StatusCode::BAD_REQUEST, "Bad request")?), }; let default_root = PathBuf::from ("./"); @@ -79,10 +81,8 @@ async fn handle_all (req: Request , state: Arc >) let mut resp = Response::builder () .status (StatusCode::from (ptth_resp.parts.status_code)); - use std::str::FromStr; - for (k, v) in ptth_resp.parts.headers.into_iter () { - resp = resp.header (hyper::header::HeaderName::from_str (&k).unwrap (), v); + resp = resp.header (hyper::header::HeaderName::from_str (&k)?, v); } let body = ptth_resp.body @@ -90,9 +90,7 @@ async fn handle_all (req: Request , state: Arc >) .unwrap_or_else (Body::empty) ; - let resp = resp.body (body).unwrap (); - - Ok (resp) + resp.body (body) } #[derive (Deserialize)] diff --git a/crates/ptth_server/src/file_server/mod.rs b/crates/ptth_server/src/file_server/mod.rs index e5932a6..3715e2a 100644 --- a/crates/ptth_server/src/file_server/mod.rs +++ b/crates/ptth_server/src/file_server/mod.rs @@ -1,9 +1,12 @@ // Static file server that can plug into the PTTH reverse server +// I'm not sure if I like this one +#![allow (clippy::enum_glob_use)] + use std::{ borrow::Cow, cmp::min, - collections::*, + collections::HashMap, convert::{Infallible, TryInto}, error::Error, fmt::Debug, @@ -12,7 +15,9 @@ use std::{ }; use handlebars::Handlebars; -use percent_encoding::*; +use percent_encoding::{ + percent_decode, +}; use serde::Serialize; use tokio::{ fs::{ @@ -84,7 +89,7 @@ struct TemplateDirPage <'a> { } fn parse_range_header (range_str: &str) -> (Option , Option ) { - use lazy_static::*; + use lazy_static::lazy_static; lazy_static! { static ref RE: Regex = Regex::new (r"^bytes=(\d*)-(\d*)$").expect ("Couldn't compile regex for Range header"); @@ -94,17 +99,17 @@ fn parse_range_header (range_str: &str) -> (Option , Option ) { let caps = match RE.captures (range_str) { Some (x) => x, - _ => return (None, None), + None => return (None, None), }; let start = caps.get (1).map (|x| x.as_str ()); let end = caps.get (2).map (|x| x.as_str ()); - let start = start.map (|x| u64::from_str_radix (x, 10).ok ()).flatten (); + let start = start.and_then (|x| u64::from_str_radix (x, 10).ok ()); // HTTP specifies ranges as [start inclusive, end inclusive] // But that's dumb and [start inclusive, end exclusive) is better - let end = end.map (|x| u64::from_str_radix (x, 10).ok ().map (|x| x + 1)).flatten (); + let end = end.and_then (|x| u64::from_str_radix (x, 10).ok ().map (|x| x + 1)); (start, end) } @@ -151,9 +156,9 @@ fn check_range (range_str: Option <&str>, file_len: u64) fn get_icon (file_name: &str) -> &'static str { // Because my editor actually doesn't render these - let video = "🎞️"; - let picture = "📷"; - let file = "📄"; + let video = "\u{1f39e}\u{fe0f}"; + let picture = "\u{1f4f7}"; + let file = "\u{1f4c4}"; if file_name.ends_with (".mp4") || @@ -178,10 +183,15 @@ fn get_icon (file_name: &str) -> &'static str { async fn read_dir_entry (entry: DirEntry) -> TemplateDirEntry { + use percent_encoding::{ + CONTROLS, + utf8_percent_encode, + }; + let file_name = match entry.file_name ().into_string () { Ok (x) => x, Err (_) => return TemplateDirEntry { - icon: "⚠️", + icon: "\u{26a0}\u{fe0f}", trailing_slash: "", file_name: "File / directory name is not UTF-8".into (), encoded_file_name: "".into (), @@ -193,7 +203,7 @@ async fn read_dir_entry (entry: DirEntry) -> TemplateDirEntry let metadata = match entry.metadata ().await { Ok (x) => x, Err (_) => return TemplateDirEntry { - icon: "⚠️", + icon: "\u{26a0}\u{fe0f}", trailing_slash: "", file_name: "Could not fetch metadata".into (), encoded_file_name: "".into (), @@ -204,7 +214,7 @@ async fn read_dir_entry (entry: DirEntry) -> TemplateDirEntry let (trailing_slash, icon, size) = { let t = metadata.file_type (); - let icon_folder = "📁"; + let icon_folder = "\u{1f4c1}"; if t.is_dir () { ("/", icon_folder, "".into ()) @@ -214,8 +224,6 @@ async fn read_dir_entry (entry: DirEntry) -> TemplateDirEntry } }; - use percent_encoding::*; - let encoded_file_name = utf8_percent_encode (&file_name, CONTROLS).to_string (); TemplateDirEntry { @@ -307,7 +315,7 @@ async fn serve_file ( let mut next_mark = mark_interval; loop { - let mut buffer = vec! [0u8; 65_536]; + let mut buffer = vec! [0_u8; 65_536]; let bytes_read: u64 = f.read (&mut buffer).await.unwrap ().try_into ().unwrap (); let bytes_read = min (bytes_left, bytes_read); @@ -353,11 +361,11 @@ async fn serve_file ( response.header (String::from ("content-length"), range.end.to_string ().into_bytes ()); } - if ! should_send_body { - response.status_code (StatusCode::NoContent); + if should_send_body { + response.content_length = Some (content_length); } else { - response.content_length = Some (content_length); + response.status_code (StatusCode::NoContent); } if let Some (body) = body { @@ -546,7 +554,7 @@ async fn internal_serve_all ( let file_len = file_md.len (); - let range_header = headers.get ("range").map (|v| std::str::from_utf8 (v).ok ()).flatten (); + let range_header = headers.get ("range").and_then (|v| std::str::from_utf8 (v).ok ()); match check_range (range_header, file_len) { ParsedRange::RangeNotSatisfiable (file_len) => RangeNotSatisfiable (file_len), @@ -557,7 +565,7 @@ async fn internal_serve_all ( MarkdownErr (MarkdownError::TooBig) } else { - let mut buffer = vec! [0u8; MAX_BUF_SIZE.try_into ().unwrap ()]; + let mut buffer = vec! [0_u8; MAX_BUF_SIZE.try_into ().unwrap ()]; let bytes_read = file.read (&mut buffer).await.unwrap (); buffer.truncate (bytes_read); @@ -656,10 +664,10 @@ pub fn load_templates ( let asset_root = asset_root.join ("handlebars/server"); - for (k, v) in vec! [ + for (k, v) in &[ ("file_server_dir", "file_server_dir.html"), ("file_server_root", "file_server_root.html"), - ].into_iter () { + ] { handlebars.register_template_file (k, asset_root.join (v))?; } diff --git a/crates/ptth_server/src/lib.rs b/crates/ptth_server/src/lib.rs index 41dcaea..588a61e 100644 --- a/crates/ptth_server/src/lib.rs +++ b/crates/ptth_server/src/lib.rs @@ -1,3 +1,12 @@ +#![warn (clippy::pedantic)] + +// I don't see the point in documenting the errors outside of where the +// error type is defined. +#![allow (clippy::missing_errors_doc)] + +// False positive on futures::select! macro +#![allow (clippy::mut_mut)] + use std::{ error::Error, path::PathBuf, @@ -30,6 +39,7 @@ pub mod load_toml; const BAD_PASSWORDS: &[u8] = include_bytes! ("bad_passwords.txt"); +#[must_use] pub fn password_is_bad (mut password: String) -> bool { password.make_ascii_lowercase (); @@ -66,7 +76,7 @@ async fn handle_req_resp <'a> ( debug! ("Unwrapped {} requests", wrapped_reqs.len ()); - for wrapped_req in wrapped_reqs.into_iter () { + for wrapped_req in wrapped_reqs { let state = state.clone (); tokio::spawn (async move { @@ -136,6 +146,7 @@ pub struct ConfigFile { } impl ConfigFile { + #[must_use] pub fn tripcode (&self) -> String { base64::encode (blake3::hash (self.api_key.as_bytes ()).as_bytes ()) } @@ -155,10 +166,10 @@ pub async fn run_server ( ) -> Result <(), Box > { - let asset_root = asset_root.unwrap_or_else (PathBuf::new); - use std::convert::TryInto; + let asset_root = asset_root.unwrap_or_else (PathBuf::new); + if password_is_bad (config_file.api_key.clone ()) { panic! ("API key is too weak, server can't use it"); } diff --git a/crates/ptth_server/src/load_toml.rs b/crates/ptth_server/src/load_toml.rs index 921ce1f..1922adb 100644 --- a/crates/ptth_server/src/load_toml.rs +++ b/crates/ptth_server/src/load_toml.rs @@ -14,7 +14,7 @@ fn load_inner < > ( mut f: File ) -> T { - let mut buffer = vec! [0u8; 4096]; + let mut buffer = vec! [0_u8; 4096]; let bytes_read = f.read (&mut buffer).unwrap_or_else (|_| panic! ("Can't read config")); buffer.truncate (bytes_read);