· 9 years ago · Jan 16, 2017, 10:40 PM
1--[[
2 --Copyright Notice--
3
4 You may use, modifie, and distribute this
5code without the permission of the original
6developer
7
8 However, you are not allowed to remove this
9copyright notice and you must give credit to the
10original developer
11
12 --Intro--
13
14 This script is designed to run as a stand alone
15script or as a lua library. This script's
16purpose is to allow lua code to run in a
17proteced environment.
18
19 This environment will only allow lua code to
20use functions and variables defined by the user.
21Any changes in this environment will stay in the
22environment and will not effect any functions or
23variables from outside of the protected
24environment.
25
26--]]
27
28local fs = require "filesystem"
29
30local pse = {}
31
32--[[
33
34 This function determins if sandbox is a valid
35sandbox
36
37--]]
38
39local function is_sandbox(sandbox)
40 if not sandbox then
41 return false
42 elseif not type(sandbox) == "table" then
43 return false
44 elseif type(sandbox.code) == "nil" then
45 return false
46 elseif type(sandbox.args) == "nil" then
47 return false
48 end
49 return true
50end
51
52--[[
53
54 This function throws an error if the given
55sandbox is not actully a sandbox
56
57--]]
58
59local function sb_error(sandbox)
60 if not is_sandbox(sandbox) then
61 error("expected sandbox",3)
62 end
63end
64
65--[[
66
67 This next function will get anything a lua file
68will return when ran. This is a seperate function
69to make porting code to different systems easier
70
71--]]
72
73local function get_file(path)
74 if not type(path) == "string" then
75 error("expected string",3)
76 end
77 local file = fs.open(path,"r")
78 if not file then
79 error("file does not exists",3)
80 end
81 local data = ""
82 local temp = ""
83 while temp do
84 temp = file:read(512)
85 if temp then
86 data = data..temp
87 end
88 end
89 file:close()
90 return data
91end
92
93--[[
94
95 This function will create a new sanbox to work
96in. Each sandbox will contain all the code you
97put in it and it will also contain runtime
98arguments.
99
100--]]
101
102function pse.new_sandbox()
103 local sandbox = {code={},args={}}
104 return setmetatable({},{__index=sandbox})
105end
106
107function pse.newSandbox()
108 return pse.new_sandbox()
109end
110
111--[[
112
113 This function is for debugging the sandbox.
114
115--]]
116
117function pse.debug_sandbox(sandbox)
118 sb_error(sandbox)
119 print("Code:")
120 for i,j in pairs(sandbox.code) do
121 print(i)
122 print(j)
123 print()
124 end
125 print("Args:")
126 for i=1,#sandbox.args do
127 print(sandbox.args[i])
128 end
129end
130
131function pse.debugSandbox(sandbox)
132 return pse.debug_sandbox(sandbox)
133end
134
135--[[
136
137 This will add any code to the sandbox you
138provide. This code can be either a function or a
139veriable
140
141--]]
142
143function pse.add_code(sandbox,name,code)
144 sb_error(sandbox)
145 if not (type(name) == "string") then
146 error("expected string",2)
147 elseif not code then
148 error("expected code",2)
149 end
150 sandbox.code[name] = code
151 return sandbox
152end
153
154function pse.addCode(sandbox,name,code)
155 return pse.add_code(sandbox,name,code)
156end
157
158--[[
159
160 This function will add runtime arguments to
161the given sandbox
162
163--]]
164
165function pse.add_argument(sandbox,arg)
166 sb_error(sandbox)
167 if not (type(arg) == "string") then
168 error("expected string",2)
169 end
170 table.insert(sandbox.args,arg)
171 return sandbox
172end
173
174function pse.addArgument(sandbox,arg)
175 return pse.add_argument(sandbox,arg)
176end
177
178--[[
179
180 This one is similar to the last one exept it
181adds anything the file at path returns to the
182sandbox
183
184--]]
185
186function pse.add_file(sandbox,name,path)
187 sb_error(sandbox)
188 if not (type(name) == "string") then
189 error("expected string",2)
190 end
191 local program = load(get_file(path),"="..path,nil,sandbox.code)
192 local result = table.pack(pcall(program))
193 if not result[1] then
194 error("error in file",2)
195 end
196 sandbox.code[name] = result[2]
197 return sandbox
198end
199
200function pse.addFile(sandbox,name,path)
201 return pse.add_file(sandbox,name,path)
202end
203
204--[[
205
206 This function adds anything pre-defined in the
207global table. This could be any valid code. For
208example: print
209
210--]]
211
212function pse.add_global(sandbox,name)
213 sb_error(sandbox)
214 if not (type(name) == "string") then
215 error("expected string",2)
216 end
217 sandbox.code[name] = _G[name]
218 return sandbox
219end
220
221function pse.addGlobal(sandbox,name)
222 return pse.add_global(sandbox,name)
223end
224
225--[[
226
227 This function will run any string given to it
228as code withing the sandbox. It will also pass
229all the runtime arguments to the code.
230
231 It will return false is the code had an error
232and will return all error data. Otherwise, the
233function will return what ever the code does
234
235--]]
236
237function pse.run_string(sandbox,name,data)
238 sb_error(sandbox)
239 if not (type(data) == "string") then
240 error("expected string",2)
241 elseif not (type(name) == "string") then
242 error("expected string",2)
243 end
244 local program,reason = load(data,"="..name,nil,sandbox.code)
245 if not program then
246 return nil,reason
247 end
248 local status = table.pack(pcall(program,table.unpack(sandbox.args)))
249 if status[1] then
250 return table.unpack(status,2)
251 end
252 return table.unpack(status)
253end
254
255function pse.runString(sandbox,name,data)
256 return pse.run_string(sandbox,name,data)
257end
258
259--[[
260
261 This function is like the last but instead of
262treating a string like code, it will execute a
263file instead
264
265--]]
266
267function pse.run(sandbox,name,file)
268 sb_error(sandbox)
269 if not (type(name) == "string") then
270 error("expected string",2)
271 end
272 local data = get_file(file)
273 return pse.run_string(sandbox,name,data)
274end
275
276--[[
277
278 Time to return all the functions needed for
279this library to work
280
281--]]
282
283return pse