From 372a160558c22d7ebcd1ca9b3e52fc30b480643b Mon Sep 17 00:00:00 2001 From: Edward Shen Date: Wed, 27 Oct 2021 02:23:28 -0700 Subject: [PATCH] Add support for svgs --- web/src/decrypt.rs | 114 +++++++++++++++++++++++---------------------- web/src/main.ts | 2 + 2 files changed, 60 insertions(+), 56 deletions(-) diff --git a/web/src/decrypt.rs b/web/src/decrypt.rs index 8df3590..ac9059b 100644 --- a/web/src/decrypt.rs +++ b/web/src/decrypt.rs @@ -39,13 +39,12 @@ pub fn decrypt( nonce: Nonce, maybe_password: Option, ) -> Result { - let container = &mut container; log!("Stage 1 decryption started."); let start = now(); if let Some(password) = maybe_password { crate::render_message("Decrypting Stage 1...".into()); - open_in_place(container, &nonce.increment(), &password).map_err(|_| { + open_in_place(&mut container, &nonce.increment(), &password).map_err(|_| { crate::render_message("Unable to decrypt paste with the provided password.".into()); PasteCompleteConstructionError::StageOneFailure })?; @@ -55,7 +54,7 @@ pub fn decrypt( log!("Stage 2 decryption started."); let start = now(); crate::render_message("Decrypting Stage 2...".into()); - open_in_place(container, &nonce, &key).map_err(|_| { + open_in_place(&mut container, &nonce, &key).map_err(|_| { crate::render_message( "Unable to decrypt paste with the provided encryption key and nonce.".into(), ); @@ -63,65 +62,63 @@ pub fn decrypt( })?; log!(format!("Stage 2 completed in {}ms", now() - start)); - if let Ok(decrypted) = std::str::from_utf8(container) { - Ok(DecryptedData::String(Arc::new(decrypted.to_owned()))) - } else { - let mime_type = tree_magic_mini::from_u8(container); - log!("Mimetype: ", mime_type); + let mime_type = tree_magic_mini::from_u8(&container); + log!("Mimetype: ", mime_type); - log!("Blob conversion started."); - let start = now(); - let blob_chunks = Array::new_with_length(container.chunks(65536).len().try_into().unwrap()); - for (i, chunk) in container.chunks(65536).enumerate() { - let array = Uint8Array::new_with_length(chunk.len().try_into().unwrap()); - array.copy_from(chunk); - blob_chunks.set(i.try_into().unwrap(), array.dyn_into().unwrap()); - } - let mut blob_props = BlobPropertyBag::new(); - blob_props.type_(mime_type); - let blob = Arc::new( - Blob::new_with_u8_array_sequence_and_options( - blob_chunks.dyn_ref().unwrap(), - &blob_props, - ) + log!("Blob conversion started."); + let start = now(); + let blob_chunks = Array::new_with_length(container.chunks(65536).len().try_into().unwrap()); + for (i, chunk) in container.chunks(65536).enumerate() { + let array = Uint8Array::new_with_length(chunk.len().try_into().unwrap()); + array.copy_from(chunk); + blob_chunks.set(i.try_into().unwrap(), array.dyn_into().unwrap()); + } + let mut blob_props = BlobPropertyBag::new(); + blob_props.type_(mime_type); + let blob = Arc::new( + Blob::new_with_u8_array_sequence_and_options(blob_chunks.dyn_ref().unwrap(), &blob_props) .unwrap(), - ); - log!(format!("Blob conversion completed in {}ms", now() - start)); + ); + log!(format!("Blob conversion completed in {}ms", now() - start)); - 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 if mime_type == "application/zip" { - let mut entries = vec![]; - let cursor = Cursor::new(container); - if let Ok(mut zip) = zip::ZipArchive::new(cursor) { - for i in 0..zip.len() { - match zip.by_index(i) { - Ok(file) => entries.push(ArchiveMeta { - name: file.name().to_string(), - file_size: file.size() as usize, - }), - Err(err) => match err { - zip::result::ZipError::UnsupportedArchive(s) => { - log!("Unsupported: ", s.to_string()); - } - _ => { - log!(format!("Error: {}", err)); - } - }, - } + if mime_type.starts_with("text/") { + String::from_utf8(container) + .map(Arc::new) + .map(DecryptedData::String) + .map_err(|_| PasteCompleteConstructionError::InvalidEncoding) + } else 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 if mime_type == "application/zip" { + let mut entries = vec![]; + let cursor = Cursor::new(container); + if let Ok(mut zip) = zip::ZipArchive::new(cursor) { + for i in 0..zip.len() { + match zip.by_index(i) { + Ok(file) => entries.push(ArchiveMeta { + name: file.name().to_string(), + file_size: file.size() as usize, + }), + Err(err) => match err { + zip::result::ZipError::UnsupportedArchive(s) => { + log!("Unsupported: ", s.to_string()); + } + _ => { + log!(format!("Error: {}", err)); + } + }, } } - Ok(DecryptedData::Archive(blob, entries)) - } else if mime_type == "application/gzip" { - let entries = vec![]; - Ok(DecryptedData::Archive(blob, entries)) - } else { - Ok(DecryptedData::Blob(blob)) } + Ok(DecryptedData::Archive(blob, entries)) + } else if mime_type == "application/gzip" { + let entries = vec![]; + Ok(DecryptedData::Archive(blob, entries)) + } else { + Ok(DecryptedData::Blob(blob)) } } @@ -129,6 +126,7 @@ pub fn decrypt( pub enum PasteCompleteConstructionError { StageOneFailure, StageTwoFailure, + InvalidEncoding, } impl std::error::Error for PasteCompleteConstructionError {} @@ -142,6 +140,10 @@ impl Display for PasteCompleteConstructionError { PasteCompleteConstructionError::StageTwoFailure => { write!(f, "Failed to decrypt stage two.") } + PasteCompleteConstructionError::InvalidEncoding => write!( + f, + "Got an file with a text/* mime type, but was unable to parsed as valid UTF-8?" + ), } } } diff --git a/web/src/main.ts b/web/src/main.ts index 127ade0..f7afa3c 100644 --- a/web/src/main.ts +++ b/web/src/main.ts @@ -177,6 +177,8 @@ function createArchivePasteUi({ expiration, data, entries }) { return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); }); + // This doesn't get sub directories and their folders, but hey it's close + // enough entries.sort((a, b) => { return b.name.includes("/") - a.name.includes("/"); });