From 21d0aee2b146397e0207d6c39589a2590a424cfa Mon Sep 17 00:00:00 2001 From: Samuel Walker Date: Sat, 22 Jun 2024 17:52:25 -0600 Subject: [PATCH] Set up get_modpacks function --- FCLauncher/src-tauri/Cargo.toml | 1 + FCLauncher/src-tauri/res/vsftpd.crt | 24 +++++++++++ FCLauncher/src-tauri/src/ftp.rs | 56 +++++++++++++++++++++++++ FCLauncher/src-tauri/src/java.rs | 54 ++++++++++++++++++++++++ FCLauncher/src-tauri/src/main.rs | 21 ++++++++++ FCLauncher/src-tauri/src/prism.rs | 45 ++++++++++++++++++++ FCLauncher/src-tauri/src/system_dirs.rs | 8 ++++ FCLauncher/src-tauri/src/util.rs | 6 +++ 8 files changed, 215 insertions(+) create mode 100644 FCLauncher/src-tauri/res/vsftpd.crt create mode 100644 FCLauncher/src-tauri/src/ftp.rs create mode 100644 FCLauncher/src-tauri/src/java.rs create mode 100644 FCLauncher/src-tauri/src/prism.rs create mode 100644 FCLauncher/src-tauri/src/system_dirs.rs create mode 100644 FCLauncher/src-tauri/src/util.rs diff --git a/FCLauncher/src-tauri/Cargo.toml b/FCLauncher/src-tauri/Cargo.toml index d894f66..fb7b008 100644 --- a/FCLauncher/src-tauri/Cargo.toml +++ b/FCLauncher/src-tauri/Cargo.toml @@ -14,6 +14,7 @@ tauri-build = { version = "1", features = [] } tauri = { version = "1", features = ["shell-open"] } serde = { version = "1", features = ["derive"] } serde_json = "1" +suppaftp = { version = "6.0.1", features = ["native-tls"] } [features] # This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!! diff --git a/FCLauncher/src-tauri/res/vsftpd.crt b/FCLauncher/src-tauri/res/vsftpd.crt new file mode 100644 index 0000000..0116f2d --- /dev/null +++ b/FCLauncher/src-tauri/res/vsftpd.crt @@ -0,0 +1,24 @@ +-----BEGIN CERTIFICATE----- +MIID8TCCAtmgAwIBAgIUeFYZmMrAiIFZ9/QFwUS636XZrJMwDQYJKoZIhvcNAQEL +BQAwgYcxCzAJBgNVBAYTAlVTMRAwDgYDVQQIDAdXeW9taW5nMREwDwYDVQQHDAhD +aGV5ZW5uZTERMA8GA1UECgwIUGVyc29uYWwxGzAZBgNVBAMMEmdpdGVhLnBpd2Fs +a2VyLm5ldDEjMCEGCSqGSIb3DQEJARYUc3dhbGtlckBwaXdhbGtlci5uZXQwHhcN +MjQwNjIyMDAzNzEwWhcNMjUwNjIyMDAzNzEwWjCBhzELMAkGA1UEBhMCVVMxEDAO +BgNVBAgMB1d5b21pbmcxETAPBgNVBAcMCENoZXllbm5lMREwDwYDVQQKDAhQZXJz +b25hbDEbMBkGA1UEAwwSZ2l0ZWEucGl3YWxrZXIubmV0MSMwIQYJKoZIhvcNAQkB +FhRzd2Fsa2VyQHBpd2Fsa2VyLm5ldDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC +AQoCggEBANOo7BOAUKhbBWodZqY8U34sQhK5Zj6WkVPQrFG1MWXX3KarDtBSuZ99 +PjbIoDR+Xm5MuNcJMnbeG4+EH6SrNsogHoyn7m8XJAQ/1N6kHEii4qeDzMIbcNu6 +7L54ZbONBw1Sygilnavp1iPY/2GzWH5ynaT4w4hQQrmDm8GlDNjxWGnw1CpOExAs +LdUP3sF6RNtN6dX1vgYMo9ziNtRazRmDANXykgrfBrPCyjUGDsI9wnqm21qoaQ/s +w506XovYI1Q6zWVu6cWUYyCFy4mABQxOOf7doJi4h6Wbxfp4WbNdcoBDHDN4nHzo +pdrMzJ8GlZD0aCmmU+8ERvIk+IXY6+kCAwEAAaNTMFEwHQYDVR0OBBYEFJ/4/N4x +fO/5nu/snApQO7Cw6CyCMB8GA1UdIwQYMBaAFJ/4/N4xfO/5nu/snApQO7Cw6CyC +MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAMFwno+imd5ApXP4 +NsuX6db5GLiT6SHV65iactFUbnvqvK35KQMKVW03hOb2FPwAzEPARcPtFlENAWBl +mHphDwAmfLbHXHdiTAKJNFO7D/AOB4TG6geBFlhYvwHCVS17nzFRJvF/0APlgbO8 +8f3XkmPBPudaGiuKHWdppdHCisk6CfYvNNnjguxihyUL/mDkwiKYQPcHsMYwdYM0 +QWCcTNyCjnFK/pbo6dLyPAFpXE9becSEhbxvFziNelADRflLkOUSd+sfxmoLMMsA +EJajfocYQkAOiuh8uVzol9xsnKcZiujRoTSnndZsRVqfiNZaJbpvZoD/kY0aBXHo +SIh5Ff4= +-----END CERTIFICATE----- diff --git a/FCLauncher/src-tauri/src/ftp.rs b/FCLauncher/src-tauri/src/ftp.rs new file mode 100644 index 0000000..ea1d263 --- /dev/null +++ b/FCLauncher/src-tauri/src/ftp.rs @@ -0,0 +1,56 @@ +use std::io::Write; +use std::path::PathBuf; + +use suppaftp::FtpError; +use suppaftp::NativeTlsFtpStream; +use suppaftp::NativeTlsConnector; +use suppaftp::native_tls::Certificate; +use suppaftp::native_tls::TlsConnector; + + +fn ftp_connection_anonymous() -> Result{ + ftp_connection("anonymous", "anonymous@") +} + + +fn ftp_connection(username: &str, password: &str) -> Result{ + let ftp_stream = NativeTlsFtpStream::connect("gitea.piwalker.net:21").unwrap_or_else(|err| + panic!("{}", err) + ); + let cert = include_bytes!("../res/vsftpd.crt"); + let cert = Certificate::from_pem(cert).unwrap(); + let mut ftp_stream = ftp_stream.into_secure(NativeTlsConnector::from(TlsConnector::builder().add_root_certificate(cert).build().unwrap()), "gitea.piwalker.net").unwrap(); + ftp_stream.login("anonymous", "anonymous@").map(|_| Ok(ftp_stream)).unwrap() +} + + +pub fn ftp_retr(file: PathBuf , mut writer: impl Write, mut callback: impl FnMut(usize)) -> Result { + let mut ftp_stream = ftp_connection_anonymous().unwrap(); + let file = file.to_str().unwrap().replace("\\", "/"); + let size = ftp_stream.size(&file)?; + let mut total = 0; + ftp_stream.retr(file.as_str(), |stream| { + let mut tx_bytes = [0u8; 1500]; + loop { + let bytes_read = stream.read(&mut tx_bytes).unwrap(); + writer.write_all(&mut tx_bytes.split_at(bytes_read).0).unwrap(); + total += bytes_read; + if total == size || bytes_read == 0 { + break; + }else{ + callback(bytes_read); + } + } + Ok(true) + })?; + Ok(true) + +} + +pub fn ftp_get_size(file: PathBuf) -> Result { + let mut stream = ftp_connection_anonymous()?; + stream.size(file.to_str().unwrap().replace("\\", "/")) +} + + + diff --git a/FCLauncher/src-tauri/src/java.rs b/FCLauncher/src-tauri/src/java.rs new file mode 100644 index 0000000..7c9be22 --- /dev/null +++ b/FCLauncher/src-tauri/src/java.rs @@ -0,0 +1,54 @@ +use std::env; +use std::io::{Cursor, Seek, Read}; +use std::path::{Components, Path, PathBuf}; +use flate2::read::GzDecoder; +use tar::Archive; + + +use crate::system_dirs::get_local_data_directory; +use crate::ftp::{self, ftp_get_size}; +use crate::util; + +fn check_java(version: u8) -> bool { + let dir = get_local_data_directory().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win" } else {"lin"})); + dir.exists() +} + +pub fn install_java(version: u8) { + if check_java(version) { + return; + } + let ftp_dir = PathBuf::new().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win.zip" } else {"lin.tar.gz"})); + let mut buff = Cursor::new(vec![]); + let mut total: usize = 0; + let size = ftp_get_size(ftp_dir.clone()).unwrap(); + ftp::ftp_retr(ftp_dir, &mut buff, |data| util::download_callback(data, &mut total, size)).unwrap(); + + std::fs::create_dir_all(get_local_data_directory().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win" } else {"lin"}))).unwrap(); + buff.rewind().unwrap(); + if env::consts::OS != "windows" { + let tar = GzDecoder::new(buff); + let mut archive = Archive::new(tar); + if !unpack_archive(archive, get_local_data_directory().join("java").join(format!("java-{}-lin", version))).is_ok() { + std::fs::remove_dir_all(get_local_data_directory().join("java").join(format!("java-{}-lin", version))).unwrap(); + } + } else { + if !zip_extract::extract(buff, get_local_data_directory().join("java").join(format!("java-{}-win", version)).as_path(), true).is_ok() { + std::fs::remove_dir_all(get_local_data_directory().join("java").join(format!("java-{}-win", version))).unwrap(); + } + } + +} + +fn unpack_archive(mut archive: Archive, dst: PathBuf) -> Result<(), Box> { + for file in archive.entries()? { + let path = PathBuf::new().join(dst.clone()); + let mut file = file?; + let file_path = file.path()?; + let mut file_path = file_path.components(); + let _ = file_path.next(); + let file_path = file_path.as_path(); + file.unpack(path.join(file_path))?; + } + Ok(()) +} diff --git a/FCLauncher/src-tauri/src/main.rs b/FCLauncher/src-tauri/src/main.rs index 523550d..9a9305e 100644 --- a/FCLauncher/src-tauri/src/main.rs +++ b/FCLauncher/src-tauri/src/main.rs @@ -1,13 +1,34 @@ // Prevents additional console window on Windows in release, DO NOT REMOVE!! #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] +use std::{io::Cursor, path::PathBuf}; +use std::io::Seek; +use serde_json::{Result, Value}; + +mod ftp; + // Learn more about Tauri commands at https://tauri.app/v1/guides/features/command #[tauri::command] fn greet(name: &str) -> String { format!("Hello, {}! You've been greeted from Rust!", name) } +#[tauri::command] +fn get_modpacks() -> Vec { + let mut buf = Cursor::new(vec![]); + ftp::ftp_retr(PathBuf::new().join("modpacks.json"), &mut buf, |_| return); + buf.rewind(); + let v: Value = serde_json::from_reader(buf).unwrap(); + println!("{}", v[0]["name"]); + let mut packs: Vec = Vec::new(); + for pack in v.as_array().unwrap() { + packs.push(pack["name"].to_string()); + } + return packs; +} + fn main() { + println!("{}", get_modpacks()[0]); tauri::Builder::default() .invoke_handler(tauri::generate_handler![greet]) .run(tauri::generate_context!()) diff --git a/FCLauncher/src-tauri/src/prism.rs b/FCLauncher/src-tauri/src/prism.rs new file mode 100644 index 0000000..3772ca3 --- /dev/null +++ b/FCLauncher/src-tauri/src/prism.rs @@ -0,0 +1,45 @@ +use std::{env, io::{Cursor, Seek}, path::PathBuf}; +use flate2::read::GzDecoder; +use tar::Archive; + +use crate::{ftp, java, system_dirs::get_local_data_directory}; + + +pub fn check_prism() -> bool { + let path = get_local_data_directory().join("prism"); + path.exists() +} + +pub fn install_prism() -> Result<(), Box>{ + if check_prism() { + return Ok(()); + } + java::install_java(21); + let path = PathBuf::new().join("prism").join(format!("prism-{}",if env::consts::OS == "windows" {"win.zip"} else {"lin.tar.gz"})); + let size = ftp::ftp_get_size(path.clone())?; + let mut buff = Cursor::new(vec![]); + let mut total = 0; + ftp::ftp_retr(path, &mut buff, |data| { + total += data; + println!("Downloading Prism: {}MB / {}MB", total/(1024*1024), size/(1024*1024)); + }).unwrap(); + std::fs::create_dir_all(get_local_data_directory().join("prism"))?; + buff.rewind()?; + if env::consts::OS != "windows" { + let tar = GzDecoder::new(buff); + let mut archive = Archive::new(tar); + if !archive.unpack(get_local_data_directory().join("prism")).is_ok() { + std::fs::remove_dir_all(get_local_data_directory().join("prism")); + } + } else { + if !zip_extract::extract(buff, get_local_data_directory().join("prism").as_path(), true).is_ok() { + std::fs::remove_dir_all(get_local_data_directory().join("prism")); + } + } + + let buff = Cursor::new(vec![]); + ftp::ftp_retr(PathBuf, writer, callback) + + + Ok(()) +} diff --git a/FCLauncher/src-tauri/src/system_dirs.rs b/FCLauncher/src-tauri/src/system_dirs.rs new file mode 100644 index 0000000..ba67006 --- /dev/null +++ b/FCLauncher/src-tauri/src/system_dirs.rs @@ -0,0 +1,8 @@ +use std::{env, path::{Path, PathBuf}}; +use dirs::home_dir; + + + +pub fn get_local_data_directory() -> PathBuf { + dirs::data_local_dir().unwrap().join("FCLauncher") +} diff --git a/FCLauncher/src-tauri/src/util.rs b/FCLauncher/src-tauri/src/util.rs new file mode 100644 index 0000000..3195d68 --- /dev/null +++ b/FCLauncher/src-tauri/src/util.rs @@ -0,0 +1,6 @@ + +pub fn download_callback(count: usize, total: &mut usize, size: usize){ + *total += count; + println!("Downloading {}MB / {}MB", *total/(1024*1024), size/(1024*1024)); +} +