Encode spaces in filenames

This commit is contained in:
Matt Brubeck 2020-12-30 21:16:12 -08:00
parent 9683146851
commit 70b28a65e1
3 changed files with 13 additions and 2 deletions

1
Cargo.lock generated
View file

@ -11,6 +11,7 @@ dependencies = [
"log", "log",
"mime_guess", "mime_guess",
"once_cell", "once_cell",
"percent-encoding",
"rustls", "rustls",
"url", "url",
] ]

View file

@ -18,6 +18,7 @@ getopts = "0.2.21"
log = "0.4" log = "0.4"
mime_guess = "2.0" mime_guess = "2.0"
once_cell = "1.4" once_cell = "1.4"
percent-encoding = "2.1"
rustls = "0.19.0" rustls = "0.19.0"
url = "2.1" url = "2.1"

View file

@ -6,6 +6,7 @@ use async_std::{
}; };
use async_tls::TlsAcceptor; use async_tls::TlsAcceptor;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use percent_encoding::{AsciiSet, CONTROLS, percent_decode_str, percent_encode};
use rustls::{ use rustls::{
internal::pemfile::{certs, pkcs8_private_keys}, internal::pemfile::{certs, pkcs8_private_keys},
NoClientAuth, ServerConfig, NoClientAuth, ServerConfig,
@ -181,7 +182,9 @@ async fn parse_request<R: Read + Unpin>(
async fn send_response<W: Write + Unpin>(url: Url, stream: &mut W) -> Result { async fn send_response<W: Write + Unpin>(url: Url, stream: &mut W) -> Result {
let mut path = std::path::PathBuf::from(&ARGS.content_dir); let mut path = std::path::PathBuf::from(&ARGS.content_dir);
if let Some(segments) = url.path_segments() { if let Some(segments) = url.path_segments() {
path.extend(segments); for segment in segments {
path.push(&*percent_decode_str(segment).decode_utf8()?);
}
} }
if async_std::fs::metadata(&path).await?.is_dir() { if async_std::fs::metadata(&path).await?.is_dir() {
if url.path().ends_with('/') || url.path().is_empty() { if url.path().ends_with('/') || url.path().is_empty() {
@ -226,6 +229,7 @@ async fn send_header<W: Write + Unpin>(stream: &mut W, status: &str, meta: &[&st
} }
async fn list_directory<W: Write + Unpin>(stream: &mut W, path: &Path) -> Result { async fn list_directory<W: Write + Unpin>(stream: &mut W, path: &Path) -> Result {
const WHITESPACE: AsciiSet = CONTROLS.add(b' ');
log::info!("Listing directory {:?}", path); log::info!("Listing directory {:?}", path);
send_text_gemini_header(stream).await?; send_text_gemini_header(stream).await?;
let mut entries = async_std::fs::read_dir(path).await?; let mut entries = async_std::fs::read_dir(path).await?;
@ -239,8 +243,13 @@ async fn list_directory<W: Write + Unpin>(stream: &mut W, path: &Path) -> Result
if entry.file_type().await?.is_dir() { if entry.file_type().await?.is_dir() {
name += "/"; name += "/";
} }
if name.contains(char::is_whitespace) {
let url = percent_encode(name.as_bytes(), &WHITESPACE);
lines.push(format!("=> {} {}\n", url, name));
} else {
lines.push(format!("=> {}\n", name)); lines.push(format!("=> {}\n", name));
} }
}
lines.sort(); lines.sort();
for line in lines { for line in lines {
stream.write_all(line.as_bytes()).await?; stream.write_all(line.as_bytes()).await?;