diff --git a/src/bin/kawari-admin.rs b/src/bin/kawari-admin.rs index d20e8b7..3c03ecf 100644 --- a/src/bin/kawari-admin.rs +++ b/src/bin/kawari-admin.rs @@ -1,16 +1,12 @@ use std::net::SocketAddr; -use axum::{ - Json, - Router, routing::get, - extract::Form -}; -use serde::{Deserialize, Serialize}; use axum::response::{Html, Redirect}; use axum::routing::post; +use axum::{Json, Router, extract::Form, routing::get}; use kawari::config::{Config, get_config}; -use minijinja::{Environment, context}; use kawari::setup_default_environment; +use minijinja::{Environment, context}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] struct GateStatus { @@ -56,11 +52,8 @@ async fn apply(Form(input): Form) -> Redirect { config.boot_patches_location = boot_patch_location; } - serde_json::to_writer( - &std::fs::File::create("config.json").unwrap(), - &config, - ) - .expect("TODO: panic message"); + serde_json::to_writer(&std::fs::File::create("config.json").unwrap(), &config) + .expect("TODO: panic message"); Redirect::to("/") } @@ -79,4 +72,4 @@ async fn main() { .serve(app.into_make_service()) .await .unwrap(); -} \ No newline at end of file +} diff --git a/src/bin/kawari-frontier.rs b/src/bin/kawari-frontier.rs index dff4ce9..a2a343c 100644 --- a/src/bin/kawari-frontier.rs +++ b/src/bin/kawari-frontier.rs @@ -1,11 +1,8 @@ use std::net::SocketAddr; -use axum::{ - Json, - Router, routing::get, -}; -use serde::{Deserialize, Serialize}; +use axum::{Json, Router, routing::get}; use kawari::config::{Config, get_config}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] struct GateStatus { @@ -17,7 +14,7 @@ async fn get_login_status() -> Json { let config = get_config(); Json(GateStatus { - status: config.login_open.into() + status: config.login_open.into(), }) } @@ -26,14 +23,14 @@ async fn get_world_status() -> Json { let config = get_config(); Json(GateStatus { - status: config.login_open.into() + status: config.login_open.into(), }) } #[derive(Debug, Clone, Serialize, Deserialize)] struct Banner { link: String, - lsb_banner: String + lsb_banner: String, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -42,7 +39,7 @@ struct NewsItem { id: String, tag: String, title: String, - url: String + url: String, } #[derive(Debug, Clone, Serialize, Deserialize)] @@ -85,4 +82,4 @@ async fn main() { .serve(app.into_make_service()) .await .unwrap(); -} \ No newline at end of file +} diff --git a/src/bin/kawari-login.rs b/src/bin/kawari-login.rs index 99ba5af..c92dc99 100644 --- a/src/bin/kawari-login.rs +++ b/src/bin/kawari-login.rs @@ -1,13 +1,13 @@ use std::net::SocketAddr; -use axum::{Form, Router, routing::get}; use axum::extract::Query; use axum::response::Html; use axum::routing::post; -use rand::distributions::Alphanumeric; -use rand::Rng; -use serde::Deserialize; +use axum::{Form, Router, routing::get}; use kawari::generate_sid; +use rand::Rng; +use rand::distributions::Alphanumeric; +use serde::Deserialize; #[derive(Deserialize)] #[allow(dead_code)] @@ -17,11 +17,13 @@ struct Params { isft: String, cssmode: String, isnew: String, - launchver: String + launchver: String, } async fn top(Query(params): Query) -> Html<&'static str> { - Html("\r\n\r\n\r\n\r\n
\r\n\t\r\n\t\t\r\n\t\t\n\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\r\n\t\t
\r\n\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\r\n\t\t
\r\n\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\r\n\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\r\n\t
\r\n\r\n\r\n\r\n\r\n") + Html( + "\r\n\r\n\r\n\r\n
\r\n\t\r\n\t\t\r\n\t\t\n\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\r\n\t\t
\r\n\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\r\n\t\t
\r\n\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\r\n\t\t\r\n\t\t
\r\n\t\t\t\r\n\t\t\t\r\n\t\t
\r\n\t\t\r\n\r\n\t\t
\r\n\t\t\t\r\n\t\t
\r\n\r\n\t
\r\n\r\n\r\n\r\n\r\n", + ) } #[derive(Deserialize, Debug)] @@ -30,12 +32,14 @@ struct Input { _STORED_: String, sqexid: String, password: String, - otppw: String + otppw: String, } -async fn login_send(Form(input): Form) -> Html { +async fn login_send(Form(input): Form) -> Html { let sid = generate_sid(); - Html(format!("window.external.user(\"login=auth,ok,sid,{sid},terms,1,region,2,etmadd,0,playable,1,ps3pkg,0,maxex,4,product,1\");")) + Html(format!( + "window.external.user(\"login=auth,ok,sid,{sid},terms,1,region,2,etmadd,0,playable,1,ps3pkg,0,maxex,4,product,1\");" + )) } #[tokio::main] @@ -52,4 +56,4 @@ async fn main() { .serve(app.into_make_service()) .await .unwrap(); -} \ No newline at end of file +} diff --git a/src/bin/kawari-patch.rs b/src/bin/kawari-patch.rs index 0f866d8..9412660 100644 --- a/src/bin/kawari-patch.rs +++ b/src/bin/kawari-patch.rs @@ -2,22 +2,22 @@ use std::cmp::Ordering; use std::fs::read_dir; use std::net::SocketAddr; -use axum::{Form, Json, Router, routing::get}; -use axum::extract::Query; -use axum::response::Html; -use axum::routing::post; -use serde::{Deserialize, Serialize}; -use kawari::config::{Config, get_config}; use axum::extract::Path; -use axum::response::IntoResponse; +use axum::extract::Query; use axum::http::{HeaderMap, StatusCode}; -use minijinja::filters::list; +use axum::response::Html; +use axum::response::IntoResponse; +use axum::routing::post; +use axum::{Form, Json, Router, routing::get}; +use kawari::config::{Config, get_config}; use kawari::patchlist::{PatchEntry, PatchList, PatchType}; +use minijinja::filters::list; +use serde::{Deserialize, Serialize}; fn list_patch_files(dir_path: &str) -> Vec { // If the dir doesn't exist, pretend there is no patch files let Ok(dir) = read_dir(dir_path) else { - return Vec::new() + return Vec::new(); }; let mut entries: Vec<_> = dir.flatten().collect(); entries.sort_by_key(|dir| dir.path()); @@ -38,20 +38,37 @@ fn list_patch_files(dir_path: &str) -> Vec { .collect(); game_patches.sort_by(|a, b| { // Ignore H/D in front of filenames - let mut a_path = a.as_path().file_name().unwrap().to_str().unwrap().to_string(); + let mut a_path = a + .as_path() + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string(); if a_path.starts_with("H") { return Ordering::Less; } - let mut b_path = b.as_path().file_name().unwrap().to_str().unwrap().to_string(); + let mut b_path = b + .as_path() + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string(); /*if b_path.starts_with("H") { return Ordering::Greater; }*/ a_path.partial_cmp(&b_path).unwrap() }); // ensure we're actually installing them in the correct order - game_patches.iter().map(|x| x.file_stem().unwrap().to_str().unwrap().to_string() ).collect() + game_patches + .iter() + .map(|x| x.file_stem().unwrap().to_str().unwrap().to_string()) + .collect() } -async fn verify_session(Path((platform, game_version, sid)): Path<(String, String, String)>) -> impl IntoResponse { +async fn verify_session( + Path((platform, game_version, sid)): Path<(String, String, String)>, +) -> impl IntoResponse { let config = get_config(); if !config.supports_platform(&platform) { return StatusCode::INTERNAL_SERVER_ERROR.into_response(); @@ -63,7 +80,6 @@ async fn verify_session(Path((platform, game_version, sid)): Path<(String, Strin (headers).into_response() } - async fn verify_boot(Path((platform, boot_version)): Path<(String, String)>) -> impl IntoResponse { tracing::info!("Verifying boot components..."); @@ -85,18 +101,16 @@ async fn verify_boot(Path((platform, boot_version)): Path<(String, String)>) -> id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(), patch_type: PatchType::Boot, requested_version: boot_version.clone(), - patches: vec![ - PatchEntry { - url: format!("http://{}", patch).to_string(), - version: "2023.09.15.0000.0000".to_string(), - hash_block_size: 50000000, - length: 1479062470, - size_on_disk: 0, - hashes: vec![], - unknown_a: 0, - unknown_b: 0, - } - ] + patches: vec![PatchEntry { + url: format!("http://{}", patch).to_string(), + version: "2023.09.15.0000.0000".to_string(), + hash_block_size: 50000000, + length: 1479062470, + size_on_disk: 0, + hashes: vec![], + unknown_a: 0, + unknown_b: 0, + }], }; let patch_list_str = patch_list.to_string(); return patch_list_str.into_response(); @@ -112,8 +126,14 @@ async fn main() { tracing_subscriber::fmt::init(); let app = Router::new() - .route("/http/:platform/ffxivneo_release_game/:game_version/:sid", post(verify_session)) - .route("/http/:platform/ffxivneo_release_boot/*boot_version", get(verify_boot)); // NOTE: for future programmers, this is a wildcard because axum hates the /version/?time=blah format. + .route( + "/http/:platform/ffxivneo_release_game/:game_version/:sid", + post(verify_session), + ) + .route( + "/http/:platform/ffxivneo_release_boot/*boot_version", + get(verify_boot), + ); // NOTE: for future programmers, this is a wildcard because axum hates the /version/?time=blah format. let addr = SocketAddr::from(([127, 0, 0, 1], 6900)); tracing::info!("Patch server started on {}", addr); diff --git a/src/bin/kawari-web.rs b/src/bin/kawari-web.rs index 31786bb..4b06c19 100644 --- a/src/bin/kawari-web.rs +++ b/src/bin/kawari-web.rs @@ -1,16 +1,12 @@ use std::net::SocketAddr; -use axum::{ - Json, - Router, routing::get, - extract::Form -}; -use serde::{Deserialize, Serialize}; use axum::response::{Html, Redirect}; use axum::routing::post; +use axum::{Json, Router, extract::Form, routing::get}; use kawari::config::{Config, get_config}; -use minijinja::{Environment, context}; use kawari::setup_default_environment; +use minijinja::{Environment, context}; +use serde::{Deserialize, Serialize}; #[derive(Debug, Clone, Serialize, Deserialize)] struct GateStatus { @@ -22,7 +18,7 @@ async fn root() -> Html { let environment = setup_default_environment(); let template = environment.get_template("web.html").unwrap(); - Html(template.render(context! { }).unwrap()) + Html(template.render(context! {}).unwrap()) } async fn login() -> Html { @@ -30,7 +26,7 @@ async fn login() -> Html { let environment = setup_default_environment(); let template = environment.get_template("login.html").unwrap(); - Html(template.render(context! { }).unwrap()) + Html(template.render(context! {}).unwrap()) } async fn register() -> Html { @@ -38,7 +34,7 @@ async fn register() -> Html { let environment = setup_default_environment(); let template = environment.get_template("register.html").unwrap(); - Html(template.render(context! { }).unwrap()) + Html(template.render(context! {}).unwrap()) } async fn world_status() -> Html { @@ -46,7 +42,11 @@ async fn world_status() -> Html { let environment = setup_default_environment(); let template = environment.get_template("worldstatus.html").unwrap(); - Html(template.render(context! { login_open => config.login_open, worlds_open => config.worlds_open }).unwrap()) + Html( + template + .render(context! { login_open => config.login_open, worlds_open => config.worlds_open }) + .unwrap(), + ) } #[derive(Deserialize, Debug)] @@ -60,10 +60,7 @@ async fn apply(Form(input): Form) -> Redirect { let mut config = get_config(); - serde_json::to_writer( - &std::fs::File::create("config.json").unwrap(), - &config, - ) + serde_json::to_writer(&std::fs::File::create("config.json").unwrap(), &config) .expect("TODO: panic message"); Redirect::to("/") @@ -86,4 +83,4 @@ async fn main() { .serve(app.into_make_service()) .await .unwrap(); -} \ No newline at end of file +} diff --git a/src/config.rs b/src/config.rs index e081cd0..b813f01 100644 --- a/src/config.rs +++ b/src/config.rs @@ -12,7 +12,7 @@ pub struct Config { pub supported_platforms: Vec, #[serde(default)] - pub boot_patches_location: String + pub boot_patches_location: String, } impl Default for Config { @@ -21,7 +21,7 @@ impl Default for Config { worlds_open: false, login_open: false, boot_patches_location: String::new(), - supported_platforms: default_supported_platforms() + supported_platforms: default_supported_platforms(), } } } @@ -42,4 +42,4 @@ pub fn get_config() -> Config { } else { Config::default() } -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index 94bbc63..4567360 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,6 +1,6 @@ use minijinja::Environment; -use rand::distributions::Alphanumeric; use rand::Rng; +use rand::distributions::Alphanumeric; pub mod config; pub mod patchlist; @@ -16,11 +16,19 @@ pub fn generate_sid() -> String { pub fn setup_default_environment() -> Environment<'static> { let mut env = Environment::new(); - env.add_template("admin.html", include_str!("../templates/admin.html")).unwrap(); - env.add_template("web.html", include_str!("../templates/web.html")).unwrap(); - env.add_template("login.html", include_str!("../templates/login.html")).unwrap(); - env.add_template("register.html", include_str!("../templates/register.html")).unwrap(); - env.add_template("worldstatus.html", include_str!("../templates/worldstatus.html")).unwrap(); + env.add_template("admin.html", include_str!("../templates/admin.html")) + .unwrap(); + env.add_template("web.html", include_str!("../templates/web.html")) + .unwrap(); + env.add_template("login.html", include_str!("../templates/login.html")) + .unwrap(); + env.add_template("register.html", include_str!("../templates/register.html")) + .unwrap(); + env.add_template( + "worldstatus.html", + include_str!("../templates/worldstatus.html"), + ) + .unwrap(); env -} \ No newline at end of file +} diff --git a/src/patchlist.rs b/src/patchlist.rs index 36477a8..22a43aa 100644 --- a/src/patchlist.rs +++ b/src/patchlist.rs @@ -14,7 +14,7 @@ pub enum PatchType { /// Corresponds to 4e9a232b Boot, /// Corresponds to 2b5cbc63 - Game + Game, } pub struct PatchList { @@ -22,7 +22,7 @@ pub struct PatchList { pub id: String, pub patch_type: PatchType, pub requested_version: String, - pub patches: Vec + pub patches: Vec, } impl PatchList { @@ -34,7 +34,15 @@ impl PatchList { str.push_str(&self.id); str.push_str("\r\n"); str.push_str("Content-Type: application/octet-stream\r\n"); - str.push_str(&format!("Content-Location: ffxivpatch/{}/metainfo/{}.http\r\n", if self.patch_type == PatchType::Boot { "2b5cbc63" } else { "4e9a232b" }, self.requested_version)); + str.push_str(&format!( + "Content-Location: ffxivpatch/{}/metainfo/{}.http\r\n", + if self.patch_type == PatchType::Boot { + "2b5cbc63" + } else { + "4e9a232b" + }, + self.requested_version + )); let mut total_patch_size = 0; for patch in &self.patches { @@ -115,18 +123,17 @@ mod tests { id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(), requested_version: "D2023.04.28.0000.0001".to_string(), patch_type: PatchType::Boot, - patches: vec![ - PatchEntry { - url: "http://patch-dl.ffxiv.com/boot/2b5cbc63/D2023.09.14.0000.0001.patch".to_string(), - version: "2023.09.14.0000.0001".to_string(), - hash_block_size: 0, - length: 22221335, - size_on_disk: 69674819, - hashes: vec![], - unknown_a: 19, - unknown_b: 18 - } - ] + patches: vec![PatchEntry { + url: "http://patch-dl.ffxiv.com/boot/2b5cbc63/D2023.09.14.0000.0001.patch" + .to_string(), + version: "2023.09.14.0000.0001".to_string(), + hash_block_size: 0, + length: 22221335, + size_on_disk: 69674819, + hashes: vec![], + unknown_a: 19, + unknown_b: 18, + }], }; assert_eq!(patch_list.to_string(), test_case); @@ -153,51 +160,50 @@ mod tests { id: "477D80B1_38BC_41d4_8B48_5273ADB89CAC".to_string(), requested_version: "2023.07.26.0000.0000".to_string(), patch_type: PatchType::Game, - patches: vec![ - PatchEntry { - url: "http://patch-dl.ffxiv.com/game/4e9a232b/D2023.09.15.0000.0000.patch".to_string(), - version: "2023.09.15.0000.0000".to_string(), - hash_block_size: 50000000, - length: 1479062470, - size_on_disk: 44145529682, - unknown_a: 71, - unknown_b: 11, - hashes: vec![ - "1c66becde2a8cf26a99d0fc7c06f15f8bab2d87c".to_string(), - "950725418366c965d824228bf20f0496f81e0b9a".to_string(), - "cabef48f7bf00fbf18b72843bdae2f61582ad264".to_string(), - "53608de567b52f5fdb43fdb8b623156317e26704".to_string(), - "f0bc06cabf9ff6490f36114b25f62619d594dbe8".to_string(), - "3c5e4b962cd8445bd9ee29011ecdb331d108abd8".to_string(), - "88e1a2a322f09de3dc28173d4130a2829950d4e0".to_string(), - "1040667917dc99b9215dfccff0e458c2e8a724a8".to_string(), - "149c7e20e9e3e376377a130e0526b35fd7f43df2".to_string(), - "1bb4e33807355cdf46af93ce828b6e145a9a8795".to_string(), - "a79daff43db488f087da8e22bb4c21fd3a390f3c".to_string(), - "6b04fadb656d467fb8318eba1c7f5ee8f030d967".to_string(), - "a6641e1c894db961a49b70fda2b0d6d87be487a7".to_string(), - "edf419de49f42ef19bd6814f8184b35a25e9e977".to_string(), - "c1525c4df6001b66b575e2891db0284dc3a16566".to_string(), - "01b7628095b07fa3c9c1aed2d66d32d118020321".to_string(), - "991b137ea0ebb11bd668f82149bc2392a4cbcf52".to_string(), - "ad3f74d4fca143a6cf507fc859544a4bcd501d85".to_string(), - "936a0f1711e273519cae6b2da0d8b435fe6aa020".to_string(), - "023f19d8d8b3ecaaf865e3170e8243dd437a384c".to_string(), - "2d9e934de152956961a849e81912ca8d848265ca".to_string(), - "8e32f9aa76c95c60a9dbe0967aee5792b812d5ec".to_string(), - "dee052b9aa1cc8863efd61afc63ac3c2d56f9acc".to_string(), - "fa81225aea53fa13a9bae1e8e02dea07de6d7052".to_string(), - "59b24693b1b62ea1660bc6f96a61f7d41b3f7878".to_string(), - "349b691db1853f6c0120a8e66093c763ba6e3671".to_string(), - "4561eb6f954d80cdb1ece3cc4d58cbd864bf2b50".to_string(), - "de94175c4db39a11d5334aefc7a99434eea8e4f9".to_string(), - "55dd7215f24441d6e47d1f9b32cebdb041f2157f".to_string(), - "2ca09db645cfeefa41a04251dfcb13587418347a".to_string() - ], - } - ] + patches: vec![PatchEntry { + url: "http://patch-dl.ffxiv.com/game/4e9a232b/D2023.09.15.0000.0000.patch" + .to_string(), + version: "2023.09.15.0000.0000".to_string(), + hash_block_size: 50000000, + length: 1479062470, + size_on_disk: 44145529682, + unknown_a: 71, + unknown_b: 11, + hashes: vec![ + "1c66becde2a8cf26a99d0fc7c06f15f8bab2d87c".to_string(), + "950725418366c965d824228bf20f0496f81e0b9a".to_string(), + "cabef48f7bf00fbf18b72843bdae2f61582ad264".to_string(), + "53608de567b52f5fdb43fdb8b623156317e26704".to_string(), + "f0bc06cabf9ff6490f36114b25f62619d594dbe8".to_string(), + "3c5e4b962cd8445bd9ee29011ecdb331d108abd8".to_string(), + "88e1a2a322f09de3dc28173d4130a2829950d4e0".to_string(), + "1040667917dc99b9215dfccff0e458c2e8a724a8".to_string(), + "149c7e20e9e3e376377a130e0526b35fd7f43df2".to_string(), + "1bb4e33807355cdf46af93ce828b6e145a9a8795".to_string(), + "a79daff43db488f087da8e22bb4c21fd3a390f3c".to_string(), + "6b04fadb656d467fb8318eba1c7f5ee8f030d967".to_string(), + "a6641e1c894db961a49b70fda2b0d6d87be487a7".to_string(), + "edf419de49f42ef19bd6814f8184b35a25e9e977".to_string(), + "c1525c4df6001b66b575e2891db0284dc3a16566".to_string(), + "01b7628095b07fa3c9c1aed2d66d32d118020321".to_string(), + "991b137ea0ebb11bd668f82149bc2392a4cbcf52".to_string(), + "ad3f74d4fca143a6cf507fc859544a4bcd501d85".to_string(), + "936a0f1711e273519cae6b2da0d8b435fe6aa020".to_string(), + "023f19d8d8b3ecaaf865e3170e8243dd437a384c".to_string(), + "2d9e934de152956961a849e81912ca8d848265ca".to_string(), + "8e32f9aa76c95c60a9dbe0967aee5792b812d5ec".to_string(), + "dee052b9aa1cc8863efd61afc63ac3c2d56f9acc".to_string(), + "fa81225aea53fa13a9bae1e8e02dea07de6d7052".to_string(), + "59b24693b1b62ea1660bc6f96a61f7d41b3f7878".to_string(), + "349b691db1853f6c0120a8e66093c763ba6e3671".to_string(), + "4561eb6f954d80cdb1ece3cc4d58cbd864bf2b50".to_string(), + "de94175c4db39a11d5334aefc7a99434eea8e4f9".to_string(), + "55dd7215f24441d6e47d1f9b32cebdb041f2157f".to_string(), + "2ca09db645cfeefa41a04251dfcb13587418347a".to_string(), + ], + }], }; assert_eq!(patch_list.to_string(), test_case); } -} \ No newline at end of file +}