function script_path() local str = debug.getinfo(2, "S").source:sub(2) return str:match("(.*/)") end -------------------------------------[response strings]------------------------------------- response_ok = "HTTP/1.1 200 OK\r\nContent-Length: 2\r\n\r\nOK" response_bad = "HTTP/1.1 400 Bad Request\r\nContent-Length: 11\r\n\r\nbad request" response_forbidden = "HTTP/1.1 403 Forbidden\r\nContent-Length: 9\r\n\r\nforbidden" response_error = "HTTP/1.1 500 Internal Server Error\r\nContent-Length: 21\r\n\r\nInternal Server Error" function ResponseStr(str) if type(str) ~= "string" then return response_error end return "HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: " .. #str .. "\r\n\r\n" .. str end -------------------------------------[config]------------------------------------- config = { maxConnections = 10000, port = 25560, restPort = 8080, restAdminPort = 4040, restAdminCert = script_path().."cert/master.crt", restAdminKey = script_path().."cert/master.key", restAdminVerifyFile = script_path().."cert/rootCA.crt" } admins = require("admins") bansFile = script_path().."/".."banned.json" -------------------------------------[logic]------------------------------------- loggedIn = {} -- {{"koncord", "127.0.0.1"}} banned = {} if type(admins) ~= "table" then error("\"admins.lua\" is not configured.") end local json = require ("dkjson"); function ban(addr, admin, reason, dontInsert) local entry = { address = addr, date = tonumber(os.date("%s")), by = admin, reason = reason } if dontInsert == nil then -- if dontInsert is not provided to arguments then entry will not be inserted table.insert(banned, entry) end BanAddress(addr) end function unban(addr) for idx, value in pairs(banned) do if value.address == addr then table.remove(banned, idx) UnbanAddress(addr) return true end end return false end function loadBans() local file = assert(io.open(bansFile, 'r'), 'Error loading file: ' .. bansFile) local content = file:read("*all") file:close() banned = json.decode(content, 1, nil) for _, entry in pairs(banned) do ban(entry.address, entry.admin, entry.reason, true) end end function saveBans() local content = json.encode(banned, { indent = true, --[[keyorder = {"address", "date", "by", "reason"}]]}) if content ~= "null" then local file = assert(io.open(bansFile, 'w+b'), 'Error loading file: ' .. bansFile) file:write(content) file:close() end end -- _type 1 for login, 2 for address function LoginId(_type, value) for k, entry in ipairs(loggedIn) do if entry[_type] == value then return k end end return nil end function LogOut(address) local loginId = LoginId(2, address) if loginId == nil then return end table.remove(loggedIn, loginId) end -- returns false if response is not modified -- returns true and response if response is modified function OnCommand(command, v, address) print("Command: " .. command) if command == "login" then print("Login attempt.") print("Login: "..v["login"]) print("PassMD5: "..v["passMD5"]) local loginId = LoginId(1, v["login"]) if loginId ~= nil then print("Already logged in with address: " .. loggedIn[loginId][2]) return true, response_forbidden end for _, entry in ipairs(admins) do -- find user in admins list if entry[1] == v["login"] and entry[2] == v["passMD5"] then table.insert(loggedIn, {entry[1], address}) return false -- ok, user found and logged in end end return true, response_forbidden end local loginId = LoginId(2, address) if loginId == nil then print("User with address \"" .. address .. "\" is not logged in") return true, response_forbidden end if command == "ban" then print("Ban address: " .. v["address"]) ban(v["address"], loggedIn[loginId][1], v["reason"]) elseif command == "unban" then print("Unban address: " .. v["address"]) if not unban(v["address"]) then -- if server not found return true, response_bad end elseif command == "banlist" then -- can be used only as last command local data = json.encode(banned, { indent = true--[[, keyorder = {"address", "date", "by", "reason"} ]] }) return true, ResponseStr(data) elseif command == "savebans" then saveBans() end return false end -------------------------------------[callbacks]------------------------------------- function OnAdminRequest(address, request) -- callback local content = json.decode(request, 1, nil)["content"]; local response = response_ok for k, v in ipairs(content) do local stop = false for k2, v2 in pairs(v) do if k2 == "command" then local ret, resp = OnCommand(v2, v, address) if ret == true then response = resp stop = true end break end end if stop == true then break end end LogOut(address) return response end function OnServerAnnounce(address, sserver) -- callback print(sserver.name) print(sserver.gamemode) print(sserver.version) return true end function OnInit() -- called when master server thread was started loadBans() end function OnExit() -- callback saveBans() end