Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- local commitLocBase = "commits/"
- local fileLocBase = "files/"
- local usersLoc = "users/"
- local inactivityTimeout = 900
- local allowGuest = false
- local silent = false
- local args = {...}
- if #args > 1 then
- for i=1, #args do
- if args[i] == "-silent" then
- silent = true
- elseif args[i] == "-guest_read" then
- allowGuest = true
- end
- end
- end
- if not fs.exists(commitLocBase) then
- fs.makeDir(commitLocBase)
- end
- if not fs.exists(fileLocBase) then
- fs.makeDir(fileLocBase)
- end
- if not fs.exists(usersLoc) then
- fs.makeDir(usersLoc)
- end
- local defaultPrint = print
- print = function(...)
- local str = ""
- for i=1, #arg do
- str = str..arg[i]
- end
- if not silent then
- defaultPrint(str)
- end
- end
- local loggedIn = {}
- if fs.exists("arcfour") then
- os.loadAPI("arcfour")
- cipher = arcfour.rc4_cipher
- else
- if http then
- local webHandle = http.get("http://pastebin.com/raw.php?i=73q8zCPc")
- local data = webHandle.readAll()
- webHandle.close()
- local fileHandle = fs.open("arcfour", "w")
- fileHandle.write(data)
- fileHandle.close()
- os.loadAPI("arcfour")
- cipher = arcfour.rc4_cipher
- end
- end
- local function makeFileSafe(file)
- file = string.gsub(file, "%/", "#002F")
- file = string.gsub(file, "%\\", "#005C")
- file = string.gsub(file, "%:", "#003A")
- file = string.gsub(file, "%*", "#002A")
- file = string.gsub(file, "%?", "#003F")
- file = string.gsub(file, "%\"", "#0022")
- file = string.gsub(file, "%<", "#003C")
- file = string.gsub(file, "%>", "#003E")
- file = string.gsub(file, "%|", "#007C")
- return file
- end
- local function safeFilenameToTrueName(file)
- file = string.gsub(file, "#002F", "/")
- file = string.gsub(file, "#005C", "\\")
- file = string.gsub(file, "#003A", ":")
- file = string.gsub(file, "#002A", "*")
- file = string.gsub(file, "#003F", "?")
- file = string.gsub(file, "#0022", "\"")
- file = string.gsub(file, "#003C", "<")
- file = string.gsub(file, "#003E", ">")
- file = string.gsub(file, "#007C", "|")
- return file
- end
- local function handleMsg(id, msg)
- local user = loggedIn[id]
- commitLoc = commitLocBase..user[3].."/"
- fileLoc = fileLocBase..user[3].."/"
- local function doCommit(id, file, data, commit_msg)
- local timeHandle = http.get("http://timeapi.org/utc/now")
- local currentTime = timeHandle.readAll()
- timeHandle.close()
- local commitID = 0
- if not commit_msg then
- commit_msg = "No Message Given"
- end
- print("Making commit to file "..file..".")
- print("Message: "..commit_msg)
- if not fs.exists(commitLoc..file) then
- fs.makeDir(commitLoc..file)
- end
- if not fs.exists(commitLoc..file.."/.metadata") then
- fs.makeDir(commitLoc..file.."/.metadata")
- end
- while true do
- if fs.exists(commitLoc..file.."/"..tostring(commitID)) then
- commitID = commitID + 1
- else
- local commit = fs.open(commitLoc..file.."/"..tostring(commitID), "w")
- if fs.exists(fileLoc..file) then
- local fileHandle = fs.open(fileLoc..file, "r")
- commit.write(fileHandle.readAll())
- fileHandle.close()
- else
- commit.write(data)
- end
- commit.close()
- break
- end
- end
- local commitData = fs.open(commitLoc..file.."/.metadata/"..tostring(commitID), "w")
- commitData.writeLine(commit_msg)
- commitData.writeLine(id)
- commitData.writeLine("UTC: "..currentTime)
- commitData.close()
- if data ~= nil then
- local commit = fs.open(fileLoc..file, "w")
- commit.write(data)
- commit.close()
- end
- end
- if not fs.exists(commitLoc) then
- fs.makeDir(commitLoc)
- end
- if not fs.exists(fileLoc) then
- fs.makeDir(fileLoc)
- end
- local oldPrint = print
- print = function(...)
- local printStr = "["..id.."] "
- for i,v in ipairs(arg) do
- printStr = printStr..v
- end
- local logHandle = fs.open("dbLog", "a")
- logHandle.writeLine(printStr)
- logHandle.close()
- oldPrint(printStr)
- end
- msg = textutils.unserialize(msg)
- if type(msg) == "table" then
- if not fs.exists(commitLoc) then
- fs.makeDir(commitLoc)
- end
- if not fs.exists(fileLoc) then
- fs.makeDir(fileLoc)
- end
- if msg[1] == "switch" then
- loggedIn[id][3] = msg[2]
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- elseif msg[1] == "clone_branch" or msg[1] == "copy_branch" then
- fs.copy(fileLoc, fileLocBase..msg[2])
- fs.copy(commitLoc, commitLocBase..msg[2])
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- elseif msg[1] == "new_branch" then
- fs.makeDir(fileLocBase..msg[2])
- fs.makeDir(commitLocBase..msg[2])
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- elseif msg[1] == "get_commit" then
- local file = makeFileSafe(msg[2])
- local commitHandle = fs.open(commitLoc..file.."/"..tostring(msg[3]), "r")
- local commitMsgHandle = fs.open(commitLoc..file.."/.metadata/"..tostring(msg[3]), "r")
- if commitHandle then
- local commitData = commitHandle.readAll()
- if commitMsgHandle then
- local commitMsg = commitMsgHandle.readLine()
- commitMsgHandle.close()
- end
- commitHandle.close()
- rednet.send(id, textutils.serialize({"DB", "commit_data", msg[2], msg[3], commitData, commitMsg}))
- else
- rednet.send(id, textutils.serialize({"DB", "error", "That commit does not exist."}))
- end
- elseif msg[1] == "commit" then
- doCommit(id, msg[2], msg[3], msg[4])
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- elseif msg[1] == "undo" or msg[1] == "revert" then
- print("Reverting "..msg[2].." to commit "..tostring(msg[3]))
- local file = makeFileSafe(msg[2])
- local commitID = tostring(msg[3])
- if fs.exists(commitLoc..file.."/"..commitID) then
- local commit = fs.open(commitLoc..file.."/"..commitID, "r")
- local fileHandle = fs.open(fileLoc..file, "w")
- fileHandle.write(commit.readAll())
- fileHandle.close()
- commit.close()
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- else
- rednet.send(id, textutils.serialize({"DB", "error", "That commit does not exist."}))
- end
- elseif msg[1] == "delete" then
- local file = makeFileSafe(msg[2])
- local commitID = 0
- print("Deleting: "..fileLoc..file)
- if fs.exists(fileLoc..file) then
- doCommit(id, file, nil, "Being deleted...")
- fs.delete(fileLoc..file)
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- else
- rednet.send(id, textutils.serialize({"DB", "error", "That file does not exist."}))
- end
- elseif msg[1] == "move" or msg[1] == "rename" then
- local oldFile = makeFileSafe(msg[2])
- local newFile = makeFileSafe(msg[3])
- print("Moving: "..oldFile.." to "..newFile)
- if fs.exists(fileLoc..oldFile) then
- local fileHandle = fs.open(fileLoc..oldFile, "r")
- local oldFileData = fileHandle.readAll()
- fileHandle.close()
- doCommit(id, oldFile, nil, "Moved to: "..newFile)
- doCommit(id, newFile, oldFileData, "Moved from: "..oldFile)
- fs.delete(fileLoc..oldFile)
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- else
- rednet.send(id, textutils.serialize({"DB", "error", "That file does not exist."}))
- end
- elseif msg[1] == "copy" then
- local oldFile = makeFileSafe(msg[2])
- local newFile = makeFileSafe(msg[3])
- print("Copying: "..oldFile.." to "..newFile)
- if fs.exists(fileLoc..oldFile) then
- local fileHandle = fs.open(fileLoc..oldFile, "r")
- local oldFileData = fileHandle.readAll()
- fileHandle.close()
- doCommit(id, oldFile, nil, "Copied to: "..newFile)
- doCommit(id, newFile, oldFileData, "Copied from: "..oldFile)
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- else
- rednet.send(id, textutils.serialize({"DB", "error", "That file does not exist."}))
- end
- elseif msg[1] == "read" then
- local file = makeFileSafe(msg[2])
- local commitID = tostring(msg[3])
- local data = ""
- if commitID == "-1" or commitID == "nil" then
- print("Request for "..fileLoc..file..".")
- if fs.exists(fileLoc..file) then
- local fileHandle = fs.open(fileLoc..file, "r")
- data = fileHandle.readAll()
- fileHandle.close()
- end
- else
- print("Request for "..commitLoc..file.."/"..commitID..".")
- if fs.exists(commitLoc..file.."/"..commitID) then
- local commit = fs.open(commitLoc..file.."/"..commitID, "r")
- data = commit.readAll()
- commit.close()
- end
- end
- rednet.send(id, textutils.serialize({"DB", "file", msg[2], data}))
- elseif msg[1] == "list_commits" then
- print("Listing commits for file: "..msg[2])
- local file = makeFileSafe(msg[2])
- local commits = {}
- local commit = 0
- while true do
- if not fs.exists(commitLoc..file.."/"..tostring(commit)) then
- break
- end
- local comHandle = fs.open(commitLoc..file.."/"..tostring(commit), "r")
- local comMsgHandle = fs.open(commitLoc..file.."/.metadata/"..tostring(commit), "r")
- if comMsgHandle then
- local comMsg = comMsgHandle..readLine()
- comMsgHandle.close()
- end
- local data = comHandle.readAll()
- comHandle.close()
- commits[commit] = {data, comMsg}
- commit = commit + 1
- end
- local packet = {"DB", "commits", loggedIn[id][3], msg[2], commits}
- packet = textutils.serialize(packet)
- rednet.send(id, packet)
- --[[elseif msg[1] == "clone" then
- print("Copy of database requested.")
- local commits = {}
- local messages = {}
- local files = {}
- if fs.exists(commitLoc) then
- for i,file in ipairs(fs.list(commitLoc)) do
- commits[file] = {}
- messages[file] = {}
- for i2, commit in ipairs(fs.list(commitLoc..file)) do
- if commit ~= ".metadata" then
- local handle = fs.open(commitLoc..file.."/"..commit, "r")
- commits[file][commit] = handle.readAll()
- handle.close()
- end
- end
- if fs.exists(commitLoc..file..".metadata/") then
- for i2, commit in ipairs(fs.list(commitLoc..file..".metadata/")) do
- local handle = fs.open(commitLoc..file..".metadata/"..commit, "r")
- messages[file][commit] = handle.readLine()
- handle.close()
- end
- end
- end
- end
- if fs.exists(fileLoc) then
- for i,v in ipairs(fs.list(fileLoc)) do
- local handle = fs.open(fileLoc..v, "r")
- files[v] = handle.readAll()
- handle.close()
- end
- end
- rednet.send(id, textutils.serialize({"DB", "clone", loggedIn[id][3], messages, commits, files}))]]
- elseif msg[1] == "pastebin_get" then
- local webHandle = http.get("http://pastebin.com/raw.php?i="..msg[2])
- if webHandle then
- local data = webHandle.readAll()
- webHandle.close()
- doCommit(id, msg[3], data, msg[4])
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- else
- rednet.send(id, textutils.serialize({"DB", "error", "Could not connect to Pastebin."}))
- end
- elseif msg[1] == "github_get" then
- local file = makeFileSafe(msg[2])
- local url = "https://raw.github.com/"..msg[3].."/"..msg[4].."/"..msg[5].."/"..msg[6]
- local webHandle = http.get(url)
- if webHandle then
- local data = webHandle.readAll()
- webHandle.close()
- doCommit(id, msg[2], data, msg[7])
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- else
- rednet.send(id, textutils.serialize({"DB", "error", "Could not connect to GitHub."}))
- end
- elseif msg[1] == "list" then
- rednet.send(id, textutils.serialize({"DB", "files", fs.list(fileLoc)}))
- end
- end
- print = oldPrint
- end
- for i,v in ipairs(rs.getSides()) do
- if peripheral.getType(v) == "modem" then
- rednet.open(v)
- end
- end
- if cipher then
- print("ARC4 cipher found.")
- else
- print("No ARC4 cipher found.")
- print("This means that passwords will be read as cleartext.")
- print("Try enabling the HTTP API if possible.")
- end
- local function recvThread(id, msg)
- --print(id..": "..msg.." @ "..os.clock())
- local packet = textutils.unserialize(msg)
- if type(packet) == "table" then
- if packet[1] == "login" then
- local user = packet[2]
- local pass = packet[3]
- if fs.exists(usersLoc..user) then
- if cipher then
- local userHandle = fs.open(usersLoc..user, "rb")
- local cBytes = {}
- while true do
- local byte = userHandle.read()
- if byte then
- table.insert(cBytes, byte)
- else
- break
- end
- end
- local ciphertext = string.char(unpack(cBytes))
- local plaintext = cipher(pass, ciphertext)
- if plaintext == user then
- loggedIn[id] = {user, os.clock(), "master"} -- {user, time since last activity, current branch}
- print("Login sucessful. User: "..user)
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- else
- print("Login failed: incorrect password")
- rednet.send(id, textutils.serialize({"DB", "error", "Incorrect password."}))
- end
- else
- local userHandle = fs.open(usersLoc..user, "r")
- local pw = userHandle.readAll()
- if pass == pw then
- loggedIn[id] = {user, os.clock(), "master"} -- {user, time since last activity, current branch}
- print("Login sucessful. User: "..user)
- rednet.send(id, textutils.serialize({"DB", "successful"}))
- else
- print("Login failed: incorrect password")
- rednet.send(id, textutils.serialize({"DB", "error", "Incorrect password."}))
- end
- end
- else
- print("Login failed: unknown user")
- rednet.send(id, textutils.serialize({"DB", "error", "User not found."}))
- end
- elseif packet[1] == "logout" or packet[1] == "logoff" then
- if loggedIn[id] ~= nil then
- if loggedIn[id][1] ~= nil then
- print(loggedIn[id][1].." logged out.")
- loggedIn[id] = nil
- rednet.send(id, textutils.serialize({"DB", "goodbye"}))
- else
- rednet.send(id, textutils.serialize({"DB", "error", "You have not logged in!"}))
- end
- else
- rednet.send(id, textutils.serialize({"DB", "error", "You have not logged in!"}))
- end
- elseif loggedIn[id] then
- if loggedIn[id] ~= nil then
- loggedIn[id][2] = os.clock()
- end
- handleMsg(id, msg)
- return
- elseif allowGuest and (packet[1] == "list" or packet[1] == "read") then
- if packet[1] == "list" then
- local logHandle = fs.open("dbLog", "a")
- logHandle.writeLine("["..id.."] ".."Guest requested file listing.")
- logHandle.close()
- print("["..id.."] ".."Guest requested file listing. Path: "..fileLocBase.."master/")
- local files = fs.list(fileLocBase.."master/")
- rednet.send(id, textutils.serialize({"DB", "files", files}))
- elseif packet[1] == "read" then
- local logHandle = fs.open("dbLog", "a")
- logHandle.writeLine("["..id.."] ".."Guest requested file: "..packet[2])
- logHandle.close()
- if fs.exists(fileLocBase.."master/"..makeFileSafe(packet[2])) then
- print("["..id.."] ".."Guest requested file: "..packet[2])
- local file = makeFileSafe(packet[2])
- local handle = fs.open(fileLocBase.."master/"..file, "r")
- local data = handle.readAll()
- handle.close()
- rednet.send(id, textutils.serialize({"DB", "file", packet[2], data}))
- else
- rednet.send(id, textutils.serialize({"DB", "error", "That file does not exist."}))
- end
- end
- else
- rednet.send(id, textutils.serialize({"DB", "error", "You have not logged in!"}))
- return
- end
- end
- end
- local function loginTrackerThread()
- while true do
- local currentTime = os.clock()
- for i=1, table.maxn(loggedIn) do
- v = loggedIn[i]
- if v then
- if currentTime - v[2] > inactivityTimeout then
- print("Logging "..v[1].." out due to inactivity...")
- loggedIn[i] = nil
- end
- end
- end
- os.sleep(1)
- end
- end
- local newUserProgram = [[
- if fs.exists("arcfour") then
- os.loadAPI("arcfour")
- end
- local args = {...}
- local user = args[1]
- local pw = args[2]
- local function writePassword(file, password)
- local handle = fs.open(file, "wb")
- local bytes = {}
- for i=1, #password do
- handle.write(string.byte(password, i, i))
- end
- handle.close()
- end
- if arcfour then
- writePassword("users/"..user, arcfour.rc4_cipher(pw, user))
- else
- local handle = fs.open("users/"..user, "w")
- handle.write(pw)
- handle.close()
- end
- ]]
- if not fs.exists("newUser") then
- local handle = fs.open("newUser", "w")
- handle.write(newUserProgram)
- handle.close()
- end
- if allowGuest then
- print("Guest restricted read-only access enabled.")
- end
- parallel.waitForAll(
- function()
- while true do
- local id, msg = rednet.receive()
- recvThread(id, msg)
- end
- end,
- loginTrackerThread
- )
- print = defaultPrint
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement