Use naturalWidth and naturalHeight instead

This commit is contained in:
Edward Shen 2021-10-25 17:31:30 -07:00
parent f5e9b3abd2
commit 6a17a84d3b
Signed by: edward
GPG key ID: 19182661E818369F
10 changed files with 67 additions and 81 deletions

7
Cargo.lock generated
View file

@ -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",

View file

@ -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();

View file

@ -303,7 +303,7 @@ impl TryFrom<web_sys::Headers> 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)
}
}

View file

@ -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<DB>) {
fn set_up_expirations(db: &Arc<DB>) {
let mut corrupted = 0;
let mut expired = 0;
let mut pending = 0;
@ -77,7 +77,7 @@ fn set_up_expirations(db: Arc<DB>) {
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<DB>) {
};
for (key, value) in db.iterator_cf(meta_cf, IteratorMode::Start) {
let expires = if let Ok(value) = bincode::deserialize::<Expiration>(&value) {
let expiration = if let Ok(value) = bincode::deserialize::<Expiration>(&value) {
value
} else {
corrupted += 1;
@ -99,7 +99,7 @@ fn set_up_expirations(db: Arc<DB>) {
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<DB>) {
};
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<DB>) {
} else {
warn!("Found {} corrupted pastes.", corrupted);
}
info!("Found {} expired pastes.", expired);
info!("Found {} active pastes.", pending);
info!("Cleanup timers have been initialized.");

View file

@ -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"

View file

@ -11,7 +11,7 @@ use web_sys::Blob;
pub enum DecryptedData {
String(Arc<String>),
Blob(Arc<Blob>),
Image(Arc<Blob>, (usize, usize), usize),
Image(Arc<Blob>, usize),
Audio(Arc<Blob>),
Video(Arc<Blob>),
}
@ -69,33 +69,19 @@ 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
));
if let Some(dimensions) = dimensions {
Ok(DecryptedData::Image(
blob,
(dimensions.width, dimensions.height),
container.len(),
))
} else {
let mime_type = tree_magic_mini::from_u8(container);
log!(mime_type);
if mime_type.starts_with("audio/") {
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.ends_with("x-matroska") {
} else if mime_type.starts_with("video/") || mime_type == "application/x-matroska" {
Ok(DecryptedData::Video(blob))
} else {
Ok(DecryptedData::Blob(blob))
}
}
}
}
#[derive(Debug)]
pub enum PasteCompleteConstructionError {

View file

@ -17,7 +17,7 @@ impl<State: IdbObjectState> IdbObject<State> {
impl From<IdbObject<Ready>> for Object {
fn from(db_object: IdbObject<Ready>) -> 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<NeedsType> {
}
}
impl Default for IdbObject<NeedsType> {
fn default() -> Self {
Self::new()
}
}
impl IdbObject<NeedsExpiration> {
pub fn expiration_text(self, expires: &str) -> IdbObject<NeedsData> {
self.add_tuple("expiration", &JsString::from(expires))

View file

@ -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 => {
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 => {
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<dyn FnMut(Event)>);
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());

View file

@ -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) {

View file

@ -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};