Advertisement
Xandaros

FTP Server ComputerCraft

Sep 1st, 2012
420
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 8.12 KB | None | 0 0
  1. local connections = {}
  2. local validusers = {}
  3. local protected= {"/users", "/logs"}
  4. local userdir = "/users"
  5. local logdir = "/logs"
  6. local logfile
  7.  
  8. --[[
  9. rednet_message:
  10.     source id
  11.     message
  12.     distance
  13. ]]
  14.  
  15. local function validUser(username)
  16.     for k,v in pairs(validusers) do
  17.         if k == username then return true end
  18.     end
  19.     return false
  20. end
  21.  
  22. local function split(s, del)
  23.     local ret = {}
  24.     local del = del or " "
  25.     local pattern = string.format("([^%s]+)", del)
  26.     s:gsub(pattern, function(c) ret[#ret+1] = c end)
  27.     return ret
  28. end
  29.  
  30. local function log(s)
  31.     logfile:write(s .. "\n")
  32.     print(s)
  33.     --logfile:flush()
  34. end
  35.  
  36. local function send(id, message)
  37.     os.sleep(0.1)
  38.     rednet.send(id, message)
  39. end
  40.  
  41. local function canRead(user)
  42.     if not user.permissions.read then
  43.         send(id, "532 Permission denied.")
  44.         return false
  45.     end
  46.     return true
  47. end
  48.  
  49. local function canWrite(user)
  50.     if not user.permissions.write then
  51.         send(id, "532 Permission denied.")
  52.         return false
  53.     end
  54.     return true
  55. end
  56.  
  57. local function isProtected(f)
  58.     for k,v in pairs(protected) do
  59.         if shell.resolve(v) == shell.resolve(f) then return true end
  60.     end
  61.     return false
  62. end
  63.  
  64. -- Load users
  65. local list = fs.list(userdir)
  66. for k,v in pairs(list) do
  67.     local filename = fs.combine(userdir, v)
  68.     local file = io.open(filename, "r")
  69.    
  70.     local user = {
  71.         username = file:read():lower(),
  72.         password = file:read(),
  73.         permissions = {
  74.             read = file:read() == "1",
  75.             write = file:read() == "1"
  76.         }
  77.     }
  78.    
  79.     validusers[user.username:lower()] = user
  80. end
  81.  
  82. -- Open log
  83. local i = 1
  84. while true do
  85.     list = fs.list(logdir)
  86.     local found = true
  87.     for k,v in pairs(list) do
  88.         if tonumber(v) == i then
  89.             found = false
  90.             break
  91.         end
  92.     end
  93.     if found then
  94.         logfile = io.open(fs.combine(logdir,i),"w")
  95.         break
  96.     end
  97.     i = i + 1
  98. end
  99.  
  100. -- Clear terminal
  101. rednet.open("top")
  102. term.clear()
  103. term.setCursorPos(1,1)
  104.  
  105. print("Server started")
  106.  
  107. -- Mainloop
  108. while true do
  109.     local event,id,message,distance = os.pullEvent()
  110.     if event == "rednet_message" then
  111.         local conn = connections[id]
  112.         local user
  113.         if conn ~= nil then user = conn.user end
  114.         if conn == nil then
  115.             -- New connection
  116.             if validUser(message:lower()) then
  117.                 local newconnection = {}
  118.                 newconnection.id = id
  119.                 newconnection.user = validusers[message:lower()]
  120.                 newconnection.idle = 0
  121.                
  122.                 local pwd = validusers[message:lower()].password
  123.                 if pwd == "" or pwd == nil then
  124.                     send(id, "230 Login successful.")
  125.                     newconnection.connected = true
  126.                     newconnection.dir = "/"
  127.                     newconnection.waiting = false
  128.                     log(message:lower() .. " logged in from " .. id .. ".")
  129.                 else
  130.                     send(id, "331 Password required for " .. message .. ".")
  131.                     newconnection.connected = false
  132.                 end
  133.                 connections[id] = newconnection
  134.             else
  135.                 send(id, "332 Need account for login.")
  136.             end
  137.         elseif conn.connected == false or conn.connected == nil then
  138.             -- Password
  139.             local username = user.username
  140.             if validusers[username].password == message then
  141.                 conn.connected = true
  142.                 conn.waiting = false
  143.                 conn.dir = "/"
  144.                 send(id, "230 Login successful.")
  145.                 log(username .. " logged in from " .. id .. ".")
  146.             else
  147.                 send(id, "332 Need account for login.")
  148.                 connections[id] = nil
  149.                 log("Connection from " .. id .. " entered wrong password for " .. username .. ".")
  150.             end
  151.         else
  152.             if conn.waiting then
  153.                 conn.waiting = false
  154.                 local handle = conn.handle
  155.                 conn.handle = nil
  156.                
  157.                 handle:write(message)
  158.                 handle:close()
  159.                 send(id, "200 OK.")
  160.             else
  161.                 local username = user.username
  162.                 local cmdparams = split(message, " ")
  163.                 local cmd = cmdparams[1] or ""
  164.                 cmd = cmd:lower()
  165.                
  166.                 if cmd == "bye" or cmd == "quit" then
  167.                     send(id, "221 Goodbye.")
  168.                     connections[id] = nil
  169.                 elseif cmd == "cd" then
  170.                     if canRead(user) then
  171.                         local dir = cmdparams[2]
  172.                         if dir == nil then
  173.                             send(id, "501 Not enough parameters.")
  174.                         else
  175.                             local path = fs.combine(conn.dir, dir)
  176.                             if not fs.exists(path) then
  177.                                 send(id, "501 File or directory does not exist.")
  178.                             else
  179.                                 if not fs.isDir(path) then
  180.                                     send(id, "501 Not a directory.")
  181.                                 else
  182.                                     if isProtected(path) then
  183.                                         send(id, "532 Permission denied.")
  184.                                     else
  185.                                         conn.dir = "/" .. path
  186.                                         send(id, "200 CD command successful.")
  187.                                     end
  188.                                 end
  189.                             end
  190.                         end
  191.                     end
  192.                 elseif cmd == "rm" then
  193.                     if canWrite(user) then
  194.                         local file = cmdparams[2]
  195.                         if file == nil then
  196.                             send(id, "501 Not enough parameters.")
  197.                         else
  198.                             file = fs.combine(conn.dir,file)
  199.                             if not fs.exists(file) then
  200.                                 send(id, "501 File or directory not found")
  201.                             else
  202.                                 if isProtected(file) then
  203.                                     send(id, "532 Permission denied.")
  204.                                 else
  205.                                     if fs.isReadOnly(file) then
  206.                                         send(id, "532 Permission denied.")
  207.                                     else
  208.                                         fs.delete(file)
  209.                                         send(id, "200 RM command successful.")
  210.                                         log(username .. " from " .. id .. " deleted " .. file .. ".")
  211.                                     end
  212.                                 end
  213.                             end
  214.                         end
  215.                     end
  216.                 elseif cmd == "get" then
  217.                     if canRead(user) then
  218.                         local file = cmdparams[2]
  219.                         if file == nil then
  220.                             send(id, "501 Not enough parameters.")
  221.                         else
  222.                             file = fs.combine(conn.dir,file)
  223.                             if not fs.exists(file) then
  224.                                 send(id, "501 File or directory not found.")
  225.                             else
  226.                                 if isProtected(file) then
  227.                                     send(id, "532 Permission denied.")
  228.                                 else
  229.                                     local handle = io.open(file, "r")
  230.                                     if not handle then
  231.                                         send(id, "501 Could not open file for reading.")
  232.                                     else
  233.                                         local content = handle:read("*a")
  234.                                         handle:close()
  235.                                         send(id, content)
  236.                                         send(id, "200 OK.")
  237.                                         log(username .. " from " .. id .. " downloaded " .. file .. ".")
  238.                                     end
  239.                                 end
  240.                             end
  241.                         end
  242.                     end
  243.                 elseif cmd == "ls" then
  244.                     if canRead(user) then
  245.                         local dir = cmdparams[2]
  246.                         if dir == nil then
  247.                             dir = conn.dir
  248.                         else
  249.                             dir = fs.combine(conn.dir, dir)
  250.                         end
  251.                        
  252.                         if not fs.exists(dir) then
  253.                             send(id, "501 File or directory not found.")
  254.                         else
  255.                             if isProtected(dir) then
  256.                                 send(id, "532 Permission denied.")
  257.                             else
  258.                                 local list = fs.list(dir)
  259.                                 for k,v in pairs(list) do
  260.                                     if fs.isDir(fs.combine(dir,v)) then
  261.                                         list[k] = "[" .. v .. "]"
  262.                                     end
  263.                                 end
  264.                                 local ret = table.concat(list, " ")
  265.                                 send(id, ret)
  266.                                 send(id, "200 LS command successful.")
  267.                             end
  268.                         end
  269.                     end
  270.                 elseif cmd == "mkdir" then
  271.                     if canWrite(user) then
  272.                         local file = cmdparams[2]
  273.                         if file == nil then
  274.                             send(id, "501 Not enough parameters.")
  275.                         else
  276.                             file = fs.combine(conn.dir, file)
  277.                             if fs.exists(file) then
  278.                                 send(id, "501 File exists.")
  279.                             else
  280.                                 if fs.isReadOnly(file) then
  281.                                     send(id, "532 Permission denied.")
  282.                                 else
  283.                                     fs.makeDir(file)
  284.                                     send(id, "200 MKDIR command successful.")
  285.                                     log(username .. " from " .. id .. " created directory " .. file .. ".")
  286.                                 end
  287.                             end
  288.                         end
  289.                     end
  290.                 elseif cmd == "put" then
  291.                     if canWrite(user) then
  292.                         local file = cmdparams[2]
  293.                         if file == nil then
  294.                             send(id, "501 Not enough parameters.")
  295.                         else
  296.                             file = fs.combine(conn.dir, file)
  297.                             if fs.isReadOnly(file) then
  298.                                 send(id, "532 Permission denied.")
  299.                             else
  300.                                 if isProtected(file) then
  301.                                     send(id, "532 Permission denied.")
  302.                                 else
  303.                                     conn.handle = io.open(file, "w")
  304.                                     if not conn.handle then
  305.                                         send(id, "501 Could not open file for writing.")
  306.                                     else
  307.                                         conn.waiting = true
  308.                                         send(id, "150 OK.")
  309.                                         log(username .. " from " .. id .. " uploaded " .. file .. ".")
  310.                                     end
  311.                                 end
  312.                             end
  313.                         end
  314.                     end
  315.                 elseif cmd == "pwd" then
  316.                     send(id, conn.dir)
  317.                     send(id, "200 OK.")
  318.                 else
  319.                     send(id, "500 Unknown command.")
  320.                 end
  321.             end
  322.         end
  323.     end
  324. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement