diff --git a/Cargo.lock b/Cargo.lock index ae1a15a..b351f1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1230,6 +1230,17 @@ dependencies = [ "libc", ] +[[package]] +name = "simplelog" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59d0fe306a0ced1c88a58042dc22fc2ddd000982c26d75f6aa09a394547c41e0" +dependencies = [ + "chrono", + "log", + "termcolor", +] + [[package]] name = "smallvec" version = "1.6.1" @@ -1291,6 +1302,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + [[package]] name = "termscp" version = "0.5.0" @@ -1307,6 +1327,7 @@ dependencies = [ "hostname", "keyring", "lazy_static", + "log", "magic-crypt", "path-slash", "pretty_assertions", @@ -1314,6 +1335,7 @@ dependencies = [ "regex", "rpassword", "serde", + "simplelog", "ssh2", "tempfile", "textwrap", @@ -1664,6 +1686,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" diff --git a/Cargo.toml b/Cargo.toml index e9d44be..efe5e2e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,10 +37,12 @@ edit = "0.1.3" getopts = "0.2.21" hostname = "0.3.1" lazy_static = "1.4.0" +log = "0.4.14" magic-crypt = "3.1.7" rand = "0.8.3" regex = "1.5.4" rpassword = "5.0.1" +simplelog = "0.10.0" ssh2 = "0.9.0" tempfile = "3.1.0" textwrap = "0.13.4" diff --git a/src/lib.rs b/src/lib.rs index de77513..3847ecd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -35,6 +35,8 @@ extern crate bitflags; #[macro_use] extern crate lazy_static; #[macro_use] +extern crate log; +#[macro_use] extern crate magic_crypt; pub mod activity_manager; diff --git a/src/system/environment.rs b/src/system/environment.rs index 619c679..c17cc99 100644 --- a/src/system/environment.rs +++ b/src/system/environment.rs @@ -87,6 +87,15 @@ pub fn get_config_paths(config_dir: &Path) -> (PathBuf, PathBuf) { (bookmarks_file, keys_dir) } +/// ### get_log_paths +/// +/// Returns the path for the supposed log file +pub fn get_log_paths(config_dir: &Path) -> PathBuf { + let mut log_file: PathBuf = PathBuf::from(config_dir); + log_file.push("termscp.log"); + log_file +} + #[cfg(test)] mod tests { @@ -143,4 +152,12 @@ mod tests { ) ); } + + #[test] + fn test_system_environment_get_log_paths() { + assert_eq!( + get_log_paths(&Path::new("/home/omar/.config/termscp/")), + PathBuf::from("/home/omar/.config/termscp/termscp.log"), + ); + } } diff --git a/src/system/logging.rs b/src/system/logging.rs new file mode 100644 index 0000000..35d4603 --- /dev/null +++ b/src/system/logging.rs @@ -0,0 +1,77 @@ +//! ## Logging +//! +//! `logging` is the module which initializes the logging system for termscp + +/** + * MIT License + * + * termscp - Copyright (c) 2021 Christian Visintin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +// locals +use crate::system::environment::{get_log_paths, init_config_dir}; +use crate::utils::file::open_file; +// ext +use simplelog::{Color, ConfigBuilder, Level, LevelFilter, WriteLogger}; +use std::fs::File; +use std::path::PathBuf; + +/// ### init +/// +/// Initialize logger +pub fn init() -> Result<(), String> { + // Init config dir + let config_dir: PathBuf = match init_config_dir() { + Ok(Some(p)) => p, + Ok(None) => { + return Err(String::from( + "This system doesn't seem to support CONFIG_DIR", + )) + } + Err(err) => return Err(err), + }; + let log_file_path: PathBuf = get_log_paths(config_dir.as_path()); + // Open log file + let file: File = open_file(log_file_path.as_path(), true, true, false) + .map_err(|e| format!("Failed to open file {}: {}", log_file_path.display(), e))?; + // Prepare log config + let config = ConfigBuilder::new() + .set_time_format_str("%Y-%m-%dT%H:%M:%S%z") + .set_level_color(Level::Trace, None) + .set_level_color(Level::Debug, Some(Color::Cyan)) + .set_level_color(Level::Info, Some(Color::Yellow)) + .set_level_color(Level::Warn, Some(Color::Magenta)) + .set_level_color(Level::Error, Some(Color::Red)) + .build(); + // Make logger + WriteLogger::init(LevelFilter::Debug, config, file) + .map_err(|e| format!("Failed to initialize logger: {}", e)) +} + +#[cfg(test)] +mod test { + + use super::*; + + #[test] + fn test_system_logging_setup() { + assert!(init().is_ok()); + } +} diff --git a/src/system/mod.rs b/src/system/mod.rs index f48b603..7ff9694 100644 --- a/src/system/mod.rs +++ b/src/system/mod.rs @@ -30,4 +30,5 @@ pub mod bookmarks_client; pub mod config_client; pub mod environment; pub(crate) mod keys; +pub mod logging; pub mod sshkey_storage; diff --git a/src/utils/file.rs b/src/utils/file.rs new file mode 100644 index 0000000..46c3018 --- /dev/null +++ b/src/utils/file.rs @@ -0,0 +1,57 @@ +//! ## File +//! +//! `file` is the module which exposes file related utilities + +/** + * MIT License + * + * termscp - Copyright (c) 2021 Christian Visintin + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +use std::fs::File; +use std::fs::OpenOptions; +use std::io; +use std::path::Path; + +/// ### open_file +/// +/// Open file provided as parameter +pub fn open_file

(filename: P, create: bool, write: bool, append: bool) -> io::Result +where + P: AsRef, +{ + OpenOptions::new() + .create(create) + .write(write) + .append(append) + .truncate(!append) + .open(filename) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_utils_file_open() { + let tmpfile: tempfile::NamedTempFile = tempfile::NamedTempFile::new().unwrap(); + assert!(open_file(tmpfile.path(), true, true, true).is_ok()); + } +} diff --git a/src/utils/fmt.rs b/src/utils/fmt.rs index 202cdf3..8f3a210 100644 --- a/src/utils/fmt.rs +++ b/src/utils/fmt.rs @@ -152,6 +152,13 @@ pub fn fmt_path_elide(p: &Path, width: usize) -> String { } } +/// ### shadow_password +/// +/// Return a string with the same length of input string, but each character is replaced by '*' +pub fn shadow_password(s: &str) -> String { + (0..s.len()).map(|_| '*').collect() +} + #[cfg(test)] mod tests { @@ -219,4 +226,9 @@ mod tests { let p: &Path = &Path::new("/develop/pippo/foo/bar"); assert_eq!(fmt_path_elide(p, 16), String::from("/develop/.../foo/bar")); } + + #[test] + fn test_utils_fmt_shadow_password() { + assert_eq!(shadow_password("foobar"), String::from("******")); + } } diff --git a/src/utils/mod.rs b/src/utils/mod.rs index d3028c6..e11bd67 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -27,6 +27,7 @@ */ // modules pub mod crypto; +pub mod file; pub mod fmt; pub mod git; pub mod parser;