From 541e99b1b2b4c2640b8c7a6983ee5143165959c2 Mon Sep 17 00:00:00 2001 From: PrintedScript <64908610+PrintedScript@users.noreply.github.com> Date: Sat, 20 Jan 2024 21:43:50 +0800 Subject: [PATCH] improvements --- .github/workflows/build-release.yml | 48 ++++++++++++ Cargo.lock | 7 +- Cargo.toml | 3 +- src/main.rs | 117 +++++++++++++++------------- 4 files changed, 116 insertions(+), 59 deletions(-) create mode 100644 .github/workflows/build-release.yml diff --git a/.github/workflows/build-release.yml b/.github/workflows/build-release.yml new file mode 100644 index 0000000..74e03ef --- /dev/null +++ b/.github/workflows/build-release.yml @@ -0,0 +1,48 @@ +name: Build Release Executables +on: + release: + types: + - created + +jobs: + build-release-windows: + name: Build on Windows ${{ github.event.release.tag_name }} + runs-on: windows-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/cargo@v1 + with: + command: build + args: --release + - name: Rename executable + run: mv target/release/syntax_bootstrapper.exe target/release/SyntaxPlayerLauncher.exe + - name: Upload Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: target/release/SyntaxPlayerLauncher.exe + asset_name: SyntaxPlayerLauncher.exe + asset_content_type: application/octet-stream + + build-release-linux: + name: Build on Linux ${{ github.event.release.tag_name }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - uses: actions-rs/cargo@v1 + with: + command: build + args: --release + - name: Rename executable + run: mv target/release/syntax_bootstrapper target/release/SyntaxPlayerLinuxLauncher + - name: Upload Release Asset + uses: actions/upload-release-asset@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + upload_url: ${{ github.event.release.upload_url }} + asset_path: target/release/SyntaxPlayerLinuxLauncher + asset_name: SyntaxPlayerLinuxLauncher + asset_content_type: application/octet-stream diff --git a/Cargo.lock b/Cargo.lock index 1d33c26..42a42d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1178,9 +1178,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -1261,7 +1261,7 @@ dependencies = [ [[package]] name = "syntax_bootstrapper" -version = "1.3.2" +version = "1.3.3" dependencies = [ "chrono", "colored", @@ -1271,6 +1271,7 @@ dependencies = [ "indicatif", "md5", "reqwest", + "sha1", "term_size", "tokio", "winreg 0.51.0", diff --git a/Cargo.toml b/Cargo.toml index e4f57f9..318a633 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "syntax_bootstrapper" -version = "1.3.2" +version = "1.3.3" edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -17,6 +17,7 @@ tokio = { version = "1.32.0", features=["full"]} futures-util = "0.3.28" md5 = "0.7.0" zip-extract = "0.1.2" +sha1 = "0.10.6" [target.'cfg(windows)'.dependencies] winreg = "0.51.0" diff --git a/src/main.rs b/src/main.rs index c6b0126..46a238e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -6,6 +6,7 @@ use dirs::data_local_dir; use futures_util::StreamExt; use md5; use zip_extract; +use sha1::{Sha1, Digest}; #[cfg(target_os = "windows")] use std::os::windows::prelude::FileExt; @@ -112,6 +113,14 @@ pub async fn create_folder_if_not_exists( path: &PathBuf ) { } } +pub async fn get_sha1_hash_of_file( path: &PathBuf ) -> String { + let mut file = std::fs::File::open(path).unwrap(); + let mut hasher = Sha1::new(); + std::io::copy(&mut file, &mut hasher).unwrap(); + let hash = hasher.finalize(); + return format!("{:x}", hash); +} + fn get_installation_directory() -> PathBuf { return PathBuf::from(data_local_dir().unwrap().to_str().unwrap()).join("Syntax"); } @@ -245,34 +254,48 @@ async fn main() { // Download the latest bootstrapper download_file(&http_client, &format!("https://{}/{}-{}", setup_url, latest_client_version, bootstrapper_filename), &latest_bootstrapper_path).await; } - // Run the latest bootstrapper ( with the same arguments passed to us ) and exit - #[cfg(target_os = "windows")] - { - let mut command = std::process::Command::new(latest_bootstrapper_path.clone()); - command.args(&args[1..]); - match command.spawn() { - Ok(_) => {}, - Err(e) => { - debug(&format!("Bootstrapper errored with error {}", e)); - info("Found bootstrapper was corrupted! Downloading..."); - std::fs::remove_file(latest_bootstrapper_path.clone()).unwrap(); - download_file(&http_client, &format!("https://{}/{}-{}", setup_url, latest_client_version, bootstrapper_filename), &latest_bootstrapper_path).await; - command.spawn().expect("Bootstrapper is still corrupted."); - std::thread::sleep(std::time::Duration::from_secs(20)); + + // Lets compare the SHA1 hash of the latest bootstrapper to the one we are currently running + // If they are the same, then we can continue with the update process + // We do this because antivirus software does not like this type of behavior + + let latest_bootstrapper_hash = get_sha1_hash_of_file(&latest_bootstrapper_path).await; + let current_exe_hash = get_sha1_hash_of_file(¤t_exe_path).await; + + debug(&format!("Latest Bootstrapper Hash: {}", latest_bootstrapper_hash.bright_blue())); + debug(&format!("Current Bootstrapper Hash: {}", current_exe_hash.bright_blue())); + + if latest_bootstrapper_hash != current_exe_hash { + // Run the latest bootstrapper ( with the same arguments passed to us ) and exit + #[cfg(target_os = "windows")] + { + let mut command = std::process::Command::new(latest_bootstrapper_path.clone()); + command.args(&args[1..]); + match command.spawn() { + Ok(_) => {}, + Err(e) => { + debug(&format!("Bootstrapper errored with error {}", e)); + info("Found bootstrapper was corrupted! Downloading..."); + std::fs::remove_file(latest_bootstrapper_path.clone()).unwrap(); + download_file(&http_client, &format!("https://{}/{}-{}", setup_url, latest_client_version, bootstrapper_filename), &latest_bootstrapper_path).await; + command.spawn().expect("Bootstrapper is still corrupted."); + std::thread::sleep(std::time::Duration::from_secs(20)); + } } } - } - #[cfg(not(target_os = "windows"))] - { - // Make sure the latest bootstrapper is executable - std::process::Command::new("chmod").arg("+x").arg(latest_bootstrapper_path.to_str().unwrap()).spawn().unwrap(); + #[cfg(not(target_os = "windows"))] + { + // Make sure the latest bootstrapper is executable + std::process::Command::new("chmod").arg("+x").arg(latest_bootstrapper_path.to_str().unwrap()).spawn().unwrap(); + + info("We need permission to run the latest bootstrapper"); + let mut command = std::process::Command::new(latest_bootstrapper_path); + command.args(&args[1..]); + command.spawn().unwrap(); + } + std::process::exit(0); - info("We need permission to run the latest bootstrapper"); - let mut command = std::process::Command::new(latest_bootstrapper_path); - command.args(&args[1..]); - command.spawn().unwrap(); } - std::process::exit(0); } // Looks like we are running from the latest version directory, so we can continue with the update process @@ -280,14 +303,13 @@ async fn main() { // If it doesent exist, then we got either a fresh directory or a corrupted installation // So delete the every file in the current version directory except for the Bootstrapper itself let app_settings_path = current_version_directory.join("AppSettings.xml"); - let client_executable_path = current_version_directory.join("SyntaxPlayerBeta.exe"); if !app_settings_path.exists() { //|| !client_executable_path.exists() { info("Downloading the latest client files, this may take a while."); for entry in std::fs::read_dir(¤t_version_directory).unwrap() { let entry = entry.unwrap(); let path = entry.path(); if path.is_file() { - if path != current_exe_path { + if path != latest_bootstrapper_path { std::fs::remove_file(path).unwrap(); } } else { @@ -339,43 +361,28 @@ async fn main() { let hkey_syntax_player_shell_open = hkey_syntax_player_shell.create_subkey("open").unwrap().0; let hkey_syntax_player_shell_open_command = hkey_syntax_player_shell_open.create_subkey("command").unwrap().0; let defaulticon = hkey_syntax_player.create_subkey("DefaultIcon").unwrap().0; - hkey_syntax_player_shell_open_command.set_value("", &format!("\"{}\" \"%1\"", current_exe_path.to_str().unwrap())).unwrap(); - defaulticon.set_value("", &format!("\"{}\",0", current_exe_path.to_str().unwrap())).unwrap(); + hkey_syntax_player_shell_open_command.set_value("", &format!("\"{}\" \"%1\"", latest_bootstrapper_path.to_str().unwrap())).unwrap(); + defaulticon.set_value("", &format!("\"{}\",0", latest_bootstrapper_path.to_str().unwrap())).unwrap(); hkey_syntax_player.set_value("", &format!("URL: Syntax Protocol")).unwrap(); hkey_syntax_player.set_value("URL Protocol", &"").unwrap(); } #[cfg(not(target_os = "windows"))] { // Linux support - // We have to write a .desktop file to ~/.local/share/applications - let desktop_file_path = dirs::data_local_dir().unwrap().join("applications").join("syntax-player.desktop"); - let desktop_file = format!( -"[Desktop Entry] -Name=Syntax Launcher + let desktop_file_content = &format!("[Desktop Entry] +Name=Syntax Player Exec={} %u -Terminal=true Type=Application -MimeType=x-scheme-handler/syntax-player; -Icon={} -StartupWMClass=SyntaxLauncher -Categories=Game; -Comment=Syntax Launcher -", current_exe_path.to_str().unwrap(), current_exe_path.to_str().unwrap()); - std::fs::write(desktop_file_path, desktop_file).unwrap(); - // We also have to write a mimeapps.list file to ~/.config - let mimeapps_list_path = dirs::config_dir().unwrap().join("mimeapps.list"); - let mimeapps_list = format!( -"[Default Applications] -x-scheme-handler/syntax-player=syntax-player.desktop -"); - std::fs::write(mimeapps_list_path, mimeapps_list).unwrap(); - // We also have to write a mimeapps.list file to ~/.local/share - let mimeapps_list_path = dirs::data_local_dir().unwrap().join("mimeapps.list"); - let mimeapps_list = format!( -"[Default Applications] -x-scheme-handler/syntax-player=syntax-player.desktop -"); - std::fs::write(mimeapps_list_path, mimeapps_list).unwrap(); +Terminal=false +Version={} +MimeType=x-scheme-handler/syntax-player;", latest_bootstrapper_path.to_str().unwrap(), env!("CARGO_PKG_VERSION")); + + let desktop_file_path = "/usr/share/applications/syntax-player.desktop"; + + let mut file = File::create(desktop_file_path).expect("Unable to create desktop file"); + file.write_all(desktop_file_content.as_bytes()) + .expect("Unable to write to desktop file"); + } // Write the AppSettings.xml file