Advertisement
1lann

firewolf-stable

Aug 3rd, 2012
776
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 90.24 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.  
  1128. -- Background color of the address bar
  1129. address-bar-background=
  1130.  
  1131. -- Color of separator bar when live searching
  1132. address-bar-base=
  1133.  
  1134. -- Top box color
  1135. top-box=
  1136.  
  1137. -- Bottom box color
  1138. bottom-box=
  1139.  
  1140. -- Background color
  1141. background=
  1142.  
  1143. -- Main text color
  1144. text-color=
  1145.  
  1146. ]]
  1147.  
  1148.  
  1149. --  -------- Themes
  1150.  
  1151. local defaultTheme = {["address-bar-text"] = "white", ["address-bar-background"] = "gray",
  1152.     ["address-bar-base"] = "lightGray", ["top-box"] = "red", ["bottom-box"] = "orange",
  1153.     ["text-color"] = "white", ["background"] = "gray"}
  1154. local originalTheme = {["address-bar-text"] = "white", ["address-bar-background"] = "black",
  1155.     ["address-bar-base"] = "black", ["top-box"] = "black", ["bottom-box"] = "black",
  1156.     ["text-color"] = "white", ["background"] = "black"}
  1157.  
  1158. local function loadTheme(path)
  1159.     if fs.exists(path) and not fs.isDir(path) then
  1160.         local a = {}
  1161.         local f = io.open(path, "r")
  1162.         local l = f:read("*l")
  1163.         while l ~= nil do
  1164.             l = l:gsub("^%s*(.-)%s*$", "%1")
  1165.             if l ~= "" and l ~= nil and l ~= "\n" and l:sub(1, 2) ~= "--" then
  1166.                 local b = l:find("=")
  1167.                 if a and b then
  1168.                     local c = l:sub(1, b - 1)
  1169.                     local d = l:sub(b + 1, -1)
  1170.                     if c == "" or d == "" then return nil
  1171.                     else a[c] = d end
  1172.                 else return nil end
  1173.             end
  1174.             l = f:read("*l")
  1175.         end
  1176.         f:close()
  1177.  
  1178.         return a
  1179.     end
  1180. end
  1181.  
  1182.  
  1183. --  -------- Filesystem and HTTP
  1184.  
  1185. local function download(url, path)
  1186.     for i = 1, 3 do
  1187.         local response = http.get(url)
  1188.         if response then
  1189.             local data = response.readAll()
  1190.             response.close()
  1191.             if path then
  1192.                 local f = io.open(path, "w")
  1193.                 f:write(data)
  1194.                 f:close()
  1195.             end
  1196.             return true
  1197.         end
  1198.     end
  1199.  
  1200.     return false  
  1201. end
  1202.  
  1203. local function updateClient()
  1204.     local skipNormal = false
  1205.     if serverID ~= "experimental" then
  1206.         http.request(buildURL)
  1207.         local a = os.startTimer(10)
  1208.         while true do
  1209.             local e, url, handle = os.pullEvent()
  1210.             if e == "http_success" then
  1211.                 if tonumber(handle.readAll()) > build then break
  1212.                 else return false end
  1213.             elseif e == "http_failure" or (e == "timer" and url == a) then
  1214.                 skipNormal = true
  1215.                 break
  1216.             end
  1217.         end
  1218.     end
  1219.  
  1220.     local source = nil
  1221.  
  1222.     if not skipNormal then
  1223.         local _, y = term.getCursorPos()
  1224.         term.setCursorPos(1, y - 2)
  1225.         rightWrite(string.rep(" ", 32))
  1226.         rightWrite("Updating Firewolf... ")
  1227.  
  1228.         http.request(firewolfURL)
  1229.         local a = os.startTimer(10)
  1230.         while true do
  1231.             local e, url, handle = os.pullEvent()
  1232.             if e == "http_success" then
  1233.                 source = handle
  1234.                 break
  1235.             elseif e == "http_failure" or (e == "timer" and url == a) then
  1236.                 break
  1237.             end
  1238.         end
  1239.     end
  1240.  
  1241.     if not source then
  1242.         if isAdvanced() then
  1243.             term.setTextColor(colors[theme["text-color"]])
  1244.             term.setBackgroundColor(colors[theme["background"]])
  1245.             term.clear()
  1246.             if not fs.exists(rootFolder) then fs.makeDir(rootFolder) end
  1247.             local f = io.open(rootFolder .. "/temp_file", "w")
  1248.             f:write(graphics.githubImage)
  1249.             f:close()
  1250.             local a = paintutils.loadImage(rootFolder .. "/temp_file")
  1251.             paintutils.drawImage(a, 5, 5)
  1252.             fs.delete(rootFolder .. "/temp_file")
  1253.  
  1254.             term.setCursorPos(19, 4)
  1255.             term.setBackgroundColor(colors[theme["top-box"]])
  1256.             write(string.rep(" ", 32))
  1257.             term.setCursorPos(19, 5)
  1258.             write("  Could Not Connect to GitHub!  ")
  1259.             term.setCursorPos(19, 6)
  1260.             write(string.rep(" ", 32))
  1261.             term.setBackgroundColor(colors[theme["bottom-box"]])
  1262.             term.setCursorPos(19, 8)
  1263.             write(string.rep(" ", 32))
  1264.             term.setCursorPos(19, 9)
  1265.             write("    Sorry, Firewolf could not   ")
  1266.             term.setCursorPos(19, 10)
  1267.             write(" connect to GitHub to download  ")
  1268.             term.setCursorPos(19, 11)
  1269.             write(" necessary files. Please check: ")
  1270.             term.setCursorPos(19, 12)
  1271.             write("    http://status.github.com    ")
  1272.             term.setCursorPos(19, 13)
  1273.             write(string.rep(" ", 32))
  1274.             term.setCursorPos(19, 14)
  1275.             write("        Click to exit...        ")
  1276.             term.setCursorPos(19, 15)
  1277.             write(string.rep(" ", 32))
  1278.         else
  1279.             term.clear()
  1280.             term.setCursorPos(1, 1)
  1281.             term.setBackgroundColor(colors.black)
  1282.             term.setTextColor(colors.white)
  1283.             print("\n")
  1284.             centerPrint("Could not connect to GitHub!")
  1285.             print("")
  1286.             centerPrint("Sorry, Firewolf could not connect to")
  1287.             centerPrint("GitHub to download necessary files.")
  1288.             centerPrint("Please check:")
  1289.             centerPrint("http://status.github.com")
  1290.             print("")
  1291.             centerPrint("Press any key to exit...")
  1292.         end
  1293.  
  1294.         while true do
  1295.             local e = oldpullevent()
  1296.             if e == "mouse_click" or e == "key" then break end
  1297.         end
  1298.  
  1299.         return false
  1300.     elseif source and autoupdate == "true" then
  1301.         local b = io.open(firewolfLocation, "r")
  1302.         local new = source.readAll()
  1303.         local cur = b:read("*a")
  1304.         source.close()
  1305.         b:close()
  1306.  
  1307.         if cur ~= new then
  1308.             fs.delete(firewolfLocation)
  1309.             local f = io.open(firewolfLocation, "w")
  1310.             f:write(new)
  1311.             f:close()
  1312.             return true
  1313.         else
  1314.             return false
  1315.         end
  1316.     end
  1317. end
  1318.  
  1319. local function resetFilesystem()
  1320.     -- Migrate
  1321.     fs.delete(rootFolder .. "/available_themes")
  1322.     fs.delete(rootFolder .. "/default_theme")
  1323.  
  1324.     -- Reset
  1325.     if not fs.exists(rootFolder) then fs.makeDir(rootFolder)
  1326.     elseif not fs.isDir(rootFolder) then fs.move(rootFolder, "/Firewolf_Data.old") end
  1327.  
  1328.     if not fs.isDir(serverFolder) then fs.delete(serverFolder) end
  1329.     if not fs.exists(serverFolder) then fs.makeDir(serverFolder) end
  1330.     if not fs.isDir(cacheFolder) then fs.delete(cacheFolder) end
  1331.     if not fs.exists(cacheFolder) then fs.makeDir(cacheFolder) end
  1332.     if not fs.isDir(websiteDataFolder) then fs.delete(websiteDataFolder) end
  1333.     if not fs.exists(websiteDataFolder) then fs.makeDir(websiteDataFolder) end
  1334.  
  1335.     if fs.isDir(settingsLocation) then fs.delete(settingsLocation) end
  1336.     if fs.isDir(serverLocation) then fs.delete(serverLocation) end
  1337.  
  1338.     if not fs.exists(settingsLocation) then
  1339.         local f = io.open(settingsLocation, "w")
  1340.         f:write(textutils.serialize({auto = "true", incog = "false", home = "firewolf"}))
  1341.         f:close()
  1342.     end
  1343.  
  1344.     if not fs.exists(serverLocation) then
  1345.         download(serverURL, serverLocation)
  1346.     end
  1347.  
  1348.     fs.delete(rootFolder .. "/temp_file")
  1349.  
  1350.     for _, v in pairs({userWhitelist, userBlacklist}) do
  1351.         if fs.isDir(v) then fs.delete(v) end
  1352.         if not fs.exists(v) then
  1353.             local f = io.open(v, "w")
  1354.             f:write("")
  1355.             f:close()
  1356.         end
  1357.     end
  1358. end
  1359.  
  1360. local function checkForModem(display)
  1361.     while true do
  1362.         local present = false
  1363.         for _, v in pairs(rs.getSides()) do
  1364.             if peripheral.getType(v) == "modem" then
  1365.                 rednet.open(v)
  1366.                 present = true
  1367.                 break
  1368.             end
  1369.         end
  1370.  
  1371.         if not present and type(display) == "function" then
  1372.             display()
  1373.             os.pullEvent("peripheral")
  1374.         else
  1375.             return true
  1376.         end
  1377.     end
  1378. end
  1379.  
  1380.  
  1381. --  -------- Databases
  1382.  
  1383. local function loadDatabases()
  1384.     -- Blacklist
  1385.     if fs.exists(userBlacklist) and not fs.isDir(userBlacklist) then
  1386.         local bf = io.open(userBlacklist, "r")
  1387.         local l = bf:read("*l")
  1388.         while l ~= nil do
  1389.             if l ~= nil and l ~= "" and l ~= "\n" then
  1390.                 l = l:gsub("^%s*(.-)%s*$", "%1")
  1391.                 table.insert(blacklist, l)
  1392.             end
  1393.             l = bf:read("*l")
  1394.         end
  1395.         bf:close()
  1396.     end
  1397.  
  1398.     -- Whitelist
  1399.     if fs.exists(userWhitelist) and not fs.isDir(userWhitelist) then
  1400.         local wf = io.open(userWhitelist, "r")
  1401.         local l = wf:read("*l")
  1402.         while l ~= nil do
  1403.             if l ~= nil and l ~= "" and l ~= "\n" then
  1404.                 l = l:gsub("^%s*(.-)%s*$", "%1")
  1405.                 local a, b = l:find("| |")
  1406.                 table.insert(whitelist, {l:sub(1, a - 1), l:sub(b + 1, -1)})
  1407.             end
  1408.             l = wf:read("*l")
  1409.         end
  1410.         wf:close()
  1411.     end
  1412. end
  1413.  
  1414. local function verifyBlacklist(id)
  1415.     for _, v in pairs(blacklist) do
  1416.         if tostring(id) == v then return true end
  1417.     end
  1418.     return false
  1419. end
  1420.  
  1421. local function verifyWhitelist(id, url)
  1422.     for _, v in pairs(whitelist) do
  1423.         if v[2] == tostring(args[1]) and v[1] == tostring(args[2]) then
  1424.             return true
  1425.         end
  1426.     end
  1427.     return false
  1428. end
  1429.  
  1430.  
  1431. --  -------- Protocols
  1432.  
  1433. protocols.rdnt = {}
  1434. protocols.http = {}
  1435.  
  1436. protocols.rdnt.getSearchResults = function()
  1437.     dnsDatabase = {[1] = {}, [2] = {}}
  1438.     local resultIDs = {}
  1439.     local conflict = {}
  1440.  
  1441.     rednet.broadcast("firewolf.broadcast.dns.list")
  1442.     local startClock = os.clock()
  1443.     while os.clock() - startClock < timeout do
  1444.         local id, i = rednet.receive(timeout)
  1445.         if id then
  1446.             if i:sub(1, 14) == "firewolf-site:" then
  1447.                 i = i:sub(15, -1)
  1448.                 local bl, wl = verifyBlacklist(id), verifyWhitelist(id, i)
  1449.                 if not i:find(" ") and i:len() < 40 and (not bl or (bl and wl)) then
  1450.                     if not resultIDs[tostring(id)] then resultIDs[tostring(id)] = 1
  1451.                     else resultIDs[tostring(id)] = resultIDs[tostring(id)] + 1
  1452.                     end
  1453.                    
  1454.                     if not i:find("rdnt://") then i = ("rdnt://" .. i) end
  1455.                     local x = false
  1456.                     if conflict[i] then
  1457.                         x = true
  1458.                         table.insert(conflict[i], id)
  1459.                     else
  1460.                         for m, n in pairs(dnsDatabase[1]) do
  1461.                             if n:lower() == i:lower() then
  1462.                                 x = true
  1463.                                 table.remove(dnsDatabase[1], m)
  1464.                                 table.remove(dnsDatabase[2], m)
  1465.                                 if conflict[i] then
  1466.                                     table.insert(conflict[i], id)
  1467.                                 else
  1468.                                     conflict[i] = {}
  1469.                                     table.insert(conflict[i], id)
  1470.                                 end
  1471.                                 break
  1472.                             end
  1473.                         end
  1474.                     end
  1475.  
  1476.                     if not x and resultIDs[tostring(id)] <= 3 then
  1477.                         table.insert(dnsDatabase[1], i)
  1478.                         table.insert(dnsDatabase[2], id)
  1479.                     end
  1480.                 end
  1481.             end
  1482.         else
  1483.             break
  1484.         end
  1485.     end
  1486.     for k,v in pairs(conflict) do
  1487.         table.sort(v)
  1488.         table.insert(dnsDatabase[1], k)
  1489.         table.insert(dnsDatabase[2], v[1])
  1490.     end
  1491.  
  1492.     return dnsDatabase[1]
  1493. end
  1494.  
  1495. protocols.rdnt.getWebsite = function(site)
  1496.     local id, content, status = nil, nil, nil
  1497.     local clock = os.clock()
  1498.     local websiteID = nil
  1499.     for k, v in pairs(dnsDatabase[1]) do
  1500.         local web = site:gsub("rdnt://", "")
  1501.         if web:find("/") then web = web:sub(1, web:find("/") - 1) end
  1502.         if web == v:gsub("rdnt://", "") then
  1503.             websiteID = dnsDatabase[2][k]
  1504.             break
  1505.         end
  1506.     end
  1507.     if not websiteID then return nil, nil, nil end
  1508.  
  1509.     sleep(timeout)
  1510.     rednet.send(websiteID, site)
  1511.     clock = os.clock()
  1512.     while os.clock() - clock < timeout do
  1513.         id, content = rednet.receive(timeout)
  1514.         if id then
  1515.             if id == websiteID then
  1516.                 local bl = verifyBlacklist(id)
  1517.                 local wl = verifyWhitelist(id, site)
  1518.                 status = nil
  1519.                 if (bl and not wl) or site == "" or site == "." or site == ".." then
  1520.                     -- Ignore
  1521.                 elseif wl then
  1522.                     status = "whitelist"
  1523.                     break
  1524.                 else
  1525.                     status = "safe"
  1526.                     break
  1527.                 end
  1528.             end
  1529.         end
  1530.     end
  1531.  
  1532.     return id, content, status
  1533. end
  1534.  
  1535. protocols.http.getSearchResults = function()
  1536.     dnsDatabase = {[1] = {}, [2] = {}}
  1537.     return dnsDatabase[1]
  1538. end
  1539.  
  1540. protocols.http.getWebsite = function()
  1541.     return nil, nil, nil
  1542. end
  1543.  
  1544.  
  1545. --  -------- Homepage
  1546.  
  1547. pages["firewolf"] = function(site)
  1548.     openAddressBar = true
  1549.     term.setBackgroundColor(colors[theme["background"]])
  1550.     term.clear()
  1551.     term.setTextColor(colors[theme["text-color"]])
  1552.     term.setBackgroundColor(colors[theme["top-box"]])
  1553.     print("")
  1554.     leftPrint(string.rep(" ", 42))
  1555.     leftPrint([[        _,-='"-.__               /\_/\    ]])
  1556.     leftPrint([[         -.}        =._,.-==-._.,  @ @._, ]])
  1557.     leftPrint([[            -.__  __,-.   )       _,.-'   ]])
  1558.     leftPrint([[ Firewolf ]] .. version .. string.rep(" ", 8 - version:len()) ..
  1559.         [["    G..m-"^m m'        ]])
  1560.     leftPrint(string.rep(" ", 42))
  1561.     print("\n")
  1562.  
  1563.     term.setBackgroundColor(colors[theme["bottom-box"]])
  1564.     rightPrint(string.rep(" ", 42))
  1565.     if isAdvanced() then rightPrint("  News:                       [- Sites -] ")
  1566.     else rightPrint("  News:                                   ") end
  1567.     rightPrint("    Firewolf 2.4 is out! It cuts out 1500 ")
  1568.     rightPrint("   lines, and contains many improvements! ")
  1569.     rightPrint(string.rep(" ", 42))
  1570.     rightPrint("   Firewolf 3.0 will be out soon! It will ")
  1571.     rightPrint("     bring the long awaited HTTP support! ")
  1572.     rightPrint(string.rep(" ", 42))
  1573.  
  1574.     while true do
  1575.         local e, but, x, y = os.pullEvent()
  1576.         if isAdvanced() and e == "mouse_click" and x >= 40 and x <= 50 and y == 11 then
  1577.             redirect("firewolf/sites")
  1578.         end
  1579.     end
  1580. end
  1581.  
  1582. pages["firefox"] = function(site) redirect("firewolf") end
  1583.  
  1584. pages["firewolf/sites"] = function(site)
  1585.     term.setBackgroundColor(colors[theme["background"]])
  1586.     term.clear()
  1587.     term.setTextColor(colors[theme["text-color"]])
  1588.     term.setBackgroundColor(colors[theme["top-box"]])
  1589.     print("\n")
  1590.     leftPrint(string.rep(" ", 17))
  1591.     leftPrint(" Built-In Sites  ")
  1592.     leftPrint(string.rep(" ", 17))
  1593.  
  1594.     local sx = 8
  1595.     term.setBackgroundColor(colors[theme["bottom-box"]])
  1596.     term.setCursorPos(1, sx)
  1597.     rightPrint(string.rep(" ", 40))
  1598.     rightPrint("  rdnt://firewolf              Homepage ")
  1599.     rightPrint("  rdnt://firewolf/sites           Sites ")
  1600.     rightPrint("  rdnt://server       Server Management ")
  1601.     rightPrint("  rdnt://help                 Help Page ")
  1602.     rightPrint("  rdnt://settings              Settings ")
  1603.     rightPrint("  rdnt://credits                Credits ")
  1604.     rightPrint("  rdnt://exit                      Exit ")
  1605.     rightPrint(string.rep(" ", 40))
  1606.  
  1607.     local a = {"firewolf", "firewolf/sites", "server", "help", "settings", "credits", "exit"}
  1608.     while true do
  1609.         local e, but, x, y = os.pullEvent()
  1610.         if isAdvanced() and e == "mouse_click" and x >= 14 and x <= 50 then
  1611.             for i, v in ipairs(a) do
  1612.                 if y == sx + i then
  1613.                     if v == "exit" then return true end
  1614.                     redirect(v)
  1615.                 end
  1616.             end
  1617.         end
  1618.     end
  1619. end
  1620.  
  1621. pages["sites"] = function(site) redirect("firewolf/sites") end
  1622.  
  1623.  
  1624. --  -------- Server Management
  1625.  
  1626. local function manageServers(site, protocol, functionList, startServerName)
  1627.     local servers = functionList["reload servers"]()
  1628.     local sy = 7
  1629.  
  1630.     if startServerName == nil then startServerName = "Start" end
  1631.     if isAdvanced() then
  1632.         local function draw(l, sel)
  1633.             term.setBackgroundColor(colors[theme["bottom-box"]])
  1634.             term.setCursorPos(4, sy)
  1635.             write("[- New Server -]")
  1636.             for i, v in ipairs(l) do
  1637.                 term.setCursorPos(3, i + sy)
  1638.                 write(string.rep(" ", 24))
  1639.                 term.setCursorPos(4, i + sy)
  1640.                 local nv = v
  1641.                 if nv:len() > 18 then nv = nv:sub(1, 15) .. "..." end
  1642.                 if i == sel then write("[ " .. nv .. " ]")
  1643.                 else write("  " .. nv) end
  1644.             end
  1645.             if #l < 1 then
  1646.                 term.setCursorPos(4, sy + 2)
  1647.                 write("A website is literally")
  1648.                 term.setCursorPos(4, sy + 3)
  1649.                 write("just a lua script!")
  1650.                 term.setCursorPos(4, sy + 4)
  1651.                 write("Go ahead and make one!")
  1652.                 term.setCursorPos(4, sy + 6)
  1653.                 write("Also, be sure to check")
  1654.                 term.setCursorPos(4, sy + 7)
  1655.                 write("out Firewolf's APIs to")
  1656.                 term.setCursorPos(4, sy + 8)
  1657.                 write("help you make your")
  1658.                 term.setCursorPos(4, sy + 9)
  1659.                 write("site, at rdnt://help")
  1660.             end
  1661.  
  1662.             term.setCursorPos(30, sy)
  1663.             write(string.rep(" ", 19))
  1664.             term.setCursorPos(30, sy)
  1665.             if l[sel] then
  1666.                 local nl = l[sel]
  1667.                 if nl:len() > 19 then nl = nl:sub(1, 16) .. "..." end
  1668.                 write(nl)
  1669.             else write("No Server Selected!") end
  1670.             term.setCursorPos(30, sy + 2)
  1671.             write("[- " .. startServerName .. " -]")
  1672.             term.setCursorPos(30, sy + 4)
  1673.             write("[- Edit -]")
  1674.             term.setCursorPos(30, sy + 6)
  1675.             if functionList["run on boot"] then write("[- Run on Boot -]") end
  1676.             term.setCursorPos(30, sy + 8)
  1677.             write("[- Delete -]")
  1678.         end
  1679.  
  1680.         local function updateDisplayList(items, loc, len)
  1681.             local ret = {}
  1682.             for i = 1, len do
  1683.                 if items[i + loc - 1] then table.insert(ret, items[i + loc - 1]) end
  1684.             end
  1685.             return ret
  1686.         end
  1687.  
  1688.         while true do
  1689.             term.setBackgroundColor(colors[theme["background"]])
  1690.             term.clear()
  1691.             term.setCursorPos(1, 1)
  1692.             term.setTextColor(colors[theme["text-color"]])
  1693.             term.setBackgroundColor(colors[theme["top-box"]])
  1694.             print("")
  1695.             leftPrint(string.rep(" ", 27))
  1696.             leftPrint(" Server Management - " .. protocol:upper() .. "  ")
  1697.             leftPrint(string.rep(" ", 27))
  1698.             print("")
  1699.  
  1700.             term.setBackgroundColor(colors[theme["bottom-box"]])
  1701.             for i = 1, 12 do
  1702.                 term.setCursorPos(3, i + sy - 2)
  1703.                 write(string.rep(" ", 24))
  1704.                 term.setCursorPos(29, i + sy - 2)
  1705.                 write(string.rep(" ", 21))
  1706.             end
  1707.  
  1708.             local sel = 1
  1709.             local loc = 1
  1710.             local len = 10
  1711.             local disList = updateDisplayList(servers, loc, len)
  1712.             draw(disList, sel)
  1713.  
  1714.             while true do
  1715.                 local e, but, x, y = os.pullEvent()
  1716.                 if e == "key" and but == 200 and #servers > 0 and loc > 1 then
  1717.                     loc = loc - 1
  1718.                     disList = updateDisplayList(servers, loc, len)
  1719.                     draw(disList, sel)
  1720.                 elseif e == "key" and but == 208 and #servers > 0 and loc + len - 1 < #servers then
  1721.                     loc = loc + 1
  1722.                     disList = updateDisplayList(servers, loc, len)
  1723.                     draw(disList, sel)
  1724.                 elseif e == "mouse_click" then
  1725.                     if x >= 4 and x <= 25 then
  1726.                         if y == 7 then
  1727.                             functionList["new server"]()
  1728.                             servers = functionList["reload servers"]()
  1729.                             break
  1730.                         elseif #servers > 0 then
  1731.                             for i, v in ipairs(disList) do
  1732.                                 if y == i + 7 then
  1733.                                     sel = i
  1734.                                     draw(disList, sel)
  1735.                                 end
  1736.                             end
  1737.                         end
  1738.                     elseif x >= 30 and x <= 40 and y == 9 and #servers > 0 then
  1739.                         functionList["start"](disList[sel])
  1740.                         servers = functionList["reload servers"]()
  1741.                         break
  1742.                     elseif x >= 30 and x <= 39 and y == 11 and #servers > 0 then
  1743.                         functionList["edit"](disList[sel])
  1744.                         servers = functionList["reload servers"]()
  1745.                         break
  1746.                     elseif x >= 30 and x <= 46 and y == 13 and #servers > 0 and
  1747.                             functionList["run on boot"] then
  1748.                         functionList["run on boot"](disList[sel])
  1749.                         term.setBackgroundColor(colors[theme["bottom-box"]])
  1750.                         term.setCursorPos(32, 15)
  1751.                         write("Will Run on Boot!")
  1752.                         openAddressBar = false
  1753.                         sleep(1.3)
  1754.                         openAddressBar = true
  1755.                         term.setCursorPos(32, 15)
  1756.                         write(string.rep(" ", 18))
  1757.                         break
  1758.                     elseif x >= 30 and x <= 41 and y == 15 and #servers > 0 then
  1759.                         functionList["delete"](disList[sel])
  1760.                         servers = functionList["reload servers"]()
  1761.                         break
  1762.                     end
  1763.                 end
  1764.             end
  1765.         end
  1766.     else
  1767.         while true do
  1768.             term.setBackgroundColor(colors[theme["background"]])
  1769.             term.clear()
  1770.             term.setCursorPos(1, 1)
  1771.             term.setTextColor(colors[theme["text-color"]])
  1772.             term.setBackgroundColor(colors[theme["top-box"]])
  1773.             print("")
  1774.             centerPrint(string.rep(" ", 27))
  1775.             centerPrint(" Server Management - " .. protocol:upper() .. "  ")
  1776.             centerPrint(string.rep(" ", 27))
  1777.             print("")
  1778.  
  1779.             local a = {"New Server"}
  1780.             for _, v in pairs(servers) do table.insert(a, v) end
  1781.             local server = scrollingPrompt(a, 4, 7, 10)
  1782.             if server == "New Server" then
  1783.                 functionList["new server"]()
  1784.                 servers = functionList["reload servers"]()
  1785.             else
  1786.                 term.setCursorPos(30, 8)
  1787.                 write(server)
  1788.                 local a = {{"Start", 30, 9}, {"Edit", 30, 11}, {"Run on Boot", 30, 12},
  1789.                     {"Delete", 30, 13}, {"Back", 30, 15}}
  1790.                 if not functionList["run on boot"] then
  1791.                     a = {{"Start", 30, 9}, {"Edit", 30, 11}, {"Delete", 30, 13}, {"Back", 30, 15}}
  1792.                 end
  1793.                 local opt = prompt(a, "vertical")
  1794.                 if opt == "Start" then
  1795.                     functionList["start"](server)
  1796.                     servers = functionList["reload servers"]()
  1797.                 elseif opt == "Edit" then
  1798.                     functionList["edit"](server)
  1799.                     servers = functionList["reload servers"](server)
  1800.                 elseif opt == "Run on Boot" and functionList["run on boot"] then
  1801.                     functionList["run on boot"](server)
  1802.                     term.setCursorPos(32, 16)
  1803.                     write("Will Run on Boot!")
  1804.                     openAddressBar = false
  1805.                     sleep(1.3)
  1806.                     openAddressBar = true
  1807.                 elseif opt == "Delete" then
  1808.                     functionList["delete"](server)
  1809.                     servers = functionList["reload servers"]()
  1810.                 end
  1811.             end
  1812.         end
  1813.     end
  1814. end
  1815.  
  1816. local function editPages(dir)
  1817.     local oldLoc = shell.dir()
  1818.     local commandHis = {}
  1819.     term.setBackgroundColor(colors.black)
  1820.     term.setTextColor(colors.white)
  1821.     term.clear()
  1822.     term.setCursorPos(1, 1)
  1823.     print("")
  1824.     print(" Server Shell Editing")
  1825.     print(" Type 'exit' to return to Firewolf.")
  1826.     print(" The 'home' file is the index of your site.")
  1827.     print("")
  1828.  
  1829.     local allowed = {"move", "mv", "cp", "copy", "drive", "delete", "rm", "edit",
  1830.         "eject", "exit", "help", "id", "monitor", "rename", "alias", "clear",
  1831.         "paint", "firewolf", "lua", "redstone", "rs", "redprobe", "redpulse", "programs",
  1832.         "redset", "reboot", "hello", "label", "list", "ls", "easter", "pastebin", "dir"}
  1833.    
  1834.     while true do
  1835.         shell.setDir(dir)
  1836.         term.setBackgroundColor(colors.black)
  1837.         if isAdvanced() then term.setTextColor(colors.yellow)
  1838.         else term.setTextColor(colors.white) end
  1839.         write("> ")
  1840.         term.setTextColor(colors.white)
  1841.         local line = read(nil, commandHis)
  1842.         table.insert(commandHis, line)
  1843.  
  1844.         local words = {}
  1845.         for m in string.gmatch(line, "[^ \t]+") do
  1846.             local a = m:gsub("^%s*(.-)%s*$", "%1")
  1847.             table.insert(words, a)
  1848.         end
  1849.  
  1850.         local com = words[1]
  1851.         if com == "exit" then
  1852.             break
  1853.         elseif com then
  1854.             local a = false
  1855.             for _, v in pairs(allowed) do
  1856.                 if com == v then a = true break end
  1857.             end
  1858.  
  1859.             if a then
  1860.                 term.setBackgroundColor(colors.black)
  1861.                 term.setTextColor(colors.white)
  1862.                 shell.run(com, unpack(words, 2))
  1863.             else
  1864.                 term.setTextColor(colors.red)
  1865.                 print("Program Not Allowed!")
  1866.             end
  1867.         end
  1868.     end
  1869.     shell.setDir(oldLoc)
  1870. end
  1871.  
  1872. local function newServer(onCreate)
  1873.     term.setBackgroundColor(colors[theme["background"]])
  1874.     for i = 1, 12 do
  1875.         term.setCursorPos(3, i + 5)
  1876.         term.clearLine()
  1877.     end
  1878.  
  1879.     term.setBackgroundColor(colors[theme["bottom-box"]])
  1880.     term.setCursorPos(1, 7)
  1881.     for i = 1, 8 do centerPrint(string.rep(" ", 47)) end
  1882.     term.setCursorPos(5, 8)
  1883.     write("Name: ")
  1884.     local name = modRead({refusePrint = "`", visibleLength = w - 4, textLength = 200})
  1885.     term.setCursorPos(5, 10)
  1886.     write("URL:")
  1887.     term.setCursorPos(8, 11)
  1888.     write("rdnt://")
  1889.     local url = modRead({grantPrint = "abcdefghijklmnopqrstuvwxyz1234567890-_.+",
  1890.         visibleLength = w - 4, textLength = 200})
  1891.     url = url:gsub(" ", "")
  1892.     if name == "" or url == "" then
  1893.         term.setCursorPos(5, 13)
  1894.         write("URL or Name is Empty!")
  1895.         openAddressBar = false
  1896.         sleep(1.3)
  1897.         openAddressBar = true
  1898.     else
  1899.         local c = onCreate(name, url)
  1900.  
  1901.         term.setCursorPos(5, 13)
  1902.         if c and c == "true" then
  1903.             write("Successfully Created Server!")
  1904.         elseif c == "false" or c == nil then
  1905.             write("Server Creation Failed!")
  1906.         else
  1907.             write(c)
  1908.         end
  1909.         openAddressBar = false
  1910.         sleep(1.3)
  1911.         openAddressBar = true
  1912.     end
  1913. end
  1914.  
  1915. pages["server/rdnt"] = function(site)
  1916.     manageServers(site, "rdnt", {["reload servers"] = function()
  1917.         local servers = {}
  1918.         for _, v in pairs(fs.list(serverFolder)) do
  1919.             if fs.isDir(serverFolder .. "/" .. v) then table.insert(servers, v) end
  1920.         end
  1921.  
  1922.         return servers
  1923.     end, ["new server"] = function()
  1924.         newServer(function(name, url)
  1925.             if fs.exists(serverFolder .. "/" .. url) then
  1926.                 return "Server Already Exists!"
  1927.             end
  1928.  
  1929.             fs.makeDir(serverFolder .. "/" .. url)
  1930.             local f = io.open(serverFolder .. "/" .. url .. "/home", "w")
  1931.             f:write("print(\"\")\ncenterPrint(\"Welcome To " .. name .. "!\")\n\n")
  1932.             f:close()
  1933.             return "true"
  1934.         end)
  1935.     end, ["start"] = function(server)
  1936.         term.clear()
  1937.         term.setCursorPos(1, 1)
  1938.         term.setBackgroundColor(colors.black)
  1939.         term.setTextColor(colors.white)
  1940.         openAddressBar = false
  1941.         setfenv(1, oldEnv)
  1942.         shell.run(serverLocation, server, serverFolder .. "/" .. server)
  1943.         setfenv(1, override)
  1944.         openAddressBar = true
  1945.         checkForModem()
  1946.     end, ["edit"] = function(server)
  1947.         openAddressBar = false
  1948.         editPages(serverFolder .. "/" .. server)
  1949.         openAddressBar = true
  1950.         if not fs.exists(serverFolder .. "/" .. server .. "/home") then
  1951.             local f = io.open(serverFolder .. "/" .. server .. "/home", "w")
  1952.             f:write("print(\"\")\ncenterPrint(\"Welcome To " .. server .. "!\")\n\n")
  1953.             f:close()
  1954.         end
  1955.     end, ["run on boot"] = function(server)
  1956.         fs.delete("/old-startup")
  1957.         if fs.exists("/startup") then fs.move("/startup", "/old-startup") end
  1958.         local f = io.open("/startup", "w")
  1959.         f:write("shell.run(\"" .. serverLocation .. "\", \"" .. server .. "\", \"" ..
  1960.             serverFolder .. "/" .. server .. "\")")
  1961.         f:close()
  1962.     end, ["delete"] = function(server)
  1963.         fs.delete(serverFolder .. "/" .. server)
  1964.     end})
  1965. end
  1966.  
  1967. pages["server/http"] = function(site)
  1968.     term.setBackgroundColor(colors[theme["background"]])
  1969.     term.clear()
  1970.     print("\n\n")
  1971.     term.setBackgroundColor(colors[theme["top-box"]])
  1972.     centerPrint(string.rep(" ", 17))
  1973.     centerPrint("  Comming Soon!  ")
  1974.     centerPrint(string.rep(" ", 17))
  1975. end
  1976.  
  1977. pages["server"] = function(site)
  1978.     setfenv(manageServers, override)
  1979.     setfenv(newServer, override)
  1980.     setfenv(editPages, env)
  1981.     if curProtocol == protocols.rdnt then redirect("server/rdnt")
  1982.     elseif curProtocol == protocols.http then redirect("server/http") end
  1983. end
  1984.  
  1985.  
  1986. --  -------- Help
  1987.  
  1988. pages["help"] = function(site)
  1989.     term.setBackgroundColor(colors[theme["background"]])
  1990.     term.clear()
  1991.     term.setTextColor(colors[theme["text-color"]])
  1992.     term.setBackgroundColor(colors[theme["top-box"]])
  1993.     print("")
  1994.     leftPrint(string.rep(" ", 16))
  1995.     leftPrint(" Firewolf Help  ")
  1996.     leftPrint(string.rep(" ", 16))
  1997.     print("")
  1998.  
  1999.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2000.     for i = 1, 12 do rightPrint(string.rep(" ", 41)) end
  2001.     term.setCursorPos(1, 15)
  2002.     rightPrint("       View the full documentation here: ")
  2003.     rightPrint("  https://github.com/1lann/Firewolf/wiki ")
  2004.  
  2005.     local opt = prompt({{"Getting Started", w - 21, 8}, {"Making a Theme", w - 20, 10},
  2006.         {"API Documentation", w - 23, 12}}, "vertical")
  2007.     local pages = {}
  2008.     if opt == "Getting Started" then
  2009.         pages[1] = {title = "Getting Started - Intoduction", content = {
  2010.             "Hey there!",
  2011.             "",
  2012.             "Firewolf is an app that allows you to create",
  2013.             "and visit websites! Each site has an address",
  2014.             "(the URL) which you can type into the address",
  2015.             "bar above, and then visit the site.",
  2016.             "",
  2017.             "You can open the address bar by clicking on",
  2018.             "it, or by pressing control."
  2019.         }} pages[2] = {title = "Getting Started - Searching", content = {
  2020.             "The address bar can be also be used to",
  2021.             "search for sites, by simply typing in the",
  2022.             "search term.",
  2023.             "",
  2024.             "To view all sites, just open it and hit",
  2025.             "enter (leave the field blank)."
  2026.         }} pages[3] = {title = "Getting Started - Built-In Websites", content = {
  2027.             "Firewolf has a set of built-in websites",
  2028.             "available for use:",
  2029.             "",
  2030.             "rdnt://firewolf   Normal hompage",
  2031.             "rdnt://sites      Built-In Site",
  2032.             "rdnt://server     Create websites",
  2033.             "rdnt://help       Help and documentation"
  2034.         }} pages[4] = {title = "Getting Started - Built-In Websites", content = {
  2035.             "More built-in websites:",
  2036.             "",
  2037.             "rdnt://settings   Firewolf settings",
  2038.             "rdnt://credits    View the credits",
  2039.             "rdnt://exit       Exit the app"
  2040.         }}
  2041.     elseif opt == "Making a Theme" then
  2042.         pages[1] = {title = "Making a Theme - Introduction", content = {
  2043.             "Firewolf themes are files that tell Firewolf",
  2044.             "to color which things what.",
  2045.             "Several themes can already be downloaded for",
  2046.             "Firewolf from rdnt://settings/themes.",
  2047.             "",
  2048.             "You can also make your own theme, use it in",
  2049.             "your copy of Firewolf.Your theme can also be",
  2050.             "submitted it to the themes list!"
  2051.         }} pages[2] = {title = "Making a Theme - Example", content = {
  2052.             "A theme file consists of several lines of",
  2053.             "text. Here is the default theme file:",
  2054.             "address-bar-text=white",
  2055.             "address-bar-background=gray",
  2056.             "address-bar-base=lightGray",
  2057.             "top-box=red",
  2058.             "bottom-box=orange",
  2059.             "background=gray",
  2060.             "text-color=white"
  2061.         }} pages[3] = {title = "Making a Theme - Explanation", content = {
  2062.             "On each line of the example, something is",
  2063.             "given a color, like on the last line, the",
  2064.             "text of the page is told to be white.",
  2065.             "",
  2066.             "The color specified after the = is the same",
  2067.             "as when you call colors.[color name].",
  2068.             "For example, specifying 'red' after the =",
  2069.             "colors that object red."
  2070.         }} pages[4] = {title = "Making a Theme - Have a Go", content = {
  2071.             "Themes can be made at rdnt://settings/themes,",
  2072.             "click on 'Change Theme' button, and click on",
  2073.             "'New Theme'.",
  2074.             "",
  2075.             "Enter a theme name, then exit Firewolf and",
  2076.             "edit the newly created file",
  2077.             "Specify the colors for each of the keys,",
  2078.             "and return to the themes section of the",
  2079.             "downloads center. Click 'Load Theme'."
  2080.         }} pages[5] = {title = "Making a Theme - Submitting", content = {
  2081.             "To submit a theme to the theme list,",
  2082.             "send GravityScore a message on the CCForums",
  2083.             "that contains your theme file and name.",
  2084.             "",
  2085.             "He will message you back saying whether your",
  2086.             "theme has been added, or if anything needs to",
  2087.             "be changed before it is added."
  2088.         }}
  2089.     elseif opt == "API Documentation" then
  2090.         pages[1] = {title = "API Documentation - 1", content = {
  2091.             "The Firewolf API is a bunch of global",
  2092.             "functions that aim to simplify your life when",
  2093.             "designing and coding websites.",
  2094.             "",
  2095.             "For a full documentation on these functions,",
  2096.             "visit the Firewolf Wiki Page here:",
  2097.             "https://github.com/1lann/Firewolf/wiki"
  2098.         }} pages[2] = {title = "API Documentation - 2", content = {
  2099.             "centerPrint(string text)",
  2100.             "cPrint(string text)",
  2101.             "centerWrite(string text)",
  2102.             "cWrite(string text)",
  2103.             "",
  2104.             "leftPrint(string text)",
  2105.             "lPrint(string text)",
  2106.         }} pages[3] = {title = "API Documentation - 3", content = {
  2107.             "leftWrite(string text)",
  2108.             "lWrite(string text)",
  2109.             "",
  2110.             "rightPrint(string text)",
  2111.             "rPrint(string text)",
  2112.             "rightWrite(string text)",
  2113.             "rWrite(string text)"
  2114.         }} pages[4] = {title = "API Documentation - 4", content = {
  2115.             "prompt(table list, string direction)",
  2116.             "scrollingPrompt(table list, integer x,",
  2117.             "   integer y, integer length[,",
  2118.             "   integer width])",
  2119.             "",
  2120.             "urlDownload(string url)",
  2121.             "pastebinDownload(string code)",
  2122.             "redirect(string site)",
  2123.         }} pages[5] = {title = "API Documentation - 5", content = {
  2124.             "loadImageFromServer(string imagePath)",
  2125.             "ioReadFileFromServer(string filePath)",
  2126.             "fileFileFromServer(string filePath)",
  2127.             "saveFileToUserComputer(string content)",
  2128.             "",
  2129.             "writeDataFile(string path, string contents)",
  2130.             "readDataFile(string path)"
  2131.         }}
  2132.     end
  2133.  
  2134.     local function drawPage(page)
  2135.         term.setBackgroundColor(colors[theme["background"]])
  2136.         term.clear()
  2137.         term.setCursorPos(1, 1)
  2138.         term.setTextColor(colors[theme["text-color"]])
  2139.         term.setBackgroundColor(colors[theme["top-box"]])
  2140.         print("")
  2141.         leftPrint(string.rep(" ", page.title:len() + 3))
  2142.         leftPrint(" " .. page.title .. "  ")
  2143.         leftPrint(string.rep(" ", page.title:len() + 3))
  2144.         print("")
  2145.  
  2146.         term.setBackgroundColor(colors[theme["bottom-box"]])
  2147.         for i = 1, 12 do print(string.rep(" ", w)) end
  2148.         for i, v in ipairs(page.content) do
  2149.             term.setCursorPos(4, i + 7)
  2150.             write(v)
  2151.         end
  2152.     end
  2153.  
  2154.     local curPage = 1
  2155.     local a = {{"Prev", 26, 17}, {"Next", 38, 17}, {"Back",  14, 17}}
  2156.     drawPage(pages[curPage])
  2157.  
  2158.     while true do
  2159.         local b = {a[3]}
  2160.         if curPage == 1 then table.insert(b, a[2])
  2161.         elseif curPage == #pages then table.insert(b, a[1])
  2162.         else table.insert(b, a[1]) table.insert(b, a[2]) end
  2163.  
  2164.         local opt = prompt(b, "horizontal")
  2165.         if opt == "Prev" then
  2166.             curPage = curPage - 1
  2167.         elseif opt == "Next" then
  2168.             curPage = curPage + 1
  2169.         elseif opt == "Back" then
  2170.             break
  2171.         end
  2172.  
  2173.         drawPage(pages[curPage])
  2174.     end
  2175.  
  2176.     redirect("help")
  2177. end
  2178.  
  2179.  
  2180. --  -------- Settings
  2181.  
  2182. pages["settings/themes"] = function(site)
  2183.     term.setBackgroundColor(colors[theme["background"]])
  2184.     term.clear()
  2185.     term.setTextColor(colors[theme["text-color"]])
  2186.     term.setBackgroundColor(colors[theme["top-box"]])
  2187.     print("")
  2188.     leftPrint(string.rep(" ", 17))
  2189.     leftPrint(" Theme Settings  ")
  2190.     leftPrint(string.rep(" ", 17))
  2191.     print("")
  2192.  
  2193.     if isAdvanced() then
  2194.         term.setBackgroundColor(colors[theme["bottom-box"]])
  2195.         for i = 1, 12 do rightPrint(string.rep(" ", 36)) end
  2196.  
  2197.         local themes = {}
  2198.         local themenames = {"Back", "New Theme", "Load Theme"}
  2199.         local f = io.open(rootFolder .. "/temp_file", "w")
  2200.         f:write(files.availableThemes)
  2201.         f:close()
  2202.         local f = io.open(rootFolder .. "/temp_file", "r")
  2203.         local l = f:read("*l")
  2204.         while l do
  2205.             l = l:gsub("^%s*(.-)%s*$", "%1")
  2206.             local a, b = l:find("| |")
  2207.             table.insert(themenames, l:sub(b + 1, -1))
  2208.             table.insert(themes, {name = l:sub(b + 1, -1), url = l:sub(1, a - 1)})
  2209.             l = f:read("*l")
  2210.         end
  2211.         f:close()
  2212.         fs.delete(rootFolder .. "/temp_file")
  2213.  
  2214.         local t = scrollingPrompt(themenames, w - 33, 7, 10, 32)
  2215.         if t == "Back" then
  2216.             redirect("settings")
  2217.         elseif t == "New Theme" then
  2218.             term.setCursorPos(w - 33, 17)
  2219.             write("Path: /")
  2220.             local n = modRead({visibleLength = w - 2, textLength = 100})
  2221.             if n ~= "" and n ~= nil then
  2222.                 n = "/" .. n
  2223.                 local f = io.open(n, "w")
  2224.                 f:write(files.newTheme)
  2225.                 f:close()
  2226.  
  2227.                 term.setCursorPos(1, 17)
  2228.                 rightWrite(string.rep(" ", 36))
  2229.                 term.setCursorPos(1, 17)
  2230.                 rightWrite("File Created! ")
  2231.                 openAddressBar = false
  2232.                 sleep(1.1)
  2233.                 openAddressBar = true
  2234.             end
  2235.         elseif t == "Load Theme" then
  2236.             term.setCursorPos(w - 33, 17)
  2237.             write("Path: /")
  2238.             local n = modRead({visibleLength = w - 2, textLength = 100})
  2239.             if n ~= "" and n ~= nil then
  2240.                 n = "/" .. n
  2241.                 term.setCursorPos(1, 17)
  2242.                 rightWrite(string.rep(" ", 36))
  2243.                
  2244.                 term.setCursorPos(1, 17)
  2245.                 if fs.exists(n) and not fs.isDir(n) then
  2246.                     local a = loadTheme(n)
  2247.                     if a ~= nil then
  2248.                         fs.delete(themeLocation)
  2249.                         fs.copy(n, themeLocation)
  2250.                         theme = a
  2251.                         rightWrite("Theme File Loaded! :D ")
  2252.                     else
  2253.                         rightWrite("Theme File is Corrupt! D: ")
  2254.                     end
  2255.                 elseif not fs.exists(n) then
  2256.                     rightWrite("File does not exist! ")
  2257.                 elseif fs.isDir(n) then
  2258.                     rightWrite("File is a directory! ")
  2259.                 end
  2260.  
  2261.                 openAddressBar = false
  2262.                 sleep(1.1)
  2263.                 openAddressBar = true
  2264.             end
  2265.         else
  2266.             local url = ""
  2267.             for _, v in pairs(themes) do if v.name == t then url = v.url break end end
  2268.             term.setBackgroundColor(colors[theme["top-box"]])
  2269.             term.setCursorPos(1, 3)
  2270.             leftWrite(string.rep(" ", 17))
  2271.             leftWrite(" Downloading...  ")
  2272.  
  2273.             fs.delete(rootFolder .. "/temp_file")
  2274.             download(url, rootFolder .. "/temp_file")
  2275.             local th = loadTheme(rootFolder .. "/temp_file")
  2276.             if th == nil then
  2277.                 term.setCursorPos(1, 3)
  2278.                 leftWrite(string.rep(" ", 17))
  2279.                 leftWrite(" Theme Corrupt!  ")
  2280.                 openAddressBar = false
  2281.                 sleep(1.3)
  2282.                 openAddressBar = true
  2283.  
  2284.                 fs.delete(rootFolder .. "/temp_file")
  2285.             else
  2286.                 term.setCursorPos(1, 3)
  2287.                 leftWrite(string.rep(" ", 17))
  2288.                 leftWrite(" Theme Loaded!   ")
  2289.                 openAddressBar = false
  2290.                 sleep(1.3)
  2291.                 openAddressBar = true
  2292.  
  2293.                 fs.delete(themeLocation)
  2294.                 fs.move(rootFolder .. "/temp_file", themeLocation)
  2295.                 theme = th
  2296.                 redirect("home")
  2297.             end
  2298.         end
  2299.     else
  2300.         print("")
  2301.         rightPrint(string.rep(" ", 30))
  2302.         rightPrint("  Themes are not available on ")
  2303.         rightPrint("         normal computers! :( ")
  2304.         rightPrint(string.rep(" ", 30))
  2305.     end
  2306. end
  2307.  
  2308. pages["downloads"] = function(site) redirect("settings/themes") end
  2309.  
  2310. pages["settings"] = function(site)
  2311.     term.setBackgroundColor(colors[theme["background"]])
  2312.     term.clear()
  2313.     term.setTextColor(colors[theme["text-color"]])
  2314.     term.setBackgroundColor(colors[theme["top-box"]])
  2315.     print("")
  2316.     leftPrint(string.rep(" ", 17 + serverList[serverID]:len()))
  2317.     leftPrint(" Firewolf Settings  " .. string.rep(" ", serverList[serverID]:len() - 3))
  2318.     leftPrint(" Designed For: " .. serverList[serverID] .. "  ")
  2319.     leftPrint(string.rep(" ", 17 + serverList[serverID]:len()))
  2320.     print("\n")
  2321.  
  2322.     local a = "Automatic Updating - On"
  2323.     if autoupdate == "false" then a = "Automatic Updating - Off" end
  2324.     local b = "Home - rdnt://" .. homepage
  2325.     if b:len() >= 28 then b = b:sub(1, 24) .. "..." end
  2326.  
  2327.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2328.     for i = 1, 9 do rightPrint(string.rep(" ", 36)) end
  2329.     local c = {{a, w - a:len() - 6, 9}, {"Change Theme", w - 18, 11}, {b, w - b:len() - 6, 13},
  2330.         {"Reset Firewolf", w - 20, 15}}
  2331.     if not isAdvanced() then
  2332.         c = {{a, w - a:len(), 9}, {b, w - b:len(), 11}, {"Reset Firewolf", w - 14, 13}}
  2333.     end
  2334.  
  2335.     local opt = prompt(c, "vertical")
  2336.     if opt == a then
  2337.         if autoupdate == "true" then autoupdate = "false"
  2338.         elseif autoupdate == "false" then autoupdate = "true" end
  2339.     elseif opt == "Change Theme" and isAdvanced() then
  2340.         redirect("settings/themes")
  2341.     elseif opt == b then
  2342.         if isAdvanced() then term.setCursorPos(w - 30, 14)
  2343.         else term.setCursorPos(w - 30, 12) end
  2344.         write("rdnt://")
  2345.         local a = read()
  2346.         if a ~= "" then homepage = a end
  2347.     elseif opt == "Reset Firewolf" then
  2348.         term.setBackgroundColor(colors[theme["background"]])
  2349.         term.clear()
  2350.         term.setCursorPos(1, 1)
  2351.         term.setTextColor(colors[theme["text-color"]])
  2352.         term.setBackgroundColor(colors[theme["top-box"]])
  2353.         print("")
  2354.         leftPrint(string.rep(" ", 17))
  2355.         leftPrint(" Reset Firewolf  ")
  2356.         leftPrint(string.rep(" ", 17))
  2357.         print("\n")
  2358.         term.setBackgroundColor(colors[theme["bottom-box"]])
  2359.         for i = 1, 11 do rightPrint(string.rep(" ", 26)) end
  2360.         local opt = prompt({{"Reset History", w - 19, 8}, {"Reset Servers", w - 19, 9},
  2361.             {"Reset Theme", w - 17, 10}, {"Reset Cache", w - 17, 11}, {"Reset Databases", w - 21, 12},
  2362.             {"Reset Settings", w - 20, 13}, {"Back", w - 10, 14}, {"Reset All", w - 15, 16}},
  2363.             "vertical")
  2364.  
  2365.         openAddressBar = false
  2366.         if opt == "Reset All" then
  2367.             fs.delete(rootFolder)
  2368.         elseif opt == "Reset History" then
  2369.             fs.delete(historyLocation)
  2370.         elseif opt == "Reset Servers" then
  2371.             fs.delete(serverFolder)
  2372.             fs.delete(serverLocation)
  2373.         elseif opt == "Reset Cache" then
  2374.             fs.delete(cacheFolder)
  2375.         elseif opt == "Reset Databases" then
  2376.             fs.delete(userWhitelist)
  2377.             fs.delete(userBlacklist)
  2378.         elseif opt == "Reset Settings" then
  2379.             fs.delete(settingsLocation)
  2380.         elseif opt == "Reset Theme" then
  2381.             fs.delete(themeLocation)
  2382.         elseif opt == "Back" then
  2383.             openAddressBar = true
  2384.             redirect("settings")
  2385.         end
  2386.  
  2387.         term.setBackgroundColor(colors[theme["background"]])
  2388.         term.clear()
  2389.         term.setCursorPos(1, 1)
  2390.         term.setBackgroundColor(colors[theme["top-box"]])
  2391.         print("\n\n")
  2392.         leftPrint(string.rep(" ", 17))
  2393.         leftPrint(" Reset Firewolf  ")
  2394.         leftPrint(string.rep(" ", 17))
  2395.         print("")
  2396.  
  2397.         term.setCursorPos(1, 10)
  2398.         term.setBackgroundColor(colors[theme["bottom-box"]])
  2399.         rightPrint(string.rep(" ", 27))
  2400.         rightPrint("  Firewolf has been reset! ")
  2401.         rightWrite(string.rep(" ", 27))
  2402.         if isAdvanced() then rightPrint("          Click to exit... ")
  2403.         else rightPrint("  Press any key to exit... ") end
  2404.         rightPrint(string.rep(" ", 27))
  2405.  
  2406.         while true do
  2407.             local e = os.pullEvent()
  2408.             if e == "mouse_click" or e == "key" then return true end
  2409.         end
  2410.     end
  2411.  
  2412.     -- Save
  2413.     local f = io.open(settingsLocation, "w")
  2414.     f:write(textutils.serialize({auto = autoupdate, incog = incognito, home = homepage}))
  2415.     f:close()
  2416.  
  2417.     redirect("settings")
  2418. end
  2419.  
  2420.  
  2421. --  -------- Credits
  2422.  
  2423. pages["credits"] = function(site)
  2424.     term.setBackgroundColor(colors[theme["background"]])
  2425.     term.clear()
  2426.     print("\n")
  2427.     term.setTextColor(colors[theme["text-color"]])
  2428.     term.setBackgroundColor(colors[theme["top-box"]])
  2429.     leftPrint(string.rep(" ", 19))
  2430.     leftPrint(" Firewolf Credits  ")
  2431.     leftPrint(string.rep(" ", 19))
  2432.     print("\n")
  2433.  
  2434.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2435.     rightPrint(string.rep(" ", 38))
  2436.     rightPrint("  Coded by:              GravityScore ")
  2437.     rightPrint("                            and 1lann ")
  2438.     rightPrint(string.rep(" ", 38))
  2439.     rightPrint("  Based off:     RednetExplorer 2.4.1 ")
  2440.     rightPrint("           Made by ComputerCraftFan11 ")
  2441.     rightPrint(string.rep(" ", 38))
  2442. end
  2443.  
  2444.  
  2445. --  -------- Error Pages
  2446.  
  2447. errorPages["overspeed"] = function(site)
  2448.     clearPage("overspeed", colors[theme["background"]])
  2449.     print("")
  2450.     term.setTextColor(colors[theme["text-color"]])
  2451.     term.setBackgroundColor(colors[theme["top-box"]])
  2452.     leftPrint(string.rep(" ", 14))
  2453.     leftPrint(" Warning! D:  ")
  2454.     leftPrint(string.rep(" ", 14))
  2455.     print("")
  2456.  
  2457.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2458.     rightPrint(string.rep(" ", 40))
  2459.     rightPrint("  Website browsing sleep limit reached! ")
  2460.     rightPrint(string.rep(" ", 40))
  2461.     rightPrint("      To prevent Firewolf from spamming ")
  2462.     rightPrint("   rednet, Firewolf has stopped loading ")
  2463.     rightPrint("                              the page. ")
  2464.     for i = 1, 3 do rightPrint(string.rep(" ", 40)) end
  2465.  
  2466.     openAddressBar = false
  2467.     for i = 1, 5 do
  2468.         term.setCursorPos(1, 14)
  2469.         rightWrite(string.rep(" ", 43))
  2470.         if 6 - i == 1 then rightWrite("                Please wait 1 second... ")
  2471.         else rightWrite("                Please wait " .. tostring(6 - i) .. " seconds... ") end
  2472.         sleep(1)
  2473.     end
  2474.     openAddressBar = true
  2475.  
  2476.     term.setCursorPos(1, 14)
  2477.     rightWrite(string.rep(" ", 43))
  2478.     rightWrite("            You may now browse normally ")
  2479. end
  2480.  
  2481. errorPages["crash"] = function(error)
  2482.     clearPage("crash", colors[theme["background"]])
  2483.     print("")
  2484.     term.setTextColor(colors[theme["text-color"]])
  2485.     term.setBackgroundColor(colors[theme["top-box"]])
  2486.     leftPrint(string.rep(" ", 30))
  2487.     leftPrint(" The Website Has Crashed! D:  ")
  2488.     leftPrint(string.rep(" ", 30))
  2489.     print("")
  2490.  
  2491.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2492.     rightPrint(string.rep(" ", 31))
  2493.     rightPrint("      The website has crashed! ")
  2494.     rightPrint("  Report this to the operator: ")
  2495.     rightPrint(string.rep(" ", 31))
  2496.     term.setBackgroundColor(colors[theme["background"]])
  2497.     print("")
  2498.     print(" " .. tostring(error))
  2499.     print("")
  2500.  
  2501.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2502.     rightPrint(string.rep(" ", 31))
  2503.     rightPrint("   You may now browse normally ")
  2504.     rightPrint(string.rep(" ", 31))
  2505. end
  2506.  
  2507.  
  2508. --  -------- External Page
  2509.  
  2510. local function external(site)
  2511.     -- Clear
  2512.     term.setTextColor(colors[theme["text-color"]])
  2513.     term.setBackgroundColor(colors[theme["background"]])
  2514.     term.clear()
  2515.     term.setCursorPos(1, 1)
  2516.     print("\n\n\n")
  2517.     centerWrite("Connecting to Website...")
  2518.     loadingRate = loadingRate + 1
  2519.  
  2520.     -- Modem
  2521.     if curProtocol == protocols.rdnt then
  2522.         setfenv(checkForModem, override)
  2523.         checkForModem(function()
  2524.             term.setBackgroundColor(colors[theme["background"]])
  2525.             term.clear()
  2526.             term.setCursorPos(1, 1)
  2527.             print("\n")
  2528.             term.setTextColor(colors[theme["text-color"]])
  2529.             term.setBackgroundColor(colors[theme["top-box"]])
  2530.             leftPrint(string.rep(" ", 24))
  2531.             leftPrint(" No Modem Attached! D:  ")
  2532.             leftPrint(string.rep(" ", 24))
  2533.             print("\n")
  2534.  
  2535.             term.setBackgroundColor(colors[theme["bottom-box"]])
  2536.             rightPrint(string.rep(" ", 40))
  2537.             rightPrint("    No wireless modem was found on this ")
  2538.             rightPrint("  computer, and Firewolf cannot use the ")
  2539.             rightPrint("             RDNT protocol without one! ")
  2540.             rightPrint(string.rep(" ", 40))
  2541.             rightPrint("  Waiting for a modem to be attached... ")
  2542.             rightPrint(string.rep(" ", 40))
  2543.         end)
  2544.     end
  2545.  
  2546.     -- Get website
  2547.     local webFunc = curProtocol.getWebsite
  2548.     setfenv(webFunc, override)
  2549.     local id, content, status = nil, nil, nil
  2550.     pcall(function() id, content, status = webFunc(site) end)
  2551.  
  2552.     local cacheLoc = cacheFolder .. "/" .. site:gsub("/", "$slazh$")
  2553.     if id and status then
  2554.         -- Clear
  2555.         term.setBackgroundColor(colors.black)
  2556.         term.setTextColor(colors.white)
  2557.         term.clear()
  2558.         term.setCursorPos(1, 1)
  2559.  
  2560.         -- Save
  2561.         local f = io.open(cacheLoc, "w")
  2562.         f:write(content)
  2563.         f:close()
  2564.  
  2565.         local fn, err = loadfile(cacheLoc)
  2566.         if not err then
  2567.             setfenv(fn, antivirus)
  2568.             if status == "whitelist" then setfenv(fn, override) end
  2569.             _, err = pcall(function() fn() end)
  2570.             setfenv(1, override)
  2571.         end
  2572.  
  2573.         if err then
  2574.             local errFunc = errorPages["crash"]
  2575.             setfenv(errFunc, override)
  2576.             pcall(function() errFunc(err) end)
  2577.         end
  2578.     else
  2579.         if fs.exists(cacheLoc) and not fs.isDir(cacheLoc) then
  2580.             term.clearLine()
  2581.             centerPrint("Could Not Connect to Website!")
  2582.             print("")
  2583.             centerPrint("A Cached Version was Found.")
  2584.             local opt = prompt({{"Load Cache", -1, 10}, {"Continue to Search Results", -1, 12}},
  2585.                 "vertical")
  2586.             if opt == "Load Cache" then
  2587.                 -- Clear
  2588.                 term.setBackgroundColor(colors.black)
  2589.                 term.setTextColor(colors.white)
  2590.                 term.clear()
  2591.                 term.setCursorPos(1, 1)
  2592.  
  2593.                 -- Run
  2594.                 local fn, err = loadfile(cacheLoc)
  2595.                 if not err then
  2596.                     setfenv(fn, antivirus)
  2597.                     _, err = pcall(function() fn() end)
  2598.                     setfenv(1, override)
  2599.                 end
  2600.  
  2601.                 return
  2602.             end
  2603.         end
  2604.  
  2605.         openAddressBar = true
  2606.         local res = {}
  2607.         if site ~= "" then
  2608.             for _, v in pairs(dnsDatabase[1]) do
  2609.                 if v:find(site:lower(), 1, true) then
  2610.                     table.insert(res, v)
  2611.                 end
  2612.             end
  2613.         else
  2614.             for _, v in pairs(dnsDatabase[1]) do
  2615.                 table.insert(res, v)
  2616.             end
  2617.         end
  2618.  
  2619.         table.sort(res)
  2620.         table.sort(res, function(a, b)
  2621.             local _, ac = a:gsub("rdnt://", ""):gsub("http://", ""):gsub(site:lower(), "")
  2622.             local _, bc = b:gsub("rdnt://", ""):gsub("http://", ""):gsub(site:lower(), "")
  2623.             return ac > bc
  2624.         end)
  2625.  
  2626.         term.setBackgroundColor(colors[theme["background"]])
  2627.         term.clear()
  2628.         term.setCursorPos(1, 1)
  2629.         if #res > 0 then
  2630.             print("")
  2631.             term.setTextColor(colors[theme["text-color"]])
  2632.             term.setBackgroundColor(colors[theme["top-box"]])
  2633.             local t = "1 Search Result"
  2634.             if #res > 1 then t = #res .. " Search Results" end
  2635.             leftPrint(string.rep(" ", t:len() + 3))
  2636.             leftPrint(" " .. t .. "  ")
  2637.             leftPrint(string.rep(" ", t:len() + 3))
  2638.             print("")
  2639.  
  2640.             term.setBackgroundColor(colors[theme["bottom-box"]])
  2641.             for i = 1, 12 do rightPrint(string.rep(" ", 42)) end
  2642.             local opt = scrollingPrompt(res, w - 39, 7, 10, 38)
  2643.             if opt then redirect(opt:gsub("rdnt://", ""):gsub("http://", "")) end
  2644.         elseif site == "" and #res < 1 then
  2645.             print("\n\n")
  2646.             term.setTextColor(colors[theme["text-color"]])
  2647.             term.setBackgroundColor(colors[theme["top-box"]])
  2648.             centerPrint(string.rep(" ", 47))
  2649.             centerWrite(string.rep(" ", 47))
  2650.             centerPrint("No Websites are Currently Online! D:")
  2651.             centerWrite(string.rep(" ", 47))
  2652.             centerPrint(string.rep(" ", 47))
  2653.             centerWrite(string.rep(" ", 47))
  2654.             centerPrint("Why not make one yourself?")
  2655.             centerWrite(string.rep(" ", 47))
  2656.             centerPrint("Visit rdnt://server!")
  2657.             centerPrint(string.rep(" ", 47))
  2658.         else
  2659.             print("")
  2660.             term.setTextColor(colors[theme["text-color"]])
  2661.             term.setBackgroundColor(colors[theme["top-box"]])
  2662.             leftPrint(string.rep(" ", 11))
  2663.             leftPrint(" Oh Noes!  ")
  2664.             leftPrint(string.rep(" ", 11))
  2665.             print("\n")
  2666.  
  2667.             term.setBackgroundColor(colors[theme["bottom-box"]])
  2668.             rightPrint(string.rep(" ", 43))
  2669.             rightPrint([[       ______                          __  ]])
  2670.             rightPrint([[      / ____/_____ _____ ____   _____ / /  ]])
  2671.             rightPrint([[     / __/  / ___// ___// __ \ / ___// /   ]])
  2672.             rightPrint([[    / /___ / /   / /   / /_/ // /   /_/    ]])
  2673.             rightPrint([[   /_____//_/   /_/    \____//_/   (_)     ]])
  2674.             rightPrint(string.rep(" ", 43))
  2675.             if verifyBlacklist(id) then
  2676.                 rightPrint("  Could not connect to the website! It has ")
  2677.                 rightPrint("  been blocked by a database admin!        ")
  2678.             else
  2679.                 rightPrint("  Could not connect to the website! It may ")
  2680.                 rightPrint("  be down, or not exist!                   ")
  2681.             end
  2682.             rightPrint(string.rep(" ", 43))
  2683.         end
  2684.     end
  2685. end
  2686.  
  2687.  
  2688. --  -------- Website Coroutine
  2689.  
  2690. local function websitecoroutine()
  2691.     local loadingClock = os.clock()
  2692.     while true do
  2693.         -- Reset and clear
  2694.         setfenv(1, backupEnv)
  2695.         os.pullEvent = pullevent
  2696.         browserAgent = browserAgentTemplate
  2697.         w, h = term.getSize()
  2698.         curbackground = colors.black
  2699.         curtext = colors.white
  2700.  
  2701.         clearPage(website)
  2702.         term.setBackgroundColor(colors.black)
  2703.         term.setTextColor(colors.white)
  2704.  
  2705.         -- Add to history
  2706.         if website ~= "exit" and website ~= addressBarHistory[#addressBarHistory] then
  2707.             table.insert(addressBarHistory, website)
  2708.         end
  2709.  
  2710.         -- Overspeed
  2711.         checkForModem()
  2712.         if os.clock() - loadingClock > 5 then
  2713.             -- Reset loading rate
  2714.             loadingRate = 0
  2715.             loadingClock = os.clock()
  2716.         end
  2717.  
  2718.         -- Run site
  2719.         if loadingRate >= 8 then
  2720.             -- Overspeed error
  2721.             local overspeedFunc = errorPages["overspeed"]
  2722.             setfenv(overspeedFunc, override)
  2723.             overspeedFunc()
  2724.  
  2725.             loadingRate = 0
  2726.             loadingClock = os.clock()
  2727.         elseif type(pages[website]) == "function" then
  2728.             -- Run site function
  2729.             local siteFunc = pages[website]
  2730.             setfenv(siteFunc, override)
  2731.             local exit = false
  2732.             local _, err = pcall(function() exit = siteFunc() end)
  2733.  
  2734.             if err then
  2735.                 local errFunc = errorPages["crash"]
  2736.                 setfenv(errFunc, override)
  2737.                 errFunc(err)
  2738.             end
  2739.  
  2740.             if exit then
  2741.                 os.queueEvent("terminate")
  2742.                 return
  2743.             end
  2744.         else
  2745.             setfenv(external, override)
  2746.             local _, err = pcall(function() external(website) end)
  2747.  
  2748.             if err then
  2749.                 local errFunc = errorPages["crash"]
  2750.                 setfenv(errFunc, override)
  2751.                 errFunc(err)
  2752.             end
  2753.         end
  2754.  
  2755.         -- Clear data folder
  2756.         fs.delete(websiteDataFolder)
  2757.         fs.makeDir(websiteDataFolder)
  2758.  
  2759.         -- Wait for load
  2760.         oldpullevent(event_loadWebsite)
  2761.     end
  2762. end
  2763.  
  2764.  
  2765. --  -------- Address Bar Coroutine
  2766.  
  2767. local function searchresults()
  2768.     local mod = true
  2769.     if curProtocol == protocols.rdnt then
  2770.         mod = false
  2771.         for _, v in pairs(rs.getSides()) do if rednet.isOpen(v) then mod = true end end
  2772.     end
  2773.     if mod then curProtocol.getSearchResults() end
  2774.  
  2775.     local lastCheck = os.clock()
  2776.     while true do
  2777.         local e = oldpullevent()
  2778.         if website ~= "exit" and e == event_loadWebsite then
  2779.             mod = true
  2780.             if curProtocol == protocols.rdnt then
  2781.                 mod = false
  2782.                 for _, v in pairs(rs.getSides()) do if rednet.isOpen(v) then mod = true end end
  2783.             end
  2784.             if mod and os.clock() - lastCheck > 5 then
  2785.                 curProtocol.getSearchResults()
  2786.                 lastCheck = os.clock()
  2787.             end
  2788.         end
  2789.     end
  2790. end
  2791.  
  2792. local function addressbarread()
  2793.     local len = 4
  2794.     local list = {}
  2795.  
  2796.     local function draw(l)
  2797.         local ox, oy = term.getCursorPos()
  2798.         for i = 1, len do
  2799.             term.setTextColor(colors[theme["address-bar-text"]])
  2800.             term.setBackgroundColor(colors[theme["address-bar-background"]])
  2801.             term.setCursorPos(1, i + 1)
  2802.             write(string.rep(" ", w))
  2803.         end
  2804.         if theme["address-bar-base"] then term.setBackgroundColor(colors[theme["address-bar-base"]])
  2805.         else term.setBackgroundColor(colors[theme["bottom-box"]]) end
  2806.         term.setCursorPos(1, len + 2)
  2807.         write(string.rep(" ", w))
  2808.         term.setBackgroundColor(colors[theme["address-bar-background"]])
  2809.  
  2810.         for i, v in ipairs(l) do
  2811.             term.setCursorPos(2, i + 1)
  2812.             write(v)
  2813.         end
  2814.         term.setCursorPos(ox, oy)
  2815.     end
  2816.  
  2817.     local function update(line, event, ...)
  2818.         local params = {...}
  2819.         local y = params[3]
  2820.         if event == "char" or event == "history" or event == "delete" then
  2821.             list = {}
  2822.             for _, v in pairs(dnsDatabase[1]) do
  2823.                 if #list < len and
  2824.                         v:gsub("rdnt://", ""):gsub("http://", ""):find(line:lower(), 1, true) then
  2825.                     table.insert(list, v)
  2826.                 end
  2827.             end
  2828.  
  2829.             table.sort(list)
  2830.             table.sort(list, function(a, b)
  2831.                 local _, ac = a:gsub("rdnt://", ""):gsub("http://", ""):gsub(line:lower(), "")
  2832.                 local _, bc = b:gsub("rdnt://", ""):gsub("http://", ""):gsub(line:lower(), "")
  2833.                 return ac > bc
  2834.             end)
  2835.             draw(list)
  2836.             return false
  2837.         elseif event == "mouse_click" then
  2838.             for i = 1, #list do
  2839.                 if y == i + 1 then
  2840.                     return true, list[i]:gsub("rdnt://", ""):gsub("http://", "")
  2841.                 end
  2842.             end
  2843.         end
  2844.     end
  2845.  
  2846.     local mod = true
  2847.     if curProtocol == protocols.rdnt then
  2848.         mod = false
  2849.         for _, v in pairs(rs.getSides()) do if rednet.isOpen(v) then mod = true end end
  2850.     end
  2851.     if isAdvanced() and mod then
  2852.         return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300,
  2853.             liveUpdates = update, exitOnKey = "control"})
  2854.     else
  2855.         return modRead({history = addressBarHistory, visibleLength = w - 2, textLength = 300,
  2856.             exitOnKey = "control"})
  2857.     end
  2858. end
  2859.  
  2860. local function addressbarcoroutine()
  2861.     while true do
  2862.         local e, but, x, y = oldpullevent()
  2863.         if (e == "key" and (but == 29 or but == 157)) or
  2864.                 (e == "mouse_click" and y == 1 and clickableAddressBar) then
  2865.             clickableAddressBar = true
  2866.             if openAddressBar then
  2867.                 if e == "key" then x = -1 end
  2868.                 if x == w then
  2869.                     -- Open menu bar
  2870.                     menuBarOpen = true
  2871.                     term.setBackgroundColor(colors[theme["top-box"]])
  2872.                     term.setTextColor(colors[theme["text-color"]])
  2873.                     term.setCursorPos(1, 1)
  2874.                     write("> [- Exit Firewolf -]                              ")
  2875.                 elseif menuBarOpen and (x == 1 or (but == 29 or but == 157)) then
  2876.                     -- Close menu bar
  2877.                     menuBarOpen = false
  2878.                     clearPage(website, nil, true)
  2879.                 elseif x > 2 and x < 22 and menuBarOpen then
  2880.                     -- Exit
  2881.                     menuBarOpen = false
  2882.                     os.queueEvent(event_exitWebsite)
  2883.                     os.queueEvent("terminate")
  2884.                     return
  2885.                 elseif not menuBarOpen then
  2886.                     -- Exit website
  2887.                     os.queueEvent(event_exitWebsite)
  2888.  
  2889.                     -- Clear
  2890.                     term.setBackgroundColor(colors[theme["address-bar-background"]])
  2891.                     term.setTextColor(colors[theme["address-bar-text"]])
  2892.                     term.setCursorPos(2, 1)
  2893.                     term.clearLine()
  2894.                     if curProtocol == protocols.rdnt then write("rdnt://")
  2895.                     elseif curProtocol == protocols.http then write("http://") end
  2896.  
  2897.                     -- Read
  2898.                     local oldWebsite = website
  2899.                     os.pullEvent = oldpullevent
  2900.                     website = addressbarread()
  2901.                     os.pullEvent = pullevent
  2902.                     if website == nil then
  2903.                         website = oldWebsite
  2904.                     elseif website == "home" or website == "homepage" then
  2905.                         website = homepage
  2906.                     elseif website == "exit" then
  2907.                         os.queueEvent("terminate")
  2908.                         return
  2909.                     end
  2910.  
  2911.                     -- Load
  2912.                     os.queueEvent(event_loadWebsite)
  2913.                 end
  2914.             end
  2915.         elseif e == event_redirect then
  2916.             -- Exit website
  2917.             os.queueEvent(event_exitWebsite)
  2918.  
  2919.             -- Set website
  2920.             local oldWebsite = website
  2921.             website = but
  2922.             if website == nil or website == "exit" then
  2923.                 website = oldWebsite
  2924.             elseif website == "home" or website == "homepage" then
  2925.                 website = homepage
  2926.             end
  2927.  
  2928.             -- Load
  2929.             os.queueEvent(event_loadWebsite)
  2930.         end
  2931.     end
  2932. end
  2933.  
  2934.  
  2935. --  -------- Main
  2936.  
  2937. local function main()
  2938.     -- Logo
  2939.     term.setBackgroundColor(colors[theme["background"]])
  2940.     term.setTextColor(colors[theme["text-color"]])
  2941.     term.clear()
  2942.     term.setCursorPos(1, 2)
  2943.     term.setBackgroundColor(colors[theme["top-box"]])
  2944.     leftPrint(string.rep(" ", 47))
  2945.     leftPrint([[          ______ ____ ____   ______            ]])
  2946.     leftPrint([[ ------- / ____//  _// __ \ / ____/            ]])
  2947.     leftPrint([[ ------ / /_    / / / /_/ // __/               ]])
  2948.     leftPrint([[ ----- / __/  _/ / / _  _// /___               ]])
  2949.     leftPrint([[ ---- / /    /___//_/ |_|/_____/               ]])
  2950.     leftPrint([[ --- / /       _       __ ____   __     ______ ]])
  2951.     leftPrint([[ -- /_/       | |     / // __ \ / /    / ____/ ]])
  2952.     leftPrint([[              | | /| / // / / // /    / /_     ]])
  2953.     leftPrint([[              | |/ |/ // /_/ // /___ / __/     ]])
  2954.     leftPrint([[              |__/|__/ \____//_____//_/        ]])
  2955.     leftPrint(string.rep(" ", 47))
  2956.     print("\n")
  2957.     term.setBackgroundColor(colors[theme["bottom-box"]])
  2958.  
  2959.     -- Load Settings
  2960.     if fs.exists(settingsLocation) and not fs.isDir(settingsLocation) then
  2961.         local f = io.open(settingsLocation, "r")
  2962.         local a = textutils.unserialize(f:read("*l"))
  2963.         if type(a) == "table" then
  2964.             autoupdate = a.auto
  2965.             incognito = a.incog
  2966.             homepage = a.home
  2967.         end
  2968.         f:close()
  2969.     else
  2970.         autoupdate = "true"
  2971.         incognito = "false"
  2972.         homepage = "firewolf"
  2973.     end
  2974.     curProtocol = protocols.rdnt
  2975.  
  2976.     -- Update
  2977.     rightPrint(string.rep(" ", 32))
  2978.     rightPrint("        Checking for Updates... ")
  2979.     rightPrint(string.rep(" ", 32))
  2980.     setfenv(updateClient, env)
  2981.     if not noInternet then
  2982.         if updateClient() then
  2983.             if debugFile then debugFile:close() end
  2984.  
  2985.             -- Reset Environment
  2986.             setfenv(1, oldEnv)
  2987.             os.pullEvent = oldpullevent
  2988.             shell.run(firewolfLocation)
  2989.             error()
  2990.         end
  2991.     end
  2992.  
  2993.     -- Download Files
  2994.     local x, y = term.getCursorPos()
  2995.     term.setCursorPos(1, y - 2)
  2996.     rightWrite(string.rep(" ", 32))
  2997.     rightWrite("  Downloading Required Files... ")
  2998.  
  2999.     if not noInternet then resetFilesystem() end
  3000.     loadDatabases()
  3001.  
  3002.     -- Modem
  3003.     checkForModem()
  3004.     website = homepage
  3005.  
  3006.     -- Run
  3007.     parallel.waitForAll(websitecoroutine, addressbarcoroutine, searchresults)
  3008. end
  3009.  
  3010. local function startup()
  3011.     -- HTTP
  3012.     if not http and not noInternet then
  3013.         term.setTextColor(colors[theme["text-color"]])
  3014.         term.setBackgroundColor(colors[theme["background"]])
  3015.         term.clear()
  3016.         term.setCursorPos(1, 2)
  3017.         term.setBackgroundColor(colors[theme["top-box"]])
  3018.         api.leftPrint(string.rep(" ", 24))
  3019.         api.leftPrint(" HTTP API Not Enabled!  ")
  3020.         api.leftPrint(string.rep(" ", 24))
  3021.         print("")
  3022.  
  3023.         term.setBackgroundColor(colors[theme["bottom-box"]])
  3024.         api.rightPrint(string.rep(" ", 36))
  3025.         api.rightPrint("  Firewolf is unable to run without ")
  3026.         api.rightPrint("       the HTTP API Enabled! Please ")
  3027.         api.rightPrint("    enable it in your ComputerCraft ")
  3028.         api.rightPrint("                            Config! ")
  3029.         api.rightPrint(string.rep(" ", 36))
  3030.  
  3031.         if isAdvanced() then api.rightPrint("                   Click to exit... ")
  3032.         else api.rightPrint("           Press any key to exit... ") end
  3033.         api.rightPrint(string.rep(" ", 36))
  3034.  
  3035.         while true do
  3036.             local e, but, x, y = oldpullevent()
  3037.             if e == "mouse_click" or e == "key" then break end
  3038.         end
  3039.  
  3040.         return false
  3041.     end
  3042.  
  3043.     -- Turtle
  3044.     if turtle then
  3045.         term.clear()
  3046.         term.setCursorPos(1, 2)
  3047.         api.centerPrint("Advanced computer Required!")
  3048.         print("\n")
  3049.         api.centerPrint("  This version of Firewolf requires  ")
  3050.         api.centerPrint("  an Advanced computer to run!       ")
  3051.         print("")
  3052.         api.centerPrint("  Turtles may not be used to run     ")
  3053.         api.centerPrint("  Firewolf! :(                       ")
  3054.         print("")
  3055.         api.centerPrint("Press any key to exit...")
  3056.  
  3057.         oldpullevent("key")
  3058.         return false
  3059.     end
  3060.  
  3061.     -- Run
  3062.     setfenv(main, env)
  3063.     local _, err = pcall(main)
  3064.     if err and err ~= "parallel:22: Terminated" then
  3065.         term.setTextColor(colors[theme["text-color"]])
  3066.         term.setBackgroundColor(colors[theme["background"]])
  3067.         term.clear()
  3068.         term.setCursorPos(1, 2)
  3069.         term.setCursorBlink(false)
  3070.         term.setBackgroundColor(colors[theme["top-box"]])
  3071.         api.leftPrint(string.rep(" ", 27))
  3072.         api.leftPrint(" Firewolf has Crashed! D:  ")
  3073.         api.leftPrint(string.rep(" ", 27))
  3074.         print("")
  3075.         term.setBackgroundColor(colors[theme["background"]])
  3076.         print("")
  3077.         print("  " .. err)
  3078.         print("")
  3079.  
  3080.         term.setBackgroundColor(colors[theme["bottom-box"]])
  3081.         api.rightPrint(string.rep(" ", 41))
  3082.         if autoupdate == "true" then
  3083.             api.rightPrint("    Please report this error to 1lann or ")
  3084.             api.rightPrint("  GravityScore so we are able to fix it! ")
  3085.             api.rightPrint("  If this problem persists, try deleting ")
  3086.             api.rightPrint("                         " .. rootFolder .. " ")
  3087.         else
  3088.             api.rightPrint("        Automatic updating is off! A new ")
  3089.             api.rightPrint("     version may have have been released ")
  3090.             api.rightPrint("                that may fix this error! ")
  3091.             api.rightPrint("        If you didn't turn auto updating ")
  3092.             api.rightPrint("             off, delete " .. rootFolder .. " ")
  3093.         end
  3094.  
  3095.         api.rightPrint(string.rep(" ", 41))
  3096.         if isAdvanced() then api.rightPrint("                        Click to exit... ")
  3097.         else api.rightPrint("                Press any key to exit... ") end
  3098.         api.rightPrint(string.rep(" ", 41))
  3099.  
  3100.         while true do
  3101.             local e, but, x, y = oldpullevent()
  3102.             if e == "mouse_click" or e == "key" then break end
  3103.         end
  3104.  
  3105.         return false
  3106.     end
  3107. end
  3108.  
  3109. -- Check If Read Only
  3110. if fs.isReadOnly(firewolfLocation) or fs.isReadOnly(rootFolder) then
  3111.     print("Firewolf cannot modify itself or its root folder!")
  3112.     print("")
  3113.     print("This cold be caused by Firewolf being placed in")
  3114.     print("the rom folder, or another program may be")
  3115.     print("preventing the modification of Firewolf.")
  3116.  
  3117.     -- Reset Environment and Exit
  3118.     setfenv(1, oldEnv)
  3119.     error()
  3120. end
  3121.  
  3122. -- Theme
  3123. if not isAdvanced() then
  3124.     theme = originalTheme
  3125. else
  3126.     theme = loadTheme(themeLocation)
  3127.     if theme == nil then theme = defaultTheme end
  3128. end
  3129.  
  3130. -- Debug File
  3131. if #tArgs > 0 and tArgs[1] == "debug" then
  3132.     print("Debug Mode Enabled!")
  3133.  
  3134.     if fs.exists(debugLogLocation) then debugFile = io.open(debugLogLocation, "a")
  3135.     else debugFile = io.open(debugLogLocation, "w") end
  3136.     debugFile:write("\n-- [" .. textutils.formatTime(os.time()) .. "] New Log --")
  3137.     sleep(1.3)
  3138. end
  3139.  
  3140. -- Start
  3141. startup()
  3142.  
  3143. -- Exit Message
  3144. term.setBackgroundColor(colors.black)
  3145. term.setTextColor(colors.white)
  3146. term.setCursorBlink(false)
  3147. term.clear()
  3148. term.setCursorPos(1, 1)
  3149. api.centerPrint("Thank You for Using Firewolf " .. version)
  3150. api.centerPrint("Made by 1lann and GravityScore")
  3151.  
  3152. -- Close
  3153. for _, v in pairs(rs.getSides()) do
  3154.     if peripheral.getType(v) == "modem" then rednet.close(v) end
  3155. end
  3156. if debugFile then debugFile:close() end
  3157.  
  3158. -- Reset Environment
  3159. setfenv(1, oldEnv)
  3160. os.pullEvent = oldpullevent
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement