Advertisement
Guest User

Firewolf 2.4

a guest
Nov 21st, 2014
147
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 90.14 KB | None | 0 0
  1.  
  2. --
  3. --  Firewolf Website Browser
  4. --  Made by GravityScore and 1lann
  5. --  License found here: https://raw.github.com/1lann/Firewolf/master/LICENSE
  6. --
  7. --  Original Concept From RednetExplorer 2.4.1
  8. --  RednetExplorer Made by ComputerCraftFan11
  9. --
  10.  
  11.  
  12. --  -------- Variables
  13.  
  14. -- Version
  15. local version = "2.4"
  16. local build = 29
  17. local browserAgentTemplate = "Firewolf " .. version
  18. browserAgent = browserAgentTemplate
  19. local tArgs = {...}
  20.  
  21. -- Server Identification
  22. local serverID = "other"
  23. local serverList = {experimental = "Experimental", other = "Other"}
  24.  
  25. -- Updating
  26. local autoupdate = "true"
  27. local noInternet = false
  28.  
  29. -- Resources
  30. local graphics = {}
  31. local files = {}
  32. local w, h = term.getSize()
  33.  
  34. -- Debugging
  35. local debugFile = nil
  36.  
  37. -- Environment
  38. local oldpullevent = os.pullEvent
  39. local oldEnv = {}
  40. local env = {}
  41. local backupEnv = {}
  42.  
  43. local api = {}
  44. local override = {}
  45. local antivirus = {}
  46.  
  47. -- Themes
  48. local theme = {}
  49.  
  50. -- Databases
  51. local blacklist = {}
  52. local whitelist = {}
  53. local dnsDatabase = {[1] = {}, [2] = {}}
  54.  
  55. -- Website Loading
  56. local pages = {}
  57. local errorPages = {}
  58.  
  59. local website = ""
  60. local homepage = ""
  61. local timeout = 0.2
  62. local loadingRate = 0
  63. local openAddressBar = true
  64. local clickableAddressBar = true
  65. local menuBarOpen = false
  66.  
  67. -- Protocols
  68. local curProtocol = {}
  69. local protocols = {}
  70.  
  71. -- History
  72. local addressBarHistory = {}
  73.  
  74. -- Events
  75. local event_loadWebsite = "firewolf_loadWebsiteEvent"
  76. local event_exitWebsite = "firewolf_exitWebsiteEvent"
  77. local event_redirect = "firewolf_redirectEvent"
  78. local event_exitApp = "firewolf_exitAppEvent"
  79.  
  80. -- Download URLs
  81. local firewolfURL = "https://raw.github.com/1lann/firewolf/master/entities/" .. serverID .. ".lua"
  82. local a = "release"
  83. if serverID == "experimental" then a = "experimental" end
  84. local serverURL = "https://raw.github.com/1lann/firewolf/master/server/server-" .. a .. ".lua"
  85. local buildURL = "https://raw.github.com/1lann/firewolf/master/build"
  86.  
  87. -- Data Locations
  88. local rootFolder = "/.Firewolf_Data"
  89. local cacheFolder = rootFolder .. "/cache"
  90. local serverFolder = rootFolder .. "/servers"
  91. local websiteDataFolder = rootFolder .. "/website_data"
  92. local themeLocation = rootFolder .. "/theme"
  93. local serverLocation = rootFolder .. "/server_software"
  94. local settingsLocation = rootFolder .. "/settings"
  95. local debugLogLocation = "/firewolf-log"
  96. local firewolfLocation = "/" .. shell.getRunningProgram()
  97.  
  98. local userBlacklist = rootFolder .. "/user_blacklist"
  99. local userWhitelist = rootFolder .. "/user_whitelist"
  100.  
  101.  
  102. --  -------- Utilities
  103.  
  104. local function debugLog(n, ...)
  105.     local lArgs = {...}
  106.     if debugFile then
  107.         if n == nil then n = "" end
  108.         debugFile:write("\n" .. tostring(n) .. " : ")
  109.         for k, v in pairs(lArgs) do
  110.             if type(v) == "string" or type(v) == "number" or type(v) == nil or
  111.                     type(v) == "boolean" then
  112.                 debugFile:write(tostring(v) .. ", ")
  113.             else debugFile:write("type-" .. type(v) .. ", ") end
  114.         end
  115.     end
  116. end
  117.  
  118. local function modRead(properties)
  119.     local w, h = term.getSize()
  120.     local defaults = {replaceChar = nil, history = nil, visibleLength = nil, textLength = nil,
  121.         liveUpdates = nil, exitOnKey = nil}
  122.     if not properties then properties = {} end
  123.     for k, v in pairs(defaults) do if not properties[k] then properties[k] = v end end
  124.     if properties.replaceChar then properties.replaceChar = properties.replaceChar:sub(1, 1) end
  125.     if not properties.visibleLength then properties.visibleLength = w end
  126.  
  127.     local sx, sy = term.getCursorPos()
  128.     local line = ""
  129.     local pos = 0
  130.     local historyPos = nil
  131.  
  132.     local function redraw(repl)
  133.         local scroll = 0
  134.         if properties.visibleLength and sx + pos > properties.visibleLength + 1 then
  135.             scroll = (sx + pos) - (properties.visibleLength + 1)
  136.         end
  137.  
  138.         term.setCursorPos(sx, sy)
  139.         local a = repl or properties.replaceChar
  140.         if a then term.write(string.rep(a, line:len() - scroll))
  141.         else term.write(line:sub(scroll + 1, -1)) end
  142.         term.setCursorPos(sx + pos - scroll, sy)
  143.     end
  144.  
  145.     local function sendLiveUpdates(event, ...)
  146.         if type(properties.liveUpdates) == "function" then
  147.             local ox, oy = term.getCursorPos()
  148.             local a, data = properties.liveUpdates(line, event, ...)
  149.             if a == true and data == nil then
  150.                 term.setCursorBlink(false)
  151.                 return line
  152.             elseif a == true and data ~= nil then
  153.                 term.setCursorBlink(false)
  154.                 return data
  155.             end
  156.             term.setCursorPos(ox, oy)
  157.         end
  158.     end
  159.  
  160.     local a = sendLiveUpdates("delete")
  161.     if a then return a end
  162.     term.setCursorBlink(true)
  163.     while true do
  164.         local e, but, x, y, p4, p5 = os.pullEvent()
  165.  
  166.         if e == "char" then
  167.             local s = false
  168.             if properties.textLength and line:len() < properties.textLength then s = true
  169.             elseif not properties.textLength then s = true end
  170.  
  171.             local canType = true
  172.             if not properties.grantPrint and properties.refusePrint then
  173.                 local canTypeKeys = {}
  174.                 if type(properties.refusePrint) == "table" then
  175.                     for _, v in pairs(properties.refusePrint) do
  176.                         table.insert(canTypeKeys, tostring(v):sub(1, 1))
  177.                     end
  178.                 elseif type(properties.refusePrint) == "string" then
  179.                     for char in properties.refusePrint:gmatch(".") do
  180.                         table.insert(canTypeKeys, char)
  181.                     end
  182.                 end
  183.                 for _, v in pairs(canTypeKeys) do if but == v then canType = false end end
  184.             elseif properties.grantPrint then
  185.                 canType = false
  186.                 local canTypeKeys = {}
  187.                 if type(properties.grantPrint) == "table" then
  188.                     for _, v in pairs(properties.grantPrint) do
  189.                         table.insert(canTypeKeys, tostring(v):sub(1, 1))
  190.                     end
  191.                 elseif type(properties.grantPrint) == "string" then
  192.                     for char in properties.grantPrint:gmatch(".") do
  193.                         table.insert(canTypeKeys, char)
  194.                     end
  195.                 end
  196.                 for _, v in pairs(canTypeKeys) do if but == v then canType = true end end
  197.             end
  198.  
  199.             if s and canType then
  200.                 line = line:sub(1, pos) .. but .. line:sub(pos + 1, -1)
  201.                 pos = pos + 1
  202.                 redraw()
  203.             end
  204.         elseif e == "key" then
  205.             if but == keys.enter then
  206.                 break
  207.             elseif but == keys.left then
  208.                 if pos > 0 then pos = pos - 1 redraw() end
  209.             elseif but == keys.right then
  210.                 if pos < line:len() then pos = pos + 1 redraw() end
  211.             elseif (but == keys.up or but == keys.down) and properties.history and
  212.                     #properties.history > 0 then
  213.                 redraw(" ")
  214.                 if but == keys.up then
  215.                     if historyPos == nil and #properties.history > 0 then
  216.                         historyPos = #properties.history
  217.                     elseif historyPos > 1 then
  218.                         historyPos = historyPos - 1
  219.                     end
  220.                 elseif but == keys.down then
  221.                     if historyPos == #properties.history then historyPos = nil
  222.                     elseif historyPos ~= nil then historyPos = historyPos + 1 end
  223.                 end
  224.  
  225.                 if properties.history and historyPos then
  226.                     line = properties.history[historyPos]
  227.                     pos = line:len()
  228.                 else
  229.                     line = ""
  230.                     pos = 0
  231.                 end
  232.  
  233.                 redraw()
  234.                 local a = sendLiveUpdates("history")
  235.                 if a then return a end
  236.             elseif but == keys.backspace and pos > 0 then
  237.                 redraw(" ")
  238.                 line = line:sub(1, pos - 1) .. line:sub(pos + 1, -1)
  239.                 pos = pos - 1
  240.                 redraw()
  241.                 local a = sendLiveUpdates("delete")
  242.                 if a then return a end
  243.             elseif but == keys.home then
  244.                 pos = 0
  245.                 redraw()
  246.             elseif but == keys.delete and pos < line:len() then
  247.                 redraw(" ")
  248.                 line = line:sub(1, pos) .. line:sub(pos + 2, -1)
  249.                 redraw()
  250.                 local a = sendLiveUpdates("delete")
  251.                 if a then return a end
  252.             elseif but == keys["end"] then
  253.                 pos = line:len()
  254.                 redraw()
  255.             elseif properties.exitOnKey then
  256.                 if but == properties.exitOnKey or (properties.exitOnKey == "control" and
  257.                         (but == 29 or but == 157)) then
  258.                     term.setCursorBlink(false)
  259.                     return nil
  260.                 end
  261.             end
  262.         end
  263.  
  264.         local a = sendLiveUpdates(e, but, x, y, p4, p5)
  265.         if a then return a end
  266.     end
  267.  
  268.     term.setCursorBlink(false)
  269.     if line ~= nil then line = line:gsub("^%s*(.-)%s*$", "%1") end
  270.     return line
  271. end
  272.  
  273.  
  274. --  -------- Environment and APIs
  275.  
  276. local function isAdvanced()
  277.     return term.isColor and term.isColor()
  278. end
  279.  
  280. local function clearPage(site, color, redraw, tcolor)
  281.     -- Site titles
  282.     local titles = {firewolf = "Firewolf Homepage", ["server/rdnt"] = "RDNT Server Management",
  283.         ["server/http"] = "HTTP Server Management", help = "Firewolf Help",
  284.         settings = "Firewolf Settings", credits = "Firewolf Credits",
  285.         crash = "Website Has Crashed!", overspeed = "Too Fast!"}
  286.     local title = titles[site]
  287.  
  288.     -- Clear
  289.     term.setBackgroundColor(color or colors.black)
  290.     term.setTextColor(colors[theme["address-bar-text"]])
  291.     if redraw ~= true then term.clear() end
  292.  
  293.     if not menuBarOpen then
  294.         term.setBackgroundColor(colors[theme["address-bar-background"]])
  295.         term.setCursorPos(2, 1)
  296.         term.clearLine()
  297.         local a = site
  298.         if a:len() > w - 10 then a = a:sub(1, 38) .. "..." end
  299.         if curProtocol == protocols.rdnt then write("rdnt://" .. a)
  300.         elseif curProtocol == protocols.http then write("http://" .. a) end
  301.  
  302.         if title ~= nil then
  303.             term.setCursorPos(w - title:len() - 1, 1)
  304.             write(title)
  305.         end if isAdvanced() then
  306.             term.setCursorPos(w, 1)
  307.             term.setBackgroundColor(colors[theme["top-box"]])
  308.             term.setTextColor(colors[theme["text-color"]])
  309.             write("<")
  310.         end
  311.  
  312.         term.setBackgroundColor(color or colors.black)
  313.         term.setTextColor(tcolor or colors.white)
  314.     else
  315.         term.setCursorPos(1, 1)
  316.         term.setBackgroundColor(colors[theme["top-box"]])
  317.         term.setTextColor(colors[theme["text-color"]])
  318.         term.clearLine()
  319.         write("> [- Exit Firewolf -]                              ")
  320.     end
  321.  
  322.     print("")
  323. end
  324.  
  325. local function printWithType(t, func)
  326.     if type(t) == "table" then
  327.         for k, v in pairs(t) do
  328.             env.pcall(function() printWithType(v, func) end)
  329.         end
  330.     else
  331.         func(tostring(t))
  332.     end
  333. end
  334.  
  335. -- Drawing Functions
  336. api.centerWrite = function(text)
  337.     printWithType(text, function(t)
  338.         local x, y = term.getCursorPos()
  339.         term.setCursorPos(math.ceil((w + 1)/2 - t:len()/2), y)
  340.         write(t)
  341.     end)
  342. end
  343.  
  344. api.centerPrint = function(text)
  345.     printWithType(text, function(t)
  346.         local x, y = term.getCursorPos()
  347.         term.setCursorPos(math.ceil((w + 1)/2 - t:len()/2), y)
  348.         print(t)
  349.     end)
  350. end
  351.  
  352. api.leftWrite = function(text)
  353.     printWithType(text, function(t)
  354.         local x, y = term.getCursorPos()
  355.         term.setCursorPos(1, y)
  356.         write(t)
  357.     end)
  358. end
  359.  
  360. api.leftPrint = function(text)
  361.     printWithType(text, function(t)
  362.         local x, y = term.getCursorPos()
  363.         term.setCursorPos(1, y)
  364.         print(t)
  365.     end)
  366. end
  367.  
  368. api.rightWrite = function(text)
  369.     printWithType(text, function(t)
  370.         local x, y = term.getCursorPos()
  371.         term.setCursorPos(w - t:len() + 1, y)
  372.         write(t)
  373.     end)
  374. end
  375.  
  376. api.rightPrint = function(text)
  377.     printWithType(text, function(t)
  378.         local x, y = term.getCursorPos()
  379.         term.setCursorPos(w - t:len() + 1, y)
  380.         print(t)
  381.     end)
  382. end
  383.  
  384. -- Server Interation Functions
  385.  
  386. api.loadFileFromServer = function(path)
  387.     if type(path) ~= "string" then error("loadFile: expected string") end
  388.     sleep(0.05)
  389.     if path:sub(1, 1) == "/" then path = path:sub(2, -1) end
  390.     local id, content = curProtocol.getWebsite(website .. "/" .. path)
  391.     if id then
  392.         return content
  393.     end
  394.     return nil
  395. end
  396.  
  397. api.ioReadFileFromServer = function(path)
  398.     local content = api.loadFileFromServer(path)
  399.     if content then
  400.         local f = env.io.open(rootFolder .. "/temp_file", "w")
  401.         f:write(content)
  402.         f:close()
  403.         local fi = env.io.open(rootFolder .. "/temp_file", "r")
  404.         return fi
  405.     end
  406.     return nil
  407. end
  408.  
  409. api.loadImageFromServer = function(path)
  410.     local content = api.loadFileFromServer(path)
  411.     if content then
  412.         local f = env.io.open(rootFolder .. "/temp_file", "w")
  413.         f:write(content)
  414.         f:close()
  415.  
  416.         local image = paintutils.loadImage(rootFolder .. "/temp_file")
  417.         env.fs.delete("/temp_file")
  418.         return image
  419.     end
  420.     return nil
  421. end
  422.  
  423. api.writeDataFile = function(path, content)
  424.     if type(path) ~= "string" or type(content) ~= "string" then
  425.         error("writeDataFile: expected string, string") end
  426.     if path:sub(1, 1) == "/" then path = path:sub(2, -1) end
  427.     local dataPath = websiteDataFolder .. "/" .. path:gsub("/", "$slazh$")
  428.  
  429.     if env.fs.isReadOnly(dataPath) then return false end
  430.     if env.fs.exists(dataPath) then env.fs.delete(dataPath) end
  431.     local f = env.io.open(dataPath, "w")
  432.     if not f then return false end
  433.     f:write(content)
  434.     f:close()
  435.     return true
  436. end
  437.  
  438. api.readDataFile = function(path)
  439.     if type(path) ~= "string" then error("readDataFile: expected string") end
  440.     if path:sub(1, 1) == "/" then path = path:sub(2, -1) end
  441.     local dataPath = websiteDataFolder .. "/" .. path:gsub("/", "$slazh$")
  442.  
  443.     if env.fs.isDir(dataPath) then env.fs.delete(dataPath) end
  444.     if env.fs.exists(dataPath) then
  445.         local f = env.io.open(dataPath, "r")
  446.         local cont = f:read("*a")
  447.         f:close()
  448.         return cont
  449.     end
  450.     return nil
  451. end
  452.  
  453. api.saveFileToUserComputer = function(content)
  454.     if type(content) ~= "string" then error("saveFileToUserComputer: expected string") end
  455.     local oldback, oldtext = term.getBackgroundColor(), term.getTextColor()
  456.     local ox, oy = term.getCursorPos()
  457.  
  458.     term.setTextColor(colors[theme["text-color"]])
  459.     term.setBackgroundColor(colors[theme["background"]])
  460.     term.clear()
  461.     term.setCursorPos(1, 1)
  462.     term.setBackgroundColor(colors[theme["top-box"]])
  463.     print("")
  464.     leftPrint(string.rep(" ", 20))
  465.     leftPrint(" Save File Request  ")
  466.     leftPrint(string.rep(" ", 20))
  467.     print("")
  468.  
  469.     term.setBackgroundColor(colors[theme["bottom-box"]])
  470.     for i = 1, 11 do rightPrint(string.rep(" ", 36)) end
  471.     term.setCursorPos(1, 7)
  472.     rightPrint("The website: ")
  473.     rightPrint(website .. " ")
  474.     rightPrint("Is requesting to save a file ")
  475.     rightPrint("to your computer. ")
  476.  
  477.     local ret = nil
  478.     local opt = prompt({{"Save File", w - 16, 12}, {"Cancel", w - 13, 13}}, "vertical")
  479.     if opt == "Save File" then
  480.         while true do
  481.             term.setCursorPos(1, 15)
  482.             rightWrite(string.rep(" ", 36))
  483.             term.setCursorPos(w - 34, 15)
  484.             write("Path: /")
  485.             local p = read()
  486.  
  487.             term.setCursorPos(1, 15)
  488.             rightWrite(string.rep(" ", 36))
  489.             if p == "" or p == nil then
  490.                 rightWrite("File Name Empty! Cancelling... ")
  491.                 break
  492.             elseif fs.exists("/" .. p) then
  493.                 rightWrite("File Already Exists! ")
  494.             else
  495.                 rightWrite("File Saved! ")
  496.                 ret = "/" .. p
  497.                 break
  498.             end
  499.  
  500.             openAddressBar = false
  501.             sleep(1.3)
  502.             openAddressBar = true
  503.         end
  504.     elseif opt == "Cancel" then
  505.         term.setCursorPos(1, 15)
  506.         rightWrite("Saving Cancelled! ")
  507.     end
  508.  
  509.     openAddressBar = false
  510.     sleep(1.3)
  511.     openAddressBar = true
  512.  
  513.     term.setBackgroundColor(oldback or colors.black)
  514.     term.setTextColor(oldtext or colors.white)
  515.     term.clear()
  516.     term.setCursorPos(ox, oy)
  517.     return ret
  518. end
  519.  
  520. api.urlDownload = function(url)
  521.     if type(url) ~= "string" then error("download: expected string") end
  522.     local source = nil
  523.     http.request(url)
  524.     local a = os.startTimer(10)
  525.     while true do
  526.         local e, surl, handle = os.pullEvent()
  527.         if e == "http_success" then
  528.             source = handle.readAll()
  529.             break
  530.         elseif e == "http_failure" or (e == "timer" and surl == a) then
  531.             break
  532.         end
  533.     end
  534.  
  535.     if type(source) == "string" then
  536.         local saveFunc = api.saveFileToUserComputer
  537.         env.setfenv(saveFunc, override)
  538.         return saveFunc(source)
  539.     else return nil end
  540. end
  541.  
  542. api.pastebinDownload = function(code)
  543.     return api.urlDownload("http://pastebin.com/raw.php?i=" .. tostring(code))
  544. end
  545.  
  546. -- Redirect
  547. api.redirect = function(url)
  548.     if type(url) ~= "string" then url = "home" end
  549.     os.queueEvent(event_redirect, url:gsub("rdnt://"):gsub("http://"))
  550.     error()
  551. end
  552.  
  553. -- Theme Function
  554. api.themeColor = function(tag, default)
  555.     if type(tag) ~= "string" then error("themeColor: expected string") end
  556.     if theme[tag] then
  557.         return colors[theme[tag]]
  558.     elseif defaultTheme[tag] then
  559.         return colors[defaultTheme[tag]]
  560.     else
  561.         return default or colors.white
  562.     end
  563. end
  564.  
  565. api.themeColour = function(tag, default)
  566.     return api.themeColor(tag, default)
  567. end
  568.  
  569. -- Prompt Software
  570. api.prompt = function(list, dir)
  571.     if isAdvanced() then
  572.         for _, v in pairs(list) do
  573.             if v.bg then term.setBackgroundColor(v.bg) end
  574.             if v.tc then term.setTextColor(v.tc) end
  575.             if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 6)/2) end
  576.  
  577.             term.setCursorPos(v[2], v[3])
  578.             write("[- " .. v[1])
  579.             term.setCursorPos(v[2] + v[1]:len() + 3, v[3])
  580.             write(" -]")
  581.         end
  582.  
  583.         while true do
  584.             local e, but, x, y = os.pullEvent()
  585.             if e == "mouse_click" then
  586.                 for _, v in pairs(list) do
  587.                     if x >= v[2] and x <= v[2] + v[1]:len() + 5 and y == v[3] then
  588.                         return v[1]
  589.                     end
  590.                 end
  591.             end
  592.         end
  593.     else
  594.         for _, v in pairs(list) do
  595.             term.setBackgroundColor(colors.black)
  596.             term.setTextColor(colors.white)
  597.             if v[2] == -1 then v[2] = math.ceil((w + 1)/2 - (v[1]:len() + 4)/2) end
  598.  
  599.             term.setCursorPos(v[2], v[3])
  600.             write("  " .. v[1])
  601.             term.setCursorPos(v[2] + v[1]:len() + 2, v[3])
  602.             write("  ")
  603.         end
  604.  
  605.         local key1, key2 = 200, 208
  606.         if dir == "horizontal" then key1, key2 = 203, 205 end
  607.  
  608.         local curSel = 1
  609.         term.setCursorPos(list[curSel][2], list[curSel][3])
  610.         write("[")
  611.         term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])
  612.         write("]")
  613.  
  614.         while true do
  615.             local e, key = os.pullEvent()
  616.             term.setCursorPos(list[curSel][2], list[curSel][3])
  617.             write(" ")
  618.             term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])
  619.             write(" ")
  620.             if e == "key" and key == key1 and curSel > 1 then
  621.                 curSel = curSel - 1
  622.             elseif e == "key" and key == key2 and curSel < #list then
  623.                 curSel = curSel + 1
  624.             elseif e == "key" and key == 28 then
  625.                 return list[curSel][1]
  626.             end
  627.             term.setCursorPos(list[curSel][2], list[curSel][3])
  628.             write("[")
  629.             term.setCursorPos(list[curSel][2] + list[curSel][1]:len() + 3, list[curSel][3])
  630.             write("]")
  631.         end
  632.     end
  633. end
  634.  
  635. api.scrollingPrompt = function(list, x, y, len, width)
  636.     local wid = width
  637.     if wid == nil then wid = w - 3 end
  638.  
  639.     local function updateDisplayList(items, loc, len)
  640.         local ret = {}
  641.         for i = 1, len do
  642.             local item = items[i + loc - 1]
  643.             if item ~= nil then table.insert(ret, item) end
  644.         end
  645.         return ret
  646.     end
  647.  
  648.     if isAdvanced() then
  649.         local function draw(a)
  650.             for i, v in ipairs(a) do
  651.                 term.setCursorPos(x, y + i - 1)
  652.                 write(string.rep(" ", wid))
  653.                 term.setCursorPos(x, y + i - 1)
  654.                 write("[ " .. v:sub(1, wid - 5))
  655.                 term.setCursorPos(wid + x - 2, y + i - 1)
  656.                 write("  ]")
  657.             end
  658.         end
  659.  
  660.         local loc = 1
  661.         local disList = updateDisplayList(list, loc, len)
  662.         draw(disList)
  663.  
  664.         while true do
  665.             local e, but, clx, cly = os.pullEvent()
  666.             if e == "key" and but == 200 and loc > 1 then
  667.                 loc = loc - 1
  668.                 disList = updateDisplayList(list, loc, len)
  669.                 draw(disList)
  670.             elseif e == "key" and but == 208 and loc + len - 1 < #list then
  671.                 loc = loc + 1
  672.                 disList = updateDisplayList(list, loc, len)
  673.                 draw(disList)
  674.             elseif e == "mouse_scroll" and but > 0 and loc + len - 1 < #list then
  675.                 loc = loc + but
  676.                 disList = updateDisplayList(list, loc, len)
  677.                 draw(disList)
  678.             elseif e == "mouse_scroll" and but < 0 and loc > 1 then
  679.                 loc = loc + but
  680.                 disList = updateDisplayList(list, loc, len)
  681.                 draw(disList)
  682.             elseif e == "mouse_click" then
  683.                 for i, v in ipairs(disList) do
  684.                     if clx >= x and clx <= x + wid and cly == i + y - 1 then
  685.                         return v
  686.                     end
  687.                 end
  688.             end
  689.         end
  690.     else
  691.         local function draw(a)
  692.             for i, v in ipairs(a) do
  693.                 term.setCursorPos(x, y + i - 1)
  694.                 write(string.rep(" ", wid))
  695.                 term.setCursorPos(x, y + i - 1)
  696.                 write("[ ] " .. v:sub(1, wid - 5))
  697.             end
  698.         end
  699.  
  700.         local loc = 1
  701.         local curSel = 1
  702.         local disList = updateDisplayList(list, loc, len)
  703.         draw(disList)
  704.         term.setCursorPos(x + 1, y + curSel - 1)
  705.         write("x")
  706.  
  707.         while true do
  708.             local e, key = os.pullEvent()
  709.             term.setCursorPos(x + 1, y + curSel - 1)
  710.             write(" ")
  711.             if e == "key" and key == 200 then
  712.                 if curSel > 1 then
  713.                     curSel = curSel - 1
  714.                 elseif loc > 1 then
  715.                     loc = loc - 1
  716.                     disList = updateDisplayList(list, loc, len)
  717.                     draw(disList)
  718.                 end
  719.             elseif e == "key" and key == 208 then
  720.                 if curSel < #disList then
  721.                     curSel = curSel + 1
  722.                 elseif loc + len - 1 < #list then
  723.                     loc = loc + 1
  724.                     disList = updateDisplayList(list, loc, len)
  725.                     draw(disList)
  726.                 end
  727.             elseif e == "key" and key == 28 then
  728.                 return list[curSel + loc - 1]
  729.             end
  730.             term.setCursorPos(x + 1, y + curSel - 1)
  731.             write("x")
  732.         end
  733.     end
  734. end
  735.  
  736. api.clearArea = function() api.clearPage(website) end
  737. api.cPrint = function(text) api.centerPrint(text) end
  738. api.cWrite = function(text) api.centerWrite(text) end
  739. api.lPrint = function(text) api.leftPrint(text) end
  740. api.lWrite = function(text) api.leftWrite(text) end
  741. api.rPrint = function(text) api.rightPrint(text) end
  742. api.rWrite = function(text) api.rightWrite(text) end
  743.  
  744. local pullevent = function(data)
  745.     while true do
  746.         local e, p1, p2, p3, p4, p5 = os.pullEventRaw()
  747.         if e == event_exitWebsite or e == "terminate" then
  748.             error()
  749.         end
  750.  
  751.         if data then
  752.             if e == data then return e, p1, p2, p3, p4, p5 end
  753.         else return e, p1, p2, p3, p4, p5 end
  754.     end
  755. end
  756.  
  757. -- Set Environment
  758. for k, v in pairs(getfenv(0)) do env[k] = v end
  759. for k, v in pairs(getfenv(1)) do env[k] = v end
  760. for k, v in pairs(env) do oldEnv[k] = v end
  761. for k, v in pairs(api) do env[k] = v end
  762. for k, v in pairs(env) do backupEnv[k] = v end
  763.  
  764. oldEnv["os"]["pullEvent"] = oldpullevent
  765. env["os"]["pullEvent"] = pullevent
  766. os.pullEvent = pullevent
  767.  
  768.  
  769. --  -------- Website Overrides
  770.  
  771. for k, v in pairs(env) do override[k] = v end
  772. local curtext, curbackground = colors.white, colors.black
  773. override.term = {}
  774. for k, v in pairs(env.term) do override.term[k] = v end
  775. override.os = {}
  776. for k, v in pairs(env.os) do override.os[k] = v end
  777.  
  778. override.write = function( sText )
  779.     local w,h = override.term.getSize()
  780.     local x,y = override.term.getCursorPos()
  781.  
  782.     local nLinesPrinted = 0
  783.     local function newLine()
  784.         if y + 1 <= h then
  785.             override.term.setCursorPos(1, y + 1)
  786.         else
  787.             override.term.setCursorPos(1, h)
  788.             override.term.scroll(1)
  789.         end
  790.         x, y = override.term.getCursorPos()
  791.         nLinesPrinted = nLinesPrinted + 1
  792.     end
  793.  
  794.     -- Print the line with proper word wrapping
  795.     while string.len(sText) > 0 do
  796.         local whitespace = string.match( sText, "^[ \t]+" )
  797.         if whitespace then
  798.             -- Print whitespace
  799.             term.write( whitespace )
  800.             x,y = override.term.getCursorPos()
  801.             sText = string.sub( sText, string.len(whitespace) + 1 )
  802.         end
  803.  
  804.         local newline = string.match( sText, "^\n" )
  805.         if newline then
  806.             -- Print newlines
  807.             newLine()
  808.             sText = string.sub( sText, 2 )
  809.         end
  810.  
  811.         local text = string.match( sText, "^[^ \t\n]+" )
  812.         if text then
  813.             sText = string.sub( sText, string.len(text) + 1 )
  814.             if string.len(text) > w then
  815.                 -- Print a multiline word
  816.                 while string.len( text ) > 0 do
  817.                     if x > w then
  818.                         newLine()
  819.                     end
  820.                     term.write( text )
  821.                     text = string.sub( text, (w-x) + 2 )
  822.                     x,y = override.term.getCursorPos()
  823.                 end
  824.             else
  825.                 -- Print a word normally
  826.                 if x + string.len(text) - 1 > w then
  827.                     newLine()
  828.                 end
  829.                 term.write( text )
  830.                 x,y = override.term.getCursorPos()
  831.             end
  832.         end
  833.     end
  834.  
  835.     return nLinesPrinted
  836. end
  837.  
  838. override.print = function( ... )
  839.     local nLinesPrinted = 0
  840.     for n,v in ipairs( { ... } ) do
  841.         nLinesPrinted = nLinesPrinted + override.write( tostring( v ) )
  842.     end
  843.     nLinesPrinted = nLinesPrinted + override.write( "\n" )
  844.     return nLinesPrinted
  845. end
  846.  
  847. override.term.getSize = function()
  848.     local a, b = env.term.getSize()
  849.     return a, b - 1
  850. end
  851.  
  852. override.term.setCursorPos = function(x, y)
  853.     if y < 1 then
  854.         return env.term.setCursorPos(x, 2)
  855.     else
  856.         return env.term.setCursorPos(x, y+1)
  857.     end
  858. end
  859.  
  860. override.term.getCursorPos = function()
  861.     local x, y = env.term.getCursorPos()
  862.     return x, y - 1
  863. end
  864.  
  865. override.term.getBackgroundColor = function()
  866.     return curbackground
  867. end
  868.  
  869. override.term.getBackgroundColour = function()
  870.     return override.term.getBackgroundColor()
  871. end
  872.  
  873. override.term.setBackgroundColor = function(col)
  874.     curbackground = col
  875.     return env.term.setBackgroundColor(col)
  876. end
  877.  
  878. override.term.setBackgroundColour = function(col)
  879.     return override.term.setBackgroundColor(col)
  880. end
  881.  
  882. override.term.getTextColor = function()
  883.     return curtext
  884. end
  885.  
  886. override.term.getTextColour = function()
  887.     return override.term.getTextColor()
  888. end
  889.  
  890. override.term.setTextColor = function(col)
  891.     curtext = col
  892.     return env.term.setTextColor(col)
  893. end
  894.  
  895. override.term.setTextColour = function(col)
  896.     return override.term.setTextColor(col)
  897. end
  898.  
  899. override.term.clear = function()
  900.     local x, y = term.getCursorPos()
  901.     local oldbackground = override.term.getBackgroundColor()
  902.     local oldtext = override.term.getTextColor()
  903.     clearPage(website, curbackground)
  904.  
  905.     term.setBackgroundColor(oldbackground)
  906.     term.setTextColor(oldtext)
  907.     term.setCursorPos(x, y)
  908. end
  909.  
  910. override.term.scroll = function(n)
  911.     local x, y = term.getCursorPos()
  912.     local oldbackground = override.term.getBackgroundColor()
  913.     local oldtext = override.term.getTextColor()
  914.  
  915.     env.term.scroll(n)
  916.     clearPage(website, curbackground, true)
  917.     term.setBackgroundColor(oldbackground)
  918.     term.setTextColor(oldtext)
  919.     term.setCursorPos(x, y)
  920. end
  921.  
  922. override.term.isColor = function() return isAdvanced() end
  923. override.term.isColour = function() return override.term.isColor() end
  924.  
  925. override.os.queueEvent = function(event, ...)
  926.     if event == "terminate" or event == event_exitApp then
  927.         os.queueEvent(event_exitWebsite)
  928.     else
  929.         env.os.queueEvent(event, ...)
  930.     end
  931. end
  932.  
  933. override.os.pullEvent = function(data)
  934.     while true do
  935.         local e, p1, p2, p3, p4, p5 = os.pullEventRaw()
  936.         if e == event_exitWebsite or e == "terminate" then
  937.             error()
  938.         elseif (e == "mouse_click" or e == "mouse_drag") and not data then
  939.             return e, p1, p2, p3 - 1
  940.         elseif e == "mouse_click" and data == "mouse_click" then
  941.             return e, p1, p2, p3 - 1
  942.         elseif e == "mouse_drag" and data == "mouse_drag" then
  943.             return e, p1, p2, p3 - 1
  944.         end
  945.  
  946.         if data then
  947.             if e == data then return e, p1, p2, p3, p4, p5 end
  948.         else return e, p1, p2, p3, p4, p5 end
  949.     end
  950. end
  951.  
  952. local overridePullEvent = override.os.pullEvent
  953.  
  954. override.prompt = function(list, dir)
  955.     local a = {}
  956.     for k, v in pairs(list) do
  957.         table.insert(a, {v[1], v[2], v[3] + 1, tc = v.tc or curtext, bg = v.bg or curbackground})
  958.     end
  959.     return env.prompt(a, dir)
  960. end
  961.  
  962. override.scrollingPrompt = function(list, x, y, len, width)
  963.     return env.scrollingPrompt(list, x, y + 1, len, width)
  964. end
  965.  
  966. local barTerm = {}
  967. for k, v in pairs(override.term) do barTerm[k] = v end
  968.  
  969. barTerm.clear = override.term.clear
  970. barTerm.scroll = override.term.scroll
  971.  
  972. local safeTerm = {}
  973. for k, v in pairs(term) do safeTerm[k] = v end
  974.  
  975. override.showBar = function()
  976.     clickableAddressBar = true
  977.     os.pullEvent = overridePullEvent
  978.     return os.pullEvent, barTerm
  979. end
  980.  
  981. override.hideBar = function()
  982.     clickableAddressBar = false
  983.     os.pullEvent = pullevent
  984.     return os.pullEvent, safeTerm
  985. end
  986.  
  987.  
  988. --  -------- Antivirus System
  989.  
  990. -- Overrides
  991. local antivirusOverrides = {
  992.     ["Run Files"] = {"shell.run", "os.run"},
  993.     ["Modify System"] = {"shell.setAlias", "shell.clearAlias", "os.setComputerLabel", "shell.setDir",
  994.         "shell.setPath"},
  995.     ["Modify Files"] = {"fs.makeDir", "fs.move", "fs.copy", "fs.delete", "fs.open",
  996.         "io.open", "io.write", "io.read", "io.close"},
  997.     ["Shutdown Computer"] = {"os.shutdown", "os.reboot", "shell.exit"},
  998.     ["Use pcall"] = {"pcall"},
  999. }
  1000.  
  1001. local antivirusDestroy = {
  1002.     "rawset", "rawget", "setfenv", "loadfile", "loadstring", "dofile"
  1003. }
  1004.  
  1005. -- Graphical Function
  1006. local function triggerAntivirus(offence, onlyCancel)
  1007.     local oldback, oldtext = curbackground, curtext
  1008.  
  1009.     local ox, oy = term.getCursorPos()
  1010.     openAddressBar = false
  1011.     term.setBackgroundColor(colors[theme["address-bar-background"]])
  1012.     term.setTextColor(colors[theme["address-bar-text"]])
  1013.     term.setCursorPos(2, 1)
  1014.     term.clearLine()
  1015.     write("Request: " .. offence)
  1016.     local a = {{"Allow", w - 24, 1}, {"Cancel", w - 12, 1}}
  1017.     if onlyCancel == true then a = {{"Cancel", w - 12, 1}} end
  1018.     local opt = prompt(a, "horizontal")
  1019.  
  1020.     clearPage(website, nil, true)
  1021.     term.setTextColor(colors.white)
  1022.     term.setBackgroundColor(colors.black)
  1023.     term.setCursorPos(ox, oy)
  1024.     term.setBackgroundColor(oldback)
  1025.     term.setTextColor(oldtext)
  1026.     if opt == "Allow" then
  1027.         -- To prevent the menu bar from opening
  1028.         os.queueEvent("firewolf_requiredEvent")
  1029.         os.pullEvent()
  1030.  
  1031.         openAddressBar = true
  1032.         return true
  1033.     elseif opt == "Cancel" then
  1034.         redirect("home")
  1035.     end
  1036. end
  1037.  
  1038. -- Copy from override
  1039. for k, v in pairs(override) do antivirus[k] = v end
  1040.  
  1041. antivirus.shell = {}
  1042. for k, v in pairs(override.shell) do antivirus.shell[k] = v end
  1043. antivirus.os = {}
  1044. for k, v in pairs(override.os) do antivirus.os[k] = v end
  1045. antivirus.fs = {}
  1046. for k, v in pairs(override.fs) do antivirus.fs[k] = v end
  1047. antivirus.io = {}
  1048. for k, v in pairs(override.io) do antivirus.io[k] = v end
  1049.  
  1050. -- Override malicious functions
  1051. for warning, v in pairs(antivirusOverrides) do
  1052.     for k, func in pairs(v) do
  1053.         if func:find(".", 1, true) then
  1054.             -- Functions in another table
  1055.             local table = func:sub(1, func:find(".", 1, true) - 1)
  1056.             local funcname = func:sub(func:find(".", 1, true) + 1, -1)
  1057.  
  1058.             antivirus[table][funcname] = function(...)
  1059.                 env.setfenv(triggerAntivirus, env)
  1060.                 if triggerAntivirus(warning) then
  1061.                     return override[table][funcname](...)
  1062.                 end
  1063.             end
  1064.         else
  1065.             -- Plain functions
  1066.             antivirus[func] = function(...)
  1067.                 env.setfenv(triggerAntivirus, env)
  1068.                 if triggerAntivirus(warning) then
  1069.                     return override[func](...)
  1070.                 end
  1071.             end
  1072.         end
  1073.     end
  1074. end
  1075.  
  1076. -- Override functions to destroy
  1077. for k, v in pairs(antivirusDestroy) do
  1078.     antivirus[v] = function(...)
  1079.         env.setfenv(triggerAntivirus, env)
  1080.         triggerAntivirus("Destory your System! D:", true)
  1081.         return nil
  1082.     end
  1083. end
  1084.  
  1085. antivirus.pcall = function(...)
  1086.     local suc, err = env.pcall(...)
  1087.     if err:lower():find("terminate") then
  1088.         error("terminate")
  1089.     elseif err:lower():find(event_exitWebsite) then
  1090.         error(event_exitWebsite)
  1091.     end
  1092.  
  1093.     return suc, err
  1094. end
  1095.  
  1096.  
  1097. --  -------- Graphics and Files
  1098.  
  1099. graphics.githubImage = [[
  1100. f       f
  1101. fffffffff
  1102. fffffffff
  1103. f4244424f
  1104. f4444444f
  1105. fffffefffe
  1106.    fffe e
  1107.  fffff e
  1108. ff f fe e
  1109.      e   e
  1110. ]]
  1111.  
  1112. files.availableThemes = [[
  1113. https://raw.github.com/1lann/firewolf/master/themes/default.txt| |Fire (default)
  1114. https://raw.github.com/1lann/firewolf/master/themes/ice.txt| |Ice
  1115. https://raw.github.com/1lann/firewolf/master/themes/carbon.txt| |Carbon
  1116. https://raw.github.com/1lann/firewolf/master/themes/christmas.txt| |Christmas
  1117. https://raw.github.com/1lann/firewolf/master/themes/original.txt| |Original
  1118. https://raw.github.com/1lann/firewolf/master/themes/ocean.txt| |Ocean
  1119. https://raw.github.com/1lann/firewolf/master/themes/forest.txt| |Forest
  1120. https://raw.github.com/1lann/firewolf/master/themes/pinky.txt| |Pinky
  1121. https://raw.github.com/1lann/firewolf/master/themes/azhftech.txt| |AzhfTech
  1122. ]]
  1123.  
  1124. files.newTheme = [[
  1125. -- Text color of the address bar
  1126. address-bar-text=
  1127. -- Background color of the address bar
  1128. address-bar-background=
  1129. -- Color of separator bar when live searching
  1130. address-bar-base=
  1131. -- Top box color
  1132. top-box=
  1133. -- Bottom box color
  1134. bottom-box=
  1135. -- Background color
  1136. background=
  1137. -- Main text color
  1138. text-color=
  1139. ]]
  1140.  
  1141.  
  1142. --  -------- Themes
  1143.  
  1144. local defaultTheme = {["address-bar-text"] = "white", ["address-bar-background"] = "gray",
  1145.     ["address-bar-base"] = "lightGray", ["top-box"] = "red", ["bottom-box"] = "orange",
  1146.     ["text-color"] = "white", ["background"] = "gray"}
  1147. local originalTheme = {["address-bar-text"] = "white", ["address-bar-background"] = "black",
  1148.     ["address-bar-base"] = "black", ["top-box"] = "black", ["bottom-box"] = "black",
  1149.     ["text-color"] = "white", ["background"] = "black"}
  1150.  
  1151. local function loadTheme(path)
  1152.     if fs.exists(path) and not fs.isDir(path) then
  1153.         local a = {}
  1154.         local f = io.open(path, "r")
  1155.         local l = f:read("*l")
  1156.         while l ~= nil do
  1157.             l = l:gsub("^%s*(.-)%s*$", "%1")
  1158.             if l ~= "" and l ~= nil and l ~= "\n" and l:sub(1, 2) ~= "--" then
  1159.                 local b = l:find("=")
  1160.                 if a and b then
  1161.                     local c = l:sub(1, b - 1)
  1162.                     local d = l:sub(b + 1, -1)
  1163.                     if c == "" or d == "" then return nil
  1164.                     else a[c] = d end
  1165.                 else return nil end
  1166.             end
  1167.             l = f:read("*l")
  1168.         end
  1169.         f:close()
  1170.  
  1171.         return a
  1172.     end
  1173. end
  1174.  
  1175.  
  1176. --  -------- Filesystem and HTTP
  1177.  
  1178. local function download(url, path)
  1179.     for i = 1, 3 do
  1180.         local response = http.get(url)
  1181.         if response then
  1182.             local data = response.readAll()
  1183.             response.close()
  1184.             if path then
  1185.                 local f = io.open(path, "w")
  1186.                 f:write(data)
  1187.                 f:close()
  1188.             end
  1189.             return true
  1190.         end
  1191.     end
  1192.  
  1193.     return false
  1194. end
  1195.  
  1196. local function updateClient()
  1197.     local skipNormal = false
  1198.     if serverID ~= "experimental" then
  1199.         http.request(buildURL)
  1200.         local a = os.startTimer(10)
  1201.         while true do
  1202.             local e, url, handle = os.pullEvent()
  1203.             if e == "http_success" then
  1204.                 if tonumber(handle.readAll()) > build then break
  1205.                 else return false end
  1206.             elseif e == "http_failure" or (e == "timer" and url == a) then
  1207.                 skipNormal = true
  1208.                 break
  1209.             end
  1210.         end
  1211.     end
  1212.  
  1213.     local source = nil
  1214.  
  1215.     if not skipNormal then
  1216.         local _, y = term.getCursorPos()
  1217.         term.setCursorPos(1, y - 2)
  1218.         rightWrite(string.rep(" ", 32))
  1219.         rightWrite("Updating Firewolf... ")
  1220.  
  1221.         http.request(firewolfURL)
  1222.         local a = os.startTimer(10)
  1223.         while true do
  1224.             local e, url, handle = os.pullEvent()
  1225.             if e == "http_success" then
  1226.                 source = handle
  1227.                 break
  1228.             elseif e == "http_failure" or (e == "timer" and url == a) then
  1229.                 break
  1230.             end
  1231.         end
  1232.     end
  1233.  
  1234.     if not source then
  1235.         if isAdvanced() then
  1236.             term.setTextColor(colors[theme["text-color"]])
  1237.             term.setBackgroundColor(colors[theme["background"]])
  1238.             term.clear()
  1239.             if not fs.exists(rootFolder) then fs.makeDir(rootFolder) end
  1240.             local f = io.open(rootFolder .. "/temp_file", "w")
  1241.             f:write(graphics.githubImage)
  1242.             f:close()
  1243.             local a = paintutils.loadImage(rootFolder .. "/temp_file")
  1244.             paintutils.drawImage(a, 5, 5)
  1245.             fs.delete(rootFolder .. "/temp_file")
  1246.  
  1247.             term.setCursorPos(19, 4)
  1248.             term.setBackgroundColor(colors[theme["top-box"]])
  1249.             write(string.rep(" ", 32))
  1250.             term.setCursorPos(19, 5)
  1251.             write("  Could Not Connect to GitHub!  ")
  1252.             term.setCursorPos(19, 6)
  1253.             write(string.rep(" ", 32))
  1254.             term.setBackgroundColor(colors[theme["bottom-box"]])
  1255.             term.setCursorPos(19, 8)
  1256.             write(string.rep(" ", 32))
  1257.             term.setCursorPos(19, 9)
  1258.             write("    Sorry, Firewolf could not   ")
  1259.             term.setCursorPos(19, 10)
  1260.             write(" connect to GitHub to download  ")
  1261.             term.setCursorPos(19, 11)
  1262.             write(" necessary files. Please check: ")
  1263.             term.setCursorPos(19, 12)
  1264.             write("    http://status.github.com    ")
  1265.             term.setCursorPos(19, 13)
  1266.             write(string.rep(" ", 32))
  1267.             term.setCursorPos(19, 14)
  1268.             write("        Click to exit...        ")
  1269.             term.setCursorPos(19, 15)
  1270.             write(string.rep(" ", 32))
  1271.         else
  1272.             term.clear()
  1273.             term.setCursorPos(1, 1)
  1274.             term.setBackgroundColor(colors.black)
  1275.             term.setTextColor(colors.white)
  1276.             print("\n")
  1277.             centerPrint("Could not connect to GitHub!")
  1278.             print("")
  1279.             centerPrint("Sorry, Firewolf could not connect to")
  1280.             centerPrint("GitHub to download necessary files.")
  1281.             centerPrint("Please check:")
  1282.             centerPrint("http://status.github.com")
  1283.             print("")
  1284.             centerPrint("Press any key to exit...")
  1285.         end
  1286.  
  1287.         while true do
  1288.             local e = oldpullevent()
  1289.             if e == "mouse_click" or e == "key" then break end
  1290.         end
  1291.  
  1292.         return false
  1293.     elseif source and autoupdate == "true" then
  1294.         local b = io.open(firewolfLocation, "r")
  1295.         local new = source.readAll()
  1296.         local cur = b:read("*a")
  1297.         source.close()
  1298.         b:close()
  1299.  
  1300.         if cur ~= new then
  1301.             fs.delete(firewolfLocation)
  1302.             local f = io.open(firewolfLocation, "w")
  1303.             f:write(new)
  1304.             f:close()
  1305.             return true
  1306.         else
  1307.             return false
  1308.         end
  1309.     end
  1310. end
  1311.  
  1312. local function resetFilesystem()
  1313.     -- Migrate
  1314.     fs.delete(rootFolder .. "/available_themes")
  1315.     fs.delete(rootFolder .. "/default_theme")
  1316.  
  1317.     -- Reset
  1318.     if not fs.exists(rootFolder) then fs.makeDir(rootFolder)
  1319.     elseif not fs.isDir(rootFolder) then fs.move(rootFolder, "/Firewolf_Data.old") end
  1320.  
  1321.     if not fs.isDir(serverFolder) then fs.delete(serverFolder) end
  1322.     if not fs.exists(serverFolder) then fs.makeDir(serverFolder) end
  1323.     if not fs.isDir(cacheFolder) then fs.delete(cacheFolder) end
  1324.     if not fs.exists(cacheFolder) then fs.makeDir(cacheFolder) end
  1325.     if not fs.isDir(websiteDataFolder) then fs.delete(websiteDataFolder) end
  1326.     if not fs.exists(websiteDataFolder) then fs.makeDir(websiteDataFolder) end
  1327.  
  1328.     if fs.isDir(settingsLocation) then fs.delete(settingsLocation) end
  1329.     if fs.isDir(serverLocation) then fs.delete(serverLocation) end
  1330.  
  1331.     if not fs.exists(settingsLocation) then
  1332.         local f = io.open(settingsLocation, "w")
  1333.         f:write(textutils.serialize({auto = "true", incog = "false", home = "firewolf"}))
  1334.         f:close()
  1335.     end
  1336.  
  1337.     if not fs.exists(serverLocation) then
  1338.         download(serverURL, serverLocation)
  1339.     end
  1340.  
  1341.     fs.delete(rootFolder .. "/temp_file")
  1342.  
  1343.     for _, v in pairs({userWhitelist, userBlacklist}) do
  1344.         if fs.isDir(v) then fs.delete(v) end
  1345.         if not fs.exists(v) then
  1346.             local f = io.open(v, "w")
  1347.             f:write("")
  1348.             f:close()
  1349.         end
  1350.     end
  1351. end
  1352.  
  1353. local function checkForModem(display)
  1354.     while true do
  1355.         local present = false
  1356.         for _, v in pairs(rs.getSides()) do
  1357.             if peripheral.getType(v) == "modem" then
  1358.                 rednet.open(v)
  1359.                 present = true
  1360.                 break
  1361.             end
  1362.         end
  1363.  
  1364.         if not present and type(display) == "function" then
  1365.             display()
  1366.             os.pullEvent("peripheral")
  1367.         else
  1368.             return true
  1369.         end
  1370.     end
  1371. end
  1372.  
  1373.  
  1374. --  -------- Databases
  1375.  
  1376. local function loadDatabases()
  1377.     -- Blacklist
  1378.     if fs.exists(userBlacklist) and not fs.isDir(userBlacklist) then
  1379.         local bf = io.open(userBlacklist, "r")
  1380.         local l = bf:read("*l")
  1381.         while l ~= nil do
  1382.             if l ~= nil and l ~= "" and l ~= "\n" then
  1383.                 l = l:gsub("^%s*(.-)%s*$", "%1")
  1384.                 table.insert(blacklist, l)
  1385.             end
  1386.             l = bf:read("*l")
  1387.         end
  1388.         bf:close()
  1389.     end
  1390.  
  1391.     -- Whitelist
  1392.     if fs.exists(userWhitelist) and not fs.isDir(userWhitelist) then
  1393.         local wf = io.open(userWhitelist, "r")
  1394.         local l = wf:read("*l")
  1395.         while l ~= nil do
  1396.             if l ~= nil and l ~= "" and l ~= "\n" then
  1397.                 l = l:gsub("^%s*(.-)%s*$", "%1")
  1398.                 local a, b = l:find("| |")
  1399.                 table.insert(whitelist, {l:sub(1, a - 1), l:sub(b + 1, -1)})
  1400.             end
  1401.             l = wf:read("*l")
  1402.         end
  1403.         wf:close()
  1404.     end
  1405. end
  1406.  
  1407. local function verifyBlacklist(id)
  1408.     for _, v in pairs(blacklist) do
  1409.         if tostring(id) == v then return true end
  1410.     end
  1411.     return false
  1412. end
  1413.  
  1414. local function verifyWhitelist(id, url)
  1415.     for _, v in pairs(whitelist) do
  1416.         if v[2] == tostring(args[1]) and v[1] == tostring(args[2]) then
  1417.             return true
  1418.         end
  1419.     end
  1420.     return false
  1421. end
  1422.  
  1423.  
  1424. --  -------- Protocols
  1425.  
  1426. protocols.rdnt = {}
  1427. protocols.http = {}
  1428.  
  1429. protocols.rdnt.getSearchResults = function()
  1430.     dnsDatabase = {[1] = {}, [2] = {}}
  1431.     local resultIDs = {}
  1432.     local conflict = {}
  1433.  
  1434.     rednet.broadcast("firewolf.broadcast.dns.list")
  1435.     local startClock = os.clock()
  1436.     while os.clock() - startClock < timeout do
  1437.         local id, i = rednet.receive(timeout)
  1438.         if id then
  1439.             if i:sub(1, 14) == "firewolf-site:" then
  1440.                 i = i:sub(15, -1)
  1441.                 local bl, wl = verifyBlacklist(id), verifyWhitelist(id, i)
  1442.                 if not i:find(" ") and i:len() < 40 and (not bl or (bl and wl)) then
  1443.                     if not resultIDs[tostring(id)] then resultIDs[tostring(id)] = 1
  1444.                     else resultIDs[tostring(id)] = resultIDs[tostring(id)] + 1
  1445.                     end
  1446.  
  1447.                     if not i:find("rdnt://") then i = ("rdnt://" .. i) end
  1448.                     local x = false
  1449.                     if conflict[i] then
  1450.                         x = true
  1451.                         table.insert(conflict[i], id)
  1452.                     else
  1453.                         for m, n in pairs(dnsDatabase[1]) do
  1454.                             if n:lower() == i:lower() then
  1455.                                 x = true
  1456.                                 table.remove(dnsDatabase[1], m)
  1457.                                 table.remove(dnsDatabase[2], m)
  1458.                                 if conflict[i] then
  1459.                                     table.insert(conflict[i], id)
  1460.                                 else
  1461.                                     conflict[i] = {}
  1462.                                     table.insert(conflict[i], id)
  1463.                                 end
  1464.                                 break
  1465.                             end
  1466.                         end
  1467.                     end
  1468.  
  1469.                     if not x and resultIDs[tostring(id)] <= 3 then
  1470.                         table.insert(dnsDatabase[1], i)
  1471.                         table.insert(dnsDatabase[2], id)
  1472.                     end
  1473.                 end
  1474.             end
  1475.         else
  1476.             break
  1477.         end
  1478.     end
  1479.     for k,v in pairs(conflict) do
  1480.         table.sort(v)
  1481.         table.insert(dnsDatabase[1], k)
  1482.         table.insert(dnsDatabase[2], v[1])
  1483.     end
  1484.  
  1485.     return dnsDatabase[1]
  1486. end
  1487.  
  1488. protocols.rdnt.getWebsite = function(site)
  1489.     local id, content, status = nil, nil, nil
  1490.     local clock = os.clock()
  1491.     local websiteID = nil
  1492.     for k, v in pairs(dnsDatabase[1]) do
  1493.         local web = site:gsub("rdnt://", "")
  1494.         if web:find("/") then web = web:sub(1, web:find("/") - 1) end
  1495.         if web == v:gsub("rdnt://", "") then
  1496.             websiteID = dnsDatabase[2][k]
  1497.             break
  1498.         end
  1499.     end
  1500.     if not websiteID then return nil, nil, nil end
  1501.  
  1502.     sleep(timeout)
  1503.     rednet.send(websiteID, site)
  1504.     clock = os.clock()
  1505.     while os.clock() - clock < timeout do
  1506.         id, content = rednet.receive(timeout)
  1507.         if id then
  1508.             if id == websiteID then
  1509.                 local bl = verifyBlacklist(id)
  1510.                 local wl = verifyWhitelist(id, site)
  1511.                 status = nil
  1512.                 if (bl and not wl) or site == "" or site == "." or site == ".." then
  1513.                     -- Ignore
  1514.                 elseif wl then
  1515.                     status = "whitelist"
  1516.                     break
  1517.                 else
  1518.                     status = "safe"
  1519.                     break
  1520.                 end
  1521.             end
  1522.         end
  1523.     end
  1524.  
  1525.     return id, content, status
  1526. end
  1527.  
  1528. protocols.http.getSearchResults = function()
  1529.     dnsDatabase = {[1] = {}, [2] = {}}
  1530.     return dnsDatabase[1]
  1531. end
  1532.  
  1533. protocols.http.getWebsite = function()
  1534.     return nil, nil, nil
  1535. end
  1536.  
  1537.  
  1538. --  -------- Homepage
  1539.  
  1540. pages["firewolf"] = function(site)
  1541.     openAddressBar = true
  1542.     term.setBackgroundColor(colors[theme["background"]])
  1543.     term.clear()
  1544.     term.setTextColor(colors[theme["text-color"]])
  1545.     term.setBackgroundColor(colors[theme["top-box"]])
  1546.     print("")
  1547.     leftPrint(string.rep(" ", 42))
  1548.     leftPrint([[        _,-='"-.__               /\_/\    ]])
  1549.     leftPrint([[         -.}        =._,.-==-._.,  @ @._, ]])
  1550.     leftPrint([[            -.__  __,-.   )       _,.-'   ]])
  1551.     leftPrint([[ Firewolf ]] .. version .. string.rep(" ", 8 - version:len()) ..
  1552.         [["    G..m-"^m m'        ]])
  1553.     leftPrint(string.rep(" ", 42))
  1554.     print("\n")
  1555.  
  1556.     term.setBackgroundColor(colors[theme["bottom-box"]])
  1557.     rightPrint(string.rep(" ", 42))
  1558.     if isAdvanced() then rightPrint("  News:                       [- Sites -] ")
  1559.     else rightPrint("  News:                                   ") end
  1560.     rightPrint("    Firewolf 2.4 is out! It cuts out 1500 ")
  1561.     rightPrint("   lines, and contains many improvements! ")
  1562.     rightPrint(string.rep(" ", 42))
  1563.     rightPrint("   Firewolf 3.0 will be out soon! It will ")
  1564.     rightPrint("     bring the long awaited HTTP support! ")
  1565.     rightPrint(string.rep(" ", 42))
  1566.  
  1567.     while true do
  1568.         local e, but, x, y = os.pullEvent()
  1569.         if isAdvanced() and e == "mouse_click" and x >= 40 and x <= 50 and y == 11 then
  1570.             redirect("firewolf/sites")
  1571.         end
  1572.     end
  1573. end
  1574.  
  1575. pages["firefox"] = function(site) redirect("firewolf") end
  1576.  
  1577. pages["firewolf/sites"] = function(site)
  1578.     term.setBackgroundColor(colors[theme["background"]])
  1579.     term.clear()
  1580.     term.setTextColor(colors[theme["text-color"]])
  1581.     term.setBackgroundColor(colors[theme["top-box"]])
  1582.     print("\n")
  1583.     leftPrint(string.rep(" ", 17))
  1584.     leftPrint(" Built-In Sites  ")
  1585.     leftPrint(string.rep(" ", 17))
  1586.  
  1587.     local sx = 8
  1588.     term.setBackgroundColor(colors[theme["bottom-box"]])
  1589.     term.setCursorPos(1, sx)
  1590.     rightPrint(string.rep(" ", 40))
  1591.     rightPrint("  rdnt://firewolf              Homepage ")
  1592.     rightPrint("  rdnt://firewolf/sites           Sites ")
  1593.     rightPrint("  rdnt://server       Server Management ")
  1594.     rightPrint("  rdnt://help                 Help Page ")
  1595.     rightPrint("  rdnt://settings              Settings ")
  1596.     rightPrint("  rdnt://credits                Credits ")
  1597.     rightPrint("  rdnt://exit                      Exit ")
  1598.     rightPrint(string.rep(" ", 40))
  1599.  
  1600.     local a = {"firewolf", "firewolf/sites", "server", "help", "settings", "credits", "exit"}
  1601.     while true do
  1602.         local e, but, x, y = os.pullEvent()
  1603.         if isAdvanced() and e == "mouse_click" and x >= 14 and x <= 50 then
  1604.             for i, v in ipairs(a) do
  1605.                 if y == sx + i then
  1606.                     if v == "exit" then return true end
  1607.                     redirect(v)
  1608.                 end
  1609.             end
  1610.         end
  1611.     end
  1612. end
  1613.  
  1614. pages["sites"] = function(site) redirect("firewolf/sites") end
  1615.  
  1616.  
  1617. --  -------- Server Management
  1618.  
  1619. local function manageServers(site, protocol, functionList, startServerName)
  1620.     local servers = functionList["reload servers"]()
  1621.     local sy = 7
  1622.  
  1623.     if startServerName == nil then startServerName = "Start" end
  1624.     if isAdvanced() then
  1625.         local function draw(l, sel)
  1626.             term.setBackgroundColor(colors[theme["bottom-box"]])
  1627.             term.setCursorPos(4, sy)
  1628.             write("[- New Server -]")
  1629.             for i, v in ipairs(l) do
  1630.                 term.setCursorPos(3, i + sy)
  1631.                 write(string.rep(" ", 24))
  1632.                 term.setCursorPos(4, i + sy)
  1633.                 local nv = v
  1634.                 if nv:len() > 18 then nv = nv:sub(1, 15) .. "..." end
  1635.                 if i == sel then write("[ " .. nv .. " ]")
  1636.                 else write("  " .. nv) end
  1637.             end
  1638.             if #l < 1 then
  1639.                 term.setCursorPos(4, sy + 2)
  1640.                 write("A website is literally")
  1641.                 term.setCursorPos(4, sy + 3)
  1642.                 write("just a lua script!")
  1643.                 term.setCursorPos(4, sy + 4)
  1644.                 write("Go ahead and make one!")
  1645.                 term.setCursorPos(4, sy + 6)
  1646.                 write("Also, be sure to check")
  1647.                 term.setCursorPos(4, sy + 7)
  1648.                 write("out Firewolf's APIs to")
  1649.                 term.setCursorPos(4, sy + 8)
  1650.                 write("help you make your")
  1651.                 term.setCursorPos(4, sy + 9)
  1652.                 write("site, at rdnt://help")
  1653.             end
  1654.  
  1655.             term.setCursorPos(30, sy)
  1656.             write(string.rep(" ", 19))
  1657.             term.setCursorPos(30, sy)
  1658.             if l[sel] then
  1659.                 local nl = l[sel]
  1660.                 if nl:len() > 19 then nl = nl:sub(1, 16) .. "..." end
  1661.                 write(nl)
  1662.             else write("No Server Selected!") end
  1663.             term.setCursorPos(30, sy + 2)
  1664.             write("[- " .. startServerName .. " -]")
  1665.             term.setCursorPos(30, sy + 4)
  1666.             write("[- Edit -]")
  1667.             term.setCursorPos(30, sy + 6)
  1668.             if functionList["run on boot"] then write("[- Run on Boot -]") end
  1669.             term.setCursorPos(30, sy + 8)
  1670.             write("[- Delete -]")
  1671.         end
  1672.  
  1673.         local function updateDisplayList(items, loc, len)
  1674.             local ret = {}
  1675.             for i = 1, len do
  1676.                 if items[i + loc - 1] then table.insert(ret, items[i + loc - 1]) end
  1677.             end
  1678.             return ret
  1679.         end
  1680.  
  1681.         while true do
  1682.             term.setBackgroundColor(colors[theme["background"]])
  1683.             term.clear()
  1684.             term.setCursorPos(1, 1)
  1685.             term.setTextColor(colors[theme["text-color"]])
  1686.             term.setBackgroundColor(colors[theme["top-box"]])
  1687.             print("")
  1688.             leftPrint(string.rep(" ", 27))
  1689.             leftPrint(" Server Management - " .. protocol:upper() .. "  ")
  1690.             leftPrint(string.rep(" ", 27))
  1691.             print("")
  1692.  
  1693.             term.setBackgroundColor(colors[theme["bottom-box"]])
  1694.             for i = 1, 12 do
  1695.                 term.setCursorPos(3, i + sy - 2)
  1696.                 write(string.rep(" ", 24))
  1697.                 term.setCursorPos(29, i + sy - 2)
  1698.                 write(string.rep(" ", 21))
  1699.             end
  1700.  
  1701.             local sel = 1
  1702.             local loc = 1
  1703.             local len = 10
  1704.             local disList = updateDisplayList(servers, loc, len)
  1705.             draw(disList, sel)
  1706.  
  1707.             while true do
  1708.                 local e, but, x, y = os.pullEvent()
  1709.                 if e == "key" and but == 200 and #servers > 0 and loc > 1 then
  1710.                     loc = loc - 1
  1711.                     disList = updateDisplayList(servers, loc, len)
  1712.                     draw(disList, sel)
  1713.                 elseif e == "key" and but == 208 and #servers > 0 and loc + len - 1 < #servers then
  1714.                     loc = loc + 1
  1715.                     disList = updateDisplayList(servers, loc, len)
  1716.                     draw(disList, sel)
  1717.                 elseif e == "mouse_click" then
  1718.                     if x >= 4 and x <= 25 then
  1719.                         if y == 7 then
  1720.                             functionList["new server"]()
  1721.                             servers = functionList["reload servers"]()
  1722.                             break
  1723.                         elseif #servers > 0 then
  1724.                             for i, v in ipairs(disList) do
  1725.                                 if y == i + 7 then
  1726.                                     sel = i
  1727.                                     draw(disList, sel)
  1728.                                 end
  1729.                             end
  1730.                         end
  1731.                     elseif x >= 30 and x <= 40 and y == 9 and #servers > 0 then
  1732.                         functionList["start"](disList[sel])
  1733.                         servers = functionList["reload servers"]()
  1734.                         break
  1735.                     elseif x >= 30 and x <= 39 and y == 11 and #servers > 0 then
  1736.                         functionList["edit"](disList[sel])
  1737.                         servers = functionList["reload servers"]()
  1738.                         break
  1739.                     elseif x >= 30 and x <= 46 and y == 13 and #servers > 0 and
  1740.                             functionList["run on boot"] then
  1741.                         functionList["run on boot"](disList[sel])
  1742.                         term.setBackgroundColor(colors[theme["bottom-box"]])
  1743.                         term.setCursorPos(32, 15)
  1744.                         write("Will Run on Boot!")
  1745.                         openAddressBar = false
  1746.                         sleep(1.3)
  1747.                         openAddressBar = true
  1748.                         term.setCursorPos(32, 15)
  1749.                         write(string.rep(" ", 18))
  1750.                         break
  1751.                     elseif x >= 30 and x <= 41 and y == 15 and #servers > 0 then
  1752.                         functionList["delete"](disList[sel])
  1753.                         servers = functionList["reload servers"]()
  1754.                         break
  1755.                     end
  1756.                 end
  1757.             end
  1758.         end
  1759.     else
  1760.         while true do
  1761.             term.setBackgroundColor(colors[theme["background"]])
  1762.             term.clear()
  1763.             term.setCursorPos(1, 1)
  1764.             term.setTextColor(colors[theme["text-color"]])
  1765.             term.setBackgroundColor(colors[theme["top-box"]])
  1766.             print("")
  1767.             centerPrint(string.rep(" ", 27))
  1768.             centerPrint(" Server Management - " .. protocol:upper() .. "  ")
  1769.             centerPrint(string.rep(" ", 27))
  1770.             print("")
  1771.  
  1772.             local a = {"New Server"}
  1773.             for _, v in pairs(servers) do table.insert(a, v) end
  1774.             local server = scrollingPrompt(a, 4, 7, 10)
  1775.             if server == "New Server" then
  1776.                 functionList["new server"]()
  1777.                 servers = functionList["reload servers"]()
  1778.             else
  1779.                 term.setCursorPos(30, 8)
  1780.                 write(server)
  1781.                 local a = {{"Start", 30, 9}, {"Edit", 30, 11}, {"Run on Boot", 30, 12},
  1782.                     {"Delete", 30, 13}, {"Back", 30, 15}}
  1783.                 if not functionList["run on boot"] then
  1784.                     a = {{"Start", 30, 9}, {"Edit", 30, 11}, {"Delete", 30, 13}, {"Back", 30, 15}}
  1785.                 end
  1786.                 local opt = prompt(a, "vertical")
  1787.                 if opt == "Start" then
  1788.                     functionList["start"](server)
  1789.                     servers = functionList["reload servers"]()
  1790.                 elseif opt == "Edit" then
  1791.                     functionList["edit"](server)
  1792.                     servers = functionList["reload servers"](server)
  1793.                 elseif opt == "Run on Boot" and functionList["run on boot"] then
  1794.                     functionList["run on boot"](server)
  1795.                     term.setCursorPos(32, 16)
  1796.                     write("Will Run on Boot!")
  1797.                     openAddressBar = false
  1798.                     sleep(1.3)
  1799.                     openAddressBar = true
  1800.                 elseif opt == "Delete" then
  1801.                     functionList["delete"](server)
  1802.                     servers = functionList["reload servers"]()
  1803.                 end
  1804.             end
  1805.         end
  1806.     end
  1807. end
  1808.  
  1809. local function editPages(dir)
  1810.     local oldLoc = shell.dir()
  1811.     local commandHis = {}
  1812.     term.setBackgroundColor(colors.black)
  1813.     term.setTextColor(colors.white)
  1814.     term.clear()
  1815.     term.setCursorPos(1, 1)
  1816.     print("")
  1817.     print(" Server Shell Editing")
  1818.     print(" Type 'exit' to return to Firewolf.")
  1819.     print(" The 'home' file is the index of your site.")
  1820.     print("")
  1821.  
  1822.     local allowed = {"move", "mv", "cp", "copy", "drive", "delete", "rm", "edit",
  1823.         "eject", "exit", "help", "id", "monitor", "rename", "alias", "clear",
  1824.         "paint", "firewolf", "lua", "redstone", "rs", "redprobe", "redpulse", "programs",
  1825.         "redset", "reboot", "hello", "label", "list", "ls", "easter", "pastebin", "dir"}
  1826.  
  1827.     while true do
  1828.         shell.setDir(dir)
  1829.         term.setBackgroundColor(colors.black)
  1830.         if isAdvanced() then term.setTextColor(colors.yellow)
  1831.         else term.setTextColor(colors.white) end
  1832.         write("> ")
  1833.         term.setTextColor(colors.white)
  1834.         local line = read(nil, commandHis)
  1835.         table.insert(commandHis, line)
  1836.  
  1837.         local words = {}
  1838.         for m in string.gmatch(line, "[^ \t]+") do
  1839.             local a = m:gsub("^%s*(.-)%s*$", "%1")
  1840.             table.insert(words, a)
  1841.         end
  1842.  
  1843.         local com = words[1]
  1844.         if com == "exit" then
  1845.             break
  1846.         elseif com then
  1847.             local a = false
  1848.             for _, v in pairs(allowed) do
  1849.                 if com == v then a = true break end
  1850.             end
  1851.  
  1852.             if a then
  1853.                 term.setBackgroundColor(colors.black)
  1854.                 term.setTextColor(colors.white)
  1855.                 shell.run(com, unpack(words, 2))
  1856.             else
  1857.                 term.setTextColor(colors.red)
  1858.                 print("Program Not Allowed!")
  1859.             end
  1860.         end
  1861.     end
  1862.     shell.setDir(oldLoc)
  1863. end
  1864.  
  1865. local function newServer(onCreate)
  1866.     term.setBackgroundColor(colors[theme["background"]])
  1867.     for i = 1, 12 do
  1868.         term.setCursorPos(3, i + 5)
  1869.         term.clearLine()
  1870.     end
  1871.  
  1872.     term.setBackgroundColor(colors[theme["bottom-box"]])
  1873.     term.setCursorPos(1, 7)
  1874.     for i = 1, 8 do centerPrint(string.rep(" ", 47)) end
  1875.     term.setCursorPos(5, 8)
  1876.     write("Name: ")
  1877.     local name = modRead({refusePrint = "`", visibleLength = w - 4, textLength = 200})
  1878.     term.setCursorPos(5, 10)
  1879.     write("URL:")
  1880.     term.setCursorPos(8, 11)
  1881.     write("rdnt://")
  1882.     local url = modRead({grantPrint = "abcdefghijklmnopqrstuvwxyz1234567890-_.+",
  1883.         visibleLength = w - 4, textLength = 200})
  1884.     url = url:gsub(" ", "")
  1885.     if name == "" or url == "" then
  1886.         term.setCursorPos(5, 13)
  1887.         write("URL or Name is Empty!")
  1888.         openAddressBar = false
  1889.         sleep(1.3)
  1890.         openAddressBar = true
  1891.     else
  1892.         local c = onCreate(name, url)
  1893.  
  1894.         term.setCursorPos(5, 13)
  1895.         if c and c == "true" then
  1896.             write("Successfully Created Server!")
  1897.         elseif c == "false" or c == nil then
  1898.             write("Server Creation Failed!")
  1899.         else
  1900.             write(c)
  1901.         end
  1902.         openAddressBar = false
  1903.         sleep(1.3)
  1904.         openAddressBar = true
  1905.     end
  1906. end
  1907.  
  1908. pages["server/rdnt"] = function(site)
  1909.     manageServers(site, "rdnt", {["reload servers"] = function()
  1910.         local servers = {}
  1911.         for _, v in pairs(fs.list(serverFolder)) do
  1912.             if fs.isDir(serverFolder .. "/" .. v) then table.insert(servers, v) end
  1913.         end
  1914.  
  1915.         return servers
  1916.     end, ["new server"] = function()
  1917.         newServer(function(name, url)
  1918.             if fs.exists(serverFolder .. "/" .. url) then
  1919.                 return "Server Already Exists!"
  1920.             end
  1921.  
  1922.             fs.makeDir(serverFolder .. "/" .. url)
  1923.             local f = io.open(serverFolder .. "/" .. url .. "/home", "w")
  1924.             f:write("print(\"\")\ncenterPrint(\"Welcome To " .. name .. "!\")\n\n")
  1925.             f:close()
  1926.             return "true"
  1927.         end)
  1928.     end, ["start"] = function(server)
  1929.         term.clear()
  1930.         term.setCursorPos(1, 1)
  1931.         term.setBackgroundColor(colors.black)
  1932.         term.setTextColor(colors.white)
  1933.         openAddressBar = false
  1934.         setfenv(1, oldEnv)
  1935.         shell.run(serverLocation, server, serverFolder .. "/" .. server)
  1936.         setfenv(1, override)
  1937.         openAddressBar = true
  1938.         checkForModem()
  1939.     end, ["edit"] = function(server)
  1940.         openAddressBar = false
  1941.         editPages(serverFolder .. "/" .. server)
  1942.         openAddressBar = true
  1943.         if not fs.exists(serverFolder .. "/" .. server .. "/home") then
  1944.             local f = io.open(serverFolder .. "/" .. server .. "/home", "w")
  1945.             f:write("print(\"\")\ncenterPrint(\"Welcome To " .. server .. "!\")\n\n")
  1946.             f:close()
  1947.         end
  1948.     end, ["run on boot"] = function(server)
  1949.         fs.delete("/old-startup")
  1950.         if fs.exists("/startup") then fs.move("/startup", "/old-startup") end
  1951.         local f = io.open("/startup", "w")
  1952.         f:write("shell.run(\"" .. serverLocation .. "\", \"" .. server .. "\", \"" ..
  1953.             serverFolder .. "/" .. server .. "\")")
  1954.         f:close()
  1955.     end, ["delete"] = function(server)
  1956.         fs.delete(serverFolder .. "/" .. server)
  1957.     end})
  1958. end
  1959.  
  1960. pages["server/http"] = function(site)
  1961.     term.setBackgroundColor(colors[theme["background"]])
  1962.     term.clear()
  1963.     print("\n\n")
  1964.     term.setBackgroundColor(colors[theme["top-box"]])
  1965.     centerPrint(string.rep(" ", 17))
  1966.     centerPrint("  Comming Soon!  ")
  1967.     centerPrint(string.rep(" ", 17))
  1968. end
  1969.  
  1970. pages["server"] = function(site)
  1971.     setfenv(manageServers, override)
  1972.     setfenv(newServer, override)
  1973.     setfenv(editPages, env)
  1974.     if curProtocol == protocols.rdnt then redirect("server/rdnt")
  1975.     elseif curProtocol == protocols.http then redirect("server/http") end
  1976. end
  1977.  
  1978.  
  1979. --  -------- Help
  1980.  
  1981. pages["help"] = function(site)
  1982.     term.setBackgroundColor(colors[theme["background"]])
  1983.     term.clear()
  1984.     term.setTextColor(colors[theme["text-color"]])
  1985.     term.setBackgroundColor(colors[theme["top-box"]])
  1986.     print("")
  1987.     leftPrint(string.rep(" ", 16))
  1988.     leftPrint(" Firewolf Help  ")
  1989.     leftPrint(string.rep(" ", 16))
  1990.     print("")
  1991.  
  1992.     term.setBackgroundColor(colors[theme["bottom-box"]])
  1993.     for i = 1, 12 do rightPrint(string.rep(" ", 41)) end
  1994.     term.setCursorPos(1, 15)
  1995.     rightPrint("       View the full documentation here: ")
  1996.     rightPrint("  https://github.com/1lann/Firewolf/wiki ")
  1997.  
  1998.     local opt = prompt({{"Getting Started", w - 21, 8}, {"Making a Theme", w - 20, 10},
  1999.         {"API Documentation", w - 23, 12}}, "vertical")
  2000.     local pages = {}
  2001.     if opt == "Getting Started" then
  2002.         pages[1] = {title = "Getting Started - Intoduction", content = {
  2003.             "Hey there!",
  2004.             "",
  2005.             "Firewolf is an app that allows you to create",
  2006.             "and visit websites! Each site has an address",
  2007.             "(the URL) which you can type into the address",
  2008.             "bar above, and then visit the site.",
  2009.             "",
  2010.             "You can open the address bar by clicking on",
  2011.             "it, or by pressing control."
  2012.         }} pages[2] = {title = "Getting Started - Searching", content = {
  2013.             "The address bar can be also be used to",
  2014.             "search for sites, by simply typing in the",
  2015.             "search term.",
  2016.             "",
  2017.             "To view all sites, just open it and hit",
  2018.             "enter (leave the field blank)."
  2019.         }} pages[3] = {title = "Getting Started - Built-In Websites", content = {
  2020.             "Firewolf has a set of built-in websites",
  2021.             "available for use:",
  2022.             "",
  2023.             "rdnt://firewolf   Normal hompage",
  2024.             "rdnt://sites      Built-In Site",
  2025.             "rdnt://server     Create websites",
  2026.             "rdnt://help       Help and documentation"
  2027.         }} pages[4] = {title = "Getting Started - Built-In Websites", content = {
  2028.             "More built-in websites:",
  2029.             "",
  2030.             "rdnt://settings   Firewolf settings",
  2031.             "rdnt://credits    View the credits",
  2032.             "rdnt://exit       Exit the app"
  2033.         }}
  2034.     elseif opt == "Making a Theme" then
  2035.         pages[1] = {title = "Making a Theme - Introduction", content = {
  2036.             "Firewolf themes are files that tell Firewolf",
  2037.             "to color which things what.",
  2038.             "Several themes can already be downloaded for",
  2039.             "Firewolf from rdnt://settings/themes.",
  2040.             "",
  2041.             "You can also make your own theme, use it in",
  2042.             "your copy of Firewolf.Your theme can also be",
  2043.             "submitted it to the themes list!"
  2044.         }} pages[2] = {title = "Making a Theme - Example", content = {
  2045.             "A theme file consists of several lines of",
  2046.             "text. Here is the default theme file:",
  2047.             "address-bar-text=white",
  2048.             "address-bar-background=gray",
  2049.             "address-bar-base=lightGray",
  2050.             "top-box=red",
  2051.             "bottom-box=orange",
  2052.             "background=gray",
  2053.             "text-color=white"
  2054.         }} pages[3] = {title = "Making a Theme - Explanation", content = {
  2055.             "On each line of the example, something is",
  2056.             "given a color, like on the last line, the",
  2057.             "text of the page is told to be white.",
  2058.             "",
  2059.             "The color specified after the = is the same",
  2060.             "as when you call colors.[color name].",
  2061.             "For example, specifying 'red' after the =",
  2062.             "colors that object red."
  2063.         }} pages[4] = {title = "Making a Theme - Have a Go", content = {
  2064.             "Themes can be made at rdnt://settings/themes,",
  2065.             "click on 'Change Theme' button, and click on",
  2066.             "'New Theme'.",
  2067.             "",
  2068.             "Enter a theme name, then exit Firewolf and",
  2069.             "edit the newly created file",
  2070.             "Specify the colors for each of the keys,",
  2071.             "and return to the themes section of the",
  2072.             "downloads center. Click 'Load Theme'."
  2073.         }} pages[5] = {title = "Making a Theme - Submitting", content = {
  2074.             "To submit a theme to the theme list,",
  2075.             "send GravityScore a message on the CCForums",
  2076.             "that contains your theme file and name.",
  2077.             "",
  2078.             "He will message you back saying whether your",
  2079.             "theme has been added, or if anything needs to",
  2080.             "be changed before it is added."
  2081.         }}
  2082.     elseif opt == "API Documentation" then
  2083.         pages[1] = {title = "API Documentation - 1", content = {
  2084.             "The Firewolf API is a bunch of global",
  2085.             "functions that aim to simplify your life when",
  2086.             "designing and coding websites.",
  2087.             "",
  2088.             "For a full documentation on these functions,",
  2089.             "visit the Firewolf Wiki Page here:",
  2090.             "https://github.com/1lann/Firewolf/wiki"
  2091.         }} pages[2] = {title = "API Documentation - 2", content = {
  2092.             "centerPrint(string text)",
  2093.             "cPrint(string text)",
  2094.             "centerWrite(string text)",
  2095.             "cWrite(string text)",
  2096.             "",
  2097.             "leftPrint(string text)",
  2098.             "lPrint(string text)",
  2099.         }} pages[3] = {title = "API Documentation - 3", content = {
  2100.             "leftWrite(string text)",
  2101.             "lWrite(string text)",
  2102.             "",
  2103.             "rightPrint(string text)",
  2104.             "rPrint(string text)",
  2105.             "rightWrite(string text)",
  2106.             "rWrite(string text)"
  2107.         }} pages[4] = {title = "API Documentation - 4", content = {
  2108.             "prompt(table list, string direction)",
  2109.             "scrollingPrompt(table list, integer x,",
  2110.             "   integer y, integer length[,",
  2111.             "   integer width])",
  2112.             "",
  2113.             "urlDownload(string url)",
  2114.             "pastebinDownload(string code)",
  2115.             "redirect(string site)",
  2116.         }} pages[5] = {title = "API Documentation - 5", content = {
  2117.             "loadImageFromServer(string imagePath)",
  2118.             "ioReadFileFromServer(string filePath)",
  2119.             "fileFileFromServer(string filePath)",
  2120.             "saveFileToUserComputer(string content)",
  2121.             "",
  2122.             "writeDataFile(string path, string contents)",
  2123.             "readDataFile(string path)"
  2124.         }}
  2125.     end
  2126.  
  2127.     local function drawPage(page)
  2128.         term.setBackgroundColor(colors[theme["background"]])
  2129.         term.clear()
  2130.         term.setCursorPos(1, 1)
  2131.         term.setTextColor(colors[theme["text-color"]])
  2132.         term.setBackgroundColor(colors[theme["top-box"]])
  2133.         print("")
  2134.         leftPrint(string.rep(" ", page.title:len() + 3))
  2135.         leftPrint(" " .. page.title .. "  ")
  2136.         leftPrint(string.rep(" ", page.title:len() + 3))
  2137.         print("")
  2138.  
  2139.         term.setBackgroundColor(colors[theme["bottom-box"]])
  2140.         for i = 1, 12 do print(string.rep(" ", w)) end
  2141.         for i, v in ipairs(page.content) do
  2142.             term.setCursorPos(4, i + 7)
  2143.             write(v)
  2144.         end
  2145.     end
  2146.  
  2147.     local curPage = 1
  2148.     local a = {{"Prev", 26, 17}, {"Next", 38, 17}, {"Back",  14, 17}}
  2149.     drawPage(pages[curPage])
  2150.  
  2151.     while true do
  2152.         local b = {a[3]}
  2153.         if curPage == 1 then table.insert(b, a[2])
  2154.         elseif curPage == #pages then table.insert(b, a[1])
  2155.         else table.insert(b, a[1]) table.insert(b, a[2]) end
  2156.  
  2157.         local opt = prompt(b, "horizontal")
  2158.         if opt == "Prev" then
  2159.             curPage = curPage - 1
  2160.         elseif opt == "Next" then
  2161.             curPage = curPage + 1
  2162.         elseif opt == "Back" then
  2163.             break
  2164.         end
  2165.  
  2166.         drawPage(pages[curPage])
  2167.     end
  2168.  
  2169.     redirect("help")
  2170. end
  2171.  
  2172.  
  2173. --  -------- Settings
  2174.  
  2175. pages["settings/themes"] = function(site)
  2176.     term.setBackgroundColor(colors[theme["background"]])
  2177.     term.clear()
  2178.     term.setTextColor(colors[theme["text-color"]])
  2179.     term.setBackgroundColor(colors[theme["top-box"]])
  2180.     print("")
  2181.     leftPrint(string.rep(" ", 17))
  2182.     leftPrint(" Theme Settings  ")
  2183.     leftPrint(string.rep(" ", 17))
  2184.     print("")
  2185.  
  2186.     if isAdvanced() then
  2187.         term.setBackgroundColor(colors[theme["bottom-box"]])
  2188.         for i = 1, 12 do rightPrint(string.rep(" ", 36)) end
  2189.  
  2190.         local themes = {}
  2191.         local themenames = {"Back", "New Theme", "Load Theme"}
  2192.         local f = io.open(rootFolder .. "/temp_file", "w")
  2193.         f:write(files.availableThemes)
  2194.         f:close()
  2195.         local f = io.open(rootFolder .. "/temp_file", "r")
  2196.         local l = f:read("*l")
  2197.         while l do
  2198.             l = l:gsub("^%s*(.-)%s*$", "%1")
  2199.             local a, b = l:find("| |")
  2200.             table.insert(themenames, l:sub(b + 1, -1))
  2201.             table.insert(themes, {name = l:sub(b + 1, -1), url = l:sub(1, a - 1)})
  2202.             l = f:read("*l")
  2203.         end
  2204.         f:close()
  2205.         fs.delete(rootFolder .. "/temp_file")
  2206.  
  2207.         local t = scrollingPrompt(themenames, w - 33, 7, 10, 32)
  2208.         if t == "Back" then
  2209.             redirect("settings")
  2210.         elseif t == "New Theme" then
  2211.             term.setCursorPos(w - 33, 17)
  2212.             write("Path: /")
  2213.             local n = modRead({visibleLength = w - 2, textLength = 100})
  2214.             if n ~= "" and n ~= nil then
  2215.                 n = "/" .. n
  2216.                 local f = io.open(n, "w")
  2217.                 f:write(files.newTheme)
  2218.                 f:close()
  2219.  
  2220.                 term.setCursorPos(1, 17)
  2221.                 rightWrite(string.rep(" ", 36))
  2222.                 term.setCursorPos(1, 17)
  2223.                 rightWrite("File Created! ")
  2224.                 openAddressBar = false
  2225.                 sleep(1.1)
  2226.                 openAddressBar = true
  2227.             end
  2228.         elseif t == "Load Theme" then
  2229.             term.setCursorPos(w - 33, 17)
  2230.             write("Path: /")
  2231.             local n = modRead({visibleLength = w - 2, textLength = 100})
  2232.             if n ~= "" and n ~= nil then
  2233.                 n = "/" .. n
  2234.                 term.setCursorPos(1, 17)
  2235.                 rightWrite(string.rep(" ", 36))
  2236.  
  2237.                 term.setCursorPos(1, 17)
  2238.                 if fs.exists(n) and not fs.isDir(n) then
  2239.                     local a = loadTheme(n)
  2240.                     if a ~= nil then
  2241.                         fs.delete(themeLocation)
  2242.                         fs.copy(n, themeLocation)
  2243.                         theme = a
  2244.                         rightWrite("Theme File Loaded! :D ")
  2245.                     else
  2246.                         rightWrite("Theme File is Corrupt! D: ")
  2247.                     end
  2248.                 elseif not fs.exists(n) then
  2249.                     rightWrite("File does not exist! ")
  2250.                 elseif fs.isDir(n) then
  2251.                     rightWrite("File is a directory! ")
  2252.                 end
  2253.  
  2254.                 openAddressBar = false
  2255.                 sleep(1.1)
  2256.                 openAddressBar = true
  2257.             end
  2258.         else
  2259.             local url = ""
  2260.             for _, v in pairs(themes) do if v.name == t then url = v.url break end end
  2261.             term.setBackgroundColor(colors[theme["top-box"]])
  2262.             term.setCursorPos(1, 3)
  2263.             leftWrite(string.rep(" ", 17))
  2264.             leftWrite(" Downloading...  ")
  2265.  
  2266.             fs.delete(rootFolder .. "/temp_file")
  2267.             download(url, rootFolder .. "/temp_file")
  2268.             local th = loadTheme(rootFolder .. "/temp_file")
  2269.             if th == nil then
  2270.                 term.setCursorPos(1, 3)
  2271.                 leftWrite(string.rep(" ", 17))
  2272.                 leftWrite(" Theme Corrupt!  ")
  2273.                 openAddressBar = false
  2274.                 sleep(1.3)
  2275.                 openAddressBar = true
  2276.  
  2277.                 fs.delete(rootFolder .. "/temp_file")
  2278.             else
  2279.                 term.setCursorPos(1, 3)
  2280.                 leftWrite(string.rep(" ", 17))
  2281.                 leftWrite(" Theme Loaded!   ")
  2282.                 openAddressBar = false
  2283.                 sleep(1.3)
  2284.                 openAddressBar = true
  2285.  
  2286.                 fs.delete(themeLocation)
  2287.                 fs.move(rootFolder .. "/temp_file", themeLocation)
  2288.                 theme = th
  2289.                 redirect("home")
  2290.             end
  2291.         end
  2292.     else
  2293.         print("")
  2294.         rightPrint(string.rep(" ", 30))
  2295.         rightPrint("  Themes are not available on ")
  2296.         rightPrint("         normal computers! :( ")
  2297.         rightPrint(string.rep(" ", 30))
  2298.     end
  2299. end
  2300.  
  2301. pages["downloads"] = function(site) redirect("settings/themes") end
  2302.  
  2303. pages["settings"] = function(site)
  2304.     term.setBackgroundColor(colors[theme["background"]])
  2305.     term.clear()
  2306.     term.setTextColor(colors[theme["text-color"]])
  2307.     term.setBackgroundColor(colors[theme["top-box"]])
  2308.     print("")
  2309.     leftPrint(string.rep(" ", 17 + serverList[serverID]:len()))
  2310.     leftPrint(" Firewolf Settings  " .. string.rep(" ", serverList[serverID]:len() - 3))
  2311.     leftPrint(" Designed For: " .. serverList[serverID] .. "  ")
  2312.     leftPrint(string.rep(" ", 17 + serverList[serverID]:len()))
  2313.     print("\n")
  2314.  
  2315.     local a = "Automatic Updating - On"
  2316.     if autoupdate == "false" then a = "Automatic Updating - Off" end
  2317.     local b = "Home - rdnt://" .. homepage
  2318.     if b:len() >= 28 then b = b:sub(1, 24) .. "..." end
  2319.  
  2320.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2321.     for i = 1, 9 do rightPrint(string.rep(" ", 36)) end
  2322.     local c = {{a, w - a:len() - 6, 9}, {"Change Theme", w - 18, 11}, {b, w - b:len() - 6, 13},
  2323.         {"Reset Firewolf", w - 20, 15}}
  2324.     if not isAdvanced() then
  2325.         c = {{a, w - a:len(), 9}, {b, w - b:len(), 11}, {"Reset Firewolf", w - 14, 13}}
  2326.     end
  2327.  
  2328.     local opt = prompt(c, "vertical")
  2329.     if opt == a then
  2330.         if autoupdate == "true" then autoupdate = "false"
  2331.         elseif autoupdate == "false" then autoupdate = "true" end
  2332.     elseif opt == "Change Theme" and isAdvanced() then
  2333.         redirect("settings/themes")
  2334.     elseif opt == b then
  2335.         if isAdvanced() then term.setCursorPos(w - 30, 14)
  2336.         else term.setCursorPos(w - 30, 12) end
  2337.         write("rdnt://")
  2338.         local a = read()
  2339.         if a ~= "" then homepage = a end
  2340.     elseif opt == "Reset Firewolf" then
  2341.         term.setBackgroundColor(colors[theme["background"]])
  2342.         term.clear()
  2343.         term.setCursorPos(1, 1)
  2344.         term.setTextColor(colors[theme["text-color"]])
  2345.         term.setBackgroundColor(colors[theme["top-box"]])
  2346.         print("")
  2347.         leftPrint(string.rep(" ", 17))
  2348.         leftPrint(" Reset Firewolf  ")
  2349.         leftPrint(string.rep(" ", 17))
  2350.         print("\n")
  2351.         term.setBackgroundColor(colors[theme["bottom-box"]])
  2352.         for i = 1, 11 do rightPrint(string.rep(" ", 26)) end
  2353.         local opt = prompt({{"Reset History", w - 19, 8}, {"Reset Servers", w - 19, 9},
  2354.             {"Reset Theme", w - 17, 10}, {"Reset Cache", w - 17, 11}, {"Reset Databases", w - 21, 12},
  2355.             {"Reset Settings", w - 20, 13}, {"Back", w - 10, 14}, {"Reset All", w - 15, 16}},
  2356.             "vertical")
  2357.  
  2358.         openAddressBar = false
  2359.         if opt == "Reset All" then
  2360.             fs.delete(rootFolder)
  2361.         elseif opt == "Reset History" then
  2362.             fs.delete(historyLocation)
  2363.         elseif opt == "Reset Servers" then
  2364.             fs.delete(serverFolder)
  2365.             fs.delete(serverLocation)
  2366.         elseif opt == "Reset Cache" then
  2367.             fs.delete(cacheFolder)
  2368.         elseif opt == "Reset Databases" then
  2369.             fs.delete(userWhitelist)
  2370.             fs.delete(userBlacklist)
  2371.         elseif opt == "Reset Settings" then
  2372.             fs.delete(settingsLocation)
  2373.         elseif opt == "Reset Theme" then
  2374.             fs.delete(themeLocation)
  2375.         elseif opt == "Back" then
  2376.             openAddressBar = true
  2377.             redirect("settings")
  2378.         end
  2379.  
  2380.         term.setBackgroundColor(colors[theme["background"]])
  2381.         term.clear()
  2382.         term.setCursorPos(1, 1)
  2383.         term.setBackgroundColor(colors[theme["top-box"]])
  2384.         print("\n\n")
  2385.         leftPrint(string.rep(" ", 17))
  2386.         leftPrint(" Reset Firewolf  ")
  2387.         leftPrint(string.rep(" ", 17))
  2388.         print("")
  2389.  
  2390.         term.setCursorPos(1, 10)
  2391.         term.setBackgroundColor(colors[theme["bottom-box"]])
  2392.         rightPrint(string.rep(" ", 27))
  2393.         rightPrint("  Firewolf has been reset! ")
  2394.         rightWrite(string.rep(" ", 27))
  2395.         if isAdvanced() then rightPrint("          Click to exit... ")
  2396.         else rightPrint("  Press any key to exit... ") end
  2397.         rightPrint(string.rep(" ", 27))
  2398.  
  2399.         while true do
  2400.             local e = os.pullEvent()
  2401.             if e == "mouse_click" or e == "key" then return true end
  2402.         end
  2403.     end
  2404.  
  2405.     -- Save
  2406.     local f = io.open(settingsLocation, "w")
  2407.     f:write(textutils.serialize({auto = autoupdate, incog = incognito, home = homepage}))
  2408.     f:close()
  2409.  
  2410.     redirect("settings")
  2411. end
  2412.  
  2413.  
  2414. --  -------- Credits
  2415.  
  2416. pages["credits"] = function(site)
  2417.     term.setBackgroundColor(colors[theme["background"]])
  2418.     term.clear()
  2419.     print("\n")
  2420.     term.setTextColor(colors[theme["text-color"]])
  2421.     term.setBackgroundColor(colors[theme["top-box"]])
  2422.     leftPrint(string.rep(" ", 19))
  2423.     leftPrint(" Firewolf Credits  ")
  2424.     leftPrint(string.rep(" ", 19))
  2425.     print("\n")
  2426.  
  2427.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2428.     rightPrint(string.rep(" ", 38))
  2429.     rightPrint("  Coded by:              GravityScore ")
  2430.     rightPrint("                            and 1lann ")
  2431.     rightPrint(string.rep(" ", 38))
  2432.     rightPrint("  Based off:     RednetExplorer 2.4.1 ")
  2433.     rightPrint("           Made by ComputerCraftFan11 ")
  2434.     rightPrint(string.rep(" ", 38))
  2435. end
  2436.  
  2437.  
  2438. --  -------- Error Pages
  2439.  
  2440. errorPages["overspeed"] = function(site)
  2441.     clearPage("overspeed", colors[theme["background"]])
  2442.     print("")
  2443.     term.setTextColor(colors[theme["text-color"]])
  2444.     term.setBackgroundColor(colors[theme["top-box"]])
  2445.     leftPrint(string.rep(" ", 14))
  2446.     leftPrint(" Warning! D:  ")
  2447.     leftPrint(string.rep(" ", 14))
  2448.     print("")
  2449.  
  2450.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2451.     rightPrint(string.rep(" ", 40))
  2452.     rightPrint("  Website browsing sleep limit reached! ")
  2453.     rightPrint(string.rep(" ", 40))
  2454.     rightPrint("      To prevent Firewolf from spamming ")
  2455.     rightPrint("   rednet, Firewolf has stopped loading ")
  2456.     rightPrint("                              the page. ")
  2457.     for i = 1, 3 do rightPrint(string.rep(" ", 40)) end
  2458.  
  2459.     openAddressBar = false
  2460.     for i = 1, 5 do
  2461.         term.setCursorPos(1, 14)
  2462.         rightWrite(string.rep(" ", 43))
  2463.         if 6 - i == 1 then rightWrite("                Please wait 1 second... ")
  2464.         else rightWrite("                Please wait " .. tostring(6 - i) .. " seconds... ") end
  2465.         sleep(1)
  2466.     end
  2467.     openAddressBar = true
  2468.  
  2469.     term.setCursorPos(1, 14)
  2470.     rightWrite(string.rep(" ", 43))
  2471.     rightWrite("            You may now browse normally ")
  2472. end
  2473.  
  2474. errorPages["crash"] = function(error)
  2475.     clearPage("crash", colors[theme["background"]])
  2476.     print("")
  2477.     term.setTextColor(colors[theme["text-color"]])
  2478.     term.setBackgroundColor(colors[theme["top-box"]])
  2479.     leftPrint(string.rep(" ", 30))
  2480.     leftPrint(" The Website Has Crashed! D:  ")
  2481.     leftPrint(string.rep(" ", 30))
  2482.     print("")
  2483.  
  2484.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2485.     rightPrint(string.rep(" ", 31))
  2486.     rightPrint("      The website has crashed! ")
  2487.     rightPrint("  Report this to the operator: ")
  2488.     rightPrint(string.rep(" ", 31))
  2489.     term.setBackgroundColor(colors[theme["background"]])
  2490.     print("")
  2491.     print(" " .. tostring(error))
  2492.     print("")
  2493.  
  2494.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2495.     rightPrint(string.rep(" ", 31))
  2496.     rightPrint("   You may now browse normally ")
  2497.     rightPrint(string.rep(" ", 31))
  2498. end
  2499.  
  2500.  
  2501. --  -------- External Page
  2502.  
  2503. local function external(site)
  2504.     -- Clear
  2505.     term.setTextColor(colors[theme["text-color"]])
  2506.     term.setBackgroundColor(colors[theme["background"]])
  2507.     term.clear()
  2508.     term.setCursorPos(1, 1)
  2509.     print("\n\n\n")
  2510.     centerWrite("Connecting to Website...")
  2511.     loadingRate = loadingRate + 1
  2512.  
  2513.     -- Modem
  2514.     if curProtocol == protocols.rdnt then
  2515.         setfenv(checkForModem, override)
  2516.         checkForModem(function()
  2517.             term.setBackgroundColor(colors[theme["background"]])
  2518.             term.clear()
  2519.             term.setCursorPos(1, 1)
  2520.             print("\n")
  2521.             term.setTextColor(colors[theme["text-color"]])
  2522.             term.setBackgroundColor(colors[theme["top-box"]])
  2523.             leftPrint(string.rep(" ", 24))
  2524.             leftPrint(" No Modem Attached! D:  ")
  2525.             leftPrint(string.rep(" ", 24))
  2526.             print("\n")
  2527.  
  2528.             term.setBackgroundColor(colors[theme["bottom-box"]])
  2529.             rightPrint(string.rep(" ", 40))
  2530.             rightPrint("    No wireless modem was found on this ")
  2531.             rightPrint("  computer, and Firewolf cannot use the ")
  2532.             rightPrint("             RDNT protocol without one! ")
  2533.             rightPrint(string.rep(" ", 40))
  2534.             rightPrint("  Waiting for a modem to be attached... ")
  2535.             rightPrint(string.rep(" ", 40))
  2536.         end)
  2537.     end
  2538.  
  2539.     -- Get website
  2540.     local webFunc = curProtocol.getWebsite
  2541.     setfenv(webFunc, override)
  2542.     local id, content, status = nil, nil, nil
  2543.     pcall(function() id, content, status = webFunc(site) end)
  2544.  
  2545.     local cacheLoc = cacheFolder .. "/" .. site:gsub("/", "$slazh$")
  2546.     if id and status then
  2547.         -- Clear
  2548.         term.setBackgroundColor(colors.black)
  2549.         term.setTextColor(colors.white)
  2550.         term.clear()
  2551.         term.setCursorPos(1, 1)
  2552.  
  2553.         -- Save
  2554.         local f = io.open(cacheLoc, "w")
  2555.         f:write(content)
  2556.         f:close()
  2557.  
  2558.         local fn, err = loadfile(cacheLoc)
  2559.         if not err then
  2560.             setfenv(fn, antivirus)
  2561.             if status == "whitelist" then setfenv(fn, override) end
  2562.             _, err = pcall(function() fn() end)
  2563.             setfenv(1, override)
  2564.         end
  2565.  
  2566.         if err then
  2567.             local errFunc = errorPages["crash"]
  2568.             setfenv(errFunc, override)
  2569.             pcall(function() errFunc(err) end)
  2570.         end
  2571.     else
  2572.         if fs.exists(cacheLoc) and not fs.isDir(cacheLoc) then
  2573.             term.clearLine()
  2574.             centerPrint("Could Not Connect to Website!")
  2575.             print("")
  2576.             centerPrint("A Cached Version was Found.")
  2577.             local opt = prompt({{"Load Cache", -1, 10}, {"Continue to Search Results", -1, 12}},
  2578.                 "vertical")
  2579.             if opt == "Load Cache" then
  2580.                 -- Clear
  2581.                 term.setBackgroundColor(colors.black)
  2582.                 term.setTextColor(colors.white)
  2583.                 term.clear()
  2584.                 term.setCursorPos(1, 1)
  2585.  
  2586.                 -- Run
  2587.                 local fn, err = loadfile(cacheLoc)
  2588.                 if not err then
  2589.                     setfenv(fn, antivirus)
  2590.                     _, err = pcall(function() fn() end)
  2591.                     setfenv(1, override)
  2592.                 end
  2593.  
  2594.                 return
  2595.             end
  2596.         end
  2597.  
  2598.         openAddressBar = true
  2599.         local res = {}
  2600.         if site ~= "" then
  2601.             for _, v in pairs(dnsDatabase[1]) do
  2602.                 if v:find(site:lower(), 1, true) then
  2603.                     table.insert(res, v)
  2604.                 end
  2605.             end
  2606.         else
  2607.             for _, v in pairs(dnsDatabase[1]) do
  2608.                 table.insert(res, v)
  2609.             end
  2610.         end
  2611.  
  2612.         table.sort(res)
  2613.         table.sort(res, function(a, b)
  2614.             local _, ac = a:gsub("rdnt://", ""):gsub("http://", ""):gsub(site:lower(), "")
  2615.             local _, bc = b:gsub("rdnt://", ""):gsub("http://", ""):gsub(site:lower(), "")
  2616.             return ac > bc
  2617.         end)
  2618.  
  2619.         term.setBackgroundColor(colors[theme["background"]])
  2620.         term.clear()
  2621.         term.setCursorPos(1, 1)
  2622.         if #res > 0 then
  2623.             print("")
  2624.             term.setTextColor(colors[theme["text-color"]])
  2625.             term.setBackgroundColor(colors[theme["top-box"]])
  2626.             local t = "1 Search Result"
  2627.             if #res > 1 then t = #res .. " Search Results" end
  2628.             leftPrint(string.rep(" ", t:len() + 3))
  2629.             leftPrint(" " .. t .. "  ")
  2630.             leftPrint(string.rep(" ", t:len() + 3))
  2631.             print("")
  2632.  
  2633.             term.setBackgroundColor(colors[theme["bottom-box"]])
  2634.             for i = 1, 12 do rightPrint(string.rep(" ", 42)) end
  2635.             local opt = scrollingPrompt(res, w - 39, 7, 10, 38)
  2636.             if opt then redirect(opt:gsub("rdnt://", ""):gsub("http://", "")) end
  2637.         elseif site == "" and #res < 1 then
  2638.             print("\n\n")
  2639.             term.setTextColor(colors[theme["text-color"]])
  2640.             term.setBackgroundColor(colors[theme["top-box"]])
  2641.             centerPrint(string.rep(" ", 47))
  2642.             centerWrite(string.rep(" ", 47))
  2643.             centerPrint("No Websites are Currently Online! D:")
  2644.             centerWrite(string.rep(" ", 47))
  2645.             centerPrint(string.rep(" ", 47))
  2646.             centerWrite(string.rep(" ", 47))
  2647.             centerPrint("Why not make one yourself?")
  2648.             centerWrite(string.rep(" ", 47))
  2649.             centerPrint("Visit rdnt://server!")
  2650.             centerPrint(string.rep(" ", 47))
  2651.         else
  2652.             print("")
  2653.             term.setTextColor(colors[theme["text-color"]])
  2654.             term.setBackgroundColor(colors[theme["top-box"]])
  2655.             leftPrint(string.rep(" ", 11))
  2656.             leftPrint(" Oh Noes!  ")
  2657.             leftPrint(string.rep(" ", 11))
  2658.             print("\n")
  2659.  
  2660.             term.setBackgroundColor(colors[theme["bottom-box"]])
  2661.             rightPrint(string.rep(" ", 43))
  2662.             rightPrint([[       ______                          __  ]])
  2663.             rightPrint([[      / ____/_____ _____ ____   _____ / /  ]])
  2664.             rightPrint([[     / __/  / ___// ___// __ \ / ___// /   ]])
  2665.             rightPrint([[    / /___ / /   / /   / /_/ // /   /_/    ]])
  2666.             rightPrint([[   /_____//_/   /_/    \____//_/   (_)     ]])
  2667.             rightPrint(string.rep(" ", 43))
  2668.             if verifyBlacklist(id) then
  2669.                 rightPrint("  Could not connect to the website! It has ")
  2670.                 rightPrint("  been blocked by a database admin!        ")
  2671.             else
  2672.                 rightPrint("  Could not connect to the website! It may ")
  2673.                 rightPrint("  be down, or not exist!                   ")
  2674.             end
  2675.             rightPrint(string.rep(" ", 43))
  2676.         end
  2677.     end
  2678. end
  2679.  
  2680.  
  2681. --  -------- Website Coroutine
  2682.  
  2683. local function websitecoroutine()
  2684.     local loadingClock = os.clock()
  2685.     while true do
  2686.         -- Reset and clear
  2687.         setfenv(1, backupEnv)
  2688.         os.pullEvent = pullevent
  2689.         browserAgent = browserAgentTemplate
  2690.         w, h = term.getSize()
  2691.         curbackground = colors.black
  2692.         curtext = colors.white
  2693.  
  2694.         clearPage(website)
  2695.         term.setBackgroundColor(colors.black)
  2696.         term.setTextColor(colors.white)
  2697.  
  2698.         -- Add to history
  2699.         if website ~= "exit" and website ~= addressBarHistory[#addressBarHistory] then
  2700.             table.insert(addressBarHistory, website)
  2701.         end
  2702.  
  2703.         -- Overspeed
  2704.         checkForModem()
  2705.         if os.clock() - loadingClock > 5 then
  2706.             -- Reset loading rate
  2707.             loadingRate = 0
  2708.             loadingClock = os.clock()
  2709.         end
  2710.  
  2711.         -- Run site
  2712.         if loadingRate >= 8 then
  2713.             -- Overspeed error
  2714.             local overspeedFunc = errorPages["overspeed"]
  2715.             setfenv(overspeedFunc, override)
  2716.             overspeedFunc()
  2717.  
  2718.             loadingRate = 0
  2719.             loadingClock = os.clock()
  2720.         elseif type(pages[website]) == "function" then
  2721.             -- Run site function
  2722.             local siteFunc = pages[website]
  2723.             setfenv(siteFunc, override)
  2724.             local exit = false
  2725.             local _, err = pcall(function() exit = siteFunc() end)
  2726.  
  2727.             if err then
  2728.                 local errFunc = errorPages["crash"]
  2729.                 setfenv(errFunc, override)
  2730.                 errFunc(err)
  2731.             end
  2732.  
  2733.             if exit then
  2734.                 os.queueEvent("terminate")
  2735.                 return
  2736.             end
  2737.         else
  2738.             setfenv(external, override)
  2739.             local _, err = pcall(function() external(website) end)
  2740.  
  2741.             if err then
  2742.                 local errFunc = errorPages["crash"]
  2743.                 setfenv(errFunc, override)
  2744.                 errFunc(err)
  2745.             end
  2746.         end
  2747.  
  2748.         -- Clear data folder
  2749.         fs.delete(websiteDataFolder)
  2750.         fs.makeDir(websiteDataFolder)
  2751.  
  2752.         -- Wait for load
  2753.         oldpullevent(event_loadWebsite)
  2754.     end
  2755. end
  2756.  
  2757.  
  2758. --  -------- Address Bar Coroutine
  2759.  
  2760. local function searchresults()
  2761.     local mod = true
  2762.     if curProtocol == protocols.rdnt then
  2763.         mod = false
  2764.         for _, v in pairs(rs.getSides()) do if rednet.isOpen(v) then mod = true end end
  2765.     end
  2766.     if mod then curProtocol.getSearchResults() end
  2767.  
  2768.     local lastCheck = os.clock()
  2769.     while true do
  2770.         local e = oldpullevent()
  2771.         if website ~= "exit" and e == event_loadWebsite then
  2772.             mod = true
  2773.             if curProtocol == protocols.rdnt then
  2774.                 mod = false
  2775.                 for _, v in pairs(rs.getSides()) do if rednet.isOpen(v) then mod = true end end
  2776.             end
  2777.             if mod and os.clock() - lastCheck > 5 then
  2778.                 curProtocol.getSearchResults()
  2779.                 lastCheck = os.clock()
  2780.             end
  2781.         end
  2782.     end
  2783. end
  2784.  
  2785. local function addressbarread()
  2786.     local len = 4
  2787.     local list = {}
  2788.  
  2789.     local function draw(l)
  2790.         local ox, oy = term.getCursorPos()
  2791.         for i = 1, len do
  2792.             term.setTextColor(colors[theme["address-bar-text"]])
  2793.             term.setBackgroundColor(colors[theme["address-bar-background"]])
  2794.             term.setCursorPos(1, i + 1)
  2795.             write(string.rep(" ", w))
  2796.         end
  2797.         if theme["address-bar-base"] then term.setBackgroundColor(colors[theme["address-bar-base"]])
  2798.         else term.setBackgroundColor(colors[theme["bottom-box"]]) end
  2799.         term.setCursorPos(1, len + 2)
  2800.         write(string.rep(" ", w))
  2801.         term.setBackgroundColor(colors[theme["address-bar-background"]])
  2802.  
  2803.         for i, v in ipairs(l) do
  2804.             term.setCursorPos(2, i + 1)
  2805.             write(v)
  2806.         end
  2807.         term.setCursorPos(ox, oy)
  2808.     end
  2809.  
  2810.     local function update(line, event, ...)
  2811.         local params = {...}
  2812.         local y = params[3]
  2813.         if event == "char" or event == "history" or event == "delete" then
  2814.             list = {}
  2815.             for _, v in pairs(dnsDatabase[1]) do
  2816.                 if #list < len and
  2817.                         v:gsub("rdnt://", ""):gsub("http://", ""):find(line:lower(), 1, true) then
  2818.                     table.insert(list, v)
  2819.                 end
  2820.             end
  2821.  
  2822.             table.sort(list)
  2823.             table.sort(list, function(a, b)
  2824.                 local _, ac = a:gsub("rdnt://", ""):gsub("http://", ""):gsub(line:lower(), "")
  2825.                 local _, bc = b:gsub("rdnt://", ""):gsub("http://", ""):gsub(line:lower(), "")
  2826.                 return ac > bc
  2827.             end)
  2828.             draw(list)
  2829.             return false
  2830.         elseif event == "mouse_click" then
  2831.             for i = 1, #list do
  2832.                 if y == i + 1 then
  2833.                     return true, list[i]:gsub("rdnt://", ""):gsub("http://", "")
  2834.                 end
  2835.             end
  2836.         end
  2837.     end
  2838.  
  2839.     local mod = true
  2840.     if curProtocol == protocols.rdnt then
  2841.         mod = false
  2842.         for _, v in pairs(rs.getSides()) do if rednet.isOpen(v) then mod = true end end
  2843.     end
  2844.     if isAdvanced() and mod then
  2845.         return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300,
  2846.             liveUpdates = update, exitOnKey = "control"})
  2847.     else
  2848.         return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300,
  2849.             exitOnKey = "control"})
  2850.     end
  2851. end
  2852.  
  2853. local function addressbarcoroutine()
  2854.     while true do
  2855.         local e, but, x, y = oldpullevent()
  2856.         if (e == "key" and (but == 29 or but == 157)) or
  2857.                 (e == "mouse_click" and y == 1 and clickableAddressBar) then
  2858.             clickableAddressBar = true
  2859.             if openAddressBar then
  2860.                 if e == "key" then x = -1 end
  2861.                 if x == w then
  2862.                     -- Open menu bar
  2863.                     menuBarOpen = true
  2864.                     term.setBackgroundColor(colors[theme["top-box"]])
  2865.                     term.setTextColor(colors[theme["text-color"]])
  2866.                     term.setCursorPos(1, 1)
  2867.                     write("> [- Exit Firewolf -]                              ")
  2868.                 elseif menuBarOpen and (x == 1 or (but == 29 or but == 157)) then
  2869.                     -- Close menu bar
  2870.                     menuBarOpen = false
  2871.                     clearPage(website, nil, true)
  2872.                 elseif x > 2 and x < 22 and menuBarOpen then
  2873.                     -- Exit
  2874.                     menuBarOpen = false
  2875.                     os.queueEvent(event_exitWebsite)
  2876.                     os.queueEvent("terminate")
  2877.                     return
  2878.                 elseif not menuBarOpen then
  2879.                     -- Exit website
  2880.                     os.queueEvent(event_exitWebsite)
  2881.  
  2882.                     -- Clear
  2883.                     term.setBackgroundColor(colors[theme["address-bar-background"]])
  2884.                     term.setTextColor(colors[theme["address-bar-text"]])
  2885.                     term.setCursorPos(2, 1)
  2886.                     term.clearLine()
  2887.                     if curProtocol == protocols.rdnt then write("rdnt://")
  2888.                     elseif curProtocol == protocols.http then write("http://") end
  2889.  
  2890.                     -- Read
  2891.                     local oldWebsite = website
  2892.                     os.pullEvent = oldpullevent
  2893.                     website = addressbarread()
  2894.                     os.pullEvent = pullevent
  2895.                     if website == nil then
  2896.                         website = oldWebsite
  2897.                     elseif website == "home" or website == "homepage" then
  2898.                         website = homepage
  2899.                     elseif website == "exit" then
  2900.                         os.queueEvent("terminate")
  2901.                         return
  2902.                     end
  2903.  
  2904.                     -- Load
  2905.                     os.queueEvent(event_loadWebsite)
  2906.                 end
  2907.             end
  2908.         elseif e == event_redirect then
  2909.             -- Exit website
  2910.             os.queueEvent(event_exitWebsite)
  2911.  
  2912.             -- Set website
  2913.             local oldWebsite = website
  2914.             website = but
  2915.             if website == nil or website == "exit" then
  2916.                 website = oldWebsite
  2917.             elseif website == "home" or website == "homepage" then
  2918.                 website = homepage
  2919.             end
  2920.  
  2921.             -- Load
  2922.             os.queueEvent(event_loadWebsite)
  2923.         end
  2924.     end
  2925. end
  2926.  
  2927.  
  2928. --  -------- Main
  2929.  
  2930. local function main()
  2931.     -- Logo
  2932.     term.setBackgroundColor(colors[theme["background"]])
  2933.     term.setTextColor(colors[theme["text-color"]])
  2934.     term.clear()
  2935.     term.setCursorPos(1, 2)
  2936.     term.setBackgroundColor(colors[theme["top-box"]])
  2937.     leftPrint(string.rep(" ", 47))
  2938.     leftPrint([[          ______ ____ ____   ______            ]])
  2939.     leftPrint([[ ------- / ____//  _// __ \ / ____/            ]])
  2940.     leftPrint([[ ------ / /_    / / / /_/ // __/               ]])
  2941.     leftPrint([[ ----- / __/  _/ / / _  _// /___               ]])
  2942.     leftPrint([[ ---- / /    /___//_/ |_|/_____/               ]])
  2943.     leftPrint([[ --- / /       _       __ ____   __     ______ ]])
  2944.     leftPrint([[ -- /_/       | |     / // __ \ / /    / ____/ ]])
  2945.     leftPrint([[              | | /| / // / / // /    / /_     ]])
  2946.     leftPrint([[              | |/ |/ // /_/ // /___ / __/     ]])
  2947.     leftPrint([[              |__/|__/ \____//_____//_/        ]])
  2948.     leftPrint(string.rep(" ", 47))
  2949.     print("\n")
  2950.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2951.  
  2952.     -- Load Settings
  2953.     if fs.exists(settingsLocation) and not fs.isDir(settingsLocation) then
  2954.         local f = io.open(settingsLocation, "r")
  2955.         local a = textutils.unserialize(f:read("*l"))
  2956.         if type(a) == "table" then
  2957.             autoupdate = a.auto
  2958.             incognito = a.incog
  2959.             homepage = a.home
  2960.         end
  2961.         f:close()
  2962.     else
  2963.         autoupdate = "true"
  2964.         incognito = "false"
  2965.         homepage = "firewolf"
  2966.     end
  2967.     curProtocol = protocols.rdnt
  2968.  
  2969.     -- Update
  2970.     rightPrint(string.rep(" ", 32))
  2971.     rightPrint("        Checking for Updates... ")
  2972.     rightPrint(string.rep(" ", 32))
  2973.     setfenv(updateClient, env)
  2974.     if not noInternet then
  2975.         if updateClient() then
  2976.             if debugFile then debugFile:close() end
  2977.  
  2978.             -- Reset Environment
  2979.             setfenv(1, oldEnv)
  2980.             os.pullEvent = oldpullevent
  2981.             shell.run(firewolfLocation)
  2982.             error()
  2983.         end
  2984.     end
  2985.  
  2986.     -- Download Files
  2987.     local x, y = term.getCursorPos()
  2988.     term.setCursorPos(1, y - 2)
  2989.     rightWrite(string.rep(" ", 32))
  2990.     rightWrite("  Downloading Required Files... ")
  2991.  
  2992.     if not noInternet then resetFilesystem() end
  2993.     loadDatabases()
  2994.  
  2995.     -- Modem
  2996.     checkForModem()
  2997.     website = homepage
  2998.  
  2999.     -- Run
  3000.     parallel.waitForAll(websitecoroutine, addressbarcoroutine, searchresults)
  3001. end
  3002.  
  3003. local function startup()
  3004.     -- HTTP
  3005.     if not http and not noInternet then
  3006.         term.setTextColor(colors[theme["text-color"]])
  3007.         term.setBackgroundColor(colors[theme["background"]])
  3008.         term.clear()
  3009.         term.setCursorPos(1, 2)
  3010.         term.setBackgroundColor(colors[theme["top-box"]])
  3011.         api.leftPrint(string.rep(" ", 24))
  3012.         api.leftPrint(" HTTP API Not Enabled!  ")
  3013.         api.leftPrint(string.rep(" ", 24))
  3014.         print("")
  3015.  
  3016.         term.setBackgroundColor(colors[theme["bottom-box"]])
  3017.         api.rightPrint(string.rep(" ", 36))
  3018.         api.rightPrint("  Firewolf is unable to run without ")
  3019.         api.rightPrint("       the HTTP API Enabled! Please ")
  3020.         api.rightPrint("    enable it in your ComputerCraft ")
  3021.         api.rightPrint("                            Config! ")
  3022.         api.rightPrint(string.rep(" ", 36))
  3023.  
  3024.         if isAdvanced() then api.rightPrint("                   Click to exit... ")
  3025.         else api.rightPrint("           Press any key to exit... ") end
  3026.         api.rightPrint(string.rep(" ", 36))
  3027.  
  3028.         while true do
  3029.             local e, but, x, y = oldpullevent()
  3030.             if e == "mouse_click" or e == "key" then break end
  3031.         end
  3032.  
  3033.         return false
  3034.     end
  3035.  
  3036.     -- Turtle
  3037.     if turtle then
  3038.         term.clear()
  3039.         term.setCursorPos(1, 2)
  3040.         api.centerPrint("Advanced computer Required!")
  3041.         print("\n")
  3042.         api.centerPrint("  This version of Firewolf requires  ")
  3043.         api.centerPrint("  an Advanced computer to run!       ")
  3044.         print("")
  3045.         api.centerPrint("  Turtles may not be used to run     ")
  3046.         api.centerPrint("  Firewolf! :(                       ")
  3047.         print("")
  3048.         api.centerPrint("Press any key to exit...")
  3049.  
  3050.         oldpullevent("key")
  3051.         return false
  3052.     end
  3053.  
  3054.     -- Run
  3055.     setfenv(main, env)
  3056.     local _, err = pcall(main)
  3057.     if err and err ~= "parallel:22: Terminated" then
  3058.         term.setTextColor(colors[theme["text-color"]])
  3059.         term.setBackgroundColor(colors[theme["background"]])
  3060.         term.clear()
  3061.         term.setCursorPos(1, 2)
  3062.         term.setCursorBlink(false)
  3063.         term.setBackgroundColor(colors[theme["top-box"]])
  3064.         api.leftPrint(string.rep(" ", 27))
  3065.         api.leftPrint(" Firewolf has Crashed! D:  ")
  3066.         api.leftPrint(string.rep(" ", 27))
  3067.         print("")
  3068.         term.setBackgroundColor(colors[theme["background"]])
  3069.         print("")
  3070.         print("  " .. err)
  3071.         print("")
  3072.  
  3073.         term.setBackgroundColor(colors[theme["bottom-box"]])
  3074.         api.rightPrint(string.rep(" ", 41))
  3075.         if autoupdate == "true" then
  3076.             api.rightPrint("    Please report this error to 1lann or ")
  3077.             api.rightPrint("  GravityScore so we are able to fix it! ")
  3078.             api.rightPrint("  If this problem persists, try deleting ")
  3079.             api.rightPrint("                         " .. rootFolder .. " ")
  3080.         else
  3081.             api.rightPrint("        Automatic updating is off! A new ")
  3082.             api.rightPrint("     version may have have been released ")
  3083.             api.rightPrint("                that may fix this error! ")
  3084.             api.rightPrint("        If you didn't turn auto updating ")
  3085.             api.rightPrint("             off, delete " .. rootFolder .. " ")
  3086.         end
  3087.  
  3088.         api.rightPrint(string.rep(" ", 41))
  3089.         if isAdvanced() then api.rightPrint("                        Click to exit... ")
  3090.         else api.rightPrint("                Press any key to exit... ") end
  3091.         api.rightPrint(string.rep(" ", 41))
  3092.  
  3093.         while true do
  3094.             local e, but, x, y = oldpullevent()
  3095.             if e == "mouse_click" or e == "key" then break end
  3096.         end
  3097.  
  3098.         return false
  3099.     end
  3100. end
  3101.  
  3102. -- Check If Read Only
  3103. if fs.isReadOnly(firewolfLocation) or fs.isReadOnly(rootFolder) then
  3104.     print("Firewolf cannot modify itself or its root folder!")
  3105.     print("")
  3106.     print("This cold be caused by Firewolf being placed in")
  3107.     print("the rom folder, or another program may be")
  3108.     print("preventing the modification of Firewolf.")
  3109.  
  3110.     -- Reset Environment and Exit
  3111.     setfenv(1, oldEnv)
  3112.     error()
  3113. end
  3114.  
  3115. -- Theme
  3116. if not isAdvanced() then
  3117.     theme = originalTheme
  3118. else
  3119.     theme = loadTheme(themeLocation)
  3120.     if theme == nil then theme = defaultTheme end
  3121. end
  3122.  
  3123. -- Debug File
  3124. if #tArgs > 0 and tArgs[1] == "debug" then
  3125.     print("Debug Mode Enabled!")
  3126.  
  3127.     if fs.exists(debugLogLocation) then debugFile = io.open(debugLogLocation, "a")
  3128.     else debugFile = io.open(debugLogLocation, "w") end
  3129.     debugFile:write("\n-- [" .. textutils.formatTime(os.time()) .. "] New Log --")
  3130.     sleep(1.3)
  3131. end
  3132.  
  3133. -- Start
  3134. startup()
  3135.  
  3136. -- Exit Message
  3137. term.setBackgroundColor(colors.black)
  3138. term.setTextColor(colors.white)
  3139. term.setCursorBlink(false)
  3140. term.clear()
  3141. term.setCursorPos(1, 1)
  3142. api.centerPrint("Thank You for Using Firewolf " .. version)
  3143. api.centerPrint("Made by 1lann and GravityScore")
  3144.  
  3145. -- Close
  3146. for _, v in pairs(rs.getSides()) do
  3147.     if peripheral.getType(v) == "modem" then rednet.close(v) end
  3148. end
  3149. if debugFile then debugFile:close() end
  3150.  
  3151. -- Reset Environment
  3152. setfenv(1, oldEnv)
  3153. os.pullEvent = oldpullevent
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement