mirror of
https://github.com/BeamMP/BeamMP-Server.git
synced 2025-07-03 16:25:35 +00:00
Merge pull request #12 from lionkor/overhaul-resources-folder-code
Overhaul resources folder code
This commit is contained in:
commit
145b74aefc
@ -1,5 +1,7 @@
|
|||||||
|
use std::path::{Path, PathBuf};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
use crate::fs_util;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
@ -47,10 +49,26 @@ pub struct GeneralSettings {
|
|||||||
|
|
||||||
impl GeneralSettings {
|
impl GeneralSettings {
|
||||||
pub fn is_auth_key_valid(&self) -> bool {
|
pub fn is_auth_key_valid(&self) -> bool {
|
||||||
return if let Some(auth_key) = &self.auth_key {
|
if let Some(auth_key) = &self.auth_key {
|
||||||
Uuid::parse_str(auth_key.as_str()).is_ok()
|
Uuid::parse_str(auth_key.as_str()).is_ok()
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
/// Returns the client resource path, and ensures it exists.
|
||||||
|
/// Default is Resources/Client.
|
||||||
|
pub fn get_client_resource_folder(&self) -> anyhow::Result<String> {
|
||||||
|
let res_client_path = Path::new(self.resource_folder.as_str()).join("Client");
|
||||||
|
fs_util::ensure_path_exists(&res_client_path)?;
|
||||||
|
Ok(fs_util::path_to_string(res_client_path))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns the server resource path, and ensures it exists.
|
||||||
|
/// Default is Resources/Server.
|
||||||
|
pub fn get_server_resource_folder(&self) -> anyhow::Result<String> {
|
||||||
|
let res_server_path = Path::new(self.resource_folder.as_str()).join("Server");
|
||||||
|
fs_util::ensure_path_exists(&res_server_path)?;
|
||||||
|
Ok(fs_util::path_to_string(res_server_path))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
22
src/fs_util.rs
Normal file
22
src/fs_util.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
|
||||||
|
/// Ensures the given path exists by creating it if it doesn't.
|
||||||
|
pub fn ensure_path_exists(path: &PathBuf) -> anyhow::Result<()> {
|
||||||
|
if !path.exists() {
|
||||||
|
debug!("Path {:?} doesn't exist, creating it", path);
|
||||||
|
std::fs::create_dir_all(path)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Joins a parent folder and a sub-path, resolving the subpath beforehand to ensure that
|
||||||
|
/// the resulting path is still within the parent folder, regardless of ".." in the sub-path.
|
||||||
|
pub fn join_path_secure(parent: &Path, sub: &Path) -> anyhow::Result<PathBuf> {
|
||||||
|
Ok(parent.join(sub.canonicalize()?.as_path()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts a PathBuf into a String in a lossy way. This is generally the way we want to do it
|
||||||
|
/// in the server.
|
||||||
|
pub fn path_to_string(path: PathBuf) -> String {
|
||||||
|
path.into_os_string().to_string_lossy().to_string()
|
||||||
|
}
|
10
src/main.rs
10
src/main.rs
@ -2,6 +2,7 @@
|
|||||||
#[macro_use] extern crate async_trait;
|
#[macro_use] extern crate async_trait;
|
||||||
#[macro_use] extern crate lazy_static;
|
#[macro_use] extern crate lazy_static;
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
use argh::FromArgs;
|
use argh::FromArgs;
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
@ -12,6 +13,7 @@ mod tui;
|
|||||||
mod server;
|
mod server;
|
||||||
mod config;
|
mod config;
|
||||||
mod heartbeat;
|
mod heartbeat;
|
||||||
|
mod fs_util;
|
||||||
|
|
||||||
#[derive(FromArgs)]
|
#[derive(FromArgs)]
|
||||||
/// BeamMP Server v3.3.0
|
/// BeamMP Server v3.3.0
|
||||||
@ -40,8 +42,12 @@ async fn main() {
|
|||||||
.map_err(|_| error!("Failed to parse config file!"))
|
.map_err(|_| error!("Failed to parse config file!"))
|
||||||
.expect("Failed to parse config file!");
|
.expect("Failed to parse config file!");
|
||||||
|
|
||||||
// TODO: This should not error lol
|
|
||||||
for entry in std::fs::read_dir("Resources/Client").expect("Failed to read Resources/Client!") {
|
let client_resources = user_config.general
|
||||||
|
.get_client_resource_folder()
|
||||||
|
.expect("Failed to create the client resource folder");
|
||||||
|
|
||||||
|
for entry in std::fs::read_dir(client_resources).expect("Failed to read client resource folder!") {
|
||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
if entry.path().is_file() {
|
if entry.path().is_file() {
|
||||||
if let Ok(metadata) = entry.metadata() {
|
if let Ok(metadata) = entry.metadata() {
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::net::SocketAddr;
|
use std::net::SocketAddr;
|
||||||
use std::ops::DerefMut;
|
use std::ops::DerefMut;
|
||||||
|
use std::path::Path;
|
||||||
use std::sync::atomic::{AtomicU8, Ordering};
|
use std::sync::atomic::{AtomicU8, Ordering};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::time::Instant;
|
use std::time::Instant;
|
||||||
@ -18,6 +19,7 @@ use nalgebra::*;
|
|||||||
|
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use serde_aux::prelude::*;
|
use serde_aux::prelude::*;
|
||||||
|
use crate::fs_util;
|
||||||
|
|
||||||
use super::backend::*;
|
use super::backend::*;
|
||||||
use super::car::*;
|
use super::car::*;
|
||||||
@ -225,21 +227,13 @@ impl Client {
|
|||||||
// Handle file download
|
// Handle file download
|
||||||
let mut mod_name = packet.data_as_string().clone();
|
let mut mod_name = packet.data_as_string().clone();
|
||||||
mod_name.remove(0); // Remove f
|
mod_name.remove(0); // Remove f
|
||||||
debug!("Client requested file {}", mod_name);
|
debug!("Client is requesting file {}", mod_name);
|
||||||
|
|
||||||
// making sure that the requested file cant point to files outside of Resources/Client/*
|
let client_resources = config.general.get_server_resource_folder()?;
|
||||||
let path = std::path::Path::new(&mod_name);
|
let mod_path = fs_util::join_path_secure(Path::new(&client_resources), Path::new(&mod_name))?;
|
||||||
let mod_name = match path.file_name() {
|
|
||||||
Some(v) => "/".to_string() + v.to_str().unwrap(),
|
if !mod_path.exists() || !mod_path.is_file() {
|
||||||
None => {
|
error!("Client requested mod which doesn't exist: {:?}. Disconnecting", mod_path);
|
||||||
error!("Client requests invalid mod. Disconnecting");
|
|
||||||
self.kick("Invalid mod request").await;
|
|
||||||
return Ok(());
|
|
||||||
}, // client requested path (fResources/Client/) or nothing at all (f) - invalid
|
|
||||||
};
|
|
||||||
let mod_path = format!("Resources/Client{mod_name}");
|
|
||||||
if !std::path::Path::new(&mod_path).exists() {
|
|
||||||
error!("Client requests inexistent mod. Disconnecting");
|
|
||||||
self.kick("Invalid mod request").await;
|
self.kick("Invalid mod request").await;
|
||||||
return Ok(()) // client requested mod that doesnt exists within "Resources/Client/*"
|
return Ok(()) // client requested mod that doesnt exists within "Resources/Client/*"
|
||||||
}
|
}
|
||||||
|
@ -27,11 +27,12 @@ pub use plugins::*;
|
|||||||
pub use http::*;
|
pub use http::*;
|
||||||
|
|
||||||
pub use crate::config::Config;
|
pub use crate::config::Config;
|
||||||
|
use crate::config::GeneralSettings;
|
||||||
|
|
||||||
fn load_plugins() -> Vec<Plugin> {
|
fn load_plugins(server_resource_folder: String) -> Vec<Plugin> {
|
||||||
let mut plugins = Vec::new();
|
let mut plugins = Vec::new();
|
||||||
|
|
||||||
for res_entry in std::fs::read_dir("Resources/Server").expect("Failed to read Resources/Server!") {
|
for res_entry in std::fs::read_dir(server_resource_folder).expect("Failed to read server resource folder!") {
|
||||||
if let Ok(res_entry) = res_entry {
|
if let Ok(res_entry) = res_entry {
|
||||||
let res_path = res_entry.path();
|
let res_path = res_entry.path();
|
||||||
if res_path.is_dir() {
|
if res_path.is_dir() {
|
||||||
@ -158,8 +159,12 @@ impl Server {
|
|||||||
Arc::new(UdpSocket::bind(bind_addr).await?)
|
Arc::new(UdpSocket::bind(bind_addr).await?)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let server_resource_folder = config.general
|
||||||
|
.get_server_resource_folder()
|
||||||
|
.expect("Failed to create the server resource folder");
|
||||||
|
|
||||||
// Load existing plugins
|
// Load existing plugins
|
||||||
let plugins = load_plugins();
|
let plugins = load_plugins(server_resource_folder);
|
||||||
|
|
||||||
// Start client runtime
|
// Start client runtime
|
||||||
let (clients_incoming_tx, clients_incoming_rx) = mpsc::channel(100);
|
let (clients_incoming_tx, clients_incoming_rx) = mpsc::channel(100);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user