diff --git a/src/archive.rs b/src/archive.rs index 4df3a312f..e53aea880 100644 --- a/src/archive.rs +++ b/src/archive.rs @@ -53,9 +53,9 @@ impl CompressionMethod { } } - pub fn is_enabled(self, tar_enabled: bool, zip_enabled: bool) -> bool { + pub fn is_enabled(self, tar_enabled: bool, tar_gz_enabled: bool, zip_enabled: bool) -> bool { match self { - CompressionMethod::TarGz => tar_enabled, + CompressionMethod::TarGz => tar_gz_enabled, CompressionMethod::Tar => tar_enabled, CompressionMethod::Zip => zip_enabled, } diff --git a/src/args.rs b/src/args.rs index 81e49dcbe..819618f2f 100644 --- a/src/args.rs +++ b/src/args.rs @@ -99,10 +99,14 @@ pub struct CliArgs { #[structopt(short = "o", long = "overwrite-files")] pub overwrite_files: bool, - /// Enable tar archive generation + /// Enable uncompressed tar archive generation #[structopt(short = "r", long = "enable-tar")] pub enable_tar: bool, + /// Enable gz-compressed tar archive generation + #[structopt(short = "g", long = "enable-tar-gz")] + pub enable_tar_gz: bool, + /// Enable zip archive generation /// /// WARNING: Zipping large directories can result in out-of-memory exception diff --git a/src/listing.rs b/src/listing.rs index 66aea6b69..cff4f9a44 100644 --- a/src/listing.rs +++ b/src/listing.rs @@ -158,6 +158,7 @@ pub fn directory_listing( show_qrcode: bool, upload_route: String, tar_enabled: bool, + tar_gz_enabled: bool, zip_enabled: bool, dirs_first: bool, hide_version_footer: bool, @@ -330,7 +331,7 @@ pub fn directory_listing( } if let Some(compression_method) = query_params.download { - if !compression_method.is_enabled(tar_enabled, zip_enabled) { + if !compression_method.is_enabled(tar_enabled, tar_gz_enabled, zip_enabled) { return Ok(ServiceResponse::new( req.clone(), HttpResponse::Forbidden() @@ -413,6 +414,7 @@ pub fn directory_listing( &encoded_dir, breadcrumbs, tar_enabled, + tar_gz_enabled, zip_enabled, hide_version_footer, ) diff --git a/src/main.rs b/src/main.rs index 84a4cb8ee..f174d5753 100644 --- a/src/main.rs +++ b/src/main.rs @@ -90,9 +90,12 @@ pub struct MiniserveConfig { /// Enable upload to override existing files pub overwrite_files: bool, - /// If false, creation of tar archives is disabled + /// If false, creation of uncompressed tar archives is disabled pub tar_enabled: bool, + /// If false, creation of gz-compressed tar archives is disabled + pub tar_gz_enabled: bool, + /// If false, creation of zip archives is disabled pub zip_enabled: bool, @@ -161,6 +164,7 @@ impl MiniserveConfig { show_qrcode: args.qrcode, file_upload: args.file_upload, tar_enabled: args.enable_tar, + tar_gz_enabled: args.enable_tar_gz, zip_enabled: args.enable_zip, dirs_first: args.dirs_first, title: args.title, @@ -411,6 +415,7 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) { let show_qrcode = conf.show_qrcode; let file_upload = conf.file_upload; let tar_enabled = conf.tar_enabled; + let tar_gz_enabled = conf.tar_gz_enabled; let zip_enabled = conf.zip_enabled; let dirs_first = conf.dirs_first; let hide_version_footer = conf.hide_version_footer; @@ -453,6 +458,7 @@ fn configure_app(app: &mut web::ServiceConfig, conf: &MiniserveConfig) { show_qrcode, u_r.clone(), tar_enabled, + tar_gz_enabled, zip_enabled, dirs_first, hide_version_footer, diff --git a/src/renderer.rs b/src/renderer.rs index c9ec9cdbd..5cb545239 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -26,6 +26,7 @@ pub fn page( encoded_dir: &str, breadcrumbs: Vec, tar_enabled: bool, + tar_gz_enabled: bool, zip_enabled: bool, hide_version_footer: bool, ) -> Markup { @@ -94,10 +95,10 @@ pub fn page( } } div.toolbar { - @if tar_enabled || zip_enabled { + @if tar_enabled || tar_gz_enabled || zip_enabled { div.download { @for compression_method in CompressionMethod::iter() { - @if compression_method.is_enabled(tar_enabled, zip_enabled) { + @if compression_method.is_enabled(tar_enabled, tar_gz_enabled, zip_enabled) { (archive_button(compression_method, sort_method, sort_order)) } } diff --git a/tests/archive.rs b/tests/archive.rs index c170bc3a0..6a7f8bf23 100644 --- a/tests/archive.rs +++ b/tests/archive.rs @@ -51,3 +51,44 @@ fn archives_are_disabled(tmpdir: TempDir, port: u16) -> Result<(), Error> { Ok(()) } + +#[rstest] +fn test_tar_archives(tmpdir: TempDir, port: u16) -> Result<(), Error> { + let mut child = Command::cargo_bin("miniserve")? + .arg(tmpdir.path()) + .arg("-p") + .arg(port.to_string()) + .arg("-g") + .stdout(Stdio::null()) + .spawn()?; + + sleep(Duration::from_secs(1)); + + // Ensure the links to the tar archive exists and tar not exists + let body = reqwest::blocking::get(format!("http://localhost:{}", port).as_str())? + .error_for_status()?; + let parsed = Document::from_read(body)?; + assert!(parsed.find(Text).any(|x| x.text() == "Download .tar.gz")); + assert!(parsed.find(Text).all(|x| x.text() != "Download .tar")); + + // Try to download, only tar_gz should works + assert_eq!( + reqwest::blocking::get(format!("http://localhost:{}/?download=tar_gz", port).as_str())? + .status(), + StatusCode::OK + ); + assert_eq!( + reqwest::blocking::get(format!("http://localhost:{}/?download=tar", port).as_str())? + .status(), + StatusCode::FORBIDDEN + ); + assert_eq!( + reqwest::blocking::get(format!("http://localhost:{}/?download=zip", port).as_str())? + .status(), + StatusCode::FORBIDDEN + ); + + child.kill()?; + + Ok(()) +}