Skip to content
This repository has been archived by the owner on Oct 8, 2024. It is now read-only.

Commit

Permalink
Fixed Build Issues On Windows, Among Several Other Changes (#29)
Browse files Browse the repository at this point in the history
* docs: fix readme

* feat: clean up wget functionality, add tests

* deps: remove unnecessary dependencies

* fix: get rid of snake case warning

* feat: Added Windows Recursive File Downloading Powered By Powershell. [I TESTED THE SCRIPT, BUT NOT THE APP SIDE OF IT]

* feat: Added Windows Recursive File Downloading & Windows Specific Code.

* fix: Got test_execute() working for the windows version.

* fix: Converted WGET Tests To Windows Specific. All Pass.

* organized things in to screens and widgets. I think that most of this makes sense. I felt like I needed to further break this part of the code down.

* organized things in to screens and widgets. I think that most of this makes sense. I felt like I needed to further break this part of the code down. #2

* feat: Added Debug Menu To Home Menu.

* fix: Fixed A Bug Where The Cursor Would Roll Off The Screen. And I Fixed Another Bug, Where the the app.input.value() would persist if you entered something in and then you left the screen. So now , input.value() gets clearwed upon backing out to the previous screen. That unfortunatly led me to another bug where after backing out of a screen the cursor doesnt move again until you go into whatever menu option youre stuck on and then back out again?

* fix: Removed Useless Imports.

* feat: Okay, i fixed an issue where the cursor would roll off the screen. I put all the individual screens in thier own files. I fixed the build issues @PThorpe92 was having. We should be good.

* fix: Fixed Test Build Issues With Windows.

* fix: Fixed Test Build Issues With Windows. Fixed A Fuck Ton Of Glaring Issues. Im Still Not Convinced It All Works, But It Passes The Tests As They Were Intended To Be Written So.

* Update render.rs

* Update wget.rs

* Update wget.rs

* Update render.rs

* Update wget.rs

---------

Co-authored-by: PThorpe92 <[email protected]>
  • Loading branch information
KMastroluca and PThorpe92 authored Oct 1, 2023
1 parent 73e76d6 commit 73bf9fa
Show file tree
Hide file tree
Showing 33 changed files with 1,328 additions and 530 deletions.
657 changes: 329 additions & 328 deletions Cargo.lock

Large diffs are not rendered by default.

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ tui-widget-list = "0.2.2"
lazy_static = "1.4.0"
rusqlite = { version = "0.29.0", features = ["bundled"] }
serde_json = "1.0.107"
serde = { version = "1.0.188", features = ["derive"] }
serde = { version = "1.0.188", features = ["derive"] }
chrono = "0.4.31"
curl = "0.4.44"
mockito = "1.2.0"
regex = "1.9.5"
1 change: 0 additions & 1 deletion output.txt

This file was deleted.

4 changes: 2 additions & 2 deletions scripts/win64-wget.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ function Invoke-Recursive-WebRequest(
# if url is not provided exit with an error message
if (-not$url)
{
Write "Invoke-Recursive-WebRequest requires a url parameter"
Write-Error "Invoke-Recursive-WebRequest requires a url parameter"
return
}

Expand All @@ -34,7 +34,7 @@ function Invoke-Recursive-WebRequest(
#if output file is not provided exit with an error message
if (-not$outputfile)
{
Write "Invoke-Recursive-WebRequest requires an outputfile parameter"
Write-Error "Invoke-Recursive-WebRequest requires an outputfile parameter"
return
}

Expand Down
3 changes: 2 additions & 1 deletion src/app.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ impl<'a> App<'_> {
}

pub fn move_cursor_down(&mut self) {
if self.items.is_empty() || self.cursor >= self.items.len() {
// Lorenzo: I fixed a bug here with -1, where the cursor would roll off the screen.
if self.items.is_empty() || self.cursor >= self.items.len() - 1 {
return;
}
if let Some(res) = self.cursor.checked_add(1) {
Expand Down
2 changes: 1 addition & 1 deletion src/display/inputopt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ impl InputOpt {
pub fn to_string(&self) -> String {
match self {
InputOpt::URL => "URL",
InputOpt::Headers => "Headers",
InputOpt::Headers => "Header",
InputOpt::Output => "Output",
InputOpt::RequestBody => "Request Body",
InputOpt::RecursiveDownload => "Recursive Download",
Expand Down
5 changes: 4 additions & 1 deletion src/display/menuopts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@
use lazy_static::lazy_static;

lazy_static! {
pub static ref MAIN_MENU_OPTIONS: [&'static str; 4] = [
pub static ref MAIN_MENU_OPTIONS: [&'static str; 5] = [
"Build and send an HTTP request\n \n",
"Download a remote file or directory\n \n",
"View my stored API keys\n \n",
"View or execute my saved commands\n \n",
"Debug Menu. \n \n",
];
pub static ref REQUEST_MENU_OPTIONS: [&'static str; 8] = [
"Add a URL\n \n",
Expand Down Expand Up @@ -66,4 +67,6 @@ lazy_static! {
"View my saved commands\n \n",
"Delete a saved command\n \n",
];
pub static ref DEBUG_MENU_OPTIONS: [&'static str; 2] =
["Back...\n \n", "URL Input Screen Debug \n \n"];
}
6 changes: 6 additions & 0 deletions src/events/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ pub fn handle_key_events(key_event: KeyEvent, app: &mut App) -> AppResult<()> {
app.quit();
}
}
KeyCode::Esc => {
app.go_back_screen(); // Escape Should Bring You Back
if app.input.value().len() > 0 {
app.input.reset(); // If we leave the page, we should clear the input buffer
}
}
// Other handlers you could add here.
KeyCode::Up => {
app.move_cursor_up();
Expand Down
10 changes: 7 additions & 3 deletions src/request/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,7 @@ pub enum Command<'a> {
}

impl<'a> Command<'a> {
pub fn default(curl: Curl<'a>) -> Self {
Command::Curl(curl)
}
// Im gonna fix this. We should be implmenting the default trait for Command

pub fn set_method(&mut self, method: String) {
match method.as_str() {
Expand Down Expand Up @@ -150,3 +148,9 @@ impl<'a> Command<'a> {
.to_string()
}
}

impl<'a> Default for Command<'a> {
fn default() -> Self {
Command::Curl(Curl::new())
}
}
83 changes: 51 additions & 32 deletions src/request/wget.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,34 @@ impl Wget {
}
}

#[cfg(target_os = "windows")]
pub fn new() -> Self {
Wget {
cmd: String::from("powershell.exe -NoLogo -NoProfile -ExecutionPolicy Unrestricted -File scripts\\win64-wget.ps1"),
rec_level: 0,
url: String::new(),
auth: None,
output: String::new(),
response: None,
}
}

#[cfg(target_os = "windows")]
pub fn build_string(&mut self) {
if self.has_url() {
if !self.cmd.as_bytes()[self.cmd.len() - 1].is_ascii_whitespace() {
self.cmd.push(' ');
}
self.cmd.push_str("-url");
self.cmd.push(' ');
self.cmd.push_str(self.url.as_str());
}
if self.has_rec() {
if !self.cmd.as_bytes()[self.cmd.len() - 1].is_ascii_whitespace() {
self.cmd.push(' ');
}
self.cmd.push_str(format!("-r {}", self.rec_level).as_str());
self.cmd
.push_str(format!("-depth {}", self.rec_level).as_str());
}
if self.has_auth() {
if !self.cmd.as_bytes()[self.cmd.len() - 1].is_ascii_whitespace() {
Expand All @@ -45,7 +60,8 @@ impl Wget {
if !self.cmd.as_bytes()[self.cmd.len() - 1].is_ascii_whitespace() {
self.cmd.push(' ');
}
self.cmd.push_str(format!("-O {}", self.output).as_str());
self.cmd
.push_str(format!("-outputfile {}", self.output).as_str());
}
self.cmd = self.cmd.trim().to_string();
}
Expand Down Expand Up @@ -136,32 +152,33 @@ impl Wget {
Err(String::from_utf8(output.stderr).unwrap())
}
}
}

pub mod tests {
use crate::request::wget::Wget;

#[test]
#[cfg(target_os = "windows")]
pub fn execute(&mut self) -> Result<String, String> {
let output = std::process::Command::new("powershell.exe")
.arg("-NoLogo")
.arg("-NoProfile")
.arg("-ExecutionPolicy")
.arg("Unrestricted")
.arg("-File")
.arg("scripts\\win64-wget.ps1")
.arg(self.cmd.clone())
pub fn execute(&mut self) -> Result<(), String> {
let commands = self.cmd.split(" ").collect::<Vec<&str>>();
let args = commands[7..].join(" ");

let output = std::process::Command::new(commands[0])
.arg(commands[1]) // -NoLogo
.arg(commands[2]) // -NoProfile
.arg(commands[3]) // -ExecutionPolicy
.arg(commands[4]) // unrestricted
.arg(commands[5]) // -File
.arg(commands[6]) // scripts\\win64-wget.ps1
.arg(args) // Rest Of The Command Arguments
.output()
.expect("failed to execute process");
let outstr = format!("{:?}", output);
println!("{}", outstr);
if output.status.success() {
Ok(String::from_utf8(output.stdout).unwrap())
self.response = Some(String::from_utf8(output.stdout).unwrap());
Ok(())
} else {
Err(String::from_utf8(output.stderr).unwrap())
}
}
}

mod tests {
use crate::request::wget::Wget;

#[test]
#[cfg(any(target_os = "linux", target_os = "macos"))]
Expand All @@ -176,7 +193,7 @@ pub mod tests {
#[cfg(target_os = "windows")]
fn test_new_wget() {
let wget = Wget::new();
assert_eq!("", wget.cmd);
assert_eq!("powershell.exe -NoLogo -NoProfile -ExecutionPolicy Unrestricted -File scripts\\win64-wget.ps1", wget.cmd);
assert_eq!("", wget.url);
assert_eq!("", wget.output);
}
Expand All @@ -194,9 +211,9 @@ pub mod tests {
#[cfg(target_os = "windows")]
fn test_set_url_win() {
let mut wget = Wget::new();
wget.set_url(String::from("http://www.google.com"));
wget.set_url("http://www.google.com");
wget.build_string();
assert_eq!("-url http://www.google.com", wget.cmd);
assert_eq!("powershell.exe -NoLogo -NoProfile -ExecutionPolicy Unrestricted -File scripts\\win64-wget.ps1 -url http://www.google.com", wget.cmd);
}

#[test]
Expand All @@ -212,9 +229,9 @@ pub mod tests {
#[cfg(target_os = "windows")]
fn test_set_output() {
let mut wget = Wget::new();
wget.set_output(String::from("output"));
wget.set_output("output");
wget.build_string();
assert_eq!("-outputfile output", wget.cmd);
assert_eq!("powershell.exe -NoLogo -NoProfile -ExecutionPolicy Unrestricted -File scripts\\win64-wget.ps1 -outputfile output", wget.cmd);
}

#[test]
Expand All @@ -232,7 +249,7 @@ pub mod tests {
let mut wget = Wget::new();
wget.add_auth("usr", "pwd");
wget.build_string();
assert_eq!("-username usr -password pwd", wget.cmd);
assert_eq!("powershell.exe -NoLogo -NoProfile -ExecutionPolicy Unrestricted -File scripts\\win64-wget.ps1 -username usr -password pwd", wget.cmd);
}

#[test]
Expand All @@ -254,11 +271,11 @@ pub mod tests {
fn test_build_string() {
let mut wget = Wget::new();
wget.add_auth("usr", "pwd");
wget.set_url(String::from("http://www.google.com"));
wget.set_output(String::from("output"));
wget.set_url("http://www.google.com");
wget.set_output("output");
wget.build_string();
assert_eq!(
"-url http://www.google.com -username usr -password pwd -outputfile output",
"powershell.exe -NoLogo -NoProfile -ExecutionPolicy Unrestricted -File scripts\\win64-wget.ps1 -url http://www.google.com -username usr -password pwd -outputfile output",
wget.cmd
);
}
Expand All @@ -273,6 +290,7 @@ pub mod tests {
}

#[test]
#[cfg(any(target_os = "linux", target_os = "macos"))]
fn test_execute() {
let mut wget = Wget::new();
wget.set_url("http://www.google.com");
Expand All @@ -285,22 +303,23 @@ pub mod tests {
std::fs::remove_file("output").unwrap();
}

#[test]
#[cfg(target_os = "windows")]
fn test_increase_rec_level() {
let mut wget = Wget::new();
wget.set_rec_download_level(2);
assert_eq!("", wget.cmd);
assert_eq!("powershell.exe -NoLogo -NoProfile -ExecutionPolicy Unrestricted -File scripts\\win64-wget.ps1", wget.cmd);
assert_eq!(2, wget.rec_level);
}

#[test]
#[cfg(target_os = "windows")]
fn test_execute() {
let mut wget = Wget::new();
wget.set_url(String::from("http://www.google.com"));
wget.set_output(String::from("output"));
wget.set_url("http://www.google.com");
wget.set_output("output");
wget.build_string();
assert_eq!("-url http://www.google.com -outputfile output", wget.cmd);
assert_eq!("powershell.exe -NoLogo -NoProfile -ExecutionPolicy Unrestricted -File scripts\\win64-wget.ps1 -url http://www.google.com -outputfile output", wget.cmd);
let result = wget.execute();
assert_eq!(true, result.is_ok());
assert!(std::fs::metadata("output.txt").is_ok());
Expand Down
48 changes: 48 additions & 0 deletions src/screens/auth.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
use tui::backend::Backend;
use tui::widgets::ListState;
use tui::Frame;

use crate::app::App;
use crate::display::inputopt::InputOpt;
use crate::request::curl::AuthKind;
use crate::screens::screen::Screen;
use crate::ui::widgets::boxes::default_rect;
use crate::ui::widgets::menu::menu_widget;

pub fn handle_authentication_screen<B: Backend>(app: &mut App, frame: &mut Frame<'_, B>) {
let area = default_rect(frame.size());
let new_list = app.current_screen.get_list();
let mut state = ListState::with_selected(ListState::default(), Some(app.cursor));
app.items = app.current_screen.get_opts();
app.state = Some(state.clone());
app.state.as_mut().unwrap().select(Some(app.cursor));
frame.set_cursor(0, app.cursor as u16);
frame.render_stateful_widget(new_list, area, &mut state);
frame.render_widget(menu_widget(), frame.size());
if let Some(num) = app.selected {
match num {
0 => app.goto_screen(Screen::InputMenu(InputOpt::Auth(AuthKind::Basic(
String::new(),
)))),
1 => app.goto_screen(Screen::InputMenu(InputOpt::Auth(AuthKind::Bearer(
String::new(),
)))),
2 => app.goto_screen(Screen::InputMenu(InputOpt::Auth(AuthKind::Digest(
String::new(),
)))),
3 => app.goto_screen(Screen::InputMenu(InputOpt::Auth(AuthKind::AwsSigv4(
String::new(),
)))),
4 => app.goto_screen(Screen::InputMenu(InputOpt::Auth(AuthKind::Spnego(
String::new(),
)))),
5 => app.goto_screen(Screen::InputMenu(InputOpt::Auth(AuthKind::Kerberos(
String::new(),
)))),
6 => app.goto_screen(Screen::InputMenu(InputOpt::Auth(AuthKind::Ntlm(
String::new(),
)))),
_ => {}
}
}
}
34 changes: 34 additions & 0 deletions src/screens/debug.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
use tui::backend::Backend;
use tui::widgets::ListState;
use tui::Frame;

use crate::app::App;
use crate::screens::screen::Screen;
use crate::ui::widgets::boxes::centered_rect;
use crate::ui::widgets::menu::menu_widget;

pub fn handle_debug_screen<B: Backend>(app: &mut App, frame: &mut Frame<'_, B>) {
let menu_options = app.current_screen.get_list();
let area = centered_rect(70, 60, frame.size());

let mut state = ListState::with_selected(ListState::default(), Some(app.cursor));

app.state = Some(state.clone());
app.state.as_mut().unwrap().select(Some(app.cursor));

frame.set_cursor(0, app.cursor as u16);
frame.render_stateful_widget(menu_options, area, &mut state);
frame.render_widget(menu_widget(), frame.size());

match app.selected {
Some(0) => {
// Back To Home
app.goto_screen(Screen::Home); // Back
}
Some(1) => {
// Test Single Line Input Screen
app.goto_screen(Screen::URLInput);
}
_ => {}
}
}
Loading

0 comments on commit 73bf9fa

Please sign in to comment.