From 034bbbac7fe35130d1ce64ec3c0dba933cb51678 Mon Sep 17 00:00:00 2001 From: alterdekim Date: Tue, 22 Oct 2024 02:53:41 +0300 Subject: [PATCH] interface developing has started modified: Cargo.lock modified: Cargo.toml modified: src/gui.rs new file: src/toggle_switch.rs --- Cargo.lock | 164 ++++++++++++++++++++++++++++++++++- Cargo.toml | 6 +- src/gui.rs | 197 ++++++++++++++++++++++++++++++++++--------- src/toggle_switch.rs | 46 ++++++++++ 4 files changed, 370 insertions(+), 43 deletions(-) create mode 100644 src/toggle_switch.rs diff --git a/Cargo.lock b/Cargo.lock index 0a5eed0..be584b0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -60,9 +60,9 @@ dependencies = [ [[package]] name = "accesskit_macos" -version = "0.17.3" +version = "0.17.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49509c722e8da39e6c569f7d13ec51620208988913e738abbc67e3c65f06e6d5" +checksum = "bfc6c1ecd82053d127961ad80a8beaa6004fb851a3a5b96506d7a6bd462403f6" dependencies = [ "accesskit", "accesskit_consumer", @@ -106,9 +106,9 @@ dependencies = [ [[package]] name = "accesskit_winit" -version = "0.22.3" +version = "0.22.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9987e852fe7e4e5a493f8c8af0b729b47da2750f0dea10a4c8984fe1117ebaec" +checksum = "aea3522719f1c44564d03e9469a8e2f3a98b3a8a880bd66d0789c6b9c4a669dd" dependencies = [ "accesskit", "accesskit_macos", @@ -885,6 +885,36 @@ dependencies = [ "error-code", ] +[[package]] +name = "cocoa" +version = "0.25.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6140449f97a6e97f9511815c5632d84c8aacf8ac271ad77c559218161a1373c" +dependencies = [ + "bitflags 1.3.2", + "block", + "cocoa-foundation", + "core-foundation 0.9.4", + "core-graphics", + "foreign-types", + "libc", + "objc", +] + +[[package]] +name = "cocoa-foundation" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" +dependencies = [ + "bitflags 1.3.2", + "block", + "core-foundation 0.9.4", + "core-graphics-types", + "libc", + "objc", +] + [[package]] name = "codespan-reporting" version = "0.11.1" @@ -1193,6 +1223,27 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "dirs" +version = "5.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +dependencies = [ + "dirs-sys", +] + +[[package]] +name = "dirs-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.48.0", +] + [[package]] name = "dispatch" version = "0.2.0" @@ -1343,6 +1394,15 @@ dependencies = [ "resvg", ] +[[package]] +name = "egui_file" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31e8280f9aea0f814013815071aebcf5c341e1d5420b381d3b0c1e3c42604d2" +dependencies = [ + "egui", +] + [[package]] name = "egui_glow" version = "0.29.1" @@ -1360,6 +1420,19 @@ dependencies = [ "winit", ] +[[package]] +name = "egui_logger" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0d940e9a0f56a2fda347cafdd42513136ab946ca57febbc5e3c6faf77f7824" +dependencies = [ + "chrono", + "egui", + "hashbrown 0.15.0", + "log", + "regex", +] + [[package]] name = "ehttp" version = "0.5.0" @@ -1559,6 +1632,12 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foldhash" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f81ec6369c545a7d40e4589b5597581fa1c441fe1cce96dd1de43159910a36a2" + [[package]] name = "foreign-types" version = "0.5.0" @@ -1607,8 +1686,11 @@ dependencies = [ "clap", "console-subscriber", "crossbeam-channel", + "dirs", "eframe", "egui_extras", + "egui_file", + "egui_logger", "env_logger", "futures", "generic-array", @@ -1627,6 +1709,7 @@ dependencies = [ "socket2 0.4.10", "tokio", "tokio-util", + "tray-item", "tun2", "x25519-dalek", ] @@ -1983,6 +2066,11 @@ name = "hashbrown" version = "0.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] [[package]] name = "hassle-rs" @@ -2734,6 +2822,17 @@ dependencies = [ "malloc_buf", ] +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + [[package]] name = "objc-sys" version = "0.3.5" @@ -2937,6 +3036,15 @@ dependencies = [ "objc2-foundation", ] +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + [[package]] name = "object" version = "0.36.5" @@ -2958,6 +3066,12 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "orbclient" version = "0.3.48" @@ -3007,6 +3121,12 @@ dependencies = [ "thiserror", ] +[[package]] +name = "padlock" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c10569378a1dacd9f30dbe7ae49e054d2c45dc2f8ee49899903e09c3924e8b6f" + [[package]] name = "parking" version = "2.2.1" @@ -3349,6 +3469,17 @@ dependencies = [ "bitflags 2.6.0", ] +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + [[package]] name = "regex" version = "1.11.0" @@ -4197,6 +4328,22 @@ dependencies = [ "tracing-core", ] +[[package]] +name = "tray-item" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59d4bd406170690dc30eabb3badc67a085beaf9b2c3b1923afcc9c26a2191353" +dependencies = [ + "cocoa", + "core-graphics", + "libc", + "objc", + "objc-foundation", + "objc_id", + "padlock", + "windows-sys 0.52.0", +] + [[package]] name = "try-lock" version = "0.2.5" @@ -4917,6 +5064,15 @@ dependencies = [ "windows-targets 0.42.2", ] +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets 0.48.5", +] + [[package]] name = "windows-sys" version = "0.52.0" diff --git a/Cargo.toml b/Cargo.toml index 7720313..f849891 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,9 +52,13 @@ network-interface = "2.0.0" [target.'cfg(target_os="windows")'.dependencies] eframe = { version = "0.29.1", features = ["wgpu"] } egui_extras = { version = "0.29.1", features = ["all_loaders"] } +egui_file = "0.19" +dirs = "5.0.1" +egui_logger = "0.6.1" +tray-item = "0.10.0" [target.'cfg(target_os="android")'.dependencies] jni = "^0.20" robusta_jni = "0.2.2" nonblock = "0.2.0" -log4rs = "1.3.0" +log4rs = "1.3.0" \ No newline at end of file diff --git a/src/gui.rs b/src/gui.rs index a1bf068..1ede29a 100644 --- a/src/gui.rs +++ b/src/gui.rs @@ -1,22 +1,43 @@ #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] -use eframe::egui::{self, Frame, Label, Spacing, Vec2}; +use eframe::egui::{self, Context, Frame, Label, ScrollArea, Spacing, Vec2}; +use egui_file::FileDialog; +use std::{ + ffi::OsStr, + path::{Path, PathBuf}, + }; +use egui_extras::{Column, TableBuilder}; +use log::{info, error}; +use crate::config::ClientConfiguration; +use log::LevelFilter; +use env_logger::Builder; + +mod toggle_switch; +mod config; fn main() -> eframe::Result { + egui_logger::builder().init().unwrap(); + let options = eframe::NativeOptions { - viewport: egui::ViewportBuilder::default().with_inner_size([320.0, 240.0]), + viewport: egui::ViewportBuilder::default().with_inner_size([640.0, 480.0]), ..Default::default() }; + let mut hh = dirs::home_dir().unwrap(); + hh.push(".frida"); + let cfgs = std::fs::read_dir(hh).unwrap(); + let mut cv = Vec::new(); + for path in cfgs { + cv.push(path.unwrap().path()); + } eframe::run_native( "Frida", options, Box::new(|cc| { - Ok(Box::::default()) + Ok(Box::new(App::new(cv))) }), ) } - #[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] #[derive(Clone, Copy, Debug, PartialEq)] enum AppScreens { @@ -26,14 +47,16 @@ enum AppScreens { struct App { screen: AppScreens, - configs: Configs + configs: Configs, + logs: Logs, } -impl Default for App { - fn default() -> Self { +impl App { + fn new(cfgs: Vec) -> Self { Self { screen: AppScreens::Configs, - configs: Configs::default() + configs: Configs::new(cfgs), + logs: Logs::default() } } } @@ -48,73 +71,171 @@ impl eframe::App for App { ui.separator(); match self.screen { AppScreens::Configs => { - self.configs.ui(ui); + self.configs.ui(ui, ctx); } AppScreens::Log => { - + self.logs.ui(ui, ctx); } } }); } } -#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] -#[cfg_attr(feature = "serde", serde(default))] -#[derive(PartialEq)] -struct Configs { - num: u32, - btn_status: bool, +struct Logs { } -impl Default for Configs { +impl Default for Logs { fn default() -> Self { - Self { - num: 32, - btn_status: true - } + Self{} } } +impl Logs { + fn ui(&mut self, ui: &mut egui::Ui, ctx: &Context) { + egui::CentralPanel::default() + .show_inside(ui, |ui| { + egui_logger::logger_ui().show(ui); + }); + } +} + +#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))] +#[cfg_attr(feature = "serde", serde(default))] +#[derive(Debug)] +struct Configs { + num: u32, + btn_status: bool, + open_config_dialog: Option, + cfgs: Vec, + selected_cfg: Option<(ClientConfiguration, String)> +} + impl Configs { - fn ui(&mut self, ui: &mut egui::Ui) { + fn new(cfgs: Vec) -> Self { + Self { + num: 32, + btn_status: false, + open_config_dialog: None, + cfgs, + selected_cfg: None + } + } + + fn ui(&mut self, ui: &mut egui::Ui, ctx: &Context) { let Self { num, - btn_status + btn_status, + open_config_dialog, + cfgs, + selected_cfg } = self; egui::SidePanel::left("clist") .resizable(false) .exact_width(150.0) .show_inside(ui, |ui| { - + ScrollArea::vertical() + .auto_shrink(false) + .show(ui, |ui| { + ui.set_width(ui.available_width()); + self.cfgs.iter().for_each(|f| { + let filename = f.file_name().unwrap().to_str().unwrap(); + let mut b = egui::Button::new(filename); + if self.selected_cfg.is_some() && self.selected_cfg.as_ref().unwrap().1 == filename.to_string() { + b = b.fill(egui::Color32::LIGHT_BLUE); + } + let e = ui.add_sized( + Vec2::new(ui.available_width(), 0.0), + b, + ); + if e.clicked() { + let data = std::fs::read(f.clone()); + let cfg_raw = &String::from_utf8(data.unwrap()).unwrap(); + let config: ClientConfiguration = serde_yaml::from_str(cfg_raw).expect("Bad client config file structure"); + self.selected_cfg = Some((config, filename.to_string())); + } + }); + }); }); - - egui::CentralPanel::default() .show_inside(ui, |ui| { ui.spacing_mut().item_spacing.y = 20.0; + + if self.selected_cfg.is_none() { return; } + + let cfg = &self.selected_cfg.as_ref().unwrap().0; ui.group(|ui| { ui.spacing_mut().item_spacing.y = 5.0; ui.set_width(ui.available_width()); - ui.label("Interface:"); - ui.label("Status:"); - ui.label("Public key:"); - ui.label("Address:"); - if ui.add_visible(self.btn_status, egui::Button::new("Activate")).clicked() { - self.btn_status = false; - }; - if ui.add_visible(!self.btn_status, egui::Button::new("Deactivate")).clicked() { - self.btn_status = true; - } + ui.label(format!("Interface: {}", &self.selected_cfg.as_ref().unwrap().1)); + ui.label("Status: inactive"); + ui.label(format!("Public key: {}", &cfg.client.public_key)); + ui.label(format!("Address: {}", &cfg.client.address)); + ui.horizontal(|ui| { + ui.label("Activate: "); + ui.add(crate::toggle_switch::toggle(&mut self.btn_status)); + }); }); ui.group(|ui| { ui.spacing_mut().item_spacing.y = 5.0; ui.set_width(ui.available_width()); - ui.label("Public key:"); - ui.label("Endpoint:"); + ui.label(format!("Public key: {}", &cfg.server.public_key)); + ui.label(format!("Endpoint: {}", &cfg.server.endpoint)); + ui.label(format!("Keepalive: {}", &cfg.server.keepalive)); + }); + }); + + egui::TopBottomPanel::bottom("btns") + .resizable(false) + .show_inside(ui, |ui| { + ui.add_space(10.0); + ui.horizontal(|ui| { + ui.spacing_mut().item_spacing.x = 10.0; + + if ui.button("Add config").clicked() { + let filter = Box::new({ + let ext = Some(OsStr::new("yaml")); + move |path: &Path| -> bool { path.extension() == ext } + }); + let mut dialog = FileDialog::open_file(None).show_files_filter(filter); + dialog.open(); + + self.open_config_dialog = Some(dialog); + } + + if let Some(dialog) = &mut self.open_config_dialog { + if dialog.show(ctx).selected() { + if let Some(file) = dialog.path() { + if let Some(home) = dirs::home_dir() { + let mut h = home.clone(); + h.push(".frida"); + std::fs::create_dir_all(&h); + h.push(file.file_name().unwrap()); + std::fs::copy(file, &h); + + self.cfgs.push(h); + } + } + } + } + + if ui.button("Remove selected").clicked() { + let path = &self.selected_cfg.as_ref().unwrap().1; + if let Ok(r) = std::fs::remove_file(path) { + error!("FUCK"); + for i in 0..self.cfgs.len() { + error!("AA {:?}", path); + if path == self.cfgs[i].file_name().unwrap().to_str().unwrap() { + self.cfgs.remove(i); + break; + } + } + self.selected_cfg = None; + } + } }); }); } diff --git a/src/toggle_switch.rs b/src/toggle_switch.rs new file mode 100644 index 0000000..753b8e6 --- /dev/null +++ b/src/toggle_switch.rs @@ -0,0 +1,46 @@ +/// iOS-style toggle switch: +/// +/// ``` text +/// _____________ +/// / /.....\ +/// | |.......| +/// \_______\_____/ +/// ``` +/// +/// ## Example: +/// ``` ignore +/// toggle_ui(ui, &mut my_bool); +/// ``` + +use eframe::egui; + +fn toggle_ui(ui: &mut egui::Ui, on: &mut bool) -> egui::Response { + let desired_size = ui.spacing().interact_size.y * egui::vec2(2.0, 1.0); + let (rect, mut response) = ui.allocate_exact_size(desired_size, egui::Sense::click()); + if response.clicked() { + *on = !*on; + response.mark_changed(); + } + response.widget_info(|| { + egui::WidgetInfo::selected(egui::WidgetType::Checkbox, ui.is_enabled(), *on, "") + }); + + if ui.is_rect_visible(rect) { + let how_on = ui.ctx().animate_bool_responsive(response.id, *on); + let visuals = ui.style().interact_selectable(&response, *on); + let rect = rect.expand(visuals.expansion); + let radius = 0.5 * rect.height(); + ui.painter() + .rect(rect, radius, visuals.bg_fill, visuals.bg_stroke); + let circle_x = egui::lerp((rect.left() + radius)..=(rect.right() - radius), how_on); + let center = egui::pos2(circle_x, rect.center().y); + ui.painter() + .circle(center, 0.75 * radius, visuals.bg_fill, visuals.fg_stroke); + } + + response +} + +pub fn toggle(on: &mut bool) -> impl egui::Widget + '_ { + move |ui: &mut egui::Ui| toggle_ui(ui, on) +} \ No newline at end of file