Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local connections = {}
- local validusers = {}
- local protected= {"/users", "/logs"}
- local userdir = "/users"
- local logdir = "/logs"
- local logfile
- --[[
- rednet_message:
- source id
- message
- distance
- ]]
- local function validUser(username)
- for k,v in pairs(validusers) do
- if k == username then return true end
- end
- return false
- end
- local function split(s, del)
- local ret = {}
- local del = del or " "
- local pattern = string.format("([^%s]+)", del)
- s:gsub(pattern, function(c) ret[#ret+1] = c end)
- return ret
- end
- local function log(s)
- logfile:write(s .. "\n")
- print(s)
- --logfile:flush()
- end
- local function send(id, message)
- os.sleep(0.1)
- rednet.send(id, message)
- end
- local function canRead(user)
- if not user.permissions.read then
- send(id, "532 Permission denied.")
- return false
- end
- return true
- end
- local function canWrite(user)
- if not user.permissions.write then
- send(id, "532 Permission denied.")
- return false
- end
- return true
- end
- local function isProtected(f)
- for k,v in pairs(protected) do
- if shell.resolve(v) == shell.resolve(f) then return true end
- end
- return false
- end
- -- Load users
- local list = fs.list(userdir)
- for k,v in pairs(list) do
- local filename = fs.combine(userdir, v)
- local file = io.open(filename, "r")
- local user = {
- username = file:read():lower(),
- password = file:read(),
- permissions = {
- read = file:read() == "1",
- write = file:read() == "1"
- }
- }
- validusers[user.username:lower()] = user
- end
- -- Open log
- local i = 1
- while true do
- list = fs.list(logdir)
- local found = true
- for k,v in pairs(list) do
- if tonumber(v) == i then
- found = false
- break
- end
- end
- if found then
- logfile = io.open(fs.combine(logdir,i),"w")
- break
- end
- i = i + 1
- end
- -- Clear terminal
- rednet.open("top")
- term.clear()
- term.setCursorPos(1,1)
- print("Server started")
- -- Mainloop
- while true do
- local event,id,message,distance = os.pullEvent()
- if event == "rednet_message" then
- local conn = connections[id]
- local user
- if conn ~= nil then user = conn.user end
- if conn == nil then
- -- New connection
- if validUser(message:lower()) then
- local newconnection = {}
- newconnection.id = id
- newconnection.user = validusers[message:lower()]
- newconnection.idle = 0
- local pwd = validusers[message:lower()].password
- if pwd == "" or pwd == nil then
- send(id, "230 Login successful.")
- newconnection.connected = true
- newconnection.dir = "/"
- newconnection.waiting = false
- log(message:lower() .. " logged in from " .. id .. ".")
- else
- send(id, "331 Password required for " .. message .. ".")
- newconnection.connected = false
- end
- connections[id] = newconnection
- else
- send(id, "332 Need account for login.")
- end
- elseif conn.connected == false or conn.connected == nil then
- -- Password
- local username = user.username
- if validusers[username].password == message then
- conn.connected = true
- conn.waiting = false
- conn.dir = "/"
- send(id, "230 Login successful.")
- log(username .. " logged in from " .. id .. ".")
- else
- send(id, "332 Need account for login.")
- connections[id] = nil
- log("Connection from " .. id .. " entered wrong password for " .. username .. ".")
- end
- else
- if conn.waiting then
- conn.waiting = false
- local handle = conn.handle
- conn.handle = nil
- handle:write(message)
- handle:close()
- send(id, "200 OK.")
- else
- local username = user.username
- local cmdparams = split(message, " ")
- local cmd = cmdparams[1] or ""
- cmd = cmd:lower()
- if cmd == "bye" or cmd == "quit" then
- send(id, "221 Goodbye.")
- connections[id] = nil
- elseif cmd == "cd" then
- if canRead(user) then
- local dir = cmdparams[2]
- if dir == nil then
- send(id, "501 Not enough parameters.")
- else
- local path = fs.combine(conn.dir, dir)
- if not fs.exists(path) then
- send(id, "501 File or directory does not exist.")
- else
- if not fs.isDir(path) then
- send(id, "501 Not a directory.")
- else
- if isProtected(path) then
- send(id, "532 Permission denied.")
- else
- conn.dir = "/" .. path
- send(id, "200 CD command successful.")
- end
- end
- end
- end
- end
- elseif cmd == "rm" then
- if canWrite(user) then
- local file = cmdparams[2]
- if file == nil then
- send(id, "501 Not enough parameters.")
- else
- file = fs.combine(conn.dir,file)
- if not fs.exists(file) then
- send(id, "501 File or directory not found")
- else
- if isProtected(file) then
- send(id, "532 Permission denied.")
- else
- if fs.isReadOnly(file) then
- send(id, "532 Permission denied.")
- else
- fs.delete(file)
- send(id, "200 RM command successful.")
- log(username .. " from " .. id .. " deleted " .. file .. ".")
- end
- end
- end
- end
- end
- elseif cmd == "get" then
- if canRead(user) then
- local file = cmdparams[2]
- if file == nil then
- send(id, "501 Not enough parameters.")
- else
- file = fs.combine(conn.dir,file)
- if not fs.exists(file) then
- send(id, "501 File or directory not found.")
- else
- if isProtected(file) then
- send(id, "532 Permission denied.")
- else
- local handle = io.open(file, "r")
- if not handle then
- send(id, "501 Could not open file for reading.")
- else
- local content = handle:read("*a")
- handle:close()
- send(id, content)
- send(id, "200 OK.")
- log(username .. " from " .. id .. " downloaded " .. file .. ".")
- end
- end
- end
- end
- end
- elseif cmd == "ls" then
- if canRead(user) then
- local dir = cmdparams[2]
- if dir == nil then
- dir = conn.dir
- else
- dir = fs.combine(conn.dir, dir)
- end
- if not fs.exists(dir) then
- send(id, "501 File or directory not found.")
- else
- if isProtected(dir) then
- send(id, "532 Permission denied.")
- else
- local list = fs.list(dir)
- for k,v in pairs(list) do
- if fs.isDir(fs.combine(dir,v)) then
- list[k] = "[" .. v .. "]"
- end
- end
- local ret = table.concat(list, " ")
- send(id, ret)
- send(id, "200 LS command successful.")
- end
- end
- end
- elseif cmd == "mkdir" then
- if canWrite(user) then
- local file = cmdparams[2]
- if file == nil then
- send(id, "501 Not enough parameters.")
- else
- file = fs.combine(conn.dir, file)
- if fs.exists(file) then
- send(id, "501 File exists.")
- else
- if fs.isReadOnly(file) then
- send(id, "532 Permission denied.")
- else
- fs.makeDir(file)
- send(id, "200 MKDIR command successful.")
- log(username .. " from " .. id .. " created directory " .. file .. ".")
- end
- end
- end
- end
- elseif cmd == "put" then
- if canWrite(user) then
- local file = cmdparams[2]
- if file == nil then
- send(id, "501 Not enough parameters.")
- else
- file = fs.combine(conn.dir, file)
- if fs.isReadOnly(file) then
- send(id, "532 Permission denied.")
- else
- if isProtected(file) then
- send(id, "532 Permission denied.")
- else
- conn.handle = io.open(file, "w")
- if not conn.handle then
- send(id, "501 Could not open file for writing.")
- else
- conn.waiting = true
- send(id, "150 OK.")
- log(username .. " from " .. id .. " uploaded " .. file .. ".")
- end
- end
- end
- end
- end
- elseif cmd == "pwd" then
- send(id, conn.dir)
- send(id, "200 OK.")
- else
- send(id, "500 Unknown command.")
- end
- end
- end
- end
- end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement