| [234] | 1 | |
|---|
| 2 | require "Class" |
|---|
| 3 | require "List" |
|---|
| 4 | |
|---|
| 5 | SandBox = Class { |
|---|
| 6 | |
|---|
| 7 | initialize = function (self) |
|---|
| 8 | self.envs = {} |
|---|
| 9 | end, |
|---|
| 10 | |
|---|
| 11 | load = function (self, file, dir, requirefun) |
|---|
| 12 | local fun = loadfile(file) |
|---|
| 13 | local env = self:copyEnv() |
|---|
| 14 | setfenv(fun, env) |
|---|
| 15 | if dir then |
|---|
| 16 | -- filename わたす関数をラップする |
|---|
| 17 | env.dofile = function (filename, ...) |
|---|
| 18 | dofile(dir.."/"..filename, unpack(arg)) |
|---|
| 19 | end |
|---|
| 20 | env.loadfile = function (filename, ...) |
|---|
| 21 | loadfile(dir.."/"..filename, unpack(arg)) |
|---|
| 22 | end |
|---|
| 23 | env.io.lines = function (filename, ...) |
|---|
| 24 | io.lines(dir.."/"..filename, unpack(arg)) |
|---|
| 25 | end |
|---|
| 26 | env.io.open = function (filename, ...) |
|---|
| 27 | io.open(dir.."/"..filename, unpack(arg)) |
|---|
| 28 | end |
|---|
| 29 | env.os.remove = function (filename, ...) |
|---|
| 30 | os.remove(dir.."/"..filename, unpack(arg)) |
|---|
| 31 | end |
|---|
| 32 | local f, e = loadstring([[ |
|---|
| 33 | require = function (packagename) |
|---|
| 34 | if _LOADED[packagename] then return _LOADED[packagename] end |
|---|
| 35 | local ret |
|---|
| 36 | local found = false |
|---|
| 37 | if not LUA_PATH then local LUA_PATH = "?;?.lua" end |
|---|
| 38 | for v in string.gfind(LUA_PATH, "([^;]+)") do |
|---|
| 39 | filename = string.gsub(v, "%?", packagename) |
|---|
| 40 | _REQUIREDNAME = packagename |
|---|
| 41 | local ok, err = pcall(dofile, filename) |
|---|
| 42 | _REQUIREDNAME = nil |
|---|
| 43 | if ok then |
|---|
| 44 | if error == nil then |
|---|
| 45 | ret = true |
|---|
| 46 | else |
|---|
| 47 | ret = err |
|---|
| 48 | end |
|---|
| 49 | found = true |
|---|
| 50 | break |
|---|
| 51 | else |
|---|
| 52 | error(err) |
|---|
| 53 | end |
|---|
| 54 | end |
|---|
| 55 | if not found then |
|---|
| 56 | error(string.format("could not load package `%s' from path `%s'", |
|---|
| 57 | packagename, |
|---|
| 58 | LUA_PATH)) |
|---|
| 59 | end |
|---|
| 60 | _LOADED[packagename] = ret |
|---|
| 61 | return ret |
|---|
| 62 | end |
|---|
| 63 | ]]) |
|---|
| 64 | d(e) |
|---|
| 65 | setfenv(f, env) |
|---|
| 66 | f() |
|---|
| 67 | end |
|---|
| 68 | |
|---|
| 69 | -- run file |
|---|
| 70 | fun() |
|---|
| 71 | |
|---|
| 72 | self.envs[file] = env |
|---|
| 73 | return env |
|---|
| 74 | end, |
|---|
| 75 | |
|---|
| 76 | pathComponents = function (s) |
|---|
| 77 | local path = List.new() |
|---|
| 78 | for p in string.gfind(s, "(.-)/") do |
|---|
| 79 | path:push(p) |
|---|
| 80 | end |
|---|
| 81 | local _, _, last = string.find(s, ".+/(.+)") |
|---|
| 82 | if last then path:push(last) end |
|---|
| 83 | if path:isEmpty() then path:push(s) end |
|---|
| 84 | return path |
|---|
| 85 | end, |
|---|
| 86 | |
|---|
| 87 | copyEnv = function (self) |
|---|
| 88 | local ret = {} |
|---|
| 89 | for k, v in pairs(getfenv(0)) do |
|---|
| 90 | if type(v) == "table" then |
|---|
| 91 | ret[k] = {} |
|---|
| 92 | -- 標準ライブラリのため、一段階だけコピー |
|---|
| 93 | for l, w in pairs(v) do |
|---|
| 94 | ret[k][l] = w |
|---|
| 95 | end |
|---|
| 96 | else |
|---|
| 97 | ret[k] = v |
|---|
| 98 | end |
|---|
| 99 | end |
|---|
| 100 | return ret |
|---|
| 101 | end, |
|---|
| 102 | } |
|---|