From 6a17a84d3bcaa6443c1e674e857b802abc80a231 Mon Sep 17 00:00:00 2001 From: Edward Shen Date: Mon, 25 Oct 2021 17:31:30 -0700 Subject: [PATCH] Use naturalWidth and naturalHeight instead --- Cargo.lock | 7 ------- cli/src/main.rs | 6 ++++-- common/src/lib.rs | 2 +- server/src/main.rs | 19 +++++++++--------- web/Cargo.toml | 1 - web/src/decrypt.rs | 32 +++++++++--------------------- web/src/idb_object.rs | 8 +++++++- web/src/main.rs | 45 ++++++++++++++++++------------------------- web/src/main.ts | 25 ++++++++++++++++-------- web/src/util.rs | 3 --- 10 files changed, 67 insertions(+), 81 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a84e191..2b37cac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -648,12 +648,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "imagesize" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b3b62f4e783e38afa07b51eaaa789be2fba03dbe29a05a1a906eb64feb987d" - [[package]] name = "indexmap" version = "1.7.0" @@ -920,7 +914,6 @@ dependencies = [ "getrandom", "gloo-console", "http", - "imagesize", "js-sys", "omegaupload-common", "reqwasm", diff --git a/cli/src/main.rs b/cli/src/main.rs index 96b19bc..9a99337 100644 --- a/cli/src/main.rs +++ b/cli/src/main.rs @@ -113,8 +113,10 @@ fn handle_download(url: ParsedUrl) -> Result<()> { .get(EXPIRES) .and_then(|v| Expiration::try_from(v).ok()) .as_ref() - .map(ToString::to_string) - .unwrap_or_else(|| "This paste will not expire.".to_string()); + .map_or_else( + || "This paste will not expire.".to_string(), + ToString::to_string, + ); let mut data = res.bytes()?.as_ref().to_vec(); diff --git a/common/src/lib.rs b/common/src/lib.rs index 2cefdc2..90d8cef 100644 --- a/common/src/lib.rs +++ b/common/src/lib.rs @@ -303,7 +303,7 @@ impl TryFrom for Expiration { .ok() .flatten() .as_deref() - .and_then(|v| Expiration::try_from(v).ok()) + .and_then(|v| Self::try_from(v).ok()) .ok_or(ParseHeaderValueError) } } diff --git a/server/src/main.rs b/server/src/main.rs index bf01421..9f00602 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -48,7 +48,7 @@ async fn main() -> Result<()> { ], )?); - set_up_expirations(Arc::clone(&db)); + set_up_expirations(&db); axum::Server::bind(&"0.0.0.0:8081".parse()?) .serve( @@ -68,7 +68,7 @@ async fn main() -> Result<()> { Ok(()) } -fn set_up_expirations(db: Arc) { +fn set_up_expirations(db: &Arc) { let mut corrupted = 0; let mut expired = 0; let mut pending = 0; @@ -77,7 +77,7 @@ fn set_up_expirations(db: Arc) { let meta_cf = db.cf_handle(META_CF_NAME).unwrap(); - let db_ref = Arc::clone(&db); + let db_ref = Arc::clone(db); let delete_entry = move |key: &[u8]| { let blob_cf = db_ref.cf_handle(BLOB_CF_NAME).unwrap(); @@ -91,7 +91,7 @@ fn set_up_expirations(db: Arc) { }; for (key, value) in db.iterator_cf(meta_cf, IteratorMode::Start) { - let expires = if let Ok(value) = bincode::deserialize::(&value) { + let expiration = if let Ok(value) = bincode::deserialize::(&value) { value } else { corrupted += 1; @@ -99,7 +99,7 @@ fn set_up_expirations(db: Arc) { continue; }; - let expiration_time = match expires { + let expiration_time = match expiration { Expiration::BurnAfterReading => { panic!("Got burn after reading expiration time? Invariant violated"); } @@ -107,16 +107,16 @@ fn set_up_expirations(db: Arc) { }; let sleep_duration = (expiration_time - Utc::now()).to_std().unwrap_or_default(); - if sleep_duration != Duration::default() { + if sleep_duration == Duration::default() { + expired += 1; + delete_entry(&key); + } else { pending += 1; let delete_entry_ref = delete_entry.clone(); task::spawn_blocking(move || async move { tokio::time::sleep(sleep_duration).await; delete_entry_ref(&key); }); - } else { - expired += 1; - delete_entry(&key); } } @@ -125,6 +125,7 @@ fn set_up_expirations(db: Arc) { } else { warn!("Found {} corrupted pastes.", corrupted); } + info!("Found {} expired pastes.", expired); info!("Found {} active pastes.", pending); info!("Cleanup timers have been initialized."); diff --git a/web/Cargo.toml b/web/Cargo.toml index da03799..36f2c6a 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -17,7 +17,6 @@ console_error_panic_hook = "0.1" gloo-console = "0.1" http = "0.2" js-sys = "0.3" -imagesize = "0.9" reqwasm = "0.2" tree_magic_mini = { version = "3", features = ["with-gpl-data"] } wasm-bindgen = "0.2" diff --git a/web/src/decrypt.rs b/web/src/decrypt.rs index 2b72e01..689bd86 100644 --- a/web/src/decrypt.rs +++ b/web/src/decrypt.rs @@ -11,7 +11,7 @@ use web_sys::Blob; pub enum DecryptedData { String(Arc), Blob(Arc), - Image(Arc, (usize, usize), usize), + Image(Arc, usize), Audio(Arc), Video(Arc), } @@ -69,30 +69,16 @@ pub fn decrypt( Arc::new(Blob::new_with_u8_array_sequence(blob_chunks.dyn_ref().unwrap()).unwrap()); log!(format!("Blob conversion completed in {}ms", now() - start)); - log!("Image introspection started"); - let start = now(); - let dimensions = imagesize::blob_size(&container).ok(); - log!(format!( - "Image introspection completed in {}ms", - now() - start - )); + let mime_type = tree_magic_mini::from_u8(container); - if let Some(dimensions) = dimensions { - Ok(DecryptedData::Image( - blob, - (dimensions.width, dimensions.height), - container.len(), - )) + if mime_type.starts_with("image/") || mime_type == "application/x-riff" { + Ok(DecryptedData::Image(blob, container.len())) + } else if mime_type.starts_with("audio/") { + Ok(DecryptedData::Audio(blob)) + } else if mime_type.starts_with("video/") || mime_type == "application/x-matroska" { + Ok(DecryptedData::Video(blob)) } else { - let mime_type = tree_magic_mini::from_u8(container); - log!(mime_type); - if mime_type.starts_with("audio/") { - Ok(DecryptedData::Audio(blob)) - } else if mime_type.starts_with("video/") || mime_type.ends_with("x-matroska") { - Ok(DecryptedData::Video(blob)) - } else { - Ok(DecryptedData::Blob(blob)) - } + Ok(DecryptedData::Blob(blob)) } } } diff --git a/web/src/idb_object.rs b/web/src/idb_object.rs index e7847b7..f853c2e 100644 --- a/web/src/idb_object.rs +++ b/web/src/idb_object.rs @@ -17,7 +17,7 @@ impl IdbObject { impl From> for Object { fn from(db_object: IdbObject) -> Self { - match Object::from_entries(db_object.as_ref()) { + match Self::from_entries(db_object.as_ref()) { Ok(o) => o, // SAFETY: IdbObject maintains the invariant that it can eventually // be constructed into a JS object. @@ -52,6 +52,12 @@ impl IdbObject { } } +impl Default for IdbObject { + fn default() -> Self { + Self::new() + } +} + impl IdbObject { pub fn expiration_text(self, expires: &str) -> IdbObject { self.add_tuple("expiration", &JsString::from(expires)) diff --git a/web/src/main.rs b/web/src/main.rs index c5d68d0..eabc5ab 100644 --- a/web/src/main.rs +++ b/web/src/main.rs @@ -74,21 +74,19 @@ fn main() { .split_once('#') .map(|(_, fragment)| PartialParsedUrl::from(fragment)) .unwrap_or_default(); - let key = match partial_parsed_url.decryption_key { - Some(key) => key, - None => { - error!("Key is missing in url; bailing."); - render_message("Invalid paste link: Missing decryption key.".into()); - return; - } + let key = if let Some(key) = partial_parsed_url.decryption_key { + key + } else { + error!("Key is missing in url; bailing."); + render_message("Invalid paste link: Missing decryption key.".into()); + return; }; - let nonce = match partial_parsed_url.nonce { - Some(nonce) => nonce, - None => { - error!("Nonce is missing in url; bailing."); - render_message("Invalid paste link: Missing nonce.".into()); - return; - } + let nonce = if let Some(nonce) = partial_parsed_url.nonce { + nonce + } else { + error!("Nonce is missing in url; bailing."); + render_message("Invalid paste link: Missing nonce.".into()); + return; }; (key, nonce, partial_parsed_url.needs_password) }; @@ -175,20 +173,15 @@ async fn fetch_resources( DecryptedData::Blob(blob) => { IdbObject::new().blob().expiration_text(&expires).data(blob) } - DecryptedData::Image(blob, (width, height), size) => IdbObject::new() + DecryptedData::Image(blob, size) => IdbObject::new() .image() .expiration_text(&expires) .data(blob) - .extra("width", *width) - .extra("height", *height) .extra( - "button", - &format!( - "Download {} \u{2014} {} by {}", - Byte::from_bytes(*size as u128).get_appropriate_unit(true), - width, - height, - ), + "file_size", + Byte::from_bytes(*size as u128) + .get_appropriate_unit(true) + .to_string(), ), DecryptedData::Audio(blob) => IdbObject::new() .audio() @@ -233,7 +226,7 @@ async fn fetch_resources( )); let on_upgrade = Closure::wrap(Box::new(move |event: Event| { let db = as_idb_db(&event); - let _ = db.create_object_store("decrypted data").unwrap(); + let _obj_store = db.create_object_store("decrypted data").unwrap(); }) as Box); db_open_req.set_onupgradeneeded(Some(on_upgrade.into_js_value().unchecked_ref())); } @@ -244,7 +237,7 @@ async fn fetch_resources( render_message("Invalid paste URL.".into()); } Ok(err) => { - render_message(format!("{}", err.status_text()).into()); + render_message(err.status_text().into()); } Err(err) => { render_message(format!("{}", err).into()); diff --git a/web/src/main.ts b/web/src/main.ts index 83ed4a7..bda6b7e 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -117,8 +117,12 @@ function createBlobPasteUi(data) { bodyEle.appendChild(mainEle); } -function createImagePasteUi({ expiration, data, button }) { - createMultiMediaPasteUi("img", expiration, data, button); +function createImagePasteUi({ expiration, data, file_size }) { + createMultiMediaPasteUi("img", expiration, data, (downloadEle, imgEle) => { + imgEle.onload = () => { + downloadEle.textContent = "Download " + file_size + " \u2014 " + imgEle.naturalWidth + " by " + imgEle.naturalHeight; + } + }); } function createAudioPasteUi({ expiration, data }) { @@ -129,7 +133,7 @@ function createVideoPasteUi({ expiration, data }) { createMultiMediaPasteUi("video", expiration, data, "Download"); } -function createMultiMediaPasteUi(tag, expiration, data, downloadMessage) { +function createMultiMediaPasteUi(tag, expiration, data, on_create?) { let bodyEle = document.getElementsByTagName("body")[0]; bodyEle.textContent = ''; @@ -144,19 +148,24 @@ function createMultiMediaPasteUi(tag, expiration, data, downloadMessage) { expirationEle.textContent = expiration; mainEle.appendChild(expirationEle); - let videoEle = document.createElement(tag); - videoEle.src = downloadLink; - videoEle.controls = true; - mainEle.appendChild(videoEle); + let mediaEle = document.createElement(tag); + mediaEle.src = downloadLink; + mediaEle.controls = true; + mainEle.appendChild(mediaEle); let downloadEle = document.createElement("a"); downloadEle.href = downloadLink; downloadEle.download = window.location.pathname; downloadEle.classList.add("hljs-meta"); - downloadEle.textContent = downloadMessage; mainEle.appendChild(downloadEle); bodyEle.appendChild(mainEle); + + if (on_create instanceof Function) { + on_create(downloadEle, mediaEle); + } else { + downloadEle.textContent = on_create; + } } function renderMessage(message) { diff --git a/web/src/util.rs b/web/src/util.rs index 3897827..e048f16 100644 --- a/web/src/util.rs +++ b/web/src/util.rs @@ -1,6 +1,3 @@ -use js_sys::Function; -use wasm_bindgen::closure::WasmClosure; -use wasm_bindgen::prelude::Closure; use wasm_bindgen::JsCast; use web_sys::{Event, IdbDatabase, IdbOpenDbRequest};