diff --git a/README.md b/README.md index 087b49a..e4a655b 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,8 @@ sender has gone offline - Easy to send multiple files at once - they're bundled into a zip file for receivers, with zero compression so extraction is quick -- Sanitizes filenames +- Sanitises filenames, using sensible non-obnoxious defaults that + should be safe across platforms - Fires a laser beam that turns you trans ## configuration @@ -28,9 +29,7 @@ transbeam is configured with the following environment variables: ## todo -- [ ] file downloading -- [ ] upload progress bar -- [ ] uploader auth -- [ ] downloader auth -- [ ] delete uploads after a while -- [ ] configurable maximum file size +- uploader auth +- downloader auth +- delete uploads after a while +- configurable maximum file size diff --git a/src/upload.rs b/src/upload.rs index a87d5d5..90c95ec 100644 --- a/src/upload.rs +++ b/src/upload.rs @@ -11,6 +11,7 @@ use time::OffsetDateTime; use crate::{file::LiveWriter, DownloadableFile, UploadedFile}; +const MAX_FILES: usize = 256; const FILENAME_DATE_FORMAT: &[time::format_description::FormatItem] = time::macros::format_description!("[year]-[month]-[day]-[hour][minute][second]"); @@ -28,10 +29,12 @@ enum Error { UnexpectedMessageType, #[error("Metadata contained an empty list of files")] NoFiles, + #[error("Number of files submitted by client exceeded the maximum limit")] + TooManyFiles, #[error("Websocket was closed by client before completing transfer")] ClosedEarly(Option), #[error("Client sent more data than they were supposed to")] - TooMuchData, + UnexpectedExtraData, } impl Error { @@ -43,8 +46,9 @@ impl Error { Self::DuplicateFilename => CloseCode::Policy, Self::UnexpectedMessageType => CloseCode::Invalid, Self::NoFiles => CloseCode::Policy, + Self::TooManyFiles => CloseCode::Policy, Self::ClosedEarly(_) => CloseCode::Invalid, - Self::TooMuchData => CloseCode::Invalid, + Self::UnexpectedExtraData => CloseCode::Invalid, } } } @@ -105,7 +109,7 @@ impl StreamHandler> for Uploader { let msg = match msg { Ok(m) => m, Err(e) => { - error!("Websocket error: {:?}", e); + error!("Websocket error: {}", e); ctx.stop(); return; } @@ -113,7 +117,7 @@ impl StreamHandler> for Uploader { match self.handle_message(msg, ctx) { Err(e) => { - error!("{:?}", e); + error!("{}", e); ctx.close(Some(ws::CloseReason { code: e.close_code(), description: Some(e.to_string()), @@ -160,6 +164,9 @@ impl Uploader { let raw_files: Vec = serde_json::from_slice(text.as_bytes())?; info!("Received file list: {} files", raw_files.len()); debug!("{:?}", raw_files); + if raw_files.len() > MAX_FILES { + return Err(Error::TooManyFiles); + } let mut filenames: HashSet = HashSet::new(); let mut files = Vec::new(); for raw_file in raw_files.iter() { @@ -251,7 +258,7 @@ impl Uploader { fn handle_data(&mut self, data: Bytes) -> Result { if let Some(ref mut writer) = self.writer { if (data.len() as u64) > self.bytes_remaining { - return Err(Error::TooMuchData); + return Err(Error::UnexpectedExtraData); } self.bytes_remaining -= data.len() as u64; writer.write_all(&data)?; diff --git a/static/index.html b/static/index.html index da4dfbb..5728d64 100644 --- a/static/index.html +++ b/static/index.html @@ -5,7 +5,7 @@ - Upload Test + transbeam - + diff --git a/static/upload.js b/static/transbeam.js similarity index 97% rename from static/upload.js rename to static/transbeam.js index d1b570e..340d529 100644 --- a/static/upload.js +++ b/static/transbeam.js @@ -1,4 +1,5 @@ const FILE_CHUNK_SIZE = 16384; +const MAX_FILES = 256; const fileInputContainer = document.getElementById('file_input_container'); const fileInput = document.getElementById('file_input'); @@ -86,6 +87,7 @@ function updateFiles() { uploadButton.textContent = `Upload ${files.length} file${files.length > 1 ? 's' : ''} (${displaySize(totalBytes)})`; uploadButton.style.display = ''; } + fileInput.disabled = (files.length >= MAX_FILES); } updateFiles(); @@ -93,6 +95,7 @@ downloadLinkContainer.style.display = 'none'; progressContainer.style.display = 'none'; function addFile(newFile) { + if (files.length >= MAX_FILES) { return; } if (files.some((oldFile) => newFile.name === oldFile.name)) { return; } files.push(newFile);