|
@@ -1,53 +1,76 @@
|
|
|
use std::io;
|
|
|
use std::fs;
|
|
|
-use clap::{Arg, App, SubCommand};
|
|
|
+use clap::{Arg, App};
|
|
|
+use std::path::PathBuf;
|
|
|
|
|
|
fn main() {
|
|
|
|
|
|
-
|
|
|
- let matches = App::new("My Super Program")
|
|
|
+ let matches = App::new("Partun")
|
|
|
.about("Extracts zip files partially")
|
|
|
.arg(Arg::with_name("filter")
|
|
|
.short("f")
|
|
|
.long("filter")
|
|
|
- .value_name("FILE")
|
|
|
- .help("only extract this file")
|
|
|
- .takes_value(true))
|
|
|
+ .help("Only extract file containing this string")
|
|
|
+ .takes_value(true)
|
|
|
+ )
|
|
|
+ .arg(Arg::with_name("ignorepath")
|
|
|
+ .short("i")
|
|
|
+ .long("ignorepath")
|
|
|
+ .help("Extract all files to current dir, ignoring all paths")
|
|
|
+ )
|
|
|
+ .arg(Arg::with_name("random")
|
|
|
+ .short("r")
|
|
|
+ .long("random")
|
|
|
+ .help("Extract only a random file. This can be combined with the filter flag.")
|
|
|
+ )
|
|
|
.arg(Arg::with_name("ZIP")
|
|
|
.help("Sets the input file to use")
|
|
|
.required(true)
|
|
|
- .index(1))
|
|
|
+ .index(1)
|
|
|
+ )
|
|
|
.get_matches();
|
|
|
|
|
|
+
|
|
|
let archive = matches.value_of("ZIP").unwrap();
|
|
|
let filter = matches.value_of("filter");
|
|
|
+ let ignorepath = matches.is_present("ignorepath");
|
|
|
+ let random = matches.value_of("random");
|
|
|
|
|
|
|
|
|
- let fname = std::path::Path::new(archive);
|
|
|
- let file = fs::File::open(&fname).unwrap();
|
|
|
+ let archive_path = std::path::Path::new(archive);
|
|
|
+ let zipfile = fs::File::open(&archive_path).unwrap();
|
|
|
|
|
|
- let mut archive = zip::ZipArchive::new(file).unwrap();
|
|
|
+ let mut zip_archive = zip::ZipArchive::new(zipfile).unwrap();
|
|
|
|
|
|
- for i in 0..archive.len() {
|
|
|
- let mut file = archive.by_index(i).unwrap();
|
|
|
- let outpath = file.sanitized_name();
|
|
|
+
|
|
|
+
|
|
|
+ for i in 0..zip_archive.len() {
|
|
|
+ let mut file = zip_archive.by_index(i).unwrap();
|
|
|
+ let mut outpath = file.sanitized_name();
|
|
|
|
|
|
+ // Make sure only filtered items pass
|
|
|
if let Some(f) = filter {
|
|
|
if !file.name().contains(f) {
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- {
|
|
|
- let comment = file.comment();
|
|
|
- if !comment.is_empty() {
|
|
|
- println!("File {} comment: {}", i, comment);
|
|
|
+ // If ignorepath is set, turn the filename into the path
|
|
|
+ if ignorepath {
|
|
|
+ if let Some(p) = outpath.file_name() {
|
|
|
+ outpath = PathBuf::from(p);
|
|
|
+ }
|
|
|
+ if outpath.is_dir() {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if (&*file.name()).ends_with('/') {
|
|
|
+ continue;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
if (&*file.name()).ends_with('/') {
|
|
|
println!("File {} extracted to \"{}\"", i, outpath.as_path().display());
|
|
|
- fs::create_dir_all(&outpath).unwrap();
|
|
|
+ fs::create_dir_all(&outpath).unwrap();
|
|
|
} else {
|
|
|
println!("File {} extracted to \"{}\" ({} bytes)", i, outpath.as_path().display(), file.size());
|
|
|
if let Some(p) = outpath.parent() {
|