feat: add password support for decompress and list

This commit is contained in:
ttyS3 2024-03-24 03:47:20 +00:00 committed by João Marcos
parent 4ac8e2ba91
commit 512d2445b2
7 changed files with 33 additions and 15 deletions

8
Cargo.lock generated
View File

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

View File

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

View File

@ -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<usize> {
pub fn unpack_archive(archive_path: &Path, output_folder: &Path, password: Option<impl AsRef<[u8]>>, quiet: bool) -> crate::Result<usize> {
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<Item = crate::Result<FileInArchive>> {
Archive::new(archive_path)
.open_for_listing()
pub fn list_archive(archive_path: &Path, password: Option<impl AsRef<[u8]>>) -> impl Iterator<Item = crate::Result<FileInArchive>> {
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?;

View File

@ -41,6 +41,10 @@ pub struct CliArgs {
#[arg(short, long, global = true)]
pub format: Option<OsString>,
/// decompress or list with password
#[arg(short = 'p', long = "password", global = true)]
pub password: Option<String>,
// Ouch and claps subcommands
#[command(subcommand)]
pub cmd: Subcommand,

View File

@ -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<dyn FnOnce(&Path) -> 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) =

View File

@ -20,6 +20,7 @@ pub fn list_archive_contents(
formats: Vec<CompressionFormat>,
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"))]

View File

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