Skip to content

Commit

Permalink
Merge pull request #18 from vrmiguel/nightly
Browse files Browse the repository at this point in the history
Verify inputs when decompressing (canonicalize + checking if they're decompressible)
  • Loading branch information
vrmiguel authored Apr 6, 2021
2 parents e080de8 + 249e995 commit efcbdeb
Show file tree
Hide file tree
Showing 17 changed files with 142 additions and 112 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
# will have compiled files and executables
target/

makeshift_testing.py

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock
Expand Down
4 changes: 2 additions & 2 deletions src/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl Bytes {
impl std::fmt::Display for Bytes {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let num = self.bytes;
debug_assert!(num >= 0.0);
debug_assert!(num >= 0.0);
if num < 1_f64 {
return write!(f, "{} B", num);
}
Expand All @@ -27,4 +27,4 @@ impl std::fmt::Display for Bytes {
write!(f, "{:.2} ", num / delimiter.powi(exponent))?;
write!(f, "{}", UNITS[exponent as usize])
}
}
}
51 changes: 39 additions & 12 deletions src/cli.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
use std::{env, ffi::OsString, io, path::PathBuf, vec::Vec};
use std::{
env,
ffi::OsString,
path::{Path, PathBuf},
vec::Vec,
};

use oof::{arg_flag, flag};

use crate::debug;

pub const VERSION: &str = "0.1.5";

#[derive(PartialEq, Eq, Debug)]
Expand Down Expand Up @@ -41,8 +44,28 @@ pub struct ParsedArgs {
// pub program_called: OsString, // Useful?
}

fn canonicalize_files(files: Vec<PathBuf>) -> io::Result<Vec<PathBuf>> {
files.into_iter().map(|path| path.canonicalize()).collect()
fn canonicalize<'a, P>(path: P) -> crate::Result<PathBuf>
where
P: AsRef<Path> + 'a,
{
match std::fs::canonicalize(&path.as_ref()) {
Ok(abs_path) => Ok(abs_path),
Err(io_err) => {
if !path.as_ref().exists() {
Err(crate::Error::FileNotFound(PathBuf::from(path.as_ref())))
} else {
eprintln!("{} {}", "[ERROR]", io_err);
Err(crate::Error::IoError)
}
}
}
}

fn canonicalize_files<'a, P>(files: Vec<P>) -> crate::Result<Vec<PathBuf>>
where
P: AsRef<Path> + 'a,
{
files.into_iter().map(canonicalize).collect()
}

pub fn parse_args_from(mut args: Vec<OsString>) -> crate::Result<ParsedArgs> {
Expand Down Expand Up @@ -87,18 +110,22 @@ pub fn parse_args_from(mut args: Vec<OsString>) -> crate::Result<ParsedArgs> {
// Defaults to decompression when there is no subcommand
None => {
flags_info.push(arg_flag!('o', "output"));
debug!(&flags_info);

// Parse flags
let (args, mut flags) = oof::filter_flags(args, &flags_info)?;
debug!((&args, &flags));

let files: Vec<_> = args.into_iter().map(PathBuf::from).collect();
// TODO: This line doesn't seem to be working correctly
let files = args.into_iter().map(canonicalize);
for file in files.clone() {
if let Err(err) = file {
return Err(err);
}
}
let files = files.map(Result::unwrap).collect();

let output_folder = flags.take_arg("output").map(PathBuf::from);

// Is the output here fully correct?
// With the paths not canonicalized?
// TODO: ensure all files are decompressible

let command = Command::Decompress {
files,
output_folder,
Expand All @@ -109,4 +136,4 @@ pub fn parse_args_from(mut args: Vec<OsString>) -> crate::Result<ParsedArgs> {
};

Ok(parsed_args)
}
}
2 changes: 1 addition & 1 deletion src/compressors/bzip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ use colored::Colorize;

use super::{Compressor, Entry};
use crate::{
extension::CompressionFormat,
bytes::Bytes,
extension::CompressionFormat,
file::File,
utils::{check_for_multiple_files, ensure_exists},
};
Expand Down
2 changes: 1 addition & 1 deletion src/compressors/gzip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use colored::Colorize;

use super::{Compressor, Entry};
use crate::{
bytes::Bytes,
extension::CompressionFormat,
file::File,
bytes::Bytes,
utils::{check_for_multiple_files, ensure_exists},
};

Expand Down
2 changes: 1 addition & 1 deletion src/compressors/lzma.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ use colored::Colorize;

use super::{Compressor, Entry};
use crate::{
bytes::Bytes,
extension::CompressionFormat,
file::File,
bytes::Bytes,
utils::{check_for_multiple_files, ensure_exists},
};

Expand Down
2 changes: 1 addition & 1 deletion src/compressors/zip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ impl ZipCompressor {
if entry_path.is_dir() {
continue;
}

writer.start_file(entry_path.to_string_lossy(), options)?;
println!("Compressing {:?}", entry_path);
let file_bytes = std::fs::read(entry.path())?;
Expand Down
4 changes: 2 additions & 2 deletions src/decompressors/tar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@ use colored::Colorize;
use tar::{self, Archive};

use super::decompressor::{DecompressionResult, Decompressor};
use crate::{dialogs::Confirmation, file::File, bytes::Bytes, utils};
use crate::{bytes::Bytes, dialogs::Confirmation, file::File, utils};

#[derive(Debug)]
pub struct TarDecompressor {}

impl TarDecompressor {
fn unpack_files(from: File, into: &Path, flags: &oof::Flags) -> crate::Result<Vec<PathBuf>> {
fn unpack_files(from: File, into: &Path, flags: &oof::Flags) -> crate::Result<Vec<PathBuf>> {
println!(
"{}: attempting to decompress {:?}",
"ouch".bright_blue(),
Expand Down
2 changes: 1 addition & 1 deletion src/decompressors/to_memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use std::{
use colored::Colorize;

use super::decompressor::{DecompressionResult, Decompressor};
use crate::utils;
use crate::bytes::Bytes;
use crate::utils;
use crate::{extension::CompressionFormat, file::File};

struct DecompressorToMemory {}
Expand Down
2 changes: 1 addition & 1 deletion src/decompressors/zip.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use colored::Colorize;
use zip::{self, read::ZipFile, ZipArchive};

use super::decompressor::{DecompressionResult, Decompressor};
use crate::{dialogs::Confirmation, file::File, bytes::Bytes, utils};
use crate::{bytes::Bytes, dialogs::Confirmation, file::File, utils};

#[cfg(unix)]
fn __unix_set_permissions(file_path: &Path, file: &ZipFile) {
Expand Down
4 changes: 2 additions & 2 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use colored::Colorize;
#[derive(PartialEq, Eq)]
pub enum Error {
UnknownExtensionError(String),
MissingExtensionError(String),
MissingExtensionError(PathBuf),
// TODO: get rid of this error variant
InvalidUnicode,
InvalidInput,
Expand Down Expand Up @@ -35,7 +35,7 @@ impl fmt::Display for Error {
Error::MissingExtensionError(filename) => {
write!(f, "{} ", "[ERROR]".red())?;
// TODO: show MIME type of the unsupported file
write!(f, "cannot compress to \'{}\', likely because it has an unsupported (or missing) extension.", filename)
write!(f, "cannot compress to {:?}, likely because it has an unsupported (or missing) extension.", filename)
}
Error::WalkdirError => {
// Already printed in the From block
Expand Down
29 changes: 17 additions & 12 deletions src/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,19 @@ use colored::Colorize;

use crate::{
bytes::Bytes,
cli::{VERSION, Command},
cli::{Command, VERSION},
compressors::{
Entry, Compressor, BzipCompressor, GzipCompressor, LzmaCompressor, TarCompressor,
BzipCompressor, Compressor, Entry, GzipCompressor, LzmaCompressor, TarCompressor,
ZipCompressor,
},
decompressors::{
BzipDecompressor, DecompressionResult, Decompressor, GzipDecompressor, LzmaDecompressor,
TarDecompressor, ZipDecompressor,
},
dialogs::Confirmation,
extension::{CompressionFormat, Extension},
file::File,
},
dialogs::Confirmation,
extension::{CompressionFormat, Extension},
file::File,
utils,
debug
};

pub struct Evaluator {}
Expand All @@ -33,7 +32,6 @@ impl Evaluator {
pub fn get_compressor(
file: &File,
) -> crate::Result<(Option<BoxedCompressor>, BoxedCompressor)> {

let extension = match &file.extension {
Some(extension) => extension.clone(),
None => {
Expand Down Expand Up @@ -176,7 +174,6 @@ impl Evaluator {
let confirm = Confirmation::new("Do you want to overwrite 'FILE'?", Some("FILE"));
let (first_compressor, second_compressor) = Self::get_compressor(&output)?;

// TODO: use -y and -n here
if output_path.exists()
&& !utils::permission_for_overwriting(&output_path, flags, &confirm)?
{
Expand Down Expand Up @@ -214,8 +211,16 @@ impl Evaluator {
file_path: &Path,
output: Option<&Path>,
flags: &oof::Flags,
) -> crate::Result<()> {
let file = debug!(File::from(file_path)?);
) -> crate::Result<()> {
// The file to be decompressed
let file = File::from(file_path)?;
// The file must have a supported decompressible format
if file.extension == None {
return Err(crate::Error::MissingExtensionError(PathBuf::from(
file_path,
)));
}

let output = match output {
Some(inner) => Some(File::from(inner)?),
None => None,
Expand Down Expand Up @@ -290,4 +295,4 @@ fn help_message() {
println!(" ouch compress <input...> output-file");
println!("DECOMPRESSION USAGE:");
println!(" ouch <input> [-o/--output output-folder]");
}
}
10 changes: 7 additions & 3 deletions src/extension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,11 @@ impl Extension {
(os_str, snd) if os_str.is_empty() => (None, snd),
(fst, snd) => (Some(fst), snd),
},
None => return Err(crate::Error::MissingExtensionError(to_utf(file_name))),
None => {
return Err(crate::Error::MissingExtensionError(PathBuf::from(
file_name,
)))
}
};

let (first_ext, second_ext) = match (first_ext, second_ext) {
Expand Down Expand Up @@ -119,7 +123,7 @@ impl TryFrom<&PathBuf> for CompressionFormat {
let ext = match ext.extension() {
Some(ext) => ext,
None => {
return Err(crate::Error::MissingExtensionError(String::new()));
return Err(crate::Error::MissingExtensionError(PathBuf::new()));
}
};
extension_from_os_str(ext)
Expand All @@ -133,7 +137,7 @@ impl TryFrom<&str> for CompressionFormat {
let file_name = Path::new(file_name);
let ext = match file_name.extension() {
Some(ext) => ext,
None => return Err(crate::Error::MissingExtensionError(String::new())),
None => return Err(crate::Error::MissingExtensionError(PathBuf::new())),
};

extension_from_os_str(ext)
Expand Down
2 changes: 1 addition & 1 deletion src/file.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl<'a> File<'a> {
Ok(File {
path,
contents_in_memory: None,
extension
extension,
})
}
}
1 change: 0 additions & 1 deletion src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,5 @@ fn main() {

fn run() -> crate::Result<()> {
let ParsedArgs { command, flags } = cli::parse_args()?;
debug!(&command);
Evaluator::evaluate(command, &flags)
}
Loading

0 comments on commit efcbdeb

Please sign in to comment.