1
Fork 0
mirror of https://github.com/redstrate/Kawari.git synced 2025-04-24 08:07:45 +00:00

Run cargo fmt

This commit is contained in:
Joshua Goins 2025-03-08 13:27:41 -05:00
parent f7a5940f20
commit 40ef6b8193
8 changed files with 171 additions and 146 deletions

View file

@ -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,10 +52,7 @@ async fn apply(Form(input): Form<Input>) -> Redirect {
config.boot_patches_location = boot_patch_location;
}
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("/")

View file

@ -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<GateStatus> {
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<GateStatus> {
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)]

View file

@ -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<Params>) -> Html<&'static str> {
Html("\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html lang=en-GB id=gb>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><form action=\"login.send\" method=\"post\" name=\"mainForm\">\r\n\t\r\n\t\t\r\n\t\t<input type=\"hidden\" name=\"_STORED_\" value=\"42f06e5f4194001a9ad61c8481f435e8b9eac79242f9221d463aa492ab2b3373655adadff3e72dd16a798ee8a222c519848743c97084f1af71854f06050a1f2813e5c3aaf66e5f0ef24dc18588a8cf06758992e42035f7e4f99f85c8b6082200dcabc6a37c7f76ce542eefc1f1798da5e23fd4b46ed17489de5eb8e8a222c5198487433bff5f3433c061ded661b3f33b5f2d2807f5db74747f4dfe8f1fe89f9388f717347bbea9e9ec2931bb6fdc4b11648dfa9e726cdf690d74970a36f7482c12593a5ad7b966c4cf14655e11641f0bb67b8e807377edfa81055480da52031e0ba86ec52f991eb3cb8913c8f807287f3cb5ac4143326f33a4503cf31e021c8f41a5eec01870e0004acc0d0bf2bed65da5eeae3703ae878c20bd7f1167745e96770979146463fa40235e6bba8bdac1273dcbc1256cda0caacbdaad\">\n\r\n\t\t\r\n\t\t<div class=\"form-item type-id\">\r\n\t\t\t<label class=\"item-label\" for=\"sqexid\"><span class=\"label-image-text\" title=\"Square Enix ID\"></span></label>\r\n\t\t\t<input class=\"item-input\" name=\"sqexid\" id=\"sqexid\" type=\"text\" value=\"\" tabindex=\"1\" placeholder=\"ID (Required)\" maxLength=\"16\"\r\n\t\t\t\r\n\t\t\t\t />\r\n\t\t\t\r\n\t\t</div>\r\n\r\n\t\t <div class=\"form-item type-pw\">\r\n\t\t\t<label class=\"item-label\" for=\"password\"><span class=\"label-image-text\" title=\"Square Enix Password\"></span></label>\r\n\t\t\t<input class=\"item-password\" name=\"password\" id=\"password\" type=\"password\" value=\"\" tabindex=\"2\" placeholder=\"Password (Required)\" maxLength=\"32\" autocomplete=\"off\"/>\r\n\t\t</div>\r\n\t\r\n\t\t<div class=\"form-item type-otpw\">\r\n\t\t\t<label class=\"item-label\" for=\"otppw\"><span class=\"label-image-text\" title=\"One-Time Password\"></span></label>\r\n\t\t\t<input class=\"item-otpw\" name=\"otppw\" id=\"otppw\" type=\"text\" value=\"\" tabindex=\"3\" autocomplete=\"off\" maxLength=\"6\" placeholder=\"Password (Optional)\" />\r\n\t\t</div>\r\n\r\n\t\t\r\n\t\t<div class=\"form-item type-remember-id\">\r\n\t\t\t<input name=\"saveid\" id=\"saveid\" type=\"checkbox\" value=\"1\" class=\"item-checkbox\" tabindex=\"4\" />\r\n\t\t\t<label class=\"item-checkbox-label\" for=\"saveid\"><span class=\"label-checkbox-image-text\" title=\"Remember Square Enix ID\"></span></label>\r\n\t\t</div>\r\n\t\t\r\n\r\n\t\t<div class=\"form-item type-submit\">\r\n\t\t\t<button class=\"item-button\" type=\"submit\" tabindex=\"5\" onClick=\"ctrEvent('mainForm')\" id=\"btLogin\"><span class=\"button-image-text\" title=\"Login\"></span></button>\r\n\t\t</div>\r\n\r\n\t</form>\r\n</div>\r\n</body>\r\n</html>\r\n\r\n</html>")
Html(
"\r\n<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">\r\n<html lang=en-GB id=gb>\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" /></head><form action=\"login.send\" method=\"post\" name=\"mainForm\">\r\n\t\r\n\t\t\r\n\t\t<input type=\"hidden\" name=\"_STORED_\" value=\"42f06e5f4194001a9ad61c8481f435e8b9eac79242f9221d463aa492ab2b3373655adadff3e72dd16a798ee8a222c519848743c97084f1af71854f06050a1f2813e5c3aaf66e5f0ef24dc18588a8cf06758992e42035f7e4f99f85c8b6082200dcabc6a37c7f76ce542eefc1f1798da5e23fd4b46ed17489de5eb8e8a222c5198487433bff5f3433c061ded661b3f33b5f2d2807f5db74747f4dfe8f1fe89f9388f717347bbea9e9ec2931bb6fdc4b11648dfa9e726cdf690d74970a36f7482c12593a5ad7b966c4cf14655e11641f0bb67b8e807377edfa81055480da52031e0ba86ec52f991eb3cb8913c8f807287f3cb5ac4143326f33a4503cf31e021c8f41a5eec01870e0004acc0d0bf2bed65da5eeae3703ae878c20bd7f1167745e96770979146463fa40235e6bba8bdac1273dcbc1256cda0caacbdaad\">\n\r\n\t\t\r\n\t\t<div class=\"form-item type-id\">\r\n\t\t\t<label class=\"item-label\" for=\"sqexid\"><span class=\"label-image-text\" title=\"Square Enix ID\"></span></label>\r\n\t\t\t<input class=\"item-input\" name=\"sqexid\" id=\"sqexid\" type=\"text\" value=\"\" tabindex=\"1\" placeholder=\"ID (Required)\" maxLength=\"16\"\r\n\t\t\t\r\n\t\t\t\t />\r\n\t\t\t\r\n\t\t</div>\r\n\r\n\t\t <div class=\"form-item type-pw\">\r\n\t\t\t<label class=\"item-label\" for=\"password\"><span class=\"label-image-text\" title=\"Square Enix Password\"></span></label>\r\n\t\t\t<input class=\"item-password\" name=\"password\" id=\"password\" type=\"password\" value=\"\" tabindex=\"2\" placeholder=\"Password (Required)\" maxLength=\"32\" autocomplete=\"off\"/>\r\n\t\t</div>\r\n\t\r\n\t\t<div class=\"form-item type-otpw\">\r\n\t\t\t<label class=\"item-label\" for=\"otppw\"><span class=\"label-image-text\" title=\"One-Time Password\"></span></label>\r\n\t\t\t<input class=\"item-otpw\" name=\"otppw\" id=\"otppw\" type=\"text\" value=\"\" tabindex=\"3\" autocomplete=\"off\" maxLength=\"6\" placeholder=\"Password (Optional)\" />\r\n\t\t</div>\r\n\r\n\t\t\r\n\t\t<div class=\"form-item type-remember-id\">\r\n\t\t\t<input name=\"saveid\" id=\"saveid\" type=\"checkbox\" value=\"1\" class=\"item-checkbox\" tabindex=\"4\" />\r\n\t\t\t<label class=\"item-checkbox-label\" for=\"saveid\"><span class=\"label-checkbox-image-text\" title=\"Remember Square Enix ID\"></span></label>\r\n\t\t</div>\r\n\t\t\r\n\r\n\t\t<div class=\"form-item type-submit\">\r\n\t\t\t<button class=\"item-button\" type=\"submit\" tabindex=\"5\" onClick=\"ctrEvent('mainForm')\" id=\"btLogin\"><span class=\"button-image-text\" title=\"Login\"></span></button>\r\n\t\t</div>\r\n\r\n\t</form>\r\n</div>\r\n</body>\r\n</html>\r\n\r\n</html>",
)
}
#[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<Input>) -> Html<String> {
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]

