Haxe / hscript - предотвращение предоставления определенных методов сценариям
Итак, я создал "интерфейсный класс" со всеми статическими методами, которые я хочу показать hscript
скрипты. Это выглядит так:
package com.application.interfaces.Terrain;
import com.application.TerrainCore
class Terrain {
private static var terrain:TerrainCore;
public static function _init(inTerrain:TerrainCore):Void {
terrain = inTerrain;
}
public static function test(s:Int):Void {
terrain.test(s);
}
}
Проблема в том, что мне нужно установить terrain
как-то возражать, но я не хочу, чтобы он подвергался воздействию скриптов. Я выставляю целые классы с
var interp = new Interp();
var module = Type.resolveClass("com.application.interfaces.Terrain");
interp.variables.set("Terrain", module)
Идея была переопределить метод call
в hscript.Interp
поэтому он не выполняет какой-либо метод с именем _init
, но я не знаю, как это сделать. оригинал call
Метод выглядит так:
function call( o : Dynamic, f : Dynamic, args : Array<Dynamic> ) : Dynamic {
return Reflect.callMethod(o,f,args);
}
2 ответа
Можете ли вы использовать экземпляр класса Terrain вместо статических членов? Например:
interp.variables.set("Terrain", new Terrain(new TerrainCore()));
Пользователи сценариев не будут знать, используют ли они статические методы или методы экземпляра, так как к нему все равно будет доступ через:
Terrain.test(123);
в сценарии.
Другой вариант (основанный на clemos) - использовать rtti для определения того, что разрешено (вместо того, чтобы поддерживать его список), например:
Terrain._init(new TerrainCore());
_init сейчас является частной функцией, поэтому вам нужно @:allow
это из вашего вызывающего класса (см. ниже), также вы должны аннотировать с @:rtti
так что вы можете получить информацию о функциях во время выполнения, поэтому Terrain теперь выглядит так:
@:rtti
class Terrain {
private static var terrain:TerrainCore;
@:allow(test.hscript.demo.Main)
private static function _init(inTerrain:TerrainCore):Void {
terrain = inTerrain;
}
public static function test(s:Int):Void {
terrain.test(s);
}
}
Наконец, сценарий взаимодействия fcall
Теперь учитывается, является ли поле публичным или частным, то есть:
public override function fcall(o:Dynamic, f:String, args:Array<Dynamic>):Dynamic
var rtti = haxe.rtti.Rtti.getRtti(o);
for (field in rtti.statics) {
if (field.name == f && field.isPublic == false) {
error(EInvalidAccess(f));
}
}
return super.fcall(o, f, args);
}
Стоит отметить, что я использовал statics
скорее, чем fields
по понятным причинам. Я также не уверен, какие издержки это может вызвать с циклом и RTI.
Я верю что это fcall
вы должны переопределить, как call
используется только для вызовов верхнего уровня:
https://github.com/HaxeFoundation/hscript/blob/master/hscript/Interp.hx#L328-L331
Это должно быть легко фильтровать f
аргумент как:
if ( FORBIDDEN_FIELDS.indexOf( f ) > -1 ) throw EInvalidAccess( f );
или же
if ( f.indexOf('_') == 0 ) throw EInvalidAccess( f );