feat: switch lang from args
This commit is contained in:
@@ -1,49 +1,30 @@
|
||||
use clap::{App, AppSettings, Arg, ArgMatches};
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::sync::Once;
|
||||
use clap::ArgMatches;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct SingletonReader {
|
||||
pub regex: Vec<Vec<String>>,
|
||||
pub whitelist: Vec<Vec<String>>,
|
||||
pub args: Config<'static>,
|
||||
pub args: ArgMatches<'static>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Config<'a> {
|
||||
pub filepath: Option<&'a str>,
|
||||
pub attackhunt: Option<&'a str>,
|
||||
pub csv_timeline: Option<&'a str>,
|
||||
pub human_readable_timeline: Option<&'a str>,
|
||||
pub lang: Option<&'a str>,
|
||||
pub timezone: Option<&'a str>,
|
||||
pub enum Lang {
|
||||
Ja,
|
||||
En,
|
||||
}
|
||||
|
||||
impl<'a> Config<'a> {
|
||||
fn new(args: ArgMatches<'a>) -> Self {
|
||||
Config {
|
||||
filepath: args.value_of("filepath"),
|
||||
attackhunt: args.value_of("attackhunt"),
|
||||
csv_timeline: args.value_of("csv-timeline"),
|
||||
human_readable_timeline: args.value_of("human-readable-timeline"),
|
||||
lang: args.value_of("lang"),
|
||||
timezone: args.value_of("timezone"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init_singleton(args: ArgMatches<'static>) -> Box<SingletonReader> {
|
||||
pub fn singleton() -> Box<SingletonReader> {
|
||||
static mut SINGLETON: Option<Box<SingletonReader>> = Option::None;
|
||||
static ONCE: Once = Once::new();
|
||||
static CONFIG: Config = Config::new(args);
|
||||
|
||||
unsafe {
|
||||
ONCE.call_once(|| {
|
||||
let singleton = SingletonReader {
|
||||
regex: read_csv("regexes.txt"),
|
||||
whitelist: read_csv("whitelist.txt"),
|
||||
args: CONFIG,
|
||||
args: build_app().get_matches(),
|
||||
};
|
||||
|
||||
SINGLETON = Some(Box::new(singleton));
|
||||
@@ -53,11 +34,31 @@ pub fn init_singleton(args: ArgMatches<'static>) -> Box<SingletonReader> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn singleton() -> Box<SingletonReader> {
|
||||
static mut SINGLETON: Option<Box<SingletonReader>> = Option::None;
|
||||
unsafe {
|
||||
return SINGLETON.clone().unwrap();
|
||||
}
|
||||
fn build_app() -> clap::App<'static, 'static> {
|
||||
let program = std::env::args()
|
||||
.nth(0)
|
||||
.and_then(|s| {
|
||||
std::path::PathBuf::from(s)
|
||||
.file_stem()
|
||||
.map(|s| s.to_string_lossy().into_owned())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
App::new(program)
|
||||
.about("Yea! (Yamato Event Analyzer). Aiming to be the world's greatest Windows event log analysis tool!")
|
||||
.version("0.0.1")
|
||||
.author("Author name <author@example.com>")
|
||||
.setting(AppSettings::VersionlessSubcommands)
|
||||
.arg(Arg::from_usage("-f --filepath=[FILEPATH] 'event file path'"))
|
||||
.arg(Arg::from_usage("--attackhunt=[ATTACK_HUNT] 'Attack Hunt'"))
|
||||
.arg(Arg::from_usage("--csv-timeline=[CSV_TIMELINE] 'csv output timeline'"))
|
||||
.arg(Arg::from_usage("--human-readable-timeline=[HUMAN_READABLE_TIMELINE] 'human readable timeline'"))
|
||||
.arg(Arg::from_usage("-l --lang=[LANG] 'output language'"))
|
||||
.arg(Arg::from_usage("-t --timezone=[TIMEZONE] 'timezone setting'"))
|
||||
.arg(Arg::from_usage("-d --directory 'event log files directory'"))
|
||||
.arg(Arg::from_usage("-s --statistics 'event statistics'"))
|
||||
.arg(Arg::from_usage("-u --update 'signature update'"))
|
||||
.arg(Arg::from_usage("--credits 'Zachary Mathis, Akira Nishikawa'"))
|
||||
}
|
||||
|
||||
fn read_csv(filename: &str) -> Vec<Vec<String>> {
|
||||
@@ -82,3 +83,14 @@ fn read_csv(filename: &str) -> Vec<Vec<String>> {
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/// Argsから言語情報を読み取り Lang を返す
|
||||
pub fn get_lang() -> Lang {
|
||||
let lang: String = singleton().args.value_of("lang").unwrap_or("").to_string();
|
||||
|
||||
match &*lang {
|
||||
"Ja" | "ja" => Lang::Ja,
|
||||
"En" | "en" => Lang::En,
|
||||
_ => Lang::En,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ mod common;
|
||||
pub mod configs;
|
||||
pub mod detection;
|
||||
mod powershell;
|
||||
mod print;
|
||||
pub mod print;
|
||||
mod security;
|
||||
mod sysmon;
|
||||
mod system;
|
||||
|
||||
@@ -1,15 +1,11 @@
|
||||
use crate::detections::configs::{get_lang, Lang};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum Lang {
|
||||
Ja,
|
||||
En,
|
||||
}
|
||||
use std::fmt;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct MessageText {
|
||||
ja: String,
|
||||
en: String,
|
||||
pub ja: String,
|
||||
pub en: String,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -35,18 +31,25 @@ impl Message {
|
||||
self.map.insert(error_code, message);
|
||||
}
|
||||
|
||||
/// メッセージを指定された言語で返す
|
||||
pub fn return_error_message(&self, error_num: &str, lang: Lang) -> String {
|
||||
let messages = self.map.get(error_num).unwrap_or(self.map.get("undefined").unwrap());
|
||||
match lang {
|
||||
Lang::Ja => messages.ja.clone(),
|
||||
Lang::En => messages.en.clone(),
|
||||
/// メッセージを返す
|
||||
pub fn return_message(&self, message_num: &str) -> &MessageText {
|
||||
self.map.get(message_num).unwrap_or(self.map.get("undefined").unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
/// メッセージテキストを言語設定に合わせて返す
|
||||
/// println!("{}", <MessageText>) とすると今の言語設定で出力される
|
||||
impl fmt::Display for MessageText {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match get_lang() {
|
||||
Lang::Ja => write!(f, "{}", self.ja),
|
||||
Lang::En => write!(f, "{}", self.en),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_create_error_message() {
|
||||
fn test_create_and_read_message() {
|
||||
let mut error_message = Message::new();
|
||||
|
||||
error_message.insert_message(
|
||||
@@ -57,18 +60,7 @@ fn test_create_error_message() {
|
||||
},
|
||||
);
|
||||
|
||||
let message_ja1 = error_message.return_error_message("4103", Lang::Ja);
|
||||
assert_eq!(message_ja1, "パイプライン実行をしています");
|
||||
let message_ja2 = error_message.return_error_message("4103", Lang::Ja);
|
||||
assert_eq!(message_ja2, "パイプライン実行をしています");
|
||||
let display = format!("{}", format_args!("{}", error_message.return_message("4103")));
|
||||
|
||||
let message_en1 = error_message.return_error_message("4103", Lang::En);
|
||||
assert_eq!(message_en1, "Execute pipeline");
|
||||
let message_en2 = error_message.return_error_message("4103", Lang::En);
|
||||
assert_eq!(message_en2, "Execute pipeline");
|
||||
|
||||
let undef_ja = error_message.return_error_message("HOGE", Lang::Ja);
|
||||
assert_eq!(undef_ja, "未設定");
|
||||
let undef_en = error_message.return_error_message("HOGE", Lang::En);
|
||||
assert_eq!(undef_en, "Undefined");
|
||||
assert_eq!(display, "Execute pipeline")
|
||||
}
|
||||
|
||||
45
src/main.rs
45
src/main.rs
@@ -1,51 +1,24 @@
|
||||
extern crate clap;
|
||||
extern crate serde;
|
||||
|
||||
use clap::{App, AppSettings, Arg};
|
||||
use evtx::EvtxParser;
|
||||
use quick_xml::de::DeError;
|
||||
use std::{fs, path::PathBuf, process};
|
||||
use yamato_event_analyzer::detections::configs;
|
||||
use yamato_event_analyzer::detections::detection;
|
||||
use yamato_event_analyzer::detections::print;
|
||||
use yamato_event_analyzer::omikuji::Omikuji;
|
||||
use yamato_event_analyzer::toml;
|
||||
|
||||
fn build_app() -> clap::App<'static, 'static> {
|
||||
let program = std::env::args()
|
||||
.nth(0)
|
||||
.and_then(|s| {
|
||||
std::path::PathBuf::from(s)
|
||||
.file_stem()
|
||||
.map(|s| s.to_string_lossy().into_owned())
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
App::new(program)
|
||||
.about("Yea! (Yamato Event Analyzer). Aiming to be the world's greatest Windows event log analysis tool!")
|
||||
.version("0.0.1")
|
||||
.author("Author name <author@example.com>")
|
||||
.setting(AppSettings::VersionlessSubcommands)
|
||||
.arg(Arg::from_usage("-f --filepath=[FILEPATH] 'event file path'"))
|
||||
.arg(Arg::from_usage("--attackhunt=[ATTACK_HUNT] 'Attack Hunt'"))
|
||||
.arg(Arg::from_usage("--csv-timeline=[CSV_TIMELINE] 'csv output timeline'"))
|
||||
.arg(Arg::from_usage("--human-readable-timeline=[HUMAN_READABLE_TIMELINE] 'human readable timeline'"))
|
||||
.arg(Arg::from_usage("-l --lang=[LANG] 'output language'"))
|
||||
.arg(Arg::from_usage("-t --timezone=[TIMEZONE] 'timezone setting'"))
|
||||
.arg(Arg::from_usage("-d --directory 'event log files directory'"))
|
||||
.arg(Arg::from_usage("-s --statistics 'event statistics'"))
|
||||
.arg(Arg::from_usage("-u --update 'signature update'"))
|
||||
.arg(Arg::from_usage("-o --omikuji 'output with omikuji'"))
|
||||
.arg(Arg::from_usage("--credits 'Zachary Mathis, Akira Nishikawa'"))
|
||||
}
|
||||
|
||||
fn main() -> Result<(), DeError> {
|
||||
let args = build_app().get_matches();
|
||||
configs::init_singleton(&args);
|
||||
configs::singleton();
|
||||
|
||||
let filepath: Option<&str> = configs::singleton().args.filepath;
|
||||
|
||||
if let Some(filepath) = filepath {
|
||||
parse_file(filepath);
|
||||
let filepath: String = configs::singleton()
|
||||
.args
|
||||
.value_of("filepath")
|
||||
.unwrap_or("")
|
||||
.to_string();
|
||||
if filepath != "" {
|
||||
parse_file(&filepath);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
Reference in New Issue
Block a user