View file

@ -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<String> {
// 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<String> {
.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,8 +101,7 @@ 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 {
patches: vec![PatchEntry {
url: format!("http://{}", patch).to_string(),
version: "2023.09.15.0000.0000".to_string(),
hash_block_size: 50000000,
@ -95,8 +110,7 @@ async fn verify_boot(Path((platform, boot_version)): Path<(String, String)>) ->
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);

View file

@ -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<String> {
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<String> {
@ -30,7 +26,7 @@ async fn login() -> Html<String> {
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<String> {
@ -38,7 +34,7 @@ async fn register() -> Html<String> {
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<String> {
@ -46,7 +42,11 @@ async fn world_status() -> Html<String> {
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<Input>) -> 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("/")

View file

@ -12,7 +12,7 @@ pub struct Config {
pub supported_platforms: Vec<String>,
#[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(),
}
}
}

View file

@ -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
}

View file

@ -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<PatchEntry>
pub patches: Vec<PatchEntry>,
}
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(),
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
}
]
unknown_b: 18,
}],
};
assert_eq!(patch_list.to_string(), test_case);
@ -153,9 +160,9 @@ 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(),
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,
@ -192,10 +199,9 @@ mod tests {
"4561eb6f954d80cdb1ece3cc4d58cbd864bf2b50".to_string(),
"de94175c4db39a11d5334aefc7a99434eea8e4f9".to_string(),
"55dd7215f24441d6e47d1f9b32cebdb041f2157f".to_string(),
"2ca09db645cfeefa41a04251dfcb13587418347a".to_string()
"2ca09db645cfeefa41a04251dfcb13587418347a".to_string(),
],
}
]
}],
};
assert_eq!(patch_list.to_string(), test_case);