From 512d2445b27773059c2a4491c3edeca74a25a243 Mon Sep 17 00:00:00 2001 From: ttyS3 Date: Sun, 24 Mar 2024 03:47:20 +0000 Subject: [PATCH] feat: add password support for decompress and list --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/archive/rar.rs | 21 ++++++++++++++++----- src/cli/args.rs | 4 ++++ src/commands/decompress.rs | 5 +++-- src/commands/list.rs | 5 +++-- src/commands/mod.rs | 3 ++- 7 files changed, 33 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ca0d406..07a8c2d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1397,9 +1397,9 @@ checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unrar" -version = "0.5.3" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f4994bfae776d5c2ee22493a00742c77d58bfa5adbe10febe83d1ba7aff2ebdc" +checksum = "c99d6a7735a222f2119ca4572e713fb468b5c3a17a4fb90b3cac3e28a8680c29" dependencies = [ "bitflags 1.3.2", "regex", @@ -1409,9 +1409,9 @@ dependencies = [ [[package]] name = "unrar_sys" -version = "0.3.1" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f691c507016acf0a56fae074981ce30f13f8b035c8f80aa878f41905d96e390" +checksum = "3f8325103479fffa0e31b41fd11267446b355037115ae184a63a9fd3f192f3da" dependencies = [ "cc", "libc", diff --git a/Cargo.toml b/Cargo.toml index 228dc42..3933521 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ snap = "1.1.1" tar = "0.4.41" tempfile = "3.10.1" time = { version = "0.3.36", default-features = false } -unrar = { version = "0.5.3", optional = true } +unrar = { version = "0.5.6", optional = true } xz2 = "0.1.7" zip = { version = "0.6.6", default-features = false, features = ["time"] } zstd = { version = "0.13.2", default-features = false, features = ["zstdmt"]} diff --git a/src/archive/rar.rs b/src/archive/rar.rs index 9219561..a3ab648 100644 --- a/src/archive/rar.rs +++ b/src/archive/rar.rs @@ -8,10 +8,17 @@ use crate::{error::Error, list::FileInArchive, utils::logger::info}; /// Unpacks the archive given by `archive_path` into the folder given by `output_folder`. /// Assumes that output_folder is empty -pub fn unpack_archive(archive_path: &Path, output_folder: &Path, quiet: bool) -> crate::Result { +pub fn unpack_archive(archive_path: &Path, output_folder: &Path, password: Option>, quiet: bool) -> crate::Result { assert!(output_folder.read_dir().expect("dir exists").count() == 0); - let mut archive = Archive::new(archive_path).open_for_processing()?; + let password = password.as_ref().map(|p| p.as_ref()); + + let archive = match password { + Some(password) => Archive::with_password(archive_path, password), + None => Archive::new(archive_path), + }; + + let mut archive = archive.open_for_processing()?; let mut unpacked = 0; while let Some(header) = archive.read_header()? { @@ -35,9 +42,13 @@ pub fn unpack_archive(archive_path: &Path, output_folder: &Path, quiet: bool) -> } /// List contents of `archive_path`, returning a vector of archive entries -pub fn list_archive(archive_path: &Path) -> impl Iterator> { - Archive::new(archive_path) - .open_for_listing() +pub fn list_archive(archive_path: &Path, password: Option>) -> impl Iterator> { + let password = password.as_ref().map(|p| p.as_ref()); + let archive = match password { + Some(password) => Archive::with_password(archive_path, password), + None => Archive::new(archive_path), + }; + archive.open_for_listing() .expect("cannot open archive") .map(|item| { let item = item?; diff --git a/src/cli/args.rs b/src/cli/args.rs index 9826c78..d0cdc73 100644 --- a/src/cli/args.rs +++ b/src/cli/args.rs @@ -41,6 +41,10 @@ pub struct CliArgs { #[arg(short, long, global = true)] pub format: Option, + /// decompress or list with password + #[arg(short = 'p', long = "password", global = true)] + pub password: Option, + // Ouch and claps subcommands #[command(subcommand)] pub cmd: Subcommand, diff --git a/src/commands/decompress.rs b/src/commands/decompress.rs index dcb8f85..4f1d989 100644 --- a/src/commands/decompress.rs +++ b/src/commands/decompress.rs @@ -36,6 +36,7 @@ pub fn decompress_file( output_file_path: PathBuf, question_policy: QuestionPolicy, quiet: bool, + password: Option<&str>, ) -> crate::Result<()> { assert!(output_dir.exists()); let input_is_stdin = is_path_stdin(input_file_path); @@ -172,9 +173,9 @@ pub fn decompress_file( let unpack_fn: Box UnpackResult> = if formats.len() > 1 || input_is_stdin { let mut temp_file = tempfile::NamedTempFile::new()?; io::copy(&mut reader, &mut temp_file)?; - Box::new(move |output_dir| crate::archive::rar::unpack_archive(temp_file.path(), output_dir, quiet)) + Box::new(move |output_dir| crate::archive::rar::unpack_archive(temp_file.path(), output_dir, password, quiet)) } else { - Box::new(|output_dir| crate::archive::rar::unpack_archive(input_file_path, output_dir, quiet)) + Box::new(|output_dir| crate::archive::rar::unpack_archive(input_file_path, output_dir, password, quiet)) }; if let ControlFlow::Continue(files) = diff --git a/src/commands/list.rs b/src/commands/list.rs index d33ced5..bb30968 100644 --- a/src/commands/list.rs +++ b/src/commands/list.rs @@ -20,6 +20,7 @@ pub fn list_archive_contents( formats: Vec, list_options: ListOptions, question_policy: QuestionPolicy, + password: Option<&str>, ) -> crate::Result<()> { let reader = fs::File::open(archive_path)?; @@ -86,9 +87,9 @@ pub fn list_archive_contents( if formats.len() > 1 { let mut temp_file = tempfile::NamedTempFile::new()?; io::copy(&mut reader, &mut temp_file)?; - Box::new(crate::archive::rar::list_archive(temp_file.path())) + Box::new(crate::archive::rar::list_archive(temp_file.path(), password)) } else { - Box::new(crate::archive::rar::list_archive(archive_path)) + Box::new(crate::archive::rar::list_archive(archive_path, password)) } } #[cfg(not(feature = "unrar"))] diff --git a/src/commands/mod.rs b/src/commands/mod.rs index 6e5e9db..c051cb0 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -188,6 +188,7 @@ pub fn run( output_file_path, question_policy, args.quiet, + args.password.as_deref(), ) }) } @@ -221,7 +222,7 @@ pub fn run( println!(); } let formats = extension::flatten_compression_formats(&formats); - list_archive_contents(archive_path, formats, list_options, question_policy)?; + list_archive_contents(archive_path, formats, list_options, question_policy, args.password.as_deref())?; } Ok(())