From a8046f11e551c69d1e45cd432694b4c8a04ee7b7 Mon Sep 17 00:00:00 2001 From: alyx Date: Sat, 6 Apr 2024 16:59:12 -0400 Subject: Lua dev mode functional --- src/theming/hbs.rs | 6 +++++- src/theming/lua.rs | 45 +++++++++++++++++++++++++++++++++++---------- 2 files changed, 40 insertions(+), 11 deletions(-) (limited to 'src/theming') diff --git a/src/theming/hbs.rs b/src/theming/hbs.rs index 67a2ae4..398715a 100644 --- a/src/theming/hbs.rs +++ b/src/theming/hbs.rs @@ -18,7 +18,7 @@ static HANDLEBARS: LazyLock = LazyLock::new(|| { log::info!("Registering internal handlebars theme `{key}`"); hb.register_template_string(key, fulltext).unwrap(); } - hb.set_dev_mode(CONFIG.theme_debug); + hb.set_dev_mode(CONFIG.theme_dev); if let Some(themes_dir) = CONFIG.theme_dir.as_ref() { log::info!("Registering handlebars theme dir `{themes_dir}` with extension `{}`.", CONFIG.theme_ext_hbs); @@ -34,3 +34,7 @@ pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option> = LazyLock::new(|| { lua.sandbox(true).expect("lua initialization"); lua.set_compiler( - if CONFIG.theme_debug { Compiler::new().set_optimization_level(0).set_debug_level(2) } + if CONFIG.theme_dev { Compiler::new().set_optimization_level(0).set_debug_level(2) } else { Compiler::new().set_optimization_level(2).set_debug_level(1) } ); @@ -38,14 +38,19 @@ static LUA: LazyLock> = LazyLock::new(|| { for (k, v) in INTERNAL_THEMES { log::info!("Registering compiled lua theme `{k}`."); - let _ = themes.set(*k, lua.load(*v).into_function().expect("loading internal theme")); + let _ = themes.set(*k, lua.load(*v).eval::().expect("loading internal theme")); } if let Some(theme_dir) = CONFIG.theme_dir.as_ref() { - log::info!("Registering lua theme dir `{theme_dir}` with extension `{}`.", CONFIG.theme_ext_lua); - for (k, v) in walk_dir(theme_dir.as_ref().as_ref()).expect("walking theme dir") { - log::info!("Registering runtime lua theme `{k}`."); - let _ = themes.set(k, lua.load(v).eval::().expect("loading internal theme")); + if !CONFIG.theme_dev { + log::info!("Registering lua theme dir `{theme_dir}` with extension `{}`.", CONFIG.theme_ext_lua); + for (k, v) in walk_dir(theme_dir.as_ref().as_ref()).expect("walking theme dir") { + log::info!("Registering runtime lua theme `{k}`."); + let _ = themes.set(k, lua.load(v).eval::().expect("loading external theme")); + } + } + else { + log::info!("Ready to dev-load lua themes from `{theme_dir}` with extension `{}`.", CONFIG.theme_ext_lua); } } @@ -86,13 +91,29 @@ fn walk_dir(path: &Path) -> std::io::Result> { } pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option> { + if name == ".." || name.starts_with("../") || name.ends_with("/..") || name.contains("/../") { + return Some(Err(StatusCode::BAD_REQUEST)) + } + LUA.clear_poison(); let lua = LUA.lock().expect("FIXME: Mutex poisoning race condition."); let themes: Table = lua.globals().get("__themes").unwrap(); - let Ok(Value::Function(theme)) = themes.get(name) - else { - return None; - }; + let theme; + match themes.get(name) { + Ok(Value::Function(themefn)) => { theme = themefn; }, + Ok(Value::Nil) if !CONFIG.theme_dev || CONFIG.theme_dir.is_none() => { return None; }, + Ok(Value::Nil) => { + let code = fs::read_to_string(CONFIG.theme_dir.as_ref().unwrap().to_string() + "/" + name + &CONFIG.theme_ext_lua).ok()?; + let res = lua.load(code).eval::(); + match res { + Ok(Value::Function(themefn)) => { theme = themefn; }, + Ok(v) => { log::error!("Got `{v:?}` instead of Function when dev-loading `{name}`."); return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)); }, + Err(e) => { log::error!("Error dev-loading `{name}`: {e}"); return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)); }, + } + }, + Ok(v) => { log::error!("Got `{v:?}` instead of Function when loading `{name}`."); return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)); } + Err(e) => { log::error!("Error loading `{name}`: {e}"); return Some(Err(StatusCode::INTERNAL_SERVER_ERROR)); }, //TODO: gate behind flag + } let ctx = match lua.to_value(ctx) { Ok(ok) => ok, @@ -104,3 +125,7 @@ pub fn render_theme(name: &str, ctx: &crate::ctx::Ctx) -> Option