local mainPath = ".sysmail" local yourID = os.getComputerID() local onlyUseWiredModems = false local config = { channel = 1024, keyPath = fs.combine(mainPath, "keys"), mailPath = fs.combine(mainPath, "mail"), apiPath = fs.combine(mainPath, "api") } local keys = {} local readFile = function(path) local file = fs.open(path, "r") local contents = file.readAll() file.close() return contents end local writeFile = function(path, contents) if fs.isReadOnly(path) then return false else local file = fs.open(path, "w") file.write(contents) file.close() return true end end local makeKey = function(ID, key) return writeFile(fs.combine(config.keyPath, ID), key) end local getKey = function(ID) return readFile(fs.combine(config.keyPath, ID)) end -- get personal key file local key = "" if fs.exists(fs.combine(config.keyPath, tostring(yourID))) then key = readFile(fs.combine(config.keyPath, tostring(yourID))) else for i = 1, 64 do key = key .. string.char(math.random(11, 255)) end writeFile(fs.combine(config.keyPath, tostring(yourID)), key) end local apiData = { ["aes"] = { path = "aes.lua", url = "http://pastebin.com/raw/9E5UHiqv", } } for name, data in pairs(apiData) do data.path = fs.combine(config.apiPath, data.path) if not fs.exists(data.path) then local net = http.get(data.url) if net then local file = fs.open(data.path, "w") file.write(net.readAll()) file.close() net.close() else error("Could not download " .. name) end end _ENV[name] = dofile(data.path) end local function interpretArgs(tInput, tArgs) local output = {} local errors = {} local usedEntries = {} for aName, aType in pairs(tArgs) do output[aName] = false for i = 1, #tInput do if not usedEntries[i] then if tInput[i] == aName and not output[aName] then if aType then usedEntries[i] = true if type(tInput[i+1]) == aType or type(tonumber(tInput[i+1])) == aType then usedEntries[i+1] = true if aType == "number" then output[aName] = tonumber(tInput[i+1]) else output[aName] = tInput[i+1] end else output[aName] = nil errors[1] = errors[1] and (errors[1] + 1) or 1 errors[aName] = "expected " .. aType .. ", got " .. type(tInput[i+1]) end else usedEntries[i] = true output[aName] = true end end end end end for i = 1, #tInput do if not usedEntries[i] then output[#output+1] = tInput[i] end end return output, errors end local argList = { ["--server"] = false } local argData, argErrors = interpretArgs({...}, argList) local isServer = argData["--server"] local modem local getModem = function(doNotPickWireless) local output, periphList for try = 1, 40 do periphList = peripheral.getNames() for i = 1, #periphList do if peripheral.getType(periphList[i]) == "modem" then output = peripheral.wrap(periphList[i]) if not (doNotPickWireless and output.isWireless()) then output.open(config.channel) return output end end end sleep(0.15) end error("No modems were found after 40 tries. That's as many as four tens. And that's terrible.") end -- allowed IDs local userIDs = {} -- all data recorded local DATA = {} local transmit = function(msg) modem = getModem(onlyUseWiredModems) modem.transmit(config.channel, config.channel, { msg = msg, encrypted = false }) end local encTransmit = function(msg, recipient) modem = getModem(onlyUseWiredModems) modem.transmit(config.channel, config.channel, { msg = aes.encrypt(key, msg), encrypted = true }) end local handle = { client = {}, server = {} } handle.client.findServer = function(recipient) local msgID = math.random(1, 2^30) transmit({ id = yourID, command = "find_server", msgID = msgID, }) local evt, msg local timerID = os.startTimer(2) while true do evt = {os.pullEvent()} if evt[1] == "modem_message" then if evt[5].encrypted then msg = evt[5].msg else msg = evt[5].msg end elseif evt[1] == "timer" and evt[2] == timerID then return false end end end handle.server.registerID = function(id) local path = fs.combine(config.mailPath, id) if not fs.exists(path) then fs.makeDir(path) end end -- records a full email to file handle.server.recordMail = function(sender, recipient, message, subject, attachment) -- sender: The person who sends the message -- recipient: The message will be put in their folder -- subject: The header of a message -- message: the fuck you think it is -- attachment: Contents of a SINGLE file that will be attached to an email local path = fs.combine(config.mailPath, recipient) handle.server.registerID(recipient) local time = os.epoch("utc") local file = fs.open(fs.combine(path, time), "w") file.write(textutils.serialize({ sender = id, time = time, recipient = recipient, read = false, subject = subject, message = message, attachment = attachment })) end -- returns every email in an inbox handle.server.getMail = function(id) local output, list = {}, {} local mails = fs.list(fs.combine(config.mailPath, id)) local file for k,v in pairs(mails) do list[v] = k end for k,v in pairs(list) do file = fs.open(fs.combine(config.mailPath, "/" .. id .. "/" .. k), "r") if file then output[#output + 1] = textutils.unserialize(file.readAll()) file.close() end end return output end -- receives messages and sends the appropriate response handle.server.networking = function() local evt, _msg, msg while true do evt = {os.pullEvent()} if evt[1] == "modem_message" then _msg = evt[5] if type(_msg) == "table" then if _msg.msg and type(_msg.encrypted) == "boolean" then if _msg.encrypted then msg = _msg.msg else msg = aes.decrypt(key, _msg.msg) end if msg then -- add more commands if msg.command == "find_server" then -- send the server ID end end end end end end end if isServer then handle.server.networking() else -- make a whole client interface and shit end