--[[ Author: TheOriginalBIT Version: 4.1 Created: 17 Dec 2012 Last Update: 22 Feb 2013 License: COPYRIGHT NOTICE Copyright © 2012-2013 Joshua Asbury a.k.a TheOriginalBIT [theoriginalbit@gmail.com] Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: -The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. -Visible credit is given to the original author. -The software is distributed in a non-profit way. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ]]-- -- changing anything beyond this point could break the program --[[ EXTERNAL LIBRARY BY GRAVITYSCORE ]]-- -- -- Adaptation of the Secure Hashing Algorithm (SHA-244/256) -- Found Here: http://lua-users.org/wiki/SecureHashAlgorithm -- -- Using an adapted version of the bit library -- Found Here: https://bitbucket.org/Boolsheet/bslf/src/1ee664885805/bit.lua -- -- Adapted into a single function by GravityScore -- local hash = function(msg) local function band(int1, int2, int3, ...) local ret = ((int1%0x00000002>=0x00000001 and int2%0x00000002>=0x00000001 and 0x00000001) or 0) + ((int1%0x00000004>=0x00000002 and int2%0x00000004>=0x00000002 and 0x00000002) or 0) + ((int1%0x00000008>=0x00000004 and int2%0x00000008>=0x00000004 and 0x00000004) or 0) + ((int1%0x00000010>=0x00000008 and int2%0x00000010>=0x00000008 and 0x00000008) or 0) + ((int1%0x00000020>=0x00000010 and int2%0x00000020>=0x00000010 and 0x00000010) or 0) + ((int1%0x00000040>=0x00000020 and int2%0x00000040>=0x00000020 and 0x00000020) or 0) + ((int1%0x00000080>=0x00000040 and int2%0x00000080>=0x00000040 and 0x00000040) or 0) + ((int1%0x00000100>=0x00000080 and int2%0x00000100>=0x00000080 and 0x00000080) or 0) + ((int1%0x00000200>=0x00000100 and int2%0x00000200>=0x00000100 and 0x00000100) or 0) + ((int1%0x00000400>=0x00000200 and int2%0x00000400>=0x00000200 and 0x00000200) or 0) + ((int1%0x00000800>=0x00000400 and int2%0x00000800>=0x00000400 and 0x00000400) or 0) + ((int1%0x00001000>=0x00000800 and int2%0x00001000>=0x00000800 and 0x00000800) or 0) + ((int1%0x00002000>=0x00001000 and int2%0x00002000>=0x00001000 and 0x00001000) or 0) + ((int1%0x00004000>=0x00002000 and int2%0x00004000>=0x00002000 and 0x00002000) or 0) + ((int1%0x00008000>=0x00004000 and int2%0x00008000>=0x00004000 and 0x00004000) or 0) + ((int1%0x00010000>=0x00008000 and int2%0x00010000>=0x00008000 and 0x00008000) or 0) + ((int1%0x00020000>=0x00010000 and int2%0x00020000>=0x00010000 and 0x00010000) or 0) + ((int1%0x00040000>=0x00020000 and int2%0x00040000>=0x00020000 and 0x00020000) or 0) + ((int1%0x00080000>=0x00040000 and int2%0x00080000>=0x00040000 and 0x00040000) or 0) + ((int1%0x00100000>=0x00080000 and int2%0x00100000>=0x00080000 and 0x00080000) or 0) + ((int1%0x00200000>=0x00100000 and int2%0x00200000>=0x00100000 and 0x00100000) or 0) + ((int1%0x00400000>=0x00200000 and int2%0x00400000>=0x00200000 and 0x00200000) or 0) + ((int1%0x00800000>=0x00400000 and int2%0x00800000>=0x00400000 and 0x00400000) or 0) + ((int1%0x01000000>=0x00800000 and int2%0x01000000>=0x00800000 and 0x00800000) or 0) + ((int1%0x02000000>=0x01000000 and int2%0x02000000>=0x01000000 and 0x01000000) or 0) + ((int1%0x04000000>=0x02000000 and int2%0x04000000>=0x02000000 and 0x02000000) or 0) + ((int1%0x08000000>=0x04000000 and int2%0x08000000>=0x04000000 and 0x04000000) or 0) + ((int1%0x10000000>=0x08000000 and int2%0x10000000>=0x08000000 and 0x08000000) or 0) + ((int1%0x20000000>=0x10000000 and int2%0x20000000>=0x10000000 and 0x10000000) or 0) + ((int1%0x40000000>=0x20000000 and int2%0x40000000>=0x20000000 and 0x20000000) or 0) + ((int1%0x80000000>=0x40000000 and int2%0x80000000>=0x40000000 and 0x40000000) or 0) + ((int1>=0x80000000 and int2>=0x80000000 and 0x80000000) or 0) return (int3 and band(ret, int3, ...)) or ret end local function bxor(int1, int2, int3, ...) local ret = ((int1%0x00000002>=0x00000001 ~= (int2%0x00000002>=0x00000001) and 0x00000001) or 0) + ((int1%0x00000004>=0x00000002 ~= (int2%0x00000004>=0x00000002) and 0x00000002) or 0) + ((int1%0x00000008>=0x00000004 ~= (int2%0x00000008>=0x00000004) and 0x00000004) or 0) + ((int1%0x00000010>=0x00000008 ~= (int2%0x00000010>=0x00000008) and 0x00000008) or 0) + ((int1%0x00000020>=0x00000010 ~= (int2%0x00000020>=0x00000010) and 0x00000010) or 0) + ((int1%0x00000040>=0x00000020 ~= (int2%0x00000040>=0x00000020) and 0x00000020) or 0) + ((int1%0x00000080>=0x00000040 ~= (int2%0x00000080>=0x00000040) and 0x00000040) or 0) + ((int1%0x00000100>=0x00000080 ~= (int2%0x00000100>=0x00000080) and 0x00000080) or 0) + ((int1%0x00000200>=0x00000100 ~= (int2%0x00000200>=0x00000100) and 0x00000100) or 0) + ((int1%0x00000400>=0x00000200 ~= (int2%0x00000400>=0x00000200) and 0x00000200) or 0) + ((int1%0x00000800>=0x00000400 ~= (int2%0x00000800>=0x00000400) and 0x00000400) or 0) + ((int1%0x00001000>=0x00000800 ~= (int2%0x00001000>=0x00000800) and 0x00000800) or 0) + ((int1%0x00002000>=0x00001000 ~= (int2%0x00002000>=0x00001000) and 0x00001000) or 0) + ((int1%0x00004000>=0x00002000 ~= (int2%0x00004000>=0x00002000) and 0x00002000) or 0) + ((int1%0x00008000>=0x00004000 ~= (int2%0x00008000>=0x00004000) and 0x00004000) or 0) + ((int1%0x00010000>=0x00008000 ~= (int2%0x00010000>=0x00008000) and 0x00008000) or 0) + ((int1%0x00020000>=0x00010000 ~= (int2%0x00020000>=0x00010000) and 0x00010000) or 0) + ((int1%0x00040000>=0x00020000 ~= (int2%0x00040000>=0x00020000) and 0x00020000) or 0) + ((int1%0x00080000>=0x00040000 ~= (int2%0x00080000>=0x00040000) and 0x00040000) or 0) + ((int1%0x00100000>=0x00080000 ~= (int2%0x00100000>=0x00080000) and 0x00080000) or 0) + ((int1%0x00200000>=0x00100000 ~= (int2%0x00200000>=0x00100000) and 0x00100000) or 0) + ((int1%0x00400000>=0x00200000 ~= (int2%0x00400000>=0x00200000) and 0x00200000) or 0) + ((int1%0x00800000>=0x00400000 ~= (int2%0x00800000>=0x00400000) and 0x00400000) or 0) + ((int1%0x01000000>=0x00800000 ~= (int2%0x01000000>=0x00800000) and 0x00800000) or 0) + ((int1%0x02000000>=0x01000000 ~= (int2%0x02000000>=0x01000000) and 0x01000000) or 0) + ((int1%0x04000000>=0x02000000 ~= (int2%0x04000000>=0x02000000) and 0x02000000) or 0) + ((int1%0x08000000>=0x04000000 ~= (int2%0x08000000>=0x04000000) and 0x04000000) or 0) + ((int1%0x10000000>=0x08000000 ~= (int2%0x10000000>=0x08000000) and 0x08000000) or 0) + ((int1%0x20000000>=0x10000000 ~= (int2%0x20000000>=0x10000000) and 0x10000000) or 0) + ((int1%0x40000000>=0x20000000 ~= (int2%0x40000000>=0x20000000) and 0x20000000) or 0) + ((int1%0x80000000>=0x40000000 ~= (int2%0x80000000>=0x40000000) and 0x40000000) or 0) + ((int1>=0x80000000 ~= (int2>=0x80000000) and 0x80000000) or 0) return (int3 and bxor(ret, int3, ...)) or ret end local function bnot(int) return 4294967295 - int end local function rshift(int, by) local shifted = int / (2 ^ by) return shifted - shifted % 1 end local function rrotate(int, by) local shifted = int / (2 ^ by) local fraction = shifted % 1 return (shifted - fraction) + fraction * (2 ^ 32) end local k = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2 } local function str2hexa(s) local h = string.gsub(s, ".", function(c) return string.format("%02x", string.byte(c)) end) return h end local function num2s(l, n) local s = "" for i = 1, n do local rem = l % 256 s = string.char(rem) .. s l = (l - rem) / 256 end return s end local function s232num(s, i) local n = 0 for i = i, i + 3 do n = n*256 + string.byte(s, i) end return n end local function preproc(msg, len) local extra = 64 - ((len + 1 + 8) % 64) len = num2s(8 * len, 8) msg = msg .. "\128" .. string.rep("\0", extra) .. len return msg end local function initH256(H) H[1] = 0x6a09e667 H[2] = 0xbb67ae85 H[3] = 0x3c6ef372 H[4] = 0xa54ff53a H[5] = 0x510e527f H[6] = 0x9b05688c H[7] = 0x1f83d9ab H[8] = 0x5be0cd19 return H end local function digestblock(msg, i, H) local w = {} for j = 1, 16 do w[j] = s232num(msg, i + (j - 1) * 4) end for j = 17, 64 do local v = w[j - 15] local s0 = bxor(rrotate(v, 7), rrotate(v, 18), rshift(v, 3)) v = w[j - 2] local s1 = bxor(rrotate(v, 17), rrotate(v, 19), rshift(v, 10)) w[j] = w[j - 16] + s0 + w[j - 7] + s1 end local a, b, c, d, e, f, g, h = H[1], H[2], H[3], H[4], H[5], H[6], H[7], H[8] for i = 1, 64 do local s0 = bxor(rrotate(a, 2), rrotate(a, 13), rrotate(a, 22)) local maj = bxor(band(a, b), band(a, c), band(b, c)) local t2 = s0 + maj local s1 = bxor(rrotate(e, 6), rrotate(e, 11), rrotate(e, 25)) local ch = bxor (band(e, f), band(bnot(e), g)) local t1 = h + s1 + ch + k[i] + w[i] h, g, f, e, d, c, b, a = g, f, e, d + t1, c, b, a, t1 + t2 end H[1] = band(H[1], a) H[2] = band(H[2], b) H[3] = band(H[3], c) H[4] = band(H[4], d) H[5] = band(H[5], e) H[6] = band(H[6], f) H[7] = band(H[7], g) H[8] = band(H[8], h) end msg = preproc(msg, #msg) local H = initH256({}) for i = 1, #msg, 64 do digestblock(msg, i, H) end return str2hexa(num2s(H[1], 4)..num2s(H[2], 4)..num2s(H[3], 4)..num2s(H[4], 4)..num2s(H[5], 4)..num2s(H[6], 4)..num2s(H[7], 4)..num2s(H[8], 4)) end --[[ END EXTERNAL LIBRARY ]]-- local version = "4.0" local salt = [[T0B1td2j@25-~;o2{MJ+mSB=1Ye9SSS|[~7_t195l6Q2Cg/Awb"(53cUr1Ty]] local supportLoc = ".theoriginalbit/DoorLock/" local passFile = supportLoc.."access.dat" local configFile = supportLoc.."access.cfg" local adv = term.isColor and term.isColor() local accounts = {} local terminatePass = "" local rsOutput local welcomeMessage local text = "" do --[[ Author: TheOriginalBIT Version: 1.4.5 Created: 5 Feb 2013 Last Update: 22 Feb 2013 ]]-- local configHeader = [[ +-------------------------------------------+ +-- CONFIGURATION FILE --+ +-- Generated by TheOriginalBIT's CConfig --+ +-------------------------------------------+ ]] local startsWith = function(str, prefix) prefix = tostring(prefix) return str:sub( 1, prefix:len()) == prefix end local contains = function(str, seq) str = tostring(str) local sStart, sEnd, sStr = str:find(seq, 1) return sStart ~= nil end local split = function(str, pat) local t = {} local fpat = "(.-)"..pat local last_end = 1 local s, e, cap = str:find(fpat, 1) while s do if s ~= 1 or cap ~= "" then table.insert(t,cap) end last_end = e+1 s, e, cap = str:find(fpat, last_end) end if last_end <= #str then cap = str:sub(last_end) table.insert(t, cap) end return t end local trim = function(str) return (str:gsub("^%s*(.-)%s*$", "%1")) end local log = function(...) if not emulog then return end local details = table.concat({...}," ") emulog.log(details) end local clearLog = function() if not emulog then return end emulog.clear() end -- If you're reading the code, normally I do not suggest overwriting system functions without restoring them! Do as I say, not as I do. I've made sure this 100% won't break other programs! _G.assert = function(condition, errMsg, level) if not condition then error(errMsg, (tonumber(level) or 1) + 1) end return condition end local openedConfigs = {} Configuration = {} local debugCount = 0 Configuration.__index = Configuration local function vaidateInitParams(path) assert(type(p) ~= "string", "Invalid file path supplied", 3) assert(not openedConfigs[p], "A configuration file object already exists for this file", 3) end local function validateParam(param, value) assert(type(param) == value, "Invalid parameter, expected "..value.." got "..type(param), 3) end local function validBoolean(b) return (b == "true" or b == "false" or b == "1" or b == "0" or b == 1 or b == 0 or b == true or b == false or b == "yes" or b == "no") end local colorStrings = {["colors.white"] = colors.white, ["colours.white"] = colors.white, ["white"] = colors.white, ["colors.orange"] = colors.orange, ["colours.orange"] = colors.orange, ["orange"] = colors.orange, ["colors.magenta"] = colors.magenta, ["colours.magenta"] = colors.magenta, ["magenta"] = colors.magenta, ["colors.lightblue"] = colors.lightBlue, ["colours.lightblue"] = colors.lightBlue, ["lightblue"] = colors.lightBlue, ["light blue"] = colors.lightBlue, ["colors.yellow"] = colors.yellow, ["colours.yellow"] = colors.yellow, ["yellow"] = colors.yellow, ["colors.lime"] = colors.lime, ["colours.lime"] = colors.lime, ["lime"] = colors.lime, ["colors.pink"] = colors.pink, ["colours.pink"] = colors.pink, ["pink"] = colors.pink, ["colors.gray"] = colors.gray, ["colours.gray"] = colors.gray, ["gray"] = colors.gray, ["colors.grey"] = colors.gray, ["colours.grey"] = colors.gray, ["grey"] = colors.gray, ["colors.lightgray"] = colors.lightGray, ["colours.lightgray"] = colors.lightGray, ["lightgray"] = colors.lightGray, ["light gray"] = colors.lightGray, ["colors.lightgrey"] = colors.lightGray, ["colours.lightgrey"] = colors.lightGray, ["lightgrey"] = colors.lightGray, ["light grey"] = colors.lightGray, ["colors.cyan"] = colors.cyan, ["colours.cyan"] = colors.cyan, ["cyan"] = colors.cyan, ["colors.purple"] = colors.purple, ["colours.purple"] = colors.purple, ["purple"] = colors.purple, ["colors.blue"] = colors.blue, ["colours.blue"] = colors.blue, ["blue"] = colors.blue, ["colors.brown"] = colors.brown, ["colours.brown"] = colors.brown, ["brown"] = colors.brown, ["colors.green"] = colors.green, ["colours.green"] = colors.green, ["green"] = colors.green, ["colors.red"] = colors.red, ["colours.red"] = colors.red, ["red"] = colors.red, ["colors.black"] = colors.black, ["colours.black"] = colors.black, ["black"] = colors.black} local function validateColor(col) if tonumber(col) then local col = tonumber(col) if not (col >= 2^0 and col <= (2^16)-1) then return false end return true, col else if colorStrings[col:lower()] then return true, colorStrings[col:lower()] else return false end end end function Configuration.new(p) vaidateInitParams(p) openedConfigs[p] = true return setmetatable({ path = p, properties = {} }, Configuration) end local function get(self, key, defaultValue) if type(self.properties[key]) == "table" then self.properties[key].default = defaultValue return self.properties[key].value else self.properties[key] = {} self.properties[key].value = defaultValue self.properties[key].default = defaultValue self.properties[key].comment = "" self.properties[key].restrict = "" return defaultValue end end function Configuration:getBoolean(key, defaultBoolean) validateParam(key, "string") assert(validBoolean(defaultBoolean), "Boolean value expected, got "..type(defaultBoolean).." of type "..type(defaultBoolean), 2) local v = get(self, key, defaultBoolean) assert(validBoolean(v), "No boolean value found under the key \'"..tostring(key).."\', found "..tostring(v).." of type "..type(v), 2) return v == "true" or v == true or v == "1" or v == 1 or v == "yes" end function Configuration:getNumber(key, defaultNumber) validateParam(key, "string") return assert(tonumber(get(self, key, defaultNumber)), "Number expected, got "..type(defaultNumber), 2) end function Configuration:getString(key, defaultString) validateParam(key, "string") return assert(tostring(get(self, key, defaultString)), "Invalid parameter, expected string got "..type(key), 2) end function Configuration:getColor(key, defaultColor) validateParam(key, "string") assert(validateColor(defaultColor), "Invalid parameter, color expected", 2) local ok, col = validateColor(get(self, key, defaultColor)) assert(ok, "Config file does not contain color for value "..tostring(key), 2) self.properties[key].restrict = "A number between 1 and 65535 or the string colors." return col end Configuration.getColour = Configuration.getColor function Configuration:getTable(key, defaultTable) validateParam(key, "string") validateParam(defaultTable, "table") local v = self:getString(key, textutils.serialize(defaultTable)) v = textutils.unserialize(v) return assert(v, "No table in config", 2) end function Configuration:containsKey(key) return (self.properties[key] ~= nil) end function Configuration:load() if not fs.exists(self.path) then return false end local handle = fs.open(self.path,"r") assert(handle, "Cannot open configuration file \'"..self.path.."\' for read") local contents = handle.readAll() handle.close() if not contents or contents == "" or contents == "\n" then return end local count = 1 contents = split(contents,"\n") for i = 1, #contents do local v = contents[i] if v and v ~= "" and not startsWith(v,"+--") and contains(v,"=") then local prop = split(v, "%=") key = trim(prop[1]) value = trim(prop[2]) self.properties[key] = {} self.properties[key]["value"] = value self.properties[key]["comment"] = "" self.properties[key]["default"] = value elseif v and v ~= "" and not startsWith(v,"+--") and not contains(v,"=") then print("Error: \""..self.path.."\": Cannot parse line #"..i.." in configuration file") error() end end return true end function Configuration:reset(key) if type(self) ~= "table" or type(self.properties) ~= "table" then error("Error resetting config, have you forgotten to load the config?",2) end if key and not self.properties[key] then error("No property for key "..tostring(key)..", have you forgotten to load the config?",2) end if key then self.properties[key].value = self.properties[key].default else for k,_ in pairs(self.properties) do self.properties[k].value = self.properties[k].default end end end function Configuration:save() local handle = fs.open(self.path,"w") handle.write(configHeader) for k,v in pairs(self.properties) do handle.write("+-- ") if v.comment and v.comment ~= "" then handle.write(tostring(v.comment).."; ") end if v.restrict and v.restrict ~= "" then handle.write("restrictions: "..tostring(v.restrict).."; ") end handle.write("default: "..tostring(v.default).."\n") handle.write(k.."="..tostring(v.value).."\n\n") end handle.close() end function Configuration:addCommentForKey(key,com) assert(self.properties[key], "No property with key \'"..tostring(key).."\' to add comment for", 2) self.properties[key].comment = com end function Configuration:addRestrictionForKey(key,res) assert(self.properties[key], "No property with key \'"..tostring(key).."\' to add comment for", 2) self.properties[key].restrict = res end function Configuration:debug(toFile) toFile = (toFile == true) local handle = toFile and fs.open("debug"..debugCount,"w") or nil for k,v in pairs(self.properties) do if toFile then handle.write(k..":"..v.value.."\n") else print(k..":"..v.value) end end if toFile then handle.close() debugCount = debugCount + 1 end end end term.clear = function() if adv then term.setBackgroundColor(colors.black) term.setTextColor(colors.white) end term.native.clear() term.setCursorPos(1,1) end local waitForKey = function() os.pullEventRaw("key") end local checkPass = function(pass) for _,v in pairs(accounts) do if v == pass then return true end end return false end local validateSideWithoutFail = function(side) for _,v in pairs(rs.getSides()) do if v == side then return v end end return "left" end local printRecognition = function() local sw, sh = term.getSize();local pX,pY=term.getCursorPos();term.setCursorPos(sw - string.len("By TheOriginalBIT "), sh);write("By TheOriginalBIT");term.setCursorPos(pX, pY);end local split = function(str, pat) local t = {} local fpat = "(.-)"..pat local last_end = 1 local s, e, cap = str:find(fpat, 1) while s do if s ~= 1 or cap ~= "" then table.insert(t,cap) end last_end = e+1 s, e, cap = str:find(fpat, last_end) end if last_end <= #str then cap = str:sub(last_end) table.insert(t, cap) end return t end local cwrite = function(msg,y) local w,h = term.getSize() term.setCursorPos(w/2-#msg/2+(#msg%2 and 1 or 0), y) write(msg) end local config = Configuration.new(configFile) local function loadAccounts() local file = io.open(passFile,"r") local contents = file:read("*a") file:close() contents = split(contents, "\n") terminatePass = contents[1] for i = 2, #contents do if #contents[i] == 64 then table.insert(accounts, contents[i]) end end end local function saveAccounts() local file = io.open(passFile,"w") file:write(terminatePass.."\n") file:write(table.concat(accounts,"\n")) file:close() end local function loadConfig() config:load() welcomeMessage = config:getString("welcomeMessage", "Advanced DoorLock v4.0") config:addCommentForKey("welcomeMessage", "the message to display at the top of the screen") rsOutput = validateSideWithoutFail(config:getString("redstoneSide", "left")) config:addCommentForKey("redstoneSide", "side to output when password is correct") canDiskStay = config:getBoolean("allowDisks", false) config:addCommentForKey("allowDisks", "allows disks to be inserted into any disk drives found") config:save() end local function getInput(msg, char) x, y = term.getCursorPos() input = "" print(msg) while true do term.setCursorPos(x, y) term.clearLine() write(msg.." ") if char then for i = 1, #input do write(char) end else write(input) end event = { os.pullEventRaw() } if event[1] == "char" then input = input..event[2] elseif event[1] == "key" then if event[2] == keys.backspace then input = input:sub(1, input:len() - 1) elseif event[2] == keys.enter then break end end end print() return input end local function initialSetup() term.clear() print("Setup...") if not fs.exists(supportLoc) then fs.makeDir(supportLoc) end if not fs.exists(passFile) then local pfile = io.open(passFile,"w") pfile:write() pfile:close() end while true do local ok, err = pcall(loadConfig) print("Prepare to review the config file... ") os.startTimer(3) os.pullEvent("timer") local ope = os.pullEvent os.pullEvent = os.pullEventRaw shell.run("edit "..configFile) os.pullEvent = ope local ok, err = pcall(loadConfig) if not ok then term.setTextColor(colors.red) print("Error: Cannot parse the config file. Please check syntax for what you changed.\n\n") term.setTextColor(colors.white) os.startTimer(3) os.pullEvent("timer") else break end end print("Prepare to setup passwords... ") os.startTimer(3) os.pullEvent("timer") while true do term.clear() print("Termination password setup.") local pw = getInput("Password:","*") if pw == "finished" then break end local pw2 = getInput("Again:","*") if pw2 == "finished" then break end if pw == pw2 then terminatePass = hash(pw..salt) saveAccounts() print("Password added") os.startTimer(2) os.pullEvent("timer") break else print("Passwords do not match") os.startTimer(2) os.pullEvent("timer") end end while true do term.clear() print("Type 'finished' to stop account entry") local pw = getInput("Password:","*") if pw == "finished" then break end local pw2 = getInput("Again:","*") if pw2 == "finished" then break end if pw == pw2 then table.insert(accounts,hash(pw..salt)) saveAccounts() print("Password added") os.startTimer(2) os.pullEvent("timer") else print("Passwords do not match") os.startTimer(2) os.pullEvent("timer") end end end local tArgs = {...} if #tArgs == 1 and tArgs[1] == "-setup" then initialSetup() elseif #tArgs ~= 0 then print("Usage: "..fs.getName(shell.getRunningProgram())) print("Usage: "..fs.getName(shell.getRunningProgram()).." -setup") error() end if not fs.exists(passFile) or not fs.exists(configFile) then initialSetup() else loadConfig() loadAccounts() end local sw, sh = term.getSize() local text local errorString local errorStringTimer local function reset() text = "" trollString = "" errorString = "" errorStringTimer = os.startTimer(0) rs.setOutput(rsOutput, false) end local function checkDisk() for _,v in pairs(rs.getSides()) do if peripheral.getType(v) == "drive" and disk.isPresent(v) and disk.hasData(v) then local path = disk.getMountPath(v) if fs.exists(path.."/startup") then if fs.exists(path.."/goodTry_startup") then fs.delete(path.."/goodTry_startup") end fs.move(path.."/startup", path.."/goodTry_startup") disk.eject(v) return true end end end return false end reset() while true do local w,h = term.getSize() term.clear() if adv then term.setTextColor(colors.yellow) end cwrite(welcomeMessage or "None found", 2) printRecognition() if adv then term.setTextColor(colors.white) end term.setCursorPos(6, h / 2) write("Password: "..string.rep( "*", math.min(#text, w-22))) if not canDiskStay and checkDisk() then trollString = "Error: Disks with a startup file are not allowed!" errsorStringTimer = os.startTimer(4) end if adv then term.setTextColor(colors.red) end term.setCursorPos(2, h) write(errorString) term.setCursorPos(2, h - 2) write(trollString) if adv then term.setTextColor(colors.white) end local event = { os.pullEventRaw() } if event[1] == "char" then text = text..event[2] elseif event[1] == "key" then if errorString ~= "Error: Cannot terminate!" then errorString = "" end if event[2] == keys.backspace then text = text:sub(1, text:len() - 1) elseif event[2] == keys.enter then local attempt = hash(text..salt) if checkPass( attempt ) then rs.setOutput(rsOutput, true) local waitTimer = os.startTimer(3) term.setCursorPos(6, h/2) term.clearLine() if adv then term.setTextColor(colors.lime) end cwrite("ACCESS GRANTED",h/2) while true do event = { os.pullEventRaw() } if event[1] == "timer" and event[2] == waitTimer then break end end reset() else if attempt == terminatePass then term.clear() if adv then term.setTextColor(colors.yellow) end print("Terminal Access") term.clear = term.native.clear error() else text = "" errorString = "Error: Incorrect Password" errorStringTimer = os.startTimer(4) end end end elseif event[1] == "timer" and event[2] == errorStringTimer then errorString = "" trollString = "" elseif event[1] == "terminate" then text = "" errorString = "Error: Cannot terminate!" errorStringTimer = os.startTimer(2) end end