Advertisement
Tatantyler

CC. Uni. GradeServ

Jan 1st, 2013
389
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 6.77 KB | None | 0 0
  1. local clientAssignmentDirectory = "usr/"
  2. local userList = "user_list"
  3. local adminUser = "KillaVanilla"
  4. local adminPass = "something"
  5. local lastAccessTimes = {}
  6. local logfile = "server.log"
  7. local logServ = 117
  8.  
  9. function log(stuff)
  10.     local lHandle = fs.open(logfile, "a")
  11.     lHandle.writeLine(stuff)
  12.     lHandle.close()
  13. end
  14.  
  15. local function spec_print(...)
  16.     local args2 = {...}
  17.     local str = ""
  18.     for i,v in ipairs(args2) do
  19.         str = str..v
  20.     end
  21.     rednet.send(logServ, textutils.serialize({"LOGSERV", "GradeServ", str}))
  22.     if http then
  23.         local wHandle = http.get("http://timeapi.org/utc/now")
  24.         if wHandle then
  25.             str = "[ RL TIME: "..wHandle.readAll().." UTC] "..str
  26.         else
  27.             str = "[ MC TIME: Day "..os.day().." @ "..textutils.formatTime(os.time()).."} "..str
  28.         end
  29.     end
  30.     print(str)
  31.     log(str)
  32. end
  33.  
  34. local successMsg = textutils.serialize({"assignment", "return_code", "success"})
  35.  
  36. assert(fs.exists(userList), userList.." does not exist!")
  37. for i,v in ipairs(rs.getSides()) do
  38.     if peripheral.getType(v) == "modem" then
  39.         rednet.open(v)
  40.     end
  41. end
  42.  
  43. if not fs.exists(clientAssignmentDirectory) then
  44.     fs.makeDir(clientAssignmentDirectory)
  45. end
  46.  
  47. local handle = io.open(userList, "r")
  48. local cred_table = {}
  49. for line in handle:lines() do
  50.     string.gsub(line, "([%a%p%d]+)%s+([%a%p%d]+)", function(user, pass) cred_table[user] = pass if not fs.exists(fs.combine(clientAssignmentDirectory, user)) then fs.makeDir(fs.combine(clientAssignmentDirectory, user)) end end)
  51. end
  52. cred_table[adminUser] = adminPass
  53. handle:close()
  54.  
  55. local function runTests(inputFile) -- run a simple pair of tests designed to catch (lazy) cheaters and weed out obviously-wrong answers.
  56.     if not fs.exists(inputFile) then
  57.         spec_print("Attempted to run test on nonexistent file: "..input)
  58.         return "false", "File does not exist"
  59.     end
  60.     local iHandle = fs.open(inputFile, "r")
  61.     local input = iHandle.readAll()
  62.     iHandle.close()
  63.     for i,v in ipairs(fs.list(clientAssignmentDirectory)) do
  64.         if fs.isDir(fs.combine(clientAssignmentDirectory, v)) then
  65.             for i,file in ipairs(fs.list(fs.combine(clientAssignmentDirectory, v))) do
  66.                 if file ~= "SanityTests.log" then
  67.                     local handle = fs.open(fs.combine(fs.combine(clientAssignmentDirectory, v), file), "r")
  68.                     if handle.readAll() == input then
  69.                         handle.close()
  70.                         return "false" -- cheater!
  71.                     end
  72.                     handle.close()
  73.                 end
  74.             end
  75.         end
  76.     end
  77.     local ok, err = pcall(loadstring(input))
  78.     return tostring(ok)
  79. end
  80.  
  81. local function getLoginCredent(id)
  82.     for i,v in pairs(lastAccessTimes) do
  83.         if v[2] == id then
  84.             return true, i
  85.         end
  86.     end
  87. end
  88.  
  89. local function runSanityTests()
  90.     for userID,user in ipairs(fs.list(clientAssignmentDirectory)) do
  91.         if fs.isDir(fs.combine(clientAssignmentDirectory, user)) then
  92.             local sanityLog = fs.open(fs.combine(fs.combine(clientAssignmentDirectory, user), "SanityTests.log"), "w")
  93.             for fileID, fileName in ipairs(fs.list(fs.combine(clientAssignmentDirectory, user))) do
  94.                 if fileName ~= "SanityTests.log" then
  95.                     sanityLog.writeLine(fileName..": "..runTests(fs.combine(fs.combine(clientAssignmentDirectory, user), fileName)))
  96.                 end
  97.             end
  98.             sanityLog.close()
  99.         end
  100.     end
  101. end
  102.  
  103.  
  104. local function listenerThread()
  105.     while true do
  106.         local id, msg = rednet.receive()
  107.         msg = textutils.unserialize(msg)
  108.         if msg then
  109.             local hasLoggedIn, user = getLoginCredent(id)
  110.             local isAdmin = false
  111.             if hasLoggedIn then
  112.                 isAdmin = (user == adminUser)
  113.             end
  114.             if msg[1] == "assignment" then
  115.                 if msg[2] == "login" then
  116.                     if cred_table[msg[3]] == msg[4] then
  117.                         if msg[3] == adminUser then
  118.                             spec_print("ID "..id.." logged in as "..msg[3]..". (admin account)")
  119.                         else
  120.                             spec_print("ID "..id.." logged in as "..msg[3]..". (student account)")
  121.                         end
  122.                         lastAccessTimes[msg[3]] = {os.clock(), id}
  123.                         rednet.send(id, successMsg)
  124.                     end
  125.                 elseif hasLoggedIn then
  126.                     if msg[2] == "logout" then
  127.                         spec_print("ID "..id.." ("..user..") logged out.")
  128.                         lastAccessTimes[user] = nil
  129.                         rednet.send(id, successMsg)
  130.                     elseif msg[2] == "submit" then
  131.                         if not fs.exists(fs.combine(clientAssignmentDirectory..user, msg[3])) then
  132.                             local file = fs.open(fs.combine(clientAssignmentDirectory..user, msg[3]), "w")
  133.                             file.write(msg[4])
  134.                             file.close()
  135.                             spec_print("ID "..id.." ("..user..") submitted an assignment as file "..msg[3].." ("..fs.getSize(fs.combine(clientAssignmentDirectory..user, msg[3])).." bytes written).")
  136.                             rednet.send(id, successMsg)
  137.                         end
  138.                         lastAccessTimes[user][1] = os.clock()
  139.                     elseif msg[2] == "get_results" then
  140.                         spec_print("ID "..id.." ("..user..") downloaded his/her test results.")
  141.                         local file = fs.open(fs.combine(clientAssignmentDirectory..user, "SanityTests.log"), "r")
  142.                         rednet.send(id, textutils.serialize({"assignment", "results", file.readAll()}))
  143.                         file.close()
  144.                         lastAccessTimes[user][1] = os.clock()
  145.                     elseif isAdmin then
  146.                         local fullFileName = fs.combine(clientAssignmentDirectory, msg[3])
  147.                         if msg[2] == "get" then
  148.                             if fs.exists(fullFileName) then
  149.                                 spec_print("ID "..id.." ("..user..") downloaded file "..fullFileName..".")
  150.                                 local handle = fs.open(fullFileName, "r")
  151.                                 rednet.send(id, textutils.serialize({"assignment", "file", msg[3], handle.readAll()}))
  152.                                 handle.close()
  153.                             end
  154.                         elseif msg[2] == "list" then
  155.                             spec_print("ID "..id.." ("..user..") requested directory listing for "..fullFileName..".")
  156.                             if fs.exists(fullFileName) and fs.isDir(fullFileName) then
  157.                                 rednet.send(id, textutils.serialize({"assignment", "list", msg[3], fs.list(fullFileName)}))
  158.                             end
  159.                         elseif msg[2] == "put" then
  160.                             local handle = fs.open(fullFileName, "w")
  161.                             handle.write(msg[4])
  162.                             handle.close()
  163.                             spec_print("ID "..id.." ("..user..") uploaded file "..fullFileName.." ("..fs.getSize(fullFileName).." bytes written).")
  164.                             rednet.send(id, successMsg)
  165.                         elseif msg[2] == "delete" then
  166.                             if fs.exists(fullfileName) then
  167.                                 fs.delete(fullFileName)
  168.                                 spec_print("ID "..id.." ("..user..") deleted file "..fullFileName..".")
  169.                             end
  170.                         end
  171.                     end
  172.                 end
  173.             end
  174.         end
  175.     end
  176. end
  177.  
  178. local function timedEventThread()
  179.     local sanityTestItr = 0
  180.     while true do
  181.         local lastAccessTimes_clone = {}
  182.         for i,v in pairs(lastAccessTimes) do
  183.             if os.clock() < v[1]+300 then
  184.                 lastAccessTimes_clone[i] = v
  185.             else
  186.                 spec_print("Automatically logging out ID "..v[2].." ("..i..") due to inactivity.")
  187.             end
  188.         end
  189.         lastAccessTimes = lastAccessTimes_clone
  190.         sanityTestItr = sanityTestItr+1
  191.         if sanityTestItr >= 30 then
  192.             runSanityTests()
  193.             sanityTestItr = 0
  194.         end
  195.         os.sleep(1)
  196.     end
  197. end
  198.  
  199. spec_print("GradeServ V1.2 is ONLINE!")
  200. parallel.waitForAll(listenerThread, timedEventThread)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement