Guest User

Untitled

a guest
May 12th, 2013
77
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 22.25 KB | None | 0 0
  1. local ftp_client = [[
  2. -- socket_client class(client)
  3. local socket_client = {
  4.     _modem         = false;
  5.     _channel       = 0;
  6.     _reply_channel = 0;
  7.     _side          = "top";
  8.     _stack         = {};
  9. }
  10. socket_client.__index = socket_client
  11.  
  12. socket_client.__call = function(self, ch, rep_ch)
  13.     local sides = {
  14.         "right", "left",
  15.         "top", "bottom",
  16.         "front", "back"
  17.     }
  18.  
  19.     local m = nil
  20.     local side = "none"
  21.     for k, v in ipairs(sides) do
  22.         if peripheral.getType(v) == "modem" then
  23.             side = v
  24.             break
  25.         end
  26.     end
  27.  
  28.     if side == "none" then
  29.         return -1
  30.     end
  31.  
  32.     m = peripheral.wrap(side)
  33.  
  34.     local t = {
  35.         _channel = ch;
  36.         _reply_channel = rep_ch;
  37.         _side    = s or "top";
  38.         _modem   = m;
  39.     }
  40.     setmetatable(t, socket_client)
  41.  
  42.     return t
  43. end
  44.  
  45. function socket_client:connect(timeout)
  46.     if not self._modem then return end
  47.  
  48.     self:write("request_connect")
  49.     local timer_id = 0
  50.     if timeout then timer_id = os.startTimer(timeout) end
  51.  
  52.     while true do
  53.         local ev, p1, p2, p3, p4 = os.pullEvent()
  54.  
  55.         if timeout and ev == "timer" and p1 == timer_id then
  56.             return false
  57.         elseif ev == "modem_message" then
  58.             if p4:find("success") ~= nil then
  59.                 return true
  60.             end
  61.         end
  62.     end
  63.  
  64.     self._modem.closeAll()
  65.  
  66.     return false
  67. end
  68.  
  69. function socket_client:listen()
  70.     if not self._modem then return end
  71.  
  72.     self._modem.open(self._channel)
  73.     self._modem.open(self._reply_channel)
  74.  
  75.     while true do
  76.         local ev, p1, p2, p3, p4 = os.pullEvent("modem_message")
  77.         if p2 == self._reply_channel then
  78.             return p4
  79.         end
  80.     end
  81.  
  82.     self._modem.closeAll()
  83.  
  84.     return ""
  85. end
  86.  
  87. function socket_client:read()
  88.     return self:listen()
  89. end
  90.  
  91. function socket_client:write(msg)
  92.     if not self._modem then return end
  93.  
  94.     self._modem.open(self._channel)
  95.     self._modem.transmit(self._channel, self._reply_channel, msg)
  96.     self._modem.closeAll()
  97. end
  98. setmetatable(socket_client, socket_client)
  99.  
  100. local text_utils = {}
  101. text_utils.last = function(str, tok)
  102.     local pos = -1
  103.  
  104.     while str:find(tok, pos + 1) ~= nil do
  105.         pos = str:find(tok, pos + 1)
  106.     end
  107.  
  108.     return (pos < 0 and 0 or pos - 1)
  109. end
  110.  
  111. function string:split(sep)
  112.         local sep, fields = sep or ":", {}
  113.         local pattern = string.format("([^%s]+)", sep)
  114.         self:gsub(pattern, function(c) fields[#fields+1] = c end)
  115.         return fields
  116. end
  117.  
  118. local arg = {...}
  119.  
  120. if arg[1] ~= nil and arg[1]:lower() == "help" then
  121.     print("Usage:\nFTP_client [server channel] [client channel]")
  122.     return
  123. end
  124.  
  125. local ch = arg[1] == nil and 12 or (tonumber(arg[1]) == nil and 12 or tonumber(arg[1]))
  126. local reply_ch = arg[2] == nil and 13 or (tonumber(arg[2]) == nil and 13 or tonumber(arg[2]))
  127. local socket = socket_client(ch, reply_ch)
  128.  
  129. if type(socket) == "number" and socket == -1 then
  130.     print("No modem found.")
  131.     return
  132. end
  133.  
  134. local remote_dir = "/"
  135. local local_dir = shell.getRunningProgram():sub(0, text_utils.last(shell.getRunningProgram(), "/"))
  136. local history = {}
  137.  
  138. local function cmd_cd(c, str)
  139.     socket:write("cmd:" .. str)
  140.     local d = socket:read(1)
  141.     if d == -1 then
  142.         print("Error reading from server")
  143.     else
  144.         remote_dir = d
  145.     end
  146.  
  147.     return socket:read(1)
  148. end
  149.  
  150. local function cmd_ls(c, str)
  151.     socket:write("cmd:" .. str)
  152.     local l = socket:read(1)
  153.     if l == -1 then
  154.         print("Error reading from server.")
  155.     else
  156.         if l ~= "" then
  157.             print(l)
  158.         end
  159.     end
  160. end
  161.  
  162. local function cmd_lls(c, str)
  163.     local p = c[2]
  164.     if not fs.exists(local_dir .. (p and "/" .. p or "")) then
  165.         return "no_such_file"
  166.     end
  167.  
  168.     local l = fs.list(local_dir .. (p and "/" .. p or ""))
  169.     local s = ""
  170.     for k, v in ipairs(l) do
  171.         s = s .. v .. "\n"
  172.     end
  173.     s = s:sub(1, #s - 1)
  174.     print(s)
  175. end
  176.  
  177. local function cmd_mkdir(c, str)
  178.     socket:write("cmd:" .. str)
  179.     local l = socket:read(1)
  180.     if l == -1 then
  181.         print("Error reading from server.")
  182.     else
  183.         return l
  184.     end
  185. end
  186.  
  187. local function cmd_lcd(c, str)
  188.     local p = c[2]
  189.     if p == ".." then
  190.         local_dir = local_dir:sub(1, text_utils.last(local_dir, "/"))
  191.     elseif p ~= "." then
  192.         if fs.isDir(local_dir .. "/" .. p) then
  193.             local_dir = local_dir .. "/" .. p
  194.         else
  195.             return "no_such_file"
  196.         end
  197.     end
  198.  
  199.     return local_dir .. "/"
  200. end
  201.  
  202. local function cmd_delete(c, str)
  203.     socket:write("cmd:" .. str)
  204.     local l = socket:read(1)
  205.     if l == -1 then
  206.         print("Error reading from server.")
  207.     else
  208.         return l
  209.     end
  210. end
  211.  
  212. local function cmd_rmdir(c, str)
  213.     socket:write("cmd:" .. str)
  214.     local l = socket:read(1)
  215.     if l == -1 then
  216.         print("Error reading from server.")
  217.     else
  218.         return l
  219.     end
  220. end
  221.  
  222. local function cmd_put(c, str)
  223.     local t = os.time()
  224.     if not c[2] then
  225.         return "wrong_args"
  226.     end
  227.  
  228.     if fs.isDir(local_dir .. "/" .. c[2]) then
  229.         return "custom_err Cannot upload directory. Use 'rput' or 'mput' instead."
  230.     end
  231.  
  232.     if not fs.exists(local_dir .. "/" .. c[2]) then
  233.         return "no_such_file"
  234.     end
  235.  
  236.     socket:write("cmd:" .. str)
  237.     local l = socket:read(1)
  238.     if l == -1 then
  239.         print("Error reading from server.")
  240.         return "unknown_error"
  241.     elseif l == "ready" then
  242.         local f = io.open(local_dir .. "/" .. c[2], "r")
  243.         local data = f:read("*a")
  244.         f:close()
  245.  
  246.         socket:write(data)
  247.  
  248.         local res = socket:read(1)
  249.         if res == -1 then
  250.             return "unknown_error"
  251.         else
  252.             return (res == "" and "custom_err Wrote " .. #data .. " bytes in " .. (os.time() - t) * 0.0138 .. " seconds." or res)
  253.         end
  254.     else
  255.         return l
  256.     end
  257. end
  258.  
  259. local function putfiles(dir, abs)
  260.     local ret = cmd_mkdir({}, "mkdir " .. abs)
  261.     if ret ~= "" then return ret end
  262.  
  263.     local l = fs.list(dir)
  264.  
  265.     for k, v in ipairs(l) do
  266.         if fs.isDir(local_dir .. "/" .. dir .. "/" .. v) then
  267.             putfiles(local_dir .. "/" .. dir .. "/" .. v, abs .. "/" .. v)
  268.         else
  269.             local ret = cmd_put({"put", local_dir .. "/" .. dir .. "/" .. v, abs .. "/" .. v}, "put asd " .. abs .. "/" .. v)
  270.             if ret ~= "" then
  271.                 return ret
  272.             end
  273.         end
  274.     end
  275. end
  276.  
  277. local function cmd_rput(c, str)
  278.     if not c[2] then
  279.         return "wrong_args"
  280.     end
  281.  
  282.     if not fs.exists(local_dir .. "/" .. c[2]) then
  283.         return "no_such_file"
  284.     end
  285.  
  286.     if not fs.isDir(local_dir .. "/" .. c[2]) then
  287.         return "custom_err Given path is not a directory. Use 'put' instead."
  288.     end
  289.  
  290.     ret = putfiles(local_dir .. "/" .. c[2], c[3] or c[2])
  291.     return ret
  292. end
  293.  
  294. local function cmd_get(c, str)
  295.     if not c[2] then
  296.         return "wrong_args"
  297.     end
  298.  
  299.     if fs.isDir(local_dir .. "/" .. (c[3] or c[2])) then
  300.         return "custom_err Cannot overwrite directory."
  301.     end
  302.  
  303.     if fs.exists(local_dir .. "/" .. (c[3] or c[2])) then
  304.         io.write("Overwrite file '" .. (c[3] or c[2]) .. "? (y/n) ")
  305.         local ans = io.read()
  306.  
  307.         if ans:lower() ~= "y" and ans:lower() ~= "yes" then
  308.             return ""
  309.         end
  310.     end
  311.  
  312.     socket:write("cmd:" .. str)
  313.  
  314.     local ret = socket:read()
  315.     if ret == "ok" then
  316.         socket:write("ready")
  317.         local data = socket:read()
  318.  
  319.         local f = io.open(local_dir .. "/" .. (c[3] or c[2]), "w")
  320.         f:write(data)
  321.         f:close()
  322.  
  323.         ret = socket:read()
  324.         return ret
  325.     else
  326.         return ret
  327.     end
  328. end
  329.  
  330. local function cmd_rget(c, str)
  331.     if not c[2] then
  332.         return "wrong_args"
  333.     end
  334.  
  335.     if fs.isDir(local_dir .. "/" .. (c[3] or c[2])) then
  336.         return "custom_err Cannot overwrite directory."
  337.     end
  338.  
  339.     if fs.exists(local_dir .. "/" .. (c[3] or c[2])) then
  340.         io.write("Overwrite file '" .. (c[3] or c[2]) .. "? (y/n) ")
  341.         local ans = io.read()
  342.  
  343.         if ans:lower() ~= "y" and ans:lower() ~= "yes" then
  344.             return ""
  345.         end
  346.     end
  347.  
  348.     socket:write("cmd:" .. str)
  349.  
  350.     local ret = socket:read()
  351.  
  352.     if ret == "ok" then
  353.         socket:write("ready")
  354.         local p = socket:read()
  355.         while p ~= "__getfiles_done__" do
  356.             if p:sub(1, 1) == "d" then
  357.                 fs.makeDir(local_dir .. "/" .. p:sub(2))
  358.             else
  359.                 local data = socket:read()
  360.                 local f = io.open(local_dir .. "/" .. p:sub(2), "w")
  361.                 f:write(data)
  362.                 f:close()
  363.             end
  364.  
  365.             p = socket:read()
  366.         end
  367.  
  368.         ret = socket:read()
  369.  
  370.         return ret
  371.     else
  372.         return ret
  373.     end
  374. end
  375.  
  376. local help_text = {
  377.     ["cd"] = "Usage:\ncd <dir>\n\nChanges directory to <dir> on remote\nmachine.";
  378.  
  379.     ["lcd"] = "Usage:\ncd <dir>\n\nChanges directory to <dir> on local\nmachine.";
  380.  
  381.     ["ls"] = "Usage:\nls [dir]\n\nLists files in current directory on remote\nmachine.\nIf [dir] is provided, files in that directory\nwill be listed instead.";
  382.  
  383.     ["lls"] = "Usage:\nls [dir]\n\nLists files in current directory on local\nmachine.\nIf [dir] is provided, files in that directory\nwill be listed instead.";
  384.  
  385.     ["quit"] = "Usage:\nquit|bye\n\nCloses the connection and exists the program.";
  386.  
  387.     ["pwd"] = "Usage:\npwd\n\nPrints the current directory on the remote\nmachine.";
  388.  
  389.     ["mkdir"] = "Usage:\nmkdir <dir>\n\nCreates the directory <dir> on the remote\nmachine.";
  390.  
  391.     ["delete"] = "Usage:\ndelete <file>\n\nDeletes the file <file> on the remote machine.\nCannot delete directories.";
  392.  
  393.     ["rmdir"] = "Usage:\nrmdir <dir>\n\nRemoves the directory <dir> on the remote\nmachine. Cannot delete files.";
  394.  
  395.     ["put"] = "Usage:\nput <local/path> [remote/path]\n\nUploads a file to the remote machine.\nIf [remote/path] is specified, it will upload\nto that filename, otherwise it will upload to\nas <local/path> on remote machine.\nCannot upload directories.";
  396.  
  397.     ["rput"] = "Usage:\nrput|mput <local/path> [remote/path]\n\nUploads a directory to the remote machine.\nIf [remote/path] is specified, it will upload\nto that filename, otherwise it will upload to\nas <local/path> on remote machine.\nCannot upload single files.";
  398.  
  399.     ["get"] = "Usage:\nget <remote/path> [local/path]\n\nDownloads a single file from <remote/path> on\nthe remote machine. If [local/path] is specified,\nit will save there, otherwise in <remote/path>.\nCannot download directories. Use 'rget' or 'mget'.";
  400.  
  401.     ["rget"] = "Usage:\nrget|mget <remote/path>\n\nDownloads the directory <remote/path> from the\nremote machine. The directory is saved as\n<remote/path>";
  402. }
  403. help_text["bye"] = help_text["quit"]
  404. help_text["mput"] = help_text["rput"]
  405. help_text["mget"] = help_text["rget"]
  406.  
  407. local function cmd_help(c, str)
  408.     if c[2] ~= nil then
  409.         local text = help_text[c[2] ]
  410.         if text == nil then
  411.             return "custom_err No help available for '" .. c[2] .. "'"
  412.         end
  413.  
  414.         print(text .. "\n")
  415.  
  416.         return ""
  417.     end
  418.  
  419.     print("Help for FTP:\ncd <dir>      - change directory on remote\nlcd <dir>     - change directory locally\nls [dir]      - list files on remote\nlls [dir]     - list files locally\nquit/bye      - close connection\npwd           - print current remote dir\nmkdir <dir>   - create directory on remote\ndelete <file> - remove file on remote\nrmdir <dir>   - remove directory on remote\nput <file> [remote_file] - upload file\nrput/mput <dir> [remote_dir] - upload dir\nget <remote_file> [file] - download file\nhelp          - show this screen\nhelp <cmd>    - help for specific command\n")
  420.     return ""
  421. end
  422.  
  423. local function main()
  424.     print("Connecting...")
  425.     if socket:connect(2) == false then
  426.         return false
  427.     end
  428.  
  429.     while true do
  430.         io.write(local_dir .. "> ")
  431.         local cmd = read(nil, history)
  432.         table.insert(history, cmd)
  433.  
  434.         local w = string.split(cmd, " ")
  435.  
  436.  
  437.         local ret = ""
  438.  
  439.         if w[1] ~= nil then
  440.             if w[1]:lower() == "cd" then
  441.                 ret = cmd_cd(w, cmd)
  442.             elseif w[1]:lower() == "ls" then
  443.                 ret = cmd_ls(w, cmd)
  444.             elseif w[1]:lower() == "lls" then
  445.                 ret = cmd_lls(w, cmd)
  446.             elseif w[1]:lower() == "lcd" then
  447.                 ret = cmd_lcd(w, cmd)
  448.             elseif w[1]:lower() == "quit" or w[1]:lower() == "bye" then
  449.                 socket:write("request_disconnect")
  450.                 return true
  451.             elseif w[1]:lower() == "pwd" then
  452.                 print(remote_dir)
  453.             elseif w[1]:lower() == "mkdir" then
  454.                 ret = cmd_mkdir(w, cmd)
  455.             elseif w[1]:lower() == "delete" then
  456.                 ret = cmd_delete(w, cmd)
  457.             elseif w[1]:lower() == "rmdir" then
  458.                 ret = cmd_rmdir(w, cmd)
  459.             elseif w[1]:lower() == "put" then
  460.                 ret = cmd_put(w, cmd)
  461.             elseif w[1]:lower() == "mput" or w[1]:lower() == "rput" then
  462.                 ret = cmd_rput(w, cmd)
  463.             elseif w[1]:lower() == "get" then
  464.                 ret = cmd_get(w, cmd)
  465.             elseif w[1]:lower() == "rget" or w[1]:lower() == "mget" then
  466.                 ret = cmd_rget(w, cmd)
  467.             elseif w[1]:lower() == "help" or w[1] == "?" then
  468.                 ret = cmd_help(w, cmd)
  469.             else
  470.                 ret = "unknown_command"
  471.             end
  472.         end
  473.        
  474.         if ret == "unknown_error" then
  475.             print("Unknown error.")
  476.         elseif ret == "unknown_command" then
  477.             print("Unknown command. Try 'help'")
  478.         elseif ret == "wrong_args" then
  479.             print("Insufficient arguments. Try 'help'")
  480.         elseif ret == "no_such_file" then
  481.             print("No such file or directory.")
  482.         elseif ret == "invalid_path" then
  483.             print("Invalid path.")
  484.         elseif ret == "already_exists" then
  485.             print("File or directory already exists.")
  486.         elseif ret == "not_allowed" then
  487.             print("Insufficient permissions.")
  488.         elseif type(ret) == "string" and ret:sub(0, string.len("custom_err")) == "custom_err" then
  489.             print(ret:sub(string.len("custom_err") + 2))
  490.         end
  491.     end
  492.  
  493.     return true
  494. end
  495.  
  496. term.clear()
  497. term.setCursorPos(1, 1)
  498. print("Welcome to FTP!\nFor a list of commands, run 'help'")
  499. if main() == true then
  500.     term.clear()
  501.     term.setCursorPos(1, 1)
  502.     print("Thanks for using FTP!")
  503. else
  504.     print("Unable to connect.")
  505. end
  506. ]]
  507.  
  508. local ftp_server = [[
  509. local text_utils = {}
  510. text_utils.last = function(str, tok)
  511.     local pos = -1
  512.  
  513.     while str:find(tok, pos + 1) ~= nil do
  514.         pos = str:find(tok, pos + 1)
  515.     end
  516.  
  517.     return (pos < 0 and 0 or pos - 1)
  518. end
  519.  
  520. function string:split(sep)
  521.         local sep, fields = sep or ":", {}
  522.         local pattern = string.format("([^%s]+)", sep)
  523.         self:gsub(pattern, function(c) fields[#fields+1] = c end)
  524.         return fields
  525. end
  526.  
  527. -- Socket server class
  528. local socket_server = {
  529.     _modem         = false;
  530.     _channel       = -1;
  531.     _reply_channel = 0;
  532.     _side          = "top";
  533.     _connected     = false;
  534. }
  535. socket_server.__index = socket_server
  536.  
  537. socket_server.__call = function(self, rep_ch)
  538.     local sides = {
  539.         "right", "left",
  540.         "top", "bottom",
  541.         "front", "back"
  542.     }
  543.  
  544.     local m = nil
  545.     local side = "none"
  546.     for k, v in ipairs(sides) do
  547.         if peripheral.getType(v) == "modem" then
  548.             side = v
  549.             break
  550.         end
  551.     end
  552.  
  553.     if side == "none" then
  554.         return -1
  555.     end
  556.  
  557.     m = peripheral.wrap(side)
  558.  
  559.     local t = {
  560.         _side          = s or "top";
  561.         _reply_channel = rep_ch;
  562.         _modem         = m;
  563.     }
  564.     setmetatable(t, socket_server)
  565.  
  566.     return t
  567. end
  568.  
  569. function socket_server:accept(ch, timeout)
  570.     if self._connected then return end
  571.     if not self._modem then return end
  572.  
  573.     self._modem.open(ch)
  574.  
  575.     local timer_id = 0
  576.     if timeout then timer_id = os.startTimer(timeout) end
  577.  
  578.     while true do
  579.         local ev, p1, p2, p3, p4 = os.pullEvent()
  580.  
  581.         if timeout and ev == "timer" and p1 == timer_id then
  582.             return false
  583.         elseif ev == "modem_message" then
  584.             if p4:find("request_connect") ~= nil then
  585.                 print("Client connected on channel " .. p2)
  586.                 self._channel = p2
  587.                 self._connected = true
  588.                 self._modem.transmit(self._channel, self._reply_channel, "success")
  589.                 return true
  590.             end
  591.         end
  592.     end
  593.  
  594.     self._modem.closeAll()
  595.  
  596.     return false
  597. end
  598.  
  599. function socket_server:accept_any(timeout)
  600.     if self._connected then return end
  601.     if not self._modem then return end
  602.  
  603.     for i = 0, 1000 do
  604.         self._modem.open(i)
  605.     end
  606.  
  607.     local timer_id = 0
  608.     if timeout then timer_id = os.startTimer(timeout) end
  609.  
  610.     while true do
  611.         local ev, p1, p2, p3, p4 = os.pullEvent()
  612.  
  613.         if timeout and ev == "timer" and p1 == timer_id then
  614.             return false
  615.         elseif ev == "modem_message" then
  616.             if p4:find("request_connect") ~= nil then
  617.                 print("Client connected on channel " .. p3)
  618.                 self._channel = p3
  619.                 self._connected = true
  620.                 self._modem.transmit(self._channel, self._reply_channel, "success")
  621.                 return true
  622.             end
  623.         end
  624.     end
  625.  
  626.     self._modem.closeAll()
  627.  
  628.     return false
  629. end
  630.  
  631. function socket_server:listen()
  632.     if not self._modem then return end
  633.  
  634.     while true do
  635.         if self._channel ~= -1 then
  636.             self._modem.open(self._channel)
  637.             self._modem.open(self._reply_channel)
  638.  
  639.             local ev, p1, p2, p3, p4 = os.pullEvent("modem_message")
  640.             if p2 == self._reply_channel then
  641.                 return p4
  642.             end
  643.  
  644.             self._modem.closeAll()
  645.         end
  646.     end
  647.  
  648.     return ""
  649. end
  650.  
  651. function socket_server:read()
  652.     local r = self:listen()
  653.     if r == "request_disconnect" then
  654.         print("Client on channel ".. self._channel .. " disconnected.")
  655.         self._connected = false
  656.     end
  657.     return r
  658. end
  659.  
  660. function socket_server:write(msg)
  661.     if not self._modem then return end
  662.  
  663.     self._modem.open(self._channel)
  664.     self._modem.transmit(self._channel, self._reply_channel, msg)
  665.     self._modem.closeAll()
  666. end
  667. setmetatable(socket_server, socket_server)
  668.  
  669. local arg = {...}
  670.  
  671. _print = function(...)
  672.     if not bg then print(...) end
  673. end
  674.  
  675. if arg[2] == nil and arg[1] ~= nil and (arg[1]:lower() == "-b" or arg[1]:lower() == "--background") then
  676.     arg[3] = arg[1]
  677. end
  678.  
  679. if arg[1] ~= nil and arg[1]:lower() == "help" then
  680.     _print("Usage:\nFTP_server [channel] [options]\nIf the option -b is provided, the server will run in the background")
  681.     return
  682. end
  683.  
  684. local ch = arg[1] == nil and 12 or (tonumber(arg[1]) == nil and 12 or tonumber(arg[1]))
  685.  
  686. local server = socket_server(ch)
  687.  
  688. if type(server) == "number" and server == -1 then
  689.     _print("No modem found.")
  690.     return
  691. end
  692.  
  693. local dir = ""
  694. local bg = false
  695.  
  696. local function cd(p)
  697.     if p == ".." then
  698.         dir = dir:sub(1, text_utils.last(dir, "/"))
  699.     elseif p ~= "." then
  700.         if fs.isDir(dir .. "/" .. p) then
  701.             dir = dir .. "/" .. p
  702.         else
  703.             server:write(dir .. "/")
  704.             return "no_such_file"
  705.         end
  706.     end
  707.  
  708.     server:write(dir .. "/")
  709.     return dir .. "/"
  710. end
  711.  
  712. local function ls(p)
  713.     if not fs.exists(dir .. (p and "/" .. p or "")) then
  714.         server:write("")
  715.         return "no_such_file"
  716.     end
  717.  
  718.     local l = fs.list(dir .. (p and "/" .. p or ""))
  719.     local s = ""
  720.     for k, v in ipairs(l) do
  721.         s = s .. v .. "\n"
  722.     end
  723.     s = s:sub(1, #s - 1)
  724.     server:write(s)
  725.  
  726.     return ""
  727. end
  728.  
  729. local function mkdir(p)
  730.     if fs.exists(dir .. "/" .. p) then
  731.         return "already_exists"
  732.     end
  733.  
  734.     fs.makeDir(dir .. "/" .. p)
  735.  
  736.     return ""
  737. end
  738.  
  739. local function delete(p)
  740.     if not fs.exists(dir .. "/" .. p) then
  741.         return "no_such_file"
  742.     elseif fs.isReadOnly(dir .. "/" .. p) then
  743.         return "not_allowed"
  744.     elseif fs.isDir(dir .. "/" .. p) then
  745.         return "custom_err Cannot remove a directory. Use 'rmdir' instead."
  746.     end
  747.  
  748.     fs.delete(dir .. "/" .. p)
  749.  
  750.     return ""
  751. end
  752.  
  753. local function rmdir(p)
  754.     if not fs.exists(dir .. "/" .. p) then
  755.         return "no_such_file"
  756.     elseif fs.isReadOnly(dir .. "/" .. p) then
  757.         return "not_allowed"
  758.     elseif not fs.isDir(dir .. "/" .. p) then
  759.         return "custom_err Cannot remove a file. Use 'delete' instead."
  760.     end
  761.  
  762.     fs.delete(dir .. "/" .. p)
  763.  
  764.     return ""
  765. end
  766.  
  767. local function put(p)
  768.     if fs.isDir(dir .. "/" .. p) then
  769.         return "custom_err Cannot overwrite directory."
  770.     end
  771.  
  772.     server:write("ready")
  773.     local data = server:read()
  774.     local f = io.open(dir .. "/" .. p, "w")
  775.     f:write(data)
  776.     f:close()
  777.  
  778.     return ""
  779. end
  780.  
  781. local function get(p)
  782.     if not fs.exists(dir .. "/" .. p) then
  783.         return "no_such_file"
  784.     end
  785.  
  786.     if fs.isDir(dir .. "/" .. p) then
  787.         return "custom_err Cannot download directory. Use 'rget' or 'mget' instead."
  788.     end
  789.  
  790.     server:write("ok")
  791.     local ret = server:read()
  792.     if ret ~= "ready" then
  793.         return "unknown_err"
  794.     end
  795.  
  796.     local f = io.open(dir .. "/" .. p, "r")
  797.     local data = f:read("*a")
  798.     f:close()
  799.     server:write(data)
  800.  
  801.     return ""
  802. end
  803.  
  804. local function rget(p)
  805.     if not fs.exists(dir .. "/" .. p) then
  806.         return "no_such_file"
  807.     end
  808.  
  809.     if not fs.isDir(dir .. "/" .. p) then
  810.         return "custom_err Cannot download single files.\nUse 'get' instead."
  811.     end
  812.  
  813.     server:write("ok")
  814.  
  815.     local function getfiles(path)
  816.         server:write("d" .. path)
  817.         local l = fs.list(dir .. "/" .. path)
  818.  
  819.         for k, v in ipairs(l) do
  820.             if fs.isDir(dir .. "/" .. path .. "/" .. v) then
  821.                 getfiles(dir .. "/" .. path .. "/" .. v)
  822.             else
  823.                 server:write("f" .. path .. "/" .. v)
  824.  
  825.                 local ret = server:read()
  826.                 if ret ~= "ready" then
  827.                     return ret
  828.                 end
  829.  
  830.                 local f = io.open(dir .. "/" .. path .. "/" .. v, "r")
  831.                 local data = f:read("*a")
  832.                 f:close()
  833.  
  834.                 server:write(data)
  835.             end
  836.         end
  837.     end
  838.  
  839.     getfiles(p)
  840.     server:write("__getfiles_done__")
  841. end
  842.  
  843. local function main()
  844.     server:accept_any()
  845.  
  846.     while true do
  847.         if not server._connected then
  848.             server:accept_any()
  849.         end
  850.  
  851.         local msg = server:read()
  852.  
  853.         if msg:sub(1, 4) == "cmd:" then
  854.             local cmd = msg:sub(5)
  855.             _print("Command: " .. cmd)
  856.             cmd = string.split(cmd, " ")
  857.  
  858.             if cmd[1]:lower() == "cd" then
  859.                 if not cmd[2] then
  860.                     server:write("wrong_args")
  861.                 else
  862.                     local ret = cd(cmd[2])
  863.                     server:write(ret)
  864.                 end
  865.             elseif cmd[1]:lower() == "ls" then
  866.                 local ret = ls(cmd[2] or "")
  867.                 server:write(ret)
  868.             elseif cmd[1]:lower() == "mkdir" then
  869.                 if not cmd[2] then
  870.                     server:write("wrong_args")
  871.                 else
  872.                     local ret = mkdir(cmd[2])
  873.                     server:write(ret)
  874.                 end
  875.             elseif cmd[1]:lower() == "delete" then
  876.                 if not cmd[2] then
  877.                     server:write("wrong_args")
  878.                 else
  879.                     local ret = delete(cmd[2])
  880.                     server:write(ret)
  881.                 end
  882.             elseif cmd[1]:lower() == "rmdir" then
  883.                 if not cmd[2] then
  884.                     server:write("wrong_args")
  885.                 else
  886.                     local ret = rmdir(cmd[2])
  887.                     server:write(ret)
  888.                 end
  889.             elseif cmd[1]:lower() == "put" then
  890.                 if not cmd[2] then
  891.                     server:write("wrong_args")
  892.                 else
  893.                     local ret = put((cmd[3] ~= nil and cmd[3] or cmd[2]))
  894.                     server:write(ret)
  895.                 end
  896.             elseif cmd[1]:lower() == "get" then
  897.                 if not cmd[2] then
  898.                     server:write("wrong_args")
  899.                 else
  900.                     local ret = get(cmd[2])
  901.                     server:write(ret)
  902.                 end
  903.             elseif cmd[1]:lower() == "rget" or cmd[1]:lower() == "mget" then
  904.                 if not cmd[2] then
  905.                     server:write("wrong_args")
  906.                 else
  907.                     local ret = rget((cmd[3] ~= nil and cmd[3] or cmd[2]))
  908.                     server:write(ret)
  909.                 end
  910.             else
  911.                 server:write("unknown_command")
  912.             end
  913.         end
  914.     end
  915.  
  916.     return ""
  917. end
  918.  
  919. if arg[3] ~= nil and (arg[3]:lower() == "-b" or arg[3] == "--background") then
  920.     bg = true
  921.     term.clear()
  922.     term.setCursorPos(1, 1)
  923.     parallel.waitForAll(main, function() shell.run("shell") end)
  924. else
  925.     main()
  926. end
  927. ]]
  928.  
  929. local arg = {...}
  930.  
  931. if not arg[1] then print("Usage:\ninstall server|client") else
  932.     if arg[1]:lower() == "c" or arg[1]:lower() == "client" then
  933.         local f = io.open("ftp_client", "w")
  934.         f:write(ftp_client)
  935.         f:close()
  936.         print("Installed to 'ftp_client'.\nRun 'ftp_client help' for information about using it.")
  937.     elseif arg[1]:lower() == "s" or arg[1]:lower() == "server" then
  938.         local f = io.open("ftp_server", "w")
  939.         f:write(ftp_server)
  940.         f:close()
  941.         print("Installed to 'ftp_server'.\nRun 'ftp_server' help' for information about using it.")
  942.     end
  943. end
Advertisement
Add Comment
Please, Sign In to add comment