Compare commits

..

2 commits

Author SHA1 Message Date
06a9522514
Document cli args 2021-10-27 02:23:37 -07:00
372a160558
Add support for svgs 2021-10-27 02:23:28 -07:00
3 changed files with 64 additions and 56 deletions

View file

@ -22,11 +22,15 @@ struct Opts {
#[derive(Parser)] #[derive(Parser)]
enum Action { enum Action {
Upload { Upload {
/// The OmegaUpload instance to upload data to.
url: Url, url: Url,
/// Encrypt the uploaded paste with the provided password, preventing
/// public access.
#[clap(short, long)] #[clap(short, long)]
password: Option<SecretString>, password: Option<SecretString>,
}, },
Download { Download {
/// The paste to download.
url: ParsedUrl, url: ParsedUrl,
}, },
} }

View file

@ -39,13 +39,12 @@ pub fn decrypt(
nonce: Nonce, nonce: Nonce,
maybe_password: Option<Key>, maybe_password: Option<Key>,
) -> Result<DecryptedData, PasteCompleteConstructionError> { ) -> Result<DecryptedData, PasteCompleteConstructionError> {
let container = &mut container;
log!("Stage 1 decryption started."); log!("Stage 1 decryption started.");
let start = now(); let start = now();
if let Some(password) = maybe_password { if let Some(password) = maybe_password {
crate::render_message("Decrypting Stage 1...".into()); 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()); crate::render_message("Unable to decrypt paste with the provided password.".into());
PasteCompleteConstructionError::StageOneFailure PasteCompleteConstructionError::StageOneFailure
})?; })?;
@ -55,7 +54,7 @@ pub fn decrypt(
log!("Stage 2 decryption started."); log!("Stage 2 decryption started.");
let start = now(); let start = now();
crate::render_message("Decrypting Stage 2...".into()); 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( crate::render_message(
"Unable to decrypt paste with the provided encryption key and nonce.".into(), "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)); log!(format!("Stage 2 completed in {}ms", now() - start));
if let Ok(decrypted) = std::str::from_utf8(container) { let mime_type = tree_magic_mini::from_u8(&container);
Ok(DecryptedData::String(Arc::new(decrypted.to_owned()))) log!("Mimetype: ", mime_type);
} else {
let mime_type = tree_magic_mini::from_u8(container);
log!("Mimetype: ", mime_type);
log!("Blob conversion started."); log!("Blob conversion started.");
let start = now(); let start = now();
let blob_chunks = Array::new_with_length(container.chunks(65536).len().try_into().unwrap()); let blob_chunks = Array::new_with_length(container.chunks(65536).len().try_into().unwrap());
for (i, chunk) in container.chunks(65536).enumerate() { for (i, chunk) in container.chunks(65536).enumerate() {
let array = Uint8Array::new_with_length(chunk.len().try_into().unwrap()); let array = Uint8Array::new_with_length(chunk.len().try_into().unwrap());
array.copy_from(chunk); array.copy_from(chunk);
blob_chunks.set(i.try_into().unwrap(), array.dyn_into().unwrap()); blob_chunks.set(i.try_into().unwrap(), array.dyn_into().unwrap());
} }
let mut blob_props = BlobPropertyBag::new(); let mut blob_props = BlobPropertyBag::new();
blob_props.type_(mime_type); blob_props.type_(mime_type);
let blob = Arc::new( let blob = Arc::new(
Blob::new_with_u8_array_sequence_and_options( Blob::new_with_u8_array_sequence_and_options(blob_chunks.dyn_ref().unwrap(), &blob_props)
blob_chunks.dyn_ref().unwrap(),
&blob_props,
)
.unwrap(), .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" { if mime_type.starts_with("text/") {
Ok(DecryptedData::Image(blob, container.len())) String::from_utf8(container)
} else if mime_type.starts_with("audio/") { .map(Arc::new)
Ok(DecryptedData::Audio(blob)) .map(DecryptedData::String)
} else if mime_type.starts_with("video/") || mime_type == "application/x-matroska" { .map_err(|_| PasteCompleteConstructionError::InvalidEncoding)
Ok(DecryptedData::Video(blob)) } else if mime_type.starts_with("image/") || mime_type == "application/x-riff" {
} else if mime_type == "application/zip" { Ok(DecryptedData::Image(blob, container.len()))
let mut entries = vec![]; } else if mime_type.starts_with("audio/") {
let cursor = Cursor::new(container); Ok(DecryptedData::Audio(blob))
if let Ok(mut zip) = zip::ZipArchive::new(cursor) { } else if mime_type.starts_with("video/") || mime_type == "application/x-matroska" {
for i in 0..zip.len() { Ok(DecryptedData::Video(blob))
match zip.by_index(i) { } else if mime_type == "application/zip" {
Ok(file) => entries.push(ArchiveMeta { let mut entries = vec![];
name: file.name().to_string(), let cursor = Cursor::new(container);
file_size: file.size() as usize, if let Ok(mut zip) = zip::ZipArchive::new(cursor) {
}), for i in 0..zip.len() {
Err(err) => match err { match zip.by_index(i) {
zip::result::ZipError::UnsupportedArchive(s) => { Ok(file) => entries.push(ArchiveMeta {
log!("Unsupported: ", s.to_string()); name: file.name().to_string(),
} file_size: file.size() as usize,
_ => { }),
log!(format!("Error: {}", err)); 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 { pub enum PasteCompleteConstructionError {
StageOneFailure, StageOneFailure,
StageTwoFailure, StageTwoFailure,
InvalidEncoding,
} }
impl std::error::Error for PasteCompleteConstructionError {} impl std::error::Error for PasteCompleteConstructionError {}
@ -142,6 +140,10 @@ impl Display for PasteCompleteConstructionError {
PasteCompleteConstructionError::StageTwoFailure => { PasteCompleteConstructionError::StageTwoFailure => {
write!(f, "Failed to decrypt stage two.") 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?"
),
} }
} }
} }

View file

@ -177,6 +177,8 @@ function createArchivePasteUi({ expiration, data, entries }) {
return a.name.toLowerCase().localeCompare(b.name.toLowerCase()); 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) => { entries.sort((a, b) => {
return b.name.includes("/") - a.name.includes("/"); return b.name.includes("/") - a.name.includes("/");
}); });