Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local args = {...}
- local allowExit = false
- local function setColor(color)
- -- shorthand color setting
- if term.isColor() then
- term.setTextColor(color)
- end
- end
- local function writeColor(...)
- -- shorthand color writing
- -- format: printColor(color1, 'text', color2, 'text', ...)
- local curColor
- for _, v in pairs{...} do
- if type(v) == 'number' then
- curColor = v
- else
- if curColor then
- setColor(curColor)
- end
- write(tostring(v))
- end
- end
- end
- local function printColor(...)
- -- same as writeColor but with a \n
- writeColor(...)
- print()
- end
- local function openRednet()
- -- shorthand rednet opening
- for _, side in pairs(rs.getSides()) do
- if peripheral.getType(side) == 'modem' then
- rednet.open(side)
- return side
- end
- end
- printColor(colors.red, 'Please attach rednet modem')
- end
- local function client(server)
- -- password get
- writeColor(colors.magenta, 'Password: ')
- setColor(colors.white)
- local pass = read('*')
- printColor(colors.yellow, 'Sending clone request')
- -- request files from the server while sending pass as well
- rednet.send(server, 'clone_req '..pass)
- -- listen for a sendback
- -- only allow max 10 seconds of delay
- local msg
- repeat
- local id, _msg = rednet.receive(10)
- msg = _msg
- until id == server or not id
- -- no message? probably timed out
- if not msg then
- printColor(colors.red, 'Request timed out')
- return
- end
- -- the uSER SHOULD STOP TRYING TO HACK THE SERVER oMG
- if msg == 'clone_failed_pass' then
- printColor(colors.red, 'Wrong password')
- return
- end
- printColor(colors.lime, 'Request successful')
- printColor(colors.yellow, 'Writing files')
- -- get the program list and establish a directory for our new files
- local programs = textutils.unserialize(msg)
- local clonepath = 'cloned/'..server
- -- erase the current clone, then make a new one
- if fs.exists(clonepath) then
- fs.delete(clonepath)
- end
- fs.makeDir(clonepath)
- -- write ALL OF THE PROGRAMS!
- for i=1, #programs do
- local prog = programs[i]
- local path = clonepath..'/'..prog.path
- -- because i can't directly write "cloned/254/stuff/stuff/more_stuff"
- -- gotta make the directory for it first
- local pathfolder = path:match('(.+)/')
- if not fs.exists(pathfolder) then
- fs.makeDir(pathfolder)
- end
- -- PROCEED WITH THE WRITING
- local file = fs.open(path, 'w')
- if file then
- file.write(prog.contents)
- file.close()
- setColor(colors.lime)
- printColor(colors.lime, 'Successfully wrote '..prog.path)
- else
- -- wtf why? :C
- printColor(colors.red, 'Could not write '..prog.path)
- end
- end
- shell.setDir(clonepath)
- end
- local function files()
- printColor(colors.yellow, 'Generating file list')
- -- recursively make a file list
- -- exclude specific directories
- local filelist = {}
- local function genFiles(cdir)
- for _, localpath in pairs(fs.list(cdir)) do
- local path = fs.combine(cdir, localpath)
- if fs.isDir(path) then
- if not path:find('rom')
- and not path:find('cloned') then
- genFiles(path)
- end
- else
- if not localpath:match('^/?%.') then
- local file = fs.open(path,'r')
- if file then
- table.insert(filelist, {
- path = path;
- contents = file.readAll()
- })
- file.close()
- else
- printColor(colors.red, 'Could not read '..path)
- end
- end
- end
- end
- end
- genFiles '/'
- return filelist
- end
- local function server()
- -- if there's a password file
- -- read it and key it in to the read() function
- -- by abusing events
- local passfile = fs.open('.clone_pass','r')
- if passfile then
- for v in (passfile.readAll()):gmatch('.') do
- os.queueEvent('char',v)
- end
- passfile.close()
- end
- -- get a server password
- writeColor(colors.magenta, 'Password: ')
- setColor(colors.white)
- local password = read('*')
- -- go ahead and key in a y if the saved password exists,
- -- and n if otherwise
- -- for convenience
- os.queueEvent('char', passfile and 'y' or 'n')
- -- save the password to the file
- -- if the user chooses to remember it
- writeColor(colors.magenta, 'Remember password? [y/n] ')
- setColor(colors.white)
- local answer = read():lower():sub(1,1)
- if answer == 'y' then
- local passfile = fs.open('.clone_pass','w')
- if passfile then
- passfile.write(password)
- passfile.close()
- end
- -- otherwise, delete the file
- -- to prevent rememberance
- elseif answer == 'n' then
- if fs.exists('.clone_pass') then
- fs.delete('.clone_pass')
- end
- end
- printColor(colors.lime, 'Hosting clone server')
- printColor(colors.yellow, 'Press backspace to quit.')
- allowExit = true
- -- loooOOOOOOOoooop
- while true do
- local id, msg = rednet.receive()
- printColor(colors.yellow, 'Request from '..id)
- local pass = msg:match('clone_req (.+)')
- if pass == password then
- printColor(colors.lime, 'Successful authentication')
- local files = textutils.serialize(files())
- printColor(colors.yellow, 'Sending files')
- rednet.send(id, files)
- printColor(colors.lime, 'Done')
- else
- printColor(colors.red, 'Access denied')
- rednet.send(id, 'clone_failed_pass')
- end
- end
- end
- local function exit()
- -- when used with parallel,
- -- allows exiting the program
- -- at any time :D (when allowExit is true)
- repeat
- local _, k = os.pullEvent('key')
- until k == keys.backspace
- and allowExit
- end
- printColor(colors.yellow, 'Opening rednet')
- local modemSide = openRednet()
- if not modemSide then return end
- if args[1] == 'host' then
- parallel.waitForAny(server, exit)
- elseif tonumber(args[1]) then
- client(tonumber(args[1]))
- else
- print 'Usage: "clone <id>" or "clone host"'
- end
- rednet.close(modemSide)
Advertisement
Add Comment
Please, Sign In to add comment