Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- function read( _sReplaceChar, _tHistory )
- term.setCursorBlink( true )
- local sLine = ""
- local nHistoryPos = nil
- local nPos = 0
- if _sReplaceChar then
- _sReplaceChar = string.sub( _sReplaceChar, 1, 1 )
- end
- local w, h = term.getSize()
- local sx, sy = term.getCursorPos()
- local function redraw( _sCustomReplaceChar )
- local nScroll = 0
- if sx + nPos >= w then
- nScroll = (sx + nPos) - w
- end
- local tx,ty = term.getCursorPos()
- if ty ~= sy and nPos == 0 then sy = ty + (ty - sy) end
- term.setCursorPos( sx, sy )
- local sReplace = _sCustomReplaceChar or _sReplaceChar
- if sReplace then
- term.write( string.rep(sReplace, string.len(sLine) - nScroll) )
- else
- term.write( string.sub( sLine, nScroll + 1 ) )
- end
- term.setCursorPos( sx + nPos - nScroll, sy )
- end
- while true do
- local sEvent, param = os.pullEvent()
- if sEvent == "char" then
- sLine = string.sub( sLine, 1, nPos ) .. param .. string.sub( sLine, nPos + 1 )
- nPos = nPos + 1
- redraw()
- elseif sEvent == "key" then
- if param == keys.enter then
- -- Enter
- break
- elseif param == keys.left then
- -- Left
- if nPos > 0 then
- nPos = nPos - 1
- redraw()
- end
- elseif param == keys.right then
- -- Right
- if nPos < string.len(sLine) then
- nPos = nPos + 1
- redraw()
- end
- elseif param == keys.up or param == keys.down then
- -- Up or down
- if _tHistory then
- redraw(" ");
- if param == keys.up then
- -- Up
- if nHistoryPos == nil then
- if #_tHistory > 0 then
- nHistoryPos = #_tHistory
- end
- elseif nHistoryPos > 1 then
- nHistoryPos = nHistoryPos - 1
- end
- else
- -- Down
- if nHistoryPos == #_tHistory then
- nHistoryPos = nil
- elseif nHistoryPos ~= nil then
- nHistoryPos = nHistoryPos + 1
- end
- end
- if nHistoryPos then
- sLine = _tHistory[nHistoryPos]
- nPos = string.len( sLine )
- else
- sLine = ""
- nPos = 0
- end
- redraw()
- end
- elseif param == keys.backspace then
- -- Backspace
- if nPos > 0 then
- redraw(" ");
- sLine = string.sub( sLine, 1, nPos - 1 ) .. string.sub( sLine, nPos + 1 )
- nPos = nPos - 1
- redraw()
- end
- elseif param == keys.home then
- -- Home
- nPos = 0
- redraw()
- elseif param == keys.delete then
- if nPos < string.len(sLine) then
- redraw(" ");
- sLine = string.sub( sLine, 1, nPos ) .. string.sub( sLine, nPos + 2 )
- redraw()
- end
- elseif param == keys["end"] then
- -- End
- nPos = string.len(sLine)
- redraw()
- end
- end
- end
- term.setCursorBlink( false )
- term.setCursorPos( w + 1, sy )
- print()
- return sLine
- end
- local args={...}
- local function log(s)
- local f = fs.open("ftp_log","a")
- f.writeLine(s)
- f.close()
- print(s)
- end
- for k,v in pairs(rs.getSides()) do
- if peripheral.getType(v) == "modem" then
- rednetSide = v
- break
- end
- end
- if not rednetSide then print("Rednet is needed!") return end
- rednet.open(rednetSide)
- local clients = {}
- function auth(id,data)
- local u , pass = string.gmatch(data,"^(.-):(.+)$")()
- if pass == users[u] then
- log(u .. " connected with id ".. id)
- clients[id] = {user=u}
- return true
- else
- log("Attempt to log into " .. u .. " by id " .. id .. " failed!")
- return false
- end
- end
- function getDir(file)
- return string.gsub(file,fs.getName(file).."/","")
- end
- function getPerms(file)
- if string.find(file,"/") == nil then
- if perms[file] then
- return perms[fix(file)]
- else
- return {write="all",read="all"}
- end
- end
- if perms[fix(getDir(file))] then
- if perms[fix(file)] then
- return perms[fix(file)]
- else
- return perms[fix(getDir(file))]
- end
- else
- return {write="all",read="all"}
- end
- end
- function hasRead(file, user)
- local perms = getPerms(file).read
- if perms == "all" then
- return true
- elseif perms == "logged_in" then
- return user~=nil
- elseif type(perms) == "table" then
- for k,v in pairs(perms) do
- if user == v then return true end
- end
- return false
- end
- end
- function hasWrite(file, user)
- local perms = getPerms(file).write
- if perms == "all" then
- return true
- elseif perms == "logged_in" then
- return user~=nil
- elseif type(perms) == "table" then
- for k,v in pairs(perms) do
- if user == v then return true end
- end
- return false
- end
- end
- function put(id,data)
- local filename ,contents = string.gmatch(data,"^(.-):(.+)$")()
- local user
- if clients[id] then
- user=clients[id].user
- end
- if not hasWrite(filename,user) then
- local first = "User "
- if not user then
- user = "An anonymous user"
- first = ""
- end
- log(first .. user .. " tried to write forbidden file " ..filename)
- return false
- else
- local f = fs.open(filename,"w")
- f.write(contents)
- f.close()
- return true
- end
- end
- function get(id,data)
- local filename = data
- local user
- if clients[id] then
- user=clients[id].user
- end
- if not hasRead(filename,user) then
- local first = "User "
- if not user then
- user = "An anonymous user"
- first = ""
- end
- log(first .. user .. " tried to read forbidden file ".. filename)
- else
- local f = fs.open(filename,"r")
- rednet.send(id,"DATA " .. filename .. ":" .. f.readAll())
- f.close()
- end
- end
- function list(id,data)
- local dir = data
- local s = ""
- if not hasRead(dir,user) then
- local first = "User "
- if not user then
- user = "An anonymous user"
- first = ""
- end
- log(first .. user .. " tried to list forbidden dir ".. dir)
- else
- for k,v in pairs(fs.list(data)) do
- s = s .. v .. " "
- end
- rednet.send(id,"LIST " .. s)
- end
- end
- function host()
- while true do
- local clientID,msg = rednet.receive()
- print(clientID," ",msg)
- if msg:sub(1,7) == "CONNECT" then
- if auth(clientID,msg:sub(9)) then
- rednet.send(clientID,"ACCEPT")
- else
- rednet.send(clientID,"DENY")
- end
- elseif msg:sub(1,3) == "GET" then
- get(clientID,msg:sub(5))
- elseif msg:sub(1,3) == "PUT" then
- put(clientID,msg:sub(5))
- elseif msg:sub(1,4) == "QUIT" then
- clients[clientID] = nil
- elseif msg:sub(1,4) == "LIST" then
- list(clientID,msg:sub(5))
- elseif msg:sub(1,2) == "CD" then
- if fs.exists(msg:sub(4)) or msg:sub(4) == "/" or msg:sub(4) == "" then
- rednet.send(clientID,"DIR " .. msg:sub(4))
- end
- end
- end
- end
- function client()
- while true do
- local serverID,msg = rednet.receive()
- if msg == "ACCEPT" then
- print("Connection accepted.")
- elseif msg == "DENY" then
- print("Permission denied.")
- elseif msg:sub(1,4) == "DATA" then
- local filename,content = string.gmatch(msg:sub(6),"^(.-):(.+)$")()
- local f = fs.open(filename,"w")
- f.write(content)
- f.close()
- print("Wrote " .. filename)
- elseif msg:sub(1,3) == "DIR" then
- curDir = msg:sub(5)
- elseif msg:sub(1,4) == "LIST" then
- print(msg:sub(6))
- end
- end
- end
- function readFile(name)
- local f = fs.open(name,"r")
- local r = f.readAll()
- f.close()
- return r
- end
- local curDir = ""
- function toCmd(line)
- if string.lower(line:sub(1,3)) == "get" then
- return "GET " .. line:sub(5)
- elseif string.lower(line:sub(1,3)) == "put" then
- return "PUT " .. line:sub(5) .. ":" .. readFile(line:sub(5))
- elseif string.lower(line:sub(1,4)) == "list" then
- return "LIST " .. curDir
- elseif string.lower(line:sub(1,2)) == "cd" then
- curDir = line:sub(4)
- end
- end
- function input()
- while true do
- local line = read()
- local cmd=toCmd(line)
- if cmd then
- rednet.send(server,cmd)
- end
- end
- end
- if #args >= 1 then
- if args[1] == "host" then
- local f= fs.open("users","r")
- users = textutils.unserialize(f.readAll())
- f.close()
- f = fs.open("perms","r")
- perms = textutils.unserialize(f.readAll())
- f.close()
- host()
- else
- local id = tonumber(args[1])
- io.write("Username: ")
- local user = read()
- io.write("Password: ")
- local pass = read("*")
- rednet.send(id,"CONNECT "..user..":"..pass)
- parallel.waitForAny(client,input)
- end
- else
- print("Usage: ftp host|<id>")
- end
- rednet.close(rednetSide)
Advertisement
Add Comment
Please, Sign In to add comment