diff --git a/src/download.rs b/src/download.rs index aad73e8..21fabda 100644 --- a/src/download.rs +++ b/src/download.rs @@ -16,8 +16,8 @@ use inotify::{Inotify, WatchMask}; use log::trace; use pin_project_lite::pin_project; use serde::{de, Deserialize, Deserializer}; -use std::{os::unix::fs::MetadataExt, time::SystemTime}; use time::OffsetDateTime; +use std::{os::unix::fs::MetadataExt, time::SystemTime}; use actix_web::{ body::{self, BoxBody, SizedStream}, @@ -64,9 +64,7 @@ impl<'de> de::Visitor<'de> for SelectionVisitor { } fn visit_str(self, v: &str) -> Result - where - E: de::Error, - { + where E: de::Error { if v == "all" { Ok(DownloadSelection::All) } else if let Ok(n) = v.parse::() { @@ -78,7 +76,9 @@ impl<'de> de::Visitor<'de> for SelectionVisitor { } impl<'de> Deserialize<'de> for DownloadSelection { - fn deserialize>(de: D) -> Result { + fn deserialize>( + de: D + ) -> Result { de.deserialize_any(SelectionVisitor) } } @@ -122,10 +122,8 @@ impl DownloadingFile { } fn baseline_offset(&self) -> u64 { - if let (DownloadSelection::One(n), Some(files)) = - (self.selection, self.info.contents.as_ref()) - { - crate::zip::file_data_offset(files, n) + if let (DownloadSelection::One(n), Some(files)) = (self.selection, self.info.contents.as_ref()) { + crate::zip::file_data_offset(&files, n) } else { 0 } @@ -186,7 +184,12 @@ impl DownloadingFile { res.insert_header(( header::CONTENT_RANGE, - format!("bytes {}-{}/{}", offset, offset + length - 1, total_size,), + format!( + "bytes {}-{}/{}", + offset, + offset + length - 1, + total_size, + ), )); } else { res.insert_header((header::CONTENT_RANGE, format!("bytes */{}", length))); @@ -206,12 +209,7 @@ impl DownloadingFile { .map_into_boxed_body(); } - let reader = new_live_reader( - length, - self.baseline_offset() + offset, - self.file, - self.storage_path, - ); + let reader = new_live_reader(length, self.baseline_offset() + offset, self.file, self.storage_path); if offset != 0 || length != total_size { res.status(StatusCode::PARTIAL_CONTENT); diff --git a/src/main.rs b/src/main.rs index 2fa3456..5eb24f5 100644 --- a/src/main.rs +++ b/src/main.rs @@ -8,8 +8,8 @@ use std::{fmt::Debug, path::PathBuf, str::FromStr}; use actix_files::NamedFile; use actix_web::{ - error::InternalError, get, http::StatusCode, middleware::Logger, post, web, App, HttpRequest, - HttpResponse, HttpServer, Responder, + get, http::StatusCode, middleware::Logger, post, web, App, HttpRequest, HttpResponse, + HttpServer, Responder, }; use actix_web_actors::ws; use askama::Template; @@ -51,28 +51,28 @@ pub fn log_auth_failure(ip_addr: &str) { warn!("Incorrect authentication attempt from {}", ip_addr); } + #[derive(Deserialize)] struct DownloadRequest { code: String, download: Option, } -#[derive(Serialize, Template)] +#[derive(Template)] #[template(path = "download.html")] -struct DownloadInfo { +struct DownloadInfo<'a> { file: StoredFile, - code: String, + code: &'a str, available: u64, - offsets: Option>, } #[get("/download")] async fn handle_download( req: HttpRequest, - query: web::Query, + download: web::Query, data: web::Data, ) -> actix_web::Result { - let code = &query.code; + let code = &download.code; if !store::is_valid_storage_code(code) { return not_found(req, data, true); } @@ -80,12 +80,12 @@ async fn handle_download( let info = if let Some(i) = info { i } else { - return not_found(req, data, true); + return not_found(req, data, true) }; let storage_path = data.config.storage_dir.join(code); let file = File::open(&storage_path).await?; - if let Some(selection) = query.download { + if let Some(selection) = download.download { if let download::DownloadSelection::One(n) = selection { if let Some(ref files) = info.contents { if n >= files.len() { @@ -101,66 +101,28 @@ async fn handle_download( info, selection, } - .into_response(&req)) + .into_response(&req)) } else { - let offsets = info.contents.as_deref().map(zip::file_data_offsets); - Ok(HttpResponse::Ok().body( - DownloadInfo { - file: info, - code: code.clone(), - available: file.metadata().await?.len(), - offsets, - } - .render() - .unwrap(), - )) + Ok(HttpResponse::Ok().body(DownloadInfo { + file: info, + code, + available: file.metadata().await?.len(), + }.render().unwrap())) } } -#[derive(Deserialize)] -struct InfoQuery { - code: String, -} - -#[get("/info")] -async fn download_info( +fn not_found( req: HttpRequest, - query: web::Query, data: web::Data, -) -> actix_web::Result { - let code = &query.code; - if !store::is_valid_storage_code(code) { - return not_found(req, data, true); - } - let info = data.file_store.read().await.lookup_file(code); - let info = if let Some(i) = info { - i - } else { - return not_found(req, data, true); - }; - - let storage_path = data.config.storage_dir.join(code); - let offsets = info.contents.as_deref().map(zip::file_data_offsets); - Ok(web::Json(DownloadInfo { - file: info, - code: code.clone(), - available: File::open(&storage_path).await?.metadata().await?.len(), - offsets, - })) -} - -fn not_found(req: HttpRequest, data: web::Data, report: bool) -> actix_web::Result { + report: bool, +) -> actix_web::Result { if report { let ip_addr = get_ip_addr(&req, data.config.reverse_proxy); log_auth_failure(&ip_addr); } - Err(InternalError::from_response( - "Download not found", - NamedFile::open(data.config.static_dir.join("404.html"))? - .set_status_code(StatusCode::NOT_FOUND) - .into_response(&req), - ) - .into()) + Ok(NamedFile::open(data.config.static_dir.join("404.html"))? + .set_status_code(StatusCode::NOT_FOUND) + .into_response(&req)) } #[get("/upload")] @@ -282,7 +244,6 @@ async fn main() -> std::io::Result<()> { Logger::default() }) .service(handle_download) - .service(download_info) .service(handle_upload) .service(check_upload_password) .service(upload_limits) diff --git a/src/timestamp.rs b/src/timestamp.rs index 8ee8a82..fb79450 100644 --- a/src/timestamp.rs +++ b/src/timestamp.rs @@ -3,7 +3,10 @@ use core::fmt; use serde::{de::Visitor, Deserializer, Serializer}; use time::OffsetDateTime; -pub(crate) fn serialize(time: &OffsetDateTime, ser: S) -> Result { +pub(crate) fn serialize( + time: &OffsetDateTime, + ser: S, +) -> Result { ser.serialize_i64(time.unix_timestamp()) } @@ -25,7 +28,9 @@ impl<'de> Visitor<'de> for I64Visitor { } } -pub(crate) fn deserialize<'de, D: Deserializer<'de>>(de: D) -> Result { +pub(crate) fn deserialize<'de, D: Deserializer<'de>>( + de: D, +) -> Result { Ok( OffsetDateTime::from_unix_timestamp(de.deserialize_i64(I64Visitor)?) .unwrap_or_else(|_| OffsetDateTime::now_utc()), diff --git a/src/zip.rs b/src/zip.rs index 3160e84..c0001e8 100644 --- a/src/zip.rs +++ b/src/zip.rs @@ -43,17 +43,6 @@ pub fn file_data_offset(files: &[UploadedFile], idx: usize) -> u64 { + files[idx].name.len() as u64 } -pub fn file_data_offsets(files: &[UploadedFile]) -> Vec { - let mut offsets = Vec::new(); - let mut offset: u64 = 0; - for file in files.iter() { - offset += LOCAL_HEADER_SIZE_MINUS_FILENAME + file.name.len() as u64; - offsets.push(offset); - offset += file.size + DATA_DESCRIPTOR_SIZE; - } - offsets -} - fn central_directory_size(files: &[UploadedFile]) -> u64 { let mut total = 0; for file in files.iter() { diff --git a/static/css/transbeam.css b/static/css/transbeam.css index a8d0792..48d38ba 100644 --- a/static/css/transbeam.css +++ b/static/css/transbeam.css @@ -4,7 +4,6 @@ body { max-width: 512px; margin: 0.5em auto; padding: 0 1em; - overflow-wrap: break-word; } #header h1 { diff --git a/static/js/download.js b/static/js/download.js deleted file mode 100644 index ccd1168..0000000 --- a/static/js/download.js +++ /dev/null @@ -1,14 +0,0 @@ -document.addEventListener("DOMContentLoaded", () => { - const table = document.getElementById("download_contents").getElementsByTagName("tbody")[0]; - if (table.children.length === 0) { return; } - - setInterval(() => { - fetch(`info?code=${CODE}`) - .then((res) => res.json()) - .then((info) => { - for (const [index, offset] of info.offsets.entries()) { - table.children[index].className = (offset > info.available) ? "unavailable" : ""; - } - }); - }, 5000); -}); diff --git a/templates/download.html b/templates/download.html index f282db2..413cca4 100644 --- a/templates/download.html +++ b/templates/download.html @@ -4,12 +4,10 @@ + - {{ file.name }} - transbeam @@ -27,17 +25,16 @@ {% when Some with (files) %}

Contents

- - {% let offsets = offsets.as_ref().unwrap() %} +
{% for f in files %} - + {% endfor %} -
{{ bytesize::to_string(f.size.clone(), false).replace(" ", "") }} {{ f.name }}
+
{% else %} {% endmatch %}