Kingdaro

clone

Dec 5th, 2012
439
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 5.70 KB | None | 0 0
  1. local args = {...}
  2. local allowExit = false
  3.  
  4. local function setColor(color)
  5.     -- shorthand color setting
  6.     if term.isColor() then
  7.         term.setTextColor(color)
  8.     end
  9. end
  10.  
  11. local function writeColor(...)
  12.     -- shorthand color writing
  13.     -- format: printColor(color1, 'text', color2, 'text', ...)
  14.     local curColor
  15.     for _, v in pairs{...} do
  16.         if type(v) == 'number' then
  17.             curColor = v
  18.         else
  19.             if curColor then
  20.                 setColor(curColor)
  21.             end
  22.             write(tostring(v))
  23.         end
  24.     end
  25. end
  26.  
  27. local function printColor(...)
  28.     -- same as writeColor but with a \n
  29.     writeColor(...)
  30.     print()
  31. end
  32.  
  33. local function openRednet()
  34.     -- shorthand rednet opening
  35.     for _, side in pairs(rs.getSides()) do
  36.         if peripheral.getType(side) == 'modem' then
  37.             rednet.open(side)
  38.             return side
  39.         end
  40.     end
  41.     printColor(colors.red, 'Please attach rednet modem')
  42. end
  43.  
  44. local function client(server)
  45.     -- password get
  46.     writeColor(colors.magenta, 'Password: ')   
  47.     setColor(colors.white)
  48.     local pass = read('*')
  49.    
  50.     printColor(colors.yellow, 'Sending clone request')
  51.    
  52.     -- request files from the server while sending pass as well
  53.     rednet.send(server, 'clone_req '..pass)
  54.    
  55.     -- listen for a sendback
  56.     -- only allow max 10 seconds of delay
  57.     local msg
  58.     repeat
  59.         local id, _msg = rednet.receive(10)
  60.         msg = _msg
  61.     until id == server or not id
  62.    
  63.     -- no message? probably timed out
  64.     if not msg then
  65.         printColor(colors.red, 'Request timed out')
  66.         return
  67.     end
  68.    
  69.     -- the uSER SHOULD STOP TRYING TO HACK THE SERVER oMG
  70.     if msg == 'clone_failed_pass' then
  71.         printColor(colors.red, 'Wrong password')
  72.         return
  73.     end
  74.    
  75.     printColor(colors.lime, 'Request successful')
  76.     printColor(colors.yellow, 'Writing files')
  77.    
  78.     -- get the program list and establish a directory for our new files
  79.     local programs = textutils.unserialize(msg)
  80.     local clonepath = 'cloned/'..server
  81.    
  82.     -- erase the current clone, then make a new one
  83.     if fs.exists(clonepath) then
  84.         fs.delete(clonepath)
  85.     end
  86.     fs.makeDir(clonepath)
  87.    
  88.     -- write ALL OF THE PROGRAMS!
  89.     for i=1, #programs do
  90.         local prog = programs[i]
  91.         local path = clonepath..'/'..prog.path
  92.    
  93.     -- because i can't directly write "cloned/254/stuff/stuff/more_stuff"
  94.     -- gotta make the directory for it first
  95.     local pathfolder = path:match('(.+)/')
  96.     if not fs.exists(pathfolder) then
  97.         fs.makeDir(pathfolder)
  98.     end
  99.    
  100.     -- PROCEED WITH THE WRITING
  101.         local file = fs.open(path, 'w')
  102.         if file then
  103.             file.write(prog.contents)
  104.             file.close()
  105.            
  106.             setColor(colors.lime)
  107.             printColor(colors.lime, 'Successfully wrote '..prog.path)
  108.         else
  109.         -- wtf why? :C
  110.             printColor(colors.red, 'Could not write '..prog.path)
  111.         end
  112.     end
  113.    
  114.     shell.setDir(clonepath)
  115. end
  116.  
  117. local function files()
  118.     printColor(colors.yellow, 'Generating file list')
  119.    
  120.     -- recursively make a file list
  121.     -- exclude specific directories
  122.     local filelist = {}
  123.    
  124.     local function genFiles(cdir)
  125.         for _, localpath in pairs(fs.list(cdir)) do
  126.             local path = fs.combine(cdir, localpath)
  127.        
  128.             if fs.isDir(path) then
  129.                 if not path:find('rom')
  130.                 and not path:find('cloned') then
  131.                     genFiles(path)
  132.                 end
  133.             else
  134.                 if not localpath:match('^/?%.') then
  135.                     local file = fs.open(path,'r')
  136.                     if file then
  137.                         table.insert(filelist, {
  138.                             path = path;
  139.                             contents = file.readAll()
  140.                         })
  141.                         file.close()
  142.                     else
  143.                         printColor(colors.red, 'Could not read '..path)
  144.                     end
  145.                 end
  146.             end
  147.         end
  148.     end
  149.    
  150.     genFiles '/'
  151.     return filelist
  152. end
  153.  
  154. local function server()
  155.     -- if there's a password file
  156.     -- read it and key it in to the read() function
  157.     -- by abusing events
  158.     local passfile = fs.open('.clone_pass','r')
  159.     if passfile then
  160.         for v in (passfile.readAll()):gmatch('.') do
  161.             os.queueEvent('char',v)
  162.         end
  163.         passfile.close()
  164.     end
  165.    
  166.     -- get a server password
  167.     writeColor(colors.magenta, 'Password: ')
  168.     setColor(colors.white)
  169.     local password = read('*')
  170.    
  171.     -- go ahead and key in a y if the saved password exists,
  172.     -- and n if otherwise
  173.     -- for convenience
  174.     os.queueEvent('char', passfile and 'y' or 'n')
  175.    
  176.     -- save the password to the file
  177.     -- if the user chooses to remember it
  178.     writeColor(colors.magenta, 'Remember password? [y/n] ')
  179.     setColor(colors.white)
  180.     local answer = read():lower():sub(1,1)
  181.    
  182.     if answer == 'y' then
  183.         local passfile = fs.open('.clone_pass','w')
  184.         if passfile then
  185.             passfile.write(password)
  186.             passfile.close()
  187.         end
  188.        
  189.     -- otherwise, delete the file
  190.     -- to prevent rememberance
  191.     elseif answer == 'n' then
  192.         if fs.exists('.clone_pass') then
  193.             fs.delete('.clone_pass')
  194.         end
  195.     end
  196.    
  197.     printColor(colors.lime, 'Hosting clone server')
  198.     printColor(colors.yellow, 'Press backspace to quit.')
  199.     allowExit = true
  200.    
  201.     -- loooOOOOOOOoooop
  202.     while true do
  203.         local id, msg = rednet.receive()
  204.        
  205.         printColor(colors.yellow, 'Request from '..id)
  206.        
  207.         local pass = msg:match('clone_req (.+)')
  208.         if pass == password then
  209.             printColor(colors.lime, 'Successful authentication')
  210.             local files = textutils.serialize(files())
  211.             printColor(colors.yellow, 'Sending files')
  212.             rednet.send(id, files)
  213.             printColor(colors.lime, 'Done')
  214.         else
  215.             printColor(colors.red, 'Access denied')
  216.             rednet.send(id, 'clone_failed_pass')
  217.         end
  218.     end
  219. end
  220.  
  221. local function exit()
  222.     -- when used with parallel,
  223.     -- allows exiting the program
  224.     -- at any time :D (when allowExit is true)
  225.    
  226.     repeat
  227.         local _, k = os.pullEvent('key')
  228.     until k == keys.backspace
  229.     and allowExit
  230. end
  231.  
  232. printColor(colors.yellow, 'Opening rednet')
  233. local modemSide = openRednet()
  234. if not modemSide then return end
  235.  
  236. if args[1] == 'host' then
  237.     parallel.waitForAny(server, exit)
  238. elseif tonumber(args[1]) then
  239.     client(tonumber(args[1]))
  240. else
  241.     print 'Usage: "clone <id>" or "clone host"'
  242. end
  243.  
  244. rednet.close(modemSide)
Advertisement
Add Comment
Please, Sign In to add comment