lua搭建ui_构建类魔兽UI插件的lua安全沙箱

魔兽的UI插件结构

1.使用lua+XML作为配置

分析:XML虽然人机交互很好,但其实没有几个UI是真正用纯XML写的,大多还是用编辑器比较方便。速度很慢,但尚不清楚魔兽代码里是否进行优化

2. Interface\Addons为插件目录,文件夹可以堆叠

3. 每个插件组,需要一个toc文件来做文件读取列表描述,类似于: # Libraries

embeds.xml

AceGUIWidget-DragLink.lua

Core.lua

# Localization

Locale-enUS.lua

Locale-zhCN.lua

Locale-zhTW.lua

AutoBarDB.lua

AutoBarOptions.lua

AutoBarSearch.lua

4.一个插件组里可以拥有多个lua文件,都共享一个独立的全局空间

5.WTF\Account\账号名\服务器名\角色名\AddOns.txt文件描述哪些插件需要读取

根据分析:每次魔兽启动时,都会扫描一次插件目录,并更新这个列表,但是原有的插件读取状态仍然保留,类似于: Combuctor: enabled

Combuctor_Config: enabled

Parrot: disabled

BattleInfo: disabled

BigWigs: disabled

BigWigs_Extras: disabled

BigWigs_BlackTemple: disabled

leafZone: enabled

InFlight: disabled

6. WTF\下的很多SavedVariables目录都是用于保存插件状态的,没有对lua的扩展库进行研究(ACE2/3等等),但是这是一种很好的保存插件数据的方法 OZ_Config = {

{

["bottomCol"] = {

["a"] = 1,

["r"] = 0,

["g"] = 0,

["b"] = 0.6,

},

["maxBars"] = 40,

["barHeight"] = 16,

["titleHeight"] = 20,

["sort2"] = 0,

["fadeAlpha"] = 0.3999999761581421,

["textSize"] = 10,

["colour"] = 2,

["minBars"] = 1,

["heading"] = {

3, -- [1]

0, -- [2]

0, -- [3]

7.暂时没有找到魔兽UI的核心API是否用纯脚本提供的证据,但是可以推断,按照暴雪的实力,应该是全lua api写成。

构建安全的lua沙箱

所谓沙箱,就是每个插件拥有独立的_G全局环境,即便用户误将print修改,其他的插件也不会受到影响. 同时,考虑到沙箱的安全性和权限,需要对沙箱函数访问进行订制.以下是本人摸索出的一种方案:

先看下我的UI环境及lua嵌入架构:

1. C++层将必要的API注册到lua层.但都是基于id的全局函数(考虑到效率及便捷),但是实际使用时再在lua层进行OO封装,这和WINDOWS API及MFC的原理类似

2. C++层只提供4种原生控件: Button,Label, EditBox,MultiLineEditBox。其他的控件都是由这些组成。

3. 可以将整个系统分为内核模式和用户模式。

内核模式:可以使用完整的API访问及权限。

用户模式:被沙箱保护,无法访问一些危险的API,例如io

这里,我们使用lua_setfenv进行沙箱构建,首先我们必须将创建每个沙箱对应的table// 放入沙箱名称

lua_pushstring( mLua, "mysandbox" );

// 将一个table压入栈

dotlua::table ts( mLua , false );

// 调用之前载入好的一个订制沙箱环境的函数

gt.call("SetupSandBox", ts );

// 将沙箱以mysandbox的key保存在注册表中

lua_settable( mLua, LUA_REGISTRYINDEX );

之后使用lua_loadfile载入需要放进沙箱的代码

// 这里将本沙箱对应的环境取出来

lua_pushstring( mLua, "mysandbox");

lua_gettable( mLua, LUA_REGISTRYINDEX );

// 栈内的情形为

// -1 沙箱table

// -2 chunk function

// 这里必须调用chunk函数

lua_setfenv( mLua, -2 );调用pcall执行代码这里的chunk函数,来源于lua_loadfile或者lua_loadbuffer,这2个函数将代码读入,但并不会执行,包括定义全局函数之类的操作。沙箱订制函数必须提前载入,这里发一个做参考

function SetupSandBox( e )

e._G = e

-- system lib

e.print         = print

e.printf         = printf

e.table         = table

e.string         = string

e.debug         = debug

e.math             = math

e.assert         = assert

e.getmetatable     = getmetatable

e.ipairs         = ipairs

e.pairs         = pairs

e.pcall         = pcall

e.setmetatable     = setmetatable

e.tostring         = tostring

e.tonumber         = tonumber

e.type             = type

e.unpack         = unpack

e.collectgarbage = collectgarbage

-- class

e.TREENODE = WIDGET_TREENODE

e.SERIALIZE = WIDGET_SERIALIZE

-- function

e.CreateWidget = CreateWidget

e._Inherit = _Inherit

end只有被订制的函数,才能被调用扩展:为了获得完整的内核模式开发,但又拥有独立的沙箱环境,可以使用setmetatable方式设置一个对全局table的引用,虽然速度慢了点。。当然,可以支持一套可载入dll订制权限,并注册更多的api给自己的脚本用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值