#!/usr/local/bin/lua --[[ Copyright (c) 2011, 2012 James Turner Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ]] local tincan = require("tincan") local print_buff = {} local function term_print(...) local args, n = {...}, select("#", ...) for i = 1, n do args[i] = tostring(args[i]) end table.insert(print_buff, table.concat(args, "\t")) end local env = { _VERSION = _VERSION, assert = assert, error = error, getmetatable = getmetatable, ipairs = ipairs, next = next, pairs = pairs, pcall = pcall, print = term_print, rawequal = rawequal, rawget = rawget, rawlen = rawlen, rawset = rawset, select = select, setmetatable = setmetatable, tonumber = tonumber, tostring = tostring, type = type, xpcall = xpcall, bit32 = { arshift = bit32.arshift, band = bit32.band, bnot = bit32.bnot, bor = bit32.bor, btest = bit32.btest, bxor = bit32.bxor, extract = bit32.extract, lrotate = bit32.lrotate, lshift = bit32.lshift, replace = bit32.replace, rrotate = bit32.rrotate, rshift = bit32.rshift }, coroutine = { create = coroutine.create, resume = coroutine.resume, running = coroutine.running, status = coroutine.status, wrap = coroutine.wrap, yield = coroutine.yield }, math = { abs = math.abs, acos = math.acos, asin = math.asin, atan = math.atan, atan2 = math.atan2, ceil = math.ceil, cos = math.cos, cosh = math.cosh, deg = math.deg, exp = math.exp, floor = math.floor, fmod = math.fmod, frexp = math.frexp, huge = math.huge, ldexp = math.ldexp, log = math.log, max = math.max, min = math.min, modf = math.modf, pi = math.pi, pow = math.pow, rad = math.rad, random = math.random, randomseed = math.randomseed, sin = math.sin, sinh = math.sinh, sqrt = math.sqrt, tan = math.tan, tanh = math.tanh }, string = { byte = string.byte, char = string.char, dump = string.dump, find = string.find, format = string.format, gmatch = string.gmatch, gsub = string.gsub, len = string.len, lower = string.lower, match = string.match, rep = string.rep, reverse = string.reverse, sub = string.sub, upper = string.upper }, table = { concat = table.concat, insert = table.insert, pack = table.pack, remove = table.remove, sort = table.sort, unpack = table.unpack } } env._G = env local function eval(expr, hash) local func, err, stat, val tincan.load("trylua.db") local history = tincan.get(hash) if history then for _, stmt in ipairs(history) do func = load(stmt, "", "t", env) if func then _, val = pcall(func) end end else history = {} end print_buff = {} expr = string.gsub(expr, "^%s*=%s*", "return ") if not expr then return "expression is nil" end func, err = load(expr, "", "t", env) if func then stat, val = pcall(func) if not stat then err = val else if #print_buff > 0 then val = table.concat(print_buff, "\n") else local beginner = "return" if val == nil and string.sub(expr, 0, #beginner) ~= beginner then val = "" end end table.insert(history, expr) tincan.set(hash, history) tincan.save("trylua.db") return tostring(val) end end if err then local ender = "" err = tostring(err) err = string.gsub(err, '^%[string ".*"%]:[0-9]+: ', "") if string.sub(err, -#ender) == ender then return "continued" end return err end end local function url_decode(str) str = string.gsub(str, "+", " ") str = string.gsub(str, "%%(%x%x)", function(h) return string.char(tonumber(h, 16)) end) str = string.gsub(str, "\r\n", "\n") return str end local info = os.getenv("QUERY_STRING") or "" local params = {} for key, value in string.gmatch(info .. "&", "(.-)%=(.-)%&") do params[key] = url_decode(value) end if params.expr and params.hash then local res = eval(params.expr, params.hash) print("Content-type: text/plain\n") print(res) else print("Content-type: text/plain\n") end