mintrt 0.1.1

Security-featured runtime for lua.
//     <<*>> Revenge of snowflake.
//     -^v-  SASWE
//     @ This source code is licensed under a dual license model:
//       1. MPL-2.0 for non-commercial use only
//       2. Commercial License for commercial use
//       See LICENSE and LICENSE_COMMERCIAL files for details.
use log::trace;
use mlua::Lua;
use crate::config::{entity_ro, Dandelion};

use crate::{dynload, security, transmit};
use crate::dynload::runtime;
use crate::security::detailed_restrict::enable_detailed_restrict_fio;
use crate::security::env_modify;
use crate::security::env_modify::LuaApis;


pub fn init_runtime(entity: &entity_ro, flags: Vec<String>) -> Result<(), mlua::Error> {
    // 1 初始化运行环境
    let lua = Lua::new();

    //加载用户自定义模块(在这之前加载防御没有意义,因为dll本身就能让我所有的措施形同虚设)
    let work_path = &entity.pkg_path;
    let pkg = Dandelion::autofill(work_path);
    trace!("限制模块加载路径");
    dynload::restrict_module_load_path(&pkg, &lua)?;
    trace!("加载用户 mint 或 wing 模块");
        
    // 调试:打印 package.path
    let package_path: String = lua.globals().get("package.path").unwrap_or_default();
    let package_cpath: String = lua.globals().get("package.cpath").unwrap_or_default();
    log::trace!("package.path: {}", package_path);
    log::trace!("package.cpath: {}", package_cpath);
    lua.load(dynload::generate_lua_script_for_lib_loading(entity.lua_access_no_suffix.clone())).exec()?;
    trace!("加载 lua 的 c 拓展");
    lua.load(dynload::generate_lua_script_for_lib_loading(entity.native_access_no_suffix.clone())).exec()?;
    //

    //准备做自定义模块的限制

    // 检测与加载用户脚本
    //1 加载 Executor
    // 安全:检查是否有 main 里的函数调用
    if !security::check_exec::check_executable_lua_file(&entity.executor_script_or_compiled) {
        eprintln!("[ERROR] Executor 不可执行:{}", &entity.executor_script_or_compiled);
        std::process::exit(1);
    }
    // 直接加载 executor 字节码文件并执行
    let executor_bytecode = std::fs::read(&entity.executor_script_or_compiled).unwrap_or_else(|e| {
        eprintln!("[ERROR] 读取 executor 字节码失败:{}", e);
        std::process::exit(1);
    });
    log::info!("Loading executor bytecode from: {}", &entity.executor_script_or_compiled);
    lua.load(executor_bytecode).exec().unwrap_or_else(|e| {
        eprintln!("[ERROR] 执行 executor 字节码失败:{}", e);
        std::process::exit(1);
    });
    log::info!("Executor loaded successfully");
    
    //安全设置:hook
    log::debug!("About to call batch_hook_sec...");
    let hook_task = security::generate_basic_ctrl_hook_task(&entity.basic_authority);//用户配置
    env_modify::batch_hook_sec(&lua, hook_task).unwrap_or_else(|e| {
        eprintln!("[ERROR] batch_hook_sec 失败:{}", e);
        std::process::exit(1);
    });
    log::debug!("batch_hook_sec completed");

    //hook 命令执行与文件访问权限细化控制
    enable_detailed_restrict_fio(&lua, &entity.file_access_allow, &entity.command_allow).unwrap_or_else(|e| {
        eprintln!("[ERROR] 启用详细限制失败:{}", e);
        std::process::exit(1);
    });

    // 安全设置:禁用运行时加载模块
    // Fuck guys who try to bypass the security policy.
    env_modify::deny_module_except(&lua, LuaApis::new()).unwrap_or_else(|e| {
        eprintln!("[ERROR] 禁用模块失败:{}", e);
        std::process::exit(1);
    });

    //加载要暴露给 lua 环境的 api,包括重要的 runtime.log.{trace, info, warn, error}
    let rt_log_mod = lua.create_table()?;
    // 通义添加:Option<String> 返回给 Lua - nil 成功,string 错误
    rt_log_mod.set("info", lua.create_function(|_, loginfo: String| -> Result<Option<String>, mlua::Error> {
        Ok(crate::dynload::runtime::log::log_info(loginfo))
    })?)?;
    rt_log_mod.set("warn", lua.create_function(|_, loginfo: String| -> Result<Option<String>, mlua::Error> {
        Ok(crate::dynload::runtime::log::log_warn(loginfo))
    })?)?;
    rt_log_mod.set("error", lua.create_function(|_, loginfo: String| -> Result<Option<String>, mlua::Error> {
        Ok(crate::dynload::runtime::log::log_error(loginfo))
    })?)?;
    rt_log_mod.set("trace", lua.create_function(|_, loginfo: String| -> Result<Option<String>, mlua::Error> {
        Ok(crate::dynload::runtime::log::log_trace(loginfo))
    })?)?;
    let runtime = lua.create_table()?;
    runtime.set("log", rt_log_mod)?;
    
    // 初始化消息传输模块:runtime.rtmsg
    // 支持 stdin 输入作为 runtime.rtmsg.get(...) 和 stdout SWMSG 前缀消息作为 runtime.rtmsg.send(...)
    let _transmit_manager = transmit::init_transmit(&lua, &runtime)?;
    
    lua.globals().set("runtime", runtime)?;
        
    //模拟 cli 直接执行,为脚本传递命令参数
    //将 flags 转换为 Lua 表并设置为全局变量 args
    let args_table = lua.create_table()?;
    for (index, flag) in flags.iter().enumerate() {
        args_table.set(index + 1, flag.clone())?;
    }
    lua.globals().set("args", args_table)?;

    // 检测与加载用户脚本
    //激动的心,颤抖的手
    //加载用户脚本
    let user_script = std::fs::read_to_string(entity.thinker_script.clone()).unwrap_or_else(|e| {
        eprintln!("[ERROR] 读取用户脚本失败:{}", e);
        std::process::exit(1);
    });
    log::info!("加载用户脚本:{}", entity.thinker_script);
    lua.load(user_script).exec().unwrap_or_else(|e| {
        eprintln!("[ERROR] 执行用户脚本失败:{}", e);
        std::process::exit(1);
    });
    log::info!("用户脚本执行完成");
    Ok(())
}