diff --git a/Cargo.toml b/Cargo.toml index ad55fd3..b8a5deb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2021" [dependencies] clap = { version = "4.5.4", features = ["derive"] } ignore = "0.4.22" +lazy_static = "1.4.0" prost = "0.12.4" tokio = { version = "1", features = ["full"] } tonic = "0.11.0" diff --git a/src/configuration.rs b/src/configuration.rs new file mode 100644 index 0000000..73bcf2b --- /dev/null +++ b/src/configuration.rs @@ -0,0 +1,46 @@ +use clap::Parser; +use lazy_static::lazy_static; +use std::env; +use std::path::PathBuf; + +lazy_static! { + pub static ref CONFIG: Config = Config::new(); +} + +#[derive(Parser)] +#[command(version, about, long_about = None)] +struct Args { + #[arg(help = "Directory to scan for files")] + path: Option, +} + +#[derive(Debug)] +pub struct Config { + pub base_path: PathBuf, +} + +impl Default for Config { + fn default() -> Self { + Config { + base_path: env::current_dir().expect("Current directory is not available."), + } + } +} + +impl Config { + pub fn new() -> Self { + let mut config = Self::default(); + + let cli = Self::get_cli_args(); + + if let Some(path) = cli.path { + config.base_path = path; + } + + config + } + + fn get_cli_args() -> Args { + Args::parse() + } +} diff --git a/src/file_explorer.rs b/src/file_explorer.rs index f394d7c..e932592 100644 --- a/src/file_explorer.rs +++ b/src/file_explorer.rs @@ -1,8 +1,10 @@ use ignore::types::TypesBuilder; use ignore::WalkBuilder; -use std::{io, path::PathBuf}; +use std::path::PathBuf; -pub fn walk_dir(path: &PathBuf) -> io::Result> { +use crate::configuration::CONFIG; + +pub fn walk_dir(path: &PathBuf) -> Result, &str> { let mut types_builder = TypesBuilder::new(); types_builder.add_defaults(); @@ -14,7 +16,19 @@ pub fn walk_dir(path: &PathBuf) -> io::Result> { types_builder.select("sound"); - let entries: Vec = WalkBuilder::new(path) + let search_path = CONFIG.base_path.join(path); + eprintln!( + "DEBUGPRINT[1]: file_explorer.rs:19: search_path={:#?}", + search_path + ); + + // PathBuf.join() can override the hole path, this ensure we're not accessing files outside + // base_dir + if !search_path.starts_with(&CONFIG.base_path) { + return Err("Tried to access file or directory outside of server `base_dir` config."); + } + + let entries: Vec = WalkBuilder::new(search_path) .types(types_builder.build().unwrap()) .build() .filter_map(|entry| entry.ok()) diff --git a/src/grpc/client.rs b/src/grpc/client.rs index 68f3d65..b5026b1 100644 --- a/src/grpc/client.rs +++ b/src/grpc/client.rs @@ -22,7 +22,7 @@ impl super::Connection for GRPCClient { let mut client = JunoRequestClient::connect(format!("http://{}", self.address)).await?; let request = Request::new(GetFilesRequest { - path: "/home/aleidk/Music/".to_string(), + path: "/home/aleidk/Documents/".to_string(), }); let response = client.get_files(request).await?.into_inner(); diff --git a/src/grpc/server.rs b/src/grpc/server.rs index b7cb6d4..9b1363b 100644 --- a/src/grpc/server.rs +++ b/src/grpc/server.rs @@ -43,9 +43,8 @@ impl JunoRequest for GRPCServer { let files = match file_explorer::walk_dir(&path) { Ok(files) => files, - Err(_err) => panic!("Error reading path: {:?}", path), + Err(err) => return Err(Status::invalid_argument(err)), }; - eprintln!("DEBUGPRINT[2]: server.rs:44: files={:#?}", files); let reply = GetFilesResponse { files: files.iter().map(|x| x.display().to_string()).collect(), diff --git a/src/main.rs b/src/main.rs index 0717a75..dee7a89 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,26 +1,11 @@ -use core::panic; -use std::{env, path::PathBuf}; - -use clap::Parser; use std::error::Error; +mod configuration; mod file_explorer; mod grpc; -#[derive(Parser)] -#[command(version, about, long_about = None)] -struct Args { - #[arg(help = "Directory to scan for files")] - path: Option, -} - #[tokio::main()] async fn main() -> Result<(), Box> { - let cli = Args::parse(); - let path = cli - .path - .unwrap_or(env::current_dir().expect("Current directory is not available.")); - let server = grpc::run()?; server.connect().await?